mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-26 17:32:06 +00:00
avfilter/vf_stereo3d: support interleaved rows as input format
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
09812e1200
commit
4b2bafbd4c
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user