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 @@ -63,18 +63,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); + AVFilterBufferRef *buf_out = avfilter_ref_buffer(frame, ~AV_PERM_WRITE); + if (!buf_out) { + ret = AVERROR(ENOMEM); + break; + } - 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) - 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]; + AVFilterContext *ctx = inlink->dst; + FieldOrderContext *s = ctx->priv; + AVFilterLink *outlink = ctx->outputs[0]; + int h, plane, line_step, line_size, line; + uint8_t *data; - AVFilterBufferRef *outpicref, *for_next_filter; - int ret = 0; + if (!frame->video->interlaced || + frame->video->top_field_first == s->dst_tff) + return ff_filter_frame(outlink, frame); - 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; - - /** 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; -} - -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; + AVFilterBufferRef *out; - 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; + 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; - for (p = 0; p < 4 && inpic->data[p]; p++) { + 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 && 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); + avfilter_copy_buffer_ref_props(out, in); } - outpicref->video->w = pad->w; - outpicref->video->h = pad->h; + out->video->w = pad->w; + out->video->h = pad->h; - for_next_filter = avfilter_ref_buffer(outpicref, ~0); - if (!for_next_filter) { - ret = AVERROR(ENOMEM); - goto fail; - } - - 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]); -} - -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; - } - - if (bar_h) { - ff_draw_rectangle(link->dst->outputs[0]->out_buf->data, - link->dst->outputs[0]->out_buf->linesize, + /* top bar */ + if (pad->y) { + 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, 0, pad->w, pad->y); } - 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); + /* 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, pad->y + pad->in_h, pad->w, pad->h - pad->y - pad->in_h); + } /* left border */ - ff_draw_rectangle(outpic->data, outpic->linesize, pad->line, pad->line_step, - pad->hsub, pad->vsub, 0, y, pad->x, 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(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); + 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; + avfilter_copy_buffer_ref_props(out, in); + out->video->w = outlink->w; + out->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, + 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); - 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); + sws_scale(scale->sws, in->data, in->linesize, 0, in->video->h, + out->data, out->linesize); - if (ret < 0) { - avfilter_unref_bufferp(&outpicref); - return ret; - } - - outlink->out_buf = outpicref; - return 0; -} - -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]; - - if (!scale->sws) { - return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir); - } - - 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; - - if (picref->video->pixel_aspect.num == 0) { - outlink->out_buf->video->pixel_aspect = picref->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; } - buf_out = avfilter_ref_buffer(outlink->out_buf, ~0); - if (!buf_out) - return AVERROR(ENOMEM); - return ff_start_frame(outlink, buf_out); -} + out->pts = in->pts; -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; + if (in->video->pixel_aspect.num == 0) { + out->video->pixel_aspect = in->video->pixel_aspect; + } else { + out->video->pixel_aspect.num = in->video->pixel_aspect.den; + out->video->pixel_aspect.den = in->video->pixel_aspect.num; + } - 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); + return ff_filter_frame(link->dst->outputs[0], frame); } - -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); -} - 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