Any alleged performance benefits gained from the split are purely mythological and do not justify added code complexity.
Unified · Split
| @@ -314,7 +314,7 @@ static int output_frame(AVFilterLink *outlink, int nb_samples) · 313 unmodified lines | |||
| 314 | if (s->next_pts != AV_NOPTS_VALUE) | 314 | if (s->next_pts != AV_NOPTS_VALUE) |
| 315 | s->next_pts += nb_samples; | 315 | s->next_pts += nb_samples; |
| 316 | 316 | ||
| 317 | return ff_filter_samples(outlink, out_buf); | 317 | return ff_filter_frame(outlink, out_buf); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | /** | 320 | /** |
| @@ -455,7 +455,7 @@ static int request_frame(AVFilterLink *outlink) · 134 unmodified lines | |||
| 455 | return output_frame(outlink, available_samples); | 455 | return output_frame(outlink, available_samples); |
| 456 | } | 456 | } |
| 457 | 457 | ||
| 458 | static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | 458 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 459 | { | 459 | { |
| 460 | AVFilterContext *ctx = inlink->dst; | 460 | AVFilterContext *ctx = inlink->dst; |
| 461 | MixContext *s = ctx->priv; | 461 | MixContext *s = ctx->priv; |
| @@ -509,7 +509,7 @@ static int init(AVFilterContext *ctx, const char *args) · 47 unmodified lines | |||
| 509 | snprintf(name, sizeof(name), "input%d", i); | 509 | snprintf(name, sizeof(name), "input%d", i); |
| 510 | pad.type = AVMEDIA_TYPE_AUDIO; | 510 | pad.type = AVMEDIA_TYPE_AUDIO; |
| 511 | pad.name = av_strdup(name); | 511 | pad.name = av_strdup(name); |
| 512 | pad.filter_samples = filter_samples; | 512 | pad.filter_frame = filter_frame; |
| 513 | 513 | ||
| 514 | ff_insert_inpad(ctx, i, &pad); | 514 | ff_insert_inpad(ctx, i, &pad); |
| 515 | } | 515 | } |
| @@ -34,6 +34,7 @@ · 33 unmodified lines | |||
| 34 | 34 | ||
| 35 | #include "audio.h" | 35 | #include "audio.h" |
| 36 | #include "avfilter.h" | 36 | #include "avfilter.h" |
| 37 | #include "internal.h" | ||
| 37 | 38 | ||
| 38 | typedef struct AShowInfoContext { | 39 | typedef struct AShowInfoContext { |
| 39 | /** | 40 | /** |
| @@ -64,7 +65,7 @@ static void uninit(AVFilterContext *ctx) · 24 unmodified lines | |||
| 64 | av_freep(&s->plane_checksums); | 65 | av_freep(&s->plane_checksums); |
| 65 | } | 66 | } |
| 66 | 67 | ||
| 67 | static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | 68 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 68 | { | 69 | { |
| 69 | AVFilterContext *ctx = inlink->dst; | 70 | AVFilterContext *ctx = inlink->dst; |
| 70 | AShowInfoContext *s = ctx->priv; | 71 | AShowInfoContext *s = ctx->priv; |
| @@ -103,7 +104,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 32 unmodified lines | |||
| 103 | av_log(ctx, AV_LOG_INFO, "]\n"); | 104 | av_log(ctx, AV_LOG_INFO, "]\n"); |
| 104 | 105 | ||
| 105 | s->frame++; | 106 | s->frame++; |
| 106 | return ff_filter_samples(inlink->dst->outputs[0], buf); | 107 | return ff_filter_frame(inlink->dst->outputs[0], buf); |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | static const AVFilterPad inputs[] = { | 110 | static const AVFilterPad inputs[] = { |
| @@ -112,7 +113,7 @@ static const AVFilterPad inputs[] = { · 2 unmodified lines | |||
| 112 | .type = AVMEDIA_TYPE_AUDIO, | 113 | .type = AVMEDIA_TYPE_AUDIO, |
| 113 | .get_audio_buffer = ff_null_get_audio_buffer, | 114 | .get_audio_buffer = ff_null_get_audio_buffer, |
| 114 | .config_props = config_input, | 115 | .config_props = config_input, |
| 115 | .filter_samples = filter_samples, | 116 | .filter_frame = filter_frame, |
| 116 | .min_perms = AV_PERM_READ, | 117 | .min_perms = AV_PERM_READ, |
| 117 | }, | 118 | }, |
| 118 | { NULL }, | 119 | { NULL }, |
| @@ -39,7 +39,7 @@ typedef struct ASyncContext { · 38 unmodified lines | |||
| 39 | float min_delta_sec; | 39 | float min_delta_sec; |
| 40 | int max_comp; | 40 | int max_comp; |
| 41 | 41 | ||
| 42 | /* set by filter_samples() to signal an output frame to request_frame() */ | 42 | /* set by filter_frame() to signal an output frame to request_frame() */ |
| 43 | int got_output; | 43 | int got_output; |
| 44 | } ASyncContext; | 44 | } ASyncContext; |
| 45 | 45 | ||
| @@ -141,7 +141,7 @@ static int request_frame(AVFilterLink *link) · 95 unmodified lines | |||
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | buf->pts = s->pts; | 143 | buf->pts = s->pts; |
| 144 | return ff_filter_samples(link, buf); | 144 | return ff_filter_frame(link, buf); |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | return ret; | 147 | return ret; |
| @@ -161,7 +161,7 @@ static int64_t get_delay(ASyncContext *s) · 13 unmodified lines | |||
| 161 | return avresample_available(s->avr) + avresample_get_delay(s->avr); | 161 | return avresample_available(s->avr) + avresample_get_delay(s->avr); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | 164 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 165 | { | 165 | { |
| 166 | AVFilterContext *ctx = inlink->dst; | 166 | AVFilterContext *ctx = inlink->dst; |
| 167 | ASyncContext *s = ctx->priv; | 167 | ASyncContext *s = ctx->priv; |
| @@ -217,7 +217,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 49 unmodified lines | |||
| 217 | av_samples_set_silence(buf_out->extended_data, out_size - delta, | 217 | av_samples_set_silence(buf_out->extended_data, out_size - delta, |
| 218 | delta, nb_channels, buf->format); | 218 | delta, nb_channels, buf->format); |
| 219 | } | 219 | } |
| 220 | ret = ff_filter_samples(outlink, buf_out); | 220 | ret = ff_filter_frame(outlink, buf_out); |
| 221 | if (ret < 0) | 221 | if (ret < 0) |
| 222 | goto fail; | 222 | goto fail; |
| 223 | s->got_output = 1; | 223 | s->got_output = 1; |
| @@ -243,7 +243,7 @@ static const AVFilterPad avfilter_af_asyncts_inputs[] = { · 19 unmodified lines | |||
| 243 | { | 243 | { |
| 244 | .name = "default", | 244 | .name = "default", |
| 245 | .type = AVMEDIA_TYPE_AUDIO, | 245 | .type = AVMEDIA_TYPE_AUDIO, |
| 246 | .filter_samples = filter_samples | 246 | .filter_frame = filter_frame, |
| 247 | }, | 247 | }, |
| 248 | { NULL } | 248 | { NULL } |
| 249 | }; | 249 | }; |
| @@ -313,7 +313,7 @@ static int channelmap_query_formats(AVFilterContext *ctx) · 312 unmodified lines | |||
| 313 | return 0; | 313 | return 0; |
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | 316 | static int channelmap_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 317 | { | 317 | { |
| 318 | AVFilterContext *ctx = inlink->dst; | 318 | AVFilterContext *ctx = inlink->dst; |
| 319 | AVFilterLink *outlink = ctx->outputs[0]; | 319 | AVFilterLink *outlink = ctx->outputs[0]; |
| @@ -355,7 +355,7 @@ static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *bu · 35 unmodified lines | |||
| 355 | memcpy(buf->data, buf->extended_data, | 355 | memcpy(buf->data, buf->extended_data, |
| 356 | FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0])); | 356 | FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0])); |
| 357 | 357 | ||
| 358 | return ff_filter_samples(outlink, buf); | 358 | return ff_filter_frame(outlink, buf); |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | static int channelmap_config_input(AVFilterLink *inlink) | 361 | static int channelmap_config_input(AVFilterLink *inlink) |
| @@ -389,7 +389,7 @@ static const AVFilterPad avfilter_af_channelmap_inputs[] = { · 27 unmodified lines | |||
| 389 | { | 389 | { |
| 390 | .name = "default", | 390 | .name = "default", |
| 391 | .type = AVMEDIA_TYPE_AUDIO, | 391 | .type = AVMEDIA_TYPE_AUDIO, |
| 392 | .filter_samples = channelmap_filter_samples, | 392 | .filter_frame = channelmap_filter_frame, |
| 393 | .config_props = channelmap_config_input | 393 | .config_props = channelmap_config_input |
| 394 | }, | 394 | }, |
| 395 | { NULL } | 395 | { NULL } |
| @@ -111,7 +111,7 @@ static int query_formats(AVFilterContext *ctx) · 110 unmodified lines | |||
| 111 | return 0; | 111 | return 0; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | 114 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 115 | { | 115 | { |
| 116 | AVFilterContext *ctx = inlink->dst; | 116 | AVFilterContext *ctx = inlink->dst; |
| 117 | int i, ret = 0; | 117 | int i, ret = 0; |
| @@ -128,7 +128,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 10 unmodified lines | |||
| 128 | buf_out->audio->channel_layout = | 128 | buf_out->audio->channel_layout = |
| 129 | av_channel_layout_extract_channel(buf->audio->channel_layout, i); | 129 | av_channel_layout_extract_channel(buf->audio->channel_layout, i); |
| 130 | 130 | ||
| 131 | ret = ff_filter_samples(ctx->outputs[i], buf_out); | 131 | ret = ff_filter_frame(ctx->outputs[i], buf_out); |
| 132 | if (ret < 0) | 132 | if (ret < 0) |
| 133 | break; | 133 | break; |
| 134 | } | 134 | } |
| @@ -140,7 +140,7 @@ static const AVFilterPad avfilter_af_channelsplit_inputs[] = { · 5 unmodified lines | |||
| 140 | { | 140 | { |
| 141 | .name = "default", | 141 | .name = "default", |
| 142 | .type = AVMEDIA_TYPE_AUDIO, | 142 | .type = AVMEDIA_TYPE_AUDIO, |
| 143 | .filter_samples = filter_samples, | 143 | .filter_frame = filter_frame, |
| 144 | }, | 144 | }, |
| 145 | { NULL } | 145 | { NULL } |
| 146 | }; | 146 | }; |
| @@ -93,7 +93,7 @@ static const AVClass join_class = { · 92 unmodified lines | |||
| 93 | .version = LIBAVUTIL_VERSION_INT, | 93 | .version = LIBAVUTIL_VERSION_INT, |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) | 96 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf) |
| 97 | { | 97 | { |
| 98 | AVFilterContext *ctx = link->dst; | 98 | AVFilterContext *ctx = link->dst; |
| 99 | JoinContext *s = ctx->priv; | 99 | JoinContext *s = ctx->priv; |
| @@ -230,7 +230,7 @@ static int join_init(AVFilterContext *ctx, const char *args) · 130 unmodified lines | |||
| 230 | snprintf(name, sizeof(name), "input%d", i); | 230 | snprintf(name, sizeof(name), "input%d", i); |
| 231 | pad.type = AVMEDIA_TYPE_AUDIO; | 231 | pad.type = AVMEDIA_TYPE_AUDIO; |
| 232 | pad.name = av_strdup(name); | 232 | pad.name = av_strdup(name); |
| 233 | pad.filter_samples = filter_samples; | 233 | pad.filter_frame = filter_frame; |
| 234 | 234 | ||
| 235 | pad.needs_fifo = 1; | 235 | pad.needs_fifo = 1; |
| 236 | 236 | ||
| @@ -471,7 +471,7 @@ static int join_request_frame(AVFilterLink *outlink) · 234 unmodified lines | |||
| 471 | priv->nb_in_buffers = ctx->nb_inputs; | 471 | priv->nb_in_buffers = ctx->nb_inputs; |
| 472 | buf->buf->priv = priv; | 472 | buf->buf->priv = priv; |
| 473 | 473 | ||
| 474 | ret = ff_filter_samples(outlink, buf); | 474 | ret = ff_filter_frame(outlink, buf); |
| 475 | 475 | ||
| 476 | memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs); | 476 | memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs); |
| 477 | 477 | ||
| @@ -40,7 +40,7 @@ typedef struct ResampleContext { · 39 unmodified lines | |||
| 40 | 40 | ||
| 41 | int64_t next_pts; | 41 | int64_t next_pts; |
| 42 | 42 | ||
| 43 | /* set by filter_samples() to signal an output frame to request_frame() */ | 43 | /* set by filter_frame() to signal an output frame to request_frame() */ |
| 44 | int got_output; | 44 | int got_output; |
| 45 | } ResampleContext; | 45 | } ResampleContext; |
| 46 | 46 | ||
| @@ -162,12 +162,12 @@ static int request_frame(AVFilterLink *outlink) · 115 unmodified lines | |||
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | buf->pts = s->next_pts; | 164 | buf->pts = s->next_pts; |
| 165 | return ff_filter_samples(outlink, buf); | 165 | return ff_filter_frame(outlink, buf); |
| 166 | } | 166 | } |
| 167 | return ret; | 167 | return ret; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) | 170 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 171 | { | 171 | { |
| 172 | AVFilterContext *ctx = inlink->dst; | 172 | AVFilterContext *ctx = inlink->dst; |
| 173 | ResampleContext *s = ctx->priv; | 173 | ResampleContext *s = ctx->priv; |
| @@ -224,7 +224,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 50 unmodified lines | |||
| 224 | 224 | ||
| 225 | s->next_pts = buf_out->pts + buf_out->audio->nb_samples; | 225 | s->next_pts = buf_out->pts + buf_out->audio->nb_samples; |
| 226 | 226 | ||
| 227 | ret = ff_filter_samples(outlink, buf_out); | 227 | ret = ff_filter_frame(outlink, buf_out); |
| 228 | s->got_output = 1; | 228 | s->got_output = 1; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| @@ -232,7 +232,7 @@ fail: · 1 unmodified line | |||
| 232 | avfilter_unref_buffer(buf); | 232 | avfilter_unref_buffer(buf); |
| 233 | } else { | 233 | } else { |
| 234 | buf->format = outlink->format; | 234 | buf->format = outlink->format; |
| 235 | ret = ff_filter_samples(outlink, buf); | 235 | ret = ff_filter_frame(outlink, buf); |
| 236 | s->got_output = 1; | 236 | s->got_output = 1; |
| 237 | } | 237 | } |
| 238 | 238 | ||
| @@ -243,7 +243,7 @@ static const AVFilterPad avfilter_af_resample_inputs[] = { · 4 unmodified lines | |||
| 243 | { | 243 | { |
| 244 | .name = "default", | 244 | .name = "default", |
| 245 | .type = AVMEDIA_TYPE_AUDIO, | 245 | .type = AVMEDIA_TYPE_AUDIO, |
| 246 | .filter_samples = filter_samples, | 246 | .filter_frame = filter_frame, |
| 247 | .min_perms = AV_PERM_READ | 247 | .min_perms = AV_PERM_READ |
| 248 | }, | 248 | }, |
| 249 | { NULL } | 249 | { NULL } |
| @@ -20,7 +20,7 @@ · 19 unmodified lines | |||
| 20 | #include "avfilter.h" | 20 | #include "avfilter.h" |
| 21 | #include "internal.h" | 21 | #include "internal.h" |
| 22 | 22 | ||
| 23 | static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | 23 | static int null_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref) |
| 24 | { | 24 | { |
| 25 | avfilter_unref_bufferp(&samplesref); | 25 | avfilter_unref_bufferp(&samplesref); |
| 26 | return 0; | 26 | return 0; |
| @@ -30,7 +30,7 @@ static const AVFilterPad avfilter_asink_anullsink_inputs[] = { · 3 unmodified lines | |||
| 30 | { | 30 | { |
| 31 | .name = "default", | 31 | .name = "default", |
| 32 | .type = AVMEDIA_TYPE_AUDIO, | 32 | .type = AVMEDIA_TYPE_AUDIO, |
| 33 | .filter_samples = null_filter_samples, | 33 | .filter_frame = null_filter_frame, |
| 34 | }, | 34 | }, |
| 35 | { NULL }, | 35 | { NULL }, |
| 36 | }; | 36 | }; |
| @@ -146,50 +146,3 @@ fail: · 145 unmodified lines | |||
| 146 | av_freep(&samples); | 146 | av_freep(&samples); |
| 147 | return NULL; | 147 | return NULL; |
| 148 | } | 148 | } |
| 149 | |||
| 150 | static int default_filter_samples(AVFilterLink *link, | ||
| 151 | AVFilterBufferRef *samplesref) | ||
| 152 | { | ||
| 153 | return ff_filter_samples(link->dst->outputs[0], samplesref); | ||
| 154 | } | ||
| 155 | |||
| 156 | int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) | ||
| 157 | { | ||
| 158 | int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); | ||
| 159 | AVFilterPad *dst = link->dstpad; | ||
| 160 | AVFilterBufferRef *buf_out; | ||
| 161 | |||
| 162 | FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); | ||
| 163 | |||
| 164 | if (!(filter_samples = dst->filter_samples)) | ||
| 165 | filter_samples = default_filter_samples; | ||
| 166 | |||
| 167 | /* prepare to copy the samples if the buffer has insufficient permissions */ | ||
| 168 | if ((dst->min_perms & samplesref->perms) != dst->min_perms || | ||
| 169 | dst->rej_perms & samplesref->perms) { | ||
| 170 | av_log(link->dst, AV_LOG_DEBUG, | ||
| 171 | "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n", | ||
| 172 | samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms); | ||
| 173 | |||
| 174 | buf_out = ff_default_get_audio_buffer(link, dst->min_perms, | ||
| 175 | samplesref->audio->nb_samples); | ||
| 176 | if (!buf_out) { | ||
| 177 | avfilter_unref_buffer(samplesref); | ||
| 178 | return AVERROR(ENOMEM); | ||
| 179 | } | ||
| 180 | buf_out->pts = samplesref->pts; | ||
| 181 | buf_out->audio->sample_rate = samplesref->audio->sample_rate; | ||
| 182 | |||
| 183 | /* Copy actual data into new samples buffer */ | ||
| 184 | av_samples_copy(buf_out->extended_data, samplesref->extended_data, | ||
| 185 | 0, 0, samplesref->audio->nb_samples, | ||
| 186 | av_get_channel_layout_nb_channels(link->channel_layout), | ||
| 187 | link->format); | ||
| 188 | |||
| 189 | avfilter_unref_buffer(samplesref); | ||
| 190 | } else | ||
| 191 | buf_out = samplesref; | ||
| 192 | |||
| 193 | return filter_samples(link, buf_out); | ||
| 194 | } | ||
| 195 | |||
| @@ -42,17 +42,4 @@ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms, · 41 unmodified lines | |||
| 42 | AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms, | 42 | AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms, |
| 43 | int nb_samples); | 43 | int nb_samples); |
| 44 | 44 | ||
| 45 | /** | ||
| 46 | * Send a buffer of audio samples to the next filter. | ||
| 47 | * | ||
| 48 | * @param link the output link over which the audio samples are being sent | ||
| 49 | * @param samplesref a reference to the buffer of audio samples being sent. The | ||
| 50 | * receiving filter will free this reference when it no longer | ||
| 51 | * needs it or pass it on to the next filter. | ||
| 52 | * | ||
| 53 | * @return >= 0 on success, a negative AVERROR on error. The receiving filter | ||
| 54 | * is responsible for unreferencing samplesref in case of error. | ||
| 55 | */ | ||
| 56 | int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); | ||
| 57 | |||
| 58 | #endif /* AVFILTER_AUDIO_H */ | 45 | #endif /* AVFILTER_AUDIO_H */ |
| @@ -23,12 +23,16 @@ · 22 unmodified lines | |||
| 23 | 23 | ||
| 24 | #include "libavutil/channel_layout.h" | 24 | #include "libavutil/channel_layout.h" |
| 25 | #include "libavutil/common.h" | 25 | #include "libavutil/common.h" |
| 26 | #include "libavutil/imgutils.h" | ||
| 26 | #include "libavutil/pixdesc.h" | 27 | #include "libavutil/pixdesc.h" |
| 27 | #include "libavutil/rational.h" | 28 | #include "libavutil/rational.h" |
| 29 | #include "libavutil/samplefmt.h" | ||
| 28 | 30 | ||
| 31 | #include "audio.h" | ||
| 29 | #include "avfilter.h" | 32 | #include "avfilter.h" |
| 30 | #include "formats.h" | 33 | #include "formats.h" |
| 31 | #include "internal.h" | 34 | #include "internal.h" |
| 35 | #include "video.h" | ||
| 32 | 36 | ||
| 33 | unsigned avfilter_version(void) { | 37 | unsigned avfilter_version(void) { |
| 34 | return LIBAVFILTER_VERSION_INT; | 38 | return LIBAVFILTER_VERSION_INT; |
| @@ -446,3 +450,68 @@ enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx) · 411 unmodified lines | |||
| 446 | { | 450 | { |
| 447 | return pads[pad_idx].type; | 451 | return pads[pad_idx].type; |
| 448 | } | 452 | } |
| 453 | |||
| 454 | static int default_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) | ||
| 455 | { | ||
| 456 | return ff_filter_frame(link->dst->outputs[0], frame); | ||
| 457 | } | ||
| 458 | |||
| 459 | int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) | ||
| 460 | { | ||
| 461 | int (*filter_frame)(AVFilterLink *, AVFilterBufferRef *); | ||
| 462 | AVFilterPad *dst = link->dstpad; | ||
| 463 | AVFilterBufferRef *out; | ||
| 464 | int perms = frame->perms; | ||
| 465 | |||
| 466 | FF_DPRINTF_START(NULL, filter_frame); | ||
| 467 | ff_dlog_link(NULL, link, 1); | ||
| 468 | |||
| 469 | if (!(filter_frame = dst->filter_frame)) | ||
| 470 | filter_frame = default_filter_frame; | ||
| 471 | |||
| 472 | if (frame->linesize[0] < 0) | ||
| 473 | perms |= AV_PERM_NEG_LINESIZES; | ||
| 474 | /* prepare to copy the frame if the buffer has insufficient permissions */ | ||
| 475 | if ((dst->min_perms & perms) != dst->min_perms || | ||
| 476 | dst->rej_perms & perms) { | ||
| 477 | av_log(link->dst, AV_LOG_DEBUG, | ||
| 478 | "Copying data in avfilter (have perms %x, need %x, reject %x)\n", | ||
| 479 | perms, link->dstpad->min_perms, link->dstpad->rej_perms); | ||
| 480 | |||
| 481 | switch (link->type) { | ||
| 482 | case AVMEDIA_TYPE_VIDEO: | ||
| 483 | out = ff_get_video_buffer(link, dst->min_perms, | ||
| 484 | link->w, link->h); | ||
| 485 | break; | ||
| 486 | case AVMEDIA_TYPE_AUDIO: | ||
| 487 | out = ff_get_audio_buffer(link, dst->min_perms, | ||
| 488 | frame->audio->nb_samples); | ||
| 489 | break; | ||
| 490 | default: return AVERROR(EINVAL); | ||
| 491 | } | ||
| 492 | if (!out) { | ||
| 493 | avfilter_unref_buffer(frame); | ||
| 494 | return AVERROR(ENOMEM); | ||
| 495 | } | ||
| 496 | avfilter_copy_buffer_ref_props(out, frame); | ||
| 497 | |||
| 498 | switch (link->type) { | ||
| 499 | case AVMEDIA_TYPE_VIDEO: | ||
| 500 | av_image_copy(out->data, out->linesize, frame->data, frame->linesize, | ||
| 501 | frame->format, frame->video->w, frame->video->h); | ||
| 502 | break; | ||
| 503 | case AVMEDIA_TYPE_AUDIO: | ||
| 504 | av_samples_copy(out->extended_data, frame->extended_data, | ||
| 505 | 0, 0, frame->audio->nb_samples, | ||
| 506 | av_get_channel_layout_nb_channels(frame->audio->channel_layout), | ||
| 507 | frame->format); | ||
| 508 | break; | ||
| 509 | default: return AVERROR(EINVAL); | ||
| 510 | } | ||
| 511 | |||
| 512 | avfilter_unref_buffer(frame); | ||
| 513 | } else | ||
| 514 | out = frame; | ||
| 515 | |||
| 516 | return filter_frame(link, out); | ||
| 517 | } | ||
| @@ -253,14 +253,7 @@ struct AVFilterPad { · 252 unmodified lines | |||
| 253 | int rej_perms; | 253 | int rej_perms; |
| 254 | 254 | ||
| 255 | /** | 255 | /** |
| 256 | * Callback called before passing the first slice of a new frame. If | 256 | * @deprecated unused |
| 257 | * NULL, the filter layer will default to storing a reference to the | ||
| 258 | * picture inside the link structure. | ||
| 259 | * | ||
| 260 | * Input video pads only. | ||
| 261 | * | ||
| 262 | * @return >= 0 on success, a negative AVERROR on error. picref will be | ||
| 263 | * unreferenced by the caller in case of error. | ||
| 264 | */ | 257 | */ |
| 265 | int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); | 258 | int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); |
| 266 | 259 | ||
| @@ -282,37 +275,26 @@ struct AVFilterPad { · 15 unmodified lines | |||
| 282 | int nb_samples); | 275 | int nb_samples); |
| 283 | 276 | ||
| 284 | /** | 277 | /** |
| 285 | * Callback called after the slices of a frame are completely sent. If | 278 | * @deprecated unused |
| 286 | * NULL, the filter layer will default to releasing the reference stored | ||
| 287 | * in the link structure during start_frame(). | ||
| 288 | * | ||
| 289 | * Input video pads only. | ||
| 290 | * | ||
| 291 | * @return >= 0 on success, a negative AVERROR on error. | ||
| 292 | */ | 279 | */ |
| 293 | int (*end_frame)(AVFilterLink *link); | 280 | int (*end_frame)(AVFilterLink *link); |
| 294 | 281 | ||
| 295 | /** | 282 | /** |
| 296 | * Slice drawing callback. This is where a filter receives video data | 283 | * @deprecated unused |
| 297 | * and should do its processing. | ||
| 298 | * | ||
| 299 | * Input video pads only. | ||
| 300 | * | ||
| 301 | * @return >= 0 on success, a negative AVERROR on error. | ||
| 302 | */ | 284 | */ |
| 303 | int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); | 285 | int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); |
| 304 | 286 | ||
| 305 | /** | 287 | /** |
| 306 | * Samples filtering callback. This is where a filter receives audio data | 288 | * Filtering callback. This is where a filter receives a frame with |
| 307 | * and should do its processing. | 289 | * audio/video data and should do its processing. |
| 308 | * | 290 | * |
| 309 | * Input audio pads only. | 291 | * Input pads only. |
| 310 | * | 292 | * |
| 311 | * @return >= 0 on success, a negative AVERROR on error. This function | 293 | * @return >= 0 on success, a negative AVERROR on error. This function |
| 312 | * must ensure that samplesref is properly unreferenced on error if it | 294 | * must ensure that samplesref is properly unreferenced on error if it |
| 313 | * hasn't been passed on to another filter. | 295 | * hasn't been passed on to another filter. |
| 314 | */ | 296 | */ |
| 315 | int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); | 297 | int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame); |
| 316 | 298 | ||
| 317 | /** | 299 | /** |
| 318 | * Frame poll callback. This returns the number of immediately available | 300 | * Frame poll callback. This returns the number of immediately available |
| @@ -531,18 +513,6 @@ struct AVFilterLink { · 212 unmodified lines | |||
| 531 | AVLINK_STARTINIT, ///< started, but incomplete | 513 | AVLINK_STARTINIT, ///< started, but incomplete |
| 532 | AVLINK_INIT ///< complete | 514 | AVLINK_INIT ///< complete |
| 533 | } init_state; | 515 | } init_state; |
| 534 | |||
| 535 | /** | ||
| 536 | * The buffer reference currently being sent across the link by the source | ||
| 537 | * filter. This is used internally by the filter system to allow | ||
| 538 | * automatic copying of buffers which do not have sufficient permissions | ||
| 539 | * for the destination. This should not be accessed directly by the | ||
| 540 | * filters. | ||
| 541 | */ | ||
| 542 | AVFilterBufferRef *src_buf; | ||
| 543 | |||
| 544 | AVFilterBufferRef *cur_buf; | ||
| 545 | AVFilterBufferRef *out_buf; | ||
| 546 | }; | 516 | }; |
| 547 | 517 | ||
| 548 | /** | 518 | /** |
| @@ -48,13 +48,12 @@ static av_cold void uninit(AVFilterContext *ctx) · 47 unmodified lines | |||
| 48 | av_audio_fifo_free(sink->audio_fifo); | 48 | av_audio_fifo_free(sink->audio_fifo); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf) | 51 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf) |
| 52 | { | 52 | { |
| 53 | BufferSinkContext *s = link->dst->priv; | 53 | BufferSinkContext *s = link->dst->priv; |
| 54 | 54 | ||
| 55 | av_assert0(!s->cur_buf); | 55 | av_assert0(!s->cur_buf); |
| 56 | s->cur_buf = buf; | 56 | s->cur_buf = buf; |
| 57 | link->cur_buf = NULL; | ||
| 58 | 57 | ||
| 59 | return 0; | 58 | return 0; |
| 60 | } | 59 | } |
| @@ -144,7 +143,7 @@ static const AVFilterPad avfilter_vsink_buffer_inputs[] = { · 83 unmodified lines | |||
| 144 | { | 143 | { |
| 145 | .name = "default", | 144 | .name = "default", |
| 146 | .type = AVMEDIA_TYPE_VIDEO, | 145 | .type = AVMEDIA_TYPE_VIDEO, |
| 147 | .start_frame = start_frame, | 146 | .filter_frame = filter_frame, |
| 148 | .min_perms = AV_PERM_READ, | 147 | .min_perms = AV_PERM_READ, |
| 149 | .needs_fifo = 1 | 148 | .needs_fifo = 1 |
| 150 | }, | 149 | }, |
| @@ -165,7 +164,7 @@ static const AVFilterPad avfilter_asink_abuffer_inputs[] = { · 14 unmodified lines | |||
| 165 | { | 164 | { |
| 166 | .name = "default", | 165 | .name = "default", |
| 167 | .type = AVMEDIA_TYPE_AUDIO, | 166 | .type = AVMEDIA_TYPE_AUDIO, |
| 168 | .filter_samples = start_frame, | 167 | .filter_frame = filter_frame, |
| 169 | .min_perms = AV_PERM_READ, | 168 | .min_perms = AV_PERM_READ, |
| 170 | .needs_fifo = 1 | 169 | .needs_fifo = 1 |
| 171 | }, | 170 | }, |
| @@ -327,20 +327,7 @@ static int request_frame(AVFilterLink *link) · 326 unmodified lines | |||
| 327 | } | 327 | } |
| 328 | av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL); | 328 | av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL); |
| 329 | 329 | ||
| 330 | switch (link->type) { | 330 | ff_filter_frame(link, buf); |
| 331 | case AVMEDIA_TYPE_VIDEO: | ||
| 332 | if ((ret = ff_start_frame(link, buf)) < 0 || | ||
| 333 | (ret = ff_draw_slice(link, 0, link->h, 1)) < 0 || | ||
| 334 | (ret = ff_end_frame(link)) < 0) | ||
| 335 | return ret; | ||
| 336 | break; | ||
| 337 | case AVMEDIA_TYPE_AUDIO: | ||
| 338 | ret = ff_filter_samples(link, buf); | ||
| 339 | break; | ||
| 340 | default: | ||
| 341 | avfilter_unref_bufferp(&buf); | ||
| 342 | return AVERROR(EINVAL); | ||
| 343 | } | ||
| 344 | 331 | ||
| 345 | return ret; | 332 | return ret; |
| 346 | } | 333 | } |
| @@ -77,7 +77,6 @@ static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) · 76 unmodified lines | |||
| 77 | { | 77 | { |
| 78 | FifoContext *fifo = inlink->dst->priv; | 78 | FifoContext *fifo = inlink->dst->priv; |
| 79 | 79 | ||
| 80 | inlink->cur_buf = NULL; | ||
| 81 | fifo->last->next = av_mallocz(sizeof(Buf)); | 80 | fifo->last->next = av_mallocz(sizeof(Buf)); |
| 82 | if (!fifo->last->next) { | 81 | if (!fifo->last->next) { |
| 83 | avfilter_unref_buffer(buf); | 82 | avfilter_unref_buffer(buf); |
| @@ -99,16 +98,6 @@ static void queue_pop(FifoContext *s) · 15 unmodified lines | |||
| 99 | s->root.next = tmp; | 98 | s->root.next = tmp; |
| 100 | } | 99 | } |
| 101 | 100 | ||
| 102 | static int end_frame(AVFilterLink *inlink) | ||
| 103 | { | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 108 | { | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | /** | 101 | /** |
| 113 | * Move data pointers and pts offset samples forward. | 102 | * Move data pointers and pts offset samples forward. |
| 114 | */ | 103 | */ |
| @@ -228,7 +217,7 @@ static int return_audio_frame(AVFilterContext *ctx) · 113 unmodified lines | |||
| 228 | buf_out = s->buf_out; | 217 | buf_out = s->buf_out; |
| 229 | s->buf_out = NULL; | 218 | s->buf_out = NULL; |
| 230 | } | 219 | } |
| 231 | return ff_filter_samples(link, buf_out); | 220 | return ff_filter_frame(link, buf_out); |
| 232 | } | 221 | } |
| 233 | 222 | ||
| 234 | static int request_frame(AVFilterLink *outlink) | 223 | static int request_frame(AVFilterLink *outlink) |
| @@ -241,27 +230,11 @@ static int request_frame(AVFilterLink *outlink) · 6 unmodified lines | |||
| 241 | return ret; | 230 | return ret; |
| 242 | } | 231 | } |
| 243 | 232 | ||
| 244 | /* by doing this, we give ownership of the reference to the next filter, | 233 | if (outlink->request_samples) { |
| 245 | * so we don't have to worry about dereferencing it ourselves. */ | 234 | return return_audio_frame(outlink->src); |
| 246 | switch (outlink->type) { | 235 | } else { |
| 247 | case AVMEDIA_TYPE_VIDEO: | 236 | ret = ff_filter_frame(outlink, fifo->root.next->buf); |
| 248 | if ((ret = ff_start_frame(outlink, fifo->root.next->buf)) < 0 || | ||
| 249 | (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || | ||
| 250 | (ret = ff_end_frame(outlink)) < 0) | ||
| 251 | return ret; | ||
| 252 | |||
| 253 | queue_pop(fifo); | 237 | queue_pop(fifo); |
| 254 | break; | ||
| 255 | case AVMEDIA_TYPE_AUDIO: | ||
| 256 | if (outlink->request_samples) { | ||
| 257 | return return_audio_frame(outlink->src); | ||
| 258 | } else { | ||
| 259 | ret = ff_filter_samples(outlink, fifo->root.next->buf); | ||
| 260 | queue_pop(fifo); | ||
| 261 | } | ||
| 262 | break; | ||
| 263 | default: | ||
| 264 | return AVERROR(EINVAL); | ||
| 265 | } | 238 | } |
| 266 | 239 | ||
| 267 | return ret; | 240 | return ret; |
| @@ -272,9 +245,7 @@ static const AVFilterPad avfilter_vf_fifo_inputs[] = { · 4 unmodified lines | |||
| 272 | .name = "default", | 245 | .name = "default", |
| 273 | .type = AVMEDIA_TYPE_VIDEO, | 246 | .type = AVMEDIA_TYPE_VIDEO, |
| 274 | .get_video_buffer = ff_null_get_video_buffer, | 247 | .get_video_buffer = ff_null_get_video_buffer, |
| 275 | .start_frame = add_to_queue, | 248 | .filter_frame = add_to_queue, |
| 276 | .draw_slice = draw_slice, | ||
| 277 | .end_frame = end_frame, | ||
| 278 | .rej_perms = AV_PERM_REUSE2, | 249 | .rej_perms = AV_PERM_REUSE2, |
| 279 | }, | 250 | }, |
| 280 | { NULL } | 251 | { NULL } |
| @@ -307,7 +278,7 @@ static const AVFilterPad avfilter_af_afifo_inputs[] = { · 26 unmodified lines | |||
| 307 | .name = "default", | 278 | .name = "default", |
| 308 | .type = AVMEDIA_TYPE_AUDIO, | 279 | .type = AVMEDIA_TYPE_AUDIO, |
| 309 | .get_audio_buffer = ff_null_get_audio_buffer, | 280 | .get_audio_buffer = ff_null_get_audio_buffer, |
| 310 | .filter_samples = add_to_queue, | 281 | .filter_frame = add_to_queue, |
| 311 | .rej_perms = AV_PERM_REUSE2, | 282 | .rej_perms = AV_PERM_REUSE2, |
| 312 | }, | 283 | }, |
| 313 | { NULL } | 284 | { NULL } |
| @@ -63,18 +63,6 @@ struct AVFilterPad { · 62 unmodified lines | |||
| 63 | */ | 63 | */ |
| 64 | int rej_perms; | 64 | int rej_perms; |
| 65 | 65 | ||
| 66 | /** | ||
| 67 | * Callback called before passing the first slice of a new frame. If | ||
| 68 | * NULL, the filter layer will default to storing a reference to the | ||
| 69 | * picture inside the link structure. | ||
| 70 | * | ||
| 71 | * Input video pads only. | ||
| 72 | * | ||
| 73 | * @return >= 0 on success, a negative AVERROR on error. picref will be | ||
| 74 | * unreferenced by the caller in case of error. | ||
| 75 | */ | ||
| 76 | void (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); | ||
| 77 | |||
| 78 | /** | 66 | /** |
| 79 | * Callback function to get a video buffer. If NULL, the filter system will | 67 | * Callback function to get a video buffer. If NULL, the filter system will |
| 80 | * use avfilter_default_get_video_buffer(). | 68 | * use avfilter_default_get_video_buffer(). |
| @@ -93,37 +81,16 @@ struct AVFilterPad { · 12 unmodified lines | |||
| 93 | int nb_samples); | 81 | int nb_samples); |
| 94 | 82 | ||
| 95 | /** | 83 | /** |
| 96 | * Callback called after the slices of a frame are completely sent. If | 84 | * Filtering callback. This is where a filter receives a frame with |
| 97 | * NULL, the filter layer will default to releasing the reference stored | 85 | * audio/video data and should do its processing. |
| 98 | * in the link structure during start_frame(). | ||
| 99 | * | 86 | * |
| 100 | * Input video pads only. | 87 | * Input pads only. |
| 101 | * | ||
| 102 | * @return >= 0 on success, a negative AVERROR on error. | ||
| 103 | */ | ||
| 104 | int (*end_frame)(AVFilterLink *link); | ||
| 105 | |||
| 106 | /** | ||
| 107 | * Slice drawing callback. This is where a filter receives video data | ||
| 108 | * and should do its processing. | ||
| 109 | * | ||
| 110 | * Input video pads only. | ||
| 111 | * | ||
| 112 | * @return >= 0 on success, a negative AVERROR on error. | ||
| 113 | */ | ||
| 114 | int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); | ||
| 115 | |||
| 116 | /** | ||
| 117 | * Samples filtering callback. This is where a filter receives audio data | ||
| 118 | * and should do its processing. | ||
| 119 | * | ||
| 120 | * Input audio pads only. | ||
| 121 | * | 88 | * |
| 122 | * @return >= 0 on success, a negative AVERROR on error. This function | 89 | * @return >= 0 on success, a negative AVERROR on error. This function |
| 123 | * must ensure that samplesref is properly unreferenced on error if it | 90 | * must ensure that samplesref is properly unreferenced on error if it |
| 124 | * hasn't been passed on to another filter. | 91 | * hasn't been passed on to another filter. |
| 125 | */ | 92 | */ |
| 126 | int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); | 93 | int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame); |
| 127 | 94 | ||
| 128 | /** | 95 | /** |
| 129 | * Frame poll callback. This returns the number of immediately available | 96 | * Frame poll callback. This returns the number of immediately available |
| @@ -237,4 +204,17 @@ int ff_poll_frame(AVFilterLink *link); · 107 unmodified lines | |||
| 237 | */ | 204 | */ |
| 238 | int ff_request_frame(AVFilterLink *link); | 205 | int ff_request_frame(AVFilterLink *link); |
| 239 | 206 | ||
| 207 | /** | ||
| 208 | * Send a frame of data to the next filter. | ||
| 209 | * | ||
| 210 | * @param link the output link over which the data is being sent | ||
| 211 | * @param frame a reference to the buffer of data being sent. The | ||
| 212 | * receiving filter will free this reference when it no longer | ||
| 213 | * needs it or pass it on to the next filter. | ||
| 214 | * | ||
| 215 | * @return >= 0 on success, a negative AVERROR on error. The receiving filter | ||
| 216 | * is responsible for unreferencing frame in case of error. | ||
| 217 | */ | ||
| 218 | int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame); | ||
| 219 | |||
| 240 | #endif /* AVFILTER_INTERNAL_H */ | 220 | #endif /* AVFILTER_INTERNAL_H */ |
| @@ -67,46 +67,23 @@ static void split_uninit(AVFilterContext *ctx) · 66 unmodified lines | |||
| 67 | av_freep(&ctx->output_pads[i].name); | 67 | av_freep(&ctx->output_pads[i].name); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | 70 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 71 | { | 71 | { |
| 72 | AVFilterContext *ctx = inlink->dst; | 72 | AVFilterContext *ctx = inlink->dst; |
| 73 | int i, ret = 0; | 73 | int i, ret = 0; |
| 74 | 74 | ||
| 75 | for (i = 0; i < ctx->nb_outputs; i++) { | 75 | for (i = 0; i < ctx->nb_outputs; i++) { |
| 76 | AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~AV_PERM_WRITE); | 76 | AVFilterBufferRef *buf_out = avfilter_ref_buffer(frame, ~AV_PERM_WRITE); |
| 77 | if (!buf_out) | 77 | if (!buf_out) { |
| 78 | return AVERROR(ENOMEM); | 78 | ret = AVERROR(ENOMEM); |
| 79 | |||
| 80 | ret = ff_start_frame(ctx->outputs[i], buf_out); | ||
| 81 | if (ret < 0) | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | return ret; | ||
| 85 | } | ||
| 86 | |||
| 87 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 88 | { | ||
| 89 | AVFilterContext *ctx = inlink->dst; | ||
| 90 | int i, ret = 0; | ||
| 91 | |||
| 92 | for (i = 0; i < ctx->nb_outputs; i++) { | ||
| 93 | ret = ff_draw_slice(ctx->outputs[i], y, h, slice_dir); | ||
| 94 | if (ret < 0) | ||
| 95 | break; | 79 | break; |
| 96 | } | 80 | } |
| 97 | return ret; | ||
| 98 | } | ||
| 99 | |||
| 100 | static int end_frame(AVFilterLink *inlink) | ||
| 101 | { | ||
| 102 | AVFilterContext *ctx = inlink->dst; | ||
| 103 | int i, ret = 0; | ||
| 104 | 81 | ||
| 105 | for (i = 0; i < ctx->nb_outputs; i++) { | 82 | ret = ff_filter_frame(ctx->outputs[i], buf_out); |
| 106 | ret = ff_end_frame(ctx->outputs[i]); | ||
| 107 | if (ret < 0) | 83 | if (ret < 0) |
| 108 | break; | 84 | break; |
| 109 | } | 85 | } |
| 86 | avfilter_unref_bufferp(&frame); | ||
| 110 | return ret; | 87 | return ret; |
| 111 | } | 88 | } |
| 112 | 89 | ||
| @@ -115,9 +92,7 @@ static const AVFilterPad avfilter_vf_split_inputs[] = { · 2 unmodified lines | |||
| 115 | .name = "default", | 92 | .name = "default", |
| 116 | .type = AVMEDIA_TYPE_VIDEO, | 93 | .type = AVMEDIA_TYPE_VIDEO, |
| 117 | .get_video_buffer = ff_null_get_video_buffer, | 94 | .get_video_buffer = ff_null_get_video_buffer, |
| 118 | .start_frame = start_frame, | 95 | .filter_frame = filter_frame, |
| 119 | .draw_slice = draw_slice, | ||
| 120 | .end_frame = end_frame, | ||
| 121 | }, | 96 | }, |
| 122 | { NULL } | 97 | { NULL } |
| 123 | }; | 98 | }; |
| @@ -133,33 +108,12 @@ AVFilter avfilter_vf_split = { · 9 unmodified lines | |||
| 133 | .outputs = NULL, | 108 | .outputs = NULL, |
| 134 | }; | 109 | }; |
| 135 | 110 | ||
| 136 | static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) | ||
| 137 | { | ||
| 138 | AVFilterContext *ctx = inlink->dst; | ||
| 139 | int i, ret = 0; | ||
| 140 | |||
| 141 | for (i = 0; i < ctx->nb_outputs; i++) { | ||
| 142 | AVFilterBufferRef *buf_out = avfilter_ref_buffer(samplesref, | ||
| 143 | ~AV_PERM_WRITE); | ||
| 144 | if (!buf_out) { | ||
| 145 | ret = AVERROR(ENOMEM); | ||
| 146 | break; | ||
| 147 | } | ||
| 148 | |||
| 149 | ret = ff_filter_samples(inlink->dst->outputs[i], buf_out); | ||
| 150 | if (ret < 0) | ||
| 151 | break; | ||
| 152 | } | ||
| 153 | avfilter_unref_buffer(samplesref); | ||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | |||
| 157 | static const AVFilterPad avfilter_af_asplit_inputs[] = { | 111 | static const AVFilterPad avfilter_af_asplit_inputs[] = { |
| 158 | { | 112 | { |
| 159 | .name = "default", | 113 | .name = "default", |
| 160 | .type = AVMEDIA_TYPE_AUDIO, | 114 | .type = AVMEDIA_TYPE_AUDIO, |
| 161 | .get_audio_buffer = ff_null_get_audio_buffer, | 115 | .get_audio_buffer = ff_null_get_audio_buffer, |
| 162 | .filter_samples = filter_samples | 116 | .filter_frame = filter_frame, |
| 163 | }, | 117 | }, |
| 164 | { NULL } | 118 | { NULL } |
| 165 | }; | 119 | }; |
| @@ -65,13 +65,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 64 unmodified lines | |||
| 65 | return 0; | 65 | return 0; |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 68 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) |
| 69 | { | 69 | { |
| 70 | AspectContext *aspect = link->dst->priv; | 70 | AspectContext *aspect = link->dst->priv; |
| 71 | 71 | ||
| 72 | picref->video->pixel_aspect = aspect->aspect; | 72 | frame->video->pixel_aspect = aspect->aspect; |
| 73 | link->cur_buf = NULL; | 73 | return ff_filter_frame(link->dst->outputs[0], frame); |
| 74 | return ff_start_frame(link->dst->outputs[0], picref); | ||
| 75 | } | 74 | } |
| 76 | 75 | ||
| 77 | #if CONFIG_SETDAR_FILTER | 76 | #if CONFIG_SETDAR_FILTER |
| @@ -99,8 +98,7 @@ static const AVFilterPad avfilter_vf_setdar_inputs[] = { · 21 unmodified lines | |||
| 99 | .type = AVMEDIA_TYPE_VIDEO, | 98 | .type = AVMEDIA_TYPE_VIDEO, |
| 100 | .config_props = setdar_config_props, | 99 | .config_props = setdar_config_props, |
| 101 | .get_video_buffer = ff_null_get_video_buffer, | 100 | .get_video_buffer = ff_null_get_video_buffer, |
| 102 | .start_frame = start_frame, | 101 | .filter_frame = filter_frame, |
| 103 | .end_frame = ff_null_end_frame | ||
| 104 | }, | 102 | }, |
| 105 | { NULL } | 103 | { NULL } |
| 106 | }; | 104 | }; |
| @@ -144,8 +142,7 @@ static const AVFilterPad avfilter_vf_setsar_inputs[] = { · 37 unmodified lines | |||
| 144 | .type = AVMEDIA_TYPE_VIDEO, | 142 | .type = AVMEDIA_TYPE_VIDEO, |
| 145 | .config_props = setsar_config_props, | 143 | .config_props = setsar_config_props, |
| 146 | .get_video_buffer = ff_null_get_video_buffer, | 144 | .get_video_buffer = ff_null_get_video_buffer, |
| 147 | .start_frame = start_frame, | 145 | .filter_frame = filter_frame, |
| 148 | .end_frame = ff_null_end_frame | ||
| 149 | }, | 146 | }, |
| 150 | { NULL } | 147 | { NULL } |
| 151 | }; | 148 | }; |
| @@ -78,49 +78,37 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 77 unmodified lines | |||
| 78 | return 0; | 78 | return 0; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | 81 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 82 | { | 82 | { |
| 83 | AVFilterContext *ctx = inlink->dst; | 83 | AVFilterContext *ctx = inlink->dst; |
| 84 | BlackFrameContext *blackframe = ctx->priv; | 84 | BlackFrameContext *blackframe = ctx->priv; |
| 85 | AVFilterBufferRef *picref = inlink->cur_buf; | ||
| 86 | int x, i; | 85 | int x, i; |
| 87 | uint8_t *p = picref->data[0] + y * picref->linesize[0]; | 86 | int pblack = 0; |
| 87 | uint8_t *p = frame->data[0]; | ||
| 88 | 88 | ||
| 89 | for (i = 0; i < h; i++) { | 89 | for (i = 0; i < frame->video->h; i++) { |
| 90 | for (x = 0; x < inlink->w; x++) | 90 | for (x = 0; x < inlink->w; x++) |
| 91 | blackframe->nblack += p[x] < blackframe->bthresh; | 91 | blackframe->nblack += p[x] < blackframe->bthresh; |
| 92 | p += picref->linesize[0]; | 92 | p += frame->linesize[0]; |
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | return ff_draw_slice(ctx->outputs[0], y, h, slice_dir); | ||
| 96 | } | ||
| 97 | |||
| 98 | static int end_frame(AVFilterLink *inlink) | ||
| 99 | { | ||
| 100 | AVFilterContext *ctx = inlink->dst; | ||
| 101 | BlackFrameContext *blackframe = ctx->priv; | ||
| 102 | AVFilterBufferRef *picref = inlink->cur_buf; | ||
| 103 | int pblack = 0; | ||
| 104 | |||
| 105 | pblack = blackframe->nblack * 100 / (inlink->w * inlink->h); | 95 | pblack = blackframe->nblack * 100 / (inlink->w * inlink->h); |
| 106 | if (pblack >= blackframe->bamount) | 96 | if (pblack >= blackframe->bamount) |
| 107 | av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pos:%"PRId64" pts:%"PRId64" t:%f\n", | 97 | av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pos:%"PRId64" pts:%"PRId64" t:%f\n", |
| 108 | blackframe->frame, pblack, picref->pos, picref->pts, | 98 | blackframe->frame, pblack, frame->pos, frame->pts, |
| 109 | picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base)); | 99 | frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base)); |
| 110 | 100 | ||
| 111 | blackframe->frame++; | 101 | blackframe->frame++; |
| 112 | blackframe->nblack = 0; | 102 | blackframe->nblack = 0; |
| 113 | return ff_end_frame(inlink->dst->outputs[0]); | 103 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 114 | } | 104 | } |
| 115 | 105 | ||
| 116 | static const AVFilterPad avfilter_vf_blackframe_inputs[] = { | 106 | static const AVFilterPad avfilter_vf_blackframe_inputs[] = { |
| 117 | { | 107 | { |
| 118 | .name = "default", | 108 | .name = "default", |
| 119 | .type = AVMEDIA_TYPE_VIDEO, | 109 | .type = AVMEDIA_TYPE_VIDEO, |
| 120 | .draw_slice = draw_slice, | ||
| 121 | .get_video_buffer = ff_null_get_video_buffer, | 110 | .get_video_buffer = ff_null_get_video_buffer, |
| 122 | .start_frame = ff_null_start_frame, | 111 | .filter_frame = filter_frame, |
| 123 | .end_frame = end_frame, | ||
| 124 | }, | 112 | }, |
| 125 | { NULL } | 113 | { NULL } |
| 126 | }; | 114 | }; |
| @@ -307,31 +307,39 @@ static void vblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_li · 306 unmodified lines | |||
| 307 | h, radius, power, temp); | 307 | h, radius, power, temp); |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | static int draw_slice(AVFilterLink *inlink, int y0, int h0, int slice_dir) | 310 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 311 | { | 311 | { |
| 312 | AVFilterContext *ctx = inlink->dst; | 312 | AVFilterContext *ctx = inlink->dst; |
| 313 | BoxBlurContext *boxblur = ctx->priv; | 313 | BoxBlurContext *boxblur = ctx->priv; |
| 314 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 314 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 315 | AVFilterBufferRef *inpicref = inlink ->cur_buf; | 315 | AVFilterBufferRef *out; |
| 316 | AVFilterBufferRef *outpicref = outlink->out_buf; | ||
| 317 | int plane; | 316 | int plane; |
| 318 | int cw = inlink->w >> boxblur->hsub, ch = h0 >> boxblur->vsub; | 317 | int cw = inlink->w >> boxblur->hsub, ch = in->video->h >> boxblur->vsub; |
| 319 | int w[4] = { inlink->w, cw, cw, inlink->w }; | 318 | int w[4] = { inlink->w, cw, cw, inlink->w }; |
| 320 | int h[4] = { h0, ch, ch, h0 }; | 319 | int h[4] = { in->video->h, ch, ch, in->video->h }; |
| 321 | 320 | ||
| 322 | for (plane = 0; inpicref->data[plane] && plane < 4; plane++) | 321 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 323 | hblur(outpicref->data[plane], outpicref->linesize[plane], | 322 | if (!out) { |
| 324 | inpicref ->data[plane], inpicref ->linesize[plane], | 323 | avfilter_unref_bufferp(&in); |
| 324 | return AVERROR(ENOMEM); | ||
| 325 | } | ||
| 326 | avfilter_copy_buffer_ref_props(out, in); | ||
| 327 | |||
| 328 | for (plane = 0; in->data[plane] && plane < 4; plane++) | ||
| 329 | hblur(out->data[plane], out->linesize[plane], | ||
| 330 | in ->data[plane], in ->linesize[plane], | ||
| 325 | w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], | 331 | w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], |
| 326 | boxblur->temp); | 332 | boxblur->temp); |
| 327 | 333 | ||
| 328 | for (plane = 0; inpicref->data[plane] && plane < 4; plane++) | 334 | for (plane = 0; in->data[plane] && plane < 4; plane++) |
| 329 | vblur(outpicref->data[plane], outpicref->linesize[plane], | 335 | vblur(out->data[plane], out->linesize[plane], |
| 330 | outpicref->data[plane], outpicref->linesize[plane], | 336 | out->data[plane], out->linesize[plane], |
| 331 | w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], | 337 | w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], |
| 332 | boxblur->temp); | 338 | boxblur->temp); |
| 333 | 339 | ||
| 334 | return ff_draw_slice(outlink, y0, h0, slice_dir); | 340 | avfilter_unref_bufferp(&in); |
| 341 | |||
| 342 | return ff_filter_frame(outlink, out); | ||
| 335 | } | 343 | } |
| 336 | 344 | ||
| 337 | static const AVFilterPad avfilter_vf_boxblur_inputs[] = { | 345 | static const AVFilterPad avfilter_vf_boxblur_inputs[] = { |
| @@ -339,7 +347,7 @@ static const AVFilterPad avfilter_vf_boxblur_inputs[] = { · 1 unmodified line | |||
| 339 | .name = "default", | 347 | .name = "default", |
| 340 | .type = AVMEDIA_TYPE_VIDEO, | 348 | .type = AVMEDIA_TYPE_VIDEO, |
| 341 | .config_props = config_input, | 349 | .config_props = config_input, |
| 342 | .draw_slice = draw_slice, | 350 | .filter_frame = filter_frame, |
| 343 | .min_perms = AV_PERM_READ | 351 | .min_perms = AV_PERM_READ |
| 344 | }, | 352 | }, |
| 345 | { NULL } | 353 | { NULL } |
| @@ -31,8 +31,6 @@ static const AVFilterPad avfilter_vf_copy_inputs[] = { · 30 unmodified lines | |||
| 31 | .name = "default", | 31 | .name = "default", |
| 32 | .type = AVMEDIA_TYPE_VIDEO, | 32 | .type = AVMEDIA_TYPE_VIDEO, |
| 33 | .get_video_buffer = ff_null_get_video_buffer, | 33 | .get_video_buffer = ff_null_get_video_buffer, |
| 34 | .start_frame = ff_null_start_frame, | ||
| 35 | .end_frame = ff_null_end_frame, | ||
| 36 | .rej_perms = ~0 | 34 | .rej_perms = ~0 |
| 37 | }, | 35 | }, |
| 38 | { NULL } | 36 | { NULL } |
| @@ -243,24 +243,19 @@ static int config_output(AVFilterLink *link) · 242 unmodified lines | |||
| 243 | return 0; | 243 | return 0; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 246 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) |
| 247 | { | 247 | { |
| 248 | AVFilterContext *ctx = link->dst; | 248 | AVFilterContext *ctx = link->dst; |
| 249 | CropContext *crop = ctx->priv; | 249 | CropContext *crop = ctx->priv; |
| 250 | AVFilterBufferRef *ref2; | ||
| 251 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); | 250 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); |
| 252 | int i; | 251 | int i; |
| 253 | 252 | ||
| 254 | ref2 = avfilter_ref_buffer(picref, ~0); | 253 | frame->video->w = crop->w; |
| 255 | if (!ref2) | 254 | frame->video->h = crop->h; |
| 256 | return AVERROR(ENOMEM); | ||
| 257 | 255 | ||
| 258 | ref2->video->w = crop->w; | 256 | crop->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ? |
| 259 | ref2->video->h = crop->h; | 257 | NAN : frame->pts * av_q2d(link->time_base); |
| 260 | 258 | crop->var_values[VAR_POS] = frame->pos == -1 ? NAN : frame->pos; | |
| 261 | crop->var_values[VAR_T] = picref->pts == AV_NOPTS_VALUE ? | ||
| 262 | NAN : picref->pts * av_q2d(link->time_base); | ||
| 263 | crop->var_values[VAR_POS] = picref->pos == -1 ? NAN : picref->pos; | ||
| 264 | crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL); | 259 | crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL); |
| 265 | crop->var_values[VAR_Y] = av_expr_eval(crop->y_pexpr, crop->var_values, NULL); | 260 | crop->var_values[VAR_Y] = av_expr_eval(crop->y_pexpr, crop->var_values, NULL); |
| 266 | crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL); | 261 | crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL); |
| @@ -279,60 +274,34 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 12 unmodified lines | |||
| 279 | (int)crop->var_values[VAR_N], crop->var_values[VAR_T], crop->x, | 274 | (int)crop->var_values[VAR_N], crop->var_values[VAR_T], crop->x, |
| 280 | crop->y, crop->x+crop->w, crop->y+crop->h); | 275 | crop->y, crop->x+crop->w, crop->y+crop->h); |
| 281 | 276 | ||
| 282 | ref2->data[0] += crop->y * ref2->linesize[0]; | 277 | frame->data[0] += crop->y * frame->linesize[0]; |
| 283 | ref2->data[0] += crop->x * crop->max_step[0]; | 278 | frame->data[0] += crop->x * crop->max_step[0]; |
| 284 | 279 | ||
| 285 | if (!(desc->flags & PIX_FMT_PAL || desc->flags & PIX_FMT_PSEUDOPAL)) { | 280 | if (!(desc->flags & PIX_FMT_PAL || desc->flags & PIX_FMT_PSEUDOPAL)) { |
| 286 | for (i = 1; i < 3; i ++) { | 281 | for (i = 1; i < 3; i ++) { |
| 287 | if (ref2->data[i]) { | 282 | if (frame->data[i]) { |
| 288 | ref2->data[i] += (crop->y >> crop->vsub) * ref2->linesize[i]; | 283 | frame->data[i] += (crop->y >> crop->vsub) * frame->linesize[i]; |
| 289 | ref2->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub; | 284 | frame->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub; |
| 290 | } | 285 | } |
| 291 | } | 286 | } |
| 292 | } | 287 | } |
| 293 | 288 | ||
| 294 | /* alpha plane */ | 289 | /* alpha plane */ |
| 295 | if (ref2->data[3]) { | 290 | if (frame->data[3]) { |
| 296 | ref2->data[3] += crop->y * ref2->linesize[3]; | 291 | frame->data[3] += crop->y * frame->linesize[3]; |
| 297 | ref2->data[3] += crop->x * crop->max_step[3]; | 292 | frame->data[3] += crop->x * crop->max_step[3]; |
| 298 | } | 293 | } |
| 299 | 294 | ||
| 300 | return ff_start_frame(link->dst->outputs[0], ref2); | ||
| 301 | } | ||
| 302 | |||
| 303 | static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 304 | { | ||
| 305 | AVFilterContext *ctx = link->dst; | ||
| 306 | CropContext *crop = ctx->priv; | ||
| 307 | |||
| 308 | if (y >= crop->y + crop->h || y + h <= crop->y) | ||
| 309 | return 0; | ||
| 310 | |||
| 311 | if (y < crop->y) { | ||
| 312 | h -= crop->y - y; | ||
| 313 | y = crop->y; | ||
| 314 | } | ||
| 315 | if (y + h > crop->y + crop->h) | ||
| 316 | h = crop->y + crop->h - y; | ||
| 317 | |||
| 318 | return ff_draw_slice(ctx->outputs[0], y - crop->y, h, slice_dir); | ||
| 319 | } | ||
| 320 | |||
| 321 | static int end_frame(AVFilterLink *link) | ||
| 322 | { | ||
| 323 | CropContext *crop = link->dst->priv; | ||
| 324 | |||
| 325 | crop->var_values[VAR_N] += 1.0; | 295 | crop->var_values[VAR_N] += 1.0; |
| 326 | return ff_end_frame(link->dst->outputs[0]); | 296 | |
| 297 | return ff_filter_frame(link->dst->outputs[0], frame); | ||
| 327 | } | 298 | } |
| 328 | 299 | ||
| 329 | static const AVFilterPad avfilter_vf_crop_inputs[] = { | 300 | static const AVFilterPad avfilter_vf_crop_inputs[] = { |
| 330 | { | 301 | { |
| 331 | .name = "default", | 302 | .name = "default", |
| 332 | .type = AVMEDIA_TYPE_VIDEO, | 303 | .type = AVMEDIA_TYPE_VIDEO, |
| 333 | .start_frame = start_frame, | 304 | .filter_frame = filter_frame, |
| 334 | .draw_slice = draw_slice, | ||
| 335 | .end_frame = end_frame, | ||
| 336 | .get_video_buffer = ff_null_get_video_buffer, | 305 | .get_video_buffer = ff_null_get_video_buffer, |
| 337 | .config_props = config_input, | 306 | .config_props = config_input, |
| 338 | }, | 307 | }, |
| @@ -117,11 +117,10 @@ static int config_input(AVFilterLink *inlink) · 116 unmodified lines | |||
| 117 | return 0; | 117 | return 0; |
| 118 | } | 118 | } |
| 119 | 119 | ||
| 120 | static int end_frame(AVFilterLink *inlink) | 120 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 121 | { | 121 | { |
| 122 | AVFilterContext *ctx = inlink->dst; | 122 | AVFilterContext *ctx = inlink->dst; |
| 123 | CropDetectContext *cd = ctx->priv; | 123 | CropDetectContext *cd = ctx->priv; |
| 124 | AVFilterBufferRef *picref = inlink->cur_buf; | ||
| 125 | int bpp = cd->max_pixsteps[0]; | 124 | int bpp = cd->max_pixsteps[0]; |
| 126 | int w, h, x, y, shrink_by; | 125 | int w, h, x, y, shrink_by; |
| 127 | 126 | ||
| @@ -129,36 +128,36 @@ static int end_frame(AVFilterLink *inlink) · 1 unmodified line | |||
| 129 | if (++cd->frame_nb > 0) { | 128 | if (++cd->frame_nb > 0) { |
| 130 | // Reset the crop area every reset_count frames, if reset_count is > 0 | 129 | // Reset the crop area every reset_count frames, if reset_count is > 0 |
| 131 | if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) { | 130 | if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) { |
| 132 | cd->x1 = picref->video->w-1; | 131 | cd->x1 = frame->video->w-1; |
| 133 | cd->y1 = picref->video->h-1; | 132 | cd->y1 = frame->video->h-1; |
| 134 | cd->x2 = 0; | 133 | cd->x2 = 0; |
| 135 | cd->y2 = 0; | 134 | cd->y2 = 0; |
| 136 | cd->frame_nb = 1; | 135 | cd->frame_nb = 1; |
| 137 | } | 136 | } |
| 138 | 137 | ||
| 139 | for (y = 0; y < cd->y1; y++) { | 138 | for (y = 0; y < cd->y1; y++) { |
| 140 | if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) { | 139 | if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) { |
| 141 | cd->y1 = y; | 140 | cd->y1 = y; |
| 142 | break; | 141 | break; |
| 143 | } | 142 | } |
| 144 | } | 143 | } |
| 145 | 144 | ||
| 146 | for (y = picref->video->h-1; y > cd->y2; y--) { | 145 | for (y = frame->video->h-1; y > cd->y2; y--) { |
| 147 | if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) { | 146 | if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) { |
| 148 | cd->y2 = y; | 147 | cd->y2 = y; |
| 149 | break; | 148 | break; |
| 150 | } | 149 | } |
| 151 | } | 150 | } |
| 152 | 151 | ||
| 153 | for (y = 0; y < cd->x1; y++) { | 152 | for (y = 0; y < cd->x1; y++) { |
| 154 | if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) { | 153 | if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) { |
| 155 | cd->x1 = y; | 154 | cd->x1 = y; |
| 156 | break; | 155 | break; |
| 157 | } | 156 | } |
| 158 | } | 157 | } |
| 159 | 158 | ||
| 160 | for (y = picref->video->w-1; y > cd->x2; y--) { | 159 | for (y = frame->video->w-1; y > cd->x2; y--) { |
| 161 | if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) { | 160 | if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) { |
| 162 | cd->x2 = y; | 161 | cd->x2 = y; |
| 163 | break; | 162 | break; |
| 164 | } | 163 | } |
| @@ -189,12 +188,12 @@ static int end_frame(AVFilterLink *inlink) · 24 unmodified lines | |||
| 189 | 188 | ||
| 190 | av_log(ctx, AV_LOG_INFO, | 189 | av_log(ctx, AV_LOG_INFO, |
| 191 | "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pos:%"PRId64" pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n", | 190 | "x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pos:%"PRId64" pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n", |
| 192 | cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, picref->pos, picref->pts, | 191 | cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, frame->pos, frame->pts, |
| 193 | picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base), | 192 | frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base), |
| 194 | w, h, x, y); | 193 | w, h, x, y); |
| 195 | } | 194 | } |
| 196 | 195 | ||
| 197 | return ff_end_frame(inlink->dst->outputs[0]); | 196 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 198 | } | 197 | } |
| 199 | 198 | ||
| 200 | static const AVFilterPad avfilter_vf_cropdetect_inputs[] = { | 199 | static const AVFilterPad avfilter_vf_cropdetect_inputs[] = { |
| @@ -203,8 +202,7 @@ static const AVFilterPad avfilter_vf_cropdetect_inputs[] = { · 2 unmodified lines | |||
| 203 | .type = AVMEDIA_TYPE_VIDEO, | 202 | .type = AVMEDIA_TYPE_VIDEO, |
| 204 | .config_props = config_input, | 203 | .config_props = config_input, |
| 205 | .get_video_buffer = ff_null_get_video_buffer, | 204 | .get_video_buffer = ff_null_get_video_buffer, |
| 206 | .start_frame = ff_null_start_frame, | 205 | .filter_frame = filter_frame, |
| 207 | .end_frame = end_frame, | ||
| 208 | }, | 206 | }, |
| 209 | { NULL } | 207 | { NULL } |
| 210 | }; | 208 | }; |
| @@ -215,30 +215,38 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 214 unmodified lines | |||
| 215 | return 0; | 215 | return 0; |
| 216 | } | 216 | } |
| 217 | 217 | ||
| 218 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | 218 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 219 | { | ||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int end_frame(AVFilterLink *inlink) | ||
| 224 | { | 219 | { |
| 225 | DelogoContext *delogo = inlink->dst->priv; | 220 | DelogoContext *delogo = inlink->dst->priv; |
| 226 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 221 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 227 | AVFilterBufferRef *inpicref = inlink ->cur_buf; | ||
| 228 | AVFilterBufferRef *outpicref = outlink->out_buf; | ||
| 229 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | 222 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); |
| 230 | int direct = inpicref->buf == outpicref->buf; | 223 | AVFilterBufferRef *out; |
| 231 | int hsub0 = desc->log2_chroma_w; | 224 | int hsub0 = desc->log2_chroma_w; |
| 232 | int vsub0 = desc->log2_chroma_h; | 225 | int vsub0 = desc->log2_chroma_h; |
| 226 | int direct; | ||
| 233 | int plane; | 227 | int plane; |
| 234 | int ret; | ||
| 235 | 228 | ||
| 236 | for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) { | 229 | if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) { |
| 230 | direct = 1; | ||
| 231 | out = in; | ||
| 232 | } else { | ||
| 233 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 234 | if (!out) { | ||
| 235 | avfilter_unref_bufferp(&in); | ||
| 236 | return AVERROR(ENOMEM); | ||
| 237 | } | ||
| 238 | |||
| 239 | avfilter_copy_buffer_ref_props(out, in); | ||
| 240 | out->video->w = outlink->w; | ||
| 241 | out->video->h = outlink->h; | ||
| 242 | } | ||
| 243 | |||
| 244 | for (plane = 0; plane < 4 && in->data[plane]; plane++) { | ||
| 237 | int hsub = plane == 1 || plane == 2 ? hsub0 : 0; | 245 | int hsub = plane == 1 || plane == 2 ? hsub0 : 0; |
| 238 | int vsub = plane == 1 || plane == 2 ? vsub0 : 0; | 246 | int vsub = plane == 1 || plane == 2 ? vsub0 : 0; |
| 239 | 247 | ||
| 240 | apply_delogo(outpicref->data[plane], outpicref->linesize[plane], | 248 | apply_delogo(out->data[plane], out->linesize[plane], |
| 241 | inpicref ->data[plane], inpicref ->linesize[plane], | 249 | in ->data[plane], in ->linesize[plane], |
| 242 | inlink->w>>hsub, inlink->h>>vsub, | 250 | inlink->w>>hsub, inlink->h>>vsub, |
| 243 | delogo->x>>hsub, delogo->y>>vsub, | 251 | delogo->x>>hsub, delogo->y>>vsub, |
| 244 | delogo->w>>hsub, delogo->h>>vsub, | 252 | delogo->w>>hsub, delogo->h>>vsub, |
| @@ -246,10 +254,10 @@ static int end_frame(AVFilterLink *inlink) · 1 unmodified line | |||
| 246 | delogo->show, direct); | 254 | delogo->show, direct); |
| 247 | } | 255 | } |
| 248 | 256 | ||
| 249 | if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 || | 257 | if (!direct) |
| 250 | (ret = ff_end_frame(outlink)) < 0) | 258 | avfilter_unref_bufferp(&in); |
| 251 | return ret; | 259 | |
| 252 | return 0; | 260 | return ff_filter_frame(outlink, out); |
| 253 | } | 261 | } |
| 254 | 262 | ||
| 255 | static const AVFilterPad avfilter_vf_delogo_inputs[] = { | 263 | static const AVFilterPad avfilter_vf_delogo_inputs[] = { |
| @@ -257,9 +265,7 @@ static const AVFilterPad avfilter_vf_delogo_inputs[] = { · 1 unmodified line | |||
| 257 | .name = "default", | 265 | .name = "default", |
| 258 | .type = AVMEDIA_TYPE_VIDEO, | 266 | .type = AVMEDIA_TYPE_VIDEO, |
| 259 | .get_video_buffer = ff_null_get_video_buffer, | 267 | .get_video_buffer = ff_null_get_video_buffer, |
| 260 | .start_frame = ff_inplace_start_frame, | 268 | .filter_frame = filter_frame, |
| 261 | .draw_slice = null_draw_slice, | ||
| 262 | .end_frame = end_frame, | ||
| 263 | .min_perms = AV_PERM_WRITE | AV_PERM_READ, | 269 | .min_perms = AV_PERM_WRITE | AV_PERM_READ, |
| 264 | .rej_perms = AV_PERM_PRESERVE | 270 | .rej_perms = AV_PERM_PRESERVE |
| 265 | }, | 271 | }, |
| @@ -96,21 +96,20 @@ static int config_input(AVFilterLink *inlink) · 95 unmodified lines | |||
| 96 | return 0; | 96 | return 0; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir) | 99 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 100 | { | 100 | { |
| 101 | DrawBoxContext *drawbox = inlink->dst->priv; | 101 | DrawBoxContext *drawbox = inlink->dst->priv; |
| 102 | int plane, x, y, xb = drawbox->x, yb = drawbox->y; | 102 | int plane, x, y, xb = drawbox->x, yb = drawbox->y; |
| 103 | unsigned char *row[4]; | 103 | unsigned char *row[4]; |
| 104 | AVFilterBufferRef *picref = inlink->cur_buf; | ||
| 105 | 104 | ||
| 106 | for (y = FFMAX(yb, y0); y < (y0 + h) && y < (yb + drawbox->h); y++) { | 105 | for (y = FFMAX(yb, 0); y < frame->video->h && y < (yb + drawbox->h); y++) { |
| 107 | row[0] = picref->data[0] + y * picref->linesize[0]; | 106 | row[0] = frame->data[0] + y * frame->linesize[0]; |
| 108 | 107 | ||
| 109 | for (plane = 1; plane < 3; plane++) | 108 | for (plane = 1; plane < 3; plane++) |
| 110 | row[plane] = picref->data[plane] + | 109 | row[plane] = frame->data[plane] + |
| 111 | picref->linesize[plane] * (y >> drawbox->vsub); | 110 | frame->linesize[plane] * (y >> drawbox->vsub); |
| 112 | 111 | ||
| 113 | for (x = FFMAX(xb, 0); x < (xb + drawbox->w) && x < picref->video->w; x++) { | 112 | for (x = FFMAX(xb, 0); x < (xb + drawbox->w) && x < frame->video->w; x++) { |
| 114 | double alpha = (double)drawbox->yuv_color[A] / 255; | 113 | double alpha = (double)drawbox->yuv_color[A] / 255; |
| 115 | 114 | ||
| 116 | if ((y - yb < 3) || (yb + drawbox->h - y < 4) || | 115 | if ((y - yb < 3) || (yb + drawbox->h - y < 4) || |
| @@ -122,7 +121,7 @@ static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir) · 5 unmodified lines | |||
| 122 | } | 121 | } |
| 123 | } | 122 | } |
| 124 | 123 | ||
| 125 | return ff_draw_slice(inlink->dst->outputs[0], y0, h, 1); | 124 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 126 | } | 125 | } |
| 127 | 126 | ||
| 128 | static const AVFilterPad avfilter_vf_drawbox_inputs[] = { | 127 | static const AVFilterPad avfilter_vf_drawbox_inputs[] = { |
| @@ -131,9 +130,7 @@ static const AVFilterPad avfilter_vf_drawbox_inputs[] = { · 2 unmodified lines | |||
| 131 | .type = AVMEDIA_TYPE_VIDEO, | 130 | .type = AVMEDIA_TYPE_VIDEO, |
| 132 | .config_props = config_input, | 131 | .config_props = config_input, |
| 133 | .get_video_buffer = ff_null_get_video_buffer, | 132 | .get_video_buffer = ff_null_get_video_buffer, |
| 134 | .start_frame = ff_null_start_frame, | 133 | .filter_frame = filter_frame, |
| 135 | .draw_slice = draw_slice, | ||
| 136 | .end_frame = ff_null_end_frame, | ||
| 137 | .min_perms = AV_PERM_WRITE | AV_PERM_READ, | 134 | .min_perms = AV_PERM_WRITE | AV_PERM_READ, |
| 138 | .rej_perms = AV_PERM_PRESERVE | 135 | .rej_perms = AV_PERM_PRESERVE |
| 139 | }, | 136 | }, |
| @@ -792,11 +792,6 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref, · 791 unmodified lines | |||
| 792 | return 0; | 792 | return 0; |
| 793 | } | 793 | } |
| 794 | 794 | ||
| 795 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 796 | { | ||
| 797 | return 0; | ||
| 798 | } | ||
| 799 | |||
| 800 | static inline int normalize_double(int *n, double d) | 795 | static inline int normalize_double(int *n, double d) |
| 801 | { | 796 | { |
| 802 | int ret = 0; | 797 | int ret = 0; |
| @@ -812,20 +807,20 @@ static inline int normalize_double(int *n, double d) · 9 unmodified lines | |||
| 812 | return ret; | 807 | return ret; |
| 813 | } | 808 | } |
| 814 | 809 | ||
| 815 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) | 810 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 816 | { | 811 | { |
| 817 | AVFilterContext *ctx = inlink->dst; | 812 | AVFilterContext *ctx = inlink->dst; |
| 818 | DrawTextContext *dtext = ctx->priv; | 813 | DrawTextContext *dtext = ctx->priv; |
| 819 | AVFilterBufferRef *buf_out; | ||
| 820 | int ret = 0; | 814 | int ret = 0; |
| 821 | 815 | ||
| 822 | if ((ret = dtext_prepare_text(ctx)) < 0) { | 816 | if ((ret = dtext_prepare_text(ctx)) < 0) { |
| 823 | av_log(ctx, AV_LOG_ERROR, "Can't draw text\n"); | 817 | av_log(ctx, AV_LOG_ERROR, "Can't draw text\n"); |
| 818 | avfilter_unref_bufferp(&frame); | ||
| 824 | return ret; | 819 | return ret; |
| 825 | } | 820 | } |
| 826 | 821 | ||
| 827 | dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ? | 822 | dtext->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ? |
| 828 | NAN : inpicref->pts * av_q2d(inlink->time_base); | 823 | NAN : frame->pts * av_q2d(inlink->time_base); |
| 829 | dtext->var_values[VAR_X] = | 824 | dtext->var_values[VAR_X] = |
| 830 | av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng); | 825 | av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng); |
| 831 | dtext->var_values[VAR_Y] = | 826 | dtext->var_values[VAR_Y] = |
| @@ -854,29 +849,12 @@ static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) · 22 unmodified lines | |||
| 854 | (int)dtext->var_values[VAR_N], dtext->var_values[VAR_T], | 849 | (int)dtext->var_values[VAR_N], dtext->var_values[VAR_T], |
| 855 | dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h); | 850 | dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h); |
| 856 | 851 | ||
| 857 | buf_out = avfilter_ref_buffer(inpicref, ~0); | ||
| 858 | if (!buf_out) | ||
| 859 | return AVERROR(ENOMEM); | ||
| 860 | |||
| 861 | return ff_start_frame(inlink->dst->outputs[0], buf_out); | ||
| 862 | } | ||
| 863 | |||
| 864 | static int end_frame(AVFilterLink *inlink) | ||
| 865 | { | ||
| 866 | AVFilterLink *outlink = inlink->dst->outputs[0]; | ||
| 867 | AVFilterBufferRef *picref = inlink->cur_buf; | ||
| 868 | DrawTextContext *dtext = inlink->dst->priv; | ||
| 869 | int ret; | ||
| 870 | |||
| 871 | if (dtext->draw) | 852 | if (dtext->draw) |
| 872 | draw_text(inlink->dst, picref, picref->video->w, picref->video->h); | 853 | draw_text(inlink->dst, frame, frame->video->w, frame->video->h); |
| 873 | 854 | ||
| 874 | dtext->var_values[VAR_N] += 1.0; | 855 | dtext->var_values[VAR_N] += 1.0; |
| 875 | 856 | ||
| 876 | if ((ret = ff_draw_slice(outlink, 0, picref->video->h, 1)) < 0 || | 857 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 877 | (ret = ff_end_frame(outlink)) < 0) | ||
| 878 | return ret; | ||
| 879 | return 0; | ||
| 880 | } | 858 | } |
| 881 | 859 | ||
| 882 | static const AVFilterPad avfilter_vf_drawtext_inputs[] = { | 860 | static const AVFilterPad avfilter_vf_drawtext_inputs[] = { |
| @@ -884,9 +862,7 @@ static const AVFilterPad avfilter_vf_drawtext_inputs[] = { · 1 unmodified line | |||
| 884 | .name = "default", | 862 | .name = "default", |
| 885 | .type = AVMEDIA_TYPE_VIDEO, | 863 | .type = AVMEDIA_TYPE_VIDEO, |
| 886 | .get_video_buffer = ff_null_get_video_buffer, | 864 | .get_video_buffer = ff_null_get_video_buffer, |
| 887 | .start_frame = start_frame, | 865 | .filter_frame = filter_frame, |
| 888 | .draw_slice = null_draw_slice, | ||
| 889 | .end_frame = end_frame, | ||
| 890 | .config_props = config_input, | 866 | .config_props = config_input, |
| 891 | .min_perms = AV_PERM_WRITE | | 867 | .min_perms = AV_PERM_WRITE | |
| 892 | AV_PERM_READ, | 868 | AV_PERM_READ, |
| @@ -98,17 +98,16 @@ static int config_props(AVFilterLink *inlink) · 97 unmodified lines | |||
| 98 | return 0; | 98 | return 0; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | 101 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 102 | { | 102 | { |
| 103 | FadeContext *fade = inlink->dst->priv; | 103 | FadeContext *fade = inlink->dst->priv; |
| 104 | AVFilterBufferRef *outpic = inlink->cur_buf; | ||
| 105 | uint8_t *p; | 104 | uint8_t *p; |
| 106 | int i, j, plane; | 105 | int i, j, plane; |
| 107 | 106 | ||
| 108 | if (fade->factor < UINT16_MAX) { | 107 | if (fade->factor < UINT16_MAX) { |
| 109 | /* luma or rgb plane */ | 108 | /* luma or rgb plane */ |
| 110 | for (i = 0; i < h; i++) { | 109 | for (i = 0; i < frame->video->h; i++) { |
| 111 | p = outpic->data[0] + (y+i) * outpic->linesize[0]; | 110 | p = frame->data[0] + i * frame->linesize[0]; |
| 112 | for (j = 0; j < inlink->w * fade->bpp; j++) { | 111 | for (j = 0; j < inlink->w * fade->bpp; j++) { |
| 113 | /* fade->factor is using 16 lower-order bits for decimal | 112 | /* fade->factor is using 16 lower-order bits for decimal |
| 114 | * places. 32768 = 1 << 15, it is an integer representation | 113 | * places. 32768 = 1 << 15, it is an integer representation |
| @@ -118,11 +117,11 @@ static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) · 3 unmodified lines | |||
| 118 | } | 117 | } |
| 119 | } | 118 | } |
| 120 | 119 | ||
| 121 | if (outpic->data[1] && outpic->data[2]) { | 120 | if (frame->data[1] && frame->data[2]) { |
| 122 | /* chroma planes */ | 121 | /* chroma planes */ |
| 123 | for (plane = 1; plane < 3; plane++) { | 122 | for (plane = 1; plane < 3; plane++) { |
| 124 | for (i = 0; i < h; i++) { | 123 | for (i = 0; i < frame->video->h; i++) { |
| 125 | p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane]; | 124 | p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane]; |
| 126 | for (j = 0; j < inlink->w >> fade->hsub; j++) { | 125 | for (j = 0; j < inlink->w >> fade->hsub; j++) { |
| 127 | /* 8421367 = ((128 << 1) + 1) << 15. It is an integer | 126 | /* 8421367 = ((128 << 1) + 1) << 15. It is an integer |
| 128 | * representation of 128.5. The .5 is for rounding | 127 | * representation of 128.5. The .5 is for rounding |
| @@ -135,23 +134,13 @@ static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) · 6 unmodified lines | |||
| 135 | } | 134 | } |
| 136 | } | 135 | } |
| 137 | 136 | ||
| 138 | return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int end_frame(AVFilterLink *inlink) | ||
| 142 | { | ||
| 143 | FadeContext *fade = inlink->dst->priv; | ||
| 144 | int ret; | ||
| 145 | |||
| 146 | ret = ff_end_frame(inlink->dst->outputs[0]); | ||
| 147 | |||
| 148 | if (fade->frame_index >= fade->start_frame && | 137 | if (fade->frame_index >= fade->start_frame && |
| 149 | fade->frame_index <= fade->stop_frame) | 138 | fade->frame_index <= fade->stop_frame) |
| 150 | fade->factor += fade->fade_per_frame; | 139 | fade->factor += fade->fade_per_frame; |
| 151 | fade->factor = av_clip_uint16(fade->factor); | 140 | fade->factor = av_clip_uint16(fade->factor); |
| 152 | fade->frame_index++; | 141 | fade->frame_index++; |
| 153 | 142 | ||
| 154 | return ret; | 143 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 155 | } | 144 | } |
| 156 | 145 | ||
| 157 | static const AVFilterPad avfilter_vf_fade_inputs[] = { | 146 | static const AVFilterPad avfilter_vf_fade_inputs[] = { |
| @@ -160,9 +149,7 @@ static const AVFilterPad avfilter_vf_fade_inputs[] = { · 2 unmodified lines | |||
| 160 | .type = AVMEDIA_TYPE_VIDEO, | 149 | .type = AVMEDIA_TYPE_VIDEO, |
| 161 | .config_props = config_props, | 150 | .config_props = config_props, |
| 162 | .get_video_buffer = ff_null_get_video_buffer, | 151 | .get_video_buffer = ff_null_get_video_buffer, |
| 163 | .start_frame = ff_null_start_frame, | 152 | .filter_frame = filter_frame, |
| 164 | .draw_slice = draw_slice, | ||
| 165 | .end_frame = end_frame, | ||
| 166 | .min_perms = AV_PERM_READ | AV_PERM_WRITE, | 153 | .min_perms = AV_PERM_READ | AV_PERM_WRITE, |
| 167 | .rej_perms = AV_PERM_PRESERVE, | 154 | .rej_perms = AV_PERM_PRESERVE, |
| 168 | }, | 155 | }, |
| @@ -121,90 +121,39 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int · 120 unmodified lines | |||
| 121 | return ff_get_video_buffer(outlink, perms, w, h); | 121 | return ff_get_video_buffer(outlink, perms, w, h); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) | 124 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 125 | { | 125 | { |
| 126 | AVFilterContext *ctx = inlink->dst; | 126 | AVFilterContext *ctx = inlink->dst; |
| 127 | AVFilterLink *outlink = ctx->outputs[0]; | 127 | FieldOrderContext *s = ctx->priv; |
| 128 | 128 | AVFilterLink *outlink = ctx->outputs[0]; | |
| 129 | AVFilterBufferRef *outpicref, *for_next_filter; | 129 | int h, plane, line_step, line_size, line; |
| 130 | int ret = 0; | 130 | uint8_t *data; |
| 131 | |||
| 132 | outpicref = avfilter_ref_buffer(inpicref, ~0); | ||
| 133 | if (!outpicref) | ||
| 134 | return AVERROR(ENOMEM); | ||
| 135 | |||
| 136 | for_next_filter = avfilter_ref_buffer(outpicref, ~0); | ||
| 137 | if (!for_next_filter) { | ||
| 138 | avfilter_unref_bufferp(&outpicref); | ||
| 139 | return AVERROR(ENOMEM); | ||
| 140 | } | ||
| 141 | |||
| 142 | ret = ff_start_frame(outlink, for_next_filter); | ||
| 143 | if (ret < 0) { | ||
| 144 | avfilter_unref_bufferp(&outpicref); | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 148 | outlink->out_buf = outpicref; | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 153 | { | ||
| 154 | AVFilterContext *ctx = inlink->dst; | ||
| 155 | FieldOrderContext *fieldorder = ctx->priv; | ||
| 156 | AVFilterLink *outlink = ctx->outputs[0]; | ||
| 157 | |||
| 158 | AVFilterBufferRef *inpicref = inlink->cur_buf; | ||
| 159 | 131 | ||
| 160 | /** can only currently do slices if this filter is doing nothing | 132 | if (!frame->video->interlaced || |
| 161 | * because this filter is moving picture content, the output | 133 | frame->video->top_field_first == s->dst_tff) |
| 162 | * slice will contain different video lines than the input slice | 134 | return ff_filter_frame(outlink, frame); |
| 163 | * and that complexity will be added later */ | ||
| 164 | if ( !inpicref->video->interlaced | ||
| 165 | || inpicref->video->top_field_first == fieldorder->dst_tff) { | ||
| 166 | return ff_draw_slice(outlink, y, h, slice_dir); | ||
| 167 | } | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | 135 | ||
| 171 | static int end_frame(AVFilterLink *inlink) | ||
| 172 | { | ||
| 173 | AVFilterContext *ctx = inlink->dst; | ||
| 174 | FieldOrderContext *fieldorder = ctx->priv; | ||
| 175 | AVFilterLink *outlink = ctx->outputs[0]; | ||
| 176 | |||
| 177 | AVFilterBufferRef *inpicref = inlink->cur_buf; | ||
| 178 | AVFilterBufferRef *outpicref = outlink->out_buf; | ||
| 179 | |||
| 180 | int h, plane, line_step, line_size, line; | ||
| 181 | uint8_t *cpy_src, *cpy_dst; | ||
| 182 | |||
| 183 | if ( inpicref->video->interlaced | ||
| 184 | && inpicref->video->top_field_first != fieldorder->dst_tff) { | ||
| 185 | av_dlog(ctx, | 136 | av_dlog(ctx, |
| 186 | "picture will move %s one line\n", | 137 | "picture will move %s one line\n", |
| 187 | fieldorder->dst_tff ? "up" : "down"); | 138 | s->dst_tff ? "up" : "down"); |
| 188 | h = inpicref->video->h; | 139 | h = frame->video->h; |
| 189 | for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) { | 140 | for (plane = 0; plane < 4 && frame->data[plane]; plane++) { |
| 190 | line_step = inpicref->linesize[plane]; | 141 | line_step = frame->linesize[plane]; |
| 191 | line_size = fieldorder->line_size[plane]; | 142 | line_size = s->line_size[plane]; |
| 192 | cpy_src = inpicref->data[plane]; | 143 | data = frame->data[plane]; |
| 193 | cpy_dst = outpicref->data[plane]; | 144 | if (s->dst_tff) { |
| 194 | if (fieldorder->dst_tff) { | ||
| 195 | /** Move every line up one line, working from | 145 | /** Move every line up one line, working from |
| 196 | * the top to the bottom of the frame. | 146 | * the top to the bottom of the frame. |
| 197 | * The original top line is lost. | 147 | * The original top line is lost. |
| 198 | * The new last line is created as a copy of the | 148 | * The new last line is created as a copy of the |
| 199 | * penultimate line from that field. */ | 149 | * penultimate line from that field. */ |
| 200 | for (line = 0; line < h; line++) { | 150 | for (line = 0; line < h; line++) { |
| 201 | if (1 + line < outpicref->video->h) { | 151 | if (1 + line < frame->video->h) { |
| 202 | memcpy(cpy_dst, cpy_src + line_step, line_size); | 152 | memcpy(data, data + line_step, line_size); |
| 203 | } else { | 153 | } else { |
| 204 | memcpy(cpy_dst, cpy_src - line_step - line_step, line_size); | 154 | memcpy(data, data - line_step - line_step, line_size); |
| 205 | } | 155 | } |
| 206 | cpy_src += line_step; | 156 | data += line_step; |
| 207 | cpy_dst += line_step; | ||
| 208 | } | 157 | } |
| 209 | } else { | 158 | } else { |
| 210 | /** Move every line down one line, working from | 159 | /** Move every line down one line, working from |
| @@ -212,27 +161,20 @@ static int end_frame(AVFilterLink *inlink) · 1 unmodified line | |||
| 212 | * The original bottom line is lost. | 161 | * The original bottom line is lost. |
| 213 | * The new first line is created as a copy of the | 162 | * The new first line is created as a copy of the |
| 214 | * second line from that field. */ | 163 | * second line from that field. */ |
| 215 | cpy_src += (h - 1) * line_step; | 164 | data += (h - 1) * line_step; |
| 216 | cpy_dst += (h - 1) * line_step; | ||
| 217 | for (line = h - 1; line >= 0 ; line--) { | 165 | for (line = h - 1; line >= 0 ; line--) { |
| 218 | if (line > 0) { | 166 | if (line > 0) { |
| 219 | memcpy(cpy_dst, cpy_src - line_step, line_size); | 167 | memcpy(data, data - line_step, line_size); |
| 220 | } else { | 168 | } else { |
| 221 | memcpy(cpy_dst, cpy_src + line_step + line_step, line_size); | 169 | memcpy(data, data + line_step + line_step, line_size); |
| 222 | } | 170 | } |
| 223 | cpy_src -= line_step; | 171 | data -= line_step; |
| 224 | cpy_dst -= line_step; | ||
| 225 | } | 172 | } |
| 226 | } | 173 | } |
| 227 | } | 174 | } |
| 228 | outpicref->video->top_field_first = fieldorder->dst_tff; | 175 | frame->video->top_field_first = s->dst_tff; |
| 229 | ff_draw_slice(outlink, 0, h, 1); | ||
| 230 | } else { | ||
| 231 | av_dlog(ctx, | ||
| 232 | "not interlaced or field order already correct\n"); | ||
| 233 | } | ||
| 234 | 176 | ||
| 235 | return ff_end_frame(outlink); | 177 | return ff_filter_frame(outlink, frame); |
| 236 | } | 178 | } |
| 237 | 179 | ||
| 238 | static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { | 180 | static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { |
| @@ -240,10 +182,8 @@ static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { · 1 unmodified line | |||
| 240 | .name = "default", | 182 | .name = "default", |
| 241 | .type = AVMEDIA_TYPE_VIDEO, | 183 | .type = AVMEDIA_TYPE_VIDEO, |
| 242 | .config_props = config_input, | 184 | .config_props = config_input, |
| 243 | .start_frame = start_frame, | ||
| 244 | .get_video_buffer = get_video_buffer, | 185 | .get_video_buffer = get_video_buffer, |
| 245 | .draw_slice = draw_slice, | 186 | .filter_frame = filter_frame, |
| 246 | .end_frame = end_frame, | ||
| 247 | .min_perms = AV_PERM_READ, | 187 | .min_perms = AV_PERM_READ, |
| 248 | .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE, | 188 | .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE, |
| 249 | }, | 189 | }, |
| @@ -104,9 +104,6 @@ static const AVFilterPad avfilter_vf_format_inputs[] = { · 103 unmodified lines | |||
| 104 | .name = "default", | 104 | .name = "default", |
| 105 | .type = AVMEDIA_TYPE_VIDEO, | 105 | .type = AVMEDIA_TYPE_VIDEO, |
| 106 | .get_video_buffer = ff_null_get_video_buffer, | 106 | .get_video_buffer = ff_null_get_video_buffer, |
| 107 | .start_frame = ff_null_start_frame, | ||
| 108 | .draw_slice = ff_null_draw_slice, | ||
| 109 | .end_frame = ff_null_end_frame, | ||
| 110 | }, | 107 | }, |
| 111 | { NULL } | 108 | { NULL } |
| 112 | }; | 109 | }; |
| @@ -146,9 +143,6 @@ static const AVFilterPad avfilter_vf_noformat_inputs[] = { · 33 unmodified lines | |||
| 146 | .name = "default", | 143 | .name = "default", |
| 147 | .type = AVMEDIA_TYPE_VIDEO, | 144 | .type = AVMEDIA_TYPE_VIDEO, |
| 148 | .get_video_buffer = ff_null_get_video_buffer, | 145 | .get_video_buffer = ff_null_get_video_buffer, |
| 149 | .start_frame = ff_null_start_frame, | ||
| 150 | .draw_slice = ff_null_draw_slice, | ||
| 151 | .end_frame = ff_null_end_frame, | ||
| 152 | }, | 146 | }, |
| 153 | { NULL } | 147 | { NULL } |
| 154 | }; | 148 | }; |
| @@ -144,9 +144,7 @@ static int request_frame(AVFilterLink *outlink) · 143 unmodified lines | |||
| 144 | buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, | 144 | buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, |
| 145 | outlink->time_base) + s->frames_out; | 145 | outlink->time_base) + s->frames_out; |
| 146 | 146 | ||
| 147 | if ((ret = ff_start_frame(outlink, buf)) < 0 || | 147 | if ((ret = ff_filter_frame(outlink, buf)) < 0) |
| 148 | (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || | ||
| 149 | (ret = ff_end_frame(outlink)) < 0) | ||
| 150 | return ret; | 148 | return ret; |
| 151 | 149 | ||
| 152 | s->frames_out++; | 150 | s->frames_out++; |
| @@ -171,16 +169,14 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFilterBufferRef *buf) · 18 unmodified lines | |||
| 171 | return 0; | 169 | return 0; |
| 172 | } | 170 | } |
| 173 | 171 | ||
| 174 | static int end_frame(AVFilterLink *inlink) | 172 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) |
| 175 | { | 173 | { |
| 176 | AVFilterContext *ctx = inlink->dst; | 174 | AVFilterContext *ctx = inlink->dst; |
| 177 | FPSContext *s = ctx->priv; | 175 | FPSContext *s = ctx->priv; |
| 178 | AVFilterLink *outlink = ctx->outputs[0]; | 176 | AVFilterLink *outlink = ctx->outputs[0]; |
| 179 | AVFilterBufferRef *buf = inlink->cur_buf; | ||
| 180 | int64_t delta; | 177 | int64_t delta; |
| 181 | int i, ret; | 178 | int i, ret; |
| 182 | 179 | ||
| 183 | inlink->cur_buf = NULL; | ||
| 184 | s->frames_in++; | 180 | s->frames_in++; |
| 185 | /* discard frames until we get the first timestamp */ | 181 | /* discard frames until we get the first timestamp */ |
| 186 | if (s->pts == AV_NOPTS_VALUE) { | 182 | if (s->pts == AV_NOPTS_VALUE) { |
| @@ -251,9 +247,7 @@ static int end_frame(AVFilterLink *inlink) · 64 unmodified lines | |||
| 251 | buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base, | 247 | buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base, |
| 252 | outlink->time_base) + s->frames_out; | 248 | outlink->time_base) + s->frames_out; |
| 253 | 249 | ||
| 254 | if ((ret = ff_start_frame(outlink, buf_out)) < 0 || | 250 | if ((ret = ff_filter_frame(outlink, buf_out)) < 0) { |
| 255 | (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || | ||
| 256 | (ret = ff_end_frame(outlink)) < 0) { | ||
| 257 | avfilter_unref_bufferp(&buf); | 251 | avfilter_unref_bufferp(&buf); |
| 258 | return ret; | 252 | return ret; |
| 259 | } | 253 | } |
| @@ -268,23 +262,11 @@ static int end_frame(AVFilterLink *inlink) · 8 unmodified lines | |||
| 268 | return ret; | 262 | return ret; |
| 269 | } | 263 | } |
| 270 | 264 | ||
| 271 | static int null_start_frame(AVFilterLink *link, AVFilterBufferRef *buf) | ||
| 272 | { | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 277 | { | ||
| 278 | return 0; | ||
| 279 | } | ||
| 280 | |||
| 281 | static const AVFilterPad avfilter_vf_fps_inputs[] = { | 265 | static const AVFilterPad avfilter_vf_fps_inputs[] = { |
| 282 | { | 266 | { |
| 283 | .name = "default", | 267 | .name = "default", |
| 284 | .type = AVMEDIA_TYPE_VIDEO, | 268 | .type = AVMEDIA_TYPE_VIDEO, |
| 285 | .start_frame = null_start_frame, | 269 | .filter_frame = filter_frame, |
| 286 | .draw_slice = null_draw_slice, | ||
| 287 | .end_frame = end_frame, | ||
| 288 | }, | 270 | }, |
| 289 | { NULL } | 271 | { NULL } |
| 290 | }; | 272 | }; |
| @@ -346,35 +346,34 @@ static int query_formats(AVFilterContext *ctx) · 345 unmodified lines | |||
| 346 | return 0; | 346 | return 0; |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | 349 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 350 | { | ||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int end_frame(AVFilterLink *inlink) | ||
| 355 | { | 350 | { |
| 356 | Frei0rContext *frei0r = inlink->dst->priv; | 351 | Frei0rContext *frei0r = inlink->dst->priv; |
| 357 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 352 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 358 | AVFilterBufferRef *inpicref = inlink->cur_buf; | 353 | AVFilterBufferRef *out; |
| 359 | AVFilterBufferRef *outpicref = outlink->out_buf; | 354 | |
| 360 | int ret; | 355 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 361 | 356 | if (!out) { | |
| 362 | frei0r->update(frei0r->instance, inpicref->pts * av_q2d(inlink->time_base) * 1000, | 357 | avfilter_unref_bufferp(&in); |
| 363 | (const uint32_t *)inpicref->data[0], | 358 | return AVERROR(ENOMEM); |
| 364 | (uint32_t *)outpicref->data[0]); | 359 | } |
| 365 | if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) || | 360 | avfilter_copy_buffer_ref_props(out, in); |
| 366 | (ret = ff_end_frame(outlink)) < 0) | 361 | |
| 367 | return ret; | 362 | frei0r->update(frei0r->instance, in->pts * av_q2d(inlink->time_base) * 1000, |
| 368 | return 0; | 363 | (const uint32_t *)in->data[0], |
| 364 | (uint32_t *)out->data[0]); | ||
| 365 | |||
| 366 | avfilter_unref_bufferp(&in); | ||
| 367 | |||
| 368 | return ff_filter_frame(outlink, out); | ||
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | static const AVFilterPad avfilter_vf_frei0r_inputs[] = { | 371 | static const AVFilterPad avfilter_vf_frei0r_inputs[] = { |
| 372 | { | 372 | { |
| 373 | .name = "default", | 373 | .name = "default", |
| 374 | .type = AVMEDIA_TYPE_VIDEO, | 374 | .type = AVMEDIA_TYPE_VIDEO, |
| 375 | .draw_slice = null_draw_slice, | ||
| 376 | .config_props = config_input_props, | 375 | .config_props = config_input_props, |
| 377 | .end_frame = end_frame, | 376 | .filter_frame = filter_frame, |
| 378 | .min_perms = AV_PERM_READ | 377 | .min_perms = AV_PERM_READ |
| 379 | }, | 378 | }, |
| 380 | { NULL } | 379 | { NULL } |
| @@ -456,8 +455,6 @@ static int source_request_frame(AVFilterLink *outlink) · 75 unmodified lines | |||
| 456 | { | 455 | { |
| 457 | Frei0rContext *frei0r = outlink->src->priv; | 456 | Frei0rContext *frei0r = outlink->src->priv; |
| 458 | AVFilterBufferRef *picref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | 457 | AVFilterBufferRef *picref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 459 | AVFilterBufferRef *buf_out; | ||
| 460 | int ret; | ||
| 461 | 458 | ||
| 462 | if (!picref) | 459 | if (!picref) |
| 463 | return AVERROR(ENOMEM); | 460 | return AVERROR(ENOMEM); |
| @@ -466,28 +463,10 @@ static int source_request_frame(AVFilterLink *outlink) · 2 unmodified lines | |||
| 466 | picref->pts = frei0r->pts++; | 463 | picref->pts = frei0r->pts++; |
| 467 | picref->pos = -1; | 464 | picref->pos = -1; |
| 468 | 465 | ||
| 469 | buf_out = avfilter_ref_buffer(picref, ~0); | ||
| 470 | if (!buf_out) { | ||
| 471 | ret = AVERROR(ENOMEM); | ||
| 472 | goto fail; | ||
| 473 | } | ||
| 474 | |||
| 475 | ret = ff_start_frame(outlink, buf_out); | ||
| 476 | if (ret < 0) | ||
| 477 | goto fail; | ||
| 478 | |||
| 479 | frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}), | 466 | frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}), |
| 480 | NULL, (uint32_t *)picref->data[0]); | 467 | NULL, (uint32_t *)picref->data[0]); |
| 481 | ret = ff_draw_slice(outlink, 0, outlink->h, 1); | ||
| 482 | if (ret < 0) | ||
| 483 | goto fail; | ||
| 484 | |||
| 485 | ret = ff_end_frame(outlink); | ||
| 486 | |||
| 487 | fail: | ||
| 488 | avfilter_unref_buffer(picref); | ||
| 489 | 468 | ||
| 490 | return ret; | 469 | return ff_filter_frame(outlink, picref); |
| 491 | } | 470 | } |
| 492 | 471 | ||
| 493 | static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = { | 472 | static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = { |
| @@ -182,20 +182,29 @@ static int config_input(AVFilterLink *inlink) · 181 unmodified lines | |||
| 182 | return 0; | 182 | return 0; |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | 185 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 186 | { | ||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int end_frame(AVFilterLink *inlink) | ||
| 191 | { | 186 | { |
| 192 | GradFunContext *gf = inlink->dst->priv; | 187 | GradFunContext *gf = inlink->dst->priv; |
| 193 | AVFilterBufferRef *inpic = inlink->cur_buf; | ||
| 194 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 188 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 195 | AVFilterBufferRef *outpic = outlink->out_buf; | 189 | AVFilterBufferRef *out; |
| 196 | int p, ret; | 190 | int p, direct; |
| 191 | |||
| 192 | if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) { | ||
| 193 | direct = 1; | ||
| 194 | out = in; | ||
| 195 | } else { | ||
| 196 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 197 | if (!out) { | ||
| 198 | avfilter_unref_bufferp(&in); | ||
| 199 | return AVERROR(ENOMEM); | ||
| 200 | } | ||
| 201 | |||
| 202 | avfilter_copy_buffer_ref_props(out, in); | ||
| 203 | out->video->w = outlink->w; | ||
| 204 | out->video->h = outlink->h; | ||
| 205 | } | ||
| 197 | 206 | ||
| 198 | for (p = 0; p < 4 && inpic->data[p]; p++) { | 207 | for (p = 0; p < 4 && in->data[p]; p++) { |
| 199 | int w = inlink->w; | 208 | int w = inlink->w; |
| 200 | int h = inlink->h; | 209 | int h = inlink->h; |
| 201 | int r = gf->radius; | 210 | int r = gf->radius; |
| @@ -206,15 +215,15 @@ static int end_frame(AVFilterLink *inlink) · 4 unmodified lines | |||
| 206 | } | 215 | } |
| 207 | 216 | ||
| 208 | if (FFMIN(w, h) > 2 * r) | 217 | if (FFMIN(w, h) > 2 * r) |
| 209 | filter(gf, outpic->data[p], inpic->data[p], w, h, outpic->linesize[p], inpic->linesize[p], r); | 218 | filter(gf, out->data[p], in->data[p], w, h, out->linesize[p], in->linesize[p], r); |
| 210 | else if (outpic->data[p] != inpic->data[p]) | 219 | else if (out->data[p] != in->data[p]) |
| 211 | av_image_copy_plane(outpic->data[p], outpic->linesize[p], inpic->data[p], inpic->linesize[p], w, h); | 220 | av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], w, h); |
| 212 | } | 221 | } |
| 213 | 222 | ||
| 214 | if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 || | 223 | if (!direct) |
| 215 | (ret = ff_end_frame(outlink)) < 0) | 224 | avfilter_unref_bufferp(&in); |
| 216 | return ret; | 225 | |
| 217 | return 0; | 226 | return ff_filter_frame(outlink, out); |
| 218 | } | 227 | } |
| 219 | 228 | ||
| 220 | static const AVFilterPad avfilter_vf_gradfun_inputs[] = { | 229 | static const AVFilterPad avfilter_vf_gradfun_inputs[] = { |
| @@ -222,9 +231,7 @@ static const AVFilterPad avfilter_vf_gradfun_inputs[] = { · 1 unmodified line | |||
| 222 | .name = "default", | 231 | .name = "default", |
| 223 | .type = AVMEDIA_TYPE_VIDEO, | 232 | .type = AVMEDIA_TYPE_VIDEO, |
| 224 | .config_props = config_input, | 233 | .config_props = config_input, |
| 225 | .start_frame = ff_inplace_start_frame, | 234 | .filter_frame = filter_frame, |
| 226 | .draw_slice = null_draw_slice, | ||
| 227 | .end_frame = end_frame, | ||
| 228 | .min_perms = AV_PERM_READ, | 235 | .min_perms = AV_PERM_READ, |
| 229 | }, | 236 | }, |
| 230 | { NULL } | 237 | { NULL } |
| @@ -84,22 +84,30 @@ static int config_props(AVFilterLink *inlink) · 83 unmodified lines | |||
| 84 | return 0; | 84 | return 0; |
| 85 | } | 85 | } |
| 86 | 86 | ||
| 87 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | 87 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 88 | { | 88 | { |
| 89 | FlipContext *flip = inlink->dst->priv; | 89 | AVFilterContext *ctx = inlink->dst; |
| 90 | AVFilterBufferRef *inpic = inlink->cur_buf; | 90 | FlipContext *flip = ctx->priv; |
| 91 | AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; | 91 | AVFilterLink *outlink = ctx->outputs[0]; |
| 92 | AVFilterBufferRef *out; | ||
| 92 | uint8_t *inrow, *outrow; | 93 | uint8_t *inrow, *outrow; |
| 93 | int i, j, plane, step, hsub, vsub; | 94 | int i, j, plane, step, hsub, vsub; |
| 94 | 95 | ||
| 95 | for (plane = 0; plane < 4 && inpic->data[plane]; plane++) { | 96 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 97 | if (!out) { | ||
| 98 | avfilter_unref_bufferp(&in); | ||
| 99 | return AVERROR(ENOMEM); | ||
| 100 | } | ||
| 101 | avfilter_copy_buffer_ref_props(out, in); | ||
| 102 | |||
| 103 | for (plane = 0; plane < 4 && in->data[plane]; plane++) { | ||
| 96 | step = flip->max_step[plane]; | 104 | step = flip->max_step[plane]; |
| 97 | hsub = (plane == 1 || plane == 2) ? flip->hsub : 0; | 105 | hsub = (plane == 1 || plane == 2) ? flip->hsub : 0; |
| 98 | vsub = (plane == 1 || plane == 2) ? flip->vsub : 0; | 106 | vsub = (plane == 1 || plane == 2) ? flip->vsub : 0; |
| 99 | 107 | ||
| 100 | outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane]; | 108 | outrow = out->data[plane]; |
| 101 | inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane] + ((inlink->w >> hsub) - 1) * step; | 109 | inrow = in ->data[plane] + ((inlink->w >> hsub) - 1) * step; |
| 102 | for (i = 0; i < h>>vsub; i++) { | 110 | for (i = 0; i < in->video->h >> vsub; i++) { |
| 103 | switch (step) { | 111 | switch (step) { |
| 104 | case 1: | 112 | case 1: |
| 105 | for (j = 0; j < (inlink->w >> hsub); j++) | 113 | for (j = 0; j < (inlink->w >> hsub); j++) |
| @@ -140,19 +148,20 @@ static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) · 34 unmodified lines | |||
| 140 | memcpy(outrow + j*step, inrow - j*step, step); | 148 | memcpy(outrow + j*step, inrow - j*step, step); |
| 141 | } | 149 | } |
| 142 | 150 | ||
| 143 | inrow += inpic ->linesize[plane]; | 151 | inrow += in ->linesize[plane]; |
| 144 | outrow += outpic->linesize[plane]; | 152 | outrow += out->linesize[plane]; |
| 145 | } | 153 | } |
| 146 | } | 154 | } |
| 147 | 155 | ||
| 148 | return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); | 156 | avfilter_unref_bufferp(&in); |
| 157 | return ff_filter_frame(outlink, out); | ||
| 149 | } | 158 | } |
| 150 | 159 | ||
| 151 | static const AVFilterPad avfilter_vf_hflip_inputs[] = { | 160 | static const AVFilterPad avfilter_vf_hflip_inputs[] = { |
| 152 | { | 161 | { |
| 153 | .name = "default", | 162 | .name = "default", |
| 154 | .type = AVMEDIA_TYPE_VIDEO, | 163 | .type = AVMEDIA_TYPE_VIDEO, |
| 155 | .draw_slice = draw_slice, | 164 | .filter_frame = filter_frame, |
| 156 | .config_props = config_props, | 165 | .config_props = config_props, |
| 157 | .min_perms = AV_PERM_READ, | 166 | .min_perms = AV_PERM_READ, |
| 158 | }, | 167 | }, |
| @@ -322,42 +322,49 @@ static int config_input(AVFilterLink *inlink) · 321 unmodified lines | |||
| 322 | return 0; | 322 | return 0; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | 325 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 326 | { | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int end_frame(AVFilterLink *inlink) | ||
| 331 | { | 326 | { |
| 332 | HQDN3DContext *hqdn3d = inlink->dst->priv; | 327 | HQDN3DContext *hqdn3d = inlink->dst->priv; |
| 333 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 328 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 334 | AVFilterBufferRef *inpic = inlink ->cur_buf; | 329 | AVFilterBufferRef *out; |
| 335 | AVFilterBufferRef *outpic = outlink->out_buf; | 330 | int direct, c; |
| 336 | int ret, c; | 331 | |
| 332 | if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) { | ||
| 333 | direct = 1; | ||
| 334 | out = in; | ||
| 335 | } else { | ||
| 336 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 337 | if (!out) { | ||
| 338 | avfilter_unref_bufferp(&in); | ||
| 339 | return AVERROR(ENOMEM); | ||
| 340 | } | ||
| 341 | |||
| 342 | avfilter_copy_buffer_ref_props(out, in); | ||
| 343 | out->video->w = outlink->w; | ||
| 344 | out->video->h = outlink->h; | ||
| 345 | } | ||
| 337 | 346 | ||
| 338 | for (c = 0; c < 3; c++) { | 347 | for (c = 0; c < 3; c++) { |
| 339 | denoise(hqdn3d, inpic->data[c], outpic->data[c], | 348 | denoise(hqdn3d, in->data[c], out->data[c], |
| 340 | hqdn3d->line, &hqdn3d->frame_prev[c], | 349 | hqdn3d->line, &hqdn3d->frame_prev[c], |
| 341 | inpic->video->w >> (!!c * hqdn3d->hsub), | 350 | in->video->w >> (!!c * hqdn3d->hsub), |
| 342 | inpic->video->h >> (!!c * hqdn3d->vsub), | 351 | in->video->h >> (!!c * hqdn3d->vsub), |
| 343 | inpic->linesize[c], outpic->linesize[c], | 352 | in->linesize[c], out->linesize[c], |
| 344 | hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]); | 353 | hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]); |
| 345 | } | 354 | } |
| 346 | 355 | ||
| 347 | if ((ret = ff_draw_slice(outlink, 0, inpic->video->h, 1)) < 0 || | 356 | if (!direct) |
| 348 | (ret = ff_end_frame(outlink)) < 0) | 357 | avfilter_unref_bufferp(&in); |
| 349 | return ret; | 358 | |
| 350 | return 0; | 359 | return ff_filter_frame(outlink, out); |
| 351 | } | 360 | } |
| 352 | 361 | ||
| 353 | static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = { | 362 | static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = { |
| 354 | { | 363 | { |
| 355 | .name = "default", | 364 | .name = "default", |
| 356 | .type = AVMEDIA_TYPE_VIDEO, | 365 | .type = AVMEDIA_TYPE_VIDEO, |
| 357 | .start_frame = ff_inplace_start_frame, | ||
| 358 | .draw_slice = null_draw_slice, | ||
| 359 | .config_props = config_input, | 366 | .config_props = config_input, |
| 360 | .end_frame = end_frame | 367 | .filter_frame = filter_frame, |
| 361 | }, | 368 | }, |
| 362 | { NULL } | 369 | { NULL } |
| 363 | }; | 370 | }; |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | #include "libavutil/file.h" | 32 | #include "libavutil/file.h" |
| 33 | #include "avfilter.h" | 33 | #include "avfilter.h" |
| 34 | #include "formats.h" | 34 | #include "formats.h" |
| 35 | #include "internal.h" | ||
| 35 | #include "video.h" | 36 | #include "video.h" |
| 36 | 37 | ||
| 37 | static void fill_iplimage_from_picref(IplImage *img, const AVFilterBufferRef *picref, enum AVPixelFormat pixfmt) | 38 | static void fill_iplimage_from_picref(IplImage *img, const AVFilterBufferRef *picref, enum AVPixelFormat pixfmt) |
| @@ -68,11 +69,6 @@ static int query_formats(AVFilterContext *ctx) · 30 unmodified lines | |||
| 68 | return 0; | 69 | return 0; |
| 69 | } | 70 | } |
| 70 | 71 | ||
| 71 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 72 | { | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | typedef struct { | 72 | typedef struct { |
| 77 | const char *name; | 73 | const char *name; |
| 78 | int (*init)(AVFilterContext *ctx, const char *args); | 74 | int (*init)(AVFilterContext *ctx, const char *args); |
| @@ -355,33 +351,36 @@ static av_cold void uninit(AVFilterContext *ctx) · 276 unmodified lines | |||
| 355 | memset(ocv, 0, sizeof(*ocv)); | 351 | memset(ocv, 0, sizeof(*ocv)); |
| 356 | } | 352 | } |
| 357 | 353 | ||
| 358 | static int end_frame(AVFilterLink *inlink) | 354 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 359 | { | 355 | { |
| 360 | AVFilterContext *ctx = inlink->dst; | 356 | AVFilterContext *ctx = inlink->dst; |
| 361 | OCVContext *ocv = ctx->priv; | 357 | OCVContext *ocv = ctx->priv; |
| 362 | AVFilterLink *outlink= inlink->dst->outputs[0]; | 358 | AVFilterLink *outlink= inlink->dst->outputs[0]; |
| 363 | AVFilterBufferRef *inpicref = inlink ->cur_buf; | 359 | AVFilterBufferRef *out; |
| 364 | AVFilterBufferRef *outpicref = outlink->out_buf; | ||
| 365 | IplImage inimg, outimg; | 360 | IplImage inimg, outimg; |
| 366 | int ret; | ||
| 367 | 361 | ||
| 368 | fill_iplimage_from_picref(&inimg , inpicref , inlink->format); | 362 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 369 | fill_iplimage_from_picref(&outimg, outpicref, inlink->format); | 363 | if (!out) { |
| 364 | avfilter_unref_bufferp(&in); | ||
| 365 | return AVERROR(ENOMEM); | ||
| 366 | } | ||
| 367 | avfilter_copy_buffer_ref_props(out, in); | ||
| 368 | |||
| 369 | fill_iplimage_from_picref(&inimg , in , inlink->format); | ||
| 370 | fill_iplimage_from_picref(&outimg, out, inlink->format); | ||
| 370 | ocv->end_frame_filter(ctx, &inimg, &outimg); | 371 | ocv->end_frame_filter(ctx, &inimg, &outimg); |
| 371 | fill_picref_from_iplimage(outpicref, &outimg, inlink->format); | 372 | fill_picref_from_iplimage(out, &outimg, inlink->format); |
| 372 | 373 | ||
| 373 | if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || | 374 | avfilter_unref_bufferp(&in); |
| 374 | (ret = ff_end_frame(outlink)) < 0) | 375 | |
| 375 | return ret; | 376 | return ff_filter_frame(outlink, out); |
| 376 | return 0; | ||
| 377 | } | 377 | } |
| 378 | 378 | ||
| 379 | static const AVFilterPad avfilter_vf_ocv_inputs[] = { | 379 | static const AVFilterPad avfilter_vf_ocv_inputs[] = { |
| 380 | { | 380 | { |
| 381 | .name = "default", | 381 | .name = "default", |
| 382 | .type = AVMEDIA_TYPE_VIDEO, | 382 | .type = AVMEDIA_TYPE_VIDEO, |
| 383 | .draw_slice = null_draw_slice, | 383 | .filter_frame = filter_frame, |
| 384 | .end_frame = end_frame, | ||
| 385 | .min_perms = AV_PERM_READ | 384 | .min_perms = AV_PERM_READ |
| 386 | }, | 385 | }, |
| 387 | { NULL } | 386 | { NULL } |
| @@ -295,22 +295,28 @@ static int config_props(AVFilterLink *inlink) · 294 unmodified lines | |||
| 295 | return 0; | 295 | return 0; |
| 296 | } | 296 | } |
| 297 | 297 | ||
| 298 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | 298 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 299 | { | 299 | { |
| 300 | AVFilterContext *ctx = inlink->dst; | 300 | AVFilterContext *ctx = inlink->dst; |
| 301 | LutContext *lut = ctx->priv; | 301 | LutContext *lut = ctx->priv; |
| 302 | AVFilterLink *outlink = ctx->outputs[0]; | 302 | AVFilterLink *outlink = ctx->outputs[0]; |
| 303 | AVFilterBufferRef *inpic = inlink ->cur_buf; | 303 | AVFilterBufferRef *out; |
| 304 | AVFilterBufferRef *outpic = outlink->out_buf; | ||
| 305 | uint8_t *inrow, *outrow, *inrow0, *outrow0; | 304 | uint8_t *inrow, *outrow, *inrow0, *outrow0; |
| 306 | int i, j, k, plane; | 305 | int i, j, k, plane; |
| 307 | 306 | ||
| 307 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 308 | if (!out) { | ||
| 309 | avfilter_unref_bufferp(&in); | ||
| 310 | return AVERROR(ENOMEM); | ||
| 311 | } | ||
| 312 | avfilter_copy_buffer_ref_props(out, in); | ||
| 313 | |||
| 308 | if (lut->is_rgb) { | 314 | if (lut->is_rgb) { |
| 309 | /* packed */ | 315 | /* packed */ |
| 310 | inrow0 = inpic ->data[0] + y * inpic ->linesize[0]; | 316 | inrow0 = in ->data[0]; |
| 311 | outrow0 = outpic->data[0] + y * outpic->linesize[0]; | 317 | outrow0 = out->data[0]; |
| 312 | 318 | ||
| 313 | for (i = 0; i < h; i ++) { | 319 | for (i = 0; i < in->video->h; i ++) { |
| 314 | inrow = inrow0; | 320 | inrow = inrow0; |
| 315 | outrow = outrow0; | 321 | outrow = outrow0; |
| 316 | for (j = 0; j < inlink->w; j++) { | 322 | for (j = 0; j < inlink->w; j++) { |
| @@ -319,34 +325,35 @@ static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) · 2 unmodified lines | |||
| 319 | outrow += lut->step; | 325 | outrow += lut->step; |
| 320 | inrow += lut->step; | 326 | inrow += lut->step; |
| 321 | } | 327 | } |
| 322 | inrow0 += inpic ->linesize[0]; | 328 | inrow0 += in ->linesize[0]; |
| 323 | outrow0 += outpic->linesize[0]; | 329 | outrow0 += out->linesize[0]; |
| 324 | } | 330 | } |
| 325 | } else { | 331 | } else { |
| 326 | /* planar */ | 332 | /* planar */ |
| 327 | for (plane = 0; plane < 4 && inpic->data[plane]; plane++) { | 333 | for (plane = 0; plane < 4 && in->data[plane]; plane++) { |
| 328 | int vsub = plane == 1 || plane == 2 ? lut->vsub : 0; | 334 | int vsub = plane == 1 || plane == 2 ? lut->vsub : 0; |
| 329 | int hsub = plane == 1 || plane == 2 ? lut->hsub : 0; | 335 | int hsub = plane == 1 || plane == 2 ? lut->hsub : 0; |
| 330 | 336 | ||
| 331 | inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane]; | 337 | inrow = in ->data[plane]; |
| 332 | outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane]; | 338 | outrow = out->data[plane]; |
| 333 | 339 | ||
| 334 | for (i = 0; i < h>>vsub; i ++) { | 340 | for (i = 0; i < in->video->h >> vsub; i ++) { |
| 335 | for (j = 0; j < inlink->w>>hsub; j++) | 341 | for (j = 0; j < inlink->w>>hsub; j++) |
| 336 | outrow[j] = lut->lut[plane][inrow[j]]; | 342 | outrow[j] = lut->lut[plane][inrow[j]]; |
| 337 | inrow += inpic ->linesize[plane]; | 343 | inrow += in ->linesize[plane]; |
| 338 | outrow += outpic->linesize[plane]; | 344 | outrow += out->linesize[plane]; |
| 339 | } | 345 | } |
| 340 | } | 346 | } |
| 341 | } | 347 | } |
| 342 | 348 | ||
| 343 | return ff_draw_slice(outlink, y, h, slice_dir); | 349 | avfilter_unref_bufferp(&in); |
| 350 | return ff_filter_frame(outlink, out); | ||
| 344 | } | 351 | } |
| 345 | 352 | ||
| 346 | static const AVFilterPad inputs[] = { | 353 | static const AVFilterPad inputs[] = { |
| 347 | { .name = "default", | 354 | { .name = "default", |
| 348 | .type = AVMEDIA_TYPE_VIDEO, | 355 | .type = AVMEDIA_TYPE_VIDEO, |
| 349 | .draw_slice = draw_slice, | 356 | .filter_frame = filter_frame, |
| 350 | .config_props = config_props, | 357 | .config_props = config_props, |
| 351 | .min_perms = AV_PERM_READ, }, | 358 | .min_perms = AV_PERM_READ, }, |
| 352 | { .name = NULL} | 359 | { .name = NULL} |
| @@ -31,8 +31,6 @@ static const AVFilterPad avfilter_vf_null_inputs[] = { · 30 unmodified lines | |||
| 31 | .name = "default", | 31 | .name = "default", |
| 32 | .type = AVMEDIA_TYPE_VIDEO, | 32 | .type = AVMEDIA_TYPE_VIDEO, |
| 33 | .get_video_buffer = ff_null_get_video_buffer, | 33 | .get_video_buffer = ff_null_get_video_buffer, |
| 34 | .start_frame = ff_null_start_frame, | ||
| 35 | .end_frame = ff_null_end_frame | ||
| 36 | }, | 34 | }, |
| 37 | { NULL } | 35 | { NULL } |
| 38 | }; | 36 | }; |
| @@ -269,34 +269,22 @@ static void blend_frame(AVFilterContext *ctx, · 268 unmodified lines | |||
| 269 | } | 269 | } |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | static int null_start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) | 272 | static int filter_frame_main(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 273 | { | ||
| 274 | return 0; | ||
| 275 | } | ||
| 276 | |||
| 277 | static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 278 | { | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | static int end_frame_main(AVFilterLink *inlink) | ||
| 283 | { | 273 | { |
| 284 | OverlayContext *s = inlink->dst->priv; | 274 | OverlayContext *s = inlink->dst->priv; |
| 285 | 275 | ||
| 286 | av_assert0(!s->main); | 276 | av_assert0(!s->main); |
| 287 | s->main = inlink->cur_buf; | 277 | s->main = frame; |
| 288 | inlink->cur_buf = NULL; | ||
| 289 | 278 | ||
| 290 | return 0; | 279 | return 0; |
| 291 | } | 280 | } |
| 292 | 281 | ||
| 293 | static int end_frame_overlay(AVFilterLink *inlink) | 282 | static int filter_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 294 | { | 283 | { |
| 295 | OverlayContext *s = inlink->dst->priv; | 284 | OverlayContext *s = inlink->dst->priv; |
| 296 | 285 | ||
| 297 | av_assert0(!s->over_next); | 286 | av_assert0(!s->over_next); |
| 298 | s->over_next = inlink->cur_buf; | 287 | s->over_next = frame; |
| 299 | inlink->cur_buf = NULL; | ||
| 300 | 288 | ||
| 301 | return 0; | 289 | return 0; |
| 302 | } | 290 | } |
| @@ -305,11 +293,7 @@ static int output_frame(AVFilterContext *ctx) · 2 unmodified lines | |||
| 305 | { | 293 | { |
| 306 | OverlayContext *s = ctx->priv; | 294 | OverlayContext *s = ctx->priv; |
| 307 | AVFilterLink *outlink = ctx->outputs[0]; | 295 | AVFilterLink *outlink = ctx->outputs[0]; |
| 308 | int ret = ff_start_frame(outlink, s->main); | 296 | int ret = ff_filter_frame(outlink, s->main); |
| 309 | if (ret >= 0) | ||
| 310 | ret = ff_draw_slice(outlink, 0, outlink->h, 1); | ||
| 311 | if (ret >= 0) | ||
| 312 | ret = ff_end_frame(outlink); | ||
| 313 | s->main = NULL; | 297 | s->main = NULL; |
| 314 | 298 | ||
| 315 | return ret; | 299 | return ret; |
| @@ -378,10 +362,8 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { · 62 unmodified lines | |||
| 378 | { | 362 | { |
| 379 | .name = "main", | 363 | .name = "main", |
| 380 | .type = AVMEDIA_TYPE_VIDEO, | 364 | .type = AVMEDIA_TYPE_VIDEO, |
| 381 | .start_frame = null_start_frame, | ||
| 382 | .config_props = config_input_main, | 365 | .config_props = config_input_main, |
| 383 | .draw_slice = null_draw_slice, | 366 | .filter_frame = filter_frame_main, |
| 384 | .end_frame = end_frame_main, | ||
| 385 | .min_perms = AV_PERM_READ, | 367 | .min_perms = AV_PERM_READ, |
| 386 | .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE, | 368 | .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE, |
| 387 | .needs_fifo = 1, | 369 | .needs_fifo = 1, |
| @@ -389,10 +371,8 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { · 1 unmodified line | |||
| 389 | { | 371 | { |
| 390 | .name = "overlay", | 372 | .name = "overlay", |
| 391 | .type = AVMEDIA_TYPE_VIDEO, | 373 | .type = AVMEDIA_TYPE_VIDEO, |
| 392 | .start_frame = null_start_frame, | ||
| 393 | .config_props = config_input_overlay, | 374 | .config_props = config_input_overlay, |
| 394 | .draw_slice = null_draw_slice, | 375 | .filter_frame = filter_frame_overlay, |
| 395 | .end_frame = end_frame_overlay, | ||
| 396 | .min_perms = AV_PERM_READ, | 376 | .min_perms = AV_PERM_READ, |
| 397 | .rej_perms = AV_PERM_REUSE2, | 377 | .rej_perms = AV_PERM_REUSE2, |
| 398 | .needs_fifo = 1, | 378 | .needs_fifo = 1, |
| @@ -106,7 +106,6 @@ typedef struct { · 105 unmodified lines | |||
| 106 | uint8_t *line[4]; | 106 | uint8_t *line[4]; |
| 107 | int line_step[4]; | 107 | int line_step[4]; |
| 108 | int hsub, vsub; ///< chroma subsampling values | 108 | int hsub, vsub; ///< chroma subsampling values |
| 109 | int needs_copy; | ||
| 110 | } PadContext; | 109 | } PadContext; |
| 111 | 110 | ||
| 112 | static av_cold int init(AVFilterContext *ctx, const char *args) | 111 | static av_cold int init(AVFilterContext *ctx, const char *args) |
| @@ -303,135 +302,85 @@ static int does_clip(PadContext *pad, AVFilterBufferRef *outpicref, int plane, i · 190 unmodified lines | |||
| 303 | return 0; | 302 | return 0; |
| 304 | } | 303 | } |
| 305 | 304 | ||
| 306 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) | 305 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 307 | { | 306 | { |
| 308 | PadContext *pad = inlink->dst->priv; | 307 | PadContext *pad = inlink->dst->priv; |
| 309 | AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); | 308 | AVFilterBufferRef *out = avfilter_ref_buffer(in, ~0); |
| 310 | AVFilterBufferRef *for_next_filter; | 309 | int plane, needs_copy; |
| 311 | int plane, ret = 0; | ||
| 312 | 310 | ||
| 313 | if (!outpicref) | 311 | if (!out) { |
| 312 | avfilter_unref_bufferp(&in); | ||
| 314 | return AVERROR(ENOMEM); | 313 | return AVERROR(ENOMEM); |
| 314 | } | ||
| 315 | 315 | ||
| 316 | for (plane = 0; plane < 4 && outpicref->data[plane]; plane++) { | 316 | for (plane = 0; plane < 4 && out->data[plane]; plane++) { |
| 317 | int hsub = (plane == 1 || plane == 2) ? pad->hsub : 0; | 317 | int hsub = (plane == 1 || plane == 2) ? pad->hsub : 0; |
| 318 | int vsub = (plane == 1 || plane == 2) ? pad->vsub : 0; | 318 | int vsub = (plane == 1 || plane == 2) ? pad->vsub : 0; |
| 319 | 319 | ||
| 320 | av_assert0(outpicref->buf->w>0 && outpicref->buf->h>0); | 320 | av_assert0(out->buf->w > 0 && out->buf->h > 0); |
| 321 | 321 | ||
| 322 | if(outpicref->format != outpicref->buf->format) //unsupported currently | 322 | if (out->format != out->buf->format) //unsupported currently |
| 323 | break; | 323 | break; |
| 324 | 324 | ||
| 325 | outpicref->data[plane] -= (pad->x >> hsub) * pad ->line_step[plane] | 325 | out->data[plane] -= (pad->x >> hsub) * pad->line_step[plane] + |
| 326 | + (pad->y >> vsub) * outpicref->linesize [plane]; | 326 | (pad->y >> vsub) * out->linesize [plane]; |
| 327 | 327 | ||
| 328 | if( does_clip(pad, outpicref, plane, hsub, vsub, 0, 0) | 328 | if (does_clip(pad, out, plane, hsub, vsub, 0, 0) || |
| 329 | || does_clip(pad, outpicref, plane, hsub, vsub, 0, pad->h-1) | 329 | does_clip(pad, out, plane, hsub, vsub, 0, pad->h - 1) || |
| 330 | || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, 0) | 330 | does_clip(pad, out, plane, hsub, vsub, pad->w - 1, 0) || |
| 331 | || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, pad->h-1) | 331 | does_clip(pad, out, plane, hsub, vsub, pad->w - 1, pad->h - 1)) |
| 332 | ) | ||
| 333 | break; | 332 | break; |
| 334 | } | 333 | } |
| 335 | pad->needs_copy= plane < 4 && outpicref->data[plane]; | 334 | needs_copy = plane < 4 && out->data[plane]; |
| 336 | if(pad->needs_copy){ | 335 | if (needs_copy) { |
| 337 | av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n"); | 336 | av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n"); |
| 338 | avfilter_unref_buffer(outpicref); | 337 | avfilter_unref_buffer(out); |
| 339 | outpicref = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES, | 338 | out = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES, |
| 340 | FFMAX(inlink->w, pad->w), | 339 | FFMAX(inlink->w, pad->w), |
| 341 | FFMAX(inlink->h, pad->h)); | 340 | FFMAX(inlink->h, pad->h)); |
| 342 | if (!outpicref) | 341 | if (!out) { |
| 342 | avfilter_unref_bufferp(&in); | ||
| 343 | return AVERROR(ENOMEM); | 343 | return AVERROR(ENOMEM); |
| 344 | } | ||
| 344 | 345 | ||
| 345 | avfilter_copy_buffer_ref_props(outpicref, inpicref); | 346 | avfilter_copy_buffer_ref_props(out, in); |
| 346 | } | ||
| 347 | |||
| 348 | outpicref->video->w = pad->w; | ||
| 349 | outpicref->video->h = pad->h; | ||
| 350 | |||
| 351 | for_next_filter = avfilter_ref_buffer(outpicref, ~0); | ||
| 352 | if (!for_next_filter) { | ||
| 353 | ret = AVERROR(ENOMEM); | ||
| 354 | goto fail; | ||
| 355 | } | 347 | } |
| 356 | 348 | ||
| 357 | ret = ff_start_frame(inlink->dst->outputs[0], for_next_filter); | 349 | out->video->w = pad->w; |
| 358 | if (ret < 0) | 350 | out->video->h = pad->h; |
| 359 | goto fail; | ||
| 360 | |||
| 361 | inlink->dst->outputs[0]->out_buf = outpicref; | ||
| 362 | return 0; | ||
| 363 | |||
| 364 | fail: | ||
| 365 | avfilter_unref_bufferp(&outpicref); | ||
| 366 | return ret; | ||
| 367 | } | ||
| 368 | |||
| 369 | static int end_frame(AVFilterLink *link) | ||
| 370 | { | ||
| 371 | return ff_end_frame(link->dst->outputs[0]); | ||
| 372 | } | ||
| 373 | 351 | ||
| 374 | static int draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, int before_slice) | 352 | /* top bar */ |
| 375 | { | 353 | if (pad->y) { |
| 376 | PadContext *pad = link->dst->priv; | 354 | ff_draw_rectangle(out->data, out->linesize, |
| 377 | int bar_y, bar_h = 0, ret = 0; | 355 | pad->line, pad->line_step, pad->hsub, pad->vsub, |
| 378 | 356 | 0, 0, pad->w, pad->y); | |
| 379 | if (slice_dir * before_slice == 1 && y == pad->y) { | ||
| 380 | /* top bar */ | ||
| 381 | bar_y = 0; | ||
| 382 | bar_h = pad->y; | ||
| 383 | } else if (slice_dir * before_slice == -1 && (y + h) == (pad->y + pad->in_h)) { | ||
| 384 | /* bottom bar */ | ||
| 385 | bar_y = pad->y + pad->in_h; | ||
| 386 | bar_h = pad->h - pad->in_h - pad->y; | ||
| 387 | } | 357 | } |
| 388 | 358 | ||
| 389 | if (bar_h) { | 359 | /* bottom bar */ |
| 390 | ff_draw_rectangle(link->dst->outputs[0]->out_buf->data, | 360 | if (pad->h > pad->y + pad->in_h) { |
| 391 | link->dst->outputs[0]->out_buf->linesize, | 361 | ff_draw_rectangle(out->data, out->linesize, |
| 392 | pad->line, pad->line_step, pad->hsub, pad->vsub, | 362 | pad->line, pad->line_step, pad->hsub, pad->vsub, |
| 393 | 0, bar_y, pad->w, bar_h); | 363 | 0, pad->y + pad->in_h, pad->w, pad->h - pad->y - pad->in_h); |
| 394 | ret = ff_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir); | ||
| 395 | } | 364 | } |
| 396 | return ret; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 400 | { | ||
| 401 | PadContext *pad = link->dst->priv; | ||
| 402 | AVFilterBufferRef *outpic = link->dst->outputs[0]->out_buf; | ||
| 403 | AVFilterBufferRef *inpic = link->cur_buf; | ||
| 404 | int ret; | ||
| 405 | |||
| 406 | y += pad->y; | ||
| 407 | |||
| 408 | y &= ~((1 << pad->vsub) - 1); | ||
| 409 | h &= ~((1 << pad->vsub) - 1); | ||
| 410 | |||
| 411 | if (!h) | ||
| 412 | return 0; | ||
| 413 | draw_send_bar_slice(link, y, h, slice_dir, 1); | ||
| 414 | 365 | ||
| 415 | /* left border */ | 366 | /* left border */ |
| 416 | ff_draw_rectangle(outpic->data, outpic->linesize, pad->line, pad->line_step, | 367 | ff_draw_rectangle(out->data, out->linesize, pad->line, pad->line_step, |
| 417 | pad->hsub, pad->vsub, 0, y, pad->x, h); | 368 | pad->hsub, pad->vsub, 0, pad->y, pad->x, in->video->h); |
| 418 | 369 | ||
| 419 | if(pad->needs_copy){ | 370 | if (needs_copy) { |
| 420 | ff_copy_rectangle(outpic->data, outpic->linesize, | 371 | ff_copy_rectangle(out->data, out->linesize, in->data, in->linesize, |
| 421 | inpic->data, inpic->linesize, pad->line_step, | 372 | pad->line_step, pad->hsub, pad->vsub, |
| 422 | pad->hsub, pad->vsub, | 373 | pad->x, pad->y, 0, in->video->w, in->video->h); |
| 423 | pad->x, y, y-pad->y, inpic->video->w, h); | ||
| 424 | } | 374 | } |
| 425 | 375 | ||
| 426 | /* right border */ | 376 | /* right border */ |
| 427 | ff_draw_rectangle(outpic->data, outpic->linesize, | 377 | ff_draw_rectangle(out->data, out->linesize, |
| 428 | pad->line, pad->line_step, pad->hsub, pad->vsub, | 378 | pad->line, pad->line_step, pad->hsub, pad->vsub, |
| 429 | pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h); | 379 | pad->x + pad->in_w, pad->y, pad->w - pad->x - pad->in_w, |
| 430 | ret = ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); | 380 | in->video->h); |
| 431 | if (ret < 0) | ||
| 432 | return ret; | ||
| 433 | 381 | ||
| 434 | return draw_send_bar_slice(link, y, h, slice_dir, -1); | 382 | avfilter_unref_bufferp(&in); |
| 383 | return ff_filter_frame(inlink->dst->outputs[0], out); | ||
| 435 | } | 384 | } |
| 436 | 385 | ||
| 437 | static const AVFilterPad avfilter_vf_pad_inputs[] = { | 386 | static const AVFilterPad avfilter_vf_pad_inputs[] = { |
| @@ -440,9 +389,7 @@ static const AVFilterPad avfilter_vf_pad_inputs[] = { · 2 unmodified lines | |||
| 440 | .type = AVMEDIA_TYPE_VIDEO, | 389 | .type = AVMEDIA_TYPE_VIDEO, |
| 441 | .config_props = config_input, | 390 | .config_props = config_input, |
| 442 | .get_video_buffer = get_video_buffer, | 391 | .get_video_buffer = get_video_buffer, |
| 443 | .start_frame = start_frame, | 392 | .filter_frame = filter_frame, |
| 444 | .draw_slice = draw_slice, | ||
| 445 | .end_frame = end_frame, | ||
| 446 | }, | 393 | }, |
| 447 | { NULL } | 394 | { NULL } |
| 448 | }; | 395 | }; |
| @@ -52,86 +52,65 @@ static int config_props(AVFilterLink *inlink) · 51 unmodified lines | |||
| 52 | return 0; | 52 | return 0; |
| 53 | } | 53 | } |
| 54 | 54 | ||
| 55 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | 55 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 56 | { | 56 | { |
| 57 | PixdescTestContext *priv = inlink->dst->priv; | 57 | PixdescTestContext *priv = inlink->dst->priv; |
| 58 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 58 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 59 | AVFilterBufferRef *outpicref, *for_next_filter; | 59 | AVFilterBufferRef *out; |
| 60 | int i, ret = 0; | 60 | int i, c, w = inlink->w, h = inlink->h; |
| 61 | 61 | ||
| 62 | outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, | 62 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, |
| 63 | outlink->w, outlink->h); | 63 | outlink->w, outlink->h); |
| 64 | if (!outpicref) | 64 | if (!out) { |
| 65 | avfilter_unref_bufferp(&in); | ||
| 65 | return AVERROR(ENOMEM); | 66 | return AVERROR(ENOMEM); |
| 67 | } | ||
| 66 | 68 | ||
| 67 | avfilter_copy_buffer_ref_props(outpicref, picref); | 69 | avfilter_copy_buffer_ref_props(out, in); |
| 68 | 70 | ||
| 69 | for (i = 0; i < 4; i++) { | 71 | for (i = 0; i < 4; i++) { |
| 70 | int h = outlink->h; | 72 | int h = outlink->h; |
| 71 | h = i == 1 || i == 2 ? h>>priv->pix_desc->log2_chroma_h : h; | 73 | h = i == 1 || i == 2 ? h>>priv->pix_desc->log2_chroma_h : h; |
| 72 | if (outpicref->data[i]) { | 74 | if (out->data[i]) { |
| 73 | uint8_t *data = outpicref->data[i] + | 75 | uint8_t *data = out->data[i] + |
| 74 | (outpicref->linesize[i] > 0 ? 0 : outpicref->linesize[i] * (h-1)); | 76 | (out->linesize[i] > 0 ? 0 : out->linesize[i] * (h-1)); |
| 75 | memset(data, 0, FFABS(outpicref->linesize[i]) * h); | 77 | memset(data, 0, FFABS(out->linesize[i]) * h); |
| 76 | } | 78 | } |
| 77 | } | 79 | } |
| 78 | 80 | ||
| 79 | /* copy palette */ | 81 | /* copy palette */ |
| 80 | if (priv->pix_desc->flags & PIX_FMT_PAL || | 82 | if (priv->pix_desc->flags & PIX_FMT_PAL || |
| 81 | priv->pix_desc->flags & PIX_FMT_PSEUDOPAL) | 83 | priv->pix_desc->flags & PIX_FMT_PSEUDOPAL) |
| 82 | memcpy(outpicref->data[1], outpicref->data[1], 256*4); | 84 | memcpy(out->data[1], in->data[1], 256*4); |
| 83 | |||
| 84 | for_next_filter = avfilter_ref_buffer(outpicref, ~0); | ||
| 85 | if (for_next_filter) | ||
| 86 | ret = ff_start_frame(outlink, for_next_filter); | ||
| 87 | else | ||
| 88 | ret = AVERROR(ENOMEM); | ||
| 89 | |||
| 90 | if (ret < 0) { | ||
| 91 | avfilter_unref_bufferp(&outpicref); | ||
| 92 | return ret; | ||
| 93 | } | ||
| 94 | |||
| 95 | outlink->out_buf = outpicref; | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 100 | { | ||
| 101 | PixdescTestContext *priv = inlink->dst->priv; | ||
| 102 | AVFilterBufferRef *inpic = inlink->cur_buf; | ||
| 103 | AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; | ||
| 104 | int i, c, w = inlink->w; | ||
| 105 | 85 | ||
| 106 | for (c = 0; c < priv->pix_desc->nb_components; c++) { | 86 | for (c = 0; c < priv->pix_desc->nb_components; c++) { |
| 107 | int w1 = c == 1 || c == 2 ? w>>priv->pix_desc->log2_chroma_w : w; | 87 | int w1 = c == 1 || c == 2 ? w>>priv->pix_desc->log2_chroma_w : w; |
| 108 | int h1 = c == 1 || c == 2 ? h>>priv->pix_desc->log2_chroma_h : h; | 88 | int h1 = c == 1 || c == 2 ? h>>priv->pix_desc->log2_chroma_h : h; |
| 109 | int y1 = c == 1 || c == 2 ? y>>priv->pix_desc->log2_chroma_h : y; | ||
| 110 | 89 | ||
| 111 | for (i = y1; i < y1 + h1; i++) { | 90 | for (i = 0; i < h1; i++) { |
| 112 | av_read_image_line(priv->line, | 91 | av_read_image_line(priv->line, |
| 113 | inpic->data, | 92 | in->data, |
| 114 | inpic->linesize, | 93 | in->linesize, |
| 115 | priv->pix_desc, | 94 | priv->pix_desc, |
| 116 | 0, i, c, w1, 0); | 95 | 0, i, c, w1, 0); |
| 117 | 96 | ||
| 118 | av_write_image_line(priv->line, | 97 | av_write_image_line(priv->line, |
| 119 | outpic->data, | 98 | out->data, |
| 120 | outpic->linesize, | 99 | out->linesize, |
| 121 | priv->pix_desc, | 100 | priv->pix_desc, |
| 122 | 0, i, c, w1); | 101 | 0, i, c, w1); |
| 123 | } | 102 | } |
| 124 | } | 103 | } |
| 125 | 104 | ||
| 126 | return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); | 105 | avfilter_unref_bufferp(&in); |
| 106 | return ff_filter_frame(outlink, out); | ||
| 127 | } | 107 | } |
| 128 | 108 | ||
| 129 | static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = { | 109 | static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = { |
| 130 | { | 110 | { |
| 131 | .name = "default", | 111 | .name = "default", |
| 132 | .type = AVMEDIA_TYPE_VIDEO, | 112 | .type = AVMEDIA_TYPE_VIDEO, |
| 133 | .start_frame = start_frame, | 113 | .filter_frame = filter_frame, |
| 134 | .draw_slice = draw_slice, | ||
| 135 | .config_props = config_props, | 114 | .config_props = config_props, |
| 136 | .min_perms = AV_PERM_READ, | 115 | .min_perms = AV_PERM_READ, |
| 137 | }, | 116 | }, |
| @@ -257,93 +257,46 @@ fail: · 256 unmodified lines | |||
| 257 | return ret; | 257 | return ret; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 260 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in) |
| 261 | { | 261 | { |
| 262 | ScaleContext *scale = link->dst->priv; | 262 | ScaleContext *scale = link->dst->priv; |
| 263 | AVFilterLink *outlink = link->dst->outputs[0]; | 263 | AVFilterLink *outlink = link->dst->outputs[0]; |
| 264 | AVFilterBufferRef *outpicref, *for_next_filter; | 264 | AVFilterBufferRef *out; |
| 265 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); | 265 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); |
| 266 | int ret = 0; | ||
| 267 | 266 | ||
| 268 | if (!scale->sws) { | 267 | if (!scale->sws) |
| 269 | outpicref = avfilter_ref_buffer(picref, ~0); | 268 | return ff_filter_frame(outlink, in); |
| 270 | if (!outpicref) | ||
| 271 | return AVERROR(ENOMEM); | ||
| 272 | return ff_start_frame(outlink, outpicref); | ||
| 273 | } | ||
| 274 | 269 | ||
| 275 | scale->hsub = desc->log2_chroma_w; | 270 | scale->hsub = desc->log2_chroma_w; |
| 276 | scale->vsub = desc->log2_chroma_h; | 271 | scale->vsub = desc->log2_chroma_h; |
| 277 | 272 | ||
| 278 | outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | 273 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 279 | if (!outpicref) | 274 | if (!out) { |
| 275 | avfilter_unref_bufferp(&in); | ||
| 280 | return AVERROR(ENOMEM); | 276 | return AVERROR(ENOMEM); |
| 281 | |||
| 282 | avfilter_copy_buffer_ref_props(outpicref, picref); | ||
| 283 | outpicref->video->w = outlink->w; | ||
| 284 | outpicref->video->h = outlink->h; | ||
| 285 | |||
| 286 | |||
| 287 | av_reduce(&outpicref->video->pixel_aspect.num, &outpicref->video->pixel_aspect.den, | ||
| 288 | (int64_t)picref->video->pixel_aspect.num * outlink->h * link->w, | ||
| 289 | (int64_t)picref->video->pixel_aspect.den * outlink->w * link->h, | ||
| 290 | INT_MAX); | ||
| 291 | |||
| 292 | scale->slice_y = 0; | ||
| 293 | for_next_filter = avfilter_ref_buffer(outpicref, ~0); | ||
| 294 | if (for_next_filter) | ||
| 295 | ret = ff_start_frame(outlink, for_next_filter); | ||
| 296 | else | ||
| 297 | ret = AVERROR(ENOMEM); | ||
| 298 | |||
| 299 | if (ret < 0) { | ||
| 300 | avfilter_unref_bufferp(&outpicref); | ||
| 301 | return ret; | ||
| 302 | } | 277 | } |
| 303 | 278 | ||
| 304 | outlink->out_buf = outpicref; | 279 | avfilter_copy_buffer_ref_props(out, in); |
| 305 | return 0; | 280 | out->video->w = outlink->w; |
| 306 | } | 281 | out->video->h = outlink->h; |
| 307 | 282 | ||
| 308 | static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | 283 | av_reduce(&out->video->pixel_aspect.num, &out->video->pixel_aspect.den, |
| 309 | { | 284 | (int64_t)in->video->pixel_aspect.num * outlink->h * link->w, |
| 310 | ScaleContext *scale = link->dst->priv; | 285 | (int64_t)in->video->pixel_aspect.den * outlink->w * link->h, |
| 311 | int out_h, ret; | 286 | INT_MAX); |
| 312 | AVFilterBufferRef *cur_pic = link->cur_buf; | ||
| 313 | const uint8_t *data[4]; | ||
| 314 | 287 | ||
| 315 | if (!scale->sws) { | 288 | sws_scale(scale->sws, in->data, in->linesize, 0, in->video->h, |
| 316 | return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); | 289 | out->data, out->linesize); |
| 317 | } | ||
| 318 | 290 | ||
| 319 | if (scale->slice_y == 0 && slice_dir == -1) | 291 | avfilter_unref_bufferp(&in); |
| 320 | scale->slice_y = link->dst->outputs[0]->h; | 292 | return ff_filter_frame(outlink, out); |
| 321 | |||
| 322 | data[0] = cur_pic->data[0] + y * cur_pic->linesize[0]; | ||
| 323 | data[1] = scale->input_is_pal ? | ||
| 324 | cur_pic->data[1] : | ||
| 325 | cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1]; | ||
| 326 | data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2]; | ||
| 327 | data[3] = cur_pic->data[3] + y * cur_pic->linesize[3]; | ||
| 328 | |||
| 329 | out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h, | ||
| 330 | link->dst->outputs[0]->out_buf->data, | ||
| 331 | link->dst->outputs[0]->out_buf->linesize); | ||
| 332 | |||
| 333 | if (slice_dir == -1) | ||
| 334 | scale->slice_y -= out_h; | ||
| 335 | ret = ff_draw_slice(link->dst->outputs[0], scale->slice_y, out_h, slice_dir); | ||
| 336 | if (slice_dir == 1) | ||
| 337 | scale->slice_y += out_h; | ||
| 338 | return ret; | ||
| 339 | } | 293 | } |
| 340 | 294 | ||
| 341 | static const AVFilterPad avfilter_vf_scale_inputs[] = { | 295 | static const AVFilterPad avfilter_vf_scale_inputs[] = { |
| 342 | { | 296 | { |
| 343 | .name = "default", | 297 | .name = "default", |
| 344 | .type = AVMEDIA_TYPE_VIDEO, | 298 | .type = AVMEDIA_TYPE_VIDEO, |
| 345 | .start_frame = start_frame, | 299 | .filter_frame = filter_frame, |
| 346 | .draw_slice = draw_slice, | ||
| 347 | .min_perms = AV_PERM_READ, | 300 | .min_perms = AV_PERM_READ, |
| 348 | }, | 301 | }, |
| 349 | { NULL } | 302 | { NULL } |
| @@ -228,50 +228,27 @@ static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref) · 227 unmodified lines | |||
| 228 | return res; | 228 | return res; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | 231 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 232 | { | 232 | { |
| 233 | SelectContext *select = inlink->dst->priv; | 233 | SelectContext *select = inlink->dst->priv; |
| 234 | 234 | ||
| 235 | select->select = select_frame(inlink->dst, picref); | 235 | select->select = select_frame(inlink->dst, frame); |
| 236 | if (select->select) { | 236 | if (select->select) { |
| 237 | AVFilterBufferRef *buf_out; | ||
| 238 | /* frame was requested through poll_frame */ | 237 | /* frame was requested through poll_frame */ |
| 239 | if (select->cache_frames) { | 238 | if (select->cache_frames) { |
| 240 | if (!av_fifo_space(select->pending_frames)) | 239 | if (!av_fifo_space(select->pending_frames)) { |
| 241 | av_log(inlink->dst, AV_LOG_ERROR, | 240 | av_log(inlink->dst, AV_LOG_ERROR, |
| 242 | "Buffering limit reached, cannot cache more frames\n"); | 241 | "Buffering limit reached, cannot cache more frames\n"); |
| 243 | else | 242 | avfilter_unref_bufferp(&frame); |
| 244 | av_fifo_generic_write(select->pending_frames, &picref, | 243 | } else |
| 245 | sizeof(picref), NULL); | 244 | av_fifo_generic_write(select->pending_frames, &frame, |
| 245 | sizeof(frame), NULL); | ||
| 246 | return 0; | 246 | return 0; |
| 247 | } | 247 | } |
| 248 | buf_out = avfilter_ref_buffer(picref, ~0); | 248 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 249 | if (!buf_out) | ||
| 250 | return AVERROR(ENOMEM); | ||
| 251 | return ff_start_frame(inlink->dst->outputs[0], buf_out); | ||
| 252 | } | 249 | } |
| 253 | 250 | ||
| 254 | return 0; | 251 | avfilter_unref_bufferp(&frame); |
| 255 | } | ||
| 256 | |||
| 257 | static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 258 | { | ||
| 259 | SelectContext *select = inlink->dst->priv; | ||
| 260 | |||
| 261 | if (select->select && !select->cache_frames) | ||
| 262 | return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); | ||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | |||
| 266 | static int end_frame(AVFilterLink *inlink) | ||
| 267 | { | ||
| 268 | SelectContext *select = inlink->dst->priv; | ||
| 269 | |||
| 270 | if (select->select) { | ||
| 271 | if (select->cache_frames) | ||
| 272 | return 0; | ||
| 273 | return ff_end_frame(inlink->dst->outputs[0]); | ||
| 274 | } | ||
| 275 | return 0; | 252 | return 0; |
| 276 | } | 253 | } |
| 277 | 254 | ||
| @@ -284,14 +261,9 @@ static int request_frame(AVFilterLink *outlink) · 6 unmodified lines | |||
| 284 | 261 | ||
| 285 | if (av_fifo_size(select->pending_frames)) { | 262 | if (av_fifo_size(select->pending_frames)) { |
| 286 | AVFilterBufferRef *picref; | 263 | AVFilterBufferRef *picref; |
| 287 | int ret; | ||
| 288 | 264 | ||
| 289 | av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL); | 265 | av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL); |
| 290 | if ((ret = ff_start_frame(outlink, picref)) < 0 || | 266 | return ff_filter_frame(outlink, picref); |
| 291 | (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || | ||
| 292 | (ret = ff_end_frame(outlink)) < 0); | ||
| 293 | |||
| 294 | return ret; | ||
| 295 | } | 267 | } |
| 296 | 268 | ||
| 297 | while (!select->select) { | 269 | while (!select->select) { |
| @@ -346,9 +318,7 @@ static const AVFilterPad avfilter_vf_select_inputs[] = { · 48 unmodified lines | |||
| 346 | .type = AVMEDIA_TYPE_VIDEO, | 318 | .type = AVMEDIA_TYPE_VIDEO, |
| 347 | .get_video_buffer = ff_null_get_video_buffer, | 319 | .get_video_buffer = ff_null_get_video_buffer, |
| 348 | .config_props = config_input, | 320 | .config_props = config_input, |
| 349 | .start_frame = start_frame, | 321 | .filter_frame = filter_frame, |
| 350 | .draw_slice = draw_slice, | ||
| 351 | .end_frame = end_frame | ||
| 352 | }, | 322 | }, |
| 353 | { NULL } | 323 | { NULL } |
| 354 | }; | 324 | }; |
| @@ -102,39 +102,36 @@ static int config_input(AVFilterLink *inlink) · 101 unmodified lines | |||
| 102 | #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) | 102 | #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) |
| 103 | #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) | 103 | #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) |
| 104 | 104 | ||
| 105 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) | 105 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 106 | { | 106 | { |
| 107 | SetPTSContext *setpts = inlink->dst->priv; | 107 | SetPTSContext *setpts = inlink->dst->priv; |
| 108 | int64_t in_pts = frame->pts; | ||
| 108 | double d; | 109 | double d; |
| 109 | AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); | ||
| 110 | |||
| 111 | if (!outpicref) | ||
| 112 | return AVERROR(ENOMEM); | ||
| 113 | 110 | ||
| 114 | if (isnan(setpts->var_values[VAR_STARTPTS])) | 111 | if (isnan(setpts->var_values[VAR_STARTPTS])) |
| 115 | setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts); | 112 | setpts->var_values[VAR_STARTPTS] = TS2D(frame->pts); |
| 116 | 113 | ||
| 117 | setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced; | 114 | setpts->var_values[VAR_INTERLACED] = frame->video->interlaced; |
| 118 | setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts); | 115 | setpts->var_values[VAR_PTS ] = TS2D(frame->pts); |
| 119 | setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos; | 116 | setpts->var_values[VAR_POS ] = frame->pos == -1 ? NAN : frame->pos; |
| 120 | 117 | ||
| 121 | d = av_expr_eval(setpts->expr, setpts->var_values, NULL); | 118 | d = av_expr_eval(setpts->expr, setpts->var_values, NULL); |
| 122 | outpicref->pts = D2TS(d); | 119 | frame->pts = D2TS(d); |
| 123 | 120 | ||
| 124 | #ifdef DEBUG | 121 | #ifdef DEBUG |
| 125 | av_log(inlink->dst, AV_LOG_DEBUG, | 122 | av_log(inlink->dst, AV_LOG_DEBUG, |
| 126 | "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", | 123 | "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", |
| 127 | (int64_t)setpts->var_values[VAR_N], | 124 | (int64_t)setpts->var_values[VAR_N], |
| 128 | (int)setpts->var_values[VAR_INTERLACED], | 125 | (int)setpts->var_values[VAR_INTERLACED], |
| 129 | inpicref ->pos, | 126 | frame->pos, in_pts, in_pts * av_q2d(inlink->time_base), |
| 130 | inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base), | 127 | frame->pts, frame->pts * av_q2d(inlink->time_base)); |
| 131 | outpicref->pts, outpicref->pts * av_q2d(inlink->time_base)); | ||
| 132 | #endif | 128 | #endif |
| 133 | 129 | ||
| 130 | |||
| 134 | setpts->var_values[VAR_N] += 1.0; | 131 | setpts->var_values[VAR_N] += 1.0; |
| 135 | setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts); | 132 | setpts->var_values[VAR_PREV_INPTS ] = TS2D(in_pts); |
| 136 | setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts); | 133 | setpts->var_values[VAR_PREV_OUTPTS] = TS2D(frame->pts); |
| 137 | return ff_start_frame(inlink->dst->outputs[0], outpicref); | 134 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 138 | } | 135 | } |
| 139 | 136 | ||
| 140 | static av_cold void uninit(AVFilterContext *ctx) | 137 | static av_cold void uninit(AVFilterContext *ctx) |
| @@ -150,7 +147,7 @@ static const AVFilterPad avfilter_vf_setpts_inputs[] = { · 9 unmodified lines | |||
| 150 | .type = AVMEDIA_TYPE_VIDEO, | 147 | .type = AVMEDIA_TYPE_VIDEO, |
| 151 | .get_video_buffer = ff_null_get_video_buffer, | 148 | .get_video_buffer = ff_null_get_video_buffer, |
| 152 | .config_props = config_input, | 149 | .config_props = config_input, |
| 153 | .start_frame = start_frame, | 150 | .filter_frame = filter_frame, |
| 154 | }, | 151 | }, |
| 155 | { NULL } | 152 | { NULL } |
| 156 | }; | 153 | }; |
| @@ -108,21 +108,20 @@ static int config_output_props(AVFilterLink *outlink) · 107 unmodified lines | |||
| 108 | return 0; | 108 | return 0; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | 111 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 112 | { | 112 | { |
| 113 | AVFilterContext *ctx = inlink->dst; | 113 | AVFilterContext *ctx = inlink->dst; |
| 114 | AVFilterLink *outlink = ctx->outputs[0]; | 114 | AVFilterLink *outlink = ctx->outputs[0]; |
| 115 | 115 | ||
| 116 | if (av_cmp_q(inlink->time_base, outlink->time_base)) { | 116 | if (av_cmp_q(inlink->time_base, outlink->time_base)) { |
| 117 | int64_t orig_pts = picref->pts; | 117 | int64_t orig_pts = frame->pts; |
| 118 | picref->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->time_base); | 118 | frame->pts = av_rescale_q(frame->pts, inlink->time_base, outlink->time_base); |
| 119 | av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", | 119 | av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", |
| 120 | inlink ->time_base.num, inlink ->time_base.den, orig_pts, | 120 | inlink ->time_base.num, inlink ->time_base.den, orig_pts, |
| 121 | outlink->time_base.num, outlink->time_base.den, picref->pts); | 121 | outlink->time_base.num, outlink->time_base.den, frame->pts); |
| 122 | } | 122 | } |
| 123 | inlink->cur_buf = NULL; | ||
| 124 | 123 | ||
| 125 | return ff_start_frame(outlink, picref); | 124 | return ff_filter_frame(outlink, frame); |
| 126 | } | 125 | } |
| 127 | 126 | ||
| 128 | static const AVFilterPad avfilter_vf_settb_inputs[] = { | 127 | static const AVFilterPad avfilter_vf_settb_inputs[] = { |
| @@ -130,8 +129,7 @@ static const AVFilterPad avfilter_vf_settb_inputs[] = { · 1 unmodified line | |||
| 130 | .name = "default", | 129 | .name = "default", |
| 131 | .type = AVMEDIA_TYPE_VIDEO, | 130 | .type = AVMEDIA_TYPE_VIDEO, |
| 132 | .get_video_buffer = ff_null_get_video_buffer, | 131 | .get_video_buffer = ff_null_get_video_buffer, |
| 133 | .start_frame = start_frame, | 132 | .filter_frame = filter_frame, |
| 134 | .end_frame = ff_null_end_frame | ||
| 135 | }, | 133 | }, |
| 136 | { NULL } | 134 | { NULL } |
| 137 | }; | 135 | }; |
| @@ -41,24 +41,23 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 40 unmodified lines | |||
| 41 | return 0; | 41 | return 0; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static int end_frame(AVFilterLink *inlink) | 44 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) |
| 45 | { | 45 | { |
| 46 | AVFilterContext *ctx = inlink->dst; | 46 | AVFilterContext *ctx = inlink->dst; |
| 47 | ShowInfoContext *showinfo = ctx->priv; | 47 | ShowInfoContext *showinfo = ctx->priv; |
| 48 | AVFilterBufferRef *picref = inlink->cur_buf; | ||
| 49 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); | 48 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); |
| 50 | uint32_t plane_checksum[4] = {0}, checksum = 0; | 49 | uint32_t plane_checksum[4] = {0}, checksum = 0; |
| 51 | int i, plane, vsub = desc->log2_chroma_h; | 50 | int i, plane, vsub = desc->log2_chroma_h; |
| 52 | 51 | ||
| 53 | for (plane = 0; picref->data[plane] && plane < 4; plane++) { | 52 | for (plane = 0; frame->data[plane] && plane < 4; plane++) { |
| 54 | size_t linesize = av_image_get_linesize(picref->format, picref->video->w, plane); | 53 | size_t linesize = av_image_get_linesize(frame->format, frame->video->w, plane); |
| 55 | uint8_t *data = picref->data[plane]; | 54 | uint8_t *data = frame->data[plane]; |
| 56 | int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h; | 55 | int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h; |
| 57 | 56 | ||
| 58 | for (i = 0; i < h; i++) { | 57 | for (i = 0; i < h; i++) { |
| 59 | plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); | 58 | plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); |
| 60 | checksum = av_adler32_update(checksum, data, linesize); | 59 | checksum = av_adler32_update(checksum, data, linesize); |
| 61 | data += picref->linesize[plane]; | 60 | data += frame->linesize[plane]; |
| 62 | } | 61 | } |
| 63 | } | 62 | } |
| 64 | 63 | ||
| @@ -67,18 +66,18 @@ static int end_frame(AVFilterLink *inlink) · 2 unmodified lines | |||
| 67 | "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " | 66 | "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " |
| 68 | "checksum:%u plane_checksum:[%u %u %u %u]\n", | 67 | "checksum:%u plane_checksum:[%u %u %u %u]\n", |
| 69 | showinfo->frame, | 68 | showinfo->frame, |
| 70 | picref->pts, picref->pts * av_q2d(inlink->time_base), picref->pos, | 69 | frame->pts, frame->pts * av_q2d(inlink->time_base), frame->pos, |
| 71 | desc->name, | 70 | desc->name, |
| 72 | picref->video->pixel_aspect.num, picref->video->pixel_aspect.den, | 71 | frame->video->pixel_aspect.num, frame->video->pixel_aspect.den, |
| 73 | picref->video->w, picref->video->h, | 72 | frame->video->w, frame->video->h, |
| 74 | !picref->video->interlaced ? 'P' : /* Progressive */ | 73 | !frame->video->interlaced ? 'P' : /* Progressive */ |
| 75 | picref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ | 74 | frame->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ |
| 76 | picref->video->key_frame, | 75 | frame->video->key_frame, |
| 77 | av_get_picture_type_char(picref->video->pict_type), | 76 | av_get_picture_type_char(frame->video->pict_type), |
| 78 | checksum, plane_checksum[0], plane_checksum[1], plane_checksum[2], plane_checksum[3]); | 77 | checksum, plane_checksum[0], plane_checksum[1], plane_checksum[2], plane_checksum[3]); |
| 79 | 78 | ||
| 80 | showinfo->frame++; | 79 | showinfo->frame++; |
| 81 | return ff_end_frame(inlink->dst->outputs[0]); | 80 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 82 | } | 81 | } |
| 83 | 82 | ||
| 84 | static const AVFilterPad avfilter_vf_showinfo_inputs[] = { | 83 | static const AVFilterPad avfilter_vf_showinfo_inputs[] = { |
| @@ -86,8 +85,7 @@ static const AVFilterPad avfilter_vf_showinfo_inputs[] = { · 1 unmodified line | |||
| 86 | .name = "default", | 85 | .name = "default", |
| 87 | .type = AVMEDIA_TYPE_VIDEO, | 86 | .type = AVMEDIA_TYPE_VIDEO, |
| 88 | .get_video_buffer = ff_null_get_video_buffer, | 87 | .get_video_buffer = ff_null_get_video_buffer, |
| 89 | .start_frame = ff_null_start_frame, | 88 | .filter_frame = filter_frame, |
| 90 | .end_frame = end_frame, | ||
| 91 | .min_perms = AV_PERM_READ, | 89 | .min_perms = AV_PERM_READ, |
| 92 | }, | 90 | }, |
| 93 | { NULL } | 91 | { NULL } |
| @@ -121,100 +121,88 @@ static int config_props_output(AVFilterLink *outlink) · 120 unmodified lines | |||
| 121 | return 0; | 121 | return 0; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | 124 | static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) |
| 125 | { | 125 | { |
| 126 | AVFilterLink *outlink = inlink->dst->outputs[0]; | 126 | AVFilterLink *outlink = inlink->dst->outputs[0]; |
| 127 | AVFilterBufferRef *buf_out; | 127 | TransContext *trans = inlink->dst->priv; |
| 128 | AVFilterBufferRef *out; | ||
| 129 | int plane; | ||
| 128 | 130 | ||
| 129 | outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, | 131 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); |
| 130 | outlink->w, outlink->h); | 132 | if (!out) { |
| 131 | if (!outlink->out_buf) | 133 | avfilter_unref_bufferp(&in); |
| 132 | return AVERROR(ENOMEM); | 134 | return AVERROR(ENOMEM); |
| 135 | } | ||
| 133 | 136 | ||
| 134 | outlink->out_buf->pts = picref->pts; | 137 | out->pts = in->pts; |
| 135 | 138 | ||
| 136 | if (picref->video->pixel_aspect.num == 0) { | 139 | if (in->video->pixel_aspect.num == 0) { |
| 137 | outlink->out_buf->video->pixel_aspect = picref->video->pixel_aspect; | 140 | out->video->pixel_aspect = in->video->pixel_aspect; |
| 138 | } else { | 141 | } else { |
| 139 | outlink->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den; | 142 | out->video->pixel_aspect.num = in->video->pixel_aspect.den; |
| 140 | outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num; | 143 | out->video->pixel_aspect.den = in->video->pixel_aspect.num; |
| 141 | } | 144 | } |
| 142 | 145 | ||
| 143 | buf_out = avfilter_ref_buffer(outlink->out_buf, ~0); | 146 | for (plane = 0; out->data[plane]; plane++) { |
| 144 | if (!buf_out) | ||
| 145 | return AVERROR(ENOMEM); | ||
| 146 | return ff_start_frame(outlink, buf_out); | ||
| 147 | } | ||
| 148 | |||
| 149 | static int end_frame(AVFilterLink *inlink) | ||
| 150 | { | ||
| 151 | TransContext *trans = inlink->dst->priv; | ||
| 152 | AVFilterBufferRef *inpic = inlink->cur_buf; | ||
| 153 | AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; | ||
| 154 | AVFilterLink *outlink = inlink->dst->outputs[0]; | ||
| 155 | int plane, ret; | ||
| 156 | |||
| 157 | for (plane = 0; outpic->data[plane]; plane++) { | ||
| 158 | int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; | 147 | int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; |
| 159 | int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; | 148 | int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; |
| 160 | int pixstep = trans->pixsteps[plane]; | 149 | int pixstep = trans->pixsteps[plane]; |
| 161 | int inh = inpic->video->h>>vsub; | 150 | int inh = in->video->h>>vsub; |
| 162 | int outw = outpic->video->w>>hsub; | 151 | int outw = out->video->w>>hsub; |
| 163 | int outh = outpic->video->h>>vsub; | 152 | int outh = out->video->h>>vsub; |
| 164 | uint8_t *out, *in; | 153 | uint8_t *dst, *src; |
| 165 | int outlinesize, inlinesize; | 154 | int dstlinesize, srclinesize; |
| 166 | int x, y; | 155 | int x, y; |
| 167 | 156 | ||
| 168 | out = outpic->data[plane]; outlinesize = outpic->linesize[plane]; | 157 | dst = out->data[plane]; |
| 169 | in = inpic ->data[plane]; inlinesize = inpic ->linesize[plane]; | 158 | dstlinesize = out->linesize[plane]; |
| 159 | src = in->data[plane]; | ||
| 160 | srclinesize = in->linesize[plane]; | ||
| 170 | 161 | ||
| 171 | if (trans->dir&1) { | 162 | if (trans->dir&1) { |
| 172 | in += inpic->linesize[plane] * (inh-1); | 163 | src += in->linesize[plane] * (inh-1); |
| 173 | inlinesize *= -1; | 164 | srclinesize *= -1; |
| 174 | } | 165 | } |
| 175 | 166 | ||
| 176 | if (trans->dir&2) { | 167 | if (trans->dir&2) { |
| 177 | out += outpic->linesize[plane] * (outh-1); | 168 | dst += out->linesize[plane] * (outh-1); |
| 178 | outlinesize *= -1; | 169 | dstlinesize *= -1; |
| 179 | } | 170 | } |
| 180 | 171 | ||
| 181 | for (y = 0; y < outh; y++) { | 172 | for (y = 0; y < outh; y++) { |
| 182 | switch (pixstep) { | 173 | switch (pixstep) { |
| 183 | case 1: | 174 | case 1: |
| 184 | for (x = 0; x < outw; x++) | 175 | for (x = 0; x < outw; x++) |
| 185 | out[x] = in[x*inlinesize + y]; | 176 | dst[x] = src[x*srclinesize + y]; |
| 186 | break; | 177 | break; |
| 187 | case 2: | 178 | case 2: |
| 188 | for (x = 0; x < outw; x++) | 179 | for (x = 0; x < outw; x++) |
| 189 | *((uint16_t *)(out + 2*x)) = *((uint16_t *)(in + x*inlinesize + y*2)); | 180 | *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2)); |
| 190 | break; | 181 | break; |
| 191 | case 3: | 182 | case 3: |
| 192 | for (x = 0; x < outw; x++) { | 183 | for (x = 0; x < outw; x++) { |
| 193 | int32_t v = AV_RB24(in + x*inlinesize + y*3); | 184 | int32_t v = AV_RB24(src + x*srclinesize + y*3); |
| 194 | AV_WB24(out + 3*x, v); | 185 | AV_WB24(dst + 3*x, v); |
| 195 | } | 186 | } |
| 196 | break; | 187 | break; |
| 197 | case 4: | 188 | case 4: |
| 198 | for (x = 0; x < outw; x++) | 189 | for (x = 0; x < outw; x++) |
| 199 | *((uint32_t *)(out + 4*x)) = *((uint32_t *)(in + x*inlinesize + y*4)); | 190 | *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4)); |
| 200 | break; | 191 | break; |
| 201 | } | 192 | } |
| 202 | out += outlinesize; | 193 | dst += dstlinesize; |
| 203 | } | 194 | } |
| 204 | } | 195 | } |
| 205 | 196 | ||
| 206 | if ((ret = ff_draw_slice(outlink, 0, outpic->video->h, 1)) < 0 || | 197 | avfilter_unref_bufferp(&in); |
| 207 | (ret = ff_end_frame(outlink)) < 0) | 198 | return ff_filter_frame(outlink, out); |
| 208 | return ret; | ||
| 209 | return 0; | ||
| 210 | } | 199 | } |
| 211 | 200 | ||
| 212 | static const AVFilterPad avfilter_vf_transpose_inputs[] = { | 201 | static const AVFilterPad avfilter_vf_transpose_inputs[] = { |
| 213 | { | 202 | { |
| 214 | .name = "default", | 203 | .name = "default", |
| 215 | .type = AVMEDIA_TYPE_VIDEO, | 204 | .type = AVMEDIA_TYPE_VIDEO, |
| 216 | .start_frame = start_frame, | 205 | .filter_frame = filter_frame, |
| 217 | .end_frame = end_frame, | ||
| 218 | .min_perms = AV_PERM_READ, | 206 | .min_perms = AV_PERM_READ, |
| 219 | }, | 207 | }, |
| 220 | { NULL } | 208 | { NULL } |
| @@ -214,36 +214,34 @@ static av_cold void uninit(AVFilterContext *ctx) · 213 unmodified lines | |||
| 214 | free_filter_param(&unsharp->chroma); | 214 | free_filter_param(&unsharp->chroma); |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static int end_frame(AVFilterLink *link) | 217 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in) |
| 218 | { | 218 | { |
| 219 | UnsharpContext *unsharp = link->dst->priv; | 219 | UnsharpContext *unsharp = link->dst->priv; |
| 220 | AVFilterBufferRef *in = link->cur_buf; | 220 | AVFilterLink *outlink = link->dst->outputs[0]; |
| 221 | AVFilterBufferRef *out = link->dst->outputs[0]->out_buf; | 221 | AVFilterBufferRef *out; |
| 222 | int cw = SHIFTUP(link->w, unsharp->hsub); | 222 | int cw = SHIFTUP(link->w, unsharp->hsub); |
| 223 | int ch = SHIFTUP(link->h, unsharp->vsub); | 223 | int ch = SHIFTUP(link->h, unsharp->vsub); |
| 224 | int ret; | 224 | |
| 225 | out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 226 | if (!out) { | ||
| 227 | avfilter_unref_bufferp(&in); | ||
| 228 | return AVERROR(ENOMEM); | ||
| 229 | } | ||
| 230 | avfilter_copy_buffer_ref_props(out, in); | ||
| 225 | 231 | ||
| 226 | apply_unsharp(out->data[0], out->linesize[0], in->data[0], in->linesize[0], link->w, link->h, &unsharp->luma); | 232 | apply_unsharp(out->data[0], out->linesize[0], in->data[0], in->linesize[0], link->w, link->h, &unsharp->luma); |
| 227 | apply_unsharp(out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, &unsharp->chroma); | 233 | apply_unsharp(out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, &unsharp->chroma); |
| 228 | apply_unsharp(out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, &unsharp->chroma); | 234 | apply_unsharp(out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, &unsharp->chroma); |
| 229 | 235 | ||
| 230 | if ((ret = ff_draw_slice(link->dst->outputs[0], 0, link->h, 1)) < 0 || | 236 | avfilter_unref_bufferp(&in); |
| 231 | (ret = ff_end_frame(link->dst->outputs[0])) < 0) | 237 | return ff_filter_frame(outlink, out); |
| 232 | return ret; | ||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 237 | { | ||
| 238 | return 0; | ||
| 239 | } | 238 | } |
| 240 | 239 | ||
| 241 | static const AVFilterPad avfilter_vf_unsharp_inputs[] = { | 240 | static const AVFilterPad avfilter_vf_unsharp_inputs[] = { |
| 242 | { | 241 | { |
| 243 | .name = "default", | 242 | .name = "default", |
| 244 | .type = AVMEDIA_TYPE_VIDEO, | 243 | .type = AVMEDIA_TYPE_VIDEO, |
| 245 | .draw_slice = draw_slice, | 244 | .filter_frame = filter_frame, |
| 246 | .end_frame = end_frame, | ||
| 247 | .config_props = config_props, | 245 | .config_props = config_props, |
| 248 | .min_perms = AV_PERM_READ, | 246 | .min_perms = AV_PERM_READ, |
| 249 | }, | 247 | }, |
| @@ -69,41 +69,28 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, · 68 unmodified lines | |||
| 69 | return picref; | 69 | return picref; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref) | 72 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) |
| 73 | { | 73 | { |
| 74 | FlipContext *flip = link->dst->priv; | 74 | FlipContext *flip = link->dst->priv; |
| 75 | AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); | ||
| 76 | int i; | 75 | int i; |
| 77 | 76 | ||
| 78 | if (!outpicref) | ||
| 79 | return AVERROR(ENOMEM); | ||
| 80 | |||
| 81 | for (i = 0; i < 4; i ++) { | 77 | for (i = 0; i < 4; i ++) { |
| 82 | int vsub = i == 1 || i == 2 ? flip->vsub : 0; | 78 | int vsub = i == 1 || i == 2 ? flip->vsub : 0; |
| 83 | 79 | ||
| 84 | if (outpicref->data[i]) { | 80 | if (frame->data[i]) { |
| 85 | outpicref->data[i] += ((link->h >> vsub)-1) * outpicref->linesize[i]; | 81 | frame->data[i] += ((link->h >> vsub)-1) * frame->linesize[i]; |
| 86 | outpicref->linesize[i] = -outpicref->linesize[i]; | 82 | frame->linesize[i] = -frame->linesize[i]; |
| 87 | } | 83 | } |
| 88 | } | 84 | } |
| 89 | 85 | ||
| 90 | return ff_start_frame(link->dst->outputs[0], outpicref); | 86 | return ff_filter_frame(link->dst->outputs[0], frame); |
| 91 | } | ||
| 92 | |||
| 93 | static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 94 | { | ||
| 95 | AVFilterContext *ctx = link->dst; | ||
| 96 | |||
| 97 | return ff_draw_slice(ctx->outputs[0], link->h - (y+h), h, -1 * slice_dir); | ||
| 98 | } | 87 | } |
| 99 | |||
| 100 | static const AVFilterPad avfilter_vf_vflip_inputs[] = { | 88 | static const AVFilterPad avfilter_vf_vflip_inputs[] = { |
| 101 | { | 89 | { |
| 102 | .name = "default", | 90 | .name = "default", |
| 103 | .type = AVMEDIA_TYPE_VIDEO, | 91 | .type = AVMEDIA_TYPE_VIDEO, |
| 104 | .get_video_buffer = get_video_buffer, | 92 | .get_video_buffer = get_video_buffer, |
| 105 | .start_frame = start_frame, | 93 | .filter_frame = filter_frame, |
| 106 | .draw_slice = draw_slice, | ||
| 107 | .config_props = config_input, | 94 | .config_props = config_input, |
| 108 | }, | 95 | }, |
| 109 | { NULL } | 96 | { NULL } |
| @@ -202,19 +202,14 @@ static int return_frame(AVFilterContext *ctx, int is_second) · 201 unmodified lines | |||
| 202 | } else { | 202 | } else { |
| 203 | yadif->out->pts = AV_NOPTS_VALUE; | 203 | yadif->out->pts = AV_NOPTS_VALUE; |
| 204 | } | 204 | } |
| 205 | ret = ff_start_frame(ctx->outputs[0], yadif->out); | ||
| 206 | if (ret < 0) | ||
| 207 | return ret; | ||
| 208 | } | 205 | } |
| 209 | if ((ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1)) < 0 || | 206 | ret = ff_filter_frame(ctx->outputs[0], yadif->out); |
| 210 | (ret = ff_end_frame(ctx->outputs[0])) < 0) | ||
| 211 | return ret; | ||
| 212 | 207 | ||
| 213 | yadif->frame_pending = (yadif->mode&1) && !is_second; | 208 | yadif->frame_pending = (yadif->mode&1) && !is_second; |
| 214 | return 0; | 209 | return ret; |
| 215 | } | 210 | } |
| 216 | 211 | ||
| 217 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 212 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *picref) |
| 218 | { | 213 | { |
| 219 | AVFilterContext *ctx = link->dst; | 214 | AVFilterContext *ctx = link->dst; |
| 220 | YADIFContext *yadif = ctx->priv; | 215 | YADIFContext *yadif = ctx->priv; |
| @@ -227,7 +222,6 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 6 unmodified lines | |||
| 227 | yadif->prev = yadif->cur; | 222 | yadif->prev = yadif->cur; |
| 228 | yadif->cur = yadif->next; | 223 | yadif->cur = yadif->next; |
| 229 | yadif->next = picref; | 224 | yadif->next = picref; |
| 230 | link->cur_buf = NULL; | ||
| 231 | 225 | ||
| 232 | if (!yadif->cur) | 226 | if (!yadif->cur) |
| 233 | return 0; | 227 | return 0; |
| @@ -240,7 +234,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 6 unmodified lines | |||
| 240 | avfilter_unref_bufferp(&yadif->prev); | 234 | avfilter_unref_bufferp(&yadif->prev); |
| 241 | if (yadif->out->pts != AV_NOPTS_VALUE) | 235 | if (yadif->out->pts != AV_NOPTS_VALUE) |
| 242 | yadif->out->pts *= 2; | 236 | yadif->out->pts *= 2; |
| 243 | return ff_start_frame(ctx->outputs[0], yadif->out); | 237 | return ff_filter_frame(ctx->outputs[0], yadif->out); |
| 244 | } | 238 | } |
| 245 | 239 | ||
| 246 | if (!yadif->prev && | 240 | if (!yadif->prev && |
| @@ -258,26 +252,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 11 unmodified lines | |||
| 258 | if (yadif->out->pts != AV_NOPTS_VALUE) | 252 | if (yadif->out->pts != AV_NOPTS_VALUE) |
| 259 | yadif->out->pts *= 2; | 253 | yadif->out->pts *= 2; |
| 260 | 254 | ||
| 261 | return ff_start_frame(ctx->outputs[0], yadif->out); | 255 | return return_frame(ctx, 0); |
| 262 | } | ||
| 263 | |||
| 264 | static int end_frame(AVFilterLink *link) | ||
| 265 | { | ||
| 266 | AVFilterContext *ctx = link->dst; | ||
| 267 | YADIFContext *yadif = ctx->priv; | ||
| 268 | |||
| 269 | if (!yadif->out) | ||
| 270 | return 0; | ||
| 271 | |||
| 272 | if (yadif->auto_enable && !yadif->cur->video->interlaced) { | ||
| 273 | int ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1); | ||
| 274 | if (ret >= 0) | ||
| 275 | ret = ff_end_frame(ctx->outputs[0]); | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | |||
| 279 | return_frame(ctx, 0); | ||
| 280 | return 0; | ||
| 281 | } | 256 | } |
| 282 | 257 | ||
| 283 | static int request_frame(AVFilterLink *link) | 258 | static int request_frame(AVFilterLink *link) |
| @@ -307,8 +282,7 @@ static int request_frame(AVFilterLink *link) · 23 unmodified lines | |||
| 307 | 282 | ||
| 308 | next->pts = yadif->next->pts * 2 - yadif->cur->pts; | 283 | next->pts = yadif->next->pts * 2 - yadif->cur->pts; |
| 309 | 284 | ||
| 310 | start_frame(link->src->inputs[0], next); | 285 | filter_frame(link->src->inputs[0], next); |
| 311 | end_frame(link->src->inputs[0]); | ||
| 312 | yadif->eof = 1; | 286 | yadif->eof = 1; |
| 313 | } else if (ret < 0) { | 287 | } else if (ret < 0) { |
| 314 | return ret; | 288 | return ret; |
| @@ -409,11 +383,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 94 unmodified lines | |||
| 409 | return 0; | 383 | return 0; |
| 410 | } | 384 | } |
| 411 | 385 | ||
| 412 | static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 413 | { | ||
| 414 | return 0; | ||
| 415 | } | ||
| 416 | |||
| 417 | static int config_props(AVFilterLink *link) | 386 | static int config_props(AVFilterLink *link) |
| 418 | { | 387 | { |
| 419 | link->time_base.num = link->src->inputs[0]->time_base.num; | 388 | link->time_base.num = link->src->inputs[0]->time_base.num; |
| @@ -428,10 +397,8 @@ static const AVFilterPad avfilter_vf_yadif_inputs[] = { · 8 unmodified lines | |||
| 428 | { | 397 | { |
| 429 | .name = "default", | 398 | .name = "default", |
| 430 | .type = AVMEDIA_TYPE_VIDEO, | 399 | .type = AVMEDIA_TYPE_VIDEO, |
| 431 | .start_frame = start_frame, | ||
| 432 | .get_video_buffer = get_video_buffer, | 400 | .get_video_buffer = get_video_buffer, |
| 433 | .draw_slice = null_draw_slice, | 401 | .filter_frame = filter_frame, |
| 434 | .end_frame = end_frame, | ||
| 435 | }, | 402 | }, |
| 436 | { NULL } | 403 | { NULL } |
| 437 | }; | 404 | }; |
| @@ -163,213 +163,3 @@ AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, int w, int · 162 unmodified lines | |||
| 163 | 163 | ||
| 164 | return ret; | 164 | return ret; |
| 165 | } | 165 | } |
| 166 | |||
| 167 | int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | ||
| 168 | { | ||
| 169 | AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~0); | ||
| 170 | if (!buf_out) | ||
| 171 | return AVERROR(ENOMEM); | ||
| 172 | return ff_start_frame(link->dst->outputs[0], buf_out); | ||
| 173 | } | ||
| 174 | |||
| 175 | // for filters that support (but don't require) outpic==inpic | ||
| 176 | int ff_inplace_start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) | ||
| 177 | { | ||
| 178 | AVFilterLink *outlink = inlink->dst->outputs[0]; | ||
| 179 | AVFilterBufferRef *outpicref = NULL, *for_next_filter; | ||
| 180 | int ret = 0; | ||
| 181 | |||
| 182 | if ((inpicref->perms & AV_PERM_WRITE) && !(inpicref->perms & AV_PERM_PRESERVE)) { | ||
| 183 | outpicref = avfilter_ref_buffer(inpicref, ~0); | ||
| 184 | if (!outpicref) | ||
| 185 | return AVERROR(ENOMEM); | ||
| 186 | } else { | ||
| 187 | outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 188 | if (!outpicref) | ||
| 189 | return AVERROR(ENOMEM); | ||
| 190 | |||
| 191 | avfilter_copy_buffer_ref_props(outpicref, inpicref); | ||
| 192 | outpicref->video->w = outlink->w; | ||
| 193 | outpicref->video->h = outlink->h; | ||
| 194 | } | ||
| 195 | |||
| 196 | for_next_filter = avfilter_ref_buffer(outpicref, ~0); | ||
| 197 | if (for_next_filter) | ||
| 198 | ret = ff_start_frame(outlink, for_next_filter); | ||
| 199 | else | ||
| 200 | ret = AVERROR(ENOMEM); | ||
| 201 | |||
| 202 | if (ret < 0) { | ||
| 203 | avfilter_unref_bufferp(&outpicref); | ||
| 204 | return ret; | ||
| 205 | } | ||
| 206 | |||
| 207 | outlink->out_buf = outpicref; | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | static int default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) | ||
| 212 | { | ||
| 213 | AVFilterLink *outlink = NULL; | ||
| 214 | |||
| 215 | if (inlink->dst->nb_outputs) | ||
| 216 | outlink = inlink->dst->outputs[0]; | ||
| 217 | |||
| 218 | if (outlink) { | ||
| 219 | AVFilterBufferRef *buf_out; | ||
| 220 | outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); | ||
| 221 | if (!outlink->out_buf) | ||
| 222 | return AVERROR(ENOMEM); | ||
| 223 | |||
| 224 | avfilter_copy_buffer_ref_props(outlink->out_buf, picref); | ||
| 225 | buf_out = avfilter_ref_buffer(outlink->out_buf, ~0); | ||
| 226 | if (!buf_out) | ||
| 227 | return AVERROR(ENOMEM); | ||
| 228 | |||
| 229 | return ff_start_frame(outlink, buf_out); | ||
| 230 | } | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | static void clear_link(AVFilterLink *link) | ||
| 235 | { | ||
| 236 | avfilter_unref_bufferp(&link->cur_buf); | ||
| 237 | avfilter_unref_bufferp(&link->src_buf); | ||
| 238 | avfilter_unref_bufferp(&link->out_buf); | ||
| 239 | } | ||
| 240 | |||
| 241 | /* XXX: should we do the duplicating of the picture ref here, instead of | ||
| 242 | * forcing the source filter to do it? */ | ||
| 243 | int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | ||
| 244 | { | ||
| 245 | int (*start_frame)(AVFilterLink *, AVFilterBufferRef *); | ||
| 246 | AVFilterPad *dst = link->dstpad; | ||
| 247 | int ret, perms = picref->perms; | ||
| 248 | |||
| 249 | FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1); | ||
| 250 | |||
| 251 | if (!(start_frame = dst->start_frame)) | ||
| 252 | start_frame = default_start_frame; | ||
| 253 | |||
| 254 | if (picref->linesize[0] < 0) | ||
| 255 | perms |= AV_PERM_NEG_LINESIZES; | ||
| 256 | /* prepare to copy the picture if it has insufficient permissions */ | ||
| 257 | if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) { | ||
| 258 | av_log(link->dst, AV_LOG_DEBUG, | ||
| 259 | "frame copy needed (have perms %x, need %x, reject %x)\n", | ||
| 260 | picref->perms, | ||
| 261 | link->dstpad->min_perms, link->dstpad->rej_perms); | ||
| 262 | |||
| 263 | link->cur_buf = ff_get_video_buffer(link, dst->min_perms, link->w, link->h); | ||
| 264 | if (!link->cur_buf) { | ||
| 265 | avfilter_unref_bufferp(&picref); | ||
| 266 | return AVERROR(ENOMEM); | ||
| 267 | } | ||
| 268 | |||
| 269 | link->src_buf = picref; | ||
| 270 | avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf); | ||
| 271 | } | ||
| 272 | else | ||
| 273 | link->cur_buf = picref; | ||
| 274 | |||
| 275 | ret = start_frame(link, link->cur_buf); | ||
| 276 | if (ret < 0) | ||
| 277 | clear_link(link); | ||
| 278 | |||
| 279 | return ret; | ||
| 280 | } | ||
| 281 | |||
| 282 | int ff_null_end_frame(AVFilterLink *link) | ||
| 283 | { | ||
| 284 | return ff_end_frame(link->dst->outputs[0]); | ||
| 285 | } | ||
| 286 | |||
| 287 | static int default_end_frame(AVFilterLink *inlink) | ||
| 288 | { | ||
| 289 | AVFilterLink *outlink = NULL; | ||
| 290 | |||
| 291 | if (inlink->dst->nb_outputs) | ||
| 292 | outlink = inlink->dst->outputs[0]; | ||
| 293 | |||
| 294 | if (outlink) { | ||
| 295 | return ff_end_frame(outlink); | ||
| 296 | } | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | int ff_end_frame(AVFilterLink *link) | ||
| 301 | { | ||
| 302 | int (*end_frame)(AVFilterLink *); | ||
| 303 | int ret; | ||
| 304 | |||
| 305 | if (!(end_frame = link->dstpad->end_frame)) | ||
| 306 | end_frame = default_end_frame; | ||
| 307 | |||
| 308 | ret = end_frame(link); | ||
| 309 | |||
| 310 | clear_link(link); | ||
| 311 | |||
| 312 | return ret; | ||
| 313 | } | ||
| 314 | |||
| 315 | int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 316 | { | ||
| 317 | return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); | ||
| 318 | } | ||
| 319 | |||
| 320 | static int default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) | ||
| 321 | { | ||
| 322 | AVFilterLink *outlink = NULL; | ||
| 323 | |||
| 324 | if (inlink->dst->nb_outputs) | ||
| 325 | outlink = inlink->dst->outputs[0]; | ||
| 326 | |||
| 327 | if (outlink) | ||
| 328 | return ff_draw_slice(outlink, y, h, slice_dir); | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) | ||
| 333 | { | ||
| 334 | uint8_t *src[4], *dst[4]; | ||
| 335 | int i, j, vsub, ret; | ||
| 336 | int (*draw_slice)(AVFilterLink *, int, int, int); | ||
| 337 | |||
| 338 | FF_DPRINTF_START(NULL, draw_slice); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir); | ||
| 339 | |||
| 340 | /* copy the slice if needed for permission reasons */ | ||
| 341 | if (link->src_buf) { | ||
| 342 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); | ||
| 343 | vsub = desc->log2_chroma_h; | ||
| 344 | |||
| 345 | for (i = 0; i < 4; i++) { | ||
| 346 | if (link->src_buf->data[i]) { | ||
| 347 | src[i] = link->src_buf-> data[i] + | ||
| 348 | (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; | ||
| 349 | dst[i] = link->cur_buf->data[i] + | ||
| 350 | (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i]; | ||
| 351 | } else | ||
| 352 | src[i] = dst[i] = NULL; | ||
| 353 | } | ||
| 354 | |||
| 355 | for (i = 0; i < 4; i++) { | ||
| 356 | int planew = | ||
| 357 | av_image_get_linesize(link->format, link->cur_buf->video->w, i); | ||
| 358 | |||
| 359 | if (!src[i]) continue; | ||
| 360 | |||
| 361 | for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { | ||
| 362 | memcpy(dst[i], src[i], planew); | ||
| 363 | src[i] += link->src_buf->linesize[i]; | ||
| 364 | dst[i] += link->cur_buf->linesize[i]; | ||
| 365 | } | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | if (!(draw_slice = link->dstpad->draw_slice)) | ||
| 370 | draw_slice = default_draw_slice; | ||
| 371 | ret = draw_slice(link, y, h, slice_dir); | ||
| 372 | if (ret < 0) | ||
| 373 | clear_link(link); | ||
| 374 | return ret; | ||
| 375 | } | ||
| @@ -39,51 +39,4 @@ AVFilterBufferRef *ff_null_get_video_buffer(AVFilterLink *link, int perms, int w · 38 unmodified lines | |||
| 39 | AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, | 39 | AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, |
| 40 | int w, int h); | 40 | int w, int h); |
| 41 | 41 | ||
| 42 | int ff_inplace_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); | ||
| 43 | int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); | ||
| 44 | int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); | ||
| 45 | int ff_null_end_frame(AVFilterLink *link); | ||
| 46 | |||
| 47 | /** | ||
| 48 | * Notify the next filter of the start of a frame. | ||
| 49 | * | ||
| 50 | * @param link the output link the frame will be sent over | ||
| 51 | * @param picref A reference to the frame about to be sent. The data for this | ||
| 52 | * frame need only be valid once draw_slice() is called for that | ||
| 53 | * portion. The receiving filter will free this reference when | ||
| 54 | * it no longer needs it. | ||
| 55 | * | ||
| 56 | * @return >= 0 on success, a negative AVERROR on error. This function will | ||
| 57 | * unreference picref in case of error. | ||
| 58 | */ | ||
| 59 | int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Notify the next filter that the current frame has finished. | ||
| 63 | * | ||
| 64 | * @param link the output link the frame was sent over | ||
| 65 | * | ||
| 66 | * @return >= 0 on success, a negative AVERROR on error | ||
| 67 | */ | ||
| 68 | int ff_end_frame(AVFilterLink *link); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Send a slice to the next filter. | ||
| 72 | * | ||
| 73 | * Slices have to be provided in sequential order, either in | ||
| 74 | * top-bottom or bottom-top order. If slices are provided in | ||
| 75 | * non-sequential order the behavior of the function is undefined. | ||
| 76 | * | ||
| 77 | * @param link the output link over which the frame is being sent | ||
| 78 | * @param y offset in pixels from the top of the image for this slice | ||
| 79 | * @param h height of this slice in pixels | ||
| 80 | * @param slice_dir the assumed direction for sending slices, | ||
| 81 | * from the top slice to the bottom slice if the value is 1, | ||
| 82 | * from the bottom slice to the top slice if the value is -1, | ||
| 83 | * for other values the behavior of the function is undefined. | ||
| 84 | * | ||
| 85 | * @return >= 0 on success, a negative AVERROR on error. | ||
| 86 | */ | ||
| 87 | int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); | ||
| 88 | |||
| 89 | #endif /* AVFILTER_VIDEO_H */ | 42 | #endif /* AVFILTER_VIDEO_H */ |
| @@ -20,13 +20,9 @@ · 19 unmodified lines | |||
| 20 | #include "internal.h" | 20 | #include "internal.h" |
| 21 | #include "libavutil/internal.h" | 21 | #include "libavutil/internal.h" |
| 22 | 22 | ||
| 23 | static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) | 23 | static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) |
| 24 | { | ||
| 25 | return 0; | ||
| 26 | } | ||
| 27 | |||
| 28 | static int end_frame(AVFilterLink *link) | ||
| 29 | { | 24 | { |
| 25 | avfilter_unref_bufferp(&frame); | ||
| 30 | return 0; | 26 | return 0; |
| 31 | } | 27 | } |
| 32 | 28 | ||
| @@ -34,8 +30,7 @@ static const AVFilterPad avfilter_vsink_nullsink_inputs[] = { · 1 unmodified line | |||
| 34 | { | 30 | { |
| 35 | .name = "default", | 31 | .name = "default", |
| 36 | .type = AVMEDIA_TYPE_VIDEO, | 32 | .type = AVMEDIA_TYPE_VIDEO, |
| 37 | .start_frame = start_frame, | 33 | .filter_frame = filter_frame, |
| 38 | .end_frame = end_frame, | ||
| 39 | }, | 34 | }, |
| 40 | { NULL }, | 35 | { NULL }, |
| 41 | }; | 36 | }; |
| @@ -147,8 +147,6 @@ static int color_request_frame(AVFilterLink *link) · 146 unmodified lines | |||
| 147 | { | 147 | { |
| 148 | ColorContext *color = link->src->priv; | 148 | ColorContext *color = link->src->priv; |
| 149 | AVFilterBufferRef *picref = ff_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h); | 149 | AVFilterBufferRef *picref = ff_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h); |
| 150 | AVFilterBufferRef *buf_out; | ||
| 151 | int ret; | ||
| 152 | 150 | ||
| 153 | if (!picref) | 151 | if (!picref) |
| 154 | return AVERROR(ENOMEM); | 152 | return AVERROR(ENOMEM); |
| @@ -157,29 +155,10 @@ static int color_request_frame(AVFilterLink *link) · 2 unmodified lines | |||
| 157 | picref->pts = color->pts++; | 155 | picref->pts = color->pts++; |
| 158 | picref->pos = -1; | 156 | picref->pos = -1; |
| 159 | 157 | ||
| 160 | buf_out = avfilter_ref_buffer(picref, ~0); | ||
| 161 | if (!buf_out) { | ||
| 162 | ret = AVERROR(ENOMEM); | ||
| 163 | goto fail; | ||
| 164 | } | ||
| 165 | |||
| 166 | ret = ff_start_frame(link, buf_out); | ||
| 167 | if (ret < 0) | ||
| 168 | goto fail; | ||
| 169 | |||
| 170 | ff_draw_rectangle(picref->data, picref->linesize, | 158 | ff_draw_rectangle(picref->data, picref->linesize, |
| 171 | color->line, color->line_step, color->hsub, color->vsub, | 159 | color->line, color->line_step, color->hsub, color->vsub, |
| 172 | 0, 0, color->w, color->h); | 160 | 0, 0, color->w, color->h); |
| 173 | ret = ff_draw_slice(link, 0, color->h, 1); | 161 | return ff_filter_frame(link, picref); |
| 174 | if (ret < 0) | ||
| 175 | goto fail; | ||
| 176 | |||
| 177 | ret = ff_end_frame(link); | ||
| 178 | |||
| 179 | fail: | ||
| 180 | avfilter_unref_buffer(picref); | ||
| 181 | |||
| 182 | return ret; | ||
| 183 | } | 162 | } |
| 184 | 163 | ||
| 185 | static const AVFilterPad avfilter_vsrc_color_outputs[] = { | 164 | static const AVFilterPad avfilter_vsrc_color_outputs[] = { |
| @@ -279,7 +279,6 @@ static int movie_get_frame(AVFilterLink *outlink) · 278 unmodified lines | |||
| 279 | 279 | ||
| 280 | static int request_frame(AVFilterLink *outlink) | 280 | static int request_frame(AVFilterLink *outlink) |
| 281 | { | 281 | { |
| 282 | AVFilterBufferRef *outpicref; | ||
| 283 | MovieContext *movie = outlink->src->priv; | 282 | MovieContext *movie = outlink->src->priv; |
| 284 | int ret; | 283 | int ret; |
| 285 | 284 | ||
| @@ -288,23 +287,8 @@ static int request_frame(AVFilterLink *outlink) · 2 unmodified lines | |||
| 288 | if ((ret = movie_get_frame(outlink)) < 0) | 287 | if ((ret = movie_get_frame(outlink)) < 0) |
| 289 | return ret; | 288 | return ret; |
| 290 | 289 | ||
| 291 | outpicref = avfilter_ref_buffer(movie->picref, ~0); | 290 | ret = ff_filter_frame(outlink, movie->picref); |
| 292 | if (!outpicref) { | 291 | movie->picref = NULL; |
| 293 | ret = AVERROR(ENOMEM); | ||
| 294 | goto fail; | ||
| 295 | } | ||
| 296 | |||
| 297 | ret = ff_start_frame(outlink, outpicref); | ||
| 298 | if (ret < 0) | ||
| 299 | goto fail; | ||
| 300 | |||
| 301 | ret = ff_draw_slice(outlink, 0, outlink->h, 1); | ||
| 302 | if (ret < 0) | ||
| 303 | goto fail; | ||
| 304 | |||
| 305 | ret = ff_end_frame(outlink); | ||
| 306 | fail: | ||
| 307 | avfilter_unref_bufferp(&movie->picref); | ||
| 308 | 292 | ||
| 309 | return ret; | 293 | return ret; |
| 310 | } | 294 | } |
| @@ -131,7 +131,6 @@ static int request_frame(AVFilterLink *outlink) · 130 unmodified lines | |||
| 131 | { | 131 | { |
| 132 | TestSourceContext *test = outlink->src->priv; | 132 | TestSourceContext *test = outlink->src->priv; |
| 133 | AVFilterBufferRef *picref; | 133 | AVFilterBufferRef *picref; |
| 134 | int ret; | ||
| 135 | 134 | ||
| 136 | if (test->max_pts >= 0 && test->pts > test->max_pts) | 135 | if (test->max_pts >= 0 && test->pts > test->max_pts) |
| 137 | return AVERROR_EOF; | 136 | return AVERROR_EOF; |
| @@ -148,12 +147,7 @@ static int request_frame(AVFilterLink *outlink) · 10 unmodified lines | |||
| 148 | test->nb_frame++; | 147 | test->nb_frame++; |
| 149 | test->fill_picture_fn(outlink->src, picref); | 148 | test->fill_picture_fn(outlink->src, picref); |
| 150 | 149 | ||
| 151 | if ((ret = ff_start_frame(outlink, picref)) < 0 || | 150 | return ff_filter_frame(outlink, picref); |
| 152 | (ret = ff_draw_slice(outlink, 0, test->h, 1)) < 0 || | ||
| 153 | (ret = ff_end_frame(outlink)) < 0) | ||
| 154 | return ret; | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | } | 151 | } |
| 158 | 152 | ||
| 159 | #if CONFIG_TESTSRC_FILTER | 153 | #if CONFIG_TESTSRC_FILTER |