From 4b2bafbd4c8ecba0d6d4c932b0acab185be5b7c5 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Sat, 5 Sep 2015 00:05:50 +0000 Subject: [PATCH] avfilter/vf_stereo3d: support interleaved rows as input format Signed-off-by: Paul B Mahol --- libavfilter/vf_stereo3d.c | 82 ++++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/libavfilter/vf_stereo3d.c b/libavfilter/vf_stereo3d.c index e696fab6a4..af837de2af 100644 --- a/libavfilter/vf_stereo3d.c +++ b/libavfilter/vf_stereo3d.c @@ -71,6 +71,7 @@ typedef struct StereoComponent { int off_left, off_right; int off_lstep, off_rstep; int row_left, row_right; + int row_step; } StereoComponent; static const int ana_coeff[][3][6] = { @@ -136,7 +137,6 @@ typedef struct Stereo3DContext { const AVClass *class; StereoComponent in, out; int width, height; - int row_step; const int *ana_matrix[3]; int nb_planes; int linesize[4]; @@ -152,18 +152,20 @@ typedef struct Stereo3DContext { #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM static const AVOption stereo3d_options[] = { - { "in", "set input format", OFFSET(in.format), AV_OPT_TYPE_INT, {.i64=SIDE_BY_SIDE_LR}, SIDE_BY_SIDE_LR, STEREO_CODE_COUNT-1, FLAGS, "in"}, - { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "in" }, - { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "in" }, - { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "in" }, - { "abr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, "in" }, - { "al", "alternating frames left first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR}, 0, 0, FLAGS, "in" }, - { "ar", "alternating frames right first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL}, 0, 0, FLAGS, "in" }, - { "sbs2l", "side by side half width left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, "in" }, - { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL}, 0, 0, FLAGS, "in" }, - { "sbsl", "side by side left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR}, 0, 0, FLAGS, "in" }, - { "sbsr", "side by side right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL}, 0, 0, FLAGS, "in" }, - { "out", "set output format", OFFSET(out.format), AV_OPT_TYPE_INT, {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, "out"}, + { "in", "set input format", OFFSET(in.format), AV_OPT_TYPE_INT, {.i64=SIDE_BY_SIDE_LR}, INTERLEAVE_ROWS_LR, STEREO_CODE_COUNT-1, FLAGS, "in"}, + { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "in" }, + { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "in" }, + { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "in" }, + { "abr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, "in" }, + { "al", "alternating frames left first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR}, 0, 0, FLAGS, "in" }, + { "ar", "alternating frames right first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL}, 0, 0, FLAGS, "in" }, + { "sbs2l", "side by side half width left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, "in" }, + { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL}, 0, 0, FLAGS, "in" }, + { "sbsl", "side by side left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR}, 0, 0, FLAGS, "in" }, + { "sbsr", "side by side right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL}, 0, 0, FLAGS, "in" }, + { "irl", "interleave rows left first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, "in" }, + { "irr", "interleave rows right first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, "in" }, + { "out", "set output format", OFFSET(out.format), AV_OPT_TYPE_INT, {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, "out"}, { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, "out" }, { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, "out" }, { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, "out" }, @@ -312,6 +314,8 @@ static int config_output(AVFilterLink *outlink) return AVERROR_INVALIDDATA; } break; + case INTERLEAVE_ROWS_LR: + case INTERLEAVE_ROWS_RL: case ABOVE_BELOW_2_LR: case ABOVE_BELOW_LR: case ABOVE_BELOW_2_RL: @@ -334,13 +338,13 @@ static int config_output(AVFilterLink *outlink) s->width = inlink->w; s->in.height = s->height = inlink->h; - s->row_step = 1; s->in.off_lstep = s->in.off_rstep = s->in.off_left = s->in.off_right = s->in.row_left = s->in.row_right = 0; + s->in.row_step = 1; switch (s->in.format) { case SIDE_BY_SIDE_2_LR: @@ -373,6 +377,19 @@ static int config_output(AVFilterLink *outlink) fps.den *= 2; tb.num *= 2; break; + case INTERLEAVE_ROWS_LR: + case INTERLEAVE_ROWS_RL: + s->in.row_step = 2; + if (s->in.format == INTERLEAVE_ROWS_RL) + s->in.off_lstep = 1; + else + s->in.off_rstep = 1; + if (s->out.format != INTERLEAVE_ROWS_LR && + s->out.format != INTERLEAVE_ROWS_RL && + s->out.format != CHECKERBOARD_LR && + s->out.format != CHECKERBOARD_RL) + s->height = inlink->h / 2; + break; default: av_log(ctx, AV_LOG_ERROR, "input format %d is not supported\n", s->in.format); return AVERROR(EINVAL); @@ -386,6 +403,7 @@ static int config_output(AVFilterLink *outlink) s->out.off_right = s->out.row_left = s->out.row_right = 0; + s->out.row_step = 1; switch (s->out.format) { case ANAGLYPH_RB_GRAY: @@ -435,21 +453,28 @@ static int config_output(AVFilterLink *outlink) s->out.row_left = s->height; break; case INTERLEAVE_ROWS_LR: - s->row_step = 2; + s->in.row_step = 2; + s->out.row_step = 2; s->height = s->height / 2; - s->out.off_rstep = - s->in.off_rstep = 1; + s->out.off_rstep = 1; + s->in.off_rstep = s->in.format != INTERLEAVE_ROWS_RL; break; case INTERLEAVE_ROWS_RL: - s->row_step = 2; + s->in.row_step = 2; + s->out.row_step = 2; s->height = s->height / 2; - s->out.off_lstep = - s->in.off_lstep = 1; + s->out.off_lstep = 1; + s->in.off_lstep = s->in.format != INTERLEAVE_ROWS_LR; break; case MONO_R: s->in.off_left = s->in.off_right; s->in.row_left = s->in.row_right; + if (s->in.format == INTERLEAVE_ROWS_LR) + FFSWAP(int, s->in.off_lstep, s->in.off_rstep); + break; case MONO_L: + if (s->in.format == INTERLEAVE_ROWS_RL) + FFSWAP(int, s->in.off_lstep, s->in.off_rstep); break; case ALTERNATING_RL: case ALTERNATING_LR: @@ -519,8 +544,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) for (y = start; y < end; y++) { o = out->linesize[0] * y; - il = s->in_off_left[0] + y * ileft->linesize[0]; - ir = s->in_off_right[0] + y * iright->linesize[0]; + il = s->in_off_left[0] + y * ileft->linesize[0] * s->in.row_step; + ir = s->in_off_right[0] + y * iright->linesize[0] * s->in.row_step; for (x = 0; x < out_width; x++, il += 3, ir += 3, o+= 3) { dst[o ] = ana_convert(ana_matrix[0], lsrc + il, rsrc + ir); dst[o + 1] = ana_convert(ana_matrix[1], lsrc + il, rsrc + ir); @@ -540,6 +565,9 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) int out_off_left[4], out_off_right[4]; int i; + if (s->in.format == s->out.format) + return ff_filter_frame(outlink, inpicref); + switch (s->in.format) { case ALTERNATING_LR: case ALTERNATING_RL: @@ -600,14 +628,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) case INTERLEAVE_ROWS_RL: for (i = 0; i < s->nb_planes; i++) { av_image_copy_plane(oleft->data[i] + out_off_left[i], - oleft->linesize[i] * s->row_step, + oleft->linesize[i] * s->out.row_step, ileft->data[i] + s->in_off_left[i], - ileft->linesize[i] * s->row_step, + ileft->linesize[i] * s->in.row_step, s->linesize[i], s->pheight[i]); av_image_copy_plane(oright->data[i] + out_off_right[i], - oright->linesize[i] * s->row_step, + oright->linesize[i] * s->out.row_step, iright->data[i] + s->in_off_right[i], - iright->linesize[i] * s->row_step, + iright->linesize[i] * s->in.row_step, s->linesize[i], s->pheight[i]); } break; @@ -617,7 +645,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) for (i = 0; i < s->nb_planes; i++) { av_image_copy_plane(out->data[i], out->linesize[i], iright->data[i] + s->in_off_left[i], - iright->linesize[i], + iright->linesize[i] * s->in.row_step, s->linesize[i], s->pheight[i]); } break;