You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1127 lines
46KB

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