Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2010 Gordon Schmidt <gordon.schmidt <at> s2000.tu-chemnitz.de>
  3.  * Copyright (c) 2013 Paul B Mahol
  4.  *
  5.  * This file is part of FFmpeg.
  6.  *
  7.  * FFmpeg is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * FFmpeg is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License along
  18.  * with FFmpeg; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20.  */
  21.  
  22. #include "libavutil/avassert.h"
  23. #include "libavutil/imgutils.h"
  24. #include "libavutil/opt.h"
  25. #include "libavutil/parseutils.h"
  26. #include "libavutil/pixdesc.h"
  27. #include "avfilter.h"
  28. #include "drawutils.h"
  29. #include "formats.h"
  30. #include "internal.h"
  31. #include "video.h"
  32.  
  33. enum StereoCode {
  34.     ANAGLYPH_RC_GRAY,   // anaglyph red/cyan gray
  35.     ANAGLYPH_RC_HALF,   // anaglyph red/cyan half colored
  36.     ANAGLYPH_RC_COLOR,  // anaglyph red/cyan colored
  37.     ANAGLYPH_RC_DUBOIS, // anaglyph red/cyan dubois
  38.     ANAGLYPH_GM_GRAY,   // anaglyph green/magenta gray
  39.     ANAGLYPH_GM_HALF,   // anaglyph green/magenta half colored
  40.     ANAGLYPH_GM_COLOR,  // anaglyph green/magenta colored
  41.     ANAGLYPH_GM_DUBOIS, // anaglyph green/magenta dubois
  42.     ANAGLYPH_YB_GRAY,   // anaglyph yellow/blue gray
  43.     ANAGLYPH_YB_HALF,   // anaglyph yellow/blue half colored
  44.     ANAGLYPH_YB_COLOR,  // anaglyph yellow/blue colored
  45.     ANAGLYPH_YB_DUBOIS, // anaglyph yellow/blue dubois
  46.     ANAGLYPH_RB_GRAY,   // anaglyph red/blue gray
  47.     ANAGLYPH_RG_GRAY,   // anaglyph red/green gray
  48.     MONO_L,             // mono output for debugging (left eye only)
  49.     MONO_R,             // mono output for debugging (right eye only)
  50.     INTERLEAVE_ROWS_LR, // row-interleave (left eye has top row)
  51.     INTERLEAVE_ROWS_RL, // row-interleave (right eye has top row)
  52.     SIDE_BY_SIDE_LR,    // side by side parallel (left eye left, right eye right)
  53.     SIDE_BY_SIDE_RL,    // side by side crosseye (right eye left, left eye right)
  54.     SIDE_BY_SIDE_2_LR,  // side by side parallel with half width resolution
  55.     SIDE_BY_SIDE_2_RL,  // side by side crosseye with half width resolution
  56.     ABOVE_BELOW_LR,     // above-below (left eye above, right eye below)
  57.     ABOVE_BELOW_RL,     // above-below (right eye above, left eye below)
  58.     ABOVE_BELOW_2_LR,   // above-below with half height resolution
  59.     ABOVE_BELOW_2_RL,   // above-below with half height resolution
  60.     ALTERNATING_LR,     // alternating frames (left eye first, right eye second)
  61.     ALTERNATING_RL,     // alternating frames (right eye first, left eye second)
  62.     STEREO_CODE_COUNT   // TODO: needs autodetection
  63. };
  64.  
  65. typedef struct StereoComponent {
  66.     enum StereoCode format;
  67.     int width, height;
  68.     int off_left, off_right;
  69.     int off_lstep, off_rstep;
  70.     int row_left, row_right;
  71. } StereoComponent;
  72.  
  73. static const int ana_coeff[][3][6] = {
  74.   [ANAGLYPH_RB_GRAY]   =
  75.     {{19595, 38470,  7471,     0,     0,     0},
  76.      {    0,     0,     0,     0,     0,     0},
  77.      {    0,     0,     0, 19595, 38470,  7471}},
  78.   [ANAGLYPH_RG_GRAY]   =
  79.     {{19595, 38470,  7471,     0,     0,     0},
  80.      {    0,     0,     0, 19595, 38470,  7471},
  81.      {    0,     0,     0,     0,     0,     0}},
  82.   [ANAGLYPH_RC_GRAY]   =
  83.     {{19595, 38470,  7471,     0,     0,     0},
  84.      {    0,     0,     0, 19595, 38470,  7471},
  85.      {    0,     0,     0, 19595, 38470,  7471}},
  86.   [ANAGLYPH_RC_HALF]   =
  87.     {{19595, 38470,  7471,     0,     0,     0},
  88.      {    0,     0,     0,     0, 65536,     0},
  89.      {    0,     0,     0,     0,     0, 65536}},
  90.   [ANAGLYPH_RC_COLOR]  =
  91.     {{65536,     0,     0,     0,     0,     0},
  92.      {    0,     0,     0,     0, 65536,     0},
  93.      {    0,     0,     0,     0,     0, 65536}},
  94.   [ANAGLYPH_RC_DUBOIS] =
  95.     {{29891, 32800, 11559, -2849, -5763,  -102},
  96.      {-2627, -2479, -1033, 24804, 48080, -1209},
  97.      { -997, -1350,  -358, -4729, -7403, 80373}},
  98.   [ANAGLYPH_GM_GRAY]   =
  99.     {{    0,     0,     0, 19595, 38470,  7471},
  100.      {19595, 38470,  7471,     0,     0,     0},
  101.      {    0,     0,     0, 19595, 38470,  7471}},
  102.   [ANAGLYPH_GM_HALF]   =
  103.     {{    0,     0,     0, 65536,     0,     0},
  104.      {19595, 38470,  7471,     0,     0,     0},
  105.      {    0,     0,     0,     0,     0, 65536}},
  106.   [ANAGLYPH_GM_COLOR]  =
  107.     {{    0,     0,     0, 65536,     0,     0},
  108.      {    0, 65536,     0,     0,     0,     0},
  109.      {    0,     0,     0,     0,     0, 65536}},
  110.   [ANAGLYPH_GM_DUBOIS]  =
  111.     {{-4063,-10354, -2556, 34669, 46203,  1573},
  112.      {18612, 43778,  9372, -1049,  -983, -4260},
  113.      { -983, -1769,  1376,   590,  4915, 61407}},
  114.   [ANAGLYPH_YB_GRAY]   =
  115.     {{    0,     0,     0, 19595, 38470,  7471},
  116.      {    0,     0,     0, 19595, 38470,  7471},
  117.      {19595, 38470,  7471,     0,     0,     0}},
  118.   [ANAGLYPH_YB_HALF]   =
  119.     {{    0,     0,     0, 65536,     0,     0},
  120.      {    0,     0,     0,     0, 65536,     0},
  121.      {19595, 38470,  7471,     0,     0,     0}},
  122.   [ANAGLYPH_YB_COLOR]  =
  123.     {{    0,     0,     0, 65536,     0,     0},
  124.      {    0,     0,     0,     0, 65536,     0},
  125.      {    0,     0, 65536,     0,     0,     0}},
  126.   [ANAGLYPH_YB_DUBOIS] =
  127.     {{65535,-12650,18451,   -987, -7590, -1049},
  128.      {-1604, 56032, 4196,    370,  3826, -1049},
  129.      {-2345,-10676, 1358,   5801, 11416, 56217}},
  130. };
  131.  
  132. typedef struct Stereo3DContext {
  133.     const AVClass *class;
  134.     StereoComponent in, out;
  135.     int width, height;
  136.     int row_step;
  137.     const int *ana_matrix[3];
  138.     int nb_planes;
  139.     int linesize[4];
  140.     int pheight[4];
  141.     int hsub, vsub;
  142.     int pixstep[4];
  143.     AVFrame *prev;
  144.     double ts_unit;
  145. } Stereo3DContext;
  146.  
  147. #define OFFSET(x) offsetof(Stereo3DContext, x)
  148. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  149.  
  150. static const AVOption stereo3d_options[] = {
  151.     { "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"},
  152.     { "ab2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},  0, 0, FLAGS, "in" },
  153.     { "ab2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},  0, 0, FLAGS, "in" },
  154.     { "abl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},    0, 0, FLAGS, "in" },
  155.     { "abr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},    0, 0, FLAGS, "in" },
  156.     { "al",    "alternating frames left first",       0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR},    0, 0, FLAGS, "in" },
  157.     { "ar",    "alternating frames right first",      0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL},    0, 0, FLAGS, "in" },
  158.     { "sbs2l", "side by side half width left first",  0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, "in" },
  159.     { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL}, 0, 0, FLAGS, "in" },
  160.     { "sbsl",  "side by side left first",             0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR},   0, 0, FLAGS, "in" },
  161.     { "sbsr",  "side by side right first",            0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL},   0, 0, FLAGS, "in" },
  162.     { "out",   "set output format", OFFSET(out.format), AV_OPT_TYPE_INT, {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, "out"},
  163.     { "ab2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},   0, 0, FLAGS, "out" },
  164.     { "ab2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},   0, 0, FLAGS, "out" },
  165.     { "abl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},     0, 0, FLAGS, "out" },
  166.     { "abr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},     0, 0, FLAGS, "out" },
  167.     { "agmc",  "anaglyph green magenta color",        0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_COLOR},  0, 0, FLAGS, "out" },
  168.     { "agmd",  "anaglyph green magenta dubois",       0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_DUBOIS}, 0, 0, FLAGS, "out" },
  169.     { "agmg",  "anaglyph green magenta gray",         0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_GRAY},   0, 0, FLAGS, "out" },
  170.     { "agmh",  "anaglyph green magenta half color",   0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_HALF},   0, 0, FLAGS, "out" },
  171.     { "al",    "alternating frames left first",       0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR},     0, 0, FLAGS, "out" },
  172.     { "ar",    "alternating frames right first",      0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL},     0, 0, FLAGS, "out" },
  173.     { "arbg",  "anaglyph red blue gray",              0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RB_GRAY},   0, 0, FLAGS, "out" },
  174.     { "arcc",  "anaglyph red cyan color",             0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_COLOR},  0, 0, FLAGS, "out" },
  175.     { "arcd",  "anaglyph red cyan dubois",            0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_DUBOIS}, 0, 0, FLAGS, "out" },
  176.     { "arcg",  "anaglyph red cyan gray",              0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_GRAY},   0, 0, FLAGS, "out" },
  177.     { "arch",  "anaglyph red cyan half color",        0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_HALF},   0, 0, FLAGS, "out" },
  178.     { "argg",  "anaglyph red green gray",             0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RG_GRAY},   0, 0, FLAGS, "out" },
  179.     { "aybc",  "anaglyph yellow blue color",          0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_COLOR},  0, 0, FLAGS, "out" },
  180.     { "aybd",  "anaglyph yellow blue dubois",         0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_DUBOIS}, 0, 0, FLAGS, "out" },
  181.     { "aybg",  "anaglyph yellow blue gray",           0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_GRAY},   0, 0, FLAGS, "out" },
  182.     { "aybh",  "anaglyph yellow blue half color",     0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_HALF},   0, 0, FLAGS, "out" },
  183.     { "irl",   "interleave rows left first",          0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, "out" },
  184.     { "irr",   "interleave rows right first",         0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, "out" },
  185.     { "ml",    "mono left",                           0, AV_OPT_TYPE_CONST, {.i64=MONO_L},             0, 0, FLAGS, "out" },
  186.     { "mr",    "mono right",                          0, AV_OPT_TYPE_CONST, {.i64=MONO_R},             0, 0, FLAGS, "out" },
  187.     { "sbs2l", "side by side half width left first",  0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR},  0, 0, FLAGS, "out" },
  188.     { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL},  0, 0, FLAGS, "out" },
  189.     { "sbsl",  "side by side left first",             0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR},    0, 0, FLAGS, "out" },
  190.     { "sbsr",  "side by side right first",            0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL},    0, 0, FLAGS, "out" },
  191.     { NULL }
  192. };
  193.  
  194. AVFILTER_DEFINE_CLASS(stereo3d);
  195.  
  196. static const enum AVPixelFormat anaglyph_pix_fmts[] = {
  197.     AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
  198.     AV_PIX_FMT_NONE
  199. };
  200.  
  201. static const enum AVPixelFormat other_pix_fmts[] = {
  202.     AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
  203.     AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE,
  204.     AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE,
  205.     AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_BGRA64BE,
  206.     AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE,
  207.     AV_PIX_FMT_RGBA,  AV_PIX_FMT_BGRA,
  208.     AV_PIX_FMT_ARGB,  AV_PIX_FMT_ABGR,
  209.     AV_PIX_FMT_RGB0,  AV_PIX_FMT_BGR0,
  210.     AV_PIX_FMT_0RGB,  AV_PIX_FMT_0BGR,
  211.     AV_PIX_FMT_GBRP,
  212.     AV_PIX_FMT_GBRP9BE,  AV_PIX_FMT_GBRP9LE,
  213.     AV_PIX_FMT_GBRP10BE, AV_PIX_FMT_GBRP10LE,
  214.     AV_PIX_FMT_GBRP12BE, AV_PIX_FMT_GBRP12LE,
  215.     AV_PIX_FMT_GBRP14BE, AV_PIX_FMT_GBRP14LE,
  216.     AV_PIX_FMT_GBRP16BE, AV_PIX_FMT_GBRP16LE,
  217.     AV_PIX_FMT_YUV410P,
  218.     AV_PIX_FMT_YUV411P,
  219.     AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
  220.     AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P,
  221.     AV_PIX_FMT_YUV440P,
  222.     AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P,
  223.     AV_PIX_FMT_YUVJ411P,
  224.     AV_PIX_FMT_YUVJ420P,
  225.     AV_PIX_FMT_YUVJ422P,
  226.     AV_PIX_FMT_YUVJ440P,
  227.     AV_PIX_FMT_YUVJ444P,
  228.     AV_PIX_FMT_YUV420P9LE,  AV_PIX_FMT_YUVA420P9LE,
  229.     AV_PIX_FMT_YUV420P9BE,  AV_PIX_FMT_YUVA420P9BE,
  230.     AV_PIX_FMT_YUV422P9LE,  AV_PIX_FMT_YUVA422P9LE,
  231.     AV_PIX_FMT_YUV422P9BE,  AV_PIX_FMT_YUVA422P9BE,
  232.     AV_PIX_FMT_YUV444P9LE,  AV_PIX_FMT_YUVA444P9LE,
  233.     AV_PIX_FMT_YUV444P9BE,  AV_PIX_FMT_YUVA444P9BE,
  234.     AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE,
  235.     AV_PIX_FMT_YUV420P10BE, AV_PIX_FMT_YUVA420P10BE,
  236.     AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUVA422P10LE,
  237.     AV_PIX_FMT_YUV422P10BE, AV_PIX_FMT_YUVA422P10BE,
  238.     AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUVA444P10LE,
  239.     AV_PIX_FMT_YUV444P10BE, AV_PIX_FMT_YUVA444P10BE,
  240.     AV_PIX_FMT_YUV420P12BE,  AV_PIX_FMT_YUV420P12LE,
  241.     AV_PIX_FMT_YUV422P12BE,  AV_PIX_FMT_YUV422P12LE,
  242.     AV_PIX_FMT_YUV444P12BE,  AV_PIX_FMT_YUV444P12LE,
  243.     AV_PIX_FMT_YUV420P14BE,  AV_PIX_FMT_YUV420P14LE,
  244.     AV_PIX_FMT_YUV422P14BE,  AV_PIX_FMT_YUV422P14LE,
  245.     AV_PIX_FMT_YUV444P14BE,  AV_PIX_FMT_YUV444P14LE,
  246.     AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE,
  247.     AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_YUVA420P16BE,
  248.     AV_PIX_FMT_YUV422P16LE, AV_PIX_FMT_YUVA422P16LE,
  249.     AV_PIX_FMT_YUV422P16BE, AV_PIX_FMT_YUVA422P16BE,
  250.     AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE,
  251.     AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE,
  252.     AV_PIX_FMT_NONE
  253. };
  254.  
  255. static int query_formats(AVFilterContext *ctx)
  256. {
  257.     Stereo3DContext *s = ctx->priv;
  258.     const enum AVPixelFormat *pix_fmts;
  259.  
  260.     switch (s->out.format) {
  261.     case ANAGLYPH_GM_COLOR:
  262.     case ANAGLYPH_GM_DUBOIS:
  263.     case ANAGLYPH_GM_GRAY:
  264.     case ANAGLYPH_GM_HALF:
  265.     case ANAGLYPH_RB_GRAY:
  266.     case ANAGLYPH_RC_COLOR:
  267.     case ANAGLYPH_RC_DUBOIS:
  268.     case ANAGLYPH_RC_GRAY:
  269.     case ANAGLYPH_RC_HALF:
  270.     case ANAGLYPH_RG_GRAY:
  271.     case ANAGLYPH_YB_COLOR:
  272.     case ANAGLYPH_YB_DUBOIS:
  273.     case ANAGLYPH_YB_GRAY:
  274.     case ANAGLYPH_YB_HALF:
  275.         pix_fmts = anaglyph_pix_fmts;
  276.         break;
  277.     default:
  278.         pix_fmts = other_pix_fmts;
  279.     }
  280.  
  281.     ff_set_common_formats(ctx, ff_make_format_list(pix_fmts));
  282.  
  283.     return 0;
  284. }
  285.  
  286. static int config_output(AVFilterLink *outlink)
  287. {
  288.     AVFilterContext *ctx = outlink->src;
  289.     AVFilterLink *inlink = ctx->inputs[0];
  290.     Stereo3DContext *s = ctx->priv;
  291.     AVRational aspect = inlink->sample_aspect_ratio;
  292.     AVRational fps = inlink->frame_rate;
  293.     AVRational tb = inlink->time_base;
  294.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
  295.     int ret;
  296.  
  297.     switch (s->in.format) {
  298.     case SIDE_BY_SIDE_2_LR:
  299.     case SIDE_BY_SIDE_LR:
  300.     case SIDE_BY_SIDE_2_RL:
  301.     case SIDE_BY_SIDE_RL:
  302.         if (inlink->w & 1) {
  303.             av_log(ctx, AV_LOG_ERROR, "width must be even\n");
  304.             return AVERROR_INVALIDDATA;
  305.         }
  306.         break;
  307.     case ABOVE_BELOW_2_LR:
  308.     case ABOVE_BELOW_LR:
  309.     case ABOVE_BELOW_2_RL:
  310.     case ABOVE_BELOW_RL:
  311.         if (s->out.format == INTERLEAVE_ROWS_LR ||
  312.             s->out.format == INTERLEAVE_ROWS_RL) {
  313.             if (inlink->h & 3) {
  314.                 av_log(ctx, AV_LOG_ERROR, "height must be multiple of 4\n");
  315.                 return AVERROR_INVALIDDATA;
  316.             }
  317.         }
  318.         if (inlink->h & 1) {
  319.             av_log(ctx, AV_LOG_ERROR, "height must be even\n");
  320.             return AVERROR_INVALIDDATA;
  321.         }
  322.         break;
  323.     }
  324.  
  325.     s->in.width     =
  326.     s->width        = inlink->w;
  327.     s->in.height    =
  328.     s->height       = inlink->h;
  329.     s->row_step     = 1;
  330.     s->in.off_lstep =
  331.     s->in.off_rstep =
  332.     s->in.off_left  =
  333.     s->in.off_right =
  334.     s->in.row_left  =
  335.     s->in.row_right = 0;
  336.  
  337.     switch (s->in.format) {
  338.     case SIDE_BY_SIDE_2_LR:
  339.         aspect.num     *= 2;
  340.     case SIDE_BY_SIDE_LR:
  341.         s->width        = inlink->w / 2;
  342.         s->in.off_right = s->width;
  343.         break;
  344.     case SIDE_BY_SIDE_2_RL:
  345.         aspect.num     *= 2;
  346.     case SIDE_BY_SIDE_RL:
  347.         s->width        = inlink->w / 2;
  348.         s->in.off_left  = s->width;
  349.         break;
  350.     case ABOVE_BELOW_2_LR:
  351.         aspect.den     *= 2;
  352.     case ABOVE_BELOW_LR:
  353.         s->in.row_right =
  354.         s->height       = inlink->h / 2;
  355.         break;
  356.     case ABOVE_BELOW_2_RL:
  357.         aspect.den     *= 2;
  358.     case ABOVE_BELOW_RL:
  359.         s->in.row_left  =
  360.         s->height       = inlink->h / 2;
  361.         break;
  362.     case ALTERNATING_RL:
  363.     case ALTERNATING_LR:
  364.         outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
  365.         fps.den        *= 2;
  366.         tb.num         *= 2;
  367.         break;
  368.     default:
  369.         av_log(ctx, AV_LOG_ERROR, "input format %d is not supported\n", s->in.format);
  370.         return AVERROR(EINVAL);
  371.     }
  372.  
  373.     s->out.width     = s->width;
  374.     s->out.height    = s->height;
  375.     s->out.off_lstep =
  376.     s->out.off_rstep =
  377.     s->out.off_left  =
  378.     s->out.off_right =
  379.     s->out.row_left  =
  380.     s->out.row_right = 0;
  381.  
  382.     switch (s->out.format) {
  383.     case ANAGLYPH_RB_GRAY:
  384.     case ANAGLYPH_RG_GRAY:
  385.     case ANAGLYPH_RC_GRAY:
  386.     case ANAGLYPH_RC_HALF:
  387.     case ANAGLYPH_RC_COLOR:
  388.     case ANAGLYPH_RC_DUBOIS:
  389.     case ANAGLYPH_GM_GRAY:
  390.     case ANAGLYPH_GM_HALF:
  391.     case ANAGLYPH_GM_COLOR:
  392.     case ANAGLYPH_GM_DUBOIS:
  393.     case ANAGLYPH_YB_GRAY:
  394.     case ANAGLYPH_YB_HALF:
  395.     case ANAGLYPH_YB_COLOR:
  396.     case ANAGLYPH_YB_DUBOIS: {
  397.         uint8_t rgba_map[4];
  398.  
  399.         ff_fill_rgba_map(rgba_map, outlink->format);
  400.         s->ana_matrix[rgba_map[0]] = &ana_coeff[s->out.format][0][0];
  401.         s->ana_matrix[rgba_map[1]] = &ana_coeff[s->out.format][1][0];
  402.         s->ana_matrix[rgba_map[2]] = &ana_coeff[s->out.format][2][0];
  403.         break;
  404.     }
  405.     case SIDE_BY_SIDE_2_LR:
  406.         aspect.den      *= 2;
  407.     case SIDE_BY_SIDE_LR:
  408.         s->out.width     = s->width * 2;
  409.         s->out.off_right = s->width;
  410.         break;
  411.     case SIDE_BY_SIDE_2_RL:
  412.         aspect.den      *= 2;
  413.     case SIDE_BY_SIDE_RL:
  414.         s->out.width     = s->width * 2;
  415.         s->out.off_left  = s->width;
  416.         break;
  417.     case ABOVE_BELOW_2_LR:
  418.         aspect.num      *= 2;
  419.     case ABOVE_BELOW_LR:
  420.         s->out.height    = s->height * 2;
  421.         s->out.row_right = s->height;
  422.         break;
  423.     case ABOVE_BELOW_2_RL:
  424.         aspect.num      *= 2;
  425.     case ABOVE_BELOW_RL:
  426.         s->out.height    = s->height * 2;
  427.         s->out.row_left  = s->height;
  428.         break;
  429.     case INTERLEAVE_ROWS_LR:
  430.         s->row_step      = 2;
  431.         s->height        = s->height / 2;
  432.         s->out.off_rstep =
  433.         s->in.off_rstep  = 1;
  434.         break;
  435.     case INTERLEAVE_ROWS_RL:
  436.         s->row_step      = 2;
  437.         s->height        = s->height / 2;
  438.         s->out.off_lstep =
  439.         s->in.off_lstep  = 1;
  440.         break;
  441.     case MONO_R:
  442.         s->in.off_left   = s->in.off_right;
  443.         s->in.row_left   = s->in.row_right;
  444.     case MONO_L:
  445.         break;
  446.     case ALTERNATING_RL:
  447.     case ALTERNATING_LR:
  448.         fps.num         *= 2;
  449.         tb.den          *= 2;
  450.         break;
  451.     default:
  452.         av_log(ctx, AV_LOG_ERROR, "output format %d is not supported\n", s->out.format);
  453.         return AVERROR(EINVAL);
  454.     }
  455.  
  456.     outlink->w = s->out.width;
  457.     outlink->h = s->out.height;
  458.     outlink->frame_rate = fps;
  459.     outlink->time_base = tb;
  460.     outlink->sample_aspect_ratio = aspect;
  461.  
  462.     if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, s->width)) < 0)
  463.         return ret;
  464.     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
  465.     av_image_fill_max_pixsteps(s->pixstep, NULL, desc);
  466.     s->ts_unit = av_q2d(av_inv_q(av_mul_q(outlink->frame_rate, outlink->time_base)));
  467.     s->pheight[1] = s->pheight[2] = FF_CEIL_RSHIFT(s->height, desc->log2_chroma_h);
  468.     s->pheight[0] = s->pheight[3] = s->height;
  469.     s->hsub = desc->log2_chroma_w;
  470.     s->vsub = desc->log2_chroma_h;
  471.  
  472.     return 0;
  473. }
  474.  
  475. static inline uint8_t ana_convert(const int *coeff, const uint8_t *left, const uint8_t *right)
  476. {
  477.     int sum;
  478.  
  479.     sum  = coeff[0] * left[0] + coeff[3] * right[0]; //red in
  480.     sum += coeff[1] * left[1] + coeff[4] * right[1]; //green in
  481.     sum += coeff[2] * left[2] + coeff[5] * right[2]; //blue in
  482.  
  483.     return av_clip_uint8(sum >> 16);
  484. }
  485.  
  486. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  487. {
  488.     AVFilterContext *ctx  = inlink->dst;
  489.     Stereo3DContext *s = ctx->priv;
  490.     AVFilterLink *outlink = ctx->outputs[0];
  491.     AVFrame *out, *oleft, *oright, *ileft, *iright;
  492.     int out_off_left[4], out_off_right[4];
  493.     int in_off_left[4], in_off_right[4];
  494.     int i;
  495.  
  496.     switch (s->in.format) {
  497.     case ALTERNATING_LR:
  498.     case ALTERNATING_RL:
  499.         if (!s->prev) {
  500.             s->prev = inpicref;
  501.             return 0;
  502.         }
  503.         ileft  = s->prev;
  504.         iright = inpicref;
  505.         if (s->in.format == ALTERNATING_RL)
  506.             FFSWAP(AVFrame *, ileft, iright);
  507.         break;
  508.     default:
  509.         ileft = iright = inpicref;
  510.     };
  511.  
  512.     out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  513.     if (!out) {
  514.         av_frame_free(&s->prev);
  515.         av_frame_free(&inpicref);
  516.         return AVERROR(ENOMEM);
  517.     }
  518.     av_frame_copy_props(out, inpicref);
  519.  
  520.     if (s->out.format == ALTERNATING_LR ||
  521.         s->out.format == ALTERNATING_RL) {
  522.         oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  523.         if (!oright) {
  524.             av_frame_free(&oleft);
  525.             av_frame_free(&s->prev);
  526.             av_frame_free(&inpicref);
  527.             return AVERROR(ENOMEM);
  528.         }
  529.         av_frame_copy_props(oright, inpicref);
  530.     }
  531.  
  532.     for (i = 0; i < 4; i++) {
  533.         int hsub = i == 1 || i == 2 ? s->hsub : 0;
  534.         int vsub = i == 1 || i == 2 ? s->vsub : 0;
  535.         in_off_left[i]   = (FF_CEIL_RSHIFT(s->in.row_left,   vsub) + s->in.off_lstep)  * ileft->linesize[i]  + FF_CEIL_RSHIFT(s->in.off_left   * s->pixstep[i], hsub);
  536.         in_off_right[i]  = (FF_CEIL_RSHIFT(s->in.row_right,  vsub) + s->in.off_rstep)  * iright->linesize[i] + FF_CEIL_RSHIFT(s->in.off_right  * s->pixstep[i], hsub);
  537.         out_off_left[i]  = (FF_CEIL_RSHIFT(s->out.row_left,  vsub) + s->out.off_lstep) * oleft->linesize[i]  + FF_CEIL_RSHIFT(s->out.off_left  * s->pixstep[i], hsub);
  538.         out_off_right[i] = (FF_CEIL_RSHIFT(s->out.row_right, vsub) + s->out.off_rstep) * oright->linesize[i] + FF_CEIL_RSHIFT(s->out.off_right * s->pixstep[i], hsub);
  539.     }
  540.  
  541.     switch (s->out.format) {
  542.     case ALTERNATING_LR:
  543.     case ALTERNATING_RL:
  544.     case SIDE_BY_SIDE_LR:
  545.     case SIDE_BY_SIDE_RL:
  546.     case SIDE_BY_SIDE_2_LR:
  547.     case SIDE_BY_SIDE_2_RL:
  548.     case ABOVE_BELOW_LR:
  549.     case ABOVE_BELOW_RL:
  550.     case ABOVE_BELOW_2_LR:
  551.     case ABOVE_BELOW_2_RL:
  552.     case INTERLEAVE_ROWS_LR:
  553.     case INTERLEAVE_ROWS_RL:
  554.         for (i = 0; i < s->nb_planes; i++) {
  555.             av_image_copy_plane(oleft->data[i] + out_off_left[i],
  556.                                 oleft->linesize[i] * s->row_step,
  557.                                 ileft->data[i] + in_off_left[i],
  558.                                 ileft->linesize[i] * s->row_step,
  559.                                 s->linesize[i], s->pheight[i]);
  560.             av_image_copy_plane(oright->data[i] + out_off_right[i],
  561.                                 oright->linesize[i] * s->row_step,
  562.                                 iright->data[i] + in_off_right[i],
  563.                                 iright->linesize[i] * s->row_step,
  564.                                 s->linesize[i], s->pheight[i]);
  565.         }
  566.         break;
  567.     case MONO_L:
  568.         iright = ileft;
  569.     case MONO_R:
  570.         for (i = 0; i < s->nb_planes; i++) {
  571.             av_image_copy_plane(out->data[i], out->linesize[i],
  572.                                 iright->data[i] + in_off_left[i],
  573.                                 iright->linesize[i],
  574.                                 s->linesize[i], s->pheight[i]);
  575.         }
  576.         break;
  577.     case ANAGLYPH_RB_GRAY:
  578.     case ANAGLYPH_RG_GRAY:
  579.     case ANAGLYPH_RC_GRAY:
  580.     case ANAGLYPH_RC_HALF:
  581.     case ANAGLYPH_RC_COLOR:
  582.     case ANAGLYPH_RC_DUBOIS:
  583.     case ANAGLYPH_GM_GRAY:
  584.     case ANAGLYPH_GM_HALF:
  585.     case ANAGLYPH_GM_COLOR:
  586.     case ANAGLYPH_GM_DUBOIS:
  587.     case ANAGLYPH_YB_GRAY:
  588.     case ANAGLYPH_YB_HALF:
  589.     case ANAGLYPH_YB_COLOR:
  590.     case ANAGLYPH_YB_DUBOIS: {
  591.         int x, y, il, ir, o;
  592.         const uint8_t *lsrc = ileft->data[0];
  593.         const uint8_t *rsrc = iright->data[0];
  594.         uint8_t *dst = out->data[0];
  595.         int out_width = s->out.width;
  596.         const int **ana_matrix = s->ana_matrix;
  597.  
  598.         for (y = 0; y < s->out.height; y++) {
  599.             o   = out->linesize[0] * y;
  600.             il  = in_off_left[0]  + y * ileft->linesize[0];
  601.             ir  = in_off_right[0] + y * iright->linesize[0];
  602.             for (x = 0; x < out_width; x++, il += 3, ir += 3, o+= 3) {
  603.                 dst[o    ] = ana_convert(ana_matrix[0], lsrc + il, rsrc + ir);
  604.                 dst[o + 1] = ana_convert(ana_matrix[1], lsrc + il, rsrc + ir);
  605.                 dst[o + 2] = ana_convert(ana_matrix[2], lsrc + il, rsrc + ir);
  606.             }
  607.         }
  608.         break;
  609.     }
  610.     default:
  611.         av_assert0(0);
  612.     }
  613.  
  614.     av_frame_free(&inpicref);
  615.     av_frame_free(&s->prev);
  616.     if (oright != oleft) {
  617.         if (s->out.format == ALTERNATING_LR)
  618.             FFSWAP(AVFrame *, oleft, oright);
  619.         oright->pts = outlink->frame_count * s->ts_unit;
  620.         ff_filter_frame(outlink, oright);
  621.         out = oleft;
  622.         oleft->pts = outlink->frame_count * s->ts_unit;
  623.     } else if (s->in.format == ALTERNATING_LR ||
  624.                s->in.format == ALTERNATING_RL) {
  625.         out->pts = outlink->frame_count * s->ts_unit;
  626.     }
  627.     return ff_filter_frame(outlink, out);
  628. }
  629.  
  630. static av_cold void uninit(AVFilterContext *ctx)
  631. {
  632.     Stereo3DContext *s = ctx->priv;
  633.  
  634.     av_frame_free(&s->prev);
  635. }
  636.  
  637. static const AVFilterPad stereo3d_inputs[] = {
  638.     {
  639.         .name         = "default",
  640.         .type         = AVMEDIA_TYPE_VIDEO,
  641.         .filter_frame = filter_frame,
  642.     },
  643.     { NULL }
  644. };
  645.  
  646. static const AVFilterPad stereo3d_outputs[] = {
  647.     {
  648.         .name         = "default",
  649.         .type         = AVMEDIA_TYPE_VIDEO,
  650.         .config_props = config_output,
  651.     },
  652.     { NULL }
  653. };
  654.  
  655. AVFilter avfilter_vf_stereo3d = {
  656.     .name          = "stereo3d",
  657.     .description   = NULL_IF_CONFIG_SMALL("Convert video stereoscopic 3D view."),
  658.     .priv_size     = sizeof(Stereo3DContext),
  659.     .uninit        = uninit,
  660.     .query_formats = query_formats,
  661.     .inputs        = stereo3d_inputs,
  662.     .outputs       = stereo3d_outputs,
  663.     .priv_class    = &stereo3d_class,
  664. };
  665.