]> git.sesse.net Git - ffmpeg/blob - libavfilter/vf_stereo3d.c
ff17b07c3d5b6a9bb2a9bca6b9b2bcb14423fbbe
[ffmpeg] / libavfilter / vf_stereo3d.c
1 /*
2  * Copyright (c) 2010 Gordon Schmidt <gordon.schmidt <at> s2000.tu-chemnitz.de>
3  * Copyright (c) 2013-2015 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/intreadwrite.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/parseutils.h"
27 #include "libavutil/pixdesc.h"
28 #include "avfilter.h"
29 #include "drawutils.h"
30 #include "formats.h"
31 #include "internal.h"
32 #include "video.h"
33 #include "stereo3d.h"
34
35 enum StereoCode {
36     ANAGLYPH_RC_GRAY,   // anaglyph red/cyan gray
37     ANAGLYPH_RC_HALF,   // anaglyph red/cyan half colored
38     ANAGLYPH_RC_COLOR,  // anaglyph red/cyan colored
39     ANAGLYPH_RC_DUBOIS, // anaglyph red/cyan dubois
40     ANAGLYPH_GM_GRAY,   // anaglyph green/magenta gray
41     ANAGLYPH_GM_HALF,   // anaglyph green/magenta half colored
42     ANAGLYPH_GM_COLOR,  // anaglyph green/magenta colored
43     ANAGLYPH_GM_DUBOIS, // anaglyph green/magenta dubois
44     ANAGLYPH_YB_GRAY,   // anaglyph yellow/blue gray
45     ANAGLYPH_YB_HALF,   // anaglyph yellow/blue half colored
46     ANAGLYPH_YB_COLOR,  // anaglyph yellow/blue colored
47     ANAGLYPH_YB_DUBOIS, // anaglyph yellow/blue dubois
48     ANAGLYPH_RB_GRAY,   // anaglyph red/blue gray
49     ANAGLYPH_RG_GRAY,   // anaglyph red/green gray
50     MONO_L,             // mono output for debugging (left eye only)
51     MONO_R,             // mono output for debugging (right eye only)
52     INTERLEAVE_ROWS_LR, // row-interleave (left eye has top row)
53     INTERLEAVE_ROWS_RL, // row-interleave (right eye has top row)
54     SIDE_BY_SIDE_LR,    // side by side parallel (left eye left, right eye right)
55     SIDE_BY_SIDE_RL,    // side by side crosseye (right eye left, left eye right)
56     SIDE_BY_SIDE_2_LR,  // side by side parallel with half width resolution
57     SIDE_BY_SIDE_2_RL,  // side by side crosseye with half width resolution
58     ABOVE_BELOW_LR,     // above-below (left eye above, right eye below)
59     ABOVE_BELOW_RL,     // above-below (right eye above, left eye below)
60     ABOVE_BELOW_2_LR,   // above-below with half height resolution
61     ABOVE_BELOW_2_RL,   // above-below with half height resolution
62     ALTERNATING_LR,     // alternating frames (left eye first, right eye second)
63     ALTERNATING_RL,     // alternating frames (right eye first, left eye second)
64     CHECKERBOARD_LR,    // checkerboard pattern (left eye first, right eye second)
65     CHECKERBOARD_RL,    // checkerboard pattern (right eye first, left eye second)
66     INTERLEAVE_COLS_LR, // column-interleave (left eye first, right eye second)
67     INTERLEAVE_COLS_RL, // column-interleave (right eye first, left eye second)
68     HDMI,               // HDMI frame pack (left eye first, right eye second)
69     STEREO_CODE_COUNT   // TODO: needs autodetection
70 };
71
72 typedef struct StereoComponent {
73     int format;                 ///< StereoCode
74     int width, height;
75     int off_left, off_right;
76     int off_lstep, off_rstep;
77     int row_left, row_right;
78     int row_step;
79 } StereoComponent;
80
81 static const int ana_coeff[][3][6] = {
82   [ANAGLYPH_RB_GRAY]   =
83     {{19595, 38470,  7471,     0,     0,     0},
84      {    0,     0,     0,     0,     0,     0},
85      {    0,     0,     0, 19595, 38470,  7471}},
86   [ANAGLYPH_RG_GRAY]   =
87     {{19595, 38470,  7471,     0,     0,     0},
88      {    0,     0,     0, 19595, 38470,  7471},
89      {    0,     0,     0,     0,     0,     0}},
90   [ANAGLYPH_RC_GRAY]   =
91     {{19595, 38470,  7471,     0,     0,     0},
92      {    0,     0,     0, 19595, 38470,  7471},
93      {    0,     0,     0, 19595, 38470,  7471}},
94   [ANAGLYPH_RC_HALF]   =
95     {{19595, 38470,  7471,     0,     0,     0},
96      {    0,     0,     0,     0, 65536,     0},
97      {    0,     0,     0,     0,     0, 65536}},
98   [ANAGLYPH_RC_COLOR]  =
99     {{65536,     0,     0,     0,     0,     0},
100      {    0,     0,     0,     0, 65536,     0},
101      {    0,     0,     0,     0,     0, 65536}},
102   [ANAGLYPH_RC_DUBOIS] =
103     {{29884, 32768, 11534, -2818, -5767,  -131},
104      {-2621, -2490, -1049, 24773, 48103, -1180},
105      { -983, -1376,  -328, -4719, -7406, 80347}},
106   [ANAGLYPH_GM_GRAY]   =
107     {{    0,     0,     0, 19595, 38470,  7471},
108      {19595, 38470,  7471,     0,     0,     0},
109      {    0,     0,     0, 19595, 38470,  7471}},
110   [ANAGLYPH_GM_HALF]   =
111     {{    0,     0,     0, 65536,     0,     0},
112      {19595, 38470,  7471,     0,     0,     0},
113      {    0,     0,     0,     0,     0, 65536}},
114   [ANAGLYPH_GM_COLOR]  =
115     {{    0,     0,     0, 65536,     0,     0},
116      {    0, 65536,     0,     0,     0,     0},
117      {    0,     0,     0,     0,     0, 65536}},
118   [ANAGLYPH_GM_DUBOIS]  =
119     {{-4063,-10354, -2556, 34669, 46203,  1573},
120      {18612, 43778,  9372, -1049,  -983, -4260},
121      { -983, -1769,  1376,   590,  4915, 61407}},
122   [ANAGLYPH_YB_GRAY]   =
123     {{    0,     0,     0, 19595, 38470,  7471},
124      {    0,     0,     0, 19595, 38470,  7471},
125      {19595, 38470,  7471,     0,     0,     0}},
126   [ANAGLYPH_YB_HALF]   =
127     {{    0,     0,     0, 65536,     0,     0},
128      {    0,     0,     0,     0, 65536,     0},
129      {19595, 38470,  7471,     0,     0,     0}},
130   [ANAGLYPH_YB_COLOR]  =
131     {{    0,     0,     0, 65536,     0,     0},
132      {    0,     0,     0,     0, 65536,     0},
133      {    0,     0, 65536,     0,     0,     0}},
134   [ANAGLYPH_YB_DUBOIS] =
135     {{69599,-13435,19595,  -1048, -8061, -1114},
136      {-1704, 59507, 4456,    393,  4063, -1114},
137      {-2490,-11338, 1442,   6160, 12124, 59703}},
138 };
139
140 typedef struct Stereo3DContext {
141     const AVClass *class;
142     StereoComponent in, out;
143     int width, height;
144     const int *ana_matrix[3];
145     int nb_planes;
146     int linesize[4];
147     int pheight[4];
148     int hsub, vsub;
149     int pixstep[4];
150     AVFrame *prev;
151     int blanks;
152     int in_off_left[4], in_off_right[4];
153     AVRational aspect;
154     Stereo3DDSPContext dsp;
155 } Stereo3DContext;
156
157 #define OFFSET(x) offsetof(Stereo3DContext, x)
158 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
159
160 static const AVOption stereo3d_options[] = {
161     { "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"},
162     { "ab2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},   0, 0, FLAGS, "in" },
163     { "tb2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},   0, 0, FLAGS, "in" },
164     { "ab2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},   0, 0, FLAGS, "in" },
165     { "tb2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},   0, 0, FLAGS, "in" },
166     { "abl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},     0, 0, FLAGS, "in" },
167     { "tbl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},     0, 0, FLAGS, "in" },
168     { "abr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},     0, 0, FLAGS, "in" },
169     { "tbr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},     0, 0, FLAGS, "in" },
170     { "al",    "alternating frames left first",       0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR},     0, 0, FLAGS, "in" },
171     { "ar",    "alternating frames right first",      0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL},     0, 0, FLAGS, "in" },
172     { "sbs2l", "side by side half width left first",  0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR},  0, 0, FLAGS, "in" },
173     { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL},  0, 0, FLAGS, "in" },
174     { "sbsl",  "side by side left first",             0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR},    0, 0, FLAGS, "in" },
175     { "sbsr",  "side by side right first",            0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL},    0, 0, FLAGS, "in" },
176     { "irl",   "interleave rows left first",          0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, "in" },
177     { "irr",   "interleave rows right first",         0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, "in" },
178     { "icl",   "interleave columns left first",       0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_LR}, 0, 0, FLAGS, "in" },
179     { "icr",   "interleave columns right first",      0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_RL}, 0, 0, FLAGS, "in" },
180     { "out",   "set output format", OFFSET(out.format),  AV_OPT_TYPE_INT,   {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, "out"},
181     { "ab2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},   0, 0, FLAGS, "out" },
182     { "tb2l",  "above below half height left first",  0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR},   0, 0, FLAGS, "out" },
183     { "ab2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},   0, 0, FLAGS, "out" },
184     { "tb2r",  "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL},   0, 0, FLAGS, "out" },
185     { "abl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},     0, 0, FLAGS, "out" },
186     { "tbl",   "above below left first",              0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR},     0, 0, FLAGS, "out" },
187     { "abr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},     0, 0, FLAGS, "out" },
188     { "tbr",   "above below right first",             0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL},     0, 0, FLAGS, "out" },
189     { "agmc",  "anaglyph green magenta color",        0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_COLOR},  0, 0, FLAGS, "out" },
190     { "agmd",  "anaglyph green magenta dubois",       0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_DUBOIS}, 0, 0, FLAGS, "out" },
191     { "agmg",  "anaglyph green magenta gray",         0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_GRAY},   0, 0, FLAGS, "out" },
192     { "agmh",  "anaglyph green magenta half color",   0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_HALF},   0, 0, FLAGS, "out" },
193     { "al",    "alternating frames left first",       0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR},     0, 0, FLAGS, "out" },
194     { "ar",    "alternating frames right first",      0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL},     0, 0, FLAGS, "out" },
195     { "arbg",  "anaglyph red blue gray",              0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RB_GRAY},   0, 0, FLAGS, "out" },
196     { "arcc",  "anaglyph red cyan color",             0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_COLOR},  0, 0, FLAGS, "out" },
197     { "arcd",  "anaglyph red cyan dubois",            0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_DUBOIS}, 0, 0, FLAGS, "out" },
198     { "arcg",  "anaglyph red cyan gray",              0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_GRAY},   0, 0, FLAGS, "out" },
199     { "arch",  "anaglyph red cyan half color",        0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_HALF},   0, 0, FLAGS, "out" },
200     { "argg",  "anaglyph red green gray",             0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RG_GRAY},   0, 0, FLAGS, "out" },
201     { "aybc",  "anaglyph yellow blue color",          0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_COLOR},  0, 0, FLAGS, "out" },
202     { "aybd",  "anaglyph yellow blue dubois",         0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_DUBOIS}, 0, 0, FLAGS, "out" },
203     { "aybg",  "anaglyph yellow blue gray",           0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_GRAY},   0, 0, FLAGS, "out" },
204     { "aybh",  "anaglyph yellow blue half color",     0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_HALF},   0, 0, FLAGS, "out" },
205     { "irl",   "interleave rows left first",          0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, "out" },
206     { "irr",   "interleave rows right first",         0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, "out" },
207     { "ml",    "mono left",                           0, AV_OPT_TYPE_CONST, {.i64=MONO_L},             0, 0, FLAGS, "out" },
208     { "mr",    "mono right",                          0, AV_OPT_TYPE_CONST, {.i64=MONO_R},             0, 0, FLAGS, "out" },
209     { "sbs2l", "side by side half width left first",  0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR},  0, 0, FLAGS, "out" },
210     { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL},  0, 0, FLAGS, "out" },
211     { "sbsl",  "side by side left first",             0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR},    0, 0, FLAGS, "out" },
212     { "sbsr",  "side by side right first",            0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL},    0, 0, FLAGS, "out" },
213     { "chl",   "checkerboard left first",             0, AV_OPT_TYPE_CONST, {.i64=CHECKERBOARD_LR},    0, 0, FLAGS, "out" },
214     { "chr",   "checkerboard right first",            0, AV_OPT_TYPE_CONST, {.i64=CHECKERBOARD_RL},    0, 0, FLAGS, "out" },
215     { "icl",   "interleave columns left first",       0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_LR}, 0, 0, FLAGS, "out" },
216     { "icr",   "interleave columns right first",      0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_RL}, 0, 0, FLAGS, "out" },
217     { "hdmi",  "HDMI frame pack",                     0, AV_OPT_TYPE_CONST, {.i64=HDMI},               0, 0, FLAGS, "out" },
218     { NULL }
219 };
220
221 AVFILTER_DEFINE_CLASS(stereo3d);
222
223 static const enum AVPixelFormat anaglyph_pix_fmts[] = {
224     AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
225     AV_PIX_FMT_NONE
226 };
227
228 static const enum AVPixelFormat other_pix_fmts[] = {
229     AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
230     AV_PIX_FMT_RGB48BE, AV_PIX_FMT_BGR48BE,
231     AV_PIX_FMT_RGB48LE, AV_PIX_FMT_BGR48LE,
232     AV_PIX_FMT_RGBA64BE, AV_PIX_FMT_BGRA64BE,
233     AV_PIX_FMT_RGBA64LE, AV_PIX_FMT_BGRA64LE,
234     AV_PIX_FMT_RGBA,  AV_PIX_FMT_BGRA,
235     AV_PIX_FMT_ARGB,  AV_PIX_FMT_ABGR,
236     AV_PIX_FMT_RGB0,  AV_PIX_FMT_BGR0,
237     AV_PIX_FMT_0RGB,  AV_PIX_FMT_0BGR,
238     AV_PIX_FMT_GBRP,
239     AV_PIX_FMT_GBRP9BE,  AV_PIX_FMT_GBRP9LE,
240     AV_PIX_FMT_GBRP10BE, AV_PIX_FMT_GBRP10LE,
241     AV_PIX_FMT_GBRP12BE, AV_PIX_FMT_GBRP12LE,
242     AV_PIX_FMT_GBRP14BE, AV_PIX_FMT_GBRP14LE,
243     AV_PIX_FMT_GBRP16BE, AV_PIX_FMT_GBRP16LE,
244     AV_PIX_FMT_YUV410P,
245     AV_PIX_FMT_YUV411P,
246     AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
247     AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUVA422P,
248     AV_PIX_FMT_YUV440P,
249     AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVA444P,
250     AV_PIX_FMT_YUVJ411P,
251     AV_PIX_FMT_YUVJ420P,
252     AV_PIX_FMT_YUVJ422P,
253     AV_PIX_FMT_YUVJ440P,
254     AV_PIX_FMT_YUVJ444P,
255     AV_PIX_FMT_YUV420P9LE,  AV_PIX_FMT_YUVA420P9LE,
256     AV_PIX_FMT_YUV420P9BE,  AV_PIX_FMT_YUVA420P9BE,
257     AV_PIX_FMT_YUV422P9LE,  AV_PIX_FMT_YUVA422P9LE,
258     AV_PIX_FMT_YUV422P9BE,  AV_PIX_FMT_YUVA422P9BE,
259     AV_PIX_FMT_YUV444P9LE,  AV_PIX_FMT_YUVA444P9LE,
260     AV_PIX_FMT_YUV444P9BE,  AV_PIX_FMT_YUVA444P9BE,
261     AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE,
262     AV_PIX_FMT_YUV420P10BE, AV_PIX_FMT_YUVA420P10BE,
263     AV_PIX_FMT_YUV422P10LE, AV_PIX_FMT_YUVA422P10LE,
264     AV_PIX_FMT_YUV422P10BE, AV_PIX_FMT_YUVA422P10BE,
265     AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUVA444P10LE,
266     AV_PIX_FMT_YUV444P10BE, AV_PIX_FMT_YUVA444P10BE,
267     AV_PIX_FMT_YUV420P12BE,  AV_PIX_FMT_YUV420P12LE,
268     AV_PIX_FMT_YUV422P12BE,  AV_PIX_FMT_YUV422P12LE,
269     AV_PIX_FMT_YUV444P12BE,  AV_PIX_FMT_YUV444P12LE,
270     AV_PIX_FMT_YUV420P14BE,  AV_PIX_FMT_YUV420P14LE,
271     AV_PIX_FMT_YUV422P14BE,  AV_PIX_FMT_YUV422P14LE,
272     AV_PIX_FMT_YUV444P14BE,  AV_PIX_FMT_YUV444P14LE,
273     AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE,
274     AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_YUVA420P16BE,
275     AV_PIX_FMT_YUV422P16LE, AV_PIX_FMT_YUVA422P16LE,
276     AV_PIX_FMT_YUV422P16BE, AV_PIX_FMT_YUVA422P16BE,
277     AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE,
278     AV_PIX_FMT_YUV444P16BE, AV_PIX_FMT_YUVA444P16BE,
279     AV_PIX_FMT_NONE
280 };
281
282 static int query_formats(AVFilterContext *ctx)
283 {
284     Stereo3DContext *s = ctx->priv;
285     const enum AVPixelFormat *pix_fmts;
286     AVFilterFormats *fmts_list;
287
288     switch (s->out.format) {
289     case ANAGLYPH_GM_COLOR:
290     case ANAGLYPH_GM_DUBOIS:
291     case ANAGLYPH_GM_GRAY:
292     case ANAGLYPH_GM_HALF:
293     case ANAGLYPH_RB_GRAY:
294     case ANAGLYPH_RC_COLOR:
295     case ANAGLYPH_RC_DUBOIS:
296     case ANAGLYPH_RC_GRAY:
297     case ANAGLYPH_RC_HALF:
298     case ANAGLYPH_RG_GRAY:
299     case ANAGLYPH_YB_COLOR:
300     case ANAGLYPH_YB_DUBOIS:
301     case ANAGLYPH_YB_GRAY:
302     case ANAGLYPH_YB_HALF:
303         pix_fmts = anaglyph_pix_fmts;
304         break;
305     default:
306         pix_fmts = other_pix_fmts;
307     }
308
309     fmts_list = ff_make_format_list(pix_fmts);
310     if (!fmts_list)
311         return AVERROR(ENOMEM);
312     return ff_set_common_formats(ctx, fmts_list);
313 }
314
315 static inline uint8_t ana_convert(const int *coeff, const uint8_t *left, const uint8_t *right)
316 {
317     int sum;
318
319     sum  = coeff[0] * left[0] + coeff[3] * right[0]; //red in
320     sum += coeff[1] * left[1] + coeff[4] * right[1]; //green in
321     sum += coeff[2] * left[2] + coeff[5] * right[2]; //blue in
322
323     return av_clip_uint8(sum >> 16);
324 }
325
326 static void anaglyph_ic(uint8_t *dst, uint8_t *lsrc, uint8_t *rsrc,
327                         ptrdiff_t dst_linesize, ptrdiff_t l_linesize, ptrdiff_t r_linesize,
328                         int width, int height,
329                         const int *ana_matrix_r, const int *ana_matrix_g, const int *ana_matrix_b)
330 {
331     int x, y, o;
332
333     for (y = 0; y < height; y++) {
334         for (o = 0, x = 0; x < width; x++, o+= 3) {
335             dst[o    ] = ana_convert(ana_matrix_r, lsrc + o * 2, rsrc + o * 2);
336             dst[o + 1] = ana_convert(ana_matrix_g, lsrc + o * 2, rsrc + o * 2);
337             dst[o + 2] = ana_convert(ana_matrix_b, lsrc + o * 2, rsrc + o * 2);
338         }
339
340         dst  += dst_linesize;
341         lsrc += l_linesize;
342         rsrc += r_linesize;
343     }
344 }
345
346 static void anaglyph(uint8_t *dst, uint8_t *lsrc, uint8_t *rsrc,
347                      ptrdiff_t dst_linesize, ptrdiff_t l_linesize, ptrdiff_t r_linesize,
348                      int width, int height,
349                      const int *ana_matrix_r, const int *ana_matrix_g, const int *ana_matrix_b)
350 {
351     int x, y, o;
352
353     for (y = 0; y < height; y++) {
354         for (o = 0, x = 0; x < width; x++, o+= 3) {
355             dst[o    ] = ana_convert(ana_matrix_r, lsrc + o, rsrc + o);
356             dst[o + 1] = ana_convert(ana_matrix_g, lsrc + o, rsrc + o);
357             dst[o + 2] = ana_convert(ana_matrix_b, lsrc + o, rsrc + o);
358         }
359
360         dst  += dst_linesize;
361         lsrc += l_linesize;
362         rsrc += r_linesize;
363     }
364 }
365
366 static int config_output(AVFilterLink *outlink)
367 {
368     AVFilterContext *ctx = outlink->src;
369     AVFilterLink *inlink = ctx->inputs[0];
370     Stereo3DContext *s = ctx->priv;
371     AVRational fps = inlink->frame_rate;
372     AVRational tb = inlink->time_base;
373     const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
374     int ret;
375     s->aspect = inlink->sample_aspect_ratio;
376
377     switch (s->in.format) {
378     case INTERLEAVE_COLS_LR:
379     case INTERLEAVE_COLS_RL:
380     case SIDE_BY_SIDE_2_LR:
381     case SIDE_BY_SIDE_LR:
382     case SIDE_BY_SIDE_2_RL:
383     case SIDE_BY_SIDE_RL:
384         if (inlink->w & 1) {
385             av_log(ctx, AV_LOG_ERROR, "width must be even\n");
386             return AVERROR_INVALIDDATA;
387         }
388         break;
389     case INTERLEAVE_ROWS_LR:
390     case INTERLEAVE_ROWS_RL:
391     case ABOVE_BELOW_2_LR:
392     case ABOVE_BELOW_LR:
393     case ABOVE_BELOW_2_RL:
394     case ABOVE_BELOW_RL:
395         if (inlink->h & 1) {
396             av_log(ctx, AV_LOG_ERROR, "height must be even\n");
397             return AVERROR_INVALIDDATA;
398         }
399         break;
400     }
401
402     s->in.width     =
403     s->width        = inlink->w;
404     s->in.height    =
405     s->height       = inlink->h;
406     s->in.off_lstep =
407     s->in.off_rstep =
408     s->in.off_left  =
409     s->in.off_right =
410     s->in.row_left  =
411     s->in.row_right = 0;
412     s->in.row_step  = 1;
413
414     switch (s->in.format) {
415     case SIDE_BY_SIDE_2_LR:
416         s->aspect.num  *= 2;
417     case SIDE_BY_SIDE_LR:
418         s->width        = inlink->w / 2;
419         s->in.off_right = s->width;
420         break;
421     case SIDE_BY_SIDE_2_RL:
422         s->aspect.num  *= 2;
423     case SIDE_BY_SIDE_RL:
424         s->width        = inlink->w / 2;
425         s->in.off_left  = s->width;
426         break;
427     case ABOVE_BELOW_2_LR:
428         s->aspect.den  *= 2;
429     case ABOVE_BELOW_LR:
430         s->in.row_right =
431         s->height       = inlink->h / 2;
432         break;
433     case ABOVE_BELOW_2_RL:
434         s->aspect.den  *= 2;
435     case ABOVE_BELOW_RL:
436         s->in.row_left  =
437         s->height       = inlink->h / 2;
438         break;
439     case ALTERNATING_RL:
440     case ALTERNATING_LR:
441         fps.den        *= 2;
442         tb.num         *= 2;
443         break;
444     case INTERLEAVE_COLS_RL:
445     case INTERLEAVE_COLS_LR:
446         s->width        = inlink->w / 2;
447         break;
448     case INTERLEAVE_ROWS_LR:
449     case INTERLEAVE_ROWS_RL:
450         s->in.row_step  = 2;
451         if (s->in.format == INTERLEAVE_ROWS_RL)
452             s->in.off_lstep = 1;
453         else
454             s->in.off_rstep = 1;
455         if (s->out.format != CHECKERBOARD_LR &&
456             s->out.format != CHECKERBOARD_RL)
457             s->height   = inlink->h / 2;
458         break;
459     default:
460         av_log(ctx, AV_LOG_ERROR, "input format %d is not supported\n", s->in.format);
461         return AVERROR(EINVAL);
462     }
463
464     s->out.width     = s->width;
465     s->out.height    = s->height;
466     s->out.off_lstep =
467     s->out.off_rstep =
468     s->out.off_left  =
469     s->out.off_right =
470     s->out.row_left  =
471     s->out.row_right = 0;
472     s->out.row_step  = 1;
473
474     switch (s->out.format) {
475     case ANAGLYPH_RB_GRAY:
476     case ANAGLYPH_RG_GRAY:
477     case ANAGLYPH_RC_GRAY:
478     case ANAGLYPH_RC_HALF:
479     case ANAGLYPH_RC_COLOR:
480     case ANAGLYPH_RC_DUBOIS:
481     case ANAGLYPH_GM_GRAY:
482     case ANAGLYPH_GM_HALF:
483     case ANAGLYPH_GM_COLOR:
484     case ANAGLYPH_GM_DUBOIS:
485     case ANAGLYPH_YB_GRAY:
486     case ANAGLYPH_YB_HALF:
487     case ANAGLYPH_YB_COLOR:
488     case ANAGLYPH_YB_DUBOIS: {
489         uint8_t rgba_map[4];
490
491         ff_fill_rgba_map(rgba_map, outlink->format);
492         s->ana_matrix[rgba_map[0]] = &ana_coeff[s->out.format][0][0];
493         s->ana_matrix[rgba_map[1]] = &ana_coeff[s->out.format][1][0];
494         s->ana_matrix[rgba_map[2]] = &ana_coeff[s->out.format][2][0];
495         break;
496     }
497     case SIDE_BY_SIDE_2_LR:
498         s->aspect.den   *= 2;
499     case SIDE_BY_SIDE_LR:
500         s->out.width     = s->width * 2;
501         s->out.off_right = s->width;
502         break;
503     case SIDE_BY_SIDE_2_RL:
504         s->aspect.den   *= 2;
505     case SIDE_BY_SIDE_RL:
506         s->out.width     = s->width * 2;
507         s->out.off_left  = s->width;
508         break;
509     case ABOVE_BELOW_2_LR:
510         s->aspect.num   *= 2;
511     case ABOVE_BELOW_LR:
512         s->out.height    = s->height * 2;
513         s->out.row_right = s->height;
514         break;
515     case HDMI:
516         if (s->height != 720 && s->height != 1080) {
517             av_log(ctx, AV_LOG_ERROR, "Only 720 and 1080 height supported\n");
518             return AVERROR(EINVAL);
519         }
520
521         s->blanks = s->height / 24;
522         s->out.height    = s->height * 2 + s->blanks;
523         s->out.row_right = s->height + s->blanks;
524         break;
525     case ABOVE_BELOW_2_RL:
526         s->aspect.num   *= 2;
527     case ABOVE_BELOW_RL:
528         s->out.height    = s->height * 2;
529         s->out.row_left  = s->height;
530         break;
531     case INTERLEAVE_ROWS_LR:
532         s->in.row_step   = 1 + (s->in.format == INTERLEAVE_ROWS_RL);
533         s->out.row_step  = 2;
534         s->out.height    = s->height * 2;
535         s->out.off_rstep = 1;
536         break;
537     case INTERLEAVE_ROWS_RL:
538         s->in.row_step   = 1 + (s->in.format == INTERLEAVE_ROWS_LR);
539         s->out.row_step  = 2;
540         s->out.height    = s->height * 2;
541         s->out.off_lstep = 1;
542         break;
543     case MONO_R:
544         if (s->in.format != INTERLEAVE_COLS_LR) {
545             s->in.off_left = s->in.off_right;
546             s->in.row_left = s->in.row_right;
547         }
548         if (s->in.format == INTERLEAVE_ROWS_LR)
549             FFSWAP(int, s->in.off_lstep, s->in.off_rstep);
550         break;
551     case MONO_L:
552         if (s->in.format == INTERLEAVE_ROWS_RL)
553             FFSWAP(int, s->in.off_lstep, s->in.off_rstep);
554         break;
555     case ALTERNATING_RL:
556     case ALTERNATING_LR:
557         fps.num         *= 2;
558         tb.den          *= 2;
559         break;
560     case CHECKERBOARD_LR:
561     case CHECKERBOARD_RL:
562     case INTERLEAVE_COLS_LR:
563     case INTERLEAVE_COLS_RL:
564         s->out.width     = s->width * 2;
565         break;
566     default:
567         av_log(ctx, AV_LOG_ERROR, "output format %d is not supported\n", s->out.format);
568         return AVERROR(EINVAL);
569     }
570
571     if (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) {
572         if ((s->in.format & 1) != (s->out.format & 1)) {
573             FFSWAP(int, s->in.row_left,   s->in.row_right);
574             FFSWAP(int, s->in.off_lstep,  s->in.off_rstep);
575             FFSWAP(int, s->in.off_left,   s->in.off_right);
576             FFSWAP(int, s->out.row_left,  s->out.row_right);
577             FFSWAP(int, s->out.off_lstep, s->out.off_rstep);
578             FFSWAP(int, s->out.off_left,  s->out.off_right);
579         }
580     }
581
582     outlink->w = s->out.width;
583     outlink->h = s->out.height;
584     outlink->frame_rate = fps;
585     outlink->time_base = tb;
586     outlink->sample_aspect_ratio = s->aspect;
587
588     if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, s->width)) < 0)
589         return ret;
590     s->nb_planes = av_pix_fmt_count_planes(outlink->format);
591     av_image_fill_max_pixsteps(s->pixstep, NULL, desc);
592     s->pheight[1] = s->pheight[2] = AV_CEIL_RSHIFT(s->height, desc->log2_chroma_h);
593     s->pheight[0] = s->pheight[3] = s->height;
594     s->hsub = desc->log2_chroma_w;
595     s->vsub = desc->log2_chroma_h;
596
597     s->dsp.anaglyph = anaglyph;
598     if (ARCH_X86)
599         ff_stereo3d_init_x86(&s->dsp);
600
601     return 0;
602 }
603
604 typedef struct ThreadData {
605     AVFrame *ileft, *iright;
606     AVFrame *out;
607 } ThreadData;
608
609 static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
610 {
611     Stereo3DContext *s = ctx->priv;
612     ThreadData *td = arg;
613     AVFrame *ileft = td->ileft;
614     AVFrame *iright = td->iright;
615     AVFrame *out = td->out;
616     int height = s->out.height;
617     int start = (height *  jobnr   ) / nb_jobs;
618     int end   = (height * (jobnr+1)) / nb_jobs;
619     const int **ana_matrix = s->ana_matrix;
620
621     s->dsp.anaglyph(out->data[0] + out->linesize[0] * start,
622              ileft ->data[0] + s->in_off_left [0]  + ileft->linesize[0] * start * s->in.row_step,
623              iright->data[0] + s->in_off_right[0] + iright->linesize[0] * start * s->in.row_step,
624              out->linesize[0],
625              ileft->linesize[0] * s->in.row_step,
626              iright->linesize[0] * s->in.row_step,
627              s->out.width, end - start,
628              ana_matrix[0], ana_matrix[1], ana_matrix[2]);
629
630     return 0;
631 }
632
633 static void interleave_cols_to_any(Stereo3DContext *s, int *out_off, int p, AVFrame *in, AVFrame *out, int d)
634 {
635     int y, x;
636
637     for (y = 0; y < s->pheight[p]; y++) {
638         const uint8_t *src = (const uint8_t*)in->data[p] + y * in->linesize[p] + d * s->pixstep[p];
639         uint8_t *dst = out->data[p] + out_off[p] + y * out->linesize[p] * s->out.row_step;
640
641         switch (s->pixstep[p]) {
642         case 1:
643             for (x = 0; x < s->linesize[p]; x++)
644                 dst[x] = src[x * 2];
645             break;
646         case 2:
647             for (x = 0; x < s->linesize[p]; x+=2)
648                 AV_WN16(&dst[x], AV_RN16(&src[x * 2]));
649             break;
650         case 3:
651             for (x = 0; x < s->linesize[p]; x+=3)
652                 AV_WB24(&dst[x], AV_RB24(&src[x * 2]));
653             break;
654         case 4:
655             for (x = 0; x < s->linesize[p]; x+=4)
656                 AV_WN32(&dst[x], AV_RN32(&src[x * 2]));
657             break;
658         case 6:
659             for (x = 0; x < s->linesize[p]; x+=6)
660                 AV_WB48(&dst[x], AV_RB48(&src[x * 2]));
661             break;
662         case 8:
663             for (x = 0; x < s->linesize[p]; x+=8)
664                 AV_WN64(&dst[x], AV_RN64(&src[x * 2]));
665             break;
666         }
667     }
668 }
669
670 static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
671 {
672     AVFilterContext *ctx  = inlink->dst;
673     Stereo3DContext *s = ctx->priv;
674     AVFilterLink *outlink = ctx->outputs[0];
675     AVFrame *out = NULL, *oleft, *oright, *ileft, *iright;
676     int out_off_left[4], out_off_right[4];
677     int i, ret;
678
679     if (s->in.format == s->out.format)
680         return ff_filter_frame(outlink, inpicref);
681
682     switch (s->out.format) {
683     case ALTERNATING_LR:
684     case ALTERNATING_RL:
685         if (!s->prev) {
686             s->prev = inpicref;
687             return 0;
688         }
689         break;
690     };
691
692     switch (s->in.format) {
693     case ALTERNATING_LR:
694     case ALTERNATING_RL:
695         if (!s->prev) {
696             s->prev = inpicref;
697             return 0;
698         }
699         ileft  = s->prev;
700         iright = inpicref;
701         if (s->in.format == ALTERNATING_RL)
702             FFSWAP(AVFrame *, ileft, iright);
703         break;
704     default:
705         ileft = iright = inpicref;
706     };
707
708     if ((s->out.format == ALTERNATING_LR ||
709          s->out.format == ALTERNATING_RL) &&
710         (s->in.format == SIDE_BY_SIDE_LR ||
711          s->in.format == SIDE_BY_SIDE_RL ||
712          s->in.format == SIDE_BY_SIDE_2_LR ||
713          s->in.format == SIDE_BY_SIDE_2_RL ||
714          s->in.format == ABOVE_BELOW_LR ||
715          s->in.format == ABOVE_BELOW_RL ||
716          s->in.format == ABOVE_BELOW_2_LR ||
717          s->in.format == ABOVE_BELOW_2_RL ||
718          s->in.format == INTERLEAVE_ROWS_LR ||
719          s->in.format == INTERLEAVE_ROWS_RL)) {
720         oright = av_frame_clone(s->prev);
721         oleft  = av_frame_clone(s->prev);
722         if (!oright || !oleft) {
723             av_frame_free(&oright);
724             av_frame_free(&oleft);
725             av_frame_free(&s->prev);
726             av_frame_free(&inpicref);
727             return AVERROR(ENOMEM);
728         }
729     } else if ((s->out.format == MONO_L ||
730                 s->out.format == MONO_R) &&
731         (s->in.format == SIDE_BY_SIDE_LR ||
732          s->in.format == SIDE_BY_SIDE_RL ||
733          s->in.format == SIDE_BY_SIDE_2_LR ||
734          s->in.format == SIDE_BY_SIDE_2_RL ||
735          s->in.format == ABOVE_BELOW_LR ||
736          s->in.format == ABOVE_BELOW_RL ||
737          s->in.format == ABOVE_BELOW_2_LR ||
738          s->in.format == ABOVE_BELOW_2_RL ||
739          s->in.format == INTERLEAVE_ROWS_LR ||
740          s->in.format == INTERLEAVE_ROWS_RL)) {
741         out = oleft = oright = av_frame_clone(inpicref);
742         if (!out) {
743             av_frame_free(&s->prev);
744             av_frame_free(&inpicref);
745             return AVERROR(ENOMEM);
746         }
747     } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_LR) ||
748                (s->out.format == MONO_R && s->in.format == ALTERNATING_RL)) {
749         s->prev->pts /= 2;
750         ret = ff_filter_frame(outlink, s->prev);
751         av_frame_free(&inpicref);
752         s->prev = NULL;
753         return ret;
754     } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_RL) ||
755                (s->out.format == MONO_R && s->in.format == ALTERNATING_LR)) {
756         av_frame_free(&s->prev);
757         inpicref->pts /= 2;
758         return ff_filter_frame(outlink, inpicref);
759     } else if ((s->out.format == ALTERNATING_LR && s->in.format == ALTERNATING_RL) ||
760                (s->out.format == ALTERNATING_RL && s->in.format == ALTERNATING_LR)) {
761         FFSWAP(int64_t, s->prev->pts, inpicref->pts);
762         ff_filter_frame(outlink, inpicref);
763         ret = ff_filter_frame(outlink, s->prev);
764         s->prev = NULL;
765         return ret;
766     } else {
767         out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
768         if (!out) {
769             av_frame_free(&s->prev);
770             av_frame_free(&inpicref);
771             return AVERROR(ENOMEM);
772         }
773         av_frame_copy_props(out, inpicref);
774
775         if (s->out.format == ALTERNATING_LR ||
776             s->out.format == ALTERNATING_RL) {
777             oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
778             if (!oright) {
779                 av_frame_free(&oleft);
780                 av_frame_free(&s->prev);
781                 av_frame_free(&inpicref);
782                 return AVERROR(ENOMEM);
783             }
784             av_frame_copy_props(oright, s->prev);
785         }
786     }
787
788     for (i = 0; i < 4; i++) {
789         int hsub = i == 1 || i == 2 ? s->hsub : 0;
790         int vsub = i == 1 || i == 2 ? s->vsub : 0;
791         s->in_off_left[i]   = (AV_CEIL_RSHIFT(s->in.row_left,   vsub) + s->in.off_lstep)  * ileft->linesize[i]  + AV_CEIL_RSHIFT(s->in.off_left   * s->pixstep[i], hsub);
792         s->in_off_right[i]  = (AV_CEIL_RSHIFT(s->in.row_right,  vsub) + s->in.off_rstep)  * iright->linesize[i] + AV_CEIL_RSHIFT(s->in.off_right  * s->pixstep[i], hsub);
793         out_off_left[i]  = (AV_CEIL_RSHIFT(s->out.row_left,  vsub) + s->out.off_lstep) * oleft->linesize[i]  + AV_CEIL_RSHIFT(s->out.off_left  * s->pixstep[i], hsub);
794         out_off_right[i] = (AV_CEIL_RSHIFT(s->out.row_right, vsub) + s->out.off_rstep) * oright->linesize[i] + AV_CEIL_RSHIFT(s->out.off_right * s->pixstep[i], hsub);
795     }
796
797     switch (s->out.format) {
798     case ALTERNATING_LR:
799     case ALTERNATING_RL:
800         switch (s->in.format) {
801         case INTERLEAVE_ROWS_LR:
802         case INTERLEAVE_ROWS_RL:
803             for (i = 0; i < s->nb_planes; i++) {
804                 oleft->linesize[i]  *= 2;
805                 oright->linesize[i] *= 2;
806             }
807         case ABOVE_BELOW_LR:
808         case ABOVE_BELOW_RL:
809         case ABOVE_BELOW_2_LR:
810         case ABOVE_BELOW_2_RL:
811         case SIDE_BY_SIDE_LR:
812         case SIDE_BY_SIDE_RL:
813         case SIDE_BY_SIDE_2_LR:
814         case SIDE_BY_SIDE_2_RL:
815             oleft->width   = outlink->w;
816             oright->width  = outlink->w;
817             oleft->height  = outlink->h;
818             oright->height = outlink->h;
819
820             for (i = 0; i < s->nb_planes; i++) {
821                 oleft->data[i]  += s->in_off_left[i];
822                 oright->data[i] += s->in_off_right[i];
823             }
824             break;
825         default:
826             goto copy;
827             break;
828         }
829         break;
830     case HDMI:
831         for (i = 0; i < s->nb_planes; i++) {
832             int j, h = s->height >> ((i == 1 || i == 2) ? s->vsub : 0);
833             int b = (s->blanks) >> ((i == 1 || i == 2) ? s->vsub : 0);
834
835             for (j = h; j < h + b; j++)
836                 memset(oleft->data[i] + j * s->linesize[i], 0, s->linesize[i]);
837         }
838     case SIDE_BY_SIDE_LR:
839     case SIDE_BY_SIDE_RL:
840     case SIDE_BY_SIDE_2_LR:
841     case SIDE_BY_SIDE_2_RL:
842     case ABOVE_BELOW_LR:
843     case ABOVE_BELOW_RL:
844     case ABOVE_BELOW_2_LR:
845     case ABOVE_BELOW_2_RL:
846     case INTERLEAVE_ROWS_LR:
847     case INTERLEAVE_ROWS_RL:
848 copy:
849         if (s->in.format == INTERLEAVE_COLS_LR ||
850             s->in.format == INTERLEAVE_COLS_RL) {
851             for (i = 0; i < s->nb_planes; i++) {
852                 int d = (s->in.format & 1) != (s->out.format & 1);
853
854                 interleave_cols_to_any(s, out_off_left,  i, ileft,  oleft,   d);
855                 interleave_cols_to_any(s, out_off_right, i, iright, oright, !d);
856             }
857         } else {
858             for (i = 0; i < s->nb_planes; i++) {
859                 av_image_copy_plane(oleft->data[i] + out_off_left[i],
860                                     oleft->linesize[i] * s->out.row_step,
861                                     ileft->data[i] + s->in_off_left[i],
862                                     ileft->linesize[i] * s->in.row_step,
863                                     s->linesize[i], s->pheight[i]);
864                 av_image_copy_plane(oright->data[i] + out_off_right[i],
865                                     oright->linesize[i] * s->out.row_step,
866                                     iright->data[i] + s->in_off_right[i],
867                                     iright->linesize[i] * s->in.row_step,
868                                     s->linesize[i], s->pheight[i]);
869             }
870         }
871         break;
872     case MONO_L:
873         iright = ileft;
874     case MONO_R:
875         switch (s->in.format) {
876         case INTERLEAVE_ROWS_LR:
877         case INTERLEAVE_ROWS_RL:
878             for (i = 0; i < s->nb_planes; i++) {
879                 out->linesize[i] *= 2;
880             }
881         case ABOVE_BELOW_LR:
882         case ABOVE_BELOW_RL:
883         case ABOVE_BELOW_2_LR:
884         case ABOVE_BELOW_2_RL:
885         case SIDE_BY_SIDE_LR:
886         case SIDE_BY_SIDE_RL:
887         case SIDE_BY_SIDE_2_LR:
888         case SIDE_BY_SIDE_2_RL:
889             out->width  = outlink->w;
890             out->height = outlink->h;
891
892             for (i = 0; i < s->nb_planes; i++) {
893                 out->data[i] += s->in_off_left[i];
894             }
895             break;
896         case INTERLEAVE_COLS_LR:
897         case INTERLEAVE_COLS_RL:
898             for (i = 0; i < s->nb_planes; i++) {
899                 const int d = (s->in.format & 1) != (s->out.format & 1);
900
901                 interleave_cols_to_any(s, out_off_right, i, iright, out, d);
902             }
903             break;
904         default:
905             for (i = 0; i < s->nb_planes; i++) {
906                 av_image_copy_plane(out->data[i], out->linesize[i],
907                                     iright->data[i] + s->in_off_left[i],
908                                     iright->linesize[i] * s->in.row_step,
909                                     s->linesize[i], s->pheight[i]);
910             }
911             break;
912         }
913         break;
914     case ANAGLYPH_RB_GRAY:
915     case ANAGLYPH_RG_GRAY:
916     case ANAGLYPH_RC_GRAY:
917     case ANAGLYPH_RC_HALF:
918     case ANAGLYPH_RC_COLOR:
919     case ANAGLYPH_RC_DUBOIS:
920     case ANAGLYPH_GM_GRAY:
921     case ANAGLYPH_GM_HALF:
922     case ANAGLYPH_GM_COLOR:
923     case ANAGLYPH_GM_DUBOIS:
924     case ANAGLYPH_YB_GRAY:
925     case ANAGLYPH_YB_HALF:
926     case ANAGLYPH_YB_COLOR:
927     case ANAGLYPH_YB_DUBOIS: {
928         if (s->in.format == INTERLEAVE_COLS_LR ||
929             s->in.format == INTERLEAVE_COLS_RL) {
930             const int d = (s->in.format & 1);
931
932             anaglyph_ic(out->data[0],
933                 ileft ->data[0] + s->in_off_left [0] +   d  * 3,
934                 iright->data[0] + s->in_off_right[0] + (!d) * 3,
935                 out->linesize[0],
936                 ileft->linesize[0] * s->in.row_step,
937                 iright->linesize[0] * s->in.row_step,
938                 s->out.width, s->out.height,
939                 s->ana_matrix[0], s->ana_matrix[1], s->ana_matrix[2]);
940         } else {
941             ThreadData td;
942
943             td.ileft = ileft; td.iright = iright; td.out = out;
944             ctx->internal->execute(ctx, filter_slice, &td, NULL,
945                                    FFMIN(s->out.height, ff_filter_get_nb_threads(ctx)));
946         }
947         break;
948     }
949     case CHECKERBOARD_RL:
950     case CHECKERBOARD_LR:
951         for (i = 0; i < s->nb_planes; i++) {
952             int x, y;
953
954             for (y = 0; y < s->pheight[i]; y++) {
955                 uint8_t *dst = out->data[i] + out->linesize[i] * y;
956                 const int d1 = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) && (s->in.format & 1) != (s->out.format & 1);
957                 const int d2 = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) ? !d1 : 0;
958                 const int m = 1 + (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL);
959                 uint8_t *left  = ileft->data[i]  + ileft->linesize[i]  * y + s->in_off_left[i]  + d1 * s->pixstep[i];
960                 uint8_t *right = iright->data[i] + iright->linesize[i] * y + s->in_off_right[i] + d2 * s->pixstep[i];
961                 int p, b;
962
963                 if (s->out.format == CHECKERBOARD_RL && s->in.format != INTERLEAVE_COLS_LR && s->in.format != INTERLEAVE_COLS_RL)
964                     FFSWAP(uint8_t*, left, right);
965                 switch (s->pixstep[i]) {
966                 case 1:
967                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=2, p++, b+=2) {
968                         dst[x  ] = (b&1) == (y&1) ? left[p*m] : right[p*m];
969                         dst[x+1] = (b&1) != (y&1) ? left[p*m] : right[p*m];
970                     }
971                     break;
972                 case 2:
973                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=4, p+=2, b+=2) {
974                         AV_WN16(&dst[x  ], (b&1) == (y&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
975                         AV_WN16(&dst[x+2], (b&1) != (y&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
976                     }
977                     break;
978                 case 3:
979                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=6, p+=3, b+=2) {
980                         AV_WB24(&dst[x  ], (b&1) == (y&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
981                         AV_WB24(&dst[x+3], (b&1) != (y&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
982                     }
983                     break;
984                 case 4:
985                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=8, p+=4, b+=2) {
986                         AV_WN32(&dst[x  ], (b&1) == (y&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
987                         AV_WN32(&dst[x+4], (b&1) != (y&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
988                     }
989                     break;
990                 case 6:
991                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=12, p+=6, b+=2) {
992                         AV_WB48(&dst[x  ], (b&1) == (y&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
993                         AV_WB48(&dst[x+6], (b&1) != (y&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
994                     }
995                     break;
996                 case 8:
997                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=16, p+=8, b+=2) {
998                         AV_WN64(&dst[x  ], (b&1) == (y&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
999                         AV_WN64(&dst[x+8], (b&1) != (y&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
1000                     }
1001                     break;
1002                 }
1003             }
1004         }
1005         break;
1006     case INTERLEAVE_COLS_LR:
1007     case INTERLEAVE_COLS_RL:
1008         for (i = 0; i < s->nb_planes; i++) {
1009             const int d = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL);
1010             const int m = 1 + d;
1011             int x, y;
1012
1013             for (y = 0; y < s->pheight[i]; y++) {
1014                 uint8_t *dst = out->data[i] + out->linesize[i] * y;
1015                 uint8_t *left = ileft->data[i] + ileft->linesize[i] * y * s->in.row_step + s->in_off_left[i] + d * s->pixstep[i];
1016                 uint8_t *right = iright->data[i] + iright->linesize[i] * y * s->in.row_step + s->in_off_right[i];
1017                 int p, b;
1018
1019                 if (s->out.format == INTERLEAVE_COLS_LR)
1020                     FFSWAP(uint8_t*, left, right);
1021
1022                 switch (s->pixstep[i]) {
1023                 case 1:
1024                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=2, p++, b+=2) {
1025                         dst[x  ] =   b&1  ? left[p*m] : right[p*m];
1026                         dst[x+1] = !(b&1) ? left[p*m] : right[p*m];
1027                     }
1028                     break;
1029                 case 2:
1030                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=4, p+=2, b+=2) {
1031                         AV_WN16(&dst[x  ],   b&1  ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
1032                         AV_WN16(&dst[x+2], !(b&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
1033                     }
1034                     break;
1035                 case 3:
1036                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=6, p+=3, b+=2) {
1037                         AV_WB24(&dst[x  ],   b&1  ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
1038                         AV_WB24(&dst[x+3], !(b&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
1039                     }
1040                     break;
1041                 case 4:
1042                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=8, p+=4, b+=2) {
1043                         AV_WN32(&dst[x  ],   b&1  ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
1044                         AV_WN32(&dst[x+4], !(b&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
1045                     }
1046                     break;
1047                 case 6:
1048                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=12, p+=6, b+=2) {
1049                         AV_WB48(&dst[x  ],   b&1  ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
1050                         AV_WB48(&dst[x+6], !(b&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
1051                     }
1052                     break;
1053                 case 8:
1054                     for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=16, p+=8, b+=2) {
1055                         AV_WN64(&dst[x  ],   b&1 ?  AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
1056                         AV_WN64(&dst[x+8], !(b&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
1057                     }
1058                     break;
1059                 }
1060             }
1061         }
1062         break;
1063     default:
1064         av_assert0(0);
1065     }
1066
1067     if (oright != oleft) {
1068         if (s->out.format == ALTERNATING_LR)
1069             FFSWAP(AVFrame *, oleft, oright);
1070         oright->pts = s->prev->pts * 2;
1071         ff_filter_frame(outlink, oright);
1072         out = oleft;
1073         oleft->pts = s->prev->pts + inpicref->pts;
1074         av_frame_free(&s->prev);
1075         s->prev = inpicref;
1076     } else if (s->in.format == ALTERNATING_LR ||
1077                s->in.format == ALTERNATING_RL) {
1078         out->pts = s->prev->pts / 2;
1079         av_frame_free(&s->prev);
1080         av_frame_free(&inpicref);
1081     } else {
1082         av_frame_free(&s->prev);
1083         av_frame_free(&inpicref);
1084     }
1085     av_assert0(out);
1086     out->sample_aspect_ratio = s->aspect;
1087     return ff_filter_frame(outlink, out);
1088 }
1089
1090 static av_cold void uninit(AVFilterContext *ctx)
1091 {
1092     Stereo3DContext *s = ctx->priv;
1093
1094     av_frame_free(&s->prev);
1095 }
1096
1097 static const AVFilterPad stereo3d_inputs[] = {
1098     {
1099         .name         = "default",
1100         .type         = AVMEDIA_TYPE_VIDEO,
1101         .filter_frame = filter_frame,
1102     },
1103     { NULL }
1104 };
1105
1106 static const AVFilterPad stereo3d_outputs[] = {
1107     {
1108         .name         = "default",
1109         .type         = AVMEDIA_TYPE_VIDEO,
1110         .config_props = config_output,
1111     },
1112     { NULL }
1113 };
1114
1115 AVFilter ff_vf_stereo3d = {
1116     .name          = "stereo3d",
1117     .description   = NULL_IF_CONFIG_SMALL("Convert video stereoscopic 3D view."),
1118     .priv_size     = sizeof(Stereo3DContext),
1119     .uninit        = uninit,
1120     .query_formats = query_formats,
1121     .inputs        = stereo3d_inputs,
1122     .outputs       = stereo3d_outputs,
1123     .priv_class    = &stereo3d_class,
1124     .flags         = AVFILTER_FLAG_SLICE_THREADS,
1125 };