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.     int format;                 ///< StereoCode
  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.     int in_off_left[4], in_off_right[4];
  146. } Stereo3DContext;
  147.  
  148. #define OFFSET(x) offsetof(Stereo3DContext, x)
  149. #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
  150.  
  151. static const AVOption stereo3d_options[] = {
  152.     { "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"},
  153.     { "ab2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},  0, 0, FLAGS, "in" },
  154.     { "ab2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},  0, 0, FLAGS, "in" },
  155.     { "abl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},    0, 0, FLAGS, "in" },
  156.     { "abr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},    0, 0, FLAGS, "in" },
  157.     { "al",    "alternating frames left first",       0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR},    0, 0, FLAGS, "in" },
  158.     { "ar",    "alternating frames right first",      0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL},    0, 0, FLAGS, "in" },
  159.     { "sbs2l", "side by side half width left first",  0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, "in" },
  160.     { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL}, 0, 0, FLAGS, "in" },
  161.     { "sbsl",  "side by side left first",             0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR},   0, 0, FLAGS, "in" },
  162.     { "sbsr",  "side by side right first",            0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL},   0, 0, FLAGS, "in" },
  163.     { "out",   "set output format", OFFSET(out.format), AV_OPT_TYPE_INT, {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, "out"},
  164.     { "ab2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},   0, 0, FLAGS, "out" },
  165.     { "ab2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},   0, 0, FLAGS, "out" },
  166.     { "abl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},     0, 0, FLAGS, "out" },
  167.     { "abr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},     0, 0, FLAGS, "out" },
  168.     { "agmc",  "anaglyph green magenta color",        0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_COLOR},  0, 0, FLAGS, "out" },
  169.     { "agmd",  "anaglyph green magenta dubois",       0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_DUBOIS}, 0, 0, FLAGS, "out" },
  170.     { "agmg",  "anaglyph green magenta gray",         0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_GRAY},   0, 0, FLAGS, "out" },
  171.     { "agmh",  "anaglyph green magenta half color",   0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_HALF},   0, 0, FLAGS, "out" },
  172.     { "al",    "alternating frames left first",       0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR},     0, 0, FLAGS, "out" },
  173.     { "ar",    "alternating frames right first",      0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL},     0, 0, FLAGS, "out" },
  174.     { "arbg",  "anaglyph red blue gray",              0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RB_GRAY},   0, 0, FLAGS, "out" },
  175.     { "arcc",  "anaglyph red cyan color",             0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_COLOR},  0, 0, FLAGS, "out" },
  176.     { "arcd",  "anaglyph red cyan dubois",            0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_DUBOIS}, 0, 0, FLAGS, "out" },
  177.     { "arcg",  "anaglyph red cyan gray",              0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_GRAY},   0, 0, FLAGS, "out" },
  178.     { "arch",  "anaglyph red cyan half color",        0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_HALF},   0, 0, FLAGS, "out" },
  179.     { "argg",  "anaglyph red green gray",             0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RG_GRAY},   0, 0, FLAGS, "out" },
  180.     { "aybc",  "anaglyph yellow blue color",          0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_COLOR},  0, 0, FLAGS, "out" },
  181.     { "aybd",  "anaglyph yellow blue dubois",         0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_DUBOIS}, 0, 0, FLAGS, "out" },
  182.     { "aybg",  "anaglyph yellow blue gray",           0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_GRAY},   0, 0, FLAGS, "out" },
  183.     { "aybh",  "anaglyph yellow blue half color",     0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_HALF},   0, 0, FLAGS, "out" },
  184.     { "irl",   "interleave rows left first",          0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, "out" },
  185.     { "irr",   "interleave rows right first",         0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, "out" },
  186.     { "ml",    "mono left",                           0, AV_OPT_TYPE_CONST, {.i64=MONO_L},             0, 0, FLAGS, "out" },
  187.     { "mr",    "mono right",                          0, AV_OPT_TYPE_CONST, {.i64=MONO_R},             0, 0, FLAGS, "out" },
  188.     { "sbs2l", "side by side half width left first",  0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR},  0, 0, FLAGS, "out" },
  189.     { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL},  0, 0, FLAGS, "out" },
  190.     { "sbsl",  "side by side left first",             0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR},    0, 0, FLAGS, "out" },
  191.     { "sbsr",  "side by side right first",            0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL},    0, 0, FLAGS, "out" },
  192.     { NULL }
  193. };
  194.  
  195. AVFILTER_DEFINE_CLASS(stereo3d);
  196.  
  197. static const enum AVPixelFormat anaglyph_pix_fmts[] = {
  198.     AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
  199.     AV_PIX_FMT_NONE
  200. };
  201.  
  202. static const enum AVPixelFormat other_pix_fmts[] = {
  203.     AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
  204.     AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE,
  205.     AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE,
  206.     AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_BGRA64BE,
  207.     AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE,
  208.     AV_PIX_FMT_RGBA,  AV_PIX_FMT_BGRA,
  209.     AV_PIX_FMT_ARGB,  AV_PIX_FMT_ABGR,
  210.     AV_PIX_FMT_RGB0,  AV_PIX_FMT_BGR0,
  211.     AV_PIX_FMT_0RGB,  AV_PIX_FMT_0BGR,
  212.     AV_PIX_FMT_GBRP,
  213.     AV_PIX_FMT_GBRP9BE,  AV_PIX_FMT_GBRP9LE,
  214.     AV_PIX_FMT_GBRP10BE, AV_PIX_FMT_GBRP10LE,
  215.     AV_PIX_FMT_GBRP12BE, AV_PIX_FMT_GBRP12LE,
  216.     AV_PIX_FMT_GBRP14BE, AV_PIX_FMT_GBRP14LE,
  217.     AV_PIX_FMT_GBRP16BE, AV_PIX_FMT_GBRP16LE,
  218.     AV_PIX_FMT_YUV410P,
  219.     AV_PIX_FMT_YUV411P,
  220.     AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
  221.     AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P,
  222.     AV_PIX_FMT_YUV440P,
  223.     AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P,
  224.     AV_PIX_FMT_YUVJ411P,
  225.     AV_PIX_FMT_YUVJ420P,
  226.     AV_PIX_FMT_YUVJ422P,
  227.     AV_PIX_FMT_YUVJ440P,
  228.     AV_PIX_FMT_YUVJ444P,
  229.     AV_PIX_FMT_YUV420P9LE,  AV_PIX_FMT_YUVA420P9LE,
  230.     AV_PIX_FMT_YUV420P9BE,  AV_PIX_FMT_YUVA420P9BE,
  231.     AV_PIX_FMT_YUV422P9LE,  AV_PIX_FMT_YUVA422P9LE,
  232.     AV_PIX_FMT_YUV422P9BE,  AV_PIX_FMT_YUVA422P9BE,
  233.     AV_PIX_FMT_YUV444P9LE,  AV_PIX_FMT_YUVA444P9LE,
  234.     AV_PIX_FMT_YUV444P9BE,  AV_PIX_FMT_YUVA444P9BE,
  235.     AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE,
  236.     AV_PIX_FMT_YUV420P10BE, AV_PIX_FMT_YUVA420P10BE,
  237.     AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUVA422P10LE,
  238.     AV_PIX_FMT_YUV422P10BE, AV_PIX_FMT_YUVA422P10BE,
  239.     AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUVA444P10LE,
  240.     AV_PIX_FMT_YUV444P10BE, AV_PIX_FMT_YUVA444P10BE,
  241.     AV_PIX_FMT_YUV420P12BE,  AV_PIX_FMT_YUV420P12LE,
  242.     AV_PIX_FMT_YUV422P12BE,  AV_PIX_FMT_YUV422P12LE,
  243.     AV_PIX_FMT_YUV444P12BE,  AV_PIX_FMT_YUV444P12LE,
  244.     AV_PIX_FMT_YUV420P14BE,  AV_PIX_FMT_YUV420P14LE,
  245.     AV_PIX_FMT_YUV422P14BE,  AV_PIX_FMT_YUV422P14LE,
  246.     AV_PIX_FMT_YUV444P14BE,  AV_PIX_FMT_YUV444P14LE,
  247.     AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE,
  248.     AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_YUVA420P16BE,
  249.     AV_PIX_FMT_YUV422P16LE, AV_PIX_FMT_YUVA422P16LE,
  250.     AV_PIX_FMT_YUV422P16BE, AV_PIX_FMT_YUVA422P16BE,
  251.     AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE,
  252.     AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE,
  253.     AV_PIX_FMT_NONE
  254. };
  255.  
  256. static int query_formats(AVFilterContext *ctx)
  257. {
  258.     Stereo3DContext *s = ctx->priv;
  259.     const enum AVPixelFormat *pix_fmts;
  260.     AVFilterFormats *fmts_list;
  261.  
  262.     switch (s->out.format) {
  263.     case ANAGLYPH_GM_COLOR:
  264.     case ANAGLYPH_GM_DUBOIS:
  265.     case ANAGLYPH_GM_GRAY:
  266.     case ANAGLYPH_GM_HALF:
  267.     case ANAGLYPH_RB_GRAY:
  268.     case ANAGLYPH_RC_COLOR:
  269.     case ANAGLYPH_RC_DUBOIS:
  270.     case ANAGLYPH_RC_GRAY:
  271.     case ANAGLYPH_RC_HALF:
  272.     case ANAGLYPH_RG_GRAY:
  273.     case ANAGLYPH_YB_COLOR:
  274.     case ANAGLYPH_YB_DUBOIS:
  275.     case ANAGLYPH_YB_GRAY:
  276.     case ANAGLYPH_YB_HALF:
  277.         pix_fmts = anaglyph_pix_fmts;
  278.         break;
  279.     default:
  280.         pix_fmts = other_pix_fmts;
  281.     }
  282.  
  283.     fmts_list = ff_make_format_list(pix_fmts);
  284.     if (!fmts_list)
  285.         return AVERROR(ENOMEM);
  286.     return ff_set_common_formats(ctx, fmts_list);
  287. }
  288.  
  289. static int config_output(AVFilterLink *outlink)
  290. {
  291.     AVFilterContext *ctx = outlink->src;
  292.     AVFilterLink *inlink = ctx->inputs[0];
  293.     Stereo3DContext *s = ctx->priv;
  294.     AVRational aspect = inlink->sample_aspect_ratio;
  295.     AVRational fps = inlink->frame_rate;
  296.     AVRational tb = inlink->time_base;
  297.     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
  298.     int ret;
  299.  
  300.     switch (s->in.format) {
  301.     case SIDE_BY_SIDE_2_LR:
  302.     case SIDE_BY_SIDE_LR:
  303.     case SIDE_BY_SIDE_2_RL:
  304.     case SIDE_BY_SIDE_RL:
  305.         if (inlink->w & 1) {
  306.             av_log(ctx, AV_LOG_ERROR, "width must be even\n");
  307.             return AVERROR_INVALIDDATA;
  308.         }
  309.         break;
  310.     case ABOVE_BELOW_2_LR:
  311.     case ABOVE_BELOW_LR:
  312.     case ABOVE_BELOW_2_RL:
  313.     case ABOVE_BELOW_RL:
  314.         if (s->out.format == INTERLEAVE_ROWS_LR ||
  315.             s->out.format == INTERLEAVE_ROWS_RL) {
  316.             if (inlink->h & 3) {
  317.                 av_log(ctx, AV_LOG_ERROR, "height must be multiple of 4\n");
  318.                 return AVERROR_INVALIDDATA;
  319.             }
  320.         }
  321.         if (inlink->h & 1) {
  322.             av_log(ctx, AV_LOG_ERROR, "height must be even\n");
  323.             return AVERROR_INVALIDDATA;
  324.         }
  325.         break;
  326.     }
  327.  
  328.     s->in.width     =
  329.     s->width        = inlink->w;
  330.     s->in.height    =
  331.     s->height       = inlink->h;
  332.     s->row_step     = 1;
  333.     s->in.off_lstep =
  334.     s->in.off_rstep =
  335.     s->in.off_left  =
  336.     s->in.off_right =
  337.     s->in.row_left  =
  338.     s->in.row_right = 0;
  339.  
  340.     switch (s->in.format) {
  341.     case SIDE_BY_SIDE_2_LR:
  342.         aspect.num     *= 2;
  343.     case SIDE_BY_SIDE_LR:
  344.         s->width        = inlink->w / 2;
  345.         s->in.off_right = s->width;
  346.         break;
  347.     case SIDE_BY_SIDE_2_RL:
  348.         aspect.num     *= 2;
  349.     case SIDE_BY_SIDE_RL:
  350.         s->width        = inlink->w / 2;
  351.         s->in.off_left  = s->width;
  352.         break;
  353.     case ABOVE_BELOW_2_LR:
  354.         aspect.den     *= 2;
  355.     case ABOVE_BELOW_LR:
  356.         s->in.row_right =
  357.         s->height       = inlink->h / 2;
  358.         break;
  359.     case ABOVE_BELOW_2_RL:
  360.         aspect.den     *= 2;
  361.     case ABOVE_BELOW_RL:
  362.         s->in.row_left  =
  363.         s->height       = inlink->h / 2;
  364.         break;
  365.     case ALTERNATING_RL:
  366.     case ALTERNATING_LR:
  367.         outlink->flags |= FF_LINK_FLAG_REQUEST_LOOP;
  368.         fps.den        *= 2;
  369.         tb.num         *= 2;
  370.         break;
  371.     default:
  372.         av_log(ctx, AV_LOG_ERROR, "input format %d is not supported\n", s->in.format);
  373.         return AVERROR(EINVAL);
  374.     }
  375.  
  376.     s->out.width     = s->width;
  377.     s->out.height    = s->height;
  378.     s->out.off_lstep =
  379.     s->out.off_rstep =
  380.     s->out.off_left  =
  381.     s->out.off_right =
  382.     s->out.row_left  =
  383.     s->out.row_right = 0;
  384.  
  385.     switch (s->out.format) {
  386.     case ANAGLYPH_RB_GRAY:
  387.     case ANAGLYPH_RG_GRAY:
  388.     case ANAGLYPH_RC_GRAY:
  389.     case ANAGLYPH_RC_HALF:
  390.     case ANAGLYPH_RC_COLOR:
  391.     case ANAGLYPH_RC_DUBOIS:
  392.     case ANAGLYPH_GM_GRAY:
  393.     case ANAGLYPH_GM_HALF:
  394.     case ANAGLYPH_GM_COLOR:
  395.     case ANAGLYPH_GM_DUBOIS:
  396.     case ANAGLYPH_YB_GRAY:
  397.     case ANAGLYPH_YB_HALF:
  398.     case ANAGLYPH_YB_COLOR:
  399.     case ANAGLYPH_YB_DUBOIS: {
  400.         uint8_t rgba_map[4];
  401.  
  402.         ff_fill_rgba_map(rgba_map, outlink->format);
  403.         s->ana_matrix[rgba_map[0]] = &ana_coeff[s->out.format][0][0];
  404.         s->ana_matrix[rgba_map[1]] = &ana_coeff[s->out.format][1][0];
  405.         s->ana_matrix[rgba_map[2]] = &ana_coeff[s->out.format][2][0];
  406.         break;
  407.     }
  408.     case SIDE_BY_SIDE_2_LR:
  409.         aspect.den      *= 2;
  410.     case SIDE_BY_SIDE_LR:
  411.         s->out.width     = s->width * 2;
  412.         s->out.off_right = s->width;
  413.         break;
  414.     case SIDE_BY_SIDE_2_RL:
  415.         aspect.den      *= 2;
  416.     case SIDE_BY_SIDE_RL:
  417.         s->out.width     = s->width * 2;
  418.         s->out.off_left  = s->width;
  419.         break;
  420.     case ABOVE_BELOW_2_LR:
  421.         aspect.num      *= 2;
  422.     case ABOVE_BELOW_LR:
  423.         s->out.height    = s->height * 2;
  424.         s->out.row_right = s->height;
  425.         break;
  426.     case ABOVE_BELOW_2_RL:
  427.         aspect.num      *= 2;
  428.     case ABOVE_BELOW_RL:
  429.         s->out.height    = s->height * 2;
  430.         s->out.row_left  = s->height;
  431.         break;
  432.     case INTERLEAVE_ROWS_LR:
  433.         s->row_step      = 2;
  434.         s->height        = s->height / 2;
  435.         s->out.off_rstep =
  436.         s->in.off_rstep  = 1;
  437.         break;
  438.     case INTERLEAVE_ROWS_RL:
  439.         s->row_step      = 2;
  440.         s->height        = s->height / 2;
  441.         s->out.off_lstep =
  442.         s->in.off_lstep  = 1;
  443.         break;
  444.     case MONO_R:
  445.         s->in.off_left   = s->in.off_right;
  446.         s->in.row_left   = s->in.row_right;
  447.     case MONO_L:
  448.         break;
  449.     case ALTERNATING_RL:
  450.     case ALTERNATING_LR:
  451.         fps.num         *= 2;
  452.         tb.den          *= 2;
  453.         break;
  454.     default:
  455.         av_log(ctx, AV_LOG_ERROR, "output format %d is not supported\n", s->out.format);
  456.         return AVERROR(EINVAL);
  457.     }
  458.  
  459.     outlink->w = s->out.width;
  460.     outlink->h = s->out.height;
  461.     outlink->frame_rate = fps;
  462.     outlink->time_base = tb;
  463.     outlink->sample_aspect_ratio = aspect;
  464.  
  465.     if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, s->width)) < 0)
  466.         return ret;
  467.     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
  468.     av_image_fill_max_pixsteps(s->pixstep, NULL, desc);
  469.     s->ts_unit = av_q2d(av_inv_q(av_mul_q(outlink->frame_rate, outlink->time_base)));
  470.     s->pheight[1] = s->pheight[2] = FF_CEIL_RSHIFT(s->height, desc->log2_chroma_h);
  471.     s->pheight[0] = s->pheight[3] = s->height;
  472.     s->hsub = desc->log2_chroma_w;
  473.     s->vsub = desc->log2_chroma_h;
  474.  
  475.     return 0;
  476. }
  477.  
  478. static inline uint8_t ana_convert(const int *coeff, const uint8_t *left, const uint8_t *right)
  479. {
  480.     int sum;
  481.  
  482.     sum  = coeff[0] * left[0] + coeff[3] * right[0]; //red in
  483.     sum += coeff[1] * left[1] + coeff[4] * right[1]; //green in
  484.     sum += coeff[2] * left[2] + coeff[5] * right[2]; //blue in
  485.  
  486.     return av_clip_uint8(sum >> 16);
  487. }
  488.  
  489. typedef struct ThreadData {
  490.     AVFrame *ileft, *iright;
  491.     AVFrame *out;
  492. } ThreadData;
  493.  
  494. static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
  495. {
  496.     Stereo3DContext *s = ctx->priv;
  497.     ThreadData *td = arg;
  498.     AVFrame *ileft = td->ileft;
  499.     AVFrame *iright = td->iright;
  500.     AVFrame *out = td->out;
  501.     int height = s->out.height;
  502.     int start = (height *  jobnr   ) / nb_jobs;
  503.     int end   = (height * (jobnr+1)) / nb_jobs;
  504.     uint8_t *dst = out->data[0];
  505.     const int **ana_matrix = s->ana_matrix;
  506.     int x, y, il, ir, o;
  507.     const uint8_t *lsrc = ileft->data[0];
  508.     const uint8_t *rsrc = iright->data[0];
  509.     int out_width = s->out.width;
  510.  
  511.     for (y = start; y < end; y++) {
  512.         o   = out->linesize[0] * y;
  513.         il  = s->in_off_left[0]  + y * ileft->linesize[0];
  514.         ir  = s->in_off_right[0] + y * iright->linesize[0];
  515.         for (x = 0; x < out_width; x++, il += 3, ir += 3, o+= 3) {
  516.             dst[o    ] = ana_convert(ana_matrix[0], lsrc + il, rsrc + ir);
  517.             dst[o + 1] = ana_convert(ana_matrix[1], lsrc + il, rsrc + ir);
  518.             dst[o + 2] = ana_convert(ana_matrix[2], lsrc + il, rsrc + ir);
  519.         }
  520.     }
  521.  
  522.     return 0;
  523. }
  524.  
  525. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  526. {
  527.     AVFilterContext *ctx  = inlink->dst;
  528.     Stereo3DContext *s = ctx->priv;
  529.     AVFilterLink *outlink = ctx->outputs[0];
  530.     AVFrame *out, *oleft, *oright, *ileft, *iright;
  531.     int out_off_left[4], out_off_right[4];
  532.     int i;
  533.  
  534.     switch (s->in.format) {
  535.     case ALTERNATING_LR:
  536.     case ALTERNATING_RL:
  537.         if (!s->prev) {
  538.             s->prev = inpicref;
  539.             return 0;
  540.         }
  541.         ileft  = s->prev;
  542.         iright = inpicref;
  543.         if (s->in.format == ALTERNATING_RL)
  544.             FFSWAP(AVFrame *, ileft, iright);
  545.         break;
  546.     default:
  547.         ileft = iright = inpicref;
  548.     };
  549.  
  550.     out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  551.     if (!out) {
  552.         av_frame_free(&s->prev);
  553.         av_frame_free(&inpicref);
  554.         return AVERROR(ENOMEM);
  555.     }
  556.     av_frame_copy_props(out, inpicref);
  557.  
  558.     if (s->out.format == ALTERNATING_LR ||
  559.         s->out.format == ALTERNATING_RL) {
  560.         oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  561.         if (!oright) {
  562.             av_frame_free(&oleft);
  563.             av_frame_free(&s->prev);
  564.             av_frame_free(&inpicref);
  565.             return AVERROR(ENOMEM);
  566.         }
  567.         av_frame_copy_props(oright, inpicref);
  568.     }
  569.  
  570.     for (i = 0; i < 4; i++) {
  571.         int hsub = i == 1 || i == 2 ? s->hsub : 0;
  572.         int vsub = i == 1 || i == 2 ? s->vsub : 0;
  573.         s->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);
  574.         s->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);
  575.         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);
  576.         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);
  577.     }
  578.  
  579.     switch (s->out.format) {
  580.     case ALTERNATING_LR:
  581.     case ALTERNATING_RL:
  582.     case SIDE_BY_SIDE_LR:
  583.     case SIDE_BY_SIDE_RL:
  584.     case SIDE_BY_SIDE_2_LR:
  585.     case SIDE_BY_SIDE_2_RL:
  586.     case ABOVE_BELOW_LR:
  587.     case ABOVE_BELOW_RL:
  588.     case ABOVE_BELOW_2_LR:
  589.     case ABOVE_BELOW_2_RL:
  590.     case INTERLEAVE_ROWS_LR:
  591.     case INTERLEAVE_ROWS_RL:
  592.         for (i = 0; i < s->nb_planes; i++) {
  593.             av_image_copy_plane(oleft->data[i] + out_off_left[i],
  594.                                 oleft->linesize[i] * s->row_step,
  595.                                 ileft->data[i] + s->in_off_left[i],
  596.                                 ileft->linesize[i] * s->row_step,
  597.                                 s->linesize[i], s->pheight[i]);
  598.             av_image_copy_plane(oright->data[i] + out_off_right[i],
  599.                                 oright->linesize[i] * s->row_step,
  600.                                 iright->data[i] + s->in_off_right[i],
  601.                                 iright->linesize[i] * s->row_step,
  602.                                 s->linesize[i], s->pheight[i]);
  603.         }
  604.         break;
  605.     case MONO_L:
  606.         iright = ileft;
  607.     case MONO_R:
  608.         for (i = 0; i < s->nb_planes; i++) {
  609.             av_image_copy_plane(out->data[i], out->linesize[i],
  610.                                 iright->data[i] + s->in_off_left[i],
  611.                                 iright->linesize[i],
  612.                                 s->linesize[i], s->pheight[i]);
  613.         }
  614.         break;
  615.     case ANAGLYPH_RB_GRAY:
  616.     case ANAGLYPH_RG_GRAY:
  617.     case ANAGLYPH_RC_GRAY:
  618.     case ANAGLYPH_RC_HALF:
  619.     case ANAGLYPH_RC_COLOR:
  620.     case ANAGLYPH_RC_DUBOIS:
  621.     case ANAGLYPH_GM_GRAY:
  622.     case ANAGLYPH_GM_HALF:
  623.     case ANAGLYPH_GM_COLOR:
  624.     case ANAGLYPH_GM_DUBOIS:
  625.     case ANAGLYPH_YB_GRAY:
  626.     case ANAGLYPH_YB_HALF:
  627.     case ANAGLYPH_YB_COLOR:
  628.     case ANAGLYPH_YB_DUBOIS: {
  629.         ThreadData td;
  630.  
  631.         td.ileft = ileft; td.iright = iright; td.out = out;
  632.         ctx->internal->execute(ctx, filter_slice, &td, NULL,
  633.                                FFMIN(s->out.height, ctx->graph->nb_threads));
  634.         break;
  635.     }
  636.     default:
  637.         av_assert0(0);
  638.     }
  639.  
  640.     av_frame_free(&inpicref);
  641.     av_frame_free(&s->prev);
  642.     if (oright != oleft) {
  643.         if (s->out.format == ALTERNATING_LR)
  644.             FFSWAP(AVFrame *, oleft, oright);
  645.         oright->pts = outlink->frame_count * s->ts_unit;
  646.         ff_filter_frame(outlink, oright);
  647.         out = oleft;
  648.         oleft->pts = outlink->frame_count * s->ts_unit;
  649.     } else if (s->in.format == ALTERNATING_LR ||
  650.                s->in.format == ALTERNATING_RL) {
  651.         out->pts = outlink->frame_count * s->ts_unit;
  652.     }
  653.     return ff_filter_frame(outlink, out);
  654. }
  655.  
  656. static av_cold void uninit(AVFilterContext *ctx)
  657. {
  658.     Stereo3DContext *s = ctx->priv;
  659.  
  660.     av_frame_free(&s->prev);
  661. }
  662.  
  663. static const AVFilterPad stereo3d_inputs[] = {
  664.     {
  665.         .name         = "default",
  666.         .type         = AVMEDIA_TYPE_VIDEO,
  667.         .filter_frame = filter_frame,
  668.     },
  669.     { NULL }
  670. };
  671.  
  672. static const AVFilterPad stereo3d_outputs[] = {
  673.     {
  674.         .name         = "default",
  675.         .type         = AVMEDIA_TYPE_VIDEO,
  676.         .config_props = config_output,
  677.     },
  678.     { NULL }
  679. };
  680.  
  681. AVFilter ff_vf_stereo3d = {
  682.     .name          = "stereo3d",
  683.     .description   = NULL_IF_CONFIG_SMALL("Convert video stereoscopic 3D view."),
  684.     .priv_size     = sizeof(Stereo3DContext),
  685.     .uninit        = uninit,
  686.     .query_formats = query_formats,
  687.     .inputs        = stereo3d_inputs,
  688.     .outputs       = stereo3d_outputs,
  689.     .priv_class    = &stereo3d_class,
  690.     .flags         = AVFILTER_FLAG_SLICE_THREADS,
  691. };
  692.