History

lavfi: merge start_frame/draw_slice/end_frame

Any alleged performance benefits gained from the split are purely mythological and do not justify added code complexity.

Anton Khirnov committed 13 years ago

Commit 565e4991 parent bb6c67b55 files · +632 −1458Browse files

Unified · Split

55 files
  1. libavfilter/af_amix.c +3 −3
  2. libavfilter/af_ashowinfo.c +4 −3
  3. libavfilter/af_asyncts.c +5 −5
  4. libavfilter/af_channelmap.c +3 −3
  5. libavfilter/af_channelsplit.c +3 −3
  6. libavfilter/af_join.c +3 −3
  7. libavfilter/af_resample.c +6 −6
  8. libavfilter/asink_anullsink.c +2 −2
  9. libavfilter/audio.c +0 −47
  10. libavfilter/audio.h +0 −13
  11. libavfilter/avfilter.c +69 −0
  12. libavfilter/avfilter.h +7 −37
  13. libavfilter/buffersink.c +3 −4
  14. libavfilter/buffersrc.c +1 −14
  15. libavfilter/fifo.c +7 −36
  16. libavfilter/internal.h +17 −37
  17. libavfilter/split.c +9 −55
  18. libavfilter/vf_aspect.c +5 −8
  19. libavfilter/vf_blackframe.c +9 −21
  20. libavfilter/vf_boxblur.c +21 −13
  21. libavfilter/vf_copy.c +0 −2
  22. libavfilter/vf_crop.c +17 −48
  23. libavfilter/vf_cropdetect.c +13 −15
  24. libavfilter/vf_delogo.c +26 −20
  25. libavfilter/vf_drawbox.c +8 −11
  26. libavfilter/vf_drawtext.c +7 −31
  27. libavfilter/vf_fade.c +8 −21
  28. libavfilter/vf_fieldorder.c +27 −87
  29. libavfilter/vf_format.c +0 −6
  30. libavfilter/vf_fps.c +4 −22
  31. libavfilter/vf_frei0r.c +19 −40
  32. libavfilter/vf_gradfun.c +27 −20
  33. libavfilter/vf_hflip.c +21 −12
  34. libavfilter/vf_hqdn3d.c +27 −20
  35. libavfilter/vf_libopencv.c +17 −18
  36. libavfilter/vf_lut.c +23 −16
  37. libavfilter/vf_null.c +0 −2
  38. libavfilter/vf_overlay.c +7 −27
  39. libavfilter/vf_pad.c +49 −102
  40. libavfilter/vf_pixdesctest.c +22 −43
  41. libavfilter/vf_scale.c +19 −66
  42. libavfilter/vf_select.c +11 −41
  43. libavfilter/vf_setpts.c +14 −17
  44. libavfilter/vf_settb.c +6 −8
  45. libavfilter/vf_showinfo.c +14 −16
  46. libavfilter/vf_transpose.c +36 −48
  47. libavfilter/vf_unsharp.c +13 −15
  48. libavfilter/vf_vflip.c +6 −19
  49. libavfilter/vf_yadif.c +7 −40
  50. libavfilter/video.c +0 −210
  51. libavfilter/video.h +0 −47
  52. libavfilter/vsink_nullsink.c +3 −8
  53. libavfilter/vsrc_color.c +1 −22
  54. libavfilter/vsrc_movie.c +2 −18
  55. libavfilter/vsrc_testsrc.c +1 −7
