diff options
author | Anton Khirnov <anton@khirnov.net> | 2012-11-27 07:49:45 +0100 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2012-11-28 08:50:19 +0100 |
commit | 565e4993c63f797e2d50ad2f1e8f62fdbe299666 (patch) | |
tree | bae5282b2ee875de4b01467f3cfaab54b0ab6ec0 /libavfilter | |
parent | bb6c67bb36b136de10256f0999128df4a42f9ffc (diff) | |
download | ffmpeg-565e4993c63f797e2d50ad2f1e8f62fdbe299666.tar.gz |
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.
Diffstat (limited to 'libavfilter')
55 files changed, 632 insertions, 1458 deletions
diff --git a/libavfilter/af_amix.c b/libavfilter/af_amix.c index 7ef94b9e97..c2fb158031 100644 --- a/libavfilter/af_amix.c +++ b/libavfilter/af_amix.c @@ -314,7 +314,7 @@ static int output_frame(AVFilterLink *outlink, int nb_samples) if (s->next_pts != AV_NOPTS_VALUE) s->next_pts += nb_samples; - return ff_filter_samples(outlink, out_buf); + return ff_filter_frame(outlink, out_buf); } /** @@ -455,7 +455,7 @@ static int request_frame(AVFilterLink *outlink) return output_frame(outlink, available_samples); } -static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; MixContext *s = ctx->priv; @@ -509,7 +509,7 @@ static int init(AVFilterContext *ctx, const char *args) snprintf(name, sizeof(name), "input%d", i); pad.type = AVMEDIA_TYPE_AUDIO; pad.name = av_strdup(name); - pad.filter_samples = filter_samples; + pad.filter_frame = filter_frame; ff_insert_inpad(ctx, i, &pad); } diff --git a/libavfilter/af_ashowinfo.c b/libavfilter/af_ashowinfo.c index bcf821ac65..c8e830eee7 100644 --- a/libavfilter/af_ashowinfo.c +++ b/libavfilter/af_ashowinfo.c @@ -34,6 +34,7 @@ #include "audio.h" #include "avfilter.h" +#include "internal.h" typedef struct AShowInfoContext { /** @@ -64,7 +65,7 @@ static void uninit(AVFilterContext *ctx) av_freep(&s->plane_checksums); } -static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; AShowInfoContext *s = ctx->priv; @@ -103,7 +104,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) av_log(ctx, AV_LOG_INFO, "]\n"); s->frame++; - return ff_filter_samples(inlink->dst->outputs[0], buf); + return ff_filter_frame(inlink->dst->outputs[0], buf); } static const AVFilterPad inputs[] = { @@ -112,7 +113,7 @@ static const AVFilterPad inputs[] = { .type = AVMEDIA_TYPE_AUDIO, .get_audio_buffer = ff_null_get_audio_buffer, .config_props = config_input, - .filter_samples = filter_samples, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, }, { NULL }, diff --git a/libavfilter/af_asyncts.c b/libavfilter/af_asyncts.c index 94c5452d12..5d009f020b 100644 --- a/libavfilter/af_asyncts.c +++ b/libavfilter/af_asyncts.c @@ -39,7 +39,7 @@ typedef struct ASyncContext { float min_delta_sec; int max_comp; - /* set by filter_samples() to signal an output frame to request_frame() */ + /* set by filter_frame() to signal an output frame to request_frame() */ int got_output; } ASyncContext; @@ -141,7 +141,7 @@ static int request_frame(AVFilterLink *link) } buf->pts = s->pts; - return ff_filter_samples(link, buf); + return ff_filter_frame(link, buf); } return ret; @@ -161,7 +161,7 @@ static int64_t get_delay(ASyncContext *s) return avresample_available(s->avr) + avresample_get_delay(s->avr); } -static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; ASyncContext *s = ctx->priv; @@ -217,7 +217,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) av_samples_set_silence(buf_out->extended_data, out_size - delta, delta, nb_channels, buf->format); } - ret = ff_filter_samples(outlink, buf_out); + ret = ff_filter_frame(outlink, buf_out); if (ret < 0) goto fail; s->got_output = 1; @@ -243,7 +243,7 @@ static const AVFilterPad avfilter_af_asyncts_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_samples = filter_samples + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/af_channelmap.c b/libavfilter/af_channelmap.c index 4f9ee860df..8b72d5bc9f 100644 --- a/libavfilter/af_channelmap.c +++ b/libavfilter/af_channelmap.c @@ -313,7 +313,7 @@ static int channelmap_query_formats(AVFilterContext *ctx) return 0; } -static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +static int channelmap_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; @@ -355,7 +355,7 @@ static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *bu memcpy(buf->data, buf->extended_data, FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0])); - return ff_filter_samples(outlink, buf); + return ff_filter_frame(outlink, buf); } static int channelmap_config_input(AVFilterLink *inlink) @@ -389,7 +389,7 @@ static const AVFilterPad avfilter_af_channelmap_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_samples = channelmap_filter_samples, + .filter_frame = channelmap_filter_frame, .config_props = channelmap_config_input }, { NULL } diff --git a/libavfilter/af_channelsplit.c b/libavfilter/af_channelsplit.c index e8ceb9c016..cc379f3126 100644 --- a/libavfilter/af_channelsplit.c +++ b/libavfilter/af_channelsplit.c @@ -111,7 +111,7 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; int i, ret = 0; @@ -128,7 +128,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) buf_out->audio->channel_layout = av_channel_layout_extract_channel(buf->audio->channel_layout, i); - ret = ff_filter_samples(ctx->outputs[i], buf_out); + ret = ff_filter_frame(ctx->outputs[i], buf_out); if (ret < 0) break; } @@ -140,7 +140,7 @@ static const AVFilterPad avfilter_af_channelsplit_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_samples = filter_samples, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/af_join.c b/libavfilter/af_join.c index c810e594f8..2b715d55ee 100644 --- a/libavfilter/af_join.c +++ b/libavfilter/af_join.c @@ -93,7 +93,7 @@ static const AVClass join_class = { .version = LIBAVUTIL_VERSION_INT, }; -static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf) { AVFilterContext *ctx = link->dst; JoinContext *s = ctx->priv; @@ -230,7 +230,7 @@ static int join_init(AVFilterContext *ctx, const char *args) snprintf(name, sizeof(name), "input%d", i); pad.type = AVMEDIA_TYPE_AUDIO; pad.name = av_strdup(name); - pad.filter_samples = filter_samples; + pad.filter_frame = filter_frame; pad.needs_fifo = 1; @@ -471,7 +471,7 @@ static int join_request_frame(AVFilterLink *outlink) priv->nb_in_buffers = ctx->nb_inputs; buf->buf->priv = priv; - ret = ff_filter_samples(outlink, buf); + ret = ff_filter_frame(outlink, buf); memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs); diff --git a/libavfilter/af_resample.c b/libavfilter/af_resample.c index a0c7e0e4a9..c712b46d59 100644 --- a/libavfilter/af_resample.c +++ b/libavfilter/af_resample.c @@ -40,7 +40,7 @@ typedef struct ResampleContext { int64_t next_pts; - /* set by filter_samples() to signal an output frame to request_frame() */ + /* set by filter_frame() to signal an output frame to request_frame() */ int got_output; } ResampleContext; @@ -162,12 +162,12 @@ static int request_frame(AVFilterLink *outlink) } buf->pts = s->next_pts; - return ff_filter_samples(outlink, buf); + return ff_filter_frame(outlink, buf); } return ret; } -static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; ResampleContext *s = ctx->priv; @@ -224,7 +224,7 @@ static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) s->next_pts = buf_out->pts + buf_out->audio->nb_samples; - ret = ff_filter_samples(outlink, buf_out); + ret = ff_filter_frame(outlink, buf_out); s->got_output = 1; } @@ -232,7 +232,7 @@ fail: avfilter_unref_buffer(buf); } else { buf->format = outlink->format; - ret = ff_filter_samples(outlink, buf); + ret = ff_filter_frame(outlink, buf); s->got_output = 1; } @@ -243,7 +243,7 @@ static const AVFilterPad avfilter_af_resample_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_samples = filter_samples, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ }, { NULL } diff --git a/libavfilter/asink_anullsink.c b/libavfilter/asink_anullsink.c index 397e745505..ede54c0065 100644 --- a/libavfilter/asink_anullsink.c +++ b/libavfilter/asink_anullsink.c @@ -20,7 +20,7 @@ #include "avfilter.h" #include "internal.h" -static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) +static int null_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref) { avfilter_unref_bufferp(&samplesref); return 0; @@ -30,7 +30,7 @@ static const AVFilterPad avfilter_asink_anullsink_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_samples = null_filter_samples, + .filter_frame = null_filter_frame, }, { NULL }, }; diff --git a/libavfilter/audio.c b/libavfilter/audio.c index 48e038b842..bbe12b211b 100644 --- a/libavfilter/audio.c +++ b/libavfilter/audio.c @@ -146,50 +146,3 @@ fail: av_freep(&samples); return NULL; } - -static int default_filter_samples(AVFilterLink *link, - AVFilterBufferRef *samplesref) -{ - return ff_filter_samples(link->dst->outputs[0], samplesref); -} - -int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) -{ - int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); - AVFilterPad *dst = link->dstpad; - AVFilterBufferRef *buf_out; - - FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1); - - if (!(filter_samples = dst->filter_samples)) - filter_samples = default_filter_samples; - - /* prepare to copy the samples if the buffer has insufficient permissions */ - if ((dst->min_perms & samplesref->perms) != dst->min_perms || - dst->rej_perms & samplesref->perms) { - av_log(link->dst, AV_LOG_DEBUG, - "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n", - samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms); - - buf_out = ff_default_get_audio_buffer(link, dst->min_perms, - samplesref->audio->nb_samples); - if (!buf_out) { - avfilter_unref_buffer(samplesref); - return AVERROR(ENOMEM); - } - buf_out->pts = samplesref->pts; - buf_out->audio->sample_rate = samplesref->audio->sample_rate; - - /* Copy actual data into new samples buffer */ - av_samples_copy(buf_out->extended_data, samplesref->extended_data, - 0, 0, samplesref->audio->nb_samples, - av_get_channel_layout_nb_channels(link->channel_layout), - link->format); - - avfilter_unref_buffer(samplesref); - } else - buf_out = samplesref; - - return filter_samples(link, buf_out); -} - diff --git a/libavfilter/audio.h b/libavfilter/audio.h index fa448e2fd6..a3775037e9 100644 --- a/libavfilter/audio.h +++ b/libavfilter/audio.h @@ -42,17 +42,4 @@ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms, AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms, int nb_samples); -/** - * Send a buffer of audio samples to the next filter. - * - * @param link the output link over which the audio samples are being sent - * @param samplesref a reference to the buffer of audio samples being sent. The - * receiving filter will free this reference when it no longer - * needs it or pass it on to the next filter. - * - * @return >= 0 on success, a negative AVERROR on error. The receiving filter - * is responsible for unreferencing samplesref in case of error. - */ -int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref); - #endif /* AVFILTER_AUDIO_H */ diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c index c7db857ef0..93302ccd23 100644 --- a/libavfilter/avfilter.c +++ b/libavfilter/avfilter.c @@ -23,12 +23,16 @@ #include "libavutil/channel_layout.h" #include "libavutil/common.h" +#include "libavutil/imgutils.h" #include "libavutil/pixdesc.h" #include "libavutil/rational.h" +#include "libavutil/samplefmt.h" +#include "audio.h" #include "avfilter.h" #include "formats.h" #include "internal.h" +#include "video.h" unsigned avfilter_version(void) { return LIBAVFILTER_VERSION_INT; @@ -446,3 +450,68 @@ enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx) { return pads[pad_idx].type; } + +static int default_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) +{ + return ff_filter_frame(link->dst->outputs[0], frame); +} + +int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) +{ + int (*filter_frame)(AVFilterLink *, AVFilterBufferRef *); + AVFilterPad *dst = link->dstpad; + AVFilterBufferRef *out; + int perms = frame->perms; + + FF_DPRINTF_START(NULL, filter_frame); + ff_dlog_link(NULL, link, 1); + + if (!(filter_frame = dst->filter_frame)) + filter_frame = default_filter_frame; + + if (frame->linesize[0] < 0) + perms |= AV_PERM_NEG_LINESIZES; + /* prepare to copy the frame if the buffer has insufficient permissions */ + if ((dst->min_perms & perms) != dst->min_perms || + dst->rej_perms & perms) { + av_log(link->dst, AV_LOG_DEBUG, + "Copying data in avfilter (have perms %x, need %x, reject %x)\n", + perms, link->dstpad->min_perms, link->dstpad->rej_perms); + + switch (link->type) { + case AVMEDIA_TYPE_VIDEO: + out = ff_get_video_buffer(link, dst->min_perms, + link->w, link->h); + break; + case AVMEDIA_TYPE_AUDIO: + out = ff_get_audio_buffer(link, dst->min_perms, + frame->audio->nb_samples); + break; + default: return AVERROR(EINVAL); + } + if (!out) { + avfilter_unref_buffer(frame); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, frame); + + switch (link->type) { + case AVMEDIA_TYPE_VIDEO: + av_image_copy(out->data, out->linesize, frame->data, frame->linesize, + frame->format, frame->video->w, frame->video->h); + break; + case AVMEDIA_TYPE_AUDIO: + av_samples_copy(out->extended_data, frame->extended_data, + 0, 0, frame->audio->nb_samples, + av_get_channel_layout_nb_channels(frame->audio->channel_layout), + frame->format); + break; + default: return AVERROR(EINVAL); + } + + avfilter_unref_buffer(frame); + } else + out = frame; + + return filter_frame(link, out); +} diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h index 01d39b6c0b..c5f8d56297 100644 --- a/libavfilter/avfilter.h +++ b/libavfilter/avfilter.h @@ -253,14 +253,7 @@ struct AVFilterPad { int rej_perms; /** - * Callback called before passing the first slice of a new frame. If - * NULL, the filter layer will default to storing a reference to the - * picture inside the link structure. - * - * Input video pads only. - * - * @return >= 0 on success, a negative AVERROR on error. picref will be - * unreferenced by the caller in case of error. + * @deprecated unused */ int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); @@ -282,37 +275,26 @@ struct AVFilterPad { int nb_samples); /** - * Callback called after the slices of a frame are completely sent. If - * NULL, the filter layer will default to releasing the reference stored - * in the link structure during start_frame(). - * - * Input video pads only. - * - * @return >= 0 on success, a negative AVERROR on error. + * @deprecated unused */ int (*end_frame)(AVFilterLink *link); /** - * Slice drawing callback. This is where a filter receives video data - * and should do its processing. - * - * Input video pads only. - * - * @return >= 0 on success, a negative AVERROR on error. + * @deprecated unused */ int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); /** - * Samples filtering callback. This is where a filter receives audio data - * and should do its processing. + * Filtering callback. This is where a filter receives a frame with + * audio/video data and should do its processing. * - * Input audio pads only. + * Input pads only. * * @return >= 0 on success, a negative AVERROR on error. This function * must ensure that samplesref is properly unreferenced on error if it * hasn't been passed on to another filter. */ - int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); + int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame); /** * Frame poll callback. This returns the number of immediately available @@ -531,18 +513,6 @@ struct AVFilterLink { AVLINK_STARTINIT, ///< started, but incomplete AVLINK_INIT ///< complete } init_state; - - /** - * The buffer reference currently being sent across the link by the source - * filter. This is used internally by the filter system to allow - * automatic copying of buffers which do not have sufficient permissions - * for the destination. This should not be accessed directly by the - * filters. - */ - AVFilterBufferRef *src_buf; - - AVFilterBufferRef *cur_buf; - AVFilterBufferRef *out_buf; }; /** diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c index 96f5351635..a315cb394f 100644 --- a/libavfilter/buffersink.c +++ b/libavfilter/buffersink.c @@ -48,13 +48,12 @@ static av_cold void uninit(AVFilterContext *ctx) av_audio_fifo_free(sink->audio_fifo); } -static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf) { BufferSinkContext *s = link->dst->priv; av_assert0(!s->cur_buf); s->cur_buf = buf; - link->cur_buf = NULL; return 0; } @@ -144,7 +143,7 @@ static const AVFilterPad avfilter_vsink_buffer_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, .needs_fifo = 1 }, @@ -165,7 +164,7 @@ static const AVFilterPad avfilter_asink_abuffer_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_samples = start_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, .needs_fifo = 1 }, diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 9354691862..3cee68da43 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -327,20 +327,7 @@ static int request_frame(AVFilterLink *link) } av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL); - switch (link->type) { - case AVMEDIA_TYPE_VIDEO: - if ((ret = ff_start_frame(link, buf)) < 0 || - (ret = ff_draw_slice(link, 0, link->h, 1)) < 0 || - (ret = ff_end_frame(link)) < 0) - return ret; - break; - case AVMEDIA_TYPE_AUDIO: - ret = ff_filter_samples(link, buf); - break; - default: - avfilter_unref_bufferp(&buf); - return AVERROR(EINVAL); - } + ff_filter_frame(link, buf); return ret; } diff --git a/libavfilter/fifo.c b/libavfilter/fifo.c index 1bfacafd50..88c44fe3b9 100644 --- a/libavfilter/fifo.c +++ b/libavfilter/fifo.c @@ -77,7 +77,6 @@ static int add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) { FifoContext *fifo = inlink->dst->priv; - inlink->cur_buf = NULL; fifo->last->next = av_mallocz(sizeof(Buf)); if (!fifo->last->next) { avfilter_unref_buffer(buf); @@ -99,16 +98,6 @@ static void queue_pop(FifoContext *s) s->root.next = tmp; } -static int end_frame(AVFilterLink *inlink) -{ - return 0; -} - -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - return 0; -} - /** * Move data pointers and pts offset samples forward. */ @@ -228,7 +217,7 @@ static int return_audio_frame(AVFilterContext *ctx) buf_out = s->buf_out; s->buf_out = NULL; } - return ff_filter_samples(link, buf_out); + return ff_filter_frame(link, buf_out); } static int request_frame(AVFilterLink *outlink) @@ -241,27 +230,11 @@ static int request_frame(AVFilterLink *outlink) return ret; } - /* by doing this, we give ownership of the reference to the next filter, - * so we don't have to worry about dereferencing it ourselves. */ - switch (outlink->type) { - case AVMEDIA_TYPE_VIDEO: - if ((ret = ff_start_frame(outlink, fifo->root.next->buf)) < 0 || - (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - + if (outlink->request_samples) { + return return_audio_frame(outlink->src); + } else { + ret = ff_filter_frame(outlink, fifo->root.next->buf); queue_pop(fifo); - break; - case AVMEDIA_TYPE_AUDIO: - if (outlink->request_samples) { - return return_audio_frame(outlink->src); - } else { - ret = ff_filter_samples(outlink, fifo->root.next->buf); - queue_pop(fifo); - } - break; - default: - return AVERROR(EINVAL); } return ret; @@ -272,9 +245,7 @@ static const AVFilterPad avfilter_vf_fifo_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = add_to_queue, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = add_to_queue, .rej_perms = AV_PERM_REUSE2, }, { NULL } @@ -307,7 +278,7 @@ static const AVFilterPad avfilter_af_afifo_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .get_audio_buffer = ff_null_get_audio_buffer, - .filter_samples = add_to_queue, + .filter_frame = add_to_queue, .rej_perms = AV_PERM_REUSE2, }, { NULL } diff --git a/libavfilter/internal.h b/libavfilter/internal.h index 6f868ae89f..216a3554fc 100644 --- a/libavfilter/internal.h +++ b/libavfilter/internal.h @@ -64,18 +64,6 @@ struct AVFilterPad { int rej_perms; /** - * Callback called before passing the first slice of a new frame. If - * NULL, the filter layer will default to storing a reference to the - * picture inside the link structure. - * - * Input video pads only. - * - * @return >= 0 on success, a negative AVERROR on error. picref will be - * unreferenced by the caller in case of error. - */ - void (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref); - - /** * Callback function to get a video buffer. If NULL, the filter system will * use avfilter_default_get_video_buffer(). * @@ -93,37 +81,16 @@ struct AVFilterPad { int nb_samples); /** - * Callback called after the slices of a frame are completely sent. If - * NULL, the filter layer will default to releasing the reference stored - * in the link structure during start_frame(). + * Filtering callback. This is where a filter receives a frame with + * audio/video data and should do its processing. * - * Input video pads only. - * - * @return >= 0 on success, a negative AVERROR on error. - */ - int (*end_frame)(AVFilterLink *link); - - /** - * Slice drawing callback. This is where a filter receives video data - * and should do its processing. - * - * Input video pads only. - * - * @return >= 0 on success, a negative AVERROR on error. - */ - int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir); - - /** - * Samples filtering callback. This is where a filter receives audio data - * and should do its processing. - * - * Input audio pads only. + * Input pads only. * * @return >= 0 on success, a negative AVERROR on error. This function * must ensure that samplesref is properly unreferenced on error if it * hasn't been passed on to another filter. */ - int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref); + int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame); /** * Frame poll callback. This returns the number of immediately available @@ -237,4 +204,17 @@ int ff_poll_frame(AVFilterLink *link); */ int ff_request_frame(AVFilterLink *link); +/** + * Send a frame of data to the next filter. + * + * @param link the output link over which the data is being sent + * @param frame a reference to the buffer of data being sent. The + * receiving filter will free this reference when it no longer + * needs it or pass it on to the next filter. + * + * @return >= 0 on success, a negative AVERROR on error. The receiving filter + * is responsible for unreferencing frame in case of error. + */ +int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame); + #endif /* AVFILTER_INTERNAL_H */ diff --git a/libavfilter/split.c b/libavfilter/split.c index 01bb4489f0..c1e1669bd8 100644 --- a/libavfilter/split.c +++ b/libavfilter/split.c @@ -67,46 +67,23 @@ static void split_uninit(AVFilterContext *ctx) av_freep(&ctx->output_pads[i].name); } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { AVFilterContext *ctx = inlink->dst; int i, ret = 0; for (i = 0; i < ctx->nb_outputs; i++) { - AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~AV_PERM_WRITE); - if (!buf_out) - return AVERROR(ENOMEM); - - ret = ff_start_frame(ctx->outputs[i], buf_out); - if (ret < 0) - break; - } - return ret; -} - -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - AVFilterContext *ctx = inlink->dst; - int i, ret = 0; - - for (i = 0; i < ctx->nb_outputs; i++) { - ret = ff_draw_slice(ctx->outputs[i], y, h, slice_dir); - if (ret < 0) + AVFilterBufferRef *buf_out = avfilter_ref_buffer(frame, ~AV_PERM_WRITE); + if (!buf_out) { + ret = AVERROR(ENOMEM); break; - } - return ret; -} - -static int end_frame(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - int i, ret = 0; + } - for (i = 0; i < ctx->nb_outputs; i++) { - ret = ff_end_frame(ctx->outputs[i]); + ret = ff_filter_frame(ctx->outputs[i], buf_out); if (ret < 0) break; } + avfilter_unref_bufferp(&frame); return ret; } @@ -115,9 +92,7 @@ static const AVFilterPad avfilter_vf_split_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL } }; @@ -133,33 +108,12 @@ AVFilter avfilter_vf_split = { .outputs = NULL, }; -static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref) -{ - AVFilterContext *ctx = inlink->dst; - int i, ret = 0; - - for (i = 0; i < ctx->nb_outputs; i++) { - AVFilterBufferRef *buf_out = avfilter_ref_buffer(samplesref, - ~AV_PERM_WRITE); - if (!buf_out) { - ret = AVERROR(ENOMEM); - break; - } - - ret = ff_filter_samples(inlink->dst->outputs[i], buf_out); - if (ret < 0) - break; - } - avfilter_unref_buffer(samplesref); - return ret; -} - static const AVFilterPad avfilter_af_asplit_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, .get_audio_buffer = ff_null_get_audio_buffer, - .filter_samples = filter_samples + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_aspect.c b/libavfilter/vf_aspect.c index 9f0c0c00a6..d7e851c928 100644 --- a/libavfilter/vf_aspect.c +++ b/libavfilter/vf_aspect.c @@ -65,13 +65,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args) return 0; } -static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) { AspectContext *aspect = link->dst->priv; - picref->video->pixel_aspect = aspect->aspect; - link->cur_buf = NULL; - return ff_start_frame(link->dst->outputs[0], picref); + frame->video->pixel_aspect = aspect->aspect; + return ff_filter_frame(link->dst->outputs[0], frame); } #if CONFIG_SETDAR_FILTER @@ -99,8 +98,7 @@ static const AVFilterPad avfilter_vf_setdar_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = setdar_config_props, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, - .end_frame = ff_null_end_frame + .filter_frame = filter_frame, }, { NULL } }; @@ -144,8 +142,7 @@ static const AVFilterPad avfilter_vf_setsar_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = setsar_config_props, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, - .end_frame = ff_null_end_frame + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_blackframe.c b/libavfilter/vf_blackframe.c index 9a27b6971f..275ebb2070 100644 --- a/libavfilter/vf_blackframe.c +++ b/libavfilter/vf_blackframe.c @@ -78,49 +78,37 @@ static av_cold int init(AVFilterContext *ctx, const char *args) return 0; } -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { AVFilterContext *ctx = inlink->dst; BlackFrameContext *blackframe = ctx->priv; - AVFilterBufferRef *picref = inlink->cur_buf; int x, i; - uint8_t *p = picref->data[0] + y * picref->linesize[0]; + int pblack = 0; + uint8_t *p = frame->data[0]; - for (i = 0; i < h; i++) { + for (i = 0; i < frame->video->h; i++) { for (x = 0; x < inlink->w; x++) blackframe->nblack += p[x] < blackframe->bthresh; - p += picref->linesize[0]; + p += frame->linesize[0]; } - return ff_draw_slice(ctx->outputs[0], y, h, slice_dir); -} - -static int end_frame(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - BlackFrameContext *blackframe = ctx->priv; - AVFilterBufferRef *picref = inlink->cur_buf; - int pblack = 0; - pblack = blackframe->nblack * 100 / (inlink->w * inlink->h); if (pblack >= blackframe->bamount) av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pos:%"PRId64" pts:%"PRId64" t:%f\n", - blackframe->frame, pblack, picref->pos, picref->pts, - picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base)); + blackframe->frame, pblack, frame->pos, frame->pts, + frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base)); blackframe->frame++; blackframe->nblack = 0; - return ff_end_frame(inlink->dst->outputs[0]); + return ff_filter_frame(inlink->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_blackframe_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = draw_slice, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_boxblur.c b/libavfilter/vf_boxblur.c index 755d98ea2a..d72c602d06 100644 --- a/libavfilter/vf_boxblur.c +++ b/libavfilter/vf_boxblur.c @@ -307,31 +307,39 @@ static void vblur(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_li h, radius, power, temp); } -static int draw_slice(AVFilterLink *inlink, int y0, int h0, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { AVFilterContext *ctx = inlink->dst; BoxBlurContext *boxblur = ctx->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *inpicref = inlink ->cur_buf; - AVFilterBufferRef *outpicref = outlink->out_buf; + AVFilterBufferRef *out; int plane; - int cw = inlink->w >> boxblur->hsub, ch = h0 >> boxblur->vsub; + int cw = inlink->w >> boxblur->hsub, ch = in->video->h >> boxblur->vsub; int w[4] = { inlink->w, cw, cw, inlink->w }; - int h[4] = { h0, ch, ch, h0 }; + int h[4] = { in->video->h, ch, ch, in->video->h }; - for (plane = 0; inpicref->data[plane] && plane < 4; plane++) - hblur(outpicref->data[plane], outpicref->linesize[plane], - inpicref ->data[plane], inpicref ->linesize[plane], + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, in); + + for (plane = 0; in->data[plane] && plane < 4; plane++) + hblur(out->data[plane], out->linesize[plane], + in ->data[plane], in ->linesize[plane], w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], boxblur->temp); - for (plane = 0; inpicref->data[plane] && plane < 4; plane++) - vblur(outpicref->data[plane], outpicref->linesize[plane], - outpicref->data[plane], outpicref->linesize[plane], + for (plane = 0; in->data[plane] && plane < 4; plane++) + vblur(out->data[plane], out->linesize[plane], + out->data[plane], out->linesize[plane], w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane], boxblur->temp); - return ff_draw_slice(outlink, y0, h0, slice_dir); + avfilter_unref_bufferp(&in); + + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_boxblur_inputs[] = { @@ -339,7 +347,7 @@ static const AVFilterPad avfilter_vf_boxblur_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, - .draw_slice = draw_slice, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ }, { NULL } diff --git a/libavfilter/vf_copy.c b/libavfilter/vf_copy.c index a20da93b82..8ece5cf8c5 100644 --- a/libavfilter/vf_copy.c +++ b/libavfilter/vf_copy.c @@ -31,8 +31,6 @@ static const AVFilterPad avfilter_vf_copy_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .end_frame = ff_null_end_frame, .rej_perms = ~0 }, { NULL } diff --git a/libavfilter/vf_crop.c b/libavfilter/vf_crop.c index f79f574315..981dfd6cb0 100644 --- a/libavfilter/vf_crop.c +++ b/libavfilter/vf_crop.c @@ -243,24 +243,19 @@ static int config_output(AVFilterLink *link) return 0; } -static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) { AVFilterContext *ctx = link->dst; CropContext *crop = ctx->priv; - AVFilterBufferRef *ref2; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); int i; - ref2 = avfilter_ref_buffer(picref, ~0); - if (!ref2) - return AVERROR(ENOMEM); + frame->video->w = crop->w; + frame->video->h = crop->h; - ref2->video->w = crop->w; - ref2->video->h = crop->h; - - crop->var_values[VAR_T] = picref->pts == AV_NOPTS_VALUE ? - NAN : picref->pts * av_q2d(link->time_base); - crop->var_values[VAR_POS] = picref->pos == -1 ? NAN : picref->pos; + crop->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ? + NAN : frame->pts * av_q2d(link->time_base); + crop->var_values[VAR_POS] = frame->pos == -1 ? NAN : frame->pos; crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL); crop->var_values[VAR_Y] = av_expr_eval(crop->y_pexpr, crop->var_values, NULL); 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) (int)crop->var_values[VAR_N], crop->var_values[VAR_T], crop->x, crop->y, crop->x+crop->w, crop->y+crop->h); - ref2->data[0] += crop->y * ref2->linesize[0]; - ref2->data[0] += crop->x * crop->max_step[0]; + frame->data[0] += crop->y * frame->linesize[0]; + frame->data[0] += crop->x * crop->max_step[0]; if (!(desc->flags & PIX_FMT_PAL || desc->flags & PIX_FMT_PSEUDOPAL)) { for (i = 1; i < 3; i ++) { - if (ref2->data[i]) { - ref2->data[i] += (crop->y >> crop->vsub) * ref2->linesize[i]; - ref2->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub; + if (frame->data[i]) { + frame->data[i] += (crop->y >> crop->vsub) * frame->linesize[i]; + frame->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub; } } } /* alpha plane */ - if (ref2->data[3]) { - ref2->data[3] += crop->y * ref2->linesize[3]; - ref2->data[3] += crop->x * crop->max_step[3]; + if (frame->data[3]) { + frame->data[3] += crop->y * frame->linesize[3]; + frame->data[3] += crop->x * crop->max_step[3]; } - return ff_start_frame(link->dst->outputs[0], ref2); -} - -static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - AVFilterContext *ctx = link->dst; - CropContext *crop = ctx->priv; - - if (y >= crop->y + crop->h || y + h <= crop->y) - return 0; - - if (y < crop->y) { - h -= crop->y - y; - y = crop->y; - } - if (y + h > crop->y + crop->h) - h = crop->y + crop->h - y; - - return ff_draw_slice(ctx->outputs[0], y - crop->y, h, slice_dir); -} - -static int end_frame(AVFilterLink *link) -{ - CropContext *crop = link->dst->priv; - crop->var_values[VAR_N] += 1.0; - return ff_end_frame(link->dst->outputs[0]); + + return ff_filter_frame(link->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_crop_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .get_video_buffer = ff_null_get_video_buffer, .config_props = config_input, }, diff --git a/libavfilter/vf_cropdetect.c b/libavfilter/vf_cropdetect.c index 63a72cbd05..eebd8bc144 100644 --- a/libavfilter/vf_cropdetect.c +++ b/libavfilter/vf_cropdetect.c @@ -117,11 +117,10 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { AVFilterContext *ctx = inlink->dst; CropDetectContext *cd = ctx->priv; - AVFilterBufferRef *picref = inlink->cur_buf; int bpp = cd->max_pixsteps[0]; int w, h, x, y, shrink_by; @@ -129,36 +128,36 @@ static int end_frame(AVFilterLink *inlink) if (++cd->frame_nb > 0) { // Reset the crop area every reset_count frames, if reset_count is > 0 if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) { - cd->x1 = picref->video->w-1; - cd->y1 = picref->video->h-1; + cd->x1 = frame->video->w-1; + cd->y1 = frame->video->h-1; cd->x2 = 0; cd->y2 = 0; cd->frame_nb = 1; } for (y = 0; y < cd->y1; y++) { - if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) { + if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) { cd->y1 = y; break; } } - for (y = picref->video->h-1; y > cd->y2; y--) { - if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) { + for (y = frame->video->h-1; y > cd->y2; y--) { + if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) { cd->y2 = y; break; } } for (y = 0; y < cd->x1; y++) { - if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) { + if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) { cd->x1 = y; break; } } - for (y = picref->video->w-1; y > cd->x2; y--) { - if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) { + for (y = frame->video->w-1; y > cd->x2; y--) { + if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) { cd->x2 = y; break; } @@ -189,12 +188,12 @@ static int end_frame(AVFilterLink *inlink) av_log(ctx, AV_LOG_INFO, "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", - cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, picref->pos, picref->pts, - picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base), + cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, frame->pos, frame->pts, + frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base), w, h, x, y); } - return ff_end_frame(inlink->dst->outputs[0]); + return ff_filter_frame(inlink->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_cropdetect_inputs[] = { @@ -203,8 +202,7 @@ static const AVFilterPad avfilter_vf_cropdetect_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_delogo.c b/libavfilter/vf_delogo.c index 361e0b797a..76848c3198 100644 --- a/libavfilter/vf_delogo.c +++ b/libavfilter/vf_delogo.c @@ -215,30 +215,38 @@ static av_cold int init(AVFilterContext *ctx, const char *args) return 0; } -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { DelogoContext *delogo = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *inpicref = inlink ->cur_buf; - AVFilterBufferRef *outpicref = outlink->out_buf; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - int direct = inpicref->buf == outpicref->buf; + AVFilterBufferRef *out; int hsub0 = desc->log2_chroma_w; int vsub0 = desc->log2_chroma_h; + int direct; int plane; - int ret; - for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) { + if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) { + direct = 1; + out = in; + } else { + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + + avfilter_copy_buffer_ref_props(out, in); + out->video->w = outlink->w; + out->video->h = outlink->h; + } + + for (plane = 0; plane < 4 && in->data[plane]; plane++) { int hsub = plane == 1 || plane == 2 ? hsub0 : 0; int vsub = plane == 1 || plane == 2 ? vsub0 : 0; - apply_delogo(outpicref->data[plane], outpicref->linesize[plane], - inpicref ->data[plane], inpicref ->linesize[plane], + apply_delogo(out->data[plane], out->linesize[plane], + in ->data[plane], in ->linesize[plane], inlink->w>>hsub, inlink->h>>vsub, delogo->x>>hsub, delogo->y>>vsub, delogo->w>>hsub, delogo->h>>vsub, @@ -246,10 +254,10 @@ static int end_frame(AVFilterLink *inlink) delogo->show, direct); } - if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + if (!direct) + avfilter_unref_bufferp(&in); + + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_delogo_inputs[] = { @@ -257,9 +265,7 @@ static const AVFilterPad avfilter_vf_delogo_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_inplace_start_frame, - .draw_slice = null_draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_WRITE | AV_PERM_READ, .rej_perms = AV_PERM_PRESERVE }, diff --git a/libavfilter/vf_drawbox.c b/libavfilter/vf_drawbox.c index fbae0ee841..c47422ef1b 100644 --- a/libavfilter/vf_drawbox.c +++ b/libavfilter/vf_drawbox.c @@ -96,21 +96,20 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { DrawBoxContext *drawbox = inlink->dst->priv; int plane, x, y, xb = drawbox->x, yb = drawbox->y; unsigned char *row[4]; - AVFilterBufferRef *picref = inlink->cur_buf; - for (y = FFMAX(yb, y0); y < (y0 + h) && y < (yb + drawbox->h); y++) { - row[0] = picref->data[0] + y * picref->linesize[0]; + for (y = FFMAX(yb, 0); y < frame->video->h && y < (yb + drawbox->h); y++) { + row[0] = frame->data[0] + y * frame->linesize[0]; for (plane = 1; plane < 3; plane++) - row[plane] = picref->data[plane] + - picref->linesize[plane] * (y >> drawbox->vsub); + row[plane] = frame->data[plane] + + frame->linesize[plane] * (y >> drawbox->vsub); - for (x = FFMAX(xb, 0); x < (xb + drawbox->w) && x < picref->video->w; x++) { + for (x = FFMAX(xb, 0); x < (xb + drawbox->w) && x < frame->video->w; x++) { double alpha = (double)drawbox->yuv_color[A] / 255; 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) } } - return ff_draw_slice(inlink->dst->outputs[0], y0, h, 1); + return ff_filter_frame(inlink->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_drawbox_inputs[] = { @@ -131,9 +130,7 @@ static const AVFilterPad avfilter_vf_drawbox_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .draw_slice = draw_slice, - .end_frame = ff_null_end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_WRITE | AV_PERM_READ, .rej_perms = AV_PERM_PRESERVE }, diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c index 43a42d8e26..e1c2bb1920 100644 --- a/libavfilter/vf_drawtext.c +++ b/libavfilter/vf_drawtext.c @@ -792,11 +792,6 @@ static int draw_text(AVFilterContext *ctx, AVFilterBufferRef *picref, return 0; } -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - static inline int normalize_double(int *n, double d) { int ret = 0; @@ -812,20 +807,20 @@ static inline int normalize_double(int *n, double d) return ret; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { AVFilterContext *ctx = inlink->dst; DrawTextContext *dtext = ctx->priv; - AVFilterBufferRef *buf_out; int ret = 0; if ((ret = dtext_prepare_text(ctx)) < 0) { av_log(ctx, AV_LOG_ERROR, "Can't draw text\n"); + avfilter_unref_bufferp(&frame); return ret; } - dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ? - NAN : inpicref->pts * av_q2d(inlink->time_base); + dtext->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ? + NAN : frame->pts * av_q2d(inlink->time_base); dtext->var_values[VAR_X] = av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng); dtext->var_values[VAR_Y] = @@ -854,29 +849,12 @@ static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) (int)dtext->var_values[VAR_N], dtext->var_values[VAR_T], dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h); - buf_out = avfilter_ref_buffer(inpicref, ~0); - if (!buf_out) - return AVERROR(ENOMEM); - - return ff_start_frame(inlink->dst->outputs[0], buf_out); -} - -static int end_frame(AVFilterLink *inlink) -{ - AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *picref = inlink->cur_buf; - DrawTextContext *dtext = inlink->dst->priv; - int ret; - if (dtext->draw) - draw_text(inlink->dst, picref, picref->video->w, picref->video->h); + draw_text(inlink->dst, frame, frame->video->w, frame->video->h); dtext->var_values[VAR_N] += 1.0; - if ((ret = ff_draw_slice(outlink, 0, picref->video->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + return ff_filter_frame(inlink->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_drawtext_inputs[] = { @@ -884,9 +862,7 @@ static const AVFilterPad avfilter_vf_drawtext_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, - .draw_slice = null_draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .config_props = config_input, .min_perms = AV_PERM_WRITE | AV_PERM_READ, diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index 8555798504..f609db1248 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -98,17 +98,16 @@ static int config_props(AVFilterLink *inlink) return 0; } -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { FadeContext *fade = inlink->dst->priv; - AVFilterBufferRef *outpic = inlink->cur_buf; uint8_t *p; int i, j, plane; if (fade->factor < UINT16_MAX) { /* luma or rgb plane */ - for (i = 0; i < h; i++) { - p = outpic->data[0] + (y+i) * outpic->linesize[0]; + for (i = 0; i < frame->video->h; i++) { + p = frame->data[0] + i * frame->linesize[0]; for (j = 0; j < inlink->w * fade->bpp; j++) { /* fade->factor is using 16 lower-order bits for decimal * 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) } } - if (outpic->data[1] && outpic->data[2]) { + if (frame->data[1] && frame->data[2]) { /* chroma planes */ for (plane = 1; plane < 3; plane++) { - for (i = 0; i < h; i++) { - p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane]; + for (i = 0; i < frame->video->h; i++) { + p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane]; for (j = 0; j < inlink->w >> fade->hsub; j++) { /* 8421367 = ((128 << 1) + 1) << 15. It is an integer * 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) } } - return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); -} - -static int end_frame(AVFilterLink *inlink) -{ - FadeContext *fade = inlink->dst->priv; - int ret; - - ret = ff_end_frame(inlink->dst->outputs[0]); - if (fade->frame_index >= fade->start_frame && fade->frame_index <= fade->stop_frame) fade->factor += fade->fade_per_frame; fade->factor = av_clip_uint16(fade->factor); fade->frame_index++; - return ret; + return ff_filter_frame(inlink->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_fade_inputs[] = { @@ -160,9 +149,7 @@ static const AVFilterPad avfilter_vf_fade_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = config_props, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ | AV_PERM_WRITE, .rej_perms = AV_PERM_PRESERVE, }, diff --git a/libavfilter/vf_fieldorder.c b/libavfilter/vf_fieldorder.c index 5e084ac4c8..6fbac1c541 100644 --- a/libavfilter/vf_fieldorder.c +++ b/libavfilter/vf_fieldorder.c @@ -121,90 +121,39 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms, int return ff_get_video_buffer(outlink, perms, w, h); } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { - AVFilterContext *ctx = inlink->dst; - AVFilterLink *outlink = ctx->outputs[0]; - - AVFilterBufferRef *outpicref, *for_next_filter; - int ret = 0; - - outpicref = avfilter_ref_buffer(inpicref, ~0); - if (!outpicref) - return AVERROR(ENOMEM); - - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (!for_next_filter) { - avfilter_unref_bufferp(&outpicref); - return AVERROR(ENOMEM); - } - - ret = ff_start_frame(outlink, for_next_filter); - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; - } - - outlink->out_buf = outpicref; - return 0; -} - -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - AVFilterContext *ctx = inlink->dst; - FieldOrderContext *fieldorder = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - - AVFilterBufferRef *inpicref = inlink->cur_buf; + AVFilterContext *ctx = inlink->dst; + FieldOrderContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + int h, plane, line_step, line_size, line; + uint8_t *data; - /** can only currently do slices if this filter is doing nothing - * because this filter is moving picture content, the output - * slice will contain different video lines than the input slice - * and that complexity will be added later */ - if ( !inpicref->video->interlaced - || inpicref->video->top_field_first == fieldorder->dst_tff) { - return ff_draw_slice(outlink, y, h, slice_dir); - } - return 0; -} + if (!frame->video->interlaced || + frame->video->top_field_first == s->dst_tff) + return ff_filter_frame(outlink, frame); -static int end_frame(AVFilterLink *inlink) -{ - AVFilterContext *ctx = inlink->dst; - FieldOrderContext *fieldorder = ctx->priv; - AVFilterLink *outlink = ctx->outputs[0]; - - AVFilterBufferRef *inpicref = inlink->cur_buf; - AVFilterBufferRef *outpicref = outlink->out_buf; - - int h, plane, line_step, line_size, line; - uint8_t *cpy_src, *cpy_dst; - - if ( inpicref->video->interlaced - && inpicref->video->top_field_first != fieldorder->dst_tff) { av_dlog(ctx, "picture will move %s one line\n", - fieldorder->dst_tff ? "up" : "down"); - h = inpicref->video->h; - for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) { - line_step = inpicref->linesize[plane]; - line_size = fieldorder->line_size[plane]; - cpy_src = inpicref->data[plane]; - cpy_dst = outpicref->data[plane]; - if (fieldorder->dst_tff) { + s->dst_tff ? "up" : "down"); + h = frame->video->h; + for (plane = 0; plane < 4 && frame->data[plane]; plane++) { + line_step = frame->linesize[plane]; + line_size = s->line_size[plane]; + data = frame->data[plane]; + if (s->dst_tff) { /** Move every line up one line, working from * the top to the bottom of the frame. * The original top line is lost. * The new last line is created as a copy of the * penultimate line from that field. */ for (line = 0; line < h; line++) { - if (1 + line < outpicref->video->h) { - memcpy(cpy_dst, cpy_src + line_step, line_size); + if (1 + line < frame->video->h) { + memcpy(data, data + line_step, line_size); } else { - memcpy(cpy_dst, cpy_src - line_step - line_step, line_size); + memcpy(data, data - line_step - line_step, line_size); } - cpy_src += line_step; - cpy_dst += line_step; + data += line_step; } } else { /** Move every line down one line, working from @@ -212,27 +161,20 @@ static int end_frame(AVFilterLink *inlink) * The original bottom line is lost. * The new first line is created as a copy of the * second line from that field. */ - cpy_src += (h - 1) * line_step; - cpy_dst += (h - 1) * line_step; + data += (h - 1) * line_step; for (line = h - 1; line >= 0 ; line--) { if (line > 0) { - memcpy(cpy_dst, cpy_src - line_step, line_size); + memcpy(data, data - line_step, line_size); } else { - memcpy(cpy_dst, cpy_src + line_step + line_step, line_size); + memcpy(data, data + line_step + line_step, line_size); } - cpy_src -= line_step; - cpy_dst -= line_step; + data -= line_step; } } } - outpicref->video->top_field_first = fieldorder->dst_tff; - ff_draw_slice(outlink, 0, h, 1); - } else { - av_dlog(ctx, - "not interlaced or field order already correct\n"); - } + frame->video->top_field_first = s->dst_tff; - return ff_end_frame(outlink); + return ff_filter_frame(outlink, frame); } static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { @@ -240,10 +182,8 @@ static const AVFilterPad avfilter_vf_fieldorder_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, - .start_frame = start_frame, .get_video_buffer = get_video_buffer, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE, }, diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c index 72d6348e17..7e4a26e302 100644 --- a/libavfilter/vf_format.c +++ b/libavfilter/vf_format.c @@ -104,9 +104,6 @@ static const AVFilterPad avfilter_vf_format_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .draw_slice = ff_null_draw_slice, - .end_frame = ff_null_end_frame, }, { NULL } }; @@ -146,9 +143,6 @@ static const AVFilterPad avfilter_vf_noformat_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .draw_slice = ff_null_draw_slice, - .end_frame = ff_null_end_frame, }, { NULL } }; diff --git a/libavfilter/vf_fps.c b/libavfilter/vf_fps.c index 45b8225d7f..dc20114804 100644 --- a/libavfilter/vf_fps.c +++ b/libavfilter/vf_fps.c @@ -144,9 +144,7 @@ static int request_frame(AVFilterLink *outlink) buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base, outlink->time_base) + s->frames_out; - if ((ret = ff_start_frame(outlink, buf)) < 0 || - (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) + if ((ret = ff_filter_frame(outlink, buf)) < 0) return ret; s->frames_out++; @@ -171,16 +169,14 @@ static int write_to_fifo(AVFifoBuffer *fifo, AVFilterBufferRef *buf) return 0; } -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; FPSContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFilterBufferRef *buf = inlink->cur_buf; int64_t delta; int i, ret; - inlink->cur_buf = NULL; s->frames_in++; /* discard frames until we get the first timestamp */ if (s->pts == AV_NOPTS_VALUE) { @@ -251,9 +247,7 @@ static int end_frame(AVFilterLink *inlink) buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base, outlink->time_base) + s->frames_out; - if ((ret = ff_start_frame(outlink, buf_out)) < 0 || - (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) { + if ((ret = ff_filter_frame(outlink, buf_out)) < 0) { avfilter_unref_bufferp(&buf); return ret; } @@ -268,23 +262,11 @@ static int end_frame(AVFilterLink *inlink) return ret; } -static int null_start_frame(AVFilterLink *link, AVFilterBufferRef *buf) -{ - return 0; -} - -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - static const AVFilterPad avfilter_vf_fps_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = null_start_frame, - .draw_slice = null_draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_frei0r.c b/libavfilter/vf_frei0r.c index 471e6fc3ad..fd053906ce 100644 --- a/libavfilter/vf_frei0r.c +++ b/libavfilter/vf_frei0r.c @@ -346,35 +346,34 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - return 0; -} - -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { Frei0rContext *frei0r = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *inpicref = inlink->cur_buf; - AVFilterBufferRef *outpicref = outlink->out_buf; - int ret; - - frei0r->update(frei0r->instance, inpicref->pts * av_q2d(inlink->time_base) * 1000, - (const uint32_t *)inpicref->data[0], - (uint32_t *)outpicref->data[0]); - if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + AVFilterBufferRef *out; + + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, in); + + frei0r->update(frei0r->instance, in->pts * av_q2d(inlink->time_base) * 1000, + (const uint32_t *)in->data[0], + (uint32_t *)out->data[0]); + + avfilter_unref_bufferp(&in); + + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_frei0r_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = null_draw_slice, .config_props = config_input_props, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ }, { NULL } @@ -456,8 +455,6 @@ static int source_request_frame(AVFilterLink *outlink) { Frei0rContext *frei0r = outlink->src->priv; AVFilterBufferRef *picref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); - AVFilterBufferRef *buf_out; - int ret; if (!picref) return AVERROR(ENOMEM); @@ -466,28 +463,10 @@ static int source_request_frame(AVFilterLink *outlink) picref->pts = frei0r->pts++; picref->pos = -1; - buf_out = avfilter_ref_buffer(picref, ~0); - if (!buf_out) { - ret = AVERROR(ENOMEM); - goto fail; - } - - ret = ff_start_frame(outlink, buf_out); - if (ret < 0) - goto fail; - frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}), NULL, (uint32_t *)picref->data[0]); - ret = ff_draw_slice(outlink, 0, outlink->h, 1); - if (ret < 0) - goto fail; - - ret = ff_end_frame(outlink); - -fail: - avfilter_unref_buffer(picref); - return ret; + return ff_filter_frame(outlink, picref); } static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = { diff --git a/libavfilter/vf_gradfun.c b/libavfilter/vf_gradfun.c index 2ee8b5d60d..2c9a9763c1 100644 --- a/libavfilter/vf_gradfun.c +++ b/libavfilter/vf_gradfun.c @@ -182,20 +182,29 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { GradFunContext *gf = inlink->dst->priv; - AVFilterBufferRef *inpic = inlink->cur_buf; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *outpic = outlink->out_buf; - int p, ret; + AVFilterBufferRef *out; + int p, direct; + + if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) { + direct = 1; + out = in; + } else { + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + + avfilter_copy_buffer_ref_props(out, in); + out->video->w = outlink->w; + out->video->h = outlink->h; + } - for (p = 0; p < 4 && inpic->data[p]; p++) { + for (p = 0; p < 4 && in->data[p]; p++) { int w = inlink->w; int h = inlink->h; int r = gf->radius; @@ -206,15 +215,15 @@ static int end_frame(AVFilterLink *inlink) } if (FFMIN(w, h) > 2 * r) - filter(gf, outpic->data[p], inpic->data[p], w, h, outpic->linesize[p], inpic->linesize[p], r); - else if (outpic->data[p] != inpic->data[p]) - av_image_copy_plane(outpic->data[p], outpic->linesize[p], inpic->data[p], inpic->linesize[p], w, h); + filter(gf, out->data[p], in->data[p], w, h, out->linesize[p], in->linesize[p], r); + else if (out->data[p] != in->data[p]) + av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], w, h); } - if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + if (!direct) + avfilter_unref_bufferp(&in); + + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_gradfun_inputs[] = { @@ -222,9 +231,7 @@ static const AVFilterPad avfilter_vf_gradfun_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, - .start_frame = ff_inplace_start_frame, - .draw_slice = null_draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, }, { NULL } diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c index 3ae0fc6062..85a1d92720 100644 --- a/libavfilter/vf_hflip.c +++ b/libavfilter/vf_hflip.c @@ -84,22 +84,30 @@ static int config_props(AVFilterLink *inlink) return 0; } -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { - FlipContext *flip = inlink->dst->priv; - AVFilterBufferRef *inpic = inlink->cur_buf; - AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; + AVFilterContext *ctx = inlink->dst; + FlipContext *flip = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + AVFilterBufferRef *out; uint8_t *inrow, *outrow; int i, j, plane, step, hsub, vsub; - for (plane = 0; plane < 4 && inpic->data[plane]; plane++) { + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, in); + + for (plane = 0; plane < 4 && in->data[plane]; plane++) { step = flip->max_step[plane]; hsub = (plane == 1 || plane == 2) ? flip->hsub : 0; vsub = (plane == 1 || plane == 2) ? flip->vsub : 0; - outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane]; - inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane] + ((inlink->w >> hsub) - 1) * step; - for (i = 0; i < h>>vsub; i++) { + outrow = out->data[plane]; + inrow = in ->data[plane] + ((inlink->w >> hsub) - 1) * step; + for (i = 0; i < in->video->h >> vsub; i++) { switch (step) { case 1: 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) memcpy(outrow + j*step, inrow - j*step, step); } - inrow += inpic ->linesize[plane]; - outrow += outpic->linesize[plane]; + inrow += in ->linesize[plane]; + outrow += out->linesize[plane]; } } - return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); + avfilter_unref_bufferp(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_hflip_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = draw_slice, + .filter_frame = filter_frame, .config_props = config_props, .min_perms = AV_PERM_READ, }, diff --git a/libavfilter/vf_hqdn3d.c b/libavfilter/vf_hqdn3d.c index 4ed8905979..7365b8d502 100644 --- a/libavfilter/vf_hqdn3d.c +++ b/libavfilter/vf_hqdn3d.c @@ -322,42 +322,49 @@ static int config_input(AVFilterLink *inlink) return 0; } -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { HQDN3DContext *hqdn3d = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *inpic = inlink ->cur_buf; - AVFilterBufferRef *outpic = outlink->out_buf; - int ret, c; + AVFilterBufferRef *out; + int direct, c; + + if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) { + direct = 1; + out = in; + } else { + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + + avfilter_copy_buffer_ref_props(out, in); + out->video->w = outlink->w; + out->video->h = outlink->h; + } for (c = 0; c < 3; c++) { - denoise(hqdn3d, inpic->data[c], outpic->data[c], + denoise(hqdn3d, in->data[c], out->data[c], hqdn3d->line, &hqdn3d->frame_prev[c], - inpic->video->w >> (!!c * hqdn3d->hsub), - inpic->video->h >> (!!c * hqdn3d->vsub), - inpic->linesize[c], outpic->linesize[c], + in->video->w >> (!!c * hqdn3d->hsub), + in->video->h >> (!!c * hqdn3d->vsub), + in->linesize[c], out->linesize[c], hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]); } - if ((ret = ff_draw_slice(outlink, 0, inpic->video->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + if (!direct) + avfilter_unref_bufferp(&in); + + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = ff_inplace_start_frame, - .draw_slice = null_draw_slice, .config_props = config_input, - .end_frame = end_frame + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_libopencv.c b/libavfilter/vf_libopencv.c index 3e802cde26..e558a4a9c1 100644 --- a/libavfilter/vf_libopencv.c +++ b/libavfilter/vf_libopencv.c @@ -32,6 +32,7 @@ #include "libavutil/file.h" #include "avfilter.h" #include "formats.h" +#include "internal.h" #include "video.h" static void fill_iplimage_from_picref(IplImage *img, const AVFilterBufferRef *picref, enum AVPixelFormat pixfmt) @@ -68,11 +69,6 @@ static int query_formats(AVFilterContext *ctx) return 0; } -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - typedef struct { const char *name; int (*init)(AVFilterContext *ctx, const char *args); @@ -355,33 +351,36 @@ static av_cold void uninit(AVFilterContext *ctx) memset(ocv, 0, sizeof(*ocv)); } -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { AVFilterContext *ctx = inlink->dst; OCVContext *ocv = ctx->priv; AVFilterLink *outlink= inlink->dst->outputs[0]; - AVFilterBufferRef *inpicref = inlink ->cur_buf; - AVFilterBufferRef *outpicref = outlink->out_buf; + AVFilterBufferRef *out; IplImage inimg, outimg; - int ret; - fill_iplimage_from_picref(&inimg , inpicref , inlink->format); - fill_iplimage_from_picref(&outimg, outpicref, inlink->format); + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, in); + + fill_iplimage_from_picref(&inimg , in , inlink->format); + fill_iplimage_from_picref(&outimg, out, inlink->format); ocv->end_frame_filter(ctx, &inimg, &outimg); - fill_picref_from_iplimage(outpicref, &outimg, inlink->format); + fill_picref_from_iplimage(out, &outimg, inlink->format); - if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + avfilter_unref_bufferp(&in); + + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_ocv_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = null_draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ }, { NULL } diff --git a/libavfilter/vf_lut.c b/libavfilter/vf_lut.c index c54d6d54b7..f265795fa8 100644 --- a/libavfilter/vf_lut.c +++ b/libavfilter/vf_lut.c @@ -295,22 +295,28 @@ static int config_props(AVFilterLink *inlink) return 0; } -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { AVFilterContext *ctx = inlink->dst; LutContext *lut = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - AVFilterBufferRef *inpic = inlink ->cur_buf; - AVFilterBufferRef *outpic = outlink->out_buf; + AVFilterBufferRef *out; uint8_t *inrow, *outrow, *inrow0, *outrow0; int i, j, k, plane; + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, in); + if (lut->is_rgb) { /* packed */ - inrow0 = inpic ->data[0] + y * inpic ->linesize[0]; - outrow0 = outpic->data[0] + y * outpic->linesize[0]; + inrow0 = in ->data[0]; + outrow0 = out->data[0]; - for (i = 0; i < h; i ++) { + for (i = 0; i < in->video->h; i ++) { inrow = inrow0; outrow = outrow0; for (j = 0; j < inlink->w; j++) { @@ -319,34 +325,35 @@ static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) outrow += lut->step; inrow += lut->step; } - inrow0 += inpic ->linesize[0]; - outrow0 += outpic->linesize[0]; + inrow0 += in ->linesize[0]; + outrow0 += out->linesize[0]; } } else { /* planar */ - for (plane = 0; plane < 4 && inpic->data[plane]; plane++) { + for (plane = 0; plane < 4 && in->data[plane]; plane++) { int vsub = plane == 1 || plane == 2 ? lut->vsub : 0; int hsub = plane == 1 || plane == 2 ? lut->hsub : 0; - inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane]; - outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane]; + inrow = in ->data[plane]; + outrow = out->data[plane]; - for (i = 0; i < h>>vsub; i ++) { + for (i = 0; i < in->video->h >> vsub; i ++) { for (j = 0; j < inlink->w>>hsub; j++) outrow[j] = lut->lut[plane][inrow[j]]; - inrow += inpic ->linesize[plane]; - outrow += outpic->linesize[plane]; + inrow += in ->linesize[plane]; + outrow += out->linesize[plane]; } } } - return ff_draw_slice(outlink, y, h, slice_dir); + avfilter_unref_bufferp(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = draw_slice, + .filter_frame = filter_frame, .config_props = config_props, .min_perms = AV_PERM_READ, }, { .name = NULL} diff --git a/libavfilter/vf_null.c b/libavfilter/vf_null.c index 87e4820aa7..a7abb7aab5 100644 --- a/libavfilter/vf_null.c +++ b/libavfilter/vf_null.c @@ -31,8 +31,6 @@ static const AVFilterPad avfilter_vf_null_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .end_frame = ff_null_end_frame }, { NULL } }; diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index 8fb44e30d3..8741d4805d 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -269,34 +269,22 @@ static void blend_frame(AVFilterContext *ctx, } } -static int null_start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf) -{ - return 0; -} - -static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - return 0; -} - -static int end_frame_main(AVFilterLink *inlink) +static int filter_frame_main(AVFilterLink *inlink, AVFilterBufferRef *frame) { OverlayContext *s = inlink->dst->priv; av_assert0(!s->main); - s->main = inlink->cur_buf; - inlink->cur_buf = NULL; + s->main = frame; return 0; } -static int end_frame_overlay(AVFilterLink *inlink) +static int filter_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *frame) { OverlayContext *s = inlink->dst->priv; av_assert0(!s->over_next); - s->over_next = inlink->cur_buf; - inlink->cur_buf = NULL; + s->over_next = frame; return 0; } @@ -305,11 +293,7 @@ static int output_frame(AVFilterContext *ctx) { OverlayContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; - int ret = ff_start_frame(outlink, s->main); - if (ret >= 0) - ret = ff_draw_slice(outlink, 0, outlink->h, 1); - if (ret >= 0) - ret = ff_end_frame(outlink); + int ret = ff_filter_frame(outlink, s->main); s->main = NULL; return ret; @@ -378,10 +362,8 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { { .name = "main", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = null_start_frame, .config_props = config_input_main, - .draw_slice = null_draw_slice, - .end_frame = end_frame_main, + .filter_frame = filter_frame_main, .min_perms = AV_PERM_READ, .rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE, .needs_fifo = 1, @@ -389,10 +371,8 @@ static const AVFilterPad avfilter_vf_overlay_inputs[] = { { .name = "overlay", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = null_start_frame, .config_props = config_input_overlay, - .draw_slice = null_draw_slice, - .end_frame = end_frame_overlay, + .filter_frame = filter_frame_overlay, .min_perms = AV_PERM_READ, .rej_perms = AV_PERM_REUSE2, .needs_fifo = 1, diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c index c14835d68c..f1a890eb1d 100644 --- a/libavfilter/vf_pad.c +++ b/libavfilter/vf_pad.c @@ -106,7 +106,6 @@ typedef struct { uint8_t *line[4]; int line_step[4]; int hsub, vsub; ///< chroma subsampling values - int needs_copy; } PadContext; static av_cold int init(AVFilterContext *ctx, const char *args) @@ -303,135 +302,85 @@ static int does_clip(PadContext *pad, AVFilterBufferRef *outpicref, int plane, i return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { PadContext *pad = inlink->dst->priv; - AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); - AVFilterBufferRef *for_next_filter; - int plane, ret = 0; + AVFilterBufferRef *out = avfilter_ref_buffer(in, ~0); + int plane, needs_copy; - if (!outpicref) + if (!out) { + avfilter_unref_bufferp(&in); return AVERROR(ENOMEM); + } - for (plane = 0; plane < 4 && outpicref->data[plane]; plane++) { + for (plane = 0; plane < 4 && out->data[plane]; plane++) { int hsub = (plane == 1 || plane == 2) ? pad->hsub : 0; int vsub = (plane == 1 || plane == 2) ? pad->vsub : 0; - av_assert0(outpicref->buf->w>0 && outpicref->buf->h>0); + av_assert0(out->buf->w > 0 && out->buf->h > 0); - if(outpicref->format != outpicref->buf->format) //unsupported currently + if (out->format != out->buf->format) //unsupported currently break; - outpicref->data[plane] -= (pad->x >> hsub) * pad ->line_step[plane] - + (pad->y >> vsub) * outpicref->linesize [plane]; + out->data[plane] -= (pad->x >> hsub) * pad->line_step[plane] + + (pad->y >> vsub) * out->linesize [plane]; - if( does_clip(pad, outpicref, plane, hsub, vsub, 0, 0) - || does_clip(pad, outpicref, plane, hsub, vsub, 0, pad->h-1) - || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, 0) - || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, pad->h-1) - ) + if (does_clip(pad, out, plane, hsub, vsub, 0, 0) || + does_clip(pad, out, plane, hsub, vsub, 0, pad->h - 1) || + does_clip(pad, out, plane, hsub, vsub, pad->w - 1, 0) || + does_clip(pad, out, plane, hsub, vsub, pad->w - 1, pad->h - 1)) break; } - pad->needs_copy= plane < 4 && outpicref->data[plane]; - if(pad->needs_copy){ + needs_copy = plane < 4 && out->data[plane]; + if (needs_copy) { av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n"); - avfilter_unref_buffer(outpicref); - outpicref = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES, - FFMAX(inlink->w, pad->w), - FFMAX(inlink->h, pad->h)); - if (!outpicref) + avfilter_unref_buffer(out); + out = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES, + FFMAX(inlink->w, pad->w), + FFMAX(inlink->h, pad->h)); + if (!out) { + avfilter_unref_bufferp(&in); return AVERROR(ENOMEM); + } - avfilter_copy_buffer_ref_props(outpicref, inpicref); - } - - outpicref->video->w = pad->w; - outpicref->video->h = pad->h; - - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (!for_next_filter) { - ret = AVERROR(ENOMEM); - goto fail; + avfilter_copy_buffer_ref_props(out, in); } - ret = ff_start_frame(inlink->dst->outputs[0], for_next_filter); - if (ret < 0) - goto fail; - - inlink->dst->outputs[0]->out_buf = outpicref; - return 0; - -fail: - avfilter_unref_bufferp(&outpicref); - return ret; -} - -static int end_frame(AVFilterLink *link) -{ - return ff_end_frame(link->dst->outputs[0]); -} + out->video->w = pad->w; + out->video->h = pad->h; -static int draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, int before_slice) -{ - PadContext *pad = link->dst->priv; - int bar_y, bar_h = 0, ret = 0; - - if (slice_dir * before_slice == 1 && y == pad->y) { - /* top bar */ - bar_y = 0; - bar_h = pad->y; - } else if (slice_dir * before_slice == -1 && (y + h) == (pad->y + pad->in_h)) { - /* bottom bar */ - bar_y = pad->y + pad->in_h; - bar_h = pad->h - pad->in_h - pad->y; + /* top bar */ + if (pad->y) { + ff_draw_rectangle(out->data, out->linesize, + pad->line, pad->line_step, pad->hsub, pad->vsub, + 0, 0, pad->w, pad->y); } - if (bar_h) { - ff_draw_rectangle(link->dst->outputs[0]->out_buf->data, - link->dst->outputs[0]->out_buf->linesize, + /* bottom bar */ + if (pad->h > pad->y + pad->in_h) { + ff_draw_rectangle(out->data, out->linesize, pad->line, pad->line_step, pad->hsub, pad->vsub, - 0, bar_y, pad->w, bar_h); - ret = ff_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir); + 0, pad->y + pad->in_h, pad->w, pad->h - pad->y - pad->in_h); } - return ret; -} - -static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - PadContext *pad = link->dst->priv; - AVFilterBufferRef *outpic = link->dst->outputs[0]->out_buf; - AVFilterBufferRef *inpic = link->cur_buf; - int ret; - - y += pad->y; - - y &= ~((1 << pad->vsub) - 1); - h &= ~((1 << pad->vsub) - 1); - - if (!h) - return 0; - draw_send_bar_slice(link, y, h, slice_dir, 1); /* left border */ - ff_draw_rectangle(outpic->data, outpic->linesize, pad->line, pad->line_step, - pad->hsub, pad->vsub, 0, y, pad->x, h); - - if(pad->needs_copy){ - ff_copy_rectangle(outpic->data, outpic->linesize, - inpic->data, inpic->linesize, pad->line_step, - pad->hsub, pad->vsub, - pad->x, y, y-pad->y, inpic->video->w, h); + ff_draw_rectangle(out->data, out->linesize, pad->line, pad->line_step, + pad->hsub, pad->vsub, 0, pad->y, pad->x, in->video->h); + + if (needs_copy) { + ff_copy_rectangle(out->data, out->linesize, in->data, in->linesize, + pad->line_step, pad->hsub, pad->vsub, + pad->x, pad->y, 0, in->video->w, in->video->h); } /* right border */ - ff_draw_rectangle(outpic->data, outpic->linesize, + ff_draw_rectangle(out->data, out->linesize, pad->line, pad->line_step, pad->hsub, pad->vsub, - pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h); - ret = ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); - if (ret < 0) - return ret; + pad->x + pad->in_w, pad->y, pad->w - pad->x - pad->in_w, + in->video->h); - return draw_send_bar_slice(link, y, h, slice_dir, -1); + avfilter_unref_bufferp(&in); + return ff_filter_frame(inlink->dst->outputs[0], out); } static const AVFilterPad avfilter_vf_pad_inputs[] = { @@ -440,9 +389,7 @@ static const AVFilterPad avfilter_vf_pad_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .config_props = config_input, .get_video_buffer = get_video_buffer, - .start_frame = start_frame, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_pixdesctest.c b/libavfilter/vf_pixdesctest.c index 09decea0f9..a1e982c9bc 100644 --- a/libavfilter/vf_pixdesctest.c +++ b/libavfilter/vf_pixdesctest.c @@ -52,86 +52,65 @@ static int config_props(AVFilterLink *inlink) return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { PixdescTestContext *priv = inlink->dst->priv; AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *outpicref, *for_next_filter; - int i, ret = 0; + AVFilterBufferRef *out; + int i, c, w = inlink->w, h = inlink->h; - outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, - outlink->w, outlink->h); - if (!outpicref) + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, + outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); return AVERROR(ENOMEM); + } - avfilter_copy_buffer_ref_props(outpicref, picref); + avfilter_copy_buffer_ref_props(out, in); for (i = 0; i < 4; i++) { int h = outlink->h; h = i == 1 || i == 2 ? h>>priv->pix_desc->log2_chroma_h : h; - if (outpicref->data[i]) { - uint8_t *data = outpicref->data[i] + - (outpicref->linesize[i] > 0 ? 0 : outpicref->linesize[i] * (h-1)); - memset(data, 0, FFABS(outpicref->linesize[i]) * h); + if (out->data[i]) { + uint8_t *data = out->data[i] + + (out->linesize[i] > 0 ? 0 : out->linesize[i] * (h-1)); + memset(data, 0, FFABS(out->linesize[i]) * h); } } /* copy palette */ if (priv->pix_desc->flags & PIX_FMT_PAL || priv->pix_desc->flags & PIX_FMT_PSEUDOPAL) - memcpy(outpicref->data[1], outpicref->data[1], 256*4); - - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (for_next_filter) - ret = ff_start_frame(outlink, for_next_filter); - else - ret = AVERROR(ENOMEM); - - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; - } - - outlink->out_buf = outpicref; - return 0; -} - -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - PixdescTestContext *priv = inlink->dst->priv; - AVFilterBufferRef *inpic = inlink->cur_buf; - AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; - int i, c, w = inlink->w; + memcpy(out->data[1], in->data[1], 256*4); for (c = 0; c < priv->pix_desc->nb_components; c++) { int w1 = c == 1 || c == 2 ? w>>priv->pix_desc->log2_chroma_w : w; int h1 = c == 1 || c == 2 ? h>>priv->pix_desc->log2_chroma_h : h; - int y1 = c == 1 || c == 2 ? y>>priv->pix_desc->log2_chroma_h : y; - for (i = y1; i < y1 + h1; i++) { + for (i = 0; i < h1; i++) { av_read_image_line(priv->line, - inpic->data, - inpic->linesize, + in->data, + in->linesize, priv->pix_desc, 0, i, c, w1, 0); av_write_image_line(priv->line, - outpic->data, - outpic->linesize, + out->data, + out->linesize, priv->pix_desc, 0, i, c, w1); } } - return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); + avfilter_unref_bufferp(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, - .draw_slice = draw_slice, + .filter_frame = filter_frame, .config_props = config_props, .min_perms = AV_PERM_READ, }, diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index cbc1081cd9..7f189a2215 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -257,93 +257,46 @@ fail: return ret; } -static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in) { ScaleContext *scale = link->dst->priv; AVFilterLink *outlink = link->dst->outputs[0]; - AVFilterBufferRef *outpicref, *for_next_filter; + AVFilterBufferRef *out; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); - int ret = 0; - if (!scale->sws) { - outpicref = avfilter_ref_buffer(picref, ~0); - if (!outpicref) - return AVERROR(ENOMEM); - return ff_start_frame(outlink, outpicref); - } + if (!scale->sws) + return ff_filter_frame(outlink, in); scale->hsub = desc->log2_chroma_w; scale->vsub = desc->log2_chroma_h; - outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); - if (!outpicref) + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); return AVERROR(ENOMEM); - - avfilter_copy_buffer_ref_props(outpicref, picref); - outpicref->video->w = outlink->w; - outpicref->video->h = outlink->h; - - - av_reduce(&outpicref->video->pixel_aspect.num, &outpicref->video->pixel_aspect.den, - (int64_t)picref->video->pixel_aspect.num * outlink->h * link->w, - (int64_t)picref->video->pixel_aspect.den * outlink->w * link->h, - INT_MAX); - - scale->slice_y = 0; - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (for_next_filter) - ret = ff_start_frame(outlink, for_next_filter); - else - ret = AVERROR(ENOMEM); - - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; } - outlink->out_buf = outpicref; - return 0; -} + avfilter_copy_buffer_ref_props(out, in); + out->video->w = outlink->w; + out->video->h = outlink->h; -static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - ScaleContext *scale = link->dst->priv; - int out_h, ret; - AVFilterBufferRef *cur_pic = link->cur_buf; - const uint8_t *data[4]; + av_reduce(&out->video->pixel_aspect.num, &out->video->pixel_aspect.den, + (int64_t)in->video->pixel_aspect.num * outlink->h * link->w, + (int64_t)in->video->pixel_aspect.den * outlink->w * link->h, + INT_MAX); - if (!scale->sws) { - return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); - } + sws_scale(scale->sws, in->data, in->linesize, 0, in->video->h, + out->data, out->linesize); - if (scale->slice_y == 0 && slice_dir == -1) - scale->slice_y = link->dst->outputs[0]->h; - - data[0] = cur_pic->data[0] + y * cur_pic->linesize[0]; - data[1] = scale->input_is_pal ? - cur_pic->data[1] : - cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1]; - data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2]; - data[3] = cur_pic->data[3] + y * cur_pic->linesize[3]; - - out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h, - link->dst->outputs[0]->out_buf->data, - link->dst->outputs[0]->out_buf->linesize); - - if (slice_dir == -1) - scale->slice_y -= out_h; - ret = ff_draw_slice(link->dst->outputs[0], scale->slice_y, out_h, slice_dir); - if (slice_dir == 1) - scale->slice_y += out_h; - return ret; + avfilter_unref_bufferp(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_scale_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, - .draw_slice = draw_slice, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, }, { NULL } diff --git a/libavfilter/vf_select.c b/libavfilter/vf_select.c index 25c6a146e9..674151d4ef 100644 --- a/libavfilter/vf_select.c +++ b/libavfilter/vf_select.c @@ -228,50 +228,27 @@ static int select_frame(AVFilterContext *ctx, AVFilterBufferRef *picref) return res; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { SelectContext *select = inlink->dst->priv; - select->select = select_frame(inlink->dst, picref); + select->select = select_frame(inlink->dst, frame); if (select->select) { - AVFilterBufferRef *buf_out; /* frame was requested through poll_frame */ if (select->cache_frames) { - if (!av_fifo_space(select->pending_frames)) + if (!av_fifo_space(select->pending_frames)) { av_log(inlink->dst, AV_LOG_ERROR, "Buffering limit reached, cannot cache more frames\n"); - else - av_fifo_generic_write(select->pending_frames, &picref, - sizeof(picref), NULL); + avfilter_unref_bufferp(&frame); + } else + av_fifo_generic_write(select->pending_frames, &frame, + sizeof(frame), NULL); return 0; } - buf_out = avfilter_ref_buffer(picref, ~0); - if (!buf_out) - return AVERROR(ENOMEM); - return ff_start_frame(inlink->dst->outputs[0], buf_out); + return ff_filter_frame(inlink->dst->outputs[0], frame); } - return 0; -} - -static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - SelectContext *select = inlink->dst->priv; - - if (select->select && !select->cache_frames) - return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir); - return 0; -} - -static int end_frame(AVFilterLink *inlink) -{ - SelectContext *select = inlink->dst->priv; - - if (select->select) { - if (select->cache_frames) - return 0; - return ff_end_frame(inlink->dst->outputs[0]); - } + avfilter_unref_bufferp(&frame); return 0; } @@ -284,14 +261,9 @@ static int request_frame(AVFilterLink *outlink) if (av_fifo_size(select->pending_frames)) { AVFilterBufferRef *picref; - int ret; av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL); - if ((ret = ff_start_frame(outlink, picref)) < 0 || - (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0); - - return ret; + return ff_filter_frame(outlink, picref); } while (!select->select) { @@ -346,9 +318,7 @@ static const AVFilterPad avfilter_vf_select_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, .config_props = config_input, - .start_frame = start_frame, - .draw_slice = draw_slice, - .end_frame = end_frame + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_setpts.c b/libavfilter/vf_setpts.c index f2b86a16af..0c4881efc1 100644 --- a/libavfilter/vf_setpts.c +++ b/libavfilter/vf_setpts.c @@ -102,39 +102,36 @@ static int config_input(AVFilterLink *inlink) #define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d)) #define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)) -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { SetPTSContext *setpts = inlink->dst->priv; + int64_t in_pts = frame->pts; double d; - AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); - - if (!outpicref) - return AVERROR(ENOMEM); if (isnan(setpts->var_values[VAR_STARTPTS])) - setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts); + setpts->var_values[VAR_STARTPTS] = TS2D(frame->pts); - setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced; - setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts); - setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos; + setpts->var_values[VAR_INTERLACED] = frame->video->interlaced; + setpts->var_values[VAR_PTS ] = TS2D(frame->pts); + setpts->var_values[VAR_POS ] = frame->pos == -1 ? NAN : frame->pos; d = av_expr_eval(setpts->expr, setpts->var_values, NULL); - outpicref->pts = D2TS(d); + frame->pts = D2TS(d); #ifdef DEBUG av_log(inlink->dst, AV_LOG_DEBUG, "n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n", (int64_t)setpts->var_values[VAR_N], (int)setpts->var_values[VAR_INTERLACED], - inpicref ->pos, - inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base), - outpicref->pts, outpicref->pts * av_q2d(inlink->time_base)); + frame->pos, in_pts, in_pts * av_q2d(inlink->time_base), + frame->pts, frame->pts * av_q2d(inlink->time_base)); #endif + setpts->var_values[VAR_N] += 1.0; - setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts); - setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts); - return ff_start_frame(inlink->dst->outputs[0], outpicref); + setpts->var_values[VAR_PREV_INPTS ] = TS2D(in_pts); + setpts->var_values[VAR_PREV_OUTPTS] = TS2D(frame->pts); + return ff_filter_frame(inlink->dst->outputs[0], frame); } static av_cold void uninit(AVFilterContext *ctx) @@ -150,7 +147,7 @@ static const AVFilterPad avfilter_vf_setpts_inputs[] = { .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, .config_props = config_input, - .start_frame = start_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_settb.c b/libavfilter/vf_settb.c index 0b68b342a2..a5720726e4 100644 --- a/libavfilter/vf_settb.c +++ b/libavfilter/vf_settb.c @@ -108,21 +108,20 @@ static int config_output_props(AVFilterLink *outlink) return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; if (av_cmp_q(inlink->time_base, outlink->time_base)) { - int64_t orig_pts = picref->pts; - picref->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->time_base); + int64_t orig_pts = frame->pts; + frame->pts = av_rescale_q(frame->pts, inlink->time_base, outlink->time_base); av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n", inlink ->time_base.num, inlink ->time_base.den, orig_pts, - outlink->time_base.num, outlink->time_base.den, picref->pts); + outlink->time_base.num, outlink->time_base.den, frame->pts); } - inlink->cur_buf = NULL; - return ff_start_frame(outlink, picref); + return ff_filter_frame(outlink, frame); } static const AVFilterPad avfilter_vf_settb_inputs[] = { @@ -130,8 +129,7 @@ static const AVFilterPad avfilter_vf_settb_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = start_frame, - .end_frame = ff_null_end_frame + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c index 4b78276f97..c89b0287d8 100644 --- a/libavfilter/vf_showinfo.c +++ b/libavfilter/vf_showinfo.c @@ -41,24 +41,23 @@ static av_cold int init(AVFilterContext *ctx, const char *args) return 0; } -static int end_frame(AVFilterLink *inlink) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame) { AVFilterContext *ctx = inlink->dst; ShowInfoContext *showinfo = ctx->priv; - AVFilterBufferRef *picref = inlink->cur_buf; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); uint32_t plane_checksum[4] = {0}, checksum = 0; int i, plane, vsub = desc->log2_chroma_h; - for (plane = 0; picref->data[plane] && plane < 4; plane++) { - size_t linesize = av_image_get_linesize(picref->format, picref->video->w, plane); - uint8_t *data = picref->data[plane]; + for (plane = 0; frame->data[plane] && plane < 4; plane++) { + size_t linesize = av_image_get_linesize(frame->format, frame->video->w, plane); + uint8_t *data = frame->data[plane]; int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h; for (i = 0; i < h; i++) { plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize); checksum = av_adler32_update(checksum, data, linesize); - data += picref->linesize[plane]; + data += frame->linesize[plane]; } } @@ -67,18 +66,18 @@ static int end_frame(AVFilterLink *inlink) "fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c " "checksum:%u plane_checksum:[%u %u %u %u]\n", showinfo->frame, - picref->pts, picref->pts * av_q2d(inlink->time_base), picref->pos, + frame->pts, frame->pts * av_q2d(inlink->time_base), frame->pos, desc->name, - picref->video->pixel_aspect.num, picref->video->pixel_aspect.den, - picref->video->w, picref->video->h, - !picref->video->interlaced ? 'P' : /* Progressive */ - picref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ - picref->video->key_frame, - av_get_picture_type_char(picref->video->pict_type), + frame->video->pixel_aspect.num, frame->video->pixel_aspect.den, + frame->video->w, frame->video->h, + !frame->video->interlaced ? 'P' : /* Progressive */ + frame->video->top_field_first ? 'T' : 'B', /* Top / Bottom */ + frame->video->key_frame, + av_get_picture_type_char(frame->video->pict_type), checksum, plane_checksum[0], plane_checksum[1], plane_checksum[2], plane_checksum[3]); showinfo->frame++; - return ff_end_frame(inlink->dst->outputs[0]); + return ff_filter_frame(inlink->dst->outputs[0], frame); } static const AVFilterPad avfilter_vf_showinfo_inputs[] = { @@ -86,8 +85,7 @@ static const AVFilterPad avfilter_vf_showinfo_inputs[] = { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = ff_null_get_video_buffer, - .start_frame = ff_null_start_frame, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, }, { NULL } diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c index 1ee645f308..d7a173989f 100644 --- a/libavfilter/vf_transpose.c +++ b/libavfilter/vf_transpose.c @@ -121,100 +121,88 @@ static int config_props_output(AVFilterLink *outlink) return 0; } -static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in) { AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *buf_out; + TransContext *trans = inlink->dst->priv; + AVFilterBufferRef *out; + int plane; - outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, - outlink->w, outlink->h); - if (!outlink->out_buf) + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); return AVERROR(ENOMEM); + } - outlink->out_buf->pts = picref->pts; + out->pts = in->pts; - if (picref->video->pixel_aspect.num == 0) { - outlink->out_buf->video->pixel_aspect = picref->video->pixel_aspect; + if (in->video->pixel_aspect.num == 0) { + out->video->pixel_aspect = in->video->pixel_aspect; } else { - outlink->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den; - outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num; + out->video->pixel_aspect.num = in->video->pixel_aspect.den; + out->video->pixel_aspect.den = in->video->pixel_aspect.num; } - buf_out = avfilter_ref_buffer(outlink->out_buf, ~0); - if (!buf_out) - return AVERROR(ENOMEM); - return ff_start_frame(outlink, buf_out); -} - -static int end_frame(AVFilterLink *inlink) -{ - TransContext *trans = inlink->dst->priv; - AVFilterBufferRef *inpic = inlink->cur_buf; - AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf; - AVFilterLink *outlink = inlink->dst->outputs[0]; - int plane, ret; - - for (plane = 0; outpic->data[plane]; plane++) { + for (plane = 0; out->data[plane]; plane++) { int hsub = plane == 1 || plane == 2 ? trans->hsub : 0; int vsub = plane == 1 || plane == 2 ? trans->vsub : 0; int pixstep = trans->pixsteps[plane]; - int inh = inpic->video->h>>vsub; - int outw = outpic->video->w>>hsub; - int outh = outpic->video->h>>vsub; - uint8_t *out, *in; - int outlinesize, inlinesize; + int inh = in->video->h>>vsub; + int outw = out->video->w>>hsub; + int outh = out->video->h>>vsub; + uint8_t *dst, *src; + int dstlinesize, srclinesize; int x, y; - out = outpic->data[plane]; outlinesize = outpic->linesize[plane]; - in = inpic ->data[plane]; inlinesize = inpic ->linesize[plane]; + dst = out->data[plane]; + dstlinesize = out->linesize[plane]; + src = in->data[plane]; + srclinesize = in->linesize[plane]; if (trans->dir&1) { - in += inpic->linesize[plane] * (inh-1); - inlinesize *= -1; + src += in->linesize[plane] * (inh-1); + srclinesize *= -1; } if (trans->dir&2) { - out += outpic->linesize[plane] * (outh-1); - outlinesize *= -1; + dst += out->linesize[plane] * (outh-1); + dstlinesize *= -1; } for (y = 0; y < outh; y++) { switch (pixstep) { case 1: for (x = 0; x < outw; x++) - out[x] = in[x*inlinesize + y]; + dst[x] = src[x*srclinesize + y]; break; case 2: for (x = 0; x < outw; x++) - *((uint16_t *)(out + 2*x)) = *((uint16_t *)(in + x*inlinesize + y*2)); + *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2)); break; case 3: for (x = 0; x < outw; x++) { - int32_t v = AV_RB24(in + x*inlinesize + y*3); - AV_WB24(out + 3*x, v); + int32_t v = AV_RB24(src + x*srclinesize + y*3); + AV_WB24(dst + 3*x, v); } break; case 4: for (x = 0; x < outw; x++) - *((uint32_t *)(out + 4*x)) = *((uint32_t *)(in + x*inlinesize + y*4)); + *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4)); break; } - out += outlinesize; + dst += dstlinesize; } } - if ((ret = ff_draw_slice(outlink, 0, outpic->video->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - return 0; + avfilter_unref_bufferp(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_transpose_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, - .end_frame = end_frame, + .filter_frame = filter_frame, .min_perms = AV_PERM_READ, }, { NULL } diff --git a/libavfilter/vf_unsharp.c b/libavfilter/vf_unsharp.c index 7e50bb8609..b446937898 100644 --- a/libavfilter/vf_unsharp.c +++ b/libavfilter/vf_unsharp.c @@ -214,36 +214,34 @@ static av_cold void uninit(AVFilterContext *ctx) free_filter_param(&unsharp->chroma); } -static int end_frame(AVFilterLink *link) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in) { UnsharpContext *unsharp = link->dst->priv; - AVFilterBufferRef *in = link->cur_buf; - AVFilterBufferRef *out = link->dst->outputs[0]->out_buf; + AVFilterLink *outlink = link->dst->outputs[0]; + AVFilterBufferRef *out; int cw = SHIFTUP(link->w, unsharp->hsub); int ch = SHIFTUP(link->h, unsharp->vsub); - int ret; + + out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); + if (!out) { + avfilter_unref_bufferp(&in); + return AVERROR(ENOMEM); + } + avfilter_copy_buffer_ref_props(out, in); apply_unsharp(out->data[0], out->linesize[0], in->data[0], in->linesize[0], link->w, link->h, &unsharp->luma); apply_unsharp(out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, &unsharp->chroma); apply_unsharp(out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, &unsharp->chroma); - if ((ret = ff_draw_slice(link->dst->outputs[0], 0, link->h, 1)) < 0 || - (ret = ff_end_frame(link->dst->outputs[0])) < 0) - return ret; - return 0; -} - -static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; + avfilter_unref_bufferp(&in); + return ff_filter_frame(outlink, out); } static const AVFilterPad avfilter_vf_unsharp_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .draw_slice = draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, .config_props = config_props, .min_perms = AV_PERM_READ, }, diff --git a/libavfilter/vf_vflip.c b/libavfilter/vf_vflip.c index f12290aa03..5e6e9653bd 100644 --- a/libavfilter/vf_vflip.c +++ b/libavfilter/vf_vflip.c @@ -69,41 +69,28 @@ static AVFilterBufferRef *get_video_buffer(AVFilterLink *link, int perms, return picref; } -static int start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) { FlipContext *flip = link->dst->priv; - AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0); int i; - if (!outpicref) - return AVERROR(ENOMEM); - for (i = 0; i < 4; i ++) { int vsub = i == 1 || i == 2 ? flip->vsub : 0; - if (outpicref->data[i]) { - outpicref->data[i] += ((link->h >> vsub)-1) * outpicref->linesize[i]; - outpicref->linesize[i] = -outpicref->linesize[i]; + if (frame->data[i]) { + frame->data[i] += ((link->h >> vsub)-1) * frame->linesize[i]; + frame->linesize[i] = -frame->linesize[i]; } } - return ff_start_frame(link->dst->outputs[0], outpicref); -} - -static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - AVFilterContext *ctx = link->dst; - - return ff_draw_slice(ctx->outputs[0], link->h - (y+h), h, -1 * slice_dir); + return ff_filter_frame(link->dst->outputs[0], frame); } - static const AVFilterPad avfilter_vf_vflip_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, .get_video_buffer = get_video_buffer, - .start_frame = start_frame, - .draw_slice = draw_slice, + .filter_frame = filter_frame, .config_props = config_input, }, { NULL } diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index 1c605d942d..db9c71c973 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -202,19 +202,14 @@ static int return_frame(AVFilterContext *ctx, int is_second) } else { yadif->out->pts = AV_NOPTS_VALUE; } - ret = ff_start_frame(ctx->outputs[0], yadif->out); - if (ret < 0) - return ret; } - if ((ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1)) < 0 || - (ret = ff_end_frame(ctx->outputs[0])) < 0) - return ret; + ret = ff_filter_frame(ctx->outputs[0], yadif->out); yadif->frame_pending = (yadif->mode&1) && !is_second; - return 0; + return ret; } -static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *picref) { AVFilterContext *ctx = link->dst; YADIFContext *yadif = ctx->priv; @@ -227,7 +222,6 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) yadif->prev = yadif->cur; yadif->cur = yadif->next; yadif->next = picref; - link->cur_buf = NULL; if (!yadif->cur) return 0; @@ -240,7 +234,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) avfilter_unref_bufferp(&yadif->prev); if (yadif->out->pts != AV_NOPTS_VALUE) yadif->out->pts *= 2; - return ff_start_frame(ctx->outputs[0], yadif->out); + return ff_filter_frame(ctx->outputs[0], yadif->out); } if (!yadif->prev && @@ -258,26 +252,7 @@ static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) if (yadif->out->pts != AV_NOPTS_VALUE) yadif->out->pts *= 2; - return ff_start_frame(ctx->outputs[0], yadif->out); -} - -static int end_frame(AVFilterLink *link) -{ - AVFilterContext *ctx = link->dst; - YADIFContext *yadif = ctx->priv; - - if (!yadif->out) - return 0; - - if (yadif->auto_enable && !yadif->cur->video->interlaced) { - int ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1); - if (ret >= 0) - ret = ff_end_frame(ctx->outputs[0]); - return ret; - } - - return_frame(ctx, 0); - return 0; + return return_frame(ctx, 0); } static int request_frame(AVFilterLink *link) @@ -307,8 +282,7 @@ static int request_frame(AVFilterLink *link) next->pts = yadif->next->pts * 2 - yadif->cur->pts; - start_frame(link->src->inputs[0], next); - end_frame(link->src->inputs[0]); + filter_frame(link->src->inputs[0], next); yadif->eof = 1; } else if (ret < 0) { return ret; @@ -409,11 +383,6 @@ static av_cold int init(AVFilterContext *ctx, const char *args) return 0; } -static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return 0; -} - static int config_props(AVFilterLink *link) { link->time_base.num = link->src->inputs[0]->time_base.num; @@ -428,10 +397,8 @@ static const AVFilterPad avfilter_vf_yadif_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, .get_video_buffer = get_video_buffer, - .draw_slice = null_draw_slice, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL } }; diff --git a/libavfilter/video.c b/libavfilter/video.c index 49091ad010..cb68ca4162 100644 --- a/libavfilter/video.c +++ b/libavfilter/video.c @@ -163,213 +163,3 @@ AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, int w, int return ret; } - -int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) -{ - AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~0); - if (!buf_out) - return AVERROR(ENOMEM); - return ff_start_frame(link->dst->outputs[0], buf_out); -} - -// for filters that support (but don't require) outpic==inpic -int ff_inplace_start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref) -{ - AVFilterLink *outlink = inlink->dst->outputs[0]; - AVFilterBufferRef *outpicref = NULL, *for_next_filter; - int ret = 0; - - if ((inpicref->perms & AV_PERM_WRITE) && !(inpicref->perms & AV_PERM_PRESERVE)) { - outpicref = avfilter_ref_buffer(inpicref, ~0); - if (!outpicref) - return AVERROR(ENOMEM); - } else { - outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); - if (!outpicref) - return AVERROR(ENOMEM); - - avfilter_copy_buffer_ref_props(outpicref, inpicref); - outpicref->video->w = outlink->w; - outpicref->video->h = outlink->h; - } - - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (for_next_filter) - ret = ff_start_frame(outlink, for_next_filter); - else - ret = AVERROR(ENOMEM); - - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; - } - - outlink->out_buf = outpicref; - return 0; -} - -static int default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) -{ - AVFilterLink *outlink = NULL; - - if (inlink->dst->nb_outputs) - outlink = inlink->dst->outputs[0]; - - if (outlink) { - AVFilterBufferRef *buf_out; - outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h); - if (!outlink->out_buf) - return AVERROR(ENOMEM); - - avfilter_copy_buffer_ref_props(outlink->out_buf, picref); - buf_out = avfilter_ref_buffer(outlink->out_buf, ~0); - if (!buf_out) - return AVERROR(ENOMEM); - - return ff_start_frame(outlink, buf_out); - } - return 0; -} - -static void clear_link(AVFilterLink *link) -{ - avfilter_unref_bufferp(&link->cur_buf); - avfilter_unref_bufferp(&link->src_buf); - avfilter_unref_bufferp(&link->out_buf); -} - -/* XXX: should we do the duplicating of the picture ref here, instead of - * forcing the source filter to do it? */ -int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) -{ - int (*start_frame)(AVFilterLink *, AVFilterBufferRef *); - AVFilterPad *dst = link->dstpad; - int ret, perms = picref->perms; - - FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1); - - if (!(start_frame = dst->start_frame)) - start_frame = default_start_frame; - - if (picref->linesize[0] < 0) - perms |= AV_PERM_NEG_LINESIZES; - /* prepare to copy the picture if it has insufficient permissions */ - if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) { - av_log(link->dst, AV_LOG_DEBUG, - "frame copy needed (have perms %x, need %x, reject %x)\n", - picref->perms, - link->dstpad->min_perms, link->dstpad->rej_perms); - - link->cur_buf = ff_get_video_buffer(link, dst->min_perms, link->w, link->h); - if (!link->cur_buf) { - avfilter_unref_bufferp(&picref); - return AVERROR(ENOMEM); - } - - link->src_buf = picref; - avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf); - } - else - link->cur_buf = picref; - - ret = start_frame(link, link->cur_buf); - if (ret < 0) - clear_link(link); - - return ret; -} - -int ff_null_end_frame(AVFilterLink *link) -{ - return ff_end_frame(link->dst->outputs[0]); -} - -static int default_end_frame(AVFilterLink *inlink) -{ - AVFilterLink *outlink = NULL; - - if (inlink->dst->nb_outputs) - outlink = inlink->dst->outputs[0]; - - if (outlink) { - return ff_end_frame(outlink); - } - return 0; -} - -int ff_end_frame(AVFilterLink *link) -{ - int (*end_frame)(AVFilterLink *); - int ret; - - if (!(end_frame = link->dstpad->end_frame)) - end_frame = default_end_frame; - - ret = end_frame(link); - - clear_link(link); - - return ret; -} - -int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); -} - -static int default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) -{ - AVFilterLink *outlink = NULL; - - if (inlink->dst->nb_outputs) - outlink = inlink->dst->outputs[0]; - - if (outlink) - return ff_draw_slice(outlink, y, h, slice_dir); - return 0; -} - -int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) -{ - uint8_t *src[4], *dst[4]; - int i, j, vsub, ret; - int (*draw_slice)(AVFilterLink *, int, int, int); - - 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); - - /* copy the slice if needed for permission reasons */ - if (link->src_buf) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); - vsub = desc->log2_chroma_h; - - for (i = 0; i < 4; i++) { - if (link->src_buf->data[i]) { - src[i] = link->src_buf-> data[i] + - (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i]; - dst[i] = link->cur_buf->data[i] + - (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i]; - } else - src[i] = dst[i] = NULL; - } - - for (i = 0; i < 4; i++) { - int planew = - av_image_get_linesize(link->format, link->cur_buf->video->w, i); - - if (!src[i]) continue; - - for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) { - memcpy(dst[i], src[i], planew); - src[i] += link->src_buf->linesize[i]; - dst[i] += link->cur_buf->linesize[i]; - } - } - } - - if (!(draw_slice = link->dstpad->draw_slice)) - draw_slice = default_draw_slice; - ret = draw_slice(link, y, h, slice_dir); - if (ret < 0) - clear_link(link); - return ret; -} diff --git a/libavfilter/video.h b/libavfilter/video.h index 348240c6e6..be93810bcd 100644 --- a/libavfilter/video.h +++ b/libavfilter/video.h @@ -39,51 +39,4 @@ AVFilterBufferRef *ff_null_get_video_buffer(AVFilterLink *link, int perms, int w AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms, int w, int h); -int ff_inplace_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); -int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); -int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); -int ff_null_end_frame(AVFilterLink *link); - -/** - * Notify the next filter of the start of a frame. - * - * @param link the output link the frame will be sent over - * @param picref A reference to the frame about to be sent. The data for this - * frame need only be valid once draw_slice() is called for that - * portion. The receiving filter will free this reference when - * it no longer needs it. - * - * @return >= 0 on success, a negative AVERROR on error. This function will - * unreference picref in case of error. - */ -int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref); - -/** - * Notify the next filter that the current frame has finished. - * - * @param link the output link the frame was sent over - * - * @return >= 0 on success, a negative AVERROR on error - */ -int ff_end_frame(AVFilterLink *link); - -/** - * Send a slice to the next filter. - * - * Slices have to be provided in sequential order, either in - * top-bottom or bottom-top order. If slices are provided in - * non-sequential order the behavior of the function is undefined. - * - * @param link the output link over which the frame is being sent - * @param y offset in pixels from the top of the image for this slice - * @param h height of this slice in pixels - * @param slice_dir the assumed direction for sending slices, - * from the top slice to the bottom slice if the value is 1, - * from the bottom slice to the top slice if the value is -1, - * for other values the behavior of the function is undefined. - * - * @return >= 0 on success, a negative AVERROR on error. - */ -int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); - #endif /* AVFILTER_VIDEO_H */ diff --git a/libavfilter/vsink_nullsink.c b/libavfilter/vsink_nullsink.c index b10ee626b1..71d2b3ec50 100644 --- a/libavfilter/vsink_nullsink.c +++ b/libavfilter/vsink_nullsink.c @@ -20,13 +20,9 @@ #include "internal.h" #include "libavutil/internal.h" -static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref) -{ - return 0; -} - -static int end_frame(AVFilterLink *link) +static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame) { + avfilter_unref_bufferp(&frame); return 0; } @@ -34,8 +30,7 @@ static const AVFilterPad avfilter_vsink_nullsink_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .start_frame = start_frame, - .end_frame = end_frame, + .filter_frame = filter_frame, }, { NULL }, }; diff --git a/libavfilter/vsrc_color.c b/libavfilter/vsrc_color.c index 2bb07bf16e..c0a4e1c3b2 100644 --- a/libavfilter/vsrc_color.c +++ b/libavfilter/vsrc_color.c @@ -147,8 +147,6 @@ static int color_request_frame(AVFilterLink *link) { ColorContext *color = link->src->priv; AVFilterBufferRef *picref = ff_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h); - AVFilterBufferRef *buf_out; - int ret; if (!picref) return AVERROR(ENOMEM); @@ -157,29 +155,10 @@ static int color_request_frame(AVFilterLink *link) picref->pts = color->pts++; picref->pos = -1; - buf_out = avfilter_ref_buffer(picref, ~0); - if (!buf_out) { - ret = AVERROR(ENOMEM); - goto fail; - } - - ret = ff_start_frame(link, buf_out); - if (ret < 0) - goto fail; - ff_draw_rectangle(picref->data, picref->linesize, color->line, color->line_step, color->hsub, color->vsub, 0, 0, color->w, color->h); - ret = ff_draw_slice(link, 0, color->h, 1); - if (ret < 0) - goto fail; - - ret = ff_end_frame(link); - -fail: - avfilter_unref_buffer(picref); - - return ret; + return ff_filter_frame(link, picref); } static const AVFilterPad avfilter_vsrc_color_outputs[] = { diff --git a/libavfilter/vsrc_movie.c b/libavfilter/vsrc_movie.c index 79186762cb..e6185d686e 100644 --- a/libavfilter/vsrc_movie.c +++ b/libavfilter/vsrc_movie.c @@ -279,7 +279,6 @@ static int movie_get_frame(AVFilterLink *outlink) static int request_frame(AVFilterLink *outlink) { - AVFilterBufferRef *outpicref; MovieContext *movie = outlink->src->priv; int ret; @@ -288,23 +287,8 @@ static int request_frame(AVFilterLink *outlink) if ((ret = movie_get_frame(outlink)) < 0) return ret; - outpicref = avfilter_ref_buffer(movie->picref, ~0); - if (!outpicref) { - ret = AVERROR(ENOMEM); - goto fail; - } - - ret = ff_start_frame(outlink, outpicref); - if (ret < 0) - goto fail; - - ret = ff_draw_slice(outlink, 0, outlink->h, 1); - if (ret < 0) - goto fail; - - ret = ff_end_frame(outlink); -fail: - avfilter_unref_bufferp(&movie->picref); + ret = ff_filter_frame(outlink, movie->picref); + movie->picref = NULL; return ret; } diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c index b81611d19e..632bd278ac 100644 --- a/libavfilter/vsrc_testsrc.c +++ b/libavfilter/vsrc_testsrc.c @@ -131,7 +131,6 @@ static int request_frame(AVFilterLink *outlink) { TestSourceContext *test = outlink->src->priv; AVFilterBufferRef *picref; - int ret; if (test->max_pts >= 0 && test->pts > test->max_pts) return AVERROR_EOF; @@ -148,12 +147,7 @@ static int request_frame(AVFilterLink *outlink) test->nb_frame++; test->fill_picture_fn(outlink->src, picref); - if ((ret = ff_start_frame(outlink, picref)) < 0 || - (ret = ff_draw_slice(outlink, 0, test->h, 1)) < 0 || - (ret = ff_end_frame(outlink)) < 0) - return ret; - - return 0; + return ff_filter_frame(outlink, picref); } #if CONFIG_TESTSRC_FILTER |