X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Fvf_remap.c;h=7576b9991fe83b80642e55acbd6de6b11d9cd4b3;hb=8446318502bf21347a4867a5a1fcd8d9bfbd6a41;hp=4f8d57f2291a1695a3e11ef612569e97379cf959;hpb=203bbaccfaaeac9548862e83792d38509a8c8167;p=ffmpeg diff --git a/libavfilter/vf_remap.c b/libavfilter/vf_remap.c index 4f8d57f2291..7576b9991fe 100644 --- a/libavfilter/vf_remap.c +++ b/libavfilter/vf_remap.c @@ -47,9 +47,12 @@ typedef struct RemapContext { const AVClass *class; + int format; + int nb_planes; int nb_components; int step; + FFFrameSync fs; int (*remap_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs); @@ -59,6 +62,9 @@ typedef struct RemapContext { #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption remap_options[] = { + { "format", "set output format", OFFSET(format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "format" }, + { "color", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, .flags = FLAGS, .unit = "format" }, + { "gray", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, .flags = FLAGS, .unit = "format" }, { NULL } }; @@ -73,6 +79,7 @@ typedef struct ThreadData { static int query_formats(AVFilterContext *ctx) { + RemapContext *s = ctx->priv; static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUV444P, @@ -82,12 +89,15 @@ static int query_formats(AVFilterContext *ctx) AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP, AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16, - AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P16, + AV_PIX_FMT_YUVA444P9, AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_YUVA444P12, AV_PIX_FMT_YUVA444P16, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP10, AV_PIX_FMT_GBRAP12, AV_PIX_FMT_GBRAP16, AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48, AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64, + AV_PIX_FMT_NONE + }; + static const enum AVPixelFormat gray_pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY9, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12, AV_PIX_FMT_GRAY14, AV_PIX_FMT_GRAY16, @@ -100,7 +110,7 @@ static int query_formats(AVFilterContext *ctx) AVFilterFormats *pix_formats = NULL, *map_formats = NULL; int ret; - if (!(pix_formats = ff_make_format_list(pix_fmts)) || + if (!(pix_formats = ff_make_format_list(s->format ? gray_pix_fmts : pix_fmts)) || !(map_formats = ff_make_format_list(map_fmts))) { ret = AVERROR(ENOMEM); goto fail; @@ -126,85 +136,48 @@ fail: * pixels are copied from source to target using : * Target_frame[y][x] = Source_frame[ ymap[y][x] ][ [xmap[y][x] ]; */ -static int remap_planar_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - const ThreadData *td = (ThreadData*)arg; - const AVFrame *in = td->in; - const AVFrame *xin = td->xin; - const AVFrame *yin = td->yin; - const AVFrame *out = td->out; - - const int slice_start = (out->height * jobnr ) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - - const int xlinesize = xin->linesize[0] / 2; - const int ylinesize = yin->linesize[0] / 2; - int x , y, plane; - - for (plane = 0; plane < td->nb_planes ; plane++) { - const int dlinesize = out->linesize[plane]; - const uint8_t *src = in->data[plane]; - uint8_t *dst = out->data[plane] + slice_start * dlinesize; - const int slinesize = in->linesize[plane]; - const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; - const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < out->width; x++) { - if (ymap[x] < in->height && xmap[x] < in->width) { - dst[x] = src[ymap[x] * slinesize + xmap[x]]; - } else { - dst[x] = 0; - } - } - dst += dlinesize; - xmap += xlinesize; - ymap += ylinesize; - } - } - - return 0; +#define DEFINE_REMAP_PLANAR_FUNC(name, bits, div) \ +static int remap_planar##bits##_##name##_slice(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + const ThreadData *td = arg; \ + const AVFrame *in = td->in; \ + const AVFrame *xin = td->xin; \ + const AVFrame *yin = td->yin; \ + const AVFrame *out = td->out; \ + const int slice_start = (out->height * jobnr ) / nb_jobs; \ + const int slice_end = (out->height * (jobnr+1)) / nb_jobs; \ + const int xlinesize = xin->linesize[0] / 2; \ + const int ylinesize = yin->linesize[0] / 2; \ + int x , y, plane; \ + \ + for (plane = 0; plane < td->nb_planes ; plane++) { \ + const int dlinesize = out->linesize[plane] / div; \ + const uint##bits##_t *src = (const uint##bits##_t *)in->data[plane]; \ + uint##bits##_t *dst = (uint##bits##_t *)out->data[plane] + slice_start * dlinesize; \ + const int slinesize = in->linesize[plane] / div; \ + const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; \ + const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; \ + \ + for (y = slice_start; y < slice_end; y++) { \ + for (x = 0; x < out->width; x++) { \ + if (ymap[x] < in->height && xmap[x] < in->width) { \ + dst[x] = src[ymap[x] * slinesize + xmap[x]]; \ + } else { \ + dst[x] = 0; \ + } \ + } \ + dst += dlinesize; \ + xmap += xlinesize; \ + ymap += ylinesize; \ + } \ + } \ + \ + return 0; \ } -static int remap_planar16_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - const ThreadData *td = (ThreadData*)arg; - const AVFrame *in = td->in; - const AVFrame *xin = td->xin; - const AVFrame *yin = td->yin; - const AVFrame *out = td->out; - - const int slice_start = (out->height * jobnr ) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - - const int xlinesize = xin->linesize[0] / 2; - const int ylinesize = yin->linesize[0] / 2; - int x , y, plane; - - for (plane = 0; plane < td->nb_planes ; plane++) { - const int dlinesize = out->linesize[plane] / 2; - const uint16_t *src = (const uint16_t *)in->data[plane]; - uint16_t *dst = (uint16_t *)out->data[plane] + slice_start * dlinesize; - const int slinesize = in->linesize[plane] / 2; - const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; - const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < out->width; x++) { - if (ymap[x] < in->height && xmap[x] < in->width) { - dst[x] = src[ymap[x] * slinesize + xmap[x]]; - } else { - dst[x] = 0; - } - } - dst += dlinesize; - xmap += xlinesize; - ymap += ylinesize; - } - } - - return 0; -} +DEFINE_REMAP_PLANAR_FUNC(nearest, 8, 1) +DEFINE_REMAP_PLANAR_FUNC(nearest, 16, 2) /** * remap_packed algorithm expects pixels with both padded bits (step) and @@ -212,85 +185,48 @@ static int remap_planar16_slice(AVFilterContext *ctx, void *arg, int jobnr, int * pixels are copied from source to target using : * Target_frame[y][x] = Source_frame[ ymap[y][x] ][ [xmap[y][x] ]; */ -static int remap_packed_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - const ThreadData *td = (ThreadData*)arg; - const AVFrame *in = td->in; - const AVFrame *xin = td->xin; - const AVFrame *yin = td->yin; - const AVFrame *out = td->out; - - const int slice_start = (out->height * jobnr ) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - - const int dlinesize = out->linesize[0]; - const int slinesize = in->linesize[0]; - const int xlinesize = xin->linesize[0] / 2; - const int ylinesize = yin->linesize[0] / 2; - const uint8_t *src = in->data[0]; - uint8_t *dst = out->data[0] + slice_start * dlinesize; - const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; - const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; - const int step = td->step; - int c, x, y; - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < out->width; x++) { - for (c = 0; c < td->nb_components; c++) { - if (ymap[x] < in->height && xmap[x] < in->width) { - dst[x * step + c] = src[ymap[x] * slinesize + xmap[x] * step + c]; - } else { - dst[x * step + c] = 0; - } - } - } - dst += dlinesize; - xmap += xlinesize; - ymap += ylinesize; - } - - return 0; +#define DEFINE_REMAP_PACKED_FUNC(name, bits, div) \ +static int remap_packed##bits##_##name##_slice(AVFilterContext *ctx, void *arg, \ + int jobnr, int nb_jobs) \ +{ \ + const ThreadData *td = arg; \ + const AVFrame *in = td->in; \ + const AVFrame *xin = td->xin; \ + const AVFrame *yin = td->yin; \ + const AVFrame *out = td->out; \ + const int slice_start = (out->height * jobnr ) / nb_jobs; \ + const int slice_end = (out->height * (jobnr+1)) / nb_jobs; \ + const int dlinesize = out->linesize[0] / div; \ + const int slinesize = in->linesize[0] / div; \ + const int xlinesize = xin->linesize[0] / 2; \ + const int ylinesize = yin->linesize[0] / 2; \ + const uint##bits##_t *src = (const uint##bits##_t *)in->data[0]; \ + uint##bits##_t *dst = (uint##bits##_t *)out->data[0] + slice_start * dlinesize; \ + const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; \ + const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; \ + const int step = td->step / div; \ + int c, x, y; \ + \ + for (y = slice_start; y < slice_end; y++) { \ + for (x = 0; x < out->width; x++) { \ + for (c = 0; c < td->nb_components; c++) { \ + if (ymap[x] < in->height && xmap[x] < in->width) { \ + dst[x * step + c] = src[ymap[x] * slinesize + xmap[x] * step + c]; \ + } else { \ + dst[x * step + c] = 0; \ + } \ + } \ + } \ + dst += dlinesize; \ + xmap += xlinesize; \ + ymap += ylinesize; \ + } \ + \ + return 0; \ } -static int remap_packed16_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) -{ - const ThreadData *td = (ThreadData*)arg; - const AVFrame *in = td->in; - const AVFrame *xin = td->xin; - const AVFrame *yin = td->yin; - const AVFrame *out = td->out; - - const int slice_start = (out->height * jobnr ) / nb_jobs; - const int slice_end = (out->height * (jobnr+1)) / nb_jobs; - - const int dlinesize = out->linesize[0] / 2; - const int slinesize = in->linesize[0] / 2; - const int xlinesize = xin->linesize[0] / 2; - const int ylinesize = yin->linesize[0] / 2; - const uint16_t *src = (const uint16_t *)in->data[0]; - uint16_t *dst = (uint16_t *)out->data[0] + slice_start * dlinesize; - const uint16_t *xmap = (const uint16_t *)xin->data[0] + slice_start * xlinesize; - const uint16_t *ymap = (const uint16_t *)yin->data[0] + slice_start * ylinesize; - const int step = td->step / 2; - int c, x, y; - - for (y = slice_start; y < slice_end; y++) { - for (x = 0; x < out->width; x++) { - for (c = 0; c < td->nb_components; c++) { - if (ymap[x] < in->height && xmap[x] < in->width) { - dst[x * step + c] = src[ymap[x] * slinesize + xmap[x] * step + c]; - } else { - dst[x * step + c] = 0; - } - } - } - dst += dlinesize; - xmap += xlinesize; - ymap += ylinesize; - } - - return 0; -} +DEFINE_REMAP_PACKED_FUNC(nearest, 8, 1) +DEFINE_REMAP_PACKED_FUNC(nearest, 16, 2) static int config_input(AVFilterLink *inlink) { @@ -303,15 +239,15 @@ static int config_input(AVFilterLink *inlink) if (desc->comp[0].depth == 8) { if (s->nb_planes > 1 || s->nb_components == 1) { - s->remap_slice = remap_planar_slice; + s->remap_slice = remap_planar8_nearest_slice; } else { - s->remap_slice = remap_packed_slice; + s->remap_slice = remap_packed8_nearest_slice; } } else { if (s->nb_planes > 1 || s->nb_components == 1) { - s->remap_slice = remap_planar16_slice; + s->remap_slice = remap_planar16_nearest_slice; } else { - s->remap_slice = remap_packed16_slice; + s->remap_slice = remap_packed16_nearest_slice; } } @@ -353,7 +289,7 @@ static int process_frame(FFFrameSync *fs) td.step = s->step; ctx->internal->execute(ctx, s->remap_slice, &td, NULL, FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); } - out->pts = av_rescale_q(in->pts, s->fs.time_base, outlink->time_base); + out->pts = av_rescale_q(s->fs.pts, s->fs.time_base, outlink->time_base); return ff_filter_frame(outlink, out); } @@ -379,7 +315,6 @@ static int config_output(AVFilterLink *outlink) outlink->w = xlink->w; outlink->h = xlink->h; - outlink->time_base = srclink->time_base; outlink->sample_aspect_ratio = srclink->sample_aspect_ratio; outlink->frame_rate = srclink->frame_rate; @@ -403,7 +338,10 @@ static int config_output(AVFilterLink *outlink) s->fs.opaque = s; s->fs.on_event = process_frame; - return ff_framesync_configure(&s->fs); + ret = ff_framesync_configure(&s->fs); + outlink->time_base = s->fs.time_base; + + return ret; } static int activate(AVFilterContext *ctx)