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