libavfilter/af_amix.c+3−3
@@ -314,7 +314,7 @@ static int output_frame(AVFilterLink *outlink, int nb_samples) · 313 unmodified lines
314314 if (s->next_pts != AV_NOPTS_VALUE)
315315 s->next_pts += nb_samples;
316316
317− return ff_filter_samples(outlink, out_buf);
317+ return ff_filter_frame(outlink, out_buf);
318318 }
319319
320320 /**
@@ -455,7 +455,7 @@ static int request_frame(AVFilterLink *outlink) · 134 unmodified lines
455455 return output_frame(outlink, available_samples);
456456 }
457457
458−static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
458+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
459459 {
460460 AVFilterContext *ctx = inlink->dst;
461461 MixContext *s = ctx->priv;
@@ -509,7 +509,7 @@ static int init(AVFilterContext *ctx, const char *args) · 47 unmodified lines
509509 snprintf(name, sizeof(name), "input%d", i);
510510 pad.type = AVMEDIA_TYPE_AUDIO;
511511 pad.name = av_strdup(name);
512− pad.filter_samples = filter_samples;
512+ pad.filter_frame = filter_frame;
513513
514514 ff_insert_inpad(ctx, i, &pad);
515515 }
libavfilter/af_ashowinfo.c+4−3
@@ -34,6 +34,7 @@ · 33 unmodified lines
3434
3535 #include "audio.h"
3636 #include "avfilter.h"
37+#include "internal.h"
3738
3839 typedef struct AShowInfoContext {
3940 /**
@@ -64,7 +65,7 @@ static void uninit(AVFilterContext *ctx) · 24 unmodified lines
6465 av_freep(&s->plane_checksums);
6566 }
6667
67−static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
68+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
6869 {
6970 AVFilterContext *ctx = inlink->dst;
7071 AShowInfoContext *s = ctx->priv;
@@ -103,7 +104,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 32 unmodified lines
103104 av_log(ctx, AV_LOG_INFO, "]\n");
104105
105106 s->frame++;
106− return ff_filter_samples(inlink->dst->outputs[0], buf);
107+ return ff_filter_frame(inlink->dst->outputs[0], buf);
107108 }
108109
109110 static const AVFilterPad inputs[] = {
@@ -112,7 +113,7 @@ static const AVFilterPad inputs[] = { · 2 unmodified lines
112113 .type = AVMEDIA_TYPE_AUDIO,
113114 .get_audio_buffer = ff_null_get_audio_buffer,
114115 .config_props = config_input,
115− .filter_samples = filter_samples,
116+ .filter_frame = filter_frame,
116117 .min_perms = AV_PERM_READ,
117118 },
118119 { NULL },
libavfilter/af_asyncts.c+5−5
@@ -39,7 +39,7 @@ typedef struct ASyncContext { · 38 unmodified lines
3939 float min_delta_sec;
4040 int max_comp;
4141
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() */
4343 int got_output;
4444 } ASyncContext;
4545
@@ -141,7 +141,7 @@ static int request_frame(AVFilterLink *link) · 95 unmodified lines
141141 }
142142
143143 buf->pts = s->pts;
144− return ff_filter_samples(link, buf);
144+ return ff_filter_frame(link, buf);
145145 }
146146
147147 return ret;
@@ -161,7 +161,7 @@ static int64_t get_delay(ASyncContext *s) · 13 unmodified lines
161161 return avresample_available(s->avr) + avresample_get_delay(s->avr);
162162 }
163163
164−static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
164+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
165165 {
166166 AVFilterContext *ctx = inlink->dst;
167167 ASyncContext *s = ctx->priv;
@@ -217,7 +217,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 49 unmodified lines
217217 av_samples_set_silence(buf_out->extended_data, out_size - delta,
218218 delta, nb_channels, buf->format);
219219 }
220− ret = ff_filter_samples(outlink, buf_out);
220+ ret = ff_filter_frame(outlink, buf_out);
221221 if (ret < 0)
222222 goto fail;
223223 s->got_output = 1;
@@ -243,7 +243,7 @@ static const AVFilterPad avfilter_af_asyncts_inputs[] = { · 19 unmodified lines
243243 {
244244 .name = "default",
245245 .type = AVMEDIA_TYPE_AUDIO,
246− .filter_samples = filter_samples
246+ .filter_frame = filter_frame,
247247 },
248248 { NULL }
249249 };
libavfilter/af_channelmap.c+3−3
@@ -313,7 +313,7 @@ static int channelmap_query_formats(AVFilterContext *ctx) · 312 unmodified lines
313313 return 0;
314314 }
315315
316−static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
316+static int channelmap_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
317317 {
318318 AVFilterContext *ctx = inlink->dst;
319319 AVFilterLink *outlink = ctx->outputs[0];
@@ -355,7 +355,7 @@ static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *bu · 35 unmodified lines
355355 memcpy(buf->data, buf->extended_data,
356356 FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0]));
357357
358− return ff_filter_samples(outlink, buf);
358+ return ff_filter_frame(outlink, buf);
359359 }
360360
361361 static int channelmap_config_input(AVFilterLink *inlink)
@@ -389,7 +389,7 @@ static const AVFilterPad avfilter_af_channelmap_inputs[] = { · 27 unmodified lines
389389 {
390390 .name = "default",
391391 .type = AVMEDIA_TYPE_AUDIO,
392− .filter_samples = channelmap_filter_samples,
392+ .filter_frame = channelmap_filter_frame,
393393 .config_props = channelmap_config_input
394394 },
395395 { NULL }
libavfilter/af_channelsplit.c+3−3
@@ -111,7 +111,7 @@ static int query_formats(AVFilterContext *ctx) · 110 unmodified lines
111111 return 0;
112112 }
113113
114−static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
114+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
115115 {
116116 AVFilterContext *ctx = inlink->dst;
117117 int i, ret = 0;
@@ -128,7 +128,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 10 unmodified lines
128128 buf_out->audio->channel_layout =
129129 av_channel_layout_extract_channel(buf->audio->channel_layout, i);
130130
131− ret = ff_filter_samples(ctx->outputs[i], buf_out);
131+ ret = ff_filter_frame(ctx->outputs[i], buf_out);
132132 if (ret < 0)
133133 break;
134134 }
@@ -140,7 +140,7 @@ static const AVFilterPad avfilter_af_channelsplit_inputs[] = { · 5 unmodified lines
140140 {
141141 .name = "default",
142142 .type = AVMEDIA_TYPE_AUDIO,
143− .filter_samples = filter_samples,
143+ .filter_frame = filter_frame,
144144 },
145145 { NULL }
146146 };
libavfilter/af_join.c+3−3
@@ -93,7 +93,7 @@ static const AVClass join_class = { · 92 unmodified lines
9393 .version = LIBAVUTIL_VERSION_INT,
9494 };
9595
96−static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
96+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf)
9797 {
9898 AVFilterContext *ctx = link->dst;
9999 JoinContext *s = ctx->priv;
@@ -230,7 +230,7 @@ static int join_init(AVFilterContext *ctx, const char *args) · 130 unmodified lines
230230 snprintf(name, sizeof(name), "input%d", i);
231231 pad.type = AVMEDIA_TYPE_AUDIO;
232232 pad.name = av_strdup(name);
233− pad.filter_samples = filter_samples;
233+ pad.filter_frame = filter_frame;
234234
235235 pad.needs_fifo = 1;
236236
@@ -471,7 +471,7 @@ static int join_request_frame(AVFilterLink *outlink) · 234 unmodified lines
471471 priv->nb_in_buffers = ctx->nb_inputs;
472472 buf->buf->priv = priv;
473473
474− ret = ff_filter_samples(outlink, buf);
474+ ret = ff_filter_frame(outlink, buf);
475475
476476 memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs);
477477
libavfilter/af_resample.c+6−6
@@ -40,7 +40,7 @@ typedef struct ResampleContext { · 39 unmodified lines
4040
4141 int64_t next_pts;
4242
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() */
4444 int got_output;
4545 } ResampleContext;
4646
@@ -162,12 +162,12 @@ static int request_frame(AVFilterLink *outlink) · 115 unmodified lines
162162 }
163163
164164 buf->pts = s->next_pts;
165− return ff_filter_samples(outlink, buf);
165+ return ff_filter_frame(outlink, buf);
166166 }
167167 return ret;
168168 }
169169
170−static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
170+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
171171 {
172172 AVFilterContext *ctx = inlink->dst;
173173 ResampleContext *s = ctx->priv;
@@ -224,7 +224,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) · 50 unmodified lines
224224
225225 s->next_pts = buf_out->pts + buf_out->audio->nb_samples;
226226
227− ret = ff_filter_samples(outlink, buf_out);
227+ ret = ff_filter_frame(outlink, buf_out);
228228 s->got_output = 1;
229229 }
230230
@@ -232,7 +232,7 @@ fail: · 1 unmodified line
232232 avfilter_unref_buffer(buf);
233233 } else {
234234 buf->format = outlink->format;
235− ret = ff_filter_samples(outlink, buf);
235+ ret = ff_filter_frame(outlink, buf);
236236 s->got_output = 1;
237237 }
238238
@@ -243,7 +243,7 @@ static const AVFilterPad avfilter_af_resample_inputs[] = { · 4 unmodified lines
243243 {
244244 .name = "default",
245245 .type = AVMEDIA_TYPE_AUDIO,
246− .filter_samples = filter_samples,
246+ .filter_frame = filter_frame,
247247 .min_perms = AV_PERM_READ
248248 },
249249 { NULL }
libavfilter/asink_anullsink.c+2−2
@@ -20,7 +20,7 @@ · 19 unmodified lines
2020 #include "avfilter.h"
2121 #include "internal.h"
2222
23−static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
23+static int null_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref)
2424 {
2525 avfilter_unref_bufferp(&samplesref);
2626 return 0;
@@ -30,7 +30,7 @@ static const AVFilterPad avfilter_asink_anullsink_inputs[] = { · 3 unmodified lines
3030 {
3131 .name = "default",
3232 .type = AVMEDIA_TYPE_AUDIO,
33− .filter_samples = null_filter_samples,
33+ .filter_frame = null_filter_frame,
3434 },
3535 { NULL },
3636 };
libavfilter/audio.c+0−47
@@ -146,50 +146,3 @@ fail: · 145 unmodified lines
146146 av_freep(&samples);
147147 return NULL;
148148 }
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−
libavfilter/audio.h+0−13
@@ -42,17 +42,4 @@ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms, · 41 unmodified lines
4242 AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
4343 int nb_samples);
4444
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−
5845 #endif /* AVFILTER_AUDIO_H */
libavfilter/avfilter.c+69−0
@@ -23,12 +23,16 @@ · 22 unmodified lines
2323
2424 #include "libavutil/channel_layout.h"
2525 #include "libavutil/common.h"
26+#include "libavutil/imgutils.h"
2627 #include "libavutil/pixdesc.h"
2728 #include "libavutil/rational.h"
29+#include "libavutil/samplefmt.h"
2830
31+#include "audio.h"
2932 #include "avfilter.h"
3033 #include "formats.h"
3134 #include "internal.h"
35+#include "video.h"
3236
3337 unsigned avfilter_version(void) {
3438 return LIBAVFILTER_VERSION_INT;
@@ -446,3 +450,68 @@ enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx) · 411 unmodified lines
446450 {
447451 return pads[pad_idx].type;
448452 }
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+}
libavfilter/avfilter.h+7−37
@@ -253,14 +253,7 @@ struct AVFilterPad { · 252 unmodified lines
253253 int rej_perms;
254254
255255 /**
256− * Callback called before passing the first slice of a new frame. If
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.
256+ * @deprecated unused
264257 */
265258 int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref);
266259
@@ -282,37 +275,26 @@ struct AVFilterPad { · 15 unmodified lines
282275 int nb_samples);
283276
284277 /**
285− * Callback called after the slices of a frame are completely sent. If
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.
278+ * @deprecated unused
292279 */
293280 int (*end_frame)(AVFilterLink *link);
294281
295282 /**
296− * Slice drawing callback. This is where a filter receives video data
297− * and should do its processing.
298− *
299− * Input video pads only.
300− *
301− * @return >= 0 on success, a negative AVERROR on error.
283+ * @deprecated unused
302284 */
303285 int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir);
304286
305287 /**
306− * Samples filtering callback. This is where a filter receives audio data
307− * and should do its processing.
288+ * Filtering callback. This is where a filter receives a frame with
289+ * audio/video data and should do its processing.
308290 *
309− * Input audio pads only.
291+ * Input pads only.
310292 *
311293 * @return >= 0 on success, a negative AVERROR on error. This function
312294 * must ensure that samplesref is properly unreferenced on error if it
313295 * hasn't been passed on to another filter.
314296 */
315− int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
297+ int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame);
316298
317299 /**
318300 * Frame poll callback. This returns the number of immediately available
@@ -531,18 +513,6 @@ struct AVFilterLink { · 212 unmodified lines
531513 AVLINK_STARTINIT, ///< started, but incomplete
532514 AVLINK_INIT ///< complete
533515 } 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;
546516 };
547517
548518 /**
libavfilter/buffersink.c+3−4
@@ -48,13 +48,12 @@ static av_cold void uninit(AVFilterContext *ctx) · 47 unmodified lines
4848 av_audio_fifo_free(sink->audio_fifo);
4949 }
5050
51−static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
51+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf)
5252 {
5353 BufferSinkContext *s = link->dst->priv;
5454
5555 av_assert0(!s->cur_buf);
5656 s->cur_buf = buf;
57− link->cur_buf = NULL;
5857
5958 return 0;
6059 }
@@ -144,7 +143,7 @@ static const AVFilterPad avfilter_vsink_buffer_inputs[] = { · 83 unmodified lines
144143 {
145144 .name = "default",
146145 .type = AVMEDIA_TYPE_VIDEO,
147− .start_frame = start_frame,
146+ .filter_frame = filter_frame,
148147 .min_perms = AV_PERM_READ,
149148 .needs_fifo = 1
150149 },
@@ -165,7 +164,7 @@ static const AVFilterPad avfilter_asink_abuffer_inputs[] = { · 14 unmodified lines
165164 {
166165 .name = "default",
167166 .type = AVMEDIA_TYPE_AUDIO,
168− .filter_samples = start_frame,
167+ .filter_frame = filter_frame,
169168 .min_perms = AV_PERM_READ,
170169 .needs_fifo = 1
171170 },
libavfilter/buffersrc.c+1−14
@@ -327,20 +327,7 @@ static int request_frame(AVFilterLink *link) · 326 unmodified lines
327327 }
328328 av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
329329
330− switch (link->type) {
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− }
330+ ff_filter_frame(link, buf);
344331
345332 return ret;
346333 }
libavfilter/fifo.c+7−36
@@ -77,7 +77,6 @@ static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) · 76 unmodified lines
7777 {
7878 FifoContext *fifo = inlink->dst->priv;
7979
80− inlink->cur_buf = NULL;
8180 fifo->last->next = av_mallocz(sizeof(Buf));
8281 if (!fifo->last->next) {
8382 avfilter_unref_buffer(buf);
@@ -99,16 +98,6 @@ static void queue_pop(FifoContext *s) · 15 unmodified lines
9998 s->root.next = tmp;
10099 }
101100
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−
112101 /**
113102 * Move data pointers and pts offset samples forward.
114103 */
@@ -228,7 +217,7 @@ static int return_audio_frame(AVFilterContext *ctx) · 113 unmodified lines
228217 buf_out = s->buf_out;
229218 s->buf_out = NULL;
230219 }
231− return ff_filter_samples(link, buf_out);
220+ return ff_filter_frame(link, buf_out);
232221 }
233222
234223 static int request_frame(AVFilterLink *outlink)
@@ -241,27 +230,11 @@ static int request_frame(AVFilterLink *outlink) · 6 unmodified lines
241230 return ret;
242231 }
243232
244− /* by doing this, we give ownership of the reference to the next filter,
245− * so we don't have to worry about dereferencing it ourselves. */
246− switch (outlink->type) {
247− case AVMEDIA_TYPE_VIDEO:
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−
233+ if (outlink->request_samples) {
234+ return return_audio_frame(outlink->src);
235+ } else {
236+ ret = ff_filter_frame(outlink, fifo->root.next->buf);
253237 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);
265238 }
266239
267240 return ret;
@@ -272,9 +245,7 @@ static const AVFilterPad avfilter_vf_fifo_inputs[] = { · 4 unmodified lines
272245 .name = "default",
273246 .type = AVMEDIA_TYPE_VIDEO,
274247 .get_video_buffer = ff_null_get_video_buffer,
275− .start_frame = add_to_queue,
276− .draw_slice = draw_slice,
277− .end_frame = end_frame,
248+ .filter_frame = add_to_queue,
278249 .rej_perms = AV_PERM_REUSE2,
279250 },
280251 { NULL }
@@ -307,7 +278,7 @@ static const AVFilterPad avfilter_af_afifo_inputs[] = { · 26 unmodified lines
307278 .name = "default",
308279 .type = AVMEDIA_TYPE_AUDIO,
309280 .get_audio_buffer = ff_null_get_audio_buffer,
310− .filter_samples = add_to_queue,
281+ .filter_frame = add_to_queue,
311282 .rej_perms = AV_PERM_REUSE2,
312283 },
313284 { NULL }
libavfilter/internal.h+17−37
@@ -63,18 +63,6 @@ struct AVFilterPad { · 62 unmodified lines
6363 */
6464 int rej_perms;
6565
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−
7866 /**
7967 * Callback function to get a video buffer. If NULL, the filter system will
8068 * use avfilter_default_get_video_buffer().
@@ -93,37 +81,16 @@ struct AVFilterPad { · 12 unmodified lines
9381 int nb_samples);
9482
9583 /**
96− * Callback called after the slices of a frame are completely sent. If
97− * NULL, the filter layer will default to releasing the reference stored
98− * in the link structure during start_frame().
84+ * Filtering callback. This is where a filter receives a frame with
85+ * audio/video data and should do its processing.
9986 *
100− * Input video 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.
87+ * Input pads only.
12188 *
12289 * @return >= 0 on success, a negative AVERROR on error. This function
12390 * must ensure that samplesref is properly unreferenced on error if it
12491 * hasn't been passed on to another filter.
12592 */
126− int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
93+ int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame);
12794
12895 /**
12996 * Frame poll callback. This returns the number of immediately available
@@ -237,4 +204,17 @@ int ff_poll_frame(AVFilterLink *link); · 107 unmodified lines
237204 */
238205 int ff_request_frame(AVFilterLink *link);
239206
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+
240220 #endif /* AVFILTER_INTERNAL_H */
libavfilter/split.c+9−55
@@ -67,46 +67,23 @@ static void split_uninit(AVFilterContext *ctx) · 66 unmodified lines
6767 av_freep(&ctx->output_pads[i].name);
6868 }
6969
70−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
70+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
7171 {
7272 AVFilterContext *ctx = inlink->dst;
7373 int i, ret = 0;
7474
7575 for (i = 0; i < ctx->nb_outputs; i++) {
76− AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~AV_PERM_WRITE);
77− if (!buf_out)
78− return 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)
76+ AVFilterBufferRef *buf_out = avfilter_ref_buffer(frame, ~AV_PERM_WRITE);
77+ if (!buf_out) {
78+ ret = AVERROR(ENOMEM);
9579 break;
96− }
97− return ret;
98−}
99−
100−static int end_frame(AVFilterLink *inlink)
101−{
102− AVFilterContext *ctx = inlink->dst;
103− int i, ret = 0;
80+ }
10481
105− for (i = 0; i < ctx->nb_outputs; i++) {
106− ret = ff_end_frame(ctx->outputs[i]);
82+ ret = ff_filter_frame(ctx->outputs[i], buf_out);
10783 if (ret < 0)
10884 break;
10985 }
86+ avfilter_unref_bufferp(&frame);
11087 return ret;
11188 }
11289
@@ -115,9 +92,7 @@ static const AVFilterPad avfilter_vf_split_inputs[] = { · 2 unmodified lines
11592 .name = "default",
11693 .type = AVMEDIA_TYPE_VIDEO,
11794 .get_video_buffer = ff_null_get_video_buffer,
118− .start_frame = start_frame,
119− .draw_slice = draw_slice,
120− .end_frame = end_frame,
95+ .filter_frame = filter_frame,
12196 },
12297 { NULL }
12398 };
@@ -133,33 +108,12 @@ AVFilter avfilter_vf_split = { · 9 unmodified lines
133108 .outputs = NULL,
134109 };
135110
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−
157111 static const AVFilterPad avfilter_af_asplit_inputs[] = {
158112 {
159113 .name = "default",
160114 .type = AVMEDIA_TYPE_AUDIO,
161115 .get_audio_buffer = ff_null_get_audio_buffer,
162− .filter_samples = filter_samples
116+ .filter_frame = filter_frame,
163117 },
164118 { NULL }
165119 };
libavfilter/vf_aspect.c+5−8
@@ -65,13 +65,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 64 unmodified lines
6565 return 0;
6666 }
6767
68−static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
68+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
6969 {
7070 AspectContext *aspect = link->dst->priv;
7171
72− picref->video->pixel_aspect = aspect->aspect;
73− link->cur_buf = NULL;
74− return ff_start_frame(link->dst->outputs[0], picref);
72+ frame->video->pixel_aspect = aspect->aspect;
73+ return ff_filter_frame(link->dst->outputs[0], frame);
7574 }
7675
7776 #if CONFIG_SETDAR_FILTER
@@ -99,8 +98,7 @@ static const AVFilterPad avfilter_vf_setdar_inputs[] = { · 21 unmodified lines
9998 .type = AVMEDIA_TYPE_VIDEO,
10099 .config_props = setdar_config_props,
101100 .get_video_buffer = ff_null_get_video_buffer,
102− .start_frame = start_frame,
103− .end_frame = ff_null_end_frame
101+ .filter_frame = filter_frame,
104102 },
105103 { NULL }
106104 };
@@ -144,8 +142,7 @@ static const AVFilterPad avfilter_vf_setsar_inputs[] = { · 37 unmodified lines
144142 .type = AVMEDIA_TYPE_VIDEO,
145143 .config_props = setsar_config_props,
146144 .get_video_buffer = ff_null_get_video_buffer,
147− .start_frame = start_frame,
148− .end_frame = ff_null_end_frame
145+ .filter_frame = filter_frame,
149146 },
150147 { NULL }
151148 };
libavfilter/vf_blackframe.c+9−21
@@ -78,49 +78,37 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 77 unmodified lines
7878 return 0;
7979 }
8080
81−static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
81+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
8282 {
8383 AVFilterContext *ctx = inlink->dst;
8484 BlackFrameContext *blackframe = ctx->priv;
85− AVFilterBufferRef *picref = inlink->cur_buf;
8685 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];
8888
89− for (i = 0; i < h; i++) {
89+ for (i = 0; i < frame->video->h; i++) {
9090 for (x = 0; x < inlink->w; x++)
9191 blackframe->nblack += p[x] < blackframe->bthresh;
92− p += picref->linesize[0];
92+ p += frame->linesize[0];
9393 }
9494
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−
10595 pblack = blackframe->nblack * 100 / (inlink->w * inlink->h);
10696 if (pblack >= blackframe->bamount)
10797 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,
109− picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base));
98+ blackframe->frame, pblack, frame->pos, frame->pts,
99+ frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base));
110100
111101 blackframe->frame++;
112102 blackframe->nblack = 0;
113− return ff_end_frame(inlink->dst->outputs[0]);
103+ return ff_filter_frame(inlink->dst->outputs[0], frame);
114104 }
115105
116106 static const AVFilterPad avfilter_vf_blackframe_inputs[] = {
117107 {
118108 .name = "default",
119109 .type = AVMEDIA_TYPE_VIDEO,
120− .draw_slice = draw_slice,
121110 .get_video_buffer = ff_null_get_video_buffer,
122− .start_frame = ff_null_start_frame,
123− .end_frame = end_frame,
111+ .filter_frame = filter_frame,
124112 },
125113 { NULL }
126114 };
libavfilter/vf_boxblur.c+21−13
@@ -307,31 +307,39 @@ static void vblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_li · 306 unmodified lines
307307 h, radius, power, temp);
308308 }
309309
310−static int draw_slice(AVFilterLink *inlink, int y0, int h0, int slice_dir)
310+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
311311 {
312312 AVFilterContext *ctx = inlink->dst;
313313 BoxBlurContext *boxblur = ctx->priv;
314314 AVFilterLink *outlink = inlink->dst->outputs[0];
315− AVFilterBufferRef *inpicref = inlink ->cur_buf;
316− AVFilterBufferRef *outpicref = outlink->out_buf;
315+ AVFilterBufferRef *out;
317316 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;
319318 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 };
321320
322− for (plane = 0; inpicref->data[plane] && plane < 4; plane++)
323− hblur(outpicref->data[plane], outpicref->linesize[plane],
324− inpicref ->data[plane], inpicref ->linesize[plane],
321+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
322+ if (!out) {
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],
325331 w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane],
326332 boxblur->temp);
327333
328− for (plane = 0; inpicref->data[plane] && plane < 4; plane++)
329− vblur(outpicref->data[plane], outpicref->linesize[plane],
330− outpicref->data[plane], outpicref->linesize[plane],
334+ for (plane = 0; in->data[plane] && plane < 4; plane++)
335+ vblur(out->data[plane], out->linesize[plane],
336+ out->data[plane], out->linesize[plane],
331337 w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane],
332338 boxblur->temp);
333339
334− return ff_draw_slice(outlink, y0, h0, slice_dir);
340+ avfilter_unref_bufferp(&in);
341+
342+ return ff_filter_frame(outlink, out);
335343 }
336344
337345 static const AVFilterPad avfilter_vf_boxblur_inputs[] = {
@@ -339,7 +347,7 @@ static const AVFilterPad avfilter_vf_boxblur_inputs[] = { · 1 unmodified line
339347 .name = "default",
340348 .type = AVMEDIA_TYPE_VIDEO,
341349 .config_props = config_input,
342− .draw_slice = draw_slice,
350+ .filter_frame = filter_frame,
343351 .min_perms = AV_PERM_READ
344352 },
345353 { NULL }
libavfilter/vf_copy.c+0−2
@@ -31,8 +31,6 @@ static const AVFilterPad avfilter_vf_copy_inputs[] = { · 30 unmodified lines
3131 .name = "default",
3232 .type = AVMEDIA_TYPE_VIDEO,
3333 .get_video_buffer = ff_null_get_video_buffer,
34− .start_frame = ff_null_start_frame,
35− .end_frame = ff_null_end_frame,
3634 .rej_perms = ~0
3735 },
3836 { NULL }
libavfilter/vf_crop.c+17−48
@@ -243,24 +243,19 @@ static int config_output(AVFilterLink *link) · 242 unmodified lines
243243 return 0;
244244 }
245245
246−static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
246+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
247247 {
248248 AVFilterContext *ctx = link->dst;
249249 CropContext *crop = ctx->priv;
250− AVFilterBufferRef *ref2;
251250 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
252251 int i;
253252
254− ref2 = avfilter_ref_buffer(picref, ~0);
255− if (!ref2)
256− return AVERROR(ENOMEM);
253+ frame->video->w = crop->w;
254+ frame->video->h = crop->h;
257255
258− ref2->video->w = crop->w;
259− ref2->video->h = crop->h;
260−
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;
256+ crop->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
257+ NAN : frame->pts * av_q2d(link->time_base);
258+ crop->var_values[VAR_POS] = frame->pos == -1 ? NAN : frame->pos;
264259 crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL);
265260 crop->var_values[VAR_Y] = av_expr_eval(crop->y_pexpr, crop->var_values, NULL);
266261 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
279274 (int)crop->var_values[VAR_N], crop->var_values[VAR_T], crop->x,
280275 crop->y, crop->x+crop->w, crop->y+crop->h);
281276
282− ref2->data[0] += crop->y * ref2->linesize[0];
283− ref2->data[0] += crop->x * crop->max_step[0];
277+ frame->data[0] += crop->y * frame->linesize[0];
278+ frame->data[0] += crop->x * crop->max_step[0];
284279
285280 if (!(desc->flags & PIX_FMT_PAL || desc->flags & PIX_FMT_PSEUDOPAL)) {
286281 for (i = 1; i < 3; i ++) {
287− if (ref2->data[i]) {
288− ref2->data[i] += (crop->y >> crop->vsub) * ref2->linesize[i];
289− ref2->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub;
282+ if (frame->data[i]) {
283+ frame->data[i] += (crop->y >> crop->vsub) * frame->linesize[i];
284+ frame->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub;
290285 }
291286 }
292287 }
293288
294289 /* alpha plane */
295− if (ref2->data[3]) {
296− ref2->data[3] += crop->y * ref2->linesize[3];
297− ref2->data[3] += crop->x * crop->max_step[3];
290+ if (frame->data[3]) {
291+ frame->data[3] += crop->y * frame->linesize[3];
292+ frame->data[3] += crop->x * crop->max_step[3];
298293 }
299294
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−
325295 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);
327298 }
328299
329300 static const AVFilterPad avfilter_vf_crop_inputs[] = {
330301 {
331302 .name = "default",
332303 .type = AVMEDIA_TYPE_VIDEO,
333− .start_frame = start_frame,
334− .draw_slice = draw_slice,
335− .end_frame = end_frame,
304+ .filter_frame = filter_frame,
336305 .get_video_buffer = ff_null_get_video_buffer,
337306 .config_props = config_input,
338307 },
libavfilter/vf_cropdetect.c+13−15
@@ -117,11 +117,10 @@ static int config_input(AVFilterLink *inlink) · 116 unmodified lines
117117 return 0;
118118 }
119119
120−static int end_frame(AVFilterLink *inlink)
120+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
121121 {
122122 AVFilterContext *ctx = inlink->dst;
123123 CropDetectContext *cd = ctx->priv;
124− AVFilterBufferRef *picref = inlink->cur_buf;
125124 int bpp = cd->max_pixsteps[0];
126125 int w, h, x, y, shrink_by;
127126
@@ -129,36 +128,36 @@ static int end_frame(AVFilterLink *inlink) · 1 unmodified line
129128 if (++cd->frame_nb > 0) {
130129 // Reset the crop area every reset_count frames, if reset_count is > 0
131130 if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) {
132− cd->x1 = picref->video->w-1;
133− cd->y1 = picref->video->h-1;
131+ cd->x1 = frame->video->w-1;
132+ cd->y1 = frame->video->h-1;
134133 cd->x2 = 0;
135134 cd->y2 = 0;
136135 cd->frame_nb = 1;
137136 }
138137
139138 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) {
141140 cd->y1 = y;
142141 break;
143142 }
144143 }
145144
146− for (y = picref->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) {
145+ for (y = frame->video->h-1; y > cd->y2; y--) {
146+ if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) {
148147 cd->y2 = y;
149148 break;
150149 }
151150 }
152151
153152 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) {
155154 cd->x1 = y;
156155 break;
157156 }
158157 }
159158
160− for (y = picref->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) {
159+ for (y = frame->video->w-1; y > cd->x2; y--) {
160+ if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) {
162161 cd->x2 = y;
163162 break;
164163 }
@@ -189,12 +188,12 @@ static int end_frame(AVFilterLink *inlink) · 24 unmodified lines
189188
190189 av_log(ctx, AV_LOG_INFO,
191190 "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,
193− picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base),
191+ cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, frame->pos, frame->pts,
192+ frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base),
194193 w, h, x, y);
195194 }
196195
197− return ff_end_frame(inlink->dst->outputs[0]);
196+ return ff_filter_frame(inlink->dst->outputs[0], frame);
198197 }
199198
200199 static const AVFilterPad avfilter_vf_cropdetect_inputs[] = {
@@ -203,8 +202,7 @@ static const AVFilterPad avfilter_vf_cropdetect_inputs[] = { · 2 unmodified lines
203202 .type = AVMEDIA_TYPE_VIDEO,
204203 .config_props = config_input,
205204 .get_video_buffer = ff_null_get_video_buffer,
206− .start_frame = ff_null_start_frame,
207− .end_frame = end_frame,
205+ .filter_frame = filter_frame,
208206 },
209207 { NULL }
210208 };
libavfilter/vf_delogo.c+26−20
@@ -215,30 +215,38 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 214 unmodified lines
215215 return 0;
216216 }
217217
218−static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
219−{
220− return 0;
221−}
222−
223−static int end_frame(AVFilterLink *inlink)
218+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
224219 {
225220 DelogoContext *delogo = inlink->dst->priv;
226221 AVFilterLink *outlink = inlink->dst->outputs[0];
227− AVFilterBufferRef *inpicref = inlink ->cur_buf;
228− AVFilterBufferRef *outpicref = outlink->out_buf;
229222 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
230− int direct = inpicref->buf == outpicref->buf;
223+ AVFilterBufferRef *out;
231224 int hsub0 = desc->log2_chroma_w;
232225 int vsub0 = desc->log2_chroma_h;
226+ int direct;
233227 int plane;
234− int ret;
235228
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++) {
237245 int hsub = plane == 1 || plane == 2 ? hsub0 : 0;
238246 int vsub = plane == 1 || plane == 2 ? vsub0 : 0;
239247
240− apply_delogo(outpicref->data[plane], outpicref->linesize[plane],
241− inpicref ->data[plane], inpicref ->linesize[plane],
248+ apply_delogo(out->data[plane], out->linesize[plane],
249+ in ->data[plane], in ->linesize[plane],
242250 inlink->w>>hsub, inlink->h>>vsub,
243251 delogo->x>>hsub, delogo->y>>vsub,
244252 delogo->w>>hsub, delogo->h>>vsub,
@@ -246,10 +254,10 @@ static int end_frame(AVFilterLink *inlink) · 1 unmodified line
246254 delogo->show, direct);
247255 }
248256
249− if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 ||
250− (ret = ff_end_frame(outlink)) < 0)
251− return ret;
252− return 0;
257+ if (!direct)
258+ avfilter_unref_bufferp(&in);
259+
260+ return ff_filter_frame(outlink, out);
253261 }
254262
255263 static const AVFilterPad avfilter_vf_delogo_inputs[] = {
@@ -257,9 +265,7 @@ static const AVFilterPad avfilter_vf_delogo_inputs[] = { · 1 unmodified line
257265 .name = "default",
258266 .type = AVMEDIA_TYPE_VIDEO,
259267 .get_video_buffer = ff_null_get_video_buffer,
260− .start_frame = ff_inplace_start_frame,
261− .draw_slice = null_draw_slice,
262− .end_frame = end_frame,
268+ .filter_frame = filter_frame,
263269 .min_perms = AV_PERM_WRITE | AV_PERM_READ,
264270 .rej_perms = AV_PERM_PRESERVE
265271 },
libavfilter/vf_drawbox.c+8−11
@@ -96,21 +96,20 @@ static int config_input(AVFilterLink *inlink) · 95 unmodified lines
9696 return 0;
9797 }
9898
99−static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir)
99+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
100100 {
101101 DrawBoxContext *drawbox = inlink->dst->priv;
102102 int plane, x, y, xb = drawbox->x, yb = drawbox->y;
103103 unsigned char *row[4];
104− AVFilterBufferRef *picref = inlink->cur_buf;
105104
106− for (y = FFMAX(yb, y0); y < (y0 + h) && y < (yb + drawbox->h); y++) {
107− row[0] = picref->data[0] + y * picref->linesize[0];
105+ for (y = FFMAX(yb, 0); y < frame->video->h && y < (yb + drawbox->h); y++) {
106+ row[0] = frame->data[0] + y * frame->linesize[0];
108107
109108 for (plane = 1; plane < 3; plane++)
110− row[plane] = picref->data[plane] +
111− picref->linesize[plane] * (y >> drawbox->vsub);
109+ row[plane] = frame->data[plane] +
110+ frame->linesize[plane] * (y >> drawbox->vsub);
112111
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++) {
114113 double alpha = (double)drawbox->yuv_color[A] / 255;
115114
116115 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
122121 }
123122 }
124123
125− return ff_draw_slice(inlink->dst->outputs[0], y0, h, 1);
124+ return ff_filter_frame(inlink->dst->outputs[0], frame);
126125 }
127126
128127 static const AVFilterPad avfilter_vf_drawbox_inputs[] = {
@@ -131,9 +130,7 @@ static const AVFilterPad avfilter_vf_drawbox_inputs[] = { · 2 unmodified lines
131130 .type = AVMEDIA_TYPE_VIDEO,
132131 .config_props = config_input,
133132 .get_video_buffer = ff_null_get_video_buffer,
134− .start_frame = ff_null_start_frame,
135− .draw_slice = draw_slice,
136− .end_frame = ff_null_end_frame,
133+ .filter_frame = filter_frame,
137134 .min_perms = AV_PERM_WRITE | AV_PERM_READ,
138135 .rej_perms = AV_PERM_PRESERVE
139136 },
libavfilter/vf_drawtext.c+7−31
@@ -792,11 +792,6 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref, · 791 unmodified lines
792792 return 0;
793793 }
794794
795−static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
796−{
797− return 0;
798−}
799−
800795 static inline int normalize_double(int *n, double d)
801796 {
802797 int ret = 0;
@@ -812,20 +807,20 @@ static inline int normalize_double(int *n, double d) · 9 unmodified lines
812807 return ret;
813808 }
814809
815−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
810+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
816811 {
817812 AVFilterContext *ctx = inlink->dst;
818813 DrawTextContext *dtext = ctx->priv;
819− AVFilterBufferRef *buf_out;
820814 int ret = 0;
821815
822816 if ((ret = dtext_prepare_text(ctx)) < 0) {
823817 av_log(ctx, AV_LOG_ERROR, "Can't draw text\n");
818+ avfilter_unref_bufferp(&frame);
824819 return ret;
825820 }
826821
827− dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ?
828− NAN : inpicref->pts * av_q2d(inlink->time_base);
822+ dtext->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
823+ NAN : frame->pts * av_q2d(inlink->time_base);
829824 dtext->var_values[VAR_X] =
830825 av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
831826 dtext->var_values[VAR_Y] =
@@ -854,29 +849,12 @@ static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) · 22 unmodified lines
854849 (int)dtext->var_values[VAR_N], dtext->var_values[VAR_T],
855850 dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h);
856851
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−
871852 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);
873854
874855 dtext->var_values[VAR_N] += 1.0;
875856
876− if ((ret = ff_draw_slice(outlink, 0, picref->video->h, 1)) < 0 ||
877− (ret = ff_end_frame(outlink)) < 0)
878− return ret;
879− return 0;
857+ return ff_filter_frame(inlink->dst->outputs[0], frame);
880858 }
881859
882860 static const AVFilterPad avfilter_vf_drawtext_inputs[] = {
@@ -884,9 +862,7 @@ static const AVFilterPad avfilter_vf_drawtext_inputs[] = { · 1 unmodified line
884862 .name = "default",
885863 .type = AVMEDIA_TYPE_VIDEO,
886864 .get_video_buffer = ff_null_get_video_buffer,
887− .start_frame = start_frame,
888− .draw_slice = null_draw_slice,
889− .end_frame = end_frame,
865+ .filter_frame = filter_frame,
890866 .config_props = config_input,
891867 .min_perms = AV_PERM_WRITE |
892868 AV_PERM_READ,
libavfilter/vf_fade.c+8−21
@@ -98,17 +98,16 @@ static int config_props(AVFilterLink *inlink) · 97 unmodified lines
9898 return 0;
9999 }
100100
101−static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
101+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
102102 {
103103 FadeContext *fade = inlink->dst->priv;
104− AVFilterBufferRef *outpic = inlink->cur_buf;
105104 uint8_t *p;
106105 int i, j, plane;
107106
108107 if (fade->factor < UINT16_MAX) {
109108 /* luma or rgb plane */
110− for (i = 0; i < h; i++) {
111− p = outpic->data[0] + (y+i) * outpic->linesize[0];
109+ for (i = 0; i < frame->video->h; i++) {
110+ p = frame->data[0] + i * frame->linesize[0];
112111 for (j = 0; j < inlink->w * fade->bpp; j++) {
113112 /* fade->factor is using 16 lower-order bits for decimal
114113 * 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
118117 }
119118 }
120119
121− if (outpic->data[1] && outpic->data[2]) {
120+ if (frame->data[1] && frame->data[2]) {
122121 /* chroma planes */
123122 for (plane = 1; plane < 3; plane++) {
124− for (i = 0; i < h; i++) {
125− p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane];
123+ for (i = 0; i < frame->video->h; i++) {
124+ p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane];
126125 for (j = 0; j < inlink->w >> fade->hsub; j++) {
127126 /* 8421367 = ((128 << 1) + 1) << 15. It is an integer
128127 * 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
135134 }
136135 }
137136
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−
148137 if (fade->frame_index >= fade->start_frame &&
149138 fade->frame_index <= fade->stop_frame)
150139 fade->factor += fade->fade_per_frame;
151140 fade->factor = av_clip_uint16(fade->factor);
152141 fade->frame_index++;
153142
154− return ret;
143+ return ff_filter_frame(inlink->dst->outputs[0], frame);
155144 }
156145
157146 static const AVFilterPad avfilter_vf_fade_inputs[] = {
@@ -160,9 +149,7 @@ static const AVFilterPad avfilter_vf_fade_inputs[] = { · 2 unmodified lines
160149 .type = AVMEDIA_TYPE_VIDEO,
161150 .config_props = config_props,
162151 .get_video_buffer = ff_null_get_video_buffer,
163− .start_frame = ff_null_start_frame,
164− .draw_slice = draw_slice,
165− .end_frame = end_frame,
152+ .filter_frame = filter_frame,
166153 .min_perms = AV_PERM_READ | AV_PERM_WRITE,
167154 .rej_perms = AV_PERM_PRESERVE,
168155 },
libavfilter/vf_fieldorder.c+27−87
@@ -121,90 +121,39 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int · 120 unmodified lines
121121 return ff_get_video_buffer(outlink, perms, w, h);
122122 }
123123
124−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
124+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
125125 {
126− AVFilterContext *ctx = inlink->dst;
127− AVFilterLink *outlink = ctx->outputs[0];
128−
129− AVFilterBufferRef *outpicref, *for_next_filter;
130− int ret = 0;
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;
126+ AVFilterContext *ctx = inlink->dst;
127+ FieldOrderContext *s = ctx->priv;
128+ AVFilterLink *outlink = ctx->outputs[0];
129+ int h, plane, line_step, line_size, line;
130+ uint8_t *data;
159131
160− /** can only currently do slices if this filter is doing nothing
161− * because this filter is moving picture content, the output
162− * slice will contain different video lines than the input slice
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−}
132+ if (!frame->video->interlaced ||
133+ frame->video->top_field_first == s->dst_tff)
134+ return ff_filter_frame(outlink, frame);
170135
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) {
185136 av_dlog(ctx,
186137 "picture will move %s one line\n",
187− fieldorder->dst_tff ? "up" : "down");
188− h = inpicref->video->h;
189− for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) {
190− line_step = inpicref->linesize[plane];
191− line_size = fieldorder->line_size[plane];
192− cpy_src = inpicref->data[plane];
193− cpy_dst = outpicref->data[plane];
194− if (fieldorder->dst_tff) {
138+ s->dst_tff ? "up" : "down");
139+ h = frame->video->h;
140+ for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
141+ line_step = frame->linesize[plane];
142+ line_size = s->line_size[plane];
143+ data = frame->data[plane];
144+ if (s->dst_tff) {
195145 /** Move every line up one line, working from
196146 * the top to the bottom of the frame.
197147 * The original top line is lost.
198148 * The new last line is created as a copy of the
199149 * penultimate line from that field. */
200150 for (line = 0; line < h; line++) {
201− if (1 + line < outpicref->video->h) {
202− memcpy(cpy_dst, cpy_src + line_step, line_size);
151+ if (1 + line < frame->video->h) {
152+ memcpy(data, data + line_step, line_size);
203153 } else {
204− memcpy(cpy_dst, cpy_src - line_step - line_step, line_size);
154+ memcpy(data, data - line_step - line_step, line_size);
205155 }
206− cpy_src += line_step;
207− cpy_dst += line_step;
156+ data += line_step;
208157 }
209158 } else {
210159 /** Move every line down one line, working from
@@ -212,27 +161,20 @@ static int end_frame(AVFilterLink *inlink) · 1 unmodified line
212161 * The original bottom line is lost.
213162 * The new first line is created as a copy of the
214163 * second line from that field. */
215− cpy_src += (h - 1) * line_step;
216− cpy_dst += (h - 1) * line_step;
164+ data += (h - 1) * line_step;
217165 for (line = h - 1; line >= 0 ; line--) {
218166 if (line > 0) {
219− memcpy(cpy_dst, cpy_src - line_step, line_size);
167+ memcpy(data, data - line_step, line_size);
220168 } else {
221− memcpy(cpy_dst, cpy_src + line_step + line_step, line_size);
169+ memcpy(data, data + line_step + line_step, line_size);
222170 }
223− cpy_src -= line_step;
224− cpy_dst -= line_step;
171+ data -= line_step;
225172 }
226173 }
227174 }
228− outpicref->video->top_field_first = fieldorder->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− }
175+ frame->video->top_field_first = s->dst_tff;
234176
235− return ff_end_frame(outlink);
177+ return ff_filter_frame(outlink, frame);
236178 }
237179
238180 static const AVFilterPad avfilter_vf_fieldorder_inputs[] = {
@@ -240,10 +182,8 @@ static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { · 1 unmodified line
240182 .name = "default",
241183 .type = AVMEDIA_TYPE_VIDEO,
242184 .config_props = config_input,
243− .start_frame = start_frame,
244185 .get_video_buffer = get_video_buffer,
245− .draw_slice = draw_slice,
246− .end_frame = end_frame,
186+ .filter_frame = filter_frame,
247187 .min_perms = AV_PERM_READ,
248188 .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE,
249189 },
libavfilter/vf_format.c+0−6
@@ -104,9 +104,6 @@ static const AVFilterPad avfilter_vf_format_inputs[] = { · 103 unmodified lines
104104 .name = "default",
105105 .type = AVMEDIA_TYPE_VIDEO,
106106 .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,
110107 },
111108 { NULL }
112109 };
@@ -146,9 +143,6 @@ static const AVFilterPad avfilter_vf_noformat_inputs[] = { · 33 unmodified lines
146143 .name = "default",
147144 .type = AVMEDIA_TYPE_VIDEO,
148145 .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,
152146 },
153147 { NULL }
154148 };
libavfilter/vf_fps.c+4−22
@@ -144,9 +144,7 @@ static int request_frame(AVFilterLink *outlink) · 143 unmodified lines
144144 buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
145145 outlink->time_base) + s->frames_out;
146146
147− if ((ret = ff_start_frame(outlink, buf)) < 0 ||
148− (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
149− (ret = ff_end_frame(outlink)) < 0)
147+ if ((ret = ff_filter_frame(outlink, buf)) < 0)
150148 return ret;
151149
152150 s->frames_out++;
@@ -171,16 +169,14 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFilterBufferRef *buf) · 18 unmodified lines
171169 return 0;
172170 }
173171
174−static int end_frame(AVFilterLink *inlink)
172+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
175173 {
176174 AVFilterContext *ctx = inlink->dst;
177175 FPSContext *s = ctx->priv;
178176 AVFilterLink *outlink = ctx->outputs[0];
179− AVFilterBufferRef *buf = inlink->cur_buf;
180177 int64_t delta;
181178 int i, ret;
182179
183− inlink->cur_buf = NULL;
184180 s->frames_in++;
185181 /* discard frames until we get the first timestamp */
186182 if (s->pts == AV_NOPTS_VALUE) {
@@ -251,9 +247,7 @@ static int end_frame(AVFilterLink *inlink) · 64 unmodified lines
251247 buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
252248 outlink->time_base) + s->frames_out;
253249
254− if ((ret = ff_start_frame(outlink, buf_out)) < 0 ||
255− (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
256− (ret = ff_end_frame(outlink)) < 0) {
250+ if ((ret = ff_filter_frame(outlink, buf_out)) < 0) {
257251 avfilter_unref_bufferp(&buf);
258252 return ret;
259253 }
@@ -268,23 +262,11 @@ static int end_frame(AVFilterLink *inlink) · 8 unmodified lines
268262 return ret;
269263 }
270264
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−
281265 static const AVFilterPad avfilter_vf_fps_inputs[] = {
282266 {
283267 .name = "default",
284268 .type = AVMEDIA_TYPE_VIDEO,
285− .start_frame = null_start_frame,
286− .draw_slice = null_draw_slice,
287− .end_frame = end_frame,
269+ .filter_frame = filter_frame,
288270 },
289271 { NULL }
290272 };
libavfilter/vf_frei0r.c+19−40
@@ -346,35 +346,34 @@ static int query_formats(AVFilterContext *ctx) · 345 unmodified lines
346346 return 0;
347347 }
348348
349−static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
350−{
351− return 0;
352−}
353−
354−static int end_frame(AVFilterLink *inlink)
349+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
355350 {
356351 Frei0rContext *frei0r = inlink->dst->priv;
357352 AVFilterLink *outlink = inlink->dst->outputs[0];
358− AVFilterBufferRef *inpicref = inlink->cur_buf;
359− AVFilterBufferRef *outpicref = outlink->out_buf;
360− int ret;
361−
362− frei0r->update(frei0r->instance, inpicref->pts * av_q2d(inlink->time_base) * 1000,
363− (const uint32_t *)inpicref->data[0],
364− (uint32_t *)outpicref->data[0]);
365− if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) ||
366− (ret = ff_end_frame(outlink)) < 0)
367− return ret;
368− return 0;
353+ AVFilterBufferRef *out;
354+
355+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
356+ if (!out) {
357+ avfilter_unref_bufferp(&in);
358+ return AVERROR(ENOMEM);
359+ }
360+ avfilter_copy_buffer_ref_props(out, in);
361+
362+ frei0r->update(frei0r->instance, in->pts * av_q2d(inlink->time_base) * 1000,
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);
369369 }
370370
371371 static const AVFilterPad avfilter_vf_frei0r_inputs[] = {
372372 {
373373 .name = "default",
374374 .type = AVMEDIA_TYPE_VIDEO,
375− .draw_slice = null_draw_slice,
376375 .config_props = config_input_props,
377− .end_frame = end_frame,
376+ .filter_frame = filter_frame,
378377 .min_perms = AV_PERM_READ
379378 },
380379 { NULL }
@@ -456,8 +455,6 @@ static int source_request_frame(AVFilterLink *outlink) · 75 unmodified lines
456455 {
457456 Frei0rContext *frei0r = outlink->src->priv;
458457 AVFilterBufferRef *picref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
459− AVFilterBufferRef *buf_out;
460− int ret;
461458
462459 if (!picref)
463460 return AVERROR(ENOMEM);
@@ -466,28 +463,10 @@ static int source_request_frame(AVFilterLink *outlink) · 2 unmodified lines
466463 picref->pts = frei0r->pts++;
467464 picref->pos = -1;
468465
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−
479466 frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}),
480467 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);
489468
490− return ret;
469+ return ff_filter_frame(outlink, picref);
491470 }
492471
493472 static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = {
libavfilter/vf_gradfun.c+27−20
@@ -182,20 +182,29 @@ static int config_input(AVFilterLink *inlink) · 181 unmodified lines
182182 return 0;
183183 }
184184
185−static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
186−{
187− return 0;
188−}
189−
190−static int end_frame(AVFilterLink *inlink)
185+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
191186 {
192187 GradFunContext *gf = inlink->dst->priv;
193− AVFilterBufferRef *inpic = inlink->cur_buf;
194188 AVFilterLink *outlink = inlink->dst->outputs[0];
195− AVFilterBufferRef *outpic = outlink->out_buf;
196− int p, ret;
189+ AVFilterBufferRef *out;
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+ }
197206
198− for (p = 0; p < 4 && inpic->data[p]; p++) {
207+ for (p = 0; p < 4 && in->data[p]; p++) {
199208 int w = inlink->w;
200209 int h = inlink->h;
201210 int r = gf->radius;
@@ -206,15 +215,15 @@ static int end_frame(AVFilterLink *inlink) · 4 unmodified lines
206215 }
207216
208217 if (FFMIN(w, h) > 2 * r)
209− filter(gf, outpic->data[p], inpic->data[p], w, h, outpic->linesize[p], inpic->linesize[p], r);
210− else if (outpic->data[p] != inpic->data[p])
211− av_image_copy_plane(outpic->data[p], outpic->linesize[p], inpic->data[p], inpic->linesize[p], w, h);
218+ filter(gf, out->data[p], in->data[p], w, h, out->linesize[p], in->linesize[p], r);
219+ else if (out->data[p] != in->data[p])
220+ av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], w, h);
212221 }
213222
214− if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 ||
215− (ret = ff_end_frame(outlink)) < 0)
216− return ret;
217− return 0;
223+ if (!direct)
224+ avfilter_unref_bufferp(&in);
225+
226+ return ff_filter_frame(outlink, out);
218227 }
219228
220229 static const AVFilterPad avfilter_vf_gradfun_inputs[] = {
@@ -222,9 +231,7 @@ static const AVFilterPad avfilter_vf_gradfun_inputs[] = { · 1 unmodified line
222231 .name = "default",
223232 .type = AVMEDIA_TYPE_VIDEO,
224233 .config_props = config_input,
225− .start_frame = ff_inplace_start_frame,
226− .draw_slice = null_draw_slice,
227− .end_frame = end_frame,
234+ .filter_frame = filter_frame,
228235 .min_perms = AV_PERM_READ,
229236 },
230237 { NULL }
libavfilter/vf_hflip.c+21−12
@@ -84,22 +84,30 @@ static int config_props(AVFilterLink *inlink) · 83 unmodified lines
8484 return 0;
8585 }
8686
87−static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
87+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
8888 {
89− FlipContext *flip = inlink->dst->priv;
90− AVFilterBufferRef *inpic = inlink->cur_buf;
91− AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf;
89+ AVFilterContext *ctx = inlink->dst;
90+ FlipContext *flip = ctx->priv;
91+ AVFilterLink *outlink = ctx->outputs[0];
92+ AVFilterBufferRef *out;
9293 uint8_t *inrow, *outrow;
9394 int i, j, plane, step, hsub, vsub;
9495
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++) {
96104 step = flip->max_step[plane];
97105 hsub = (plane == 1 || plane == 2) ? flip->hsub : 0;
98106 vsub = (plane == 1 || plane == 2) ? flip->vsub : 0;
99107
100− outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane];
101− inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane] + ((inlink->w >> hsub) - 1) * step;
102− for (i = 0; i < h>>vsub; i++) {
108+ outrow = out->data[plane];
109+ inrow = in ->data[plane] + ((inlink->w >> hsub) - 1) * step;
110+ for (i = 0; i < in->video->h >> vsub; i++) {
103111 switch (step) {
104112 case 1:
105113 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
140148 memcpy(outrow + j*step, inrow - j*step, step);
141149 }
142150
143− inrow += inpic ->linesize[plane];
144− outrow += outpic->linesize[plane];
151+ inrow += in ->linesize[plane];
152+ outrow += out->linesize[plane];
145153 }
146154 }
147155
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);
149158 }
150159
151160 static const AVFilterPad avfilter_vf_hflip_inputs[] = {
152161 {
153162 .name = "default",
154163 .type = AVMEDIA_TYPE_VIDEO,
155− .draw_slice = draw_slice,
164+ .filter_frame = filter_frame,
156165 .config_props = config_props,
157166 .min_perms = AV_PERM_READ,
158167 },
libavfilter/vf_hqdn3d.c+27−20
@@ -322,42 +322,49 @@ static int config_input(AVFilterLink *inlink) · 321 unmodified lines
322322 return 0;
323323 }
324324
325−static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
326−{
327− return 0;
328−}
329−
330−static int end_frame(AVFilterLink *inlink)
325+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
331326 {
332327 HQDN3DContext *hqdn3d = inlink->dst->priv;
333328 AVFilterLink *outlink = inlink->dst->outputs[0];
334− AVFilterBufferRef *inpic = inlink ->cur_buf;
335− AVFilterBufferRef *outpic = outlink->out_buf;
336− int ret, c;
329+ AVFilterBufferRef *out;
330+ int direct, 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+ }
337346
338347 for (c = 0; c < 3; c++) {
339− denoise(hqdn3d, inpic->data[c], outpic->data[c],
348+ denoise(hqdn3d, in->data[c], out->data[c],
340349 hqdn3d->line, &hqdn3d->frame_prev[c],
341− inpic->video->w >> (!!c * hqdn3d->hsub),
342− inpic->video->h >> (!!c * hqdn3d->vsub),
343− inpic->linesize[c], outpic->linesize[c],
350+ in->video->w >> (!!c * hqdn3d->hsub),
351+ in->video->h >> (!!c * hqdn3d->vsub),
352+ in->linesize[c], out->linesize[c],
344353 hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]);
345354 }
346355
347− if ((ret = ff_draw_slice(outlink, 0, inpic->video->h, 1)) < 0 ||
348− (ret = ff_end_frame(outlink)) < 0)
349− return ret;
350− return 0;
356+ if (!direct)
357+ avfilter_unref_bufferp(&in);
358+
359+ return ff_filter_frame(outlink, out);
351360 }
352361
353362 static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = {
354363 {
355364 .name = "default",
356365 .type = AVMEDIA_TYPE_VIDEO,
357− .start_frame = ff_inplace_start_frame,
358− .draw_slice = null_draw_slice,
359366 .config_props = config_input,
360− .end_frame = end_frame
367+ .filter_frame = filter_frame,
361368 },
362369 { NULL }
363370 };
libavfilter/vf_libopencv.c+17−18
@@ -32,6 +32,7 @@ · 31 unmodified lines
3232 #include "libavutil/file.h"
3333 #include "avfilter.h"
3434 #include "formats.h"
35+#include "internal.h"
3536 #include "video.h"
3637
3738 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
6869 return 0;
6970 }
7071
71−static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
72−{
73− return 0;
74−}
75−
7672 typedef struct {
7773 const char *name;
7874 int (*init)(AVFilterContext *ctx, const char *args);
@@ -355,33 +351,36 @@ static av_cold void uninit(AVFilterContext *ctx) · 276 unmodified lines
355351 memset(ocv, 0, sizeof(*ocv));
356352 }
357353
358−static int end_frame(AVFilterLink *inlink)
354+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
359355 {
360356 AVFilterContext *ctx = inlink->dst;
361357 OCVContext *ocv = ctx->priv;
362358 AVFilterLink *outlink= inlink->dst->outputs[0];
363− AVFilterBufferRef *inpicref = inlink ->cur_buf;
364− AVFilterBufferRef *outpicref = outlink->out_buf;
359+ AVFilterBufferRef *out;
365360 IplImage inimg, outimg;
366− int ret;
367361
368− fill_iplimage_from_picref(&inimg , inpicref , inlink->format);
369− fill_iplimage_from_picref(&outimg, outpicref, inlink->format);
362+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
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);
370371 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);
372373
373− if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
374− (ret = ff_end_frame(outlink)) < 0)
375− return ret;
376− return 0;
374+ avfilter_unref_bufferp(&in);
375+
376+ return ff_filter_frame(outlink, out);
377377 }
378378
379379 static const AVFilterPad avfilter_vf_ocv_inputs[] = {
380380 {
381381 .name = "default",
382382 .type = AVMEDIA_TYPE_VIDEO,
383− .draw_slice = null_draw_slice,
384− .end_frame = end_frame,
383+ .filter_frame = filter_frame,
385384 .min_perms = AV_PERM_READ
386385 },
387386 { NULL }
libavfilter/vf_lut.c+23−16
@@ -295,22 +295,28 @@ static int config_props(AVFilterLink *inlink) · 294 unmodified lines
295295 return 0;
296296 }
297297
298−static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
298+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
299299 {
300300 AVFilterContext *ctx = inlink->dst;
301301 LutContext *lut = ctx->priv;
302302 AVFilterLink *outlink = ctx->outputs[0];
303− AVFilterBufferRef *inpic = inlink ->cur_buf;
304− AVFilterBufferRef *outpic = outlink->out_buf;
303+ AVFilterBufferRef *out;
305304 uint8_t *inrow, *outrow, *inrow0, *outrow0;
306305 int i, j, k, plane;
307306
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+
308314 if (lut->is_rgb) {
309315 /* packed */
310− inrow0 = inpic ->data[0] + y * inpic ->linesize[0];
311− outrow0 = outpic->data[0] + y * outpic->linesize[0];
316+ inrow0 = in ->data[0];
317+ outrow0 = out->data[0];
312318
313− for (i = 0; i < h; i ++) {
319+ for (i = 0; i < in->video->h; i ++) {
314320 inrow = inrow0;
315321 outrow = outrow0;
316322 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
319325 outrow += lut->step;
320326 inrow += lut->step;
321327 }
322− inrow0 += inpic ->linesize[0];
323− outrow0 += outpic->linesize[0];
328+ inrow0 += in ->linesize[0];
329+ outrow0 += out->linesize[0];
324330 }
325331 } else {
326332 /* planar */
327− for (plane = 0; plane < 4 && inpic->data[plane]; plane++) {
333+ for (plane = 0; plane < 4 && in->data[plane]; plane++) {
328334 int vsub = plane == 1 || plane == 2 ? lut->vsub : 0;
329335 int hsub = plane == 1 || plane == 2 ? lut->hsub : 0;
330336
331− inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane];
332− outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane];
337+ inrow = in ->data[plane];
338+ outrow = out->data[plane];
333339
334− for (i = 0; i < h>>vsub; i ++) {
340+ for (i = 0; i < in->video->h >> vsub; i ++) {
335341 for (j = 0; j < inlink->w>>hsub; j++)
336342 outrow[j] = lut->lut[plane][inrow[j]];
337− inrow += inpic ->linesize[plane];
338− outrow += outpic->linesize[plane];
343+ inrow += in ->linesize[plane];
344+ outrow += out->linesize[plane];
339345 }
340346 }
341347 }
342348
343− return ff_draw_slice(outlink, y, h, slice_dir);
349+ avfilter_unref_bufferp(&in);
350+ return ff_filter_frame(outlink, out);
344351 }
345352
346353 static const AVFilterPad inputs[] = {
347354 { .name = "default",
348355 .type = AVMEDIA_TYPE_VIDEO,
349− .draw_slice = draw_slice,
356+ .filter_frame = filter_frame,
350357 .config_props = config_props,
351358 .min_perms = AV_PERM_READ, },
352359 { .name = NULL}
libavfilter/vf_null.c+0−2
@@ -31,8 +31,6 @@ static const AVFilterPad avfilter_vf_null_inputs[] = { · 30 unmodified lines
3131 .name = "default",
3232 .type = AVMEDIA_TYPE_VIDEO,
3333 .get_video_buffer = ff_null_get_video_buffer,
34− .start_frame = ff_null_start_frame,
35− .end_frame = ff_null_end_frame
3634 },
3735 { NULL }
3836 };
libavfilter/vf_overlay.c+7−27
@@ -269,34 +269,22 @@ static void blend_frame(AVFilterContext *ctx, · 268 unmodified lines
269269 }
270270 }
271271
272−static int null_start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
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)
272+static int filter_frame_main(AVFilterLink *inlink, AVFilterBufferRef *frame)
283273 {
284274 OverlayContext *s = inlink->dst->priv;
285275
286276 av_assert0(!s->main);
287− s->main = inlink->cur_buf;
288− inlink->cur_buf = NULL;
277+ s->main = frame;
289278
290279 return 0;
291280 }
292281
293−static int end_frame_overlay(AVFilterLink *inlink)
282+static int filter_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *frame)
294283 {
295284 OverlayContext *s = inlink->dst->priv;
296285
297286 av_assert0(!s->over_next);
298− s->over_next = inlink->cur_buf;
299− inlink->cur_buf = NULL;
287+ s->over_next = frame;
300288
301289 return 0;
302290 }
@@ -305,11 +293,7 @@ static int output_frame(AVFilterContext *ctx) · 2 unmodified lines
305293 {
306294 OverlayContext *s = ctx->priv;
307295 AVFilterLink *outlink = ctx->outputs[0];
308− int ret = ff_start_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);
296+ int ret = ff_filter_frame(outlink, s->main);
313297 s->main = NULL;
314298
315299 return ret;
@@ -378,10 +362,8 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { · 62 unmodified lines
378362 {
379363 .name = "main",
380364 .type = AVMEDIA_TYPE_VIDEO,
381− .start_frame = null_start_frame,
382365 .config_props = config_input_main,
383− .draw_slice = null_draw_slice,
384− .end_frame = end_frame_main,
366+ .filter_frame = filter_frame_main,
385367 .min_perms = AV_PERM_READ,
386368 .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE,
387369 .needs_fifo = 1,
@@ -389,10 +371,8 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { · 1 unmodified line
389371 {
390372 .name = "overlay",
391373 .type = AVMEDIA_TYPE_VIDEO,
392− .start_frame = null_start_frame,
393374 .config_props = config_input_overlay,
394− .draw_slice = null_draw_slice,
395− .end_frame = end_frame_overlay,
375+ .filter_frame = filter_frame_overlay,
396376 .min_perms = AV_PERM_READ,
397377 .rej_perms = AV_PERM_REUSE2,
398378 .needs_fifo = 1,
libavfilter/vf_pad.c+49−102
@@ -106,7 +106,6 @@ typedef struct { · 105 unmodified lines
106106 uint8_t *line[4];
107107 int line_step[4];
108108 int hsub, vsub; ///< chroma subsampling values
109− int needs_copy;
110109 } PadContext;
111110
112111 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
303302 return 0;
304303 }
305304
306−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
305+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
307306 {
308307 PadContext *pad = inlink->dst->priv;
309− AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
310− AVFilterBufferRef *for_next_filter;
311− int plane, ret = 0;
308+ AVFilterBufferRef *out = avfilter_ref_buffer(in, ~0);
309+ int plane, needs_copy;
312310
313− if (!outpicref)
311+ if (!out) {
312+ avfilter_unref_bufferp(&in);
314313 return AVERROR(ENOMEM);
314+ }
315315
316− for (plane = 0; plane < 4 && outpicref->data[plane]; plane++) {
316+ for (plane = 0; plane < 4 && out->data[plane]; plane++) {
317317 int hsub = (plane == 1 || plane == 2) ? pad->hsub : 0;
318318 int vsub = (plane == 1 || plane == 2) ? pad->vsub : 0;
319319
320− av_assert0(outpicref->buf->w>0 && outpicref->buf->h>0);
320+ av_assert0(out->buf->w > 0 && out->buf->h > 0);
321321
322− if(outpicref->format != outpicref->buf->format) //unsupported currently
322+ if (out->format != out->buf->format) //unsupported currently
323323 break;
324324
325− outpicref->data[plane] -= (pad->x >> hsub) * pad ->line_step[plane]
326− + (pad->y >> vsub) * outpicref->linesize [plane];
325+ out->data[plane] -= (pad->x >> hsub) * pad->line_step[plane] +
326+ (pad->y >> vsub) * out->linesize [plane];
327327
328− if( does_clip(pad, outpicref, plane, hsub, vsub, 0, 0)
329− || does_clip(pad, outpicref, plane, hsub, vsub, 0, pad->h-1)
330− || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, 0)
331− || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, pad->h-1)
332− )
328+ if (does_clip(pad, out, plane, hsub, vsub, 0, 0) ||
329+ does_clip(pad, out, plane, hsub, vsub, 0, pad->h - 1) ||
330+ does_clip(pad, out, plane, hsub, vsub, pad->w - 1, 0) ||
331+ does_clip(pad, out, plane, hsub, vsub, pad->w - 1, pad->h - 1))
333332 break;
334333 }
335− pad->needs_copy= plane < 4 && outpicref->data[plane];
336− if(pad->needs_copy){
334+ needs_copy = plane < 4 && out->data[plane];
335+ if (needs_copy) {
337336 av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n");
338− avfilter_unref_buffer(outpicref);
339− outpicref = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
340− FFMAX(inlink->w, pad->w),
341− FFMAX(inlink->h, pad->h));
342− if (!outpicref)
337+ avfilter_unref_buffer(out);
338+ out = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
339+ FFMAX(inlink->w, pad->w),
340+ FFMAX(inlink->h, pad->h));
341+ if (!out) {
342+ avfilter_unref_bufferp(&in);
343343 return AVERROR(ENOMEM);
344+ }
344345
345− avfilter_copy_buffer_ref_props(outpicref, inpicref);
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;
346+ avfilter_copy_buffer_ref_props(out, in);
355347 }
356348
357− ret = ff_start_frame(inlink->dst->outputs[0], for_next_filter);
358− if (ret < 0)
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−}
349+ out->video->w = pad->w;
350+ out->video->h = pad->h;
373351
374−static int draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, int before_slice)
375−{
376− PadContext *pad = link->dst->priv;
377− int bar_y, bar_h = 0, ret = 0;
378−
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;
352+ /* top bar */
353+ if (pad->y) {
354+ ff_draw_rectangle(out->data, out->linesize,
355+ pad->line, pad->line_step, pad->hsub, pad->vsub,
356+ 0, 0, pad->w, pad->y);
387357 }
388358
389− if (bar_h) {
390− ff_draw_rectangle(link->dst->outputs[0]->out_buf->data,
391− link->dst->outputs[0]->out_buf->linesize,
359+ /* bottom bar */
360+ if (pad->h > pad->y + pad->in_h) {
361+ ff_draw_rectangle(out->data, out->linesize,
392362 pad->line, pad->line_step, pad->hsub, pad->vsub,
393− 0, bar_y, pad->w, bar_h);
394− ret = ff_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir);
363+ 0, pad->y + pad->in_h, pad->w, pad->h - pad->y - pad->in_h);
395364 }
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);
414365
415366 /* left border */
416− ff_draw_rectangle(outpic->data, outpic->linesize, pad->line, pad->line_step,
417− pad->hsub, pad->vsub, 0, y, pad->x, h);
418−
419− if(pad->needs_copy){
420− ff_copy_rectangle(outpic->data, outpic->linesize,
421− inpic->data, inpic->linesize, pad->line_step,
422− pad->hsub, pad->vsub,
423− pad->x, y, y-pad->y, inpic->video->w, h);
367+ ff_draw_rectangle(out->data, out->linesize, pad->line, pad->line_step,
368+ pad->hsub, pad->vsub, 0, pad->y, pad->x, in->video->h);
369+
370+ if (needs_copy) {
371+ ff_copy_rectangle(out->data, out->linesize, in->data, in->linesize,
372+ pad->line_step, pad->hsub, pad->vsub,
373+ pad->x, pad->y, 0, in->video->w, in->video->h);
424374 }
425375
426376 /* right border */
427− ff_draw_rectangle(outpic->data, outpic->linesize,
377+ ff_draw_rectangle(out->data, out->linesize,
428378 pad->line, pad->line_step, pad->hsub, pad->vsub,
429− pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h);
430− ret = ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
431− if (ret < 0)
432− return ret;
379+ pad->x + pad->in_w, pad->y, pad->w - pad->x - pad->in_w,
380+ in->video->h);
433381
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);
435384 }
436385
437386 static const AVFilterPad avfilter_vf_pad_inputs[] = {
@@ -440,9 +389,7 @@ static const AVFilterPad avfilter_vf_pad_inputs[] = { · 2 unmodified lines
440389 .type = AVMEDIA_TYPE_VIDEO,
441390 .config_props = config_input,
442391 .get_video_buffer = get_video_buffer,
443− .start_frame = start_frame,
444− .draw_slice = draw_slice,
445− .end_frame = end_frame,
392+ .filter_frame = filter_frame,
446393 },
447394 { NULL }
448395 };
libavfilter/vf_pixdesctest.c+22−43
@@ -52,86 +52,65 @@ static int config_props(AVFilterLink *inlink) · 51 unmodified lines
5252 return 0;
5353 }
5454
55−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
55+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
5656 {
5757 PixdescTestContext *priv = inlink->dst->priv;
5858 AVFilterLink *outlink = inlink->dst->outputs[0];
59− AVFilterBufferRef *outpicref, *for_next_filter;
60− int i, ret = 0;
59+ AVFilterBufferRef *out;
60+ int i, c, w = inlink->w, h = inlink->h;
6161
62− outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE,
63− outlink->w, outlink->h);
64− if (!outpicref)
62+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE,
63+ outlink->w, outlink->h);
64+ if (!out) {
65+ avfilter_unref_bufferp(&in);
6566 return AVERROR(ENOMEM);
67+ }
6668
67− avfilter_copy_buffer_ref_props(outpicref, picref);
69+ avfilter_copy_buffer_ref_props(out, in);
6870
6971 for (i = 0; i < 4; i++) {
7072 int h = outlink->h;
7173 h = i == 1 || i == 2 ? h>>priv->pix_desc->log2_chroma_h : h;
72− if (outpicref->data[i]) {
73− uint8_t *data = outpicref->data[i] +
74− (outpicref->linesize[i] > 0 ? 0 : outpicref->linesize[i] * (h-1));
75− memset(data, 0, FFABS(outpicref->linesize[i]) * h);
74+ if (out->data[i]) {
75+ uint8_t *data = out->data[i] +
76+ (out->linesize[i] > 0 ? 0 : out->linesize[i] * (h-1));
77+ memset(data, 0, FFABS(out->linesize[i]) * h);
7678 }
7779 }
7880
7981 /* copy palette */
8082 if (priv->pix_desc->flags & PIX_FMT_PAL ||
8183 priv->pix_desc->flags & PIX_FMT_PSEUDOPAL)
82− memcpy(outpicref->data[1], outpicref->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;
84+ memcpy(out->data[1], in->data[1], 256*4);
10585
10686 for (c = 0; c < priv->pix_desc->nb_components; c++) {
10787 int w1 = c == 1 || c == 2 ? w>>priv->pix_desc->log2_chroma_w : w;
10888 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;
11089
111− for (i = y1; i < y1 + h1; i++) {
90+ for (i = 0; i < h1; i++) {
11291 av_read_image_line(priv->line,
113− inpic->data,
114− inpic->linesize,
92+ in->data,
93+ in->linesize,
11594 priv->pix_desc,
11695 0, i, c, w1, 0);
11796
11897 av_write_image_line(priv->line,
119− outpic->data,
120− outpic->linesize,
98+ out->data,
99+ out->linesize,
121100 priv->pix_desc,
122101 0, i, c, w1);
123102 }
124103 }
125104
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);
127107 }
128108
129109 static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = {
130110 {
131111 .name = "default",
132112 .type = AVMEDIA_TYPE_VIDEO,
133− .start_frame = start_frame,
134− .draw_slice = draw_slice,
113+ .filter_frame = filter_frame,
135114 .config_props = config_props,
136115 .min_perms = AV_PERM_READ,
137116 },
libavfilter/vf_scale.c+19−66
@@ -257,93 +257,46 @@ fail: · 256 unmodified lines
257257 return ret;
258258 }
259259
260−static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
260+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in)
261261 {
262262 ScaleContext *scale = link->dst->priv;
263263 AVFilterLink *outlink = link->dst->outputs[0];
264− AVFilterBufferRef *outpicref, *for_next_filter;
264+ AVFilterBufferRef *out;
265265 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
266− int ret = 0;
267266
268− if (!scale->sws) {
269− outpicref = avfilter_ref_buffer(picref, ~0);
270− if (!outpicref)
271− return AVERROR(ENOMEM);
272− return ff_start_frame(outlink, outpicref);
273− }
267+ if (!scale->sws)
268+ return ff_filter_frame(outlink, in);
274269
275270 scale->hsub = desc->log2_chroma_w;
276271 scale->vsub = desc->log2_chroma_h;
277272
278− outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
279− if (!outpicref)
273+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
274+ if (!out) {
275+ avfilter_unref_bufferp(&in);
280276 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;
302277 }
303278
304− outlink->out_buf = outpicref;
305− return 0;
306−}
279+ avfilter_copy_buffer_ref_props(out, in);
280+ out->video->w = outlink->w;
281+ out->video->h = outlink->h;
307282
308−static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
309−{
310− ScaleContext *scale = link->dst->priv;
311− int out_h, ret;
312− AVFilterBufferRef *cur_pic = link->cur_buf;
313− const uint8_t *data[4];
283+ av_reduce(&out->video->pixel_aspect.num, &out->video->pixel_aspect.den,
284+ (int64_t)in->video->pixel_aspect.num * outlink->h * link->w,
285+ (int64_t)in->video->pixel_aspect.den * outlink->w * link->h,
286+ INT_MAX);
314287
315− if (!scale->sws) {
316− return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
317− }
288+ sws_scale(scale->sws, in->data, in->linesize, 0, in->video->h,
289+ out->data, out->linesize);
318290
319− if (scale->slice_y == 0 && slice_dir == -1)
320− scale->slice_y = link->dst->outputs[0]->h;
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;
291+ avfilter_unref_bufferp(&in);
292+ return ff_filter_frame(outlink, out);
339293 }
340294
341295 static const AVFilterPad avfilter_vf_scale_inputs[] = {
342296 {
343297 .name = "default",
344298 .type = AVMEDIA_TYPE_VIDEO,
345− .start_frame = start_frame,
346− .draw_slice = draw_slice,
299+ .filter_frame = filter_frame,
347300 .min_perms = AV_PERM_READ,
348301 },
349302 { NULL }
libavfilter/vf_select.c+11−41
@@ -228,50 +228,27 @@ static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref) · 227 unmodified lines
228228 return res;
229229 }
230230
231−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
231+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
232232 {
233233 SelectContext *select = inlink->dst->priv;
234234
235− select->select = select_frame(inlink->dst, picref);
235+ select->select = select_frame(inlink->dst, frame);
236236 if (select->select) {
237− AVFilterBufferRef *buf_out;
238237 /* frame was requested through poll_frame */
239238 if (select->cache_frames) {
240− if (!av_fifo_space(select->pending_frames))
239+ if (!av_fifo_space(select->pending_frames)) {
241240 av_log(inlink->dst, AV_LOG_ERROR,
242241 "Buffering limit reached, cannot cache more frames\n");
243− else
244− av_fifo_generic_write(select->pending_frames, &picref,
245− sizeof(picref), NULL);
242+ avfilter_unref_bufferp(&frame);
243+ } else
244+ av_fifo_generic_write(select->pending_frames, &frame,
245+ sizeof(frame), NULL);
246246 return 0;
247247 }
248− buf_out = avfilter_ref_buffer(picref, ~0);
249− if (!buf_out)
250− return AVERROR(ENOMEM);
251− return ff_start_frame(inlink->dst->outputs[0], buf_out);
248+ return ff_filter_frame(inlink->dst->outputs[0], frame);
252249 }
253250
254− return 0;
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− }
251+ avfilter_unref_bufferp(&frame);
275252 return 0;
276253 }
277254
@@ -284,14 +261,9 @@ static int request_frame(AVFilterLink *outlink) · 6 unmodified lines
284261
285262 if (av_fifo_size(select->pending_frames)) {
286263 AVFilterBufferRef *picref;
287− int ret;
288264
289265 av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL);
290− if ((ret = ff_start_frame(outlink, picref)) < 0 ||
291− (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
292− (ret = ff_end_frame(outlink)) < 0);
293−
294− return ret;
266+ return ff_filter_frame(outlink, picref);
295267 }
296268
297269 while (!select->select) {
@@ -346,9 +318,7 @@ static const AVFilterPad avfilter_vf_select_inputs[] = { · 48 unmodified lines
346318 .type = AVMEDIA_TYPE_VIDEO,
347319 .get_video_buffer = ff_null_get_video_buffer,
348320 .config_props = config_input,
349− .start_frame = start_frame,
350− .draw_slice = draw_slice,
351− .end_frame = end_frame
321+ .filter_frame = filter_frame,
352322 },
353323 { NULL }
354324 };
libavfilter/vf_setpts.c+14−17
@@ -102,39 +102,36 @@ static int config_input(AVFilterLink *inlink) · 101 unmodified lines
102102 #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
103103 #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
104104
105−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
105+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
106106 {
107107 SetPTSContext *setpts = inlink->dst->priv;
108+ int64_t in_pts = frame->pts;
108109 double d;
109− AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
110−
111− if (!outpicref)
112− return AVERROR(ENOMEM);
113110
114111 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);
116113
117− setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced;
118− setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts);
119− setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos;
114+ setpts->var_values[VAR_INTERLACED] = frame->video->interlaced;
115+ setpts->var_values[VAR_PTS ] = TS2D(frame->pts);
116+ setpts->var_values[VAR_POS ] = frame->pos == -1 ? NAN : frame->pos;
120117
121118 d = av_expr_eval(setpts->expr, setpts->var_values, NULL);
122− outpicref->pts = D2TS(d);
119+ frame->pts = D2TS(d);
123120
124121 #ifdef DEBUG
125122 av_log(inlink->dst, AV_LOG_DEBUG,
126123 "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
127124 (int64_t)setpts->var_values[VAR_N],
128125 (int)setpts->var_values[VAR_INTERLACED],
129− inpicref ->pos,
130− inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base),
131− outpicref->pts, outpicref->pts * av_q2d(inlink->time_base));
126+ frame->pos, in_pts, in_pts * av_q2d(inlink->time_base),
127+ frame->pts, frame->pts * av_q2d(inlink->time_base));
132128 #endif
133129
130+
134131 setpts->var_values[VAR_N] += 1.0;
135− setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
136− setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
137− return ff_start_frame(inlink->dst->outputs[0], outpicref);
132+ setpts->var_values[VAR_PREV_INPTS ] = TS2D(in_pts);
133+ setpts->var_values[VAR_PREV_OUTPTS] = TS2D(frame->pts);
134+ return ff_filter_frame(inlink->dst->outputs[0], frame);
138135 }
139136
140137 static av_cold void uninit(AVFilterContext *ctx)
@@ -150,7 +147,7 @@ static const AVFilterPad avfilter_vf_setpts_inputs[] = { · 9 unmodified lines
150147 .type = AVMEDIA_TYPE_VIDEO,
151148 .get_video_buffer = ff_null_get_video_buffer,
152149 .config_props = config_input,
153− .start_frame = start_frame,
150+ .filter_frame = filter_frame,
154151 },
155152 { NULL }
156153 };
libavfilter/vf_settb.c+6−8
@@ -108,21 +108,20 @@ static int config_output_props(AVFilterLink *outlink) · 107 unmodified lines
108108 return 0;
109109 }
110110
111−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
111+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
112112 {
113113 AVFilterContext *ctx = inlink->dst;
114114 AVFilterLink *outlink = ctx->outputs[0];
115115
116116 if (av_cmp_q(inlink->time_base, outlink->time_base)) {
117− int64_t orig_pts = picref->pts;
118− picref->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->time_base);
117+ int64_t orig_pts = frame->pts;
118+ frame->pts = av_rescale_q(frame->pts, inlink->time_base, outlink->time_base);
119119 av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
120120 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);
122122 }
123− inlink->cur_buf = NULL;
124123
125− return ff_start_frame(outlink, picref);
124+ return ff_filter_frame(outlink, frame);
126125 }
127126
128127 static const AVFilterPad avfilter_vf_settb_inputs[] = {
@@ -130,8 +129,7 @@ static const AVFilterPad avfilter_vf_settb_inputs[] = { · 1 unmodified line
130129 .name = "default",
131130 .type = AVMEDIA_TYPE_VIDEO,
132131 .get_video_buffer = ff_null_get_video_buffer,
133− .start_frame = start_frame,
134− .end_frame = ff_null_end_frame
132+ .filter_frame = filter_frame,
135133 },
136134 { NULL }
137135 };
libavfilter/vf_showinfo.c+14−16
@@ -41,24 +41,23 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 40 unmodified lines
4141 return 0;
4242 }
4343
44−static int end_frame(AVFilterLink *inlink)
44+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
4545 {
4646 AVFilterContext *ctx = inlink->dst;
4747 ShowInfoContext *showinfo = ctx->priv;
48− AVFilterBufferRef *picref = inlink->cur_buf;
4948 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
5049 uint32_t plane_checksum[4] = {0}, checksum = 0;
5150 int i, plane, vsub = desc->log2_chroma_h;
5251
53− for (plane = 0; picref->data[plane] && plane < 4; plane++) {
54− size_t linesize = av_image_get_linesize(picref->format, picref->video->w, plane);
55− uint8_t *data = picref->data[plane];
52+ for (plane = 0; frame->data[plane] && plane < 4; plane++) {
53+ size_t linesize = av_image_get_linesize(frame->format, frame->video->w, plane);
54+ uint8_t *data = frame->data[plane];
5655 int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h;
5756
5857 for (i = 0; i < h; i++) {
5958 plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize);
6059 checksum = av_adler32_update(checksum, data, linesize);
61− data += picref->linesize[plane];
60+ data += frame->linesize[plane];
6261 }
6362 }
6463
@@ -67,18 +66,18 @@ static int end_frame(AVFilterLink *inlink) · 2 unmodified lines
6766 "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c "
6867 "checksum:%u plane_checksum:[%u %u %u %u]\n",
6968 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,
7170 desc->name,
72− picref->video->pixel_aspect.num, picref->video->pixel_aspect.den,
73− picref->video->w, picref->video->h,
74− !picref->video->interlaced ? 'P' : /* Progressive */
75− picref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */
76− picref->video->key_frame,
77− av_get_picture_type_char(picref->video->pict_type),
71+ frame->video->pixel_aspect.num, frame->video->pixel_aspect.den,
72+ frame->video->w, frame->video->h,
73+ !frame->video->interlaced ? 'P' : /* Progressive */
74+ frame->video->top_field_first ? 'T' : 'B', /* Top / Bottom */
75+ frame->video->key_frame,
76+ av_get_picture_type_char(frame->video->pict_type),
7877 checksum, plane_checksum[0], plane_checksum[1], plane_checksum[2], plane_checksum[3]);
7978
8079 showinfo->frame++;
81− return ff_end_frame(inlink->dst->outputs[0]);
80+ return ff_filter_frame(inlink->dst->outputs[0], frame);
8281 }
8382
8483 static const AVFilterPad avfilter_vf_showinfo_inputs[] = {
@@ -86,8 +85,7 @@ static const AVFilterPad avfilter_vf_showinfo_inputs[] = { · 1 unmodified line
8685 .name = "default",
8786 .type = AVMEDIA_TYPE_VIDEO,
8887 .get_video_buffer = ff_null_get_video_buffer,
89− .start_frame = ff_null_start_frame,
90− .end_frame = end_frame,
88+ .filter_frame = filter_frame,
9189 .min_perms = AV_PERM_READ,
9290 },
9391 { NULL }
libavfilter/vf_transpose.c+36−48
@@ -121,100 +121,88 @@ static int config_props_output(AVFilterLink *outlink) · 120 unmodified lines
121121 return 0;
122122 }
123123
124−static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
124+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
125125 {
126126 AVFilterLink *outlink = inlink->dst->outputs[0];
127− AVFilterBufferRef *buf_out;
127+ TransContext *trans = inlink->dst->priv;
128+ AVFilterBufferRef *out;
129+ int plane;
128130
129− outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE,
130− outlink->w, outlink->h);
131− if (!outlink->out_buf)
131+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
132+ if (!out) {
133+ avfilter_unref_bufferp(&in);
132134 return AVERROR(ENOMEM);
135+ }
133136
134− outlink->out_buf->pts = picref->pts;
137+ out->pts = in->pts;
135138
136− if (picref->video->pixel_aspect.num == 0) {
137− outlink->out_buf->video->pixel_aspect = picref->video->pixel_aspect;
139+ if (in->video->pixel_aspect.num == 0) {
140+ out->video->pixel_aspect = in->video->pixel_aspect;
138141 } else {
139− outlink->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den;
140− outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num;
142+ out->video->pixel_aspect.num = in->video->pixel_aspect.den;
143+ out->video->pixel_aspect.den = in->video->pixel_aspect.num;
141144 }
142145
143− buf_out = avfilter_ref_buffer(outlink->out_buf, ~0);
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++) {
146+ for (plane = 0; out->data[plane]; plane++) {
158147 int hsub = plane == 1 || plane == 2 ? trans->hsub : 0;
159148 int vsub = plane == 1 || plane == 2 ? trans->vsub : 0;
160149 int pixstep = trans->pixsteps[plane];
161− int inh = inpic->video->h>>vsub;
162− int outw = outpic->video->w>>hsub;
163− int outh = outpic->video->h>>vsub;
164− uint8_t *out, *in;
165− int outlinesize, inlinesize;
150+ int inh = in->video->h>>vsub;
151+ int outw = out->video->w>>hsub;
152+ int outh = out->video->h>>vsub;
153+ uint8_t *dst, *src;
154+ int dstlinesize, srclinesize;
166155 int x, y;
167156
168− out = outpic->data[plane]; outlinesize = outpic->linesize[plane];
169− in = inpic ->data[plane]; inlinesize = inpic ->linesize[plane];
157+ dst = out->data[plane];
158+ dstlinesize = out->linesize[plane];
159+ src = in->data[plane];
160+ srclinesize = in->linesize[plane];
170161
171162 if (trans->dir&1) {
172− in += inpic->linesize[plane] * (inh-1);
173− inlinesize *= -1;
163+ src += in->linesize[plane] * (inh-1);
164+ srclinesize *= -1;
174165 }
175166
176167 if (trans->dir&2) {
177− out += outpic->linesize[plane] * (outh-1);
178− outlinesize *= -1;
168+ dst += out->linesize[plane] * (outh-1);
169+ dstlinesize *= -1;
179170 }
180171
181172 for (y = 0; y < outh; y++) {
182173 switch (pixstep) {
183174 case 1:
184175 for (x = 0; x < outw; x++)
185− out[x] = in[x*inlinesize + y];
176+ dst[x] = src[x*srclinesize + y];
186177 break;
187178 case 2:
188179 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));
190181 break;
191182 case 3:
192183 for (x = 0; x < outw; x++) {
193− int32_t v = AV_RB24(in + x*inlinesize + y*3);
194− AV_WB24(out + 3*x, v);
184+ int32_t v = AV_RB24(src + x*srclinesize + y*3);
185+ AV_WB24(dst + 3*x, v);
195186 }
196187 break;
197188 case 4:
198189 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));
200191 break;
201192 }
202− out += outlinesize;
193+ dst += dstlinesize;
203194 }
204195 }
205196
206− if ((ret = ff_draw_slice(outlink, 0, outpic->video->h, 1)) < 0 ||
207− (ret = ff_end_frame(outlink)) < 0)
208− return ret;
209− return 0;
197+ avfilter_unref_bufferp(&in);
198+ return ff_filter_frame(outlink, out);
210199 }
211200
212201 static const AVFilterPad avfilter_vf_transpose_inputs[] = {
213202 {
214203 .name = "default",
215204 .type = AVMEDIA_TYPE_VIDEO,
216− .start_frame = start_frame,
217− .end_frame = end_frame,
205+ .filter_frame = filter_frame,
218206 .min_perms = AV_PERM_READ,
219207 },
220208 { NULL }
libavfilter/vf_unsharp.c+13−15
@@ -214,36 +214,34 @@ static av_cold void uninit(AVFilterContext *ctx) · 213 unmodified lines
214214 free_filter_param(&unsharp->chroma);
215215 }
216216
217−static int end_frame(AVFilterLink *link)
217+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in)
218218 {
219219 UnsharpContext *unsharp = link->dst->priv;
220− AVFilterBufferRef *in = link->cur_buf;
221− AVFilterBufferRef *out = link->dst->outputs[0]->out_buf;
220+ AVFilterLink *outlink = link->dst->outputs[0];
221+ AVFilterBufferRef *out;
222222 int cw = SHIFTUP(link->w, unsharp->hsub);
223223 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);
225231
226232 apply_unsharp(out->data[0], out->linesize[0], in->data[0], in->linesize[0], link->w, link->h, &unsharp->luma);
227233 apply_unsharp(out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, &unsharp->chroma);
228234 apply_unsharp(out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, &unsharp->chroma);
229235
230− if ((ret = ff_draw_slice(link->dst->outputs[0], 0, link->h, 1)) < 0 ||
231− (ret = ff_end_frame(link->dst->outputs[0])) < 0)
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;
236+ avfilter_unref_bufferp(&in);
237+ return ff_filter_frame(outlink, out);
239238 }
240239
241240 static const AVFilterPad avfilter_vf_unsharp_inputs[] = {
242241 {
243242 .name = "default",
244243 .type = AVMEDIA_TYPE_VIDEO,
245− .draw_slice = draw_slice,
246− .end_frame = end_frame,
244+ .filter_frame = filter_frame,
247245 .config_props = config_props,
248246 .min_perms = AV_PERM_READ,
249247 },
libavfilter/vf_vflip.c+6−19
@@ -69,41 +69,28 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, · 68 unmodified lines
6969 return picref;
7070 }
7171
72−static int start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref)
72+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
7373 {
7474 FlipContext *flip = link->dst->priv;
75− AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
7675 int i;
7776
78− if (!outpicref)
79− return AVERROR(ENOMEM);
80−
8177 for (i = 0; i < 4; i ++) {
8278 int vsub = i == 1 || i == 2 ? flip->vsub : 0;
8379
84− if (outpicref->data[i]) {
85− outpicref->data[i] += ((link->h >> vsub)-1) * outpicref->linesize[i];
86− outpicref->linesize[i] = -outpicref->linesize[i];
80+ if (frame->data[i]) {
81+ frame->data[i] += ((link->h >> vsub)-1) * frame->linesize[i];
82+ frame->linesize[i] = -frame->linesize[i];
8783 }
8884 }
8985
90− return ff_start_frame(link->dst->outputs[0], outpicref);
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);
86+ return ff_filter_frame(link->dst->outputs[0], frame);
9887 }
99−
10088 static const AVFilterPad avfilter_vf_vflip_inputs[] = {
10189 {
10290 .name = "default",
10391 .type = AVMEDIA_TYPE_VIDEO,
10492 .get_video_buffer = get_video_buffer,
105− .start_frame = start_frame,
106− .draw_slice = draw_slice,
93+ .filter_frame = filter_frame,
10794 .config_props = config_input,
10895 },
10996 { NULL }
libavfilter/vf_yadif.c+7−40
@@ -202,19 +202,14 @@ static int return_frame(AVFilterContext *ctx, int is_second) · 201 unmodified lines
202202 } else {
203203 yadif->out->pts = AV_NOPTS_VALUE;
204204 }
205− ret = ff_start_frame(ctx->outputs[0], yadif->out);
206− if (ret < 0)
207− return ret;
208205 }
209− if ((ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1)) < 0 ||
210− (ret = ff_end_frame(ctx->outputs[0])) < 0)
211− return ret;
206+ ret = ff_filter_frame(ctx->outputs[0], yadif->out);
212207
213208 yadif->frame_pending = (yadif->mode&1) && !is_second;
214− return 0;
209+ return ret;
215210 }
216211
217−static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
212+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *picref)
218213 {
219214 AVFilterContext *ctx = link->dst;
220215 YADIFContext *yadif = ctx->priv;
@@ -227,7 +222,6 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 6 unmodified lines
227222 yadif->prev = yadif->cur;
228223 yadif->cur = yadif->next;
229224 yadif->next = picref;
230− link->cur_buf = NULL;
231225
232226 if (!yadif->cur)
233227 return 0;
@@ -240,7 +234,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 6 unmodified lines
240234 avfilter_unref_bufferp(&yadif->prev);
241235 if (yadif->out->pts != AV_NOPTS_VALUE)
242236 yadif->out->pts *= 2;
243− return ff_start_frame(ctx->outputs[0], yadif->out);
237+ return ff_filter_frame(ctx->outputs[0], yadif->out);
244238 }
245239
246240 if (!yadif->prev &&
@@ -258,26 +252,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) · 11 unmodified lines
258252 if (yadif->out->pts != AV_NOPTS_VALUE)
259253 yadif->out->pts *= 2;
260254
261− return ff_start_frame(ctx->outputs[0], yadif->out);
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;
255+ return return_frame(ctx, 0);
281256 }
282257
283258 static int request_frame(AVFilterLink *link)
@@ -307,8 +282,7 @@ static int request_frame(AVFilterLink *link) · 23 unmodified lines
307282
308283 next->pts = yadif->next->pts * 2 - yadif->cur->pts;
309284
310− start_frame(link->src->inputs[0], next);
311− end_frame(link->src->inputs[0]);
285+ filter_frame(link->src->inputs[0], next);
312286 yadif->eof = 1;
313287 } else if (ret < 0) {
314288 return ret;
@@ -409,11 +383,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args) · 94 unmodified lines
409383 return 0;
410384 }
411385
412−static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
413−{
414− return 0;
415−}
416−
417386 static int config_props(AVFilterLink *link)
418387 {
419388 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
428397 {
429398 .name = "default",
430399 .type = AVMEDIA_TYPE_VIDEO,
431− .start_frame = start_frame,
432400 .get_video_buffer = get_video_buffer,
433− .draw_slice = null_draw_slice,
434− .end_frame = end_frame,
401+ .filter_frame = filter_frame,
435402 },
436403 { NULL }
437404 };
libavfilter/video.c+0−210
@@ -163,213 +163,3 @@ AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, int w, int · 162 unmodified lines
163163
164164 return ret;
165165 }
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−}
libavfilter/video.h+0−47
@@ -39,51 +39,4 @@ AVFilterBufferRef *ff_null_get_video_buffer(AVFilterLink *link, int perms, int w · 38 unmodified lines
3939 AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms,
4040 int w, int h);
4141
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−
8942 #endif /* AVFILTER_VIDEO_H */
libavfilter/vsink_nullsink.c+3−8
@@ -20,13 +20,9 @@ · 19 unmodified lines
2020 #include "internal.h"
2121 #include "libavutil/internal.h"
2222
23−static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
24−{
25− return 0;
26−}
27−
28−static int end_frame(AVFilterLink *link)
23+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
2924 {
25+ avfilter_unref_bufferp(&frame);
3026 return 0;
3127 }
3228
@@ -34,8 +30,7 @@ static const AVFilterPad avfilter_vsink_nullsink_inputs[] = { · 1 unmodified line
3430 {
3531 .name = "default",
3632 .type = AVMEDIA_TYPE_VIDEO,
37− .start_frame = start_frame,
38− .end_frame = end_frame,
33+ .filter_frame = filter_frame,
3934 },
4035 { NULL },
4136 };
libavfilter/vsrc_color.c+1−22
@@ -147,8 +147,6 @@ static int color_request_frame(AVFilterLink *link) · 146 unmodified lines
147147 {
148148 ColorContext *color = link->src->priv;
149149 AVFilterBufferRef *picref = ff_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h);
150− AVFilterBufferRef *buf_out;
151− int ret;
152150
153151 if (!picref)
154152 return AVERROR(ENOMEM);
@@ -157,29 +155,10 @@ static int color_request_frame(AVFilterLink *link) · 2 unmodified lines
157155 picref->pts = color->pts++;
158156 picref->pos = -1;
159157
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−
170158 ff_draw_rectangle(picref->data, picref->linesize,
171159 color->line, color->line_step, color->hsub, color->vsub,
172160 0, 0, color->w, color->h);
173− ret = ff_draw_slice(link, 0, color->h, 1);
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;
161+ return ff_filter_frame(link, picref);
183162 }
184163
185164 static const AVFilterPad avfilter_vsrc_color_outputs[] = {
libavfilter/vsrc_movie.c+2−18
@@ -279,7 +279,6 @@ static int movie_get_frame(AVFilterLink *outlink) · 278 unmodified lines
279279
280280 static int request_frame(AVFilterLink *outlink)
281281 {
282− AVFilterBufferRef *outpicref;
283282 MovieContext *movie = outlink->src->priv;
284283 int ret;
285284
@@ -288,23 +287,8 @@ static int request_frame(AVFilterLink *outlink) · 2 unmodified lines
288287 if ((ret = movie_get_frame(outlink)) < 0)
289288 return ret;
290289
291− outpicref = avfilter_ref_buffer(movie->picref, ~0);
292− if (!outpicref) {
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);
290+ ret = ff_filter_frame(outlink, movie->picref);
291+ movie->picref = NULL;
308292
309293 return ret;
310294 }
libavfilter/vsrc_testsrc.c+1−7
@@ -131,7 +131,6 @@ static int request_frame(AVFilterLink *outlink) · 130 unmodified lines
131131 {
132132 TestSourceContext *test = outlink->src->priv;
133133 AVFilterBufferRef *picref;
134− int ret;
135134
136135 if (test->max_pts >= 0 && test->pts > test->max_pts)
137136 return AVERROR_EOF;
@@ -148,12 +147,7 @@ static int request_frame(AVFilterLink *outlink) · 10 unmodified lines
148147 test->nb_frame++;
149148 test->fill_picture_fn(outlink->src, picref);
150149
151− if ((ret = ff_start_frame(outlink, picref)) < 0 ||
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;
150+ return ff_filter_frame(outlink, picref);
157151 }
158152
159153 #if CONFIG_TESTSRC_FILTER

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t