Line | Branch | Exec | Source |
---|---|---|---|
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, .unit = "in"}, | ||
162 | { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
163 | { "tb2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
164 | { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
165 | { "tb2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
166 | { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
167 | { "tbl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
168 | { "abr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
169 | { "tbr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
170 | { "al", "alternating frames left first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
171 | { "ar", "alternating frames right first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
172 | { "sbs2l", "side by side half width left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
173 | { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
174 | { "sbsl", "side by side left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
175 | { "sbsr", "side by side right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
176 | { "irl", "interleave rows left first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
177 | { "irr", "interleave rows right first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
178 | { "icl", "interleave columns left first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_LR}, 0, 0, FLAGS, .unit = "in" }, | ||
179 | { "icr", "interleave columns right first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_RL}, 0, 0, FLAGS, .unit = "in" }, | ||
180 | { "out", "set output format", OFFSET(out.format), AV_OPT_TYPE_INT, {.i64=ANAGLYPH_RC_DUBOIS}, 0, STEREO_CODE_COUNT-1, FLAGS, .unit = "out"}, | ||
181 | { "ab2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
182 | { "tb2l", "above below half height left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
183 | { "ab2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
184 | { "tb2r", "above below half height right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_2_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
185 | { "abl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
186 | { "tbl", "above below left first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
187 | { "abr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
188 | { "tbr", "above below right first", 0, AV_OPT_TYPE_CONST, {.i64=ABOVE_BELOW_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
189 | { "agmc", "anaglyph green magenta color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_COLOR}, 0, 0, FLAGS, .unit = "out" }, | ||
190 | { "agmd", "anaglyph green magenta dubois", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_DUBOIS}, 0, 0, FLAGS, .unit = "out" }, | ||
191 | { "agmg", "anaglyph green magenta gray", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_GRAY}, 0, 0, FLAGS, .unit = "out" }, | ||
192 | { "agmh", "anaglyph green magenta half color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_GM_HALF}, 0, 0, FLAGS, .unit = "out" }, | ||
193 | { "al", "alternating frames left first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
194 | { "ar", "alternating frames right first", 0, AV_OPT_TYPE_CONST, {.i64=ALTERNATING_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
195 | { "arbg", "anaglyph red blue gray", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RB_GRAY}, 0, 0, FLAGS, .unit = "out" }, | ||
196 | { "arcc", "anaglyph red cyan color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_COLOR}, 0, 0, FLAGS, .unit = "out" }, | ||
197 | { "arcd", "anaglyph red cyan dubois", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_DUBOIS}, 0, 0, FLAGS, .unit = "out" }, | ||
198 | { "arcg", "anaglyph red cyan gray", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_GRAY}, 0, 0, FLAGS, .unit = "out" }, | ||
199 | { "arch", "anaglyph red cyan half color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RC_HALF}, 0, 0, FLAGS, .unit = "out" }, | ||
200 | { "argg", "anaglyph red green gray", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_RG_GRAY}, 0, 0, FLAGS, .unit = "out" }, | ||
201 | { "aybc", "anaglyph yellow blue color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_COLOR}, 0, 0, FLAGS, .unit = "out" }, | ||
202 | { "aybd", "anaglyph yellow blue dubois", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_DUBOIS}, 0, 0, FLAGS, .unit = "out" }, | ||
203 | { "aybg", "anaglyph yellow blue gray", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_GRAY}, 0, 0, FLAGS, .unit = "out" }, | ||
204 | { "aybh", "anaglyph yellow blue half color", 0, AV_OPT_TYPE_CONST, {.i64=ANAGLYPH_YB_HALF}, 0, 0, FLAGS, .unit = "out" }, | ||
205 | { "irl", "interleave rows left first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
206 | { "irr", "interleave rows right first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_ROWS_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
207 | { "ml", "mono left", 0, AV_OPT_TYPE_CONST, {.i64=MONO_L}, 0, 0, FLAGS, .unit = "out" }, | ||
208 | { "mr", "mono right", 0, AV_OPT_TYPE_CONST, {.i64=MONO_R}, 0, 0, FLAGS, .unit = "out" }, | ||
209 | { "sbs2l", "side by side half width left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
210 | { "sbs2r", "side by side half width right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_2_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
211 | { "sbsl", "side by side left first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
212 | { "sbsr", "side by side right first", 0, AV_OPT_TYPE_CONST, {.i64=SIDE_BY_SIDE_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
213 | { "chl", "checkerboard left first", 0, AV_OPT_TYPE_CONST, {.i64=CHECKERBOARD_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
214 | { "chr", "checkerboard right first", 0, AV_OPT_TYPE_CONST, {.i64=CHECKERBOARD_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
215 | { "icl", "interleave columns left first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_LR}, 0, 0, FLAGS, .unit = "out" }, | ||
216 | { "icr", "interleave columns right first", 0, AV_OPT_TYPE_CONST, {.i64=INTERLEAVE_COLS_RL}, 0, 0, FLAGS, .unit = "out" }, | ||
217 | { "hdmi", "HDMI frame pack", 0, AV_OPT_TYPE_CONST, {.i64=HDMI}, 0, 0, FLAGS, .unit = "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 | 22 | static int query_formats(AVFilterContext *ctx) | |
283 | { | ||
284 | 22 | Stereo3DContext *s = ctx->priv; | |
285 | const enum AVPixelFormat *pix_fmts; | ||
286 | |||
287 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8 times.
|
22 | switch (s->out.format) { |
288 | 14 | case ANAGLYPH_GM_COLOR: | |
289 | case ANAGLYPH_GM_DUBOIS: | ||
290 | case ANAGLYPH_GM_GRAY: | ||
291 | case ANAGLYPH_GM_HALF: | ||
292 | case ANAGLYPH_RB_GRAY: | ||
293 | case ANAGLYPH_RC_COLOR: | ||
294 | case ANAGLYPH_RC_DUBOIS: | ||
295 | case ANAGLYPH_RC_GRAY: | ||
296 | case ANAGLYPH_RC_HALF: | ||
297 | case ANAGLYPH_RG_GRAY: | ||
298 | case ANAGLYPH_YB_COLOR: | ||
299 | case ANAGLYPH_YB_DUBOIS: | ||
300 | case ANAGLYPH_YB_GRAY: | ||
301 | case ANAGLYPH_YB_HALF: | ||
302 | 14 | pix_fmts = anaglyph_pix_fmts; | |
303 | 14 | break; | |
304 | 8 | default: | |
305 | 8 | pix_fmts = other_pix_fmts; | |
306 | } | ||
307 | |||
308 | 22 | return ff_set_common_formats_from_list(ctx, pix_fmts); | |
309 | } | ||
310 | |||
311 | 10644480 | static inline uint8_t ana_convert(const int *coeff, const uint8_t *left, const uint8_t *right) | |
312 | { | ||
313 | int sum; | ||
314 | |||
315 | 10644480 | sum = coeff[0] * left[0] + coeff[3] * right[0]; //red in | |
316 | 10644480 | sum += coeff[1] * left[1] + coeff[4] * right[1]; //green in | |
317 | 10644480 | sum += coeff[2] * left[2] + coeff[5] * right[2]; //blue in | |
318 | |||
319 | 10644480 | return av_clip_uint8(sum >> 16); | |
320 | } | ||
321 | |||
322 | ✗ | static void anaglyph_ic(uint8_t *dst, uint8_t *lsrc, uint8_t *rsrc, | |
323 | ptrdiff_t dst_linesize, ptrdiff_t l_linesize, ptrdiff_t r_linesize, | ||
324 | int width, int height, | ||
325 | const int *ana_matrix_r, const int *ana_matrix_g, const int *ana_matrix_b) | ||
326 | { | ||
327 | int x, y, o; | ||
328 | |||
329 | ✗ | for (y = 0; y < height; y++) { | |
330 | ✗ | for (o = 0, x = 0; x < width; x++, o+= 3) { | |
331 | ✗ | dst[o ] = ana_convert(ana_matrix_r, lsrc + o * 2, rsrc + o * 2); | |
332 | ✗ | dst[o + 1] = ana_convert(ana_matrix_g, lsrc + o * 2, rsrc + o * 2); | |
333 | ✗ | dst[o + 2] = ana_convert(ana_matrix_b, lsrc + o * 2, rsrc + o * 2); | |
334 | } | ||
335 | |||
336 | ✗ | dst += dst_linesize; | |
337 | ✗ | lsrc += l_linesize; | |
338 | ✗ | rsrc += r_linesize; | |
339 | } | ||
340 | ✗ | } | |
341 | |||
342 | 630 | static void anaglyph(uint8_t *dst, uint8_t *lsrc, uint8_t *rsrc, | |
343 | ptrdiff_t dst_linesize, ptrdiff_t l_linesize, ptrdiff_t r_linesize, | ||
344 | int width, int height, | ||
345 | const int *ana_matrix_r, const int *ana_matrix_g, const int *ana_matrix_b) | ||
346 | { | ||
347 | int x, y, o; | ||
348 | |||
349 |
2/2✓ Branch 0 taken 20160 times.
✓ Branch 1 taken 630 times.
|
20790 | for (y = 0; y < height; y++) { |
350 |
2/2✓ Branch 0 taken 3548160 times.
✓ Branch 1 taken 20160 times.
|
3568320 | for (o = 0, x = 0; x < width; x++, o+= 3) { |
351 | 3548160 | dst[o ] = ana_convert(ana_matrix_r, lsrc + o, rsrc + o); | |
352 | 3548160 | dst[o + 1] = ana_convert(ana_matrix_g, lsrc + o, rsrc + o); | |
353 | 3548160 | dst[o + 2] = ana_convert(ana_matrix_b, lsrc + o, rsrc + o); | |
354 | } | ||
355 | |||
356 | 20160 | dst += dst_linesize; | |
357 | 20160 | lsrc += l_linesize; | |
358 | 20160 | rsrc += r_linesize; | |
359 | } | ||
360 | 630 | } | |
361 | |||
362 | 22 | static int config_output(AVFilterLink *outlink) | |
363 | { | ||
364 | 22 | AVFilterContext *ctx = outlink->src; | |
365 | 22 | AVFilterLink *inlink = ctx->inputs[0]; | |
366 | 22 | Stereo3DContext *s = ctx->priv; | |
367 | 22 | AVRational fps = inlink->frame_rate; | |
368 | 22 | AVRational tb = inlink->time_base; | |
369 | 22 | const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format); | |
370 | int ret; | ||
371 | 22 | s->aspect = inlink->sample_aspect_ratio; | |
372 | |||
373 |
3/3✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
22 | switch (s->in.format) { |
374 | 18 | case INTERLEAVE_COLS_LR: | |
375 | case INTERLEAVE_COLS_RL: | ||
376 | case SIDE_BY_SIDE_2_LR: | ||
377 | case SIDE_BY_SIDE_LR: | ||
378 | case SIDE_BY_SIDE_2_RL: | ||
379 | case SIDE_BY_SIDE_RL: | ||
380 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (inlink->w & 1) { |
381 | ✗ | av_log(ctx, AV_LOG_ERROR, "width must be even\n"); | |
382 | ✗ | return AVERROR_INVALIDDATA; | |
383 | } | ||
384 | 18 | break; | |
385 | 2 | case INTERLEAVE_ROWS_LR: | |
386 | case INTERLEAVE_ROWS_RL: | ||
387 | case ABOVE_BELOW_2_LR: | ||
388 | case ABOVE_BELOW_LR: | ||
389 | case ABOVE_BELOW_2_RL: | ||
390 | case ABOVE_BELOW_RL: | ||
391 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (inlink->h & 1) { |
392 | ✗ | av_log(ctx, AV_LOG_ERROR, "height must be even\n"); | |
393 | ✗ | return AVERROR_INVALIDDATA; | |
394 | } | ||
395 | 2 | break; | |
396 | } | ||
397 | |||
398 | 22 | s->in.width = | |
399 | 22 | s->width = inlink->w; | |
400 | 22 | s->in.height = | |
401 | 22 | s->height = inlink->h; | |
402 | 22 | s->in.off_lstep = | |
403 | 22 | s->in.off_rstep = | |
404 | 22 | s->in.off_left = | |
405 | 22 | s->in.off_right = | |
406 | 22 | s->in.row_left = | |
407 | 22 | s->in.row_right = 0; | |
408 | 22 | s->in.row_step = 1; | |
409 | |||
410 |
3/12✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
✓ Branch 8 taken 2 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
22 | switch (s->in.format) { |
411 | ✗ | case SIDE_BY_SIDE_2_LR: | |
412 | ✗ | s->aspect.num *= 2; | |
413 | 18 | case SIDE_BY_SIDE_LR: | |
414 | 18 | s->width = inlink->w / 2; | |
415 | 18 | s->in.off_right = s->width; | |
416 | 18 | break; | |
417 | ✗ | case SIDE_BY_SIDE_2_RL: | |
418 | ✗ | s->aspect.num *= 2; | |
419 | ✗ | case SIDE_BY_SIDE_RL: | |
420 | ✗ | s->width = inlink->w / 2; | |
421 | ✗ | s->in.off_left = s->width; | |
422 | ✗ | break; | |
423 | ✗ | case ABOVE_BELOW_2_LR: | |
424 | ✗ | s->aspect.den *= 2; | |
425 | ✗ | case ABOVE_BELOW_LR: | |
426 | ✗ | s->in.row_right = | |
427 | ✗ | s->height = inlink->h / 2; | |
428 | ✗ | break; | |
429 | ✗ | case ABOVE_BELOW_2_RL: | |
430 | ✗ | s->aspect.den *= 2; | |
431 | 2 | case ABOVE_BELOW_RL: | |
432 | 2 | s->in.row_left = | |
433 | 2 | s->height = inlink->h / 2; | |
434 | 2 | break; | |
435 | 2 | case ALTERNATING_RL: | |
436 | case ALTERNATING_LR: | ||
437 | 2 | fps.den *= 2; | |
438 | 2 | tb.num *= 2; | |
439 | 2 | break; | |
440 | ✗ | case INTERLEAVE_COLS_RL: | |
441 | case INTERLEAVE_COLS_LR: | ||
442 | ✗ | s->width = inlink->w / 2; | |
443 | ✗ | break; | |
444 | ✗ | case INTERLEAVE_ROWS_LR: | |
445 | case INTERLEAVE_ROWS_RL: | ||
446 | ✗ | s->in.row_step = 2; | |
447 | ✗ | if (s->in.format == INTERLEAVE_ROWS_RL) | |
448 | ✗ | s->in.off_lstep = 1; | |
449 | else | ||
450 | ✗ | s->in.off_rstep = 1; | |
451 | ✗ | if (s->out.format != CHECKERBOARD_LR && | |
452 | ✗ | s->out.format != CHECKERBOARD_RL) | |
453 | ✗ | s->height = inlink->h / 2; | |
454 | ✗ | break; | |
455 | ✗ | default: | |
456 | ✗ | av_log(ctx, AV_LOG_ERROR, "input format %d is not supported\n", s->in.format); | |
457 | ✗ | return AVERROR(EINVAL); | |
458 | } | ||
459 | |||
460 | 22 | s->out.width = s->width; | |
461 | 22 | s->out.height = s->height; | |
462 | 22 | s->out.off_lstep = | |
463 | 22 | s->out.off_rstep = | |
464 | 22 | s->out.off_left = | |
465 | 22 | s->out.off_right = | |
466 | 22 | s->out.row_left = | |
467 | 22 | s->out.row_right = 0; | |
468 | 22 | s->out.row_step = 1; | |
469 | |||
470 |
8/17✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 times.
✓ Branch 13 taken 1 times.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
|
22 | switch (s->out.format) { |
471 | 14 | case ANAGLYPH_RB_GRAY: | |
472 | case ANAGLYPH_RG_GRAY: | ||
473 | case ANAGLYPH_RC_GRAY: | ||
474 | case ANAGLYPH_RC_HALF: | ||
475 | case ANAGLYPH_RC_COLOR: | ||
476 | case ANAGLYPH_RC_DUBOIS: | ||
477 | case ANAGLYPH_GM_GRAY: | ||
478 | case ANAGLYPH_GM_HALF: | ||
479 | case ANAGLYPH_GM_COLOR: | ||
480 | case ANAGLYPH_GM_DUBOIS: | ||
481 | case ANAGLYPH_YB_GRAY: | ||
482 | case ANAGLYPH_YB_HALF: | ||
483 | case ANAGLYPH_YB_COLOR: | ||
484 | case ANAGLYPH_YB_DUBOIS: { | ||
485 | uint8_t rgba_map[4]; | ||
486 | |||
487 | 14 | ff_fill_rgba_map(rgba_map, outlink->format); | |
488 | 14 | s->ana_matrix[rgba_map[0]] = &ana_coeff[s->out.format][0][0]; | |
489 | 14 | s->ana_matrix[rgba_map[1]] = &ana_coeff[s->out.format][1][0]; | |
490 | 14 | s->ana_matrix[rgba_map[2]] = &ana_coeff[s->out.format][2][0]; | |
491 | 14 | break; | |
492 | } | ||
493 | ✗ | case SIDE_BY_SIDE_2_LR: | |
494 | ✗ | s->aspect.den *= 2; | |
495 | 1 | case SIDE_BY_SIDE_LR: | |
496 | 1 | s->out.width = s->width * 2; | |
497 | 1 | s->out.off_right = s->width; | |
498 | 1 | break; | |
499 | ✗ | case SIDE_BY_SIDE_2_RL: | |
500 | ✗ | s->aspect.den *= 2; | |
501 | 1 | case SIDE_BY_SIDE_RL: | |
502 | 1 | s->out.width = s->width * 2; | |
503 | 1 | s->out.off_left = s->width; | |
504 | 1 | break; | |
505 | ✗ | case ABOVE_BELOW_2_LR: | |
506 | ✗ | s->aspect.num *= 2; | |
507 | 2 | case ABOVE_BELOW_LR: | |
508 | 2 | s->out.height = s->height * 2; | |
509 | 2 | s->out.row_right = s->height; | |
510 | 2 | break; | |
511 | ✗ | case HDMI: | |
512 | ✗ | if (s->height != 720 && s->height != 1080) { | |
513 | ✗ | av_log(ctx, AV_LOG_ERROR, "Only 720 and 1080 height supported\n"); | |
514 | ✗ | return AVERROR(EINVAL); | |
515 | } | ||
516 | |||
517 | ✗ | s->blanks = s->height / 24; | |
518 | ✗ | s->out.height = s->height * 2 + s->blanks; | |
519 | ✗ | s->out.row_right = s->height + s->blanks; | |
520 | ✗ | break; | |
521 | ✗ | case ABOVE_BELOW_2_RL: | |
522 | ✗ | s->aspect.num *= 2; | |
523 | 1 | case ABOVE_BELOW_RL: | |
524 | 1 | s->out.height = s->height * 2; | |
525 | 1 | s->out.row_left = s->height; | |
526 | 1 | break; | |
527 | ✗ | case INTERLEAVE_ROWS_LR: | |
528 | ✗ | s->in.row_step = 1 + (s->in.format == INTERLEAVE_ROWS_RL); | |
529 | ✗ | s->out.row_step = 2; | |
530 | ✗ | s->out.height = s->height * 2; | |
531 | ✗ | s->out.off_rstep = 1; | |
532 | ✗ | break; | |
533 | ✗ | case INTERLEAVE_ROWS_RL: | |
534 | ✗ | s->in.row_step = 1 + (s->in.format == INTERLEAVE_ROWS_LR); | |
535 | ✗ | s->out.row_step = 2; | |
536 | ✗ | s->out.height = s->height * 2; | |
537 | ✗ | s->out.off_lstep = 1; | |
538 | ✗ | break; | |
539 | 1 | case MONO_R: | |
540 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (s->in.format != INTERLEAVE_COLS_LR) { |
541 | 1 | s->in.off_left = s->in.off_right; | |
542 | 1 | s->in.row_left = s->in.row_right; | |
543 | } | ||
544 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (s->in.format == INTERLEAVE_ROWS_LR) |
545 | ✗ | FFSWAP(int, s->in.off_lstep, s->in.off_rstep); | |
546 | 1 | break; | |
547 | 1 | case MONO_L: | |
548 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (s->in.format == INTERLEAVE_ROWS_RL) |
549 | ✗ | FFSWAP(int, s->in.off_lstep, s->in.off_rstep); | |
550 | 1 | break; | |
551 | 1 | case ALTERNATING_RL: | |
552 | case ALTERNATING_LR: | ||
553 | 1 | fps.num *= 2; | |
554 | 1 | tb.den *= 2; | |
555 | 1 | break; | |
556 | ✗ | case CHECKERBOARD_LR: | |
557 | case CHECKERBOARD_RL: | ||
558 | case INTERLEAVE_COLS_LR: | ||
559 | case INTERLEAVE_COLS_RL: | ||
560 | ✗ | s->out.width = s->width * 2; | |
561 | ✗ | break; | |
562 | ✗ | default: | |
563 | ✗ | av_log(ctx, AV_LOG_ERROR, "output format %d is not supported\n", s->out.format); | |
564 | ✗ | return AVERROR(EINVAL); | |
565 | } | ||
566 | |||
567 |
2/4✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 22 times.
|
22 | if (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) { |
568 | ✗ | if ((s->in.format & 1) != (s->out.format & 1)) { | |
569 | ✗ | FFSWAP(int, s->in.row_left, s->in.row_right); | |
570 | ✗ | FFSWAP(int, s->in.off_lstep, s->in.off_rstep); | |
571 | ✗ | FFSWAP(int, s->in.off_left, s->in.off_right); | |
572 | ✗ | FFSWAP(int, s->out.row_left, s->out.row_right); | |
573 | ✗ | FFSWAP(int, s->out.off_lstep, s->out.off_rstep); | |
574 | ✗ | FFSWAP(int, s->out.off_left, s->out.off_right); | |
575 | } | ||
576 | } | ||
577 | |||
578 | 22 | outlink->w = s->out.width; | |
579 | 22 | outlink->h = s->out.height; | |
580 | 22 | outlink->frame_rate = fps; | |
581 | 22 | outlink->time_base = tb; | |
582 | 22 | outlink->sample_aspect_ratio = s->aspect; | |
583 | |||
584 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
|
22 | if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, s->width)) < 0) |
585 | ✗ | return ret; | |
586 | 22 | s->nb_planes = av_pix_fmt_count_planes(outlink->format); | |
587 | 22 | av_image_fill_max_pixsteps(s->pixstep, NULL, desc); | |
588 | 22 | s->pheight[1] = s->pheight[2] = AV_CEIL_RSHIFT(s->height, desc->log2_chroma_h); | |
589 | 22 | s->pheight[0] = s->pheight[3] = s->height; | |
590 | 22 | s->hsub = desc->log2_chroma_w; | |
591 | 22 | s->vsub = desc->log2_chroma_h; | |
592 | |||
593 | 22 | s->dsp.anaglyph = anaglyph; | |
594 | #if ARCH_X86 | ||
595 | 22 | ff_stereo3d_init_x86(&s->dsp); | |
596 | #endif | ||
597 | |||
598 | 22 | return 0; | |
599 | } | ||
600 | |||
601 | typedef struct ThreadData { | ||
602 | AVFrame *ileft, *iright; | ||
603 | AVFrame *out; | ||
604 | } ThreadData; | ||
605 | |||
606 | 630 | static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
607 | { | ||
608 | 630 | Stereo3DContext *s = ctx->priv; | |
609 | 630 | ThreadData *td = arg; | |
610 | 630 | AVFrame *ileft = td->ileft; | |
611 | 630 | AVFrame *iright = td->iright; | |
612 | 630 | AVFrame *out = td->out; | |
613 | 630 | int height = s->out.height; | |
614 | 630 | int start = (height * jobnr ) / nb_jobs; | |
615 | 630 | int end = (height * (jobnr+1)) / nb_jobs; | |
616 | 630 | const int **ana_matrix = s->ana_matrix; | |
617 | |||
618 | 630 | s->dsp.anaglyph(out->data[0] + out->linesize[0] * start, | |
619 | 630 | ileft ->data[0] + s->in_off_left [0] + ileft->linesize[0] * start * s->in.row_step, | |
620 | 630 | iright->data[0] + s->in_off_right[0] + iright->linesize[0] * start * s->in.row_step, | |
621 | 630 | out->linesize[0], | |
622 | 630 | ileft->linesize[0] * s->in.row_step, | |
623 | 630 | iright->linesize[0] * s->in.row_step, | |
624 | s->out.width, end - start, | ||
625 | 630 | ana_matrix[0], ana_matrix[1], ana_matrix[2]); | |
626 | |||
627 | 630 | return 0; | |
628 | } | ||
629 | |||
630 | ✗ | static void interleave_cols_to_any(Stereo3DContext *s, int *out_off, int p, AVFrame *in, AVFrame *out, int d) | |
631 | { | ||
632 | int y, x; | ||
633 | |||
634 | ✗ | for (y = 0; y < s->pheight[p]; y++) { | |
635 | ✗ | const uint8_t *src = (const uint8_t*)in->data[p] + y * in->linesize[p] + d * s->pixstep[p]; | |
636 | ✗ | uint8_t *dst = out->data[p] + out_off[p] + y * out->linesize[p] * s->out.row_step; | |
637 | |||
638 | ✗ | switch (s->pixstep[p]) { | |
639 | ✗ | case 1: | |
640 | ✗ | for (x = 0; x < s->linesize[p]; x++) | |
641 | ✗ | dst[x] = src[x * 2]; | |
642 | ✗ | break; | |
643 | ✗ | case 2: | |
644 | ✗ | for (x = 0; x < s->linesize[p]; x+=2) | |
645 | ✗ | AV_WN16(&dst[x], AV_RN16(&src[x * 2])); | |
646 | ✗ | break; | |
647 | ✗ | case 3: | |
648 | ✗ | for (x = 0; x < s->linesize[p]; x+=3) | |
649 | ✗ | AV_WB24(&dst[x], AV_RB24(&src[x * 2])); | |
650 | ✗ | break; | |
651 | ✗ | case 4: | |
652 | ✗ | for (x = 0; x < s->linesize[p]; x+=4) | |
653 | ✗ | AV_WN32(&dst[x], AV_RN32(&src[x * 2])); | |
654 | ✗ | break; | |
655 | ✗ | case 6: | |
656 | ✗ | for (x = 0; x < s->linesize[p]; x+=6) | |
657 | ✗ | AV_WB48(&dst[x], AV_RB48(&src[x * 2])); | |
658 | ✗ | break; | |
659 | ✗ | case 8: | |
660 | ✗ | for (x = 0; x < s->linesize[p]; x+=8) | |
661 | ✗ | AV_WN64(&dst[x], AV_RN64(&src[x * 2])); | |
662 | ✗ | break; | |
663 | } | ||
664 | } | ||
665 | ✗ | } | |
666 | |||
667 | 119 | static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref) | |
668 | { | ||
669 | 119 | AVFilterContext *ctx = inlink->dst; | |
670 | 119 | Stereo3DContext *s = ctx->priv; | |
671 | 119 | AVFilterLink *outlink = ctx->outputs[0]; | |
672 | 119 | AVFrame *out = NULL, *oleft, *oright, *ileft, *iright; | |
673 | int out_off_left[4], out_off_right[4]; | ||
674 | int i, ret; | ||
675 | |||
676 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
|
119 | if (s->in.format == s->out.format) |
677 | ✗ | return ff_filter_frame(outlink, inpicref); | |
678 | |||
679 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 115 times.
|
119 | switch (s->out.format) { |
680 | 4 | case ALTERNATING_LR: | |
681 | case ALTERNATING_RL: | ||
682 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
|
4 | if (!s->prev) { |
683 | 1 | s->prev = inpicref; | |
684 | 1 | return 0; | |
685 | } | ||
686 | 3 | break; | |
687 | }; | ||
688 | |||
689 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 98 times.
|
118 | switch (s->in.format) { |
690 | 20 | case ALTERNATING_LR: | |
691 | case ALTERNATING_RL: | ||
692 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
|
20 | if (!s->prev) { |
693 | 10 | s->prev = inpicref; | |
694 | 10 | return 0; | |
695 | } | ||
696 | 10 | ileft = s->prev; | |
697 | 10 | iright = inpicref; | |
698 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
|
10 | if (s->in.format == ALTERNATING_RL) |
699 | 5 | FFSWAP(AVFrame *, ileft, iright); | |
700 | 10 | break; | |
701 | 98 | default: | |
702 | 98 | ileft = iright = inpicref; | |
703 | }; | ||
704 | |||
705 |
2/2✓ Branch 0 taken 105 times.
✓ Branch 1 taken 3 times.
|
108 | if ((s->out.format == ALTERNATING_LR || |
706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
|
105 | s->out.format == ALTERNATING_RL) && |
707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | (s->in.format == SIDE_BY_SIDE_LR || |
708 | ✗ | s->in.format == SIDE_BY_SIDE_RL || | |
709 | ✗ | s->in.format == SIDE_BY_SIDE_2_LR || | |
710 | ✗ | s->in.format == SIDE_BY_SIDE_2_RL || | |
711 | ✗ | s->in.format == ABOVE_BELOW_LR || | |
712 | ✗ | s->in.format == ABOVE_BELOW_RL || | |
713 | ✗ | s->in.format == ABOVE_BELOW_2_LR || | |
714 | ✗ | s->in.format == ABOVE_BELOW_2_RL || | |
715 | ✗ | s->in.format == INTERLEAVE_ROWS_LR || | |
716 | ✗ | s->in.format == INTERLEAVE_ROWS_RL)) { | |
717 | 3 | oright = av_frame_clone(s->prev); | |
718 | 3 | oleft = av_frame_clone(s->prev); | |
719 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (!oright || !oleft) { |
720 | ✗ | av_frame_free(&oright); | |
721 | ✗ | av_frame_free(&oleft); | |
722 | ✗ | av_frame_free(&s->prev); | |
723 | ✗ | av_frame_free(&inpicref); | |
724 | ✗ | return AVERROR(ENOMEM); | |
725 | } | ||
726 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 5 times.
|
105 | } else if ((s->out.format == MONO_L || |
727 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 95 times.
|
100 | s->out.format == MONO_R) && |
728 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | (s->in.format == SIDE_BY_SIDE_LR || |
729 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | s->in.format == SIDE_BY_SIDE_RL || |
730 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | s->in.format == SIDE_BY_SIDE_2_LR || |
731 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | s->in.format == SIDE_BY_SIDE_2_RL || |
732 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | s->in.format == ABOVE_BELOW_LR || |
733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | s->in.format == ABOVE_BELOW_RL || |
734 | ✗ | s->in.format == ABOVE_BELOW_2_LR || | |
735 | ✗ | s->in.format == ABOVE_BELOW_2_RL || | |
736 | ✗ | s->in.format == INTERLEAVE_ROWS_LR || | |
737 | ✗ | s->in.format == INTERLEAVE_ROWS_RL)) { | |
738 | 10 | out = oleft = oright = av_frame_clone(inpicref); | |
739 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!out) { |
740 | ✗ | av_frame_free(&s->prev); | |
741 | ✗ | av_frame_free(&inpicref); | |
742 | ✗ | return AVERROR(ENOMEM); | |
743 | } | ||
744 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
95 | } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_LR) || |
745 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
95 | (s->out.format == MONO_R && s->in.format == ALTERNATING_RL)) { |
746 | ✗ | s->prev->pts /= 2; | |
747 | ✗ | ret = ff_filter_frame(outlink, s->prev); | |
748 | ✗ | av_frame_free(&inpicref); | |
749 | ✗ | s->prev = NULL; | |
750 | ✗ | return ret; | |
751 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
95 | } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_RL) || |
752 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
95 | (s->out.format == MONO_R && s->in.format == ALTERNATING_LR)) { |
753 | ✗ | av_frame_free(&s->prev); | |
754 | ✗ | inpicref->pts /= 2; | |
755 | ✗ | return ff_filter_frame(outlink, inpicref); | |
756 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
95 | } else if ((s->out.format == ALTERNATING_LR && s->in.format == ALTERNATING_RL) || |
757 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
95 | (s->out.format == ALTERNATING_RL && s->in.format == ALTERNATING_LR)) { |
758 | ✗ | FFSWAP(int64_t, s->prev->pts, inpicref->pts); | |
759 | ✗ | ff_filter_frame(outlink, inpicref); | |
760 | ✗ | ret = ff_filter_frame(outlink, s->prev); | |
761 | ✗ | s->prev = NULL; | |
762 | ✗ | return ret; | |
763 | } else { | ||
764 | 95 | out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
765 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
|
95 | if (!out) { |
766 | ✗ | av_frame_free(&s->prev); | |
767 | ✗ | av_frame_free(&inpicref); | |
768 | ✗ | return AVERROR(ENOMEM); | |
769 | } | ||
770 | 95 | av_frame_copy_props(out, inpicref); | |
771 | |||
772 |
1/2✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
|
95 | if (s->out.format == ALTERNATING_LR || |
773 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 95 times.
|
95 | s->out.format == ALTERNATING_RL) { |
774 | ✗ | oright = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
775 | ✗ | if (!oright) { | |
776 | ✗ | av_frame_free(&oleft); | |
777 | ✗ | av_frame_free(&s->prev); | |
778 | ✗ | av_frame_free(&inpicref); | |
779 | ✗ | return AVERROR(ENOMEM); | |
780 | } | ||
781 | ✗ | av_frame_copy_props(oright, s->prev); | |
782 | } | ||
783 | } | ||
784 | |||
785 |
2/2✓ Branch 0 taken 432 times.
✓ Branch 1 taken 108 times.
|
540 | for (i = 0; i < 4; i++) { |
786 |
4/4✓ Branch 0 taken 324 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 216 times.
|
432 | int hsub = i == 1 || i == 2 ? s->hsub : 0; |
787 |
4/4✓ Branch 0 taken 324 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 108 times.
✓ Branch 3 taken 216 times.
|
432 | int vsub = i == 1 || i == 2 ? s->vsub : 0; |
788 | 432 | 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); | |
789 | 432 | 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); | |
790 | 432 | 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); | |
791 | 432 | 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); | |
792 | } | ||
793 | |||
794 |
5/9✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 70 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
|
108 | switch (s->out.format) { |
795 | 3 | case ALTERNATING_LR: | |
796 | case ALTERNATING_RL: | ||
797 |
1/3✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | switch (s->in.format) { |
798 | ✗ | case INTERLEAVE_ROWS_LR: | |
799 | case INTERLEAVE_ROWS_RL: | ||
800 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
801 | ✗ | oleft->linesize[i] *= 2; | |
802 | ✗ | oright->linesize[i] *= 2; | |
803 | } | ||
804 | case ABOVE_BELOW_LR: | ||
805 | case ABOVE_BELOW_RL: | ||
806 | case ABOVE_BELOW_2_LR: | ||
807 | case ABOVE_BELOW_2_RL: | ||
808 | case SIDE_BY_SIDE_LR: | ||
809 | case SIDE_BY_SIDE_RL: | ||
810 | case SIDE_BY_SIDE_2_LR: | ||
811 | case SIDE_BY_SIDE_2_RL: | ||
812 | 3 | oleft->width = outlink->w; | |
813 | 3 | oright->width = outlink->w; | |
814 | 3 | oleft->height = outlink->h; | |
815 | 3 | oright->height = outlink->h; | |
816 | |||
817 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | for (i = 0; i < s->nb_planes; i++) { |
818 | 9 | oleft->data[i] += s->in_off_left[i]; | |
819 | 9 | oright->data[i] += s->in_off_right[i]; | |
820 | } | ||
821 | 3 | break; | |
822 | ✗ | default: | |
823 | ✗ | goto copy; | |
824 | break; | ||
825 | } | ||
826 | 3 | break; | |
827 | ✗ | case HDMI: | |
828 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
829 | ✗ | int j, h = s->height >> ((i == 1 || i == 2) ? s->vsub : 0); | |
830 | ✗ | int b = (s->blanks) >> ((i == 1 || i == 2) ? s->vsub : 0); | |
831 | |||
832 | ✗ | for (j = h; j < h + b; j++) | |
833 | ✗ | memset(oleft->data[i] + j * s->linesize[i], 0, s->linesize[i]); | |
834 | } | ||
835 | case SIDE_BY_SIDE_LR: | ||
836 | case SIDE_BY_SIDE_RL: | ||
837 | case SIDE_BY_SIDE_2_LR: | ||
838 | case SIDE_BY_SIDE_2_RL: | ||
839 | case ABOVE_BELOW_LR: | ||
840 | case ABOVE_BELOW_RL: | ||
841 | case ABOVE_BELOW_2_LR: | ||
842 | case ABOVE_BELOW_2_RL: | ||
843 | case INTERLEAVE_ROWS_LR: | ||
844 | case INTERLEAVE_ROWS_RL: | ||
845 | ✗ | copy: | |
846 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
25 | if (s->in.format == INTERLEAVE_COLS_LR || |
847 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | s->in.format == INTERLEAVE_COLS_RL) { |
848 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
849 | ✗ | int d = (s->in.format & 1) != (s->out.format & 1); | |
850 | |||
851 | ✗ | interleave_cols_to_any(s, out_off_left, i, ileft, oleft, d); | |
852 | ✗ | interleave_cols_to_any(s, out_off_right, i, iright, oright, !d); | |
853 | } | ||
854 | } else { | ||
855 |
2/2✓ Branch 0 taken 75 times.
✓ Branch 1 taken 25 times.
|
100 | for (i = 0; i < s->nb_planes; i++) { |
856 | 75 | av_image_copy_plane(oleft->data[i] + out_off_left[i], | |
857 | 75 | oleft->linesize[i] * s->out.row_step, | |
858 | 75 | ileft->data[i] + s->in_off_left[i], | |
859 | 75 | ileft->linesize[i] * s->in.row_step, | |
860 | s->linesize[i], s->pheight[i]); | ||
861 | 75 | av_image_copy_plane(oright->data[i] + out_off_right[i], | |
862 | 75 | oright->linesize[i] * s->out.row_step, | |
863 | 75 | iright->data[i] + s->in_off_right[i], | |
864 | 75 | iright->linesize[i] * s->in.row_step, | |
865 | s->linesize[i], s->pheight[i]); | ||
866 | } | ||
867 | } | ||
868 | 25 | break; | |
869 | 5 | case MONO_L: | |
870 | 5 | iright = ileft; | |
871 | 10 | case MONO_R: | |
872 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
10 | switch (s->in.format) { |
873 | ✗ | case INTERLEAVE_ROWS_LR: | |
874 | case INTERLEAVE_ROWS_RL: | ||
875 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
876 | ✗ | out->linesize[i] *= 2; | |
877 | } | ||
878 | case ABOVE_BELOW_LR: | ||
879 | case ABOVE_BELOW_RL: | ||
880 | case ABOVE_BELOW_2_LR: | ||
881 | case ABOVE_BELOW_2_RL: | ||
882 | case SIDE_BY_SIDE_LR: | ||
883 | case SIDE_BY_SIDE_RL: | ||
884 | case SIDE_BY_SIDE_2_LR: | ||
885 | case SIDE_BY_SIDE_2_RL: | ||
886 | 10 | out->width = outlink->w; | |
887 | 10 | out->height = outlink->h; | |
888 | |||
889 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 10 times.
|
40 | for (i = 0; i < s->nb_planes; i++) { |
890 | 30 | out->data[i] += s->in_off_left[i]; | |
891 | } | ||
892 | 10 | break; | |
893 | ✗ | case INTERLEAVE_COLS_LR: | |
894 | case INTERLEAVE_COLS_RL: | ||
895 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
896 | ✗ | const int d = (s->in.format & 1) != (s->out.format & 1); | |
897 | |||
898 | ✗ | interleave_cols_to_any(s, out_off_right, i, iright, out, d); | |
899 | } | ||
900 | ✗ | break; | |
901 | ✗ | default: | |
902 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
903 | ✗ | av_image_copy_plane(out->data[i], out->linesize[i], | |
904 | ✗ | iright->data[i] + s->in_off_left[i], | |
905 | ✗ | iright->linesize[i] * s->in.row_step, | |
906 | s->linesize[i], s->pheight[i]); | ||
907 | } | ||
908 | ✗ | break; | |
909 | } | ||
910 | 10 | break; | |
911 | 70 | case ANAGLYPH_RB_GRAY: | |
912 | case ANAGLYPH_RG_GRAY: | ||
913 | case ANAGLYPH_RC_GRAY: | ||
914 | case ANAGLYPH_RC_HALF: | ||
915 | case ANAGLYPH_RC_COLOR: | ||
916 | case ANAGLYPH_RC_DUBOIS: | ||
917 | case ANAGLYPH_GM_GRAY: | ||
918 | case ANAGLYPH_GM_HALF: | ||
919 | case ANAGLYPH_GM_COLOR: | ||
920 | case ANAGLYPH_GM_DUBOIS: | ||
921 | case ANAGLYPH_YB_GRAY: | ||
922 | case ANAGLYPH_YB_HALF: | ||
923 | case ANAGLYPH_YB_COLOR: | ||
924 | case ANAGLYPH_YB_DUBOIS: { | ||
925 |
1/2✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
|
70 | if (s->in.format == INTERLEAVE_COLS_LR || |
926 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 | s->in.format == INTERLEAVE_COLS_RL) { |
927 | ✗ | const int d = (s->in.format & 1); | |
928 | |||
929 | ✗ | anaglyph_ic(out->data[0], | |
930 | ✗ | ileft ->data[0] + s->in_off_left [0] + d * 3, | |
931 | ✗ | iright->data[0] + s->in_off_right[0] + (!d) * 3, | |
932 | ✗ | out->linesize[0], | |
933 | ✗ | ileft->linesize[0] * s->in.row_step, | |
934 | ✗ | iright->linesize[0] * s->in.row_step, | |
935 | s->out.width, s->out.height, | ||
936 | s->ana_matrix[0], s->ana_matrix[1], s->ana_matrix[2]); | ||
937 | } else { | ||
938 | ThreadData td; | ||
939 | |||
940 | 70 | td.ileft = ileft; td.iright = iright; td.out = out; | |
941 | 70 | ff_filter_execute(ctx, filter_slice, &td, NULL, | |
942 |
1/2✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
|
70 | FFMIN(s->out.height, ff_filter_get_nb_threads(ctx))); |
943 | } | ||
944 | 70 | break; | |
945 | } | ||
946 | ✗ | case CHECKERBOARD_RL: | |
947 | case CHECKERBOARD_LR: | ||
948 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
949 | int x, y; | ||
950 | |||
951 | ✗ | for (y = 0; y < s->pheight[i]; y++) { | |
952 | ✗ | uint8_t *dst = out->data[i] + out->linesize[i] * y; | |
953 | ✗ | const int d1 = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) && (s->in.format & 1) != (s->out.format & 1); | |
954 | ✗ | const int d2 = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) ? !d1 : 0; | |
955 | ✗ | const int m = 1 + (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL); | |
956 | ✗ | uint8_t *left = ileft->data[i] + ileft->linesize[i] * y + s->in_off_left[i] + d1 * s->pixstep[i]; | |
957 | ✗ | uint8_t *right = iright->data[i] + iright->linesize[i] * y + s->in_off_right[i] + d2 * s->pixstep[i]; | |
958 | int p, b; | ||
959 | |||
960 | ✗ | if (s->out.format == CHECKERBOARD_RL && s->in.format != INTERLEAVE_COLS_LR && s->in.format != INTERLEAVE_COLS_RL) | |
961 | ✗ | FFSWAP(uint8_t*, left, right); | |
962 | ✗ | switch (s->pixstep[i]) { | |
963 | ✗ | case 1: | |
964 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=2, p++, b+=2) { | |
965 | ✗ | dst[x ] = (b&1) == (y&1) ? left[p*m] : right[p*m]; | |
966 | ✗ | dst[x+1] = (b&1) != (y&1) ? left[p*m] : right[p*m]; | |
967 | } | ||
968 | ✗ | break; | |
969 | ✗ | case 2: | |
970 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=4, p+=2, b+=2) { | |
971 | ✗ | AV_WN16(&dst[x ], (b&1) == (y&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m])); | |
972 | ✗ | AV_WN16(&dst[x+2], (b&1) != (y&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m])); | |
973 | } | ||
974 | ✗ | break; | |
975 | ✗ | case 3: | |
976 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=6, p+=3, b+=2) { | |
977 | ✗ | AV_WB24(&dst[x ], (b&1) == (y&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m])); | |
978 | ✗ | AV_WB24(&dst[x+3], (b&1) != (y&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m])); | |
979 | } | ||
980 | ✗ | break; | |
981 | ✗ | case 4: | |
982 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=8, p+=4, b+=2) { | |
983 | ✗ | AV_WN32(&dst[x ], (b&1) == (y&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m])); | |
984 | ✗ | AV_WN32(&dst[x+4], (b&1) != (y&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m])); | |
985 | } | ||
986 | ✗ | break; | |
987 | ✗ | case 6: | |
988 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=12, p+=6, b+=2) { | |
989 | ✗ | AV_WB48(&dst[x ], (b&1) == (y&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m])); | |
990 | ✗ | AV_WB48(&dst[x+6], (b&1) != (y&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m])); | |
991 | } | ||
992 | ✗ | break; | |
993 | ✗ | case 8: | |
994 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=16, p+=8, b+=2) { | |
995 | ✗ | AV_WN64(&dst[x ], (b&1) == (y&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m])); | |
996 | ✗ | AV_WN64(&dst[x+8], (b&1) != (y&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m])); | |
997 | } | ||
998 | ✗ | break; | |
999 | } | ||
1000 | } | ||
1001 | } | ||
1002 | ✗ | break; | |
1003 | ✗ | case INTERLEAVE_COLS_LR: | |
1004 | case INTERLEAVE_COLS_RL: | ||
1005 | ✗ | for (i = 0; i < s->nb_planes; i++) { | |
1006 | ✗ | const int d = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL); | |
1007 | ✗ | const int m = 1 + d; | |
1008 | int x, y; | ||
1009 | |||
1010 | ✗ | for (y = 0; y < s->pheight[i]; y++) { | |
1011 | ✗ | uint8_t *dst = out->data[i] + out->linesize[i] * y; | |
1012 | ✗ | uint8_t *left = ileft->data[i] + ileft->linesize[i] * y * s->in.row_step + s->in_off_left[i] + d * s->pixstep[i]; | |
1013 | ✗ | uint8_t *right = iright->data[i] + iright->linesize[i] * y * s->in.row_step + s->in_off_right[i]; | |
1014 | int p, b; | ||
1015 | |||
1016 | ✗ | if (s->out.format == INTERLEAVE_COLS_LR) | |
1017 | ✗ | FFSWAP(uint8_t*, left, right); | |
1018 | |||
1019 | ✗ | switch (s->pixstep[i]) { | |
1020 | ✗ | case 1: | |
1021 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=2, p++, b+=2) { | |
1022 | ✗ | dst[x ] = b&1 ? left[p*m] : right[p*m]; | |
1023 | ✗ | dst[x+1] = !(b&1) ? left[p*m] : right[p*m]; | |
1024 | } | ||
1025 | ✗ | break; | |
1026 | ✗ | case 2: | |
1027 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=4, p+=2, b+=2) { | |
1028 | ✗ | AV_WN16(&dst[x ], b&1 ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m])); | |
1029 | ✗ | AV_WN16(&dst[x+2], !(b&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m])); | |
1030 | } | ||
1031 | ✗ | break; | |
1032 | ✗ | case 3: | |
1033 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=6, p+=3, b+=2) { | |
1034 | ✗ | AV_WB24(&dst[x ], b&1 ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m])); | |
1035 | ✗ | AV_WB24(&dst[x+3], !(b&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m])); | |
1036 | } | ||
1037 | ✗ | break; | |
1038 | ✗ | case 4: | |
1039 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=8, p+=4, b+=2) { | |
1040 | ✗ | AV_WN32(&dst[x ], b&1 ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m])); | |
1041 | ✗ | AV_WN32(&dst[x+4], !(b&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m])); | |
1042 | } | ||
1043 | ✗ | break; | |
1044 | ✗ | case 6: | |
1045 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=12, p+=6, b+=2) { | |
1046 | ✗ | AV_WB48(&dst[x ], b&1 ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m])); | |
1047 | ✗ | AV_WB48(&dst[x+6], !(b&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m])); | |
1048 | } | ||
1049 | ✗ | break; | |
1050 | ✗ | case 8: | |
1051 | ✗ | for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=16, p+=8, b+=2) { | |
1052 | ✗ | AV_WN64(&dst[x ], b&1 ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m])); | |
1053 | ✗ | AV_WN64(&dst[x+8], !(b&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m])); | |
1054 | } | ||
1055 | ✗ | break; | |
1056 | } | ||
1057 | } | ||
1058 | } | ||
1059 | ✗ | break; | |
1060 | ✗ | default: | |
1061 | ✗ | av_assert0(0); | |
1062 | } | ||
1063 | |||
1064 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 105 times.
|
108 | if (oright != oleft) { |
1065 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (s->out.format == ALTERNATING_LR) |
1066 | 3 | FFSWAP(AVFrame *, oleft, oright); | |
1067 | 3 | oright->pts = s->prev->pts * 2; | |
1068 | 3 | ff_filter_frame(outlink, oright); | |
1069 | 3 | out = oleft; | |
1070 | 3 | oleft->pts = s->prev->pts + inpicref->pts; | |
1071 | 3 | av_frame_free(&s->prev); | |
1072 | 3 | s->prev = inpicref; | |
1073 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 5 times.
|
105 | } else if (s->in.format == ALTERNATING_LR || |
1074 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 95 times.
|
100 | s->in.format == ALTERNATING_RL) { |
1075 | 10 | out->pts = s->prev->pts / 2; | |
1076 | 10 | av_frame_free(&s->prev); | |
1077 | 10 | av_frame_free(&inpicref); | |
1078 | } else { | ||
1079 | 95 | av_frame_free(&s->prev); | |
1080 | 95 | av_frame_free(&inpicref); | |
1081 | } | ||
1082 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
|
108 | av_assert0(out); |
1083 | 108 | out->sample_aspect_ratio = s->aspect; | |
1084 | 108 | return ff_filter_frame(outlink, out); | |
1085 | } | ||
1086 | |||
1087 | 44 | static av_cold void uninit(AVFilterContext *ctx) | |
1088 | { | ||
1089 | 44 | Stereo3DContext *s = ctx->priv; | |
1090 | |||
1091 | 44 | av_frame_free(&s->prev); | |
1092 | 44 | } | |
1093 | |||
1094 | static const AVFilterPad stereo3d_inputs[] = { | ||
1095 | { | ||
1096 | .name = "default", | ||
1097 | .type = AVMEDIA_TYPE_VIDEO, | ||
1098 | .filter_frame = filter_frame, | ||
1099 | }, | ||
1100 | }; | ||
1101 | |||
1102 | static const AVFilterPad stereo3d_outputs[] = { | ||
1103 | { | ||
1104 | .name = "default", | ||
1105 | .type = AVMEDIA_TYPE_VIDEO, | ||
1106 | .config_props = config_output, | ||
1107 | }, | ||
1108 | }; | ||
1109 | |||
1110 | const AVFilter ff_vf_stereo3d = { | ||
1111 | .name = "stereo3d", | ||
1112 | .description = NULL_IF_CONFIG_SMALL("Convert video stereoscopic 3D view."), | ||
1113 | .priv_size = sizeof(Stereo3DContext), | ||
1114 | .uninit = uninit, | ||
1115 | FILTER_INPUTS(stereo3d_inputs), | ||
1116 | FILTER_OUTPUTS(stereo3d_outputs), | ||
1117 | FILTER_QUERY_FUNC(query_formats), | ||
1118 | .priv_class = &stereo3d_class, | ||
1119 | .flags = AVFILTER_FLAG_SLICE_THREADS, | ||
1120 | }; | ||
1121 |