X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_weave.c;h=98b8d0bd06bebaae0d1770d6aceff174f7768f4e;hb=a04ad248a05e7b613abe09b3bb067f555108d794;hp=663d79f5115f6dc7c347d9ac36250e23b4497de1;hpb=73d193d1d0ff62a029a905d1404c0fd357f4c880;p=ffmpeg diff --git a/libavfilter/vf_weave.c b/libavfilter/vf_weave.c index 663d79f5115..98b8d0bd06b 100644 --- a/libavfilter/vf_weave.c +++ b/libavfilter/vf_weave.c @@ -49,6 +49,19 @@ static const AVOption weave_options[] = { AVFILTER_DEFINE_CLASS(weave); +static int query_formats(AVFilterContext *ctx) +{ + AVFilterFormats *formats = NULL; + int ret; + + ret = ff_formats_pixdesc_filter(&formats, 0, + AV_PIX_FMT_FLAG_PAL | + AV_PIX_FMT_FLAG_HWACCEL); + if (ret < 0) + return ret; + return ff_set_common_formats(ctx, formats); +} + static int config_props_output(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -77,15 +90,51 @@ static int config_props_output(AVFilterLink *outlink) return 0; } +typedef struct ThreadData { + AVFrame *in, *out; +} ThreadData; + +static int weave_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AVFilterLink *inlink = ctx->inputs[0]; + WeaveContext *s = ctx->priv; + ThreadData *td = arg; + AVFrame *in = td->in; + AVFrame *out = td->out; + + const int weave = (s->double_weave && !(inlink->frame_count_out & 1)); + const int field1 = weave ? s->first_field : (!s->first_field); + const int field2 = weave ? (!s->first_field) : s->first_field; + + for (int i = 0; i < s->nb_planes; i++) { + const int height = s->planeheight[i]; + const int start = (height * jobnr) / nb_jobs; + const int end = (height * (jobnr+1)) / nb_jobs; + + av_image_copy_plane(out->data[i] + out->linesize[i] * field1 + + out->linesize[i] * start * 2, + out->linesize[i] * 2, + in->data[i] + start * in->linesize[i], + in->linesize[i], + s->linesize[i], end - start); + av_image_copy_plane(out->data[i] + out->linesize[i] * field2 + + out->linesize[i] * start * 2, + out->linesize[i] * 2, + s->prev->data[i] + start * s->prev->linesize[i], + s->prev->linesize[i], + s->linesize[i], end - start); + } + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; WeaveContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; + ThreadData td; AVFrame *out; - int i; - int weave; - int field1, field2; if (!s->prev) { s->prev = in; @@ -100,19 +149,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) } av_frame_copy_props(out, in); - weave = (s->double_weave && !(inlink->frame_count_out & 1)); - field1 = weave ? s->first_field : (!s->first_field); - field2 = weave ? (!s->first_field) : s->first_field; - for (i = 0; i < s->nb_planes; i++) { - av_image_copy_plane(out->data[i] + out->linesize[i] * field1, - out->linesize[i] * 2, - in->data[i], in->linesize[i], - s->linesize[i], s->planeheight[i]); - av_image_copy_plane(out->data[i] + out->linesize[i] * field2, - out->linesize[i] * 2, - s->prev->data[i], s->prev->linesize[i], - s->linesize[i], s->planeheight[i]); - } + td.out = out, td.in = in; + ctx->internal->execute(ctx, weave_slice, &td, NULL, FFMIN(s->planeheight[1], + ff_filter_get_nb_threads(ctx))); out->pts = s->double_weave ? s->prev->pts : in->pts / 2; out->interlaced_frame = 1; @@ -151,14 +190,16 @@ static const AVFilterPad weave_outputs[] = { { NULL } }; -AVFilter ff_vf_weave = { +const AVFilter ff_vf_weave = { .name = "weave", .description = NULL_IF_CONFIG_SMALL("Weave input video fields into frames."), .priv_size = sizeof(WeaveContext), .priv_class = &weave_class, + .query_formats = query_formats, .uninit = uninit, .inputs = weave_inputs, .outputs = weave_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, }; static av_cold int init(AVFilterContext *ctx) @@ -174,13 +215,15 @@ static av_cold int init(AVFilterContext *ctx) #define doubleweave_options weave_options AVFILTER_DEFINE_CLASS(doubleweave); -AVFilter ff_vf_doubleweave = { +const AVFilter ff_vf_doubleweave = { .name = "doubleweave", .description = NULL_IF_CONFIG_SMALL("Weave input video fields into double number of frames."), .priv_size = sizeof(WeaveContext), .priv_class = &doubleweave_class, + .query_formats = query_formats, .init = init, .uninit = uninit, .inputs = weave_inputs, .outputs = weave_outputs, + .flags = AVFILTER_FLAG_SLICE_THREADS, };