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.

1126 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. case INTERLEAVE_COLS_LR:
  533. case INTERLEAVE_COLS_RL:
  534. s->out.width = s->width * 2;
  535. break;
  536. default:
  537. av_log(ctx, AV_LOG_ERROR, "output format %d is not supported\n", s->out.format);
  538. return AVERROR(EINVAL);
  539. }
  540. if (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) {
  541. if ((s->in.format & 1) != (s->out.format & 1)) {
  542. FFSWAP(int, s->in.row_left, s->in.row_right);
  543. FFSWAP(int, s->in.off_lstep, s->in.off_rstep);
  544. FFSWAP(int, s->in.off_left, s->in.off_right);
  545. FFSWAP(int, s->out.row_left, s->out.row_right);
  546. FFSWAP(int, s->out.off_lstep, s->out.off_rstep);
  547. FFSWAP(int, s->out.off_left, s->out.off_right);
  548. }
  549. }
  550. outlink->w = s->out.width;
  551. outlink->h = s->out.height;
  552. outlink->frame_rate = fps;
  553. outlink->time_base = tb;
  554. outlink->sample_aspect_ratio = s->aspect;
  555. if ((ret = av_image_fill_linesizes(s->linesize, outlink->format, s->width)) < 0)
  556. return ret;
  557. s->nb_planes = av_pix_fmt_count_planes(outlink->format);
  558. av_image_fill_max_pixsteps(s->pixstep, NULL, desc);
  559. s->pheight[1] = s->pheight[2] = AV_CEIL_RSHIFT(s->height, desc->log2_chroma_h);
  560. s->pheight[0] = s->pheight[3] = s->height;
  561. s->hsub = desc->log2_chroma_w;
  562. s->vsub = desc->log2_chroma_h;
  563. s->dsp.anaglyph = anaglyph;
  564. if (ARCH_X86)
  565. ff_stereo3d_init_x86(&s->dsp);
  566. return 0;
  567. }
  568. typedef struct ThreadData {
  569. AVFrame *ileft, *iright;
  570. AVFrame *out;
  571. } ThreadData;
  572. static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
  573. {
  574. Stereo3DContext *s = ctx->priv;
  575. ThreadData *td = arg;
  576. AVFrame *ileft = td->ileft;
  577. AVFrame *iright = td->iright;
  578. AVFrame *out = td->out;
  579. int height = s->out.height;
  580. int start = (height * jobnr ) / nb_jobs;
  581. int end = (height * (jobnr+1)) / nb_jobs;
  582. const int **ana_matrix = s->ana_matrix;
  583. s->dsp.anaglyph(out->data[0] + out->linesize[0] * start,
  584. ileft ->data[0] + s->in_off_left [0] + ileft->linesize[0] * start * s->in.row_step,
  585. iright->data[0] + s->in_off_right[0] + iright->linesize[0] * start * s->in.row_step,
  586. out->linesize[0],
  587. ileft->linesize[0] * s->in.row_step,
  588. iright->linesize[0] * s->in.row_step,
  589. s->out.width, end - start,
  590. ana_matrix[0], ana_matrix[1], ana_matrix[2]);
  591. return 0;
  592. }
  593. static void interleave_cols_to_any(Stereo3DContext *s, int *out_off, int p, AVFrame *in, AVFrame *out, int d)
  594. {
  595. int y, x;
  596. for (y = 0; y < s->pheight[p]; y++) {
  597. const uint8_t *src = (const uint8_t*)in->data[p] + y * in->linesize[p] + d * s->pixstep[p];
  598. uint8_t *dst = out->data[p] + out_off[p] + y * out->linesize[p] * s->out.row_step;
  599. switch (s->pixstep[p]) {
  600. case 1:
  601. for (x = 0; x < s->linesize[p]; x++)
  602. dst[x] = src[x * 2];
  603. break;
  604. case 2:
  605. for (x = 0; x < s->linesize[p]; x+=2)
  606. AV_WN16(&dst[x], AV_RN16(&src[x * 2]));
  607. break;
  608. case 3:
  609. for (x = 0; x < s->linesize[p]; x+=3)
  610. AV_WB24(&dst[x], AV_RB24(&src[x * 2]));
  611. break;
  612. case 4:
  613. for (x = 0; x < s->linesize[p]; x+=4)
  614. AV_WN32(&dst[x], AV_RN32(&src[x * 2]));
  615. break;
  616. case 6:
  617. for (x = 0; x < s->linesize[p]; x+=6)
  618. AV_WB48(&dst[x], AV_RB48(&src[x * 2]));
  619. break;
  620. case 8:
  621. for (x = 0; x < s->linesize[p]; x+=8)
  622. AV_WN64(&dst[x], AV_RN64(&src[x * 2]));
  623. break;
  624. }
  625. }
  626. }
  627. static int filter_frame(AVFilterLink *inlink, AVFrame *inpicref)
  628. {
  629. AVFilterContext *ctx = inlink->dst;
  630. Stereo3DContext *s = ctx->priv;
  631. AVFilterLink *outlink = ctx->outputs[0];
  632. AVFrame *out = NULL, *oleft, *oright, *ileft, *iright;
  633. int out_off_left[4], out_off_right[4];
  634. int i, ret;
  635. if (s->in.format == s->out.format)
  636. return ff_filter_frame(outlink, inpicref);
  637. switch (s->out.format) {
  638. case ALTERNATING_LR:
  639. case ALTERNATING_RL:
  640. if (!s->prev) {
  641. s->prev = inpicref;
  642. return 0;
  643. }
  644. break;
  645. };
  646. switch (s->in.format) {
  647. case ALTERNATING_LR:
  648. case ALTERNATING_RL:
  649. if (!s->prev) {
  650. s->prev = inpicref;
  651. return 0;
  652. }
  653. ileft = s->prev;
  654. iright = inpicref;
  655. if (s->in.format == ALTERNATING_RL)
  656. FFSWAP(AVFrame *, ileft, iright);
  657. break;
  658. default:
  659. ileft = iright = inpicref;
  660. };
  661. if ((s->out.format == ALTERNATING_LR ||
  662. s->out.format == ALTERNATING_RL) &&
  663. (s->in.format == SIDE_BY_SIDE_LR ||
  664. s->in.format == SIDE_BY_SIDE_RL ||
  665. s->in.format == SIDE_BY_SIDE_2_LR ||
  666. s->in.format == SIDE_BY_SIDE_2_RL ||
  667. s->in.format == ABOVE_BELOW_LR ||
  668. s->in.format == ABOVE_BELOW_RL ||
  669. s->in.format == ABOVE_BELOW_2_LR ||
  670. s->in.format == ABOVE_BELOW_2_RL ||
  671. s->in.format == INTERLEAVE_ROWS_LR ||
  672. s->in.format == INTERLEAVE_ROWS_RL)) {
  673. oright = av_frame_clone(s->prev);
  674. oleft = av_frame_clone(s->prev);
  675. if (!oright || !oleft) {
  676. av_frame_free(&oright);
  677. av_frame_free(&oleft);
  678. av_frame_free(&s->prev);
  679. av_frame_free(&inpicref);
  680. return AVERROR(ENOMEM);
  681. }
  682. } else if ((s->out.format == MONO_L ||
  683. s->out.format == MONO_R) &&
  684. (s->in.format == SIDE_BY_SIDE_LR ||
  685. s->in.format == SIDE_BY_SIDE_RL ||
  686. s->in.format == SIDE_BY_SIDE_2_LR ||
  687. s->in.format == SIDE_BY_SIDE_2_RL ||
  688. s->in.format == ABOVE_BELOW_LR ||
  689. s->in.format == ABOVE_BELOW_RL ||
  690. s->in.format == ABOVE_BELOW_2_LR ||
  691. s->in.format == ABOVE_BELOW_2_RL ||
  692. s->in.format == INTERLEAVE_ROWS_LR ||
  693. s->in.format == INTERLEAVE_ROWS_RL)) {
  694. out = oleft = oright = av_frame_clone(inpicref);
  695. if (!out) {
  696. av_frame_free(&s->prev);
  697. av_frame_free(&inpicref);
  698. return AVERROR(ENOMEM);
  699. }
  700. } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_LR) ||
  701. (s->out.format == MONO_R && s->in.format == ALTERNATING_RL)) {
  702. s->prev->pts /= 2;
  703. ret = ff_filter_frame(outlink, s->prev);
  704. av_frame_free(&inpicref);
  705. s->prev = NULL;
  706. return ret;
  707. } else if ((s->out.format == MONO_L && s->in.format == ALTERNATING_RL) ||
  708. (s->out.format == MONO_R && s->in.format == ALTERNATING_LR)) {
  709. av_frame_free(&s->prev);
  710. inpicref->pts /= 2;
  711. return ff_filter_frame(outlink, inpicref);
  712. } else if ((s->out.format == ALTERNATING_LR && s->in.format == ALTERNATING_RL) ||
  713. (s->out.format == ALTERNATING_RL && s->in.format == ALTERNATING_LR)) {
  714. FFSWAP(int64_t, s->prev->pts, inpicref->pts);
  715. ff_filter_frame(outlink, inpicref);
  716. ret = ff_filter_frame(outlink, s->prev);
  717. s->prev = NULL;
  718. return ret;
  719. } else {
  720. out = oleft = oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  721. if (!out) {
  722. av_frame_free(&s->prev);
  723. av_frame_free(&inpicref);
  724. return AVERROR(ENOMEM);
  725. }
  726. av_frame_copy_props(out, inpicref);
  727. if (s->out.format == ALTERNATING_LR ||
  728. s->out.format == ALTERNATING_RL) {
  729. oright = ff_get_video_buffer(outlink, outlink->w, outlink->h);
  730. if (!oright) {
  731. av_frame_free(&oleft);
  732. av_frame_free(&s->prev);
  733. av_frame_free(&inpicref);
  734. return AVERROR(ENOMEM);
  735. }
  736. av_frame_copy_props(oright, s->prev);
  737. }
  738. }
  739. for (i = 0; i < 4; i++) {
  740. int hsub = i == 1 || i == 2 ? s->hsub : 0;
  741. int vsub = i == 1 || i == 2 ? s->vsub : 0;
  742. 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);
  743. 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);
  744. 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);
  745. 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);
  746. }
  747. switch (s->out.format) {
  748. case ALTERNATING_LR:
  749. case ALTERNATING_RL:
  750. switch (s->in.format) {
  751. case INTERLEAVE_ROWS_LR:
  752. case INTERLEAVE_ROWS_RL:
  753. for (i = 0; i < s->nb_planes; i++) {
  754. oleft->linesize[i] *= 2;
  755. oright->linesize[i] *= 2;
  756. }
  757. case ABOVE_BELOW_LR:
  758. case ABOVE_BELOW_RL:
  759. case ABOVE_BELOW_2_LR:
  760. case ABOVE_BELOW_2_RL:
  761. case SIDE_BY_SIDE_LR:
  762. case SIDE_BY_SIDE_RL:
  763. case SIDE_BY_SIDE_2_LR:
  764. case SIDE_BY_SIDE_2_RL:
  765. oleft->width = outlink->w;
  766. oright->width = outlink->w;
  767. oleft->height = outlink->h;
  768. oright->height = outlink->h;
  769. for (i = 0; i < s->nb_planes; i++) {
  770. oleft->data[i] += s->in_off_left[i];
  771. oright->data[i] += s->in_off_right[i];
  772. }
  773. break;
  774. default:
  775. goto copy;
  776. break;
  777. }
  778. break;
  779. case HDMI:
  780. for (i = 0; i < s->nb_planes; i++) {
  781. int j, h = s->height >> ((i == 1 || i == 2) ? s->vsub : 0);
  782. int b = (s->blanks) >> ((i == 1 || i == 2) ? s->vsub : 0);
  783. for (j = h; j < h + b; j++)
  784. memset(oleft->data[i] + j * s->linesize[i], 0, s->linesize[i]);
  785. }
  786. case SIDE_BY_SIDE_LR:
  787. case SIDE_BY_SIDE_RL:
  788. case SIDE_BY_SIDE_2_LR:
  789. case SIDE_BY_SIDE_2_RL:
  790. case ABOVE_BELOW_LR:
  791. case ABOVE_BELOW_RL:
  792. case ABOVE_BELOW_2_LR:
  793. case ABOVE_BELOW_2_RL:
  794. case INTERLEAVE_ROWS_LR:
  795. case INTERLEAVE_ROWS_RL:
  796. copy:
  797. if (s->in.format == INTERLEAVE_COLS_LR ||
  798. s->in.format == INTERLEAVE_COLS_RL) {
  799. for (i = 0; i < s->nb_planes; i++) {
  800. int d = (s->in.format & 1) != (s->out.format & 1);
  801. interleave_cols_to_any(s, out_off_left, i, ileft, oleft, d);
  802. interleave_cols_to_any(s, out_off_right, i, iright, oright, !d);
  803. }
  804. } else {
  805. for (i = 0; i < s->nb_planes; i++) {
  806. av_image_copy_plane(oleft->data[i] + out_off_left[i],
  807. oleft->linesize[i] * s->out.row_step,
  808. ileft->data[i] + s->in_off_left[i],
  809. ileft->linesize[i] * s->in.row_step,
  810. s->linesize[i], s->pheight[i]);
  811. av_image_copy_plane(oright->data[i] + out_off_right[i],
  812. oright->linesize[i] * s->out.row_step,
  813. iright->data[i] + s->in_off_right[i],
  814. iright->linesize[i] * s->in.row_step,
  815. s->linesize[i], s->pheight[i]);
  816. }
  817. }
  818. break;
  819. case MONO_L:
  820. iright = ileft;
  821. case MONO_R:
  822. switch (s->in.format) {
  823. case INTERLEAVE_ROWS_LR:
  824. case INTERLEAVE_ROWS_RL:
  825. for (i = 0; i < s->nb_planes; i++) {
  826. out->linesize[i] *= 2;
  827. }
  828. case ABOVE_BELOW_LR:
  829. case ABOVE_BELOW_RL:
  830. case ABOVE_BELOW_2_LR:
  831. case ABOVE_BELOW_2_RL:
  832. case SIDE_BY_SIDE_LR:
  833. case SIDE_BY_SIDE_RL:
  834. case SIDE_BY_SIDE_2_LR:
  835. case SIDE_BY_SIDE_2_RL:
  836. out->width = outlink->w;
  837. out->height = outlink->h;
  838. for (i = 0; i < s->nb_planes; i++) {
  839. out->data[i] += s->in_off_left[i];
  840. }
  841. break;
  842. case INTERLEAVE_COLS_LR:
  843. case INTERLEAVE_COLS_RL:
  844. for (i = 0; i < s->nb_planes; i++) {
  845. const int d = (s->in.format & 1) != (s->out.format & 1);
  846. interleave_cols_to_any(s, out_off_right, i, iright, out, d);
  847. }
  848. break;
  849. default:
  850. for (i = 0; i < s->nb_planes; i++) {
  851. av_image_copy_plane(out->data[i], out->linesize[i],
  852. iright->data[i] + s->in_off_left[i],
  853. iright->linesize[i] * s->in.row_step,
  854. s->linesize[i], s->pheight[i]);
  855. }
  856. break;
  857. }
  858. break;
  859. case ANAGLYPH_RB_GRAY:
  860. case ANAGLYPH_RG_GRAY:
  861. case ANAGLYPH_RC_GRAY:
  862. case ANAGLYPH_RC_HALF:
  863. case ANAGLYPH_RC_COLOR:
  864. case ANAGLYPH_RC_DUBOIS:
  865. case ANAGLYPH_GM_GRAY:
  866. case ANAGLYPH_GM_HALF:
  867. case ANAGLYPH_GM_COLOR:
  868. case ANAGLYPH_GM_DUBOIS:
  869. case ANAGLYPH_YB_GRAY:
  870. case ANAGLYPH_YB_HALF:
  871. case ANAGLYPH_YB_COLOR:
  872. case ANAGLYPH_YB_DUBOIS: {
  873. if (s->in.format == INTERLEAVE_COLS_LR ||
  874. s->in.format == INTERLEAVE_COLS_RL) {
  875. const int d = (s->in.format & 1);
  876. anaglyph_ic(out->data[0],
  877. ileft ->data[0] + s->in_off_left [0] + d * 3,
  878. iright->data[0] + s->in_off_right[0] + (!d) * 3,
  879. out->linesize[0],
  880. ileft->linesize[0] * s->in.row_step,
  881. iright->linesize[0] * s->in.row_step,
  882. s->out.width, s->out.height,
  883. s->ana_matrix[0], s->ana_matrix[1], s->ana_matrix[2]);
  884. } else {
  885. ThreadData td;
  886. td.ileft = ileft; td.iright = iright; td.out = out;
  887. ctx->internal->execute(ctx, filter_slice, &td, NULL,
  888. FFMIN(s->out.height, ff_filter_get_nb_threads(ctx)));
  889. }
  890. break;
  891. }
  892. case CHECKERBOARD_RL:
  893. case CHECKERBOARD_LR:
  894. for (i = 0; i < s->nb_planes; i++) {
  895. int x, y;
  896. for (y = 0; y < s->pheight[i]; y++) {
  897. uint8_t *dst = out->data[i] + out->linesize[i] * y;
  898. const int d1 = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) && (s->in.format & 1) != (s->out.format & 1);
  899. const int d2 = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL) ? !d1 : 0;
  900. const int m = 1 + (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL);
  901. uint8_t *left = ileft->data[i] + ileft->linesize[i] * y + s->in_off_left[i] + d1 * s->pixstep[i];
  902. uint8_t *right = iright->data[i] + iright->linesize[i] * y + s->in_off_right[i] + d2 * s->pixstep[i];
  903. int p, b;
  904. if (s->out.format == CHECKERBOARD_RL && s->in.format != INTERLEAVE_COLS_LR && s->in.format != INTERLEAVE_COLS_RL)
  905. FFSWAP(uint8_t*, left, right);
  906. switch (s->pixstep[i]) {
  907. case 1:
  908. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=2, p++, b+=2) {
  909. dst[x ] = (b&1) == (y&1) ? left[p*m] : right[p*m];
  910. dst[x+1] = (b&1) != (y&1) ? left[p*m] : right[p*m];
  911. }
  912. break;
  913. case 2:
  914. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=4, p+=2, b+=2) {
  915. AV_WN16(&dst[x ], (b&1) == (y&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
  916. AV_WN16(&dst[x+2], (b&1) != (y&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
  917. }
  918. break;
  919. case 3:
  920. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=6, p+=3, b+=2) {
  921. AV_WB24(&dst[x ], (b&1) == (y&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
  922. AV_WB24(&dst[x+3], (b&1) != (y&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
  923. }
  924. break;
  925. case 4:
  926. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=8, p+=4, b+=2) {
  927. AV_WN32(&dst[x ], (b&1) == (y&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
  928. AV_WN32(&dst[x+4], (b&1) != (y&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
  929. }
  930. break;
  931. case 6:
  932. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=12, p+=6, b+=2) {
  933. AV_WB48(&dst[x ], (b&1) == (y&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
  934. AV_WB48(&dst[x+6], (b&1) != (y&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
  935. }
  936. break;
  937. case 8:
  938. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=16, p+=8, b+=2) {
  939. AV_WN64(&dst[x ], (b&1) == (y&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
  940. AV_WN64(&dst[x+8], (b&1) != (y&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
  941. }
  942. break;
  943. }
  944. }
  945. }
  946. break;
  947. case INTERLEAVE_COLS_LR:
  948. case INTERLEAVE_COLS_RL:
  949. for (i = 0; i < s->nb_planes; i++) {
  950. const int d = (s->in.format == INTERLEAVE_COLS_LR || s->in.format == INTERLEAVE_COLS_RL);
  951. const int m = 1 + d;
  952. int x, y;
  953. for (y = 0; y < s->pheight[i]; y++) {
  954. uint8_t *dst = out->data[i] + out->linesize[i] * y;
  955. uint8_t *left = ileft->data[i] + ileft->linesize[i] * y * s->in.row_step + s->in_off_left[i] + d * s->pixstep[i];
  956. uint8_t *right = iright->data[i] + iright->linesize[i] * y * s->in.row_step + s->in_off_right[i];
  957. int p, b;
  958. if (s->out.format == INTERLEAVE_COLS_LR)
  959. FFSWAP(uint8_t*, left, right);
  960. switch (s->pixstep[i]) {
  961. case 1:
  962. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=2, p++, b+=2) {
  963. dst[x ] = b&1 ? left[p*m] : right[p*m];
  964. dst[x+1] = !(b&1) ? left[p*m] : right[p*m];
  965. }
  966. break;
  967. case 2:
  968. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=4, p+=2, b+=2) {
  969. AV_WN16(&dst[x ], b&1 ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
  970. AV_WN16(&dst[x+2], !(b&1) ? AV_RN16(&left[p*m]) : AV_RN16(&right[p*m]));
  971. }
  972. break;
  973. case 3:
  974. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=6, p+=3, b+=2) {
  975. AV_WB24(&dst[x ], b&1 ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
  976. AV_WB24(&dst[x+3], !(b&1) ? AV_RB24(&left[p*m]) : AV_RB24(&right[p*m]));
  977. }
  978. break;
  979. case 4:
  980. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=8, p+=4, b+=2) {
  981. AV_WN32(&dst[x ], b&1 ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
  982. AV_WN32(&dst[x+4], !(b&1) ? AV_RN32(&left[p*m]) : AV_RN32(&right[p*m]));
  983. }
  984. break;
  985. case 6:
  986. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=12, p+=6, b+=2) {
  987. AV_WB48(&dst[x ], b&1 ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
  988. AV_WB48(&dst[x+6], !(b&1) ? AV_RB48(&left[p*m]) : AV_RB48(&right[p*m]));
  989. }
  990. break;
  991. case 8:
  992. for (x = 0, b = 0, p = 0; x < s->linesize[i] * 2; x+=16, p+=8, b+=2) {
  993. AV_WN64(&dst[x ], b&1 ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
  994. AV_WN64(&dst[x+8], !(b&1) ? AV_RN64(&left[p*m]) : AV_RN64(&right[p*m]));
  995. }
  996. break;
  997. }
  998. }
  999. }
  1000. break;
  1001. default:
  1002. av_assert0(0);
  1003. }
  1004. if (oright != oleft) {
  1005. if (s->out.format == ALTERNATING_LR)
  1006. FFSWAP(AVFrame *, oleft, oright);
  1007. oright->pts = s->prev->pts * 2;
  1008. ff_filter_frame(outlink, oright);
  1009. out = oleft;
  1010. oleft->pts = s->prev->pts + inpicref->pts;
  1011. av_frame_free(&s->prev);
  1012. s->prev = inpicref;
  1013. } else if (s->in.format == ALTERNATING_LR ||
  1014. s->in.format == ALTERNATING_RL) {
  1015. out->pts = s->prev->pts / 2;
  1016. av_frame_free(&s->prev);
  1017. av_frame_free(&inpicref);
  1018. } else {
  1019. av_frame_free(&s->prev);
  1020. av_frame_free(&inpicref);
  1021. }
  1022. av_assert0(out);
  1023. out->sample_aspect_ratio = s->aspect;
  1024. return ff_filter_frame(outlink, out);
  1025. }
  1026. static av_cold void uninit(AVFilterContext *ctx)
  1027. {
  1028. Stereo3DContext *s = ctx->priv;
  1029. av_frame_free(&s->prev);
  1030. }
  1031. static const AVFilterPad stereo3d_inputs[] = {
  1032. {
  1033. .name = "default",
  1034. .type = AVMEDIA_TYPE_VIDEO,
  1035. .filter_frame = filter_frame,
  1036. },
  1037. { NULL }
  1038. };
  1039. static const AVFilterPad stereo3d_outputs[] = {
  1040. {
  1041. .name = "default",
  1042. .type = AVMEDIA_TYPE_VIDEO,
  1043. .config_props = config_output,
  1044. },
  1045. { NULL }
  1046. };
  1047. AVFilter ff_vf_stereo3d = {
  1048. .name = "stereo3d",
  1049. .description = NULL_IF_CONFIG_SMALL("Convert video stereoscopic 3D view."),
  1050. .priv_size = sizeof(Stereo3DContext),
  1051. .uninit = uninit,
  1052. .query_formats = query_formats,
  1053. .inputs = stereo3d_inputs,
  1054. .outputs = stereo3d_outputs,
  1055. .priv_class = &stereo3d_class,
  1056. .flags = AVFILTER_FLAG_SLICE_THREADS,
  1057. };