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.

1487 lines
54KB

  1. /*
  2. * Copyright (C) 2001-2003 Michael Niedermayer <michaelni@gmx.at>
  3. *
  4. * This file is part of Libav.
  5. *
  6. * Libav is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * Libav is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with Libav; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #include <assert.h>
  21. #include <math.h>
  22. #include <stdint.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "libavutil/avutil.h"
  26. #include "libavutil/bswap.h"
  27. #include "libavutil/cpu.h"
  28. #include "libavutil/intreadwrite.h"
  29. #include "libavutil/mathematics.h"
  30. #include "libavutil/pixdesc.h"
  31. #include "config.h"
  32. #include "rgb2rgb.h"
  33. #include "swscale.h"
  34. #include "swscale_internal.h"
  35. DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_4)[2][8]={
  36. { 1, 3, 1, 3, 1, 3, 1, 3, },
  37. { 2, 0, 2, 0, 2, 0, 2, 0, },
  38. };
  39. DECLARE_ALIGNED(8, static const uint8_t, dither_2x2_8)[2][8]={
  40. { 6, 2, 6, 2, 6, 2, 6, 2, },
  41. { 0, 4, 0, 4, 0, 4, 0, 4, },
  42. };
  43. DECLARE_ALIGNED(8, const uint8_t, dither_4x4_16)[4][8]={
  44. { 8, 4, 11, 7, 8, 4, 11, 7, },
  45. { 2, 14, 1, 13, 2, 14, 1, 13, },
  46. { 10, 6, 9, 5, 10, 6, 9, 5, },
  47. { 0, 12, 3, 15, 0, 12, 3, 15, },
  48. };
  49. DECLARE_ALIGNED(8, const uint8_t, dither_8x8_32)[8][8]={
  50. { 17, 9, 23, 15, 16, 8, 22, 14, },
  51. { 5, 29, 3, 27, 4, 28, 2, 26, },
  52. { 21, 13, 19, 11, 20, 12, 18, 10, },
  53. { 0, 24, 6, 30, 1, 25, 7, 31, },
  54. { 16, 8, 22, 14, 17, 9, 23, 15, },
  55. { 4, 28, 2, 26, 5, 29, 3, 27, },
  56. { 20, 12, 18, 10, 21, 13, 19, 11, },
  57. { 1, 25, 7, 31, 0, 24, 6, 30, },
  58. };
  59. DECLARE_ALIGNED(8, const uint8_t, dither_8x8_73)[8][8]={
  60. { 0, 55, 14, 68, 3, 58, 17, 72, },
  61. { 37, 18, 50, 32, 40, 22, 54, 35, },
  62. { 9, 64, 5, 59, 13, 67, 8, 63, },
  63. { 46, 27, 41, 23, 49, 31, 44, 26, },
  64. { 2, 57, 16, 71, 1, 56, 15, 70, },
  65. { 39, 21, 52, 34, 38, 19, 51, 33, },
  66. { 11, 66, 7, 62, 10, 65, 6, 60, },
  67. { 48, 30, 43, 25, 47, 29, 42, 24, },
  68. };
  69. #if 1
  70. DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
  71. {117, 62, 158, 103, 113, 58, 155, 100, },
  72. { 34, 199, 21, 186, 31, 196, 17, 182, },
  73. {144, 89, 131, 76, 141, 86, 127, 72, },
  74. { 0, 165, 41, 206, 10, 175, 52, 217, },
  75. {110, 55, 151, 96, 120, 65, 162, 107, },
  76. { 28, 193, 14, 179, 38, 203, 24, 189, },
  77. {138, 83, 124, 69, 148, 93, 134, 79, },
  78. { 7, 172, 48, 213, 3, 168, 45, 210, },
  79. };
  80. #elif 1
  81. // tries to correct a gamma of 1.5
  82. DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
  83. { 0, 143, 18, 200, 2, 156, 25, 215, },
  84. { 78, 28, 125, 64, 89, 36, 138, 74, },
  85. { 10, 180, 3, 161, 16, 195, 8, 175, },
  86. {109, 51, 93, 38, 121, 60, 105, 47, },
  87. { 1, 152, 23, 210, 0, 147, 20, 205, },
  88. { 85, 33, 134, 71, 81, 30, 130, 67, },
  89. { 14, 190, 6, 171, 12, 185, 5, 166, },
  90. {117, 57, 101, 44, 113, 54, 97, 41, },
  91. };
  92. #elif 1
  93. // tries to correct a gamma of 2.0
  94. DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
  95. { 0, 124, 8, 193, 0, 140, 12, 213, },
  96. { 55, 14, 104, 42, 66, 19, 119, 52, },
  97. { 3, 168, 1, 145, 6, 187, 3, 162, },
  98. { 86, 31, 70, 21, 99, 39, 82, 28, },
  99. { 0, 134, 11, 206, 0, 129, 9, 200, },
  100. { 62, 17, 114, 48, 58, 16, 109, 45, },
  101. { 5, 181, 2, 157, 4, 175, 1, 151, },
  102. { 95, 36, 78, 26, 90, 34, 74, 24, },
  103. };
  104. #else
  105. // tries to correct a gamma of 2.5
  106. DECLARE_ALIGNED(8, const uint8_t, dither_8x8_220)[8][8]={
  107. { 0, 107, 3, 187, 0, 125, 6, 212, },
  108. { 39, 7, 86, 28, 49, 11, 102, 36, },
  109. { 1, 158, 0, 131, 3, 180, 1, 151, },
  110. { 68, 19, 52, 12, 81, 25, 64, 17, },
  111. { 0, 119, 5, 203, 0, 113, 4, 195, },
  112. { 45, 9, 96, 33, 42, 8, 91, 30, },
  113. { 2, 172, 1, 144, 2, 165, 0, 137, },
  114. { 77, 23, 60, 15, 72, 21, 56, 14, },
  115. };
  116. #endif
  117. #define output_pixel(pos, val, bias, signedness) \
  118. if (big_endian) { \
  119. AV_WB16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \
  120. } else { \
  121. AV_WL16(pos, bias + av_clip_ ## signedness ## 16(val >> shift)); \
  122. }
  123. static av_always_inline void
  124. yuv2plane1_16_c_template(const int32_t *src, uint16_t *dest, int dstW,
  125. int big_endian, int output_bits)
  126. {
  127. int i;
  128. int shift = 19 - output_bits;
  129. for (i = 0; i < dstW; i++) {
  130. int val = src[i] + (1 << (shift - 1));
  131. output_pixel(&dest[i], val, 0, uint);
  132. }
  133. }
  134. static av_always_inline void
  135. yuv2planeX_16_c_template(const int16_t *filter, int filterSize,
  136. const int32_t **src, uint16_t *dest, int dstW,
  137. int big_endian, int output_bits)
  138. {
  139. int i;
  140. int shift = 15 + 16 - output_bits;
  141. for (i = 0; i < dstW; i++) {
  142. int val = 1 << (30-output_bits);
  143. int j;
  144. /* range of val is [0,0x7FFFFFFF], so 31 bits, but with lanczos/spline
  145. * filters (or anything with negative coeffs, the range can be slightly
  146. * wider in both directions. To account for this overflow, we subtract
  147. * a constant so it always fits in the signed range (assuming a
  148. * reasonable filterSize), and re-add that at the end. */
  149. val -= 0x40000000;
  150. for (j = 0; j < filterSize; j++)
  151. val += src[j][i] * filter[j];
  152. output_pixel(&dest[i], val, 0x8000, int);
  153. }
  154. }
  155. #undef output_pixel
  156. #define output_pixel(pos, val) \
  157. if (big_endian) { \
  158. AV_WB16(pos, av_clip_uintp2(val >> shift, output_bits)); \
  159. } else { \
  160. AV_WL16(pos, av_clip_uintp2(val >> shift, output_bits)); \
  161. }
  162. static av_always_inline void
  163. yuv2plane1_10_c_template(const int16_t *src, uint16_t *dest, int dstW,
  164. int big_endian, int output_bits)
  165. {
  166. int i;
  167. int shift = 15 - output_bits;
  168. for (i = 0; i < dstW; i++) {
  169. int val = src[i] + (1 << (shift - 1));
  170. output_pixel(&dest[i], val);
  171. }
  172. }
  173. static av_always_inline void
  174. yuv2planeX_10_c_template(const int16_t *filter, int filterSize,
  175. const int16_t **src, uint16_t *dest, int dstW,
  176. int big_endian, int output_bits)
  177. {
  178. int i;
  179. int shift = 11 + 16 - output_bits;
  180. for (i = 0; i < dstW; i++) {
  181. int val = 1 << (26-output_bits);
  182. int j;
  183. for (j = 0; j < filterSize; j++)
  184. val += src[j][i] * filter[j];
  185. output_pixel(&dest[i], val);
  186. }
  187. }
  188. #undef output_pixel
  189. #define yuv2NBPS(bits, BE_LE, is_be, template_size, typeX_t) \
  190. static void yuv2plane1_ ## bits ## BE_LE ## _c(const int16_t *src, \
  191. uint8_t *dest, int dstW, \
  192. const uint8_t *dither, int offset)\
  193. { \
  194. yuv2plane1_ ## template_size ## _c_template((const typeX_t *) src, \
  195. (uint16_t *) dest, dstW, is_be, bits); \
  196. }\
  197. static void yuv2planeX_ ## bits ## BE_LE ## _c(const int16_t *filter, int filterSize, \
  198. const int16_t **src, uint8_t *dest, int dstW, \
  199. const uint8_t *dither, int offset)\
  200. { \
  201. yuv2planeX_## template_size ## _c_template(filter, \
  202. filterSize, (const typeX_t **) src, \
  203. (uint16_t *) dest, dstW, is_be, bits); \
  204. }
  205. yuv2NBPS( 9, BE, 1, 10, int16_t)
  206. yuv2NBPS( 9, LE, 0, 10, int16_t)
  207. yuv2NBPS(10, BE, 1, 10, int16_t)
  208. yuv2NBPS(10, LE, 0, 10, int16_t)
  209. yuv2NBPS(16, BE, 1, 16, int32_t)
  210. yuv2NBPS(16, LE, 0, 16, int32_t)
  211. static void yuv2planeX_8_c(const int16_t *filter, int filterSize,
  212. const int16_t **src, uint8_t *dest, int dstW,
  213. const uint8_t *dither, int offset)
  214. {
  215. int i;
  216. for (i=0; i<dstW; i++) {
  217. int val = dither[(i + offset) & 7] << 12;
  218. int j;
  219. for (j=0; j<filterSize; j++)
  220. val += src[j][i] * filter[j];
  221. dest[i]= av_clip_uint8(val>>19);
  222. }
  223. }
  224. static void yuv2plane1_8_c(const int16_t *src, uint8_t *dest, int dstW,
  225. const uint8_t *dither, int offset)
  226. {
  227. int i;
  228. for (i=0; i<dstW; i++) {
  229. int val = (src[i] + dither[(i + offset) & 7]) >> 7;
  230. dest[i]= av_clip_uint8(val);
  231. }
  232. }
  233. static void yuv2nv12cX_c(SwsContext *c, const int16_t *chrFilter, int chrFilterSize,
  234. const int16_t **chrUSrc, const int16_t **chrVSrc,
  235. uint8_t *dest, int chrDstW)
  236. {
  237. enum PixelFormat dstFormat = c->dstFormat;
  238. const uint8_t *chrDither = c->chrDither8;
  239. int i;
  240. if (dstFormat == PIX_FMT_NV12)
  241. for (i=0; i<chrDstW; i++) {
  242. int u = chrDither[i & 7] << 12;
  243. int v = chrDither[(i + 3) & 7] << 12;
  244. int j;
  245. for (j=0; j<chrFilterSize; j++) {
  246. u += chrUSrc[j][i] * chrFilter[j];
  247. v += chrVSrc[j][i] * chrFilter[j];
  248. }
  249. dest[2*i]= av_clip_uint8(u>>19);
  250. dest[2*i+1]= av_clip_uint8(v>>19);
  251. }
  252. else
  253. for (i=0; i<chrDstW; i++) {
  254. int u = chrDither[i & 7] << 12;
  255. int v = chrDither[(i + 3) & 7] << 12;
  256. int j;
  257. for (j=0; j<chrFilterSize; j++) {
  258. u += chrUSrc[j][i] * chrFilter[j];
  259. v += chrVSrc[j][i] * chrFilter[j];
  260. }
  261. dest[2*i]= av_clip_uint8(v>>19);
  262. dest[2*i+1]= av_clip_uint8(u>>19);
  263. }
  264. }
  265. #define accumulate_bit(acc, val) \
  266. acc <<= 1; \
  267. acc |= (val) >= (128 + 110)
  268. #define output_pixel(pos, acc) \
  269. if (target == PIX_FMT_MONOBLACK) { \
  270. pos = acc; \
  271. } else { \
  272. pos = ~acc; \
  273. }
  274. static av_always_inline void
  275. yuv2mono_X_c_template(SwsContext *c, const int16_t *lumFilter,
  276. const int16_t **lumSrc, int lumFilterSize,
  277. const int16_t *chrFilter, const int16_t **chrUSrc,
  278. const int16_t **chrVSrc, int chrFilterSize,
  279. const int16_t **alpSrc, uint8_t *dest, int dstW,
  280. int y, enum PixelFormat target)
  281. {
  282. const uint8_t * const d128=dither_8x8_220[y&7];
  283. int i;
  284. unsigned acc = 0;
  285. for (i = 0; i < dstW - 1; i += 2) {
  286. int j;
  287. int Y1 = 1 << 18;
  288. int Y2 = 1 << 18;
  289. for (j = 0; j < lumFilterSize; j++) {
  290. Y1 += lumSrc[j][i] * lumFilter[j];
  291. Y2 += lumSrc[j][i+1] * lumFilter[j];
  292. }
  293. Y1 >>= 19;
  294. Y2 >>= 19;
  295. if ((Y1 | Y2) & 0x100) {
  296. Y1 = av_clip_uint8(Y1);
  297. Y2 = av_clip_uint8(Y2);
  298. }
  299. accumulate_bit(acc, Y1 + d128[(i + 0) & 7]);
  300. accumulate_bit(acc, Y2 + d128[(i + 1) & 7]);
  301. if ((i & 7) == 6) {
  302. output_pixel(*dest++, acc);
  303. }
  304. }
  305. }
  306. static av_always_inline void
  307. yuv2mono_2_c_template(SwsContext *c, const int16_t *buf[2],
  308. const int16_t *ubuf[2], const int16_t *vbuf[2],
  309. const int16_t *abuf[2], uint8_t *dest, int dstW,
  310. int yalpha, int uvalpha, int y,
  311. enum PixelFormat target)
  312. {
  313. const int16_t *buf0 = buf[0], *buf1 = buf[1];
  314. const uint8_t * const d128 = dither_8x8_220[y & 7];
  315. int yalpha1 = 4095 - yalpha;
  316. int i;
  317. for (i = 0; i < dstW - 7; i += 8) {
  318. int Y, acc = 0;
  319. Y = (buf0[i + 0] * yalpha1 + buf1[i + 0] * yalpha) >> 19;
  320. accumulate_bit(acc, Y + d128[0]);
  321. Y = (buf0[i + 1] * yalpha1 + buf1[i + 1] * yalpha) >> 19;
  322. accumulate_bit(acc, Y + d128[1]);
  323. Y = (buf0[i + 2] * yalpha1 + buf1[i + 2] * yalpha) >> 19;
  324. accumulate_bit(acc, Y + d128[2]);
  325. Y = (buf0[i + 3] * yalpha1 + buf1[i + 3] * yalpha) >> 19;
  326. accumulate_bit(acc, Y + d128[3]);
  327. Y = (buf0[i + 4] * yalpha1 + buf1[i + 4] * yalpha) >> 19;
  328. accumulate_bit(acc, Y + d128[4]);
  329. Y = (buf0[i + 5] * yalpha1 + buf1[i + 5] * yalpha) >> 19;
  330. accumulate_bit(acc, Y + d128[5]);
  331. Y = (buf0[i + 6] * yalpha1 + buf1[i + 6] * yalpha) >> 19;
  332. accumulate_bit(acc, Y + d128[6]);
  333. Y = (buf0[i + 7] * yalpha1 + buf1[i + 7] * yalpha) >> 19;
  334. accumulate_bit(acc, Y + d128[7]);
  335. output_pixel(*dest++, acc);
  336. }
  337. }
  338. static av_always_inline void
  339. yuv2mono_1_c_template(SwsContext *c, const int16_t *buf0,
  340. const int16_t *ubuf[2], const int16_t *vbuf[2],
  341. const int16_t *abuf0, uint8_t *dest, int dstW,
  342. int uvalpha, int y, enum PixelFormat target)
  343. {
  344. const uint8_t * const d128 = dither_8x8_220[y & 7];
  345. int i;
  346. for (i = 0; i < dstW - 7; i += 8) {
  347. int acc = 0;
  348. accumulate_bit(acc, (buf0[i + 0] >> 7) + d128[0]);
  349. accumulate_bit(acc, (buf0[i + 1] >> 7) + d128[1]);
  350. accumulate_bit(acc, (buf0[i + 2] >> 7) + d128[2]);
  351. accumulate_bit(acc, (buf0[i + 3] >> 7) + d128[3]);
  352. accumulate_bit(acc, (buf0[i + 4] >> 7) + d128[4]);
  353. accumulate_bit(acc, (buf0[i + 5] >> 7) + d128[5]);
  354. accumulate_bit(acc, (buf0[i + 6] >> 7) + d128[6]);
  355. accumulate_bit(acc, (buf0[i + 7] >> 7) + d128[7]);
  356. output_pixel(*dest++, acc);
  357. }
  358. }
  359. #undef output_pixel
  360. #undef accumulate_bit
  361. #define YUV2PACKEDWRAPPER(name, base, ext, fmt) \
  362. static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
  363. const int16_t **lumSrc, int lumFilterSize, \
  364. const int16_t *chrFilter, const int16_t **chrUSrc, \
  365. const int16_t **chrVSrc, int chrFilterSize, \
  366. const int16_t **alpSrc, uint8_t *dest, int dstW, \
  367. int y) \
  368. { \
  369. name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
  370. chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
  371. alpSrc, dest, dstW, y, fmt); \
  372. } \
  373. \
  374. static void name ## ext ## _2_c(SwsContext *c, const int16_t *buf[2], \
  375. const int16_t *ubuf[2], const int16_t *vbuf[2], \
  376. const int16_t *abuf[2], uint8_t *dest, int dstW, \
  377. int yalpha, int uvalpha, int y) \
  378. { \
  379. name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
  380. dest, dstW, yalpha, uvalpha, y, fmt); \
  381. } \
  382. \
  383. static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
  384. const int16_t *ubuf[2], const int16_t *vbuf[2], \
  385. const int16_t *abuf0, uint8_t *dest, int dstW, \
  386. int uvalpha, int y) \
  387. { \
  388. name ## base ## _1_c_template(c, buf0, ubuf, vbuf, \
  389. abuf0, dest, dstW, uvalpha, \
  390. y, fmt); \
  391. }
  392. YUV2PACKEDWRAPPER(yuv2mono,, white, PIX_FMT_MONOWHITE)
  393. YUV2PACKEDWRAPPER(yuv2mono,, black, PIX_FMT_MONOBLACK)
  394. #define output_pixels(pos, Y1, U, Y2, V) \
  395. if (target == PIX_FMT_YUYV422) { \
  396. dest[pos + 0] = Y1; \
  397. dest[pos + 1] = U; \
  398. dest[pos + 2] = Y2; \
  399. dest[pos + 3] = V; \
  400. } else { \
  401. dest[pos + 0] = U; \
  402. dest[pos + 1] = Y1; \
  403. dest[pos + 2] = V; \
  404. dest[pos + 3] = Y2; \
  405. }
  406. static av_always_inline void
  407. yuv2422_X_c_template(SwsContext *c, const int16_t *lumFilter,
  408. const int16_t **lumSrc, int lumFilterSize,
  409. const int16_t *chrFilter, const int16_t **chrUSrc,
  410. const int16_t **chrVSrc, int chrFilterSize,
  411. const int16_t **alpSrc, uint8_t *dest, int dstW,
  412. int y, enum PixelFormat target)
  413. {
  414. int i;
  415. for (i = 0; i < (dstW >> 1); i++) {
  416. int j;
  417. int Y1 = 1 << 18;
  418. int Y2 = 1 << 18;
  419. int U = 1 << 18;
  420. int V = 1 << 18;
  421. for (j = 0; j < lumFilterSize; j++) {
  422. Y1 += lumSrc[j][i * 2] * lumFilter[j];
  423. Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
  424. }
  425. for (j = 0; j < chrFilterSize; j++) {
  426. U += chrUSrc[j][i] * chrFilter[j];
  427. V += chrVSrc[j][i] * chrFilter[j];
  428. }
  429. Y1 >>= 19;
  430. Y2 >>= 19;
  431. U >>= 19;
  432. V >>= 19;
  433. if ((Y1 | Y2 | U | V) & 0x100) {
  434. Y1 = av_clip_uint8(Y1);
  435. Y2 = av_clip_uint8(Y2);
  436. U = av_clip_uint8(U);
  437. V = av_clip_uint8(V);
  438. }
  439. output_pixels(4*i, Y1, U, Y2, V);
  440. }
  441. }
  442. static av_always_inline void
  443. yuv2422_2_c_template(SwsContext *c, const int16_t *buf[2],
  444. const int16_t *ubuf[2], const int16_t *vbuf[2],
  445. const int16_t *abuf[2], uint8_t *dest, int dstW,
  446. int yalpha, int uvalpha, int y,
  447. enum PixelFormat target)
  448. {
  449. const int16_t *buf0 = buf[0], *buf1 = buf[1],
  450. *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
  451. *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
  452. int yalpha1 = 4095 - yalpha;
  453. int uvalpha1 = 4095 - uvalpha;
  454. int i;
  455. for (i = 0; i < (dstW >> 1); i++) {
  456. int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 19;
  457. int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 19;
  458. int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19;
  459. int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha) >> 19;
  460. Y1 = av_clip_uint8(Y1);
  461. Y2 = av_clip_uint8(Y2);
  462. U = av_clip_uint8(U);
  463. V = av_clip_uint8(V);
  464. output_pixels(i * 4, Y1, U, Y2, V);
  465. }
  466. }
  467. static av_always_inline void
  468. yuv2422_1_c_template(SwsContext *c, const int16_t *buf0,
  469. const int16_t *ubuf[2], const int16_t *vbuf[2],
  470. const int16_t *abuf0, uint8_t *dest, int dstW,
  471. int uvalpha, int y, enum PixelFormat target)
  472. {
  473. const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0];
  474. int i;
  475. if (uvalpha < 2048) {
  476. for (i = 0; i < (dstW >> 1); i++) {
  477. int Y1 = buf0[i * 2] >> 7;
  478. int Y2 = buf0[i * 2 + 1] >> 7;
  479. int U = ubuf0[i] >> 7;
  480. int V = vbuf0[i] >> 7;
  481. Y1 = av_clip_uint8(Y1);
  482. Y2 = av_clip_uint8(Y2);
  483. U = av_clip_uint8(U);
  484. V = av_clip_uint8(V);
  485. output_pixels(i * 4, Y1, U, Y2, V);
  486. }
  487. } else {
  488. const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1];
  489. for (i = 0; i < (dstW >> 1); i++) {
  490. int Y1 = buf0[i * 2] >> 7;
  491. int Y2 = buf0[i * 2 + 1] >> 7;
  492. int U = (ubuf0[i] + ubuf1[i]) >> 8;
  493. int V = (vbuf0[i] + vbuf1[i]) >> 8;
  494. Y1 = av_clip_uint8(Y1);
  495. Y2 = av_clip_uint8(Y2);
  496. U = av_clip_uint8(U);
  497. V = av_clip_uint8(V);
  498. output_pixels(i * 4, Y1, U, Y2, V);
  499. }
  500. }
  501. }
  502. #undef output_pixels
  503. YUV2PACKEDWRAPPER(yuv2, 422, yuyv422, PIX_FMT_YUYV422)
  504. YUV2PACKEDWRAPPER(yuv2, 422, uyvy422, PIX_FMT_UYVY422)
  505. #define R_B ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? R : B)
  506. #define B_R ((target == PIX_FMT_RGB48LE || target == PIX_FMT_RGB48BE) ? B : R)
  507. #define output_pixel(pos, val) \
  508. if (isBE(target)) { \
  509. AV_WB16(pos, val); \
  510. } else { \
  511. AV_WL16(pos, val); \
  512. }
  513. static av_always_inline void
  514. yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter,
  515. const int32_t **lumSrc, int lumFilterSize,
  516. const int16_t *chrFilter, const int32_t **chrUSrc,
  517. const int32_t **chrVSrc, int chrFilterSize,
  518. const int32_t **alpSrc, uint16_t *dest, int dstW,
  519. int y, enum PixelFormat target)
  520. {
  521. int i;
  522. for (i = 0; i < (dstW >> 1); i++) {
  523. int j;
  524. int Y1 = -0x40000000;
  525. int Y2 = -0x40000000;
  526. int U = -128 << 23; // 19
  527. int V = -128 << 23;
  528. int R, G, B;
  529. for (j = 0; j < lumFilterSize; j++) {
  530. Y1 += lumSrc[j][i * 2] * lumFilter[j];
  531. Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
  532. }
  533. for (j = 0; j < chrFilterSize; j++) {
  534. U += chrUSrc[j][i] * chrFilter[j];
  535. V += chrVSrc[j][i] * chrFilter[j];
  536. }
  537. // 8bit: 12+15=27; 16-bit: 12+19=31
  538. Y1 >>= 14; // 10
  539. Y1 += 0x10000;
  540. Y2 >>= 14;
  541. Y2 += 0x10000;
  542. U >>= 14;
  543. V >>= 14;
  544. // 8bit: 27 -> 17bit, 16bit: 31 - 14 = 17bit
  545. Y1 -= c->yuv2rgb_y_offset;
  546. Y2 -= c->yuv2rgb_y_offset;
  547. Y1 *= c->yuv2rgb_y_coeff;
  548. Y2 *= c->yuv2rgb_y_coeff;
  549. Y1 += 1 << 13; // 21
  550. Y2 += 1 << 13;
  551. // 8bit: 17 + 13bit = 30bit, 16bit: 17 + 13bit = 30bit
  552. R = V * c->yuv2rgb_v2r_coeff;
  553. G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
  554. B = U * c->yuv2rgb_u2b_coeff;
  555. // 8bit: 30 - 22 = 8bit, 16bit: 30bit - 14 = 16bit
  556. output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
  557. output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
  558. output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
  559. output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
  560. output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
  561. output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
  562. dest += 6;
  563. }
  564. }
  565. static av_always_inline void
  566. yuv2rgb48_2_c_template(SwsContext *c, const int32_t *buf[2],
  567. const int32_t *ubuf[2], const int32_t *vbuf[2],
  568. const int32_t *abuf[2], uint16_t *dest, int dstW,
  569. int yalpha, int uvalpha, int y,
  570. enum PixelFormat target)
  571. {
  572. const int32_t *buf0 = buf[0], *buf1 = buf[1],
  573. *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
  574. *vbuf0 = vbuf[0], *vbuf1 = vbuf[1];
  575. int yalpha1 = 4095 - yalpha;
  576. int uvalpha1 = 4095 - uvalpha;
  577. int i;
  578. for (i = 0; i < (dstW >> 1); i++) {
  579. int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 14;
  580. int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 14;
  581. int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha + (-128 << 23)) >> 14;
  582. int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha + (-128 << 23)) >> 14;
  583. int R, G, B;
  584. Y1 -= c->yuv2rgb_y_offset;
  585. Y2 -= c->yuv2rgb_y_offset;
  586. Y1 *= c->yuv2rgb_y_coeff;
  587. Y2 *= c->yuv2rgb_y_coeff;
  588. Y1 += 1 << 13;
  589. Y2 += 1 << 13;
  590. R = V * c->yuv2rgb_v2r_coeff;
  591. G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
  592. B = U * c->yuv2rgb_u2b_coeff;
  593. output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
  594. output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
  595. output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
  596. output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
  597. output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
  598. output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
  599. dest += 6;
  600. }
  601. }
  602. static av_always_inline void
  603. yuv2rgb48_1_c_template(SwsContext *c, const int32_t *buf0,
  604. const int32_t *ubuf[2], const int32_t *vbuf[2],
  605. const int32_t *abuf0, uint16_t *dest, int dstW,
  606. int uvalpha, int y, enum PixelFormat target)
  607. {
  608. const int32_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0];
  609. int i;
  610. if (uvalpha < 2048) {
  611. for (i = 0; i < (dstW >> 1); i++) {
  612. int Y1 = (buf0[i * 2] ) >> 2;
  613. int Y2 = (buf0[i * 2 + 1]) >> 2;
  614. int U = (ubuf0[i] + (-128 << 11)) >> 2;
  615. int V = (vbuf0[i] + (-128 << 11)) >> 2;
  616. int R, G, B;
  617. Y1 -= c->yuv2rgb_y_offset;
  618. Y2 -= c->yuv2rgb_y_offset;
  619. Y1 *= c->yuv2rgb_y_coeff;
  620. Y2 *= c->yuv2rgb_y_coeff;
  621. Y1 += 1 << 13;
  622. Y2 += 1 << 13;
  623. R = V * c->yuv2rgb_v2r_coeff;
  624. G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
  625. B = U * c->yuv2rgb_u2b_coeff;
  626. output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
  627. output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
  628. output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
  629. output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
  630. output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
  631. output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
  632. dest += 6;
  633. }
  634. } else {
  635. const int32_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1];
  636. for (i = 0; i < (dstW >> 1); i++) {
  637. int Y1 = (buf0[i * 2] ) >> 2;
  638. int Y2 = (buf0[i * 2 + 1]) >> 2;
  639. int U = (ubuf0[i] + ubuf1[i] + (-128 << 12)) >> 3;
  640. int V = (vbuf0[i] + vbuf1[i] + (-128 << 12)) >> 3;
  641. int R, G, B;
  642. Y1 -= c->yuv2rgb_y_offset;
  643. Y2 -= c->yuv2rgb_y_offset;
  644. Y1 *= c->yuv2rgb_y_coeff;
  645. Y2 *= c->yuv2rgb_y_coeff;
  646. Y1 += 1 << 13;
  647. Y2 += 1 << 13;
  648. R = V * c->yuv2rgb_v2r_coeff;
  649. G = V * c->yuv2rgb_v2g_coeff + U * c->yuv2rgb_u2g_coeff;
  650. B = U * c->yuv2rgb_u2b_coeff;
  651. output_pixel(&dest[0], av_clip_uintp2(R_B + Y1, 30) >> 14);
  652. output_pixel(&dest[1], av_clip_uintp2( G + Y1, 30) >> 14);
  653. output_pixel(&dest[2], av_clip_uintp2(B_R + Y1, 30) >> 14);
  654. output_pixel(&dest[3], av_clip_uintp2(R_B + Y2, 30) >> 14);
  655. output_pixel(&dest[4], av_clip_uintp2( G + Y2, 30) >> 14);
  656. output_pixel(&dest[5], av_clip_uintp2(B_R + Y2, 30) >> 14);
  657. dest += 6;
  658. }
  659. }
  660. }
  661. #undef output_pixel
  662. #undef r_b
  663. #undef b_r
  664. #define YUV2PACKED16WRAPPER(name, base, ext, fmt) \
  665. static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
  666. const int16_t **_lumSrc, int lumFilterSize, \
  667. const int16_t *chrFilter, const int16_t **_chrUSrc, \
  668. const int16_t **_chrVSrc, int chrFilterSize, \
  669. const int16_t **_alpSrc, uint8_t *_dest, int dstW, \
  670. int y) \
  671. { \
  672. const int32_t **lumSrc = (const int32_t **) _lumSrc, \
  673. **chrUSrc = (const int32_t **) _chrUSrc, \
  674. **chrVSrc = (const int32_t **) _chrVSrc, \
  675. **alpSrc = (const int32_t **) _alpSrc; \
  676. uint16_t *dest = (uint16_t *) _dest; \
  677. name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
  678. chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
  679. alpSrc, dest, dstW, y, fmt); \
  680. } \
  681. \
  682. static void name ## ext ## _2_c(SwsContext *c, const int16_t *_buf[2], \
  683. const int16_t *_ubuf[2], const int16_t *_vbuf[2], \
  684. const int16_t *_abuf[2], uint8_t *_dest, int dstW, \
  685. int yalpha, int uvalpha, int y) \
  686. { \
  687. const int32_t **buf = (const int32_t **) _buf, \
  688. **ubuf = (const int32_t **) _ubuf, \
  689. **vbuf = (const int32_t **) _vbuf, \
  690. **abuf = (const int32_t **) _abuf; \
  691. uint16_t *dest = (uint16_t *) _dest; \
  692. name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
  693. dest, dstW, yalpha, uvalpha, y, fmt); \
  694. } \
  695. \
  696. static void name ## ext ## _1_c(SwsContext *c, const int16_t *_buf0, \
  697. const int16_t *_ubuf[2], const int16_t *_vbuf[2], \
  698. const int16_t *_abuf0, uint8_t *_dest, int dstW, \
  699. int uvalpha, int y) \
  700. { \
  701. const int32_t *buf0 = (const int32_t *) _buf0, \
  702. **ubuf = (const int32_t **) _ubuf, \
  703. **vbuf = (const int32_t **) _vbuf, \
  704. *abuf0 = (const int32_t *) _abuf0; \
  705. uint16_t *dest = (uint16_t *) _dest; \
  706. name ## base ## _1_c_template(c, buf0, ubuf, vbuf, abuf0, dest, \
  707. dstW, uvalpha, y, fmt); \
  708. }
  709. YUV2PACKED16WRAPPER(yuv2, rgb48, rgb48be, PIX_FMT_RGB48BE)
  710. YUV2PACKED16WRAPPER(yuv2, rgb48, rgb48le, PIX_FMT_RGB48LE)
  711. YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48be, PIX_FMT_BGR48BE)
  712. YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48le, PIX_FMT_BGR48LE)
  713. /*
  714. * Write out 2 RGB pixels in the target pixel format. This function takes a
  715. * R/G/B LUT as generated by ff_yuv2rgb_c_init_tables(), which takes care of
  716. * things like endianness conversion and shifting. The caller takes care of
  717. * setting the correct offset in these tables from the chroma (U/V) values.
  718. * This function then uses the luminance (Y1/Y2) values to write out the
  719. * correct RGB values into the destination buffer.
  720. */
  721. static av_always_inline void
  722. yuv2rgb_write(uint8_t *_dest, int i, unsigned Y1, unsigned Y2,
  723. unsigned A1, unsigned A2,
  724. const void *_r, const void *_g, const void *_b, int y,
  725. enum PixelFormat target, int hasAlpha)
  726. {
  727. if (target == PIX_FMT_ARGB || target == PIX_FMT_RGBA ||
  728. target == PIX_FMT_ABGR || target == PIX_FMT_BGRA) {
  729. uint32_t *dest = (uint32_t *) _dest;
  730. const uint32_t *r = (const uint32_t *) _r;
  731. const uint32_t *g = (const uint32_t *) _g;
  732. const uint32_t *b = (const uint32_t *) _b;
  733. #if CONFIG_SMALL
  734. int sh = hasAlpha ? ((target == PIX_FMT_RGB32_1 || target == PIX_FMT_BGR32_1) ? 0 : 24) : 0;
  735. dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1] + (hasAlpha ? A1 << sh : 0);
  736. dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2] + (hasAlpha ? A2 << sh : 0);
  737. #else
  738. if (hasAlpha) {
  739. int sh = (target == PIX_FMT_RGB32_1 || target == PIX_FMT_BGR32_1) ? 0 : 24;
  740. dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1] + (A1 << sh);
  741. dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2] + (A2 << sh);
  742. } else {
  743. dest[i * 2 + 0] = r[Y1] + g[Y1] + b[Y1];
  744. dest[i * 2 + 1] = r[Y2] + g[Y2] + b[Y2];
  745. }
  746. #endif
  747. } else if (target == PIX_FMT_RGB24 || target == PIX_FMT_BGR24) {
  748. uint8_t *dest = (uint8_t *) _dest;
  749. const uint8_t *r = (const uint8_t *) _r;
  750. const uint8_t *g = (const uint8_t *) _g;
  751. const uint8_t *b = (const uint8_t *) _b;
  752. #define r_b ((target == PIX_FMT_RGB24) ? r : b)
  753. #define b_r ((target == PIX_FMT_RGB24) ? b : r)
  754. dest[i * 6 + 0] = r_b[Y1];
  755. dest[i * 6 + 1] = g[Y1];
  756. dest[i * 6 + 2] = b_r[Y1];
  757. dest[i * 6 + 3] = r_b[Y2];
  758. dest[i * 6 + 4] = g[Y2];
  759. dest[i * 6 + 5] = b_r[Y2];
  760. #undef r_b
  761. #undef b_r
  762. } else if (target == PIX_FMT_RGB565 || target == PIX_FMT_BGR565 ||
  763. target == PIX_FMT_RGB555 || target == PIX_FMT_BGR555 ||
  764. target == PIX_FMT_RGB444 || target == PIX_FMT_BGR444) {
  765. uint16_t *dest = (uint16_t *) _dest;
  766. const uint16_t *r = (const uint16_t *) _r;
  767. const uint16_t *g = (const uint16_t *) _g;
  768. const uint16_t *b = (const uint16_t *) _b;
  769. int dr1, dg1, db1, dr2, dg2, db2;
  770. if (target == PIX_FMT_RGB565 || target == PIX_FMT_BGR565) {
  771. dr1 = dither_2x2_8[ y & 1 ][0];
  772. dg1 = dither_2x2_4[ y & 1 ][0];
  773. db1 = dither_2x2_8[(y & 1) ^ 1][0];
  774. dr2 = dither_2x2_8[ y & 1 ][1];
  775. dg2 = dither_2x2_4[ y & 1 ][1];
  776. db2 = dither_2x2_8[(y & 1) ^ 1][1];
  777. } else if (target == PIX_FMT_RGB555 || target == PIX_FMT_BGR555) {
  778. dr1 = dither_2x2_8[ y & 1 ][0];
  779. dg1 = dither_2x2_8[ y & 1 ][1];
  780. db1 = dither_2x2_8[(y & 1) ^ 1][0];
  781. dr2 = dither_2x2_8[ y & 1 ][1];
  782. dg2 = dither_2x2_8[ y & 1 ][0];
  783. db2 = dither_2x2_8[(y & 1) ^ 1][1];
  784. } else {
  785. dr1 = dither_4x4_16[ y & 3 ][0];
  786. dg1 = dither_4x4_16[ y & 3 ][1];
  787. db1 = dither_4x4_16[(y & 3) ^ 3][0];
  788. dr2 = dither_4x4_16[ y & 3 ][1];
  789. dg2 = dither_4x4_16[ y & 3 ][0];
  790. db2 = dither_4x4_16[(y & 3) ^ 3][1];
  791. }
  792. dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
  793. dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
  794. } else /* 8/4-bit */ {
  795. uint8_t *dest = (uint8_t *) _dest;
  796. const uint8_t *r = (const uint8_t *) _r;
  797. const uint8_t *g = (const uint8_t *) _g;
  798. const uint8_t *b = (const uint8_t *) _b;
  799. int dr1, dg1, db1, dr2, dg2, db2;
  800. if (target == PIX_FMT_RGB8 || target == PIX_FMT_BGR8) {
  801. const uint8_t * const d64 = dither_8x8_73[y & 7];
  802. const uint8_t * const d32 = dither_8x8_32[y & 7];
  803. dr1 = dg1 = d32[(i * 2 + 0) & 7];
  804. db1 = d64[(i * 2 + 0) & 7];
  805. dr2 = dg2 = d32[(i * 2 + 1) & 7];
  806. db2 = d64[(i * 2 + 1) & 7];
  807. } else {
  808. const uint8_t * const d64 = dither_8x8_73 [y & 7];
  809. const uint8_t * const d128 = dither_8x8_220[y & 7];
  810. dr1 = db1 = d128[(i * 2 + 0) & 7];
  811. dg1 = d64[(i * 2 + 0) & 7];
  812. dr2 = db2 = d128[(i * 2 + 1) & 7];
  813. dg2 = d64[(i * 2 + 1) & 7];
  814. }
  815. if (target == PIX_FMT_RGB4 || target == PIX_FMT_BGR4) {
  816. dest[i] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1] +
  817. ((r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2]) << 4);
  818. } else {
  819. dest[i * 2 + 0] = r[Y1 + dr1] + g[Y1 + dg1] + b[Y1 + db1];
  820. dest[i * 2 + 1] = r[Y2 + dr2] + g[Y2 + dg2] + b[Y2 + db2];
  821. }
  822. }
  823. }
  824. static av_always_inline void
  825. yuv2rgb_X_c_template(SwsContext *c, const int16_t *lumFilter,
  826. const int16_t **lumSrc, int lumFilterSize,
  827. const int16_t *chrFilter, const int16_t **chrUSrc,
  828. const int16_t **chrVSrc, int chrFilterSize,
  829. const int16_t **alpSrc, uint8_t *dest, int dstW,
  830. int y, enum PixelFormat target, int hasAlpha)
  831. {
  832. int i;
  833. for (i = 0; i < (dstW >> 1); i++) {
  834. int j, A1, A2;
  835. int Y1 = 1 << 18;
  836. int Y2 = 1 << 18;
  837. int U = 1 << 18;
  838. int V = 1 << 18;
  839. const void *r, *g, *b;
  840. for (j = 0; j < lumFilterSize; j++) {
  841. Y1 += lumSrc[j][i * 2] * lumFilter[j];
  842. Y2 += lumSrc[j][i * 2 + 1] * lumFilter[j];
  843. }
  844. for (j = 0; j < chrFilterSize; j++) {
  845. U += chrUSrc[j][i] * chrFilter[j];
  846. V += chrVSrc[j][i] * chrFilter[j];
  847. }
  848. Y1 >>= 19;
  849. Y2 >>= 19;
  850. U >>= 19;
  851. V >>= 19;
  852. if ((Y1 | Y2 | U | V) & 0x100) {
  853. Y1 = av_clip_uint8(Y1);
  854. Y2 = av_clip_uint8(Y2);
  855. U = av_clip_uint8(U);
  856. V = av_clip_uint8(V);
  857. }
  858. if (hasAlpha) {
  859. A1 = 1 << 18;
  860. A2 = 1 << 18;
  861. for (j = 0; j < lumFilterSize; j++) {
  862. A1 += alpSrc[j][i * 2 ] * lumFilter[j];
  863. A2 += alpSrc[j][i * 2 + 1] * lumFilter[j];
  864. }
  865. A1 >>= 19;
  866. A2 >>= 19;
  867. if ((A1 | A2) & 0x100) {
  868. A1 = av_clip_uint8(A1);
  869. A2 = av_clip_uint8(A2);
  870. }
  871. }
  872. /* FIXME fix tables so that clipping is not needed and then use _NOCLIP*/
  873. r = c->table_rV[V];
  874. g = (c->table_gU[U] + c->table_gV[V]);
  875. b = c->table_bU[U];
  876. yuv2rgb_write(dest, i, Y1, Y2, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
  877. r, g, b, y, target, hasAlpha);
  878. }
  879. }
  880. static av_always_inline void
  881. yuv2rgb_2_c_template(SwsContext *c, const int16_t *buf[2],
  882. const int16_t *ubuf[2], const int16_t *vbuf[2],
  883. const int16_t *abuf[2], uint8_t *dest, int dstW,
  884. int yalpha, int uvalpha, int y,
  885. enum PixelFormat target, int hasAlpha)
  886. {
  887. const int16_t *buf0 = buf[0], *buf1 = buf[1],
  888. *ubuf0 = ubuf[0], *ubuf1 = ubuf[1],
  889. *vbuf0 = vbuf[0], *vbuf1 = vbuf[1],
  890. *abuf0 = hasAlpha ? abuf[0] : NULL,
  891. *abuf1 = hasAlpha ? abuf[1] : NULL;
  892. int yalpha1 = 4095 - yalpha;
  893. int uvalpha1 = 4095 - uvalpha;
  894. int i;
  895. for (i = 0; i < (dstW >> 1); i++) {
  896. int Y1 = (buf0[i * 2] * yalpha1 + buf1[i * 2] * yalpha) >> 19;
  897. int Y2 = (buf0[i * 2 + 1] * yalpha1 + buf1[i * 2 + 1] * yalpha) >> 19;
  898. int U = (ubuf0[i] * uvalpha1 + ubuf1[i] * uvalpha) >> 19;
  899. int V = (vbuf0[i] * uvalpha1 + vbuf1[i] * uvalpha) >> 19;
  900. int A1, A2;
  901. const void *r = c->table_rV[V],
  902. *g = (c->table_gU[U] + c->table_gV[V]),
  903. *b = c->table_bU[U];
  904. Y1 = av_clip_uint8(Y1);
  905. Y2 = av_clip_uint8(Y2);
  906. U = av_clip_uint8(U);
  907. V = av_clip_uint8(V);
  908. if (hasAlpha) {
  909. A1 = (abuf0[i * 2 ] * yalpha1 + abuf1[i * 2 ] * yalpha) >> 19;
  910. A2 = (abuf0[i * 2 + 1] * yalpha1 + abuf1[i * 2 + 1] * yalpha) >> 19;
  911. A1 = av_clip_uint8(A1);
  912. A2 = av_clip_uint8(A2);
  913. }
  914. yuv2rgb_write(dest, i, Y1, Y2, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
  915. r, g, b, y, target, hasAlpha);
  916. }
  917. }
  918. static av_always_inline void
  919. yuv2rgb_1_c_template(SwsContext *c, const int16_t *buf0,
  920. const int16_t *ubuf[2], const int16_t *vbuf[2],
  921. const int16_t *abuf0, uint8_t *dest, int dstW,
  922. int uvalpha, int y, enum PixelFormat target,
  923. int hasAlpha)
  924. {
  925. const int16_t *ubuf0 = ubuf[0], *vbuf0 = vbuf[0];
  926. int i;
  927. if (uvalpha < 2048) {
  928. for (i = 0; i < (dstW >> 1); i++) {
  929. int Y1 = buf0[i * 2] >> 7;
  930. int Y2 = buf0[i * 2 + 1] >> 7;
  931. int U = ubuf0[i] >> 7;
  932. int V = vbuf0[i] >> 7;
  933. int A1, A2;
  934. const void *r = c->table_rV[V],
  935. *g = (c->table_gU[U] + c->table_gV[V]),
  936. *b = c->table_bU[U];
  937. Y1 = av_clip_uint8(Y1);
  938. Y2 = av_clip_uint8(Y2);
  939. U = av_clip_uint8(U);
  940. V = av_clip_uint8(V);
  941. if (hasAlpha) {
  942. A1 = abuf0[i * 2 ] >> 7;
  943. A2 = abuf0[i * 2 + 1] >> 7;
  944. A1 = av_clip_uint8(A1);
  945. A2 = av_clip_uint8(A2);
  946. }
  947. yuv2rgb_write(dest, i, Y1, Y2, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
  948. r, g, b, y, target, hasAlpha);
  949. }
  950. } else {
  951. const int16_t *ubuf1 = ubuf[1], *vbuf1 = vbuf[1];
  952. for (i = 0; i < (dstW >> 1); i++) {
  953. int Y1 = buf0[i * 2] >> 7;
  954. int Y2 = buf0[i * 2 + 1] >> 7;
  955. int U = (ubuf0[i] + ubuf1[i]) >> 8;
  956. int V = (vbuf0[i] + vbuf1[i]) >> 8;
  957. int A1, A2;
  958. const void *r = c->table_rV[V],
  959. *g = (c->table_gU[U] + c->table_gV[V]),
  960. *b = c->table_bU[U];
  961. Y1 = av_clip_uint8(Y1);
  962. Y2 = av_clip_uint8(Y2);
  963. U = av_clip_uint8(U);
  964. V = av_clip_uint8(V);
  965. if (hasAlpha) {
  966. A1 = abuf0[i * 2 ] >> 7;
  967. A2 = abuf0[i * 2 + 1] >> 7;
  968. A1 = av_clip_uint8(A1);
  969. A2 = av_clip_uint8(A2);
  970. }
  971. yuv2rgb_write(dest, i, Y1, Y2, hasAlpha ? A1 : 0, hasAlpha ? A2 : 0,
  972. r, g, b, y, target, hasAlpha);
  973. }
  974. }
  975. }
  976. #define YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \
  977. static void name ## ext ## _X_c(SwsContext *c, const int16_t *lumFilter, \
  978. const int16_t **lumSrc, int lumFilterSize, \
  979. const int16_t *chrFilter, const int16_t **chrUSrc, \
  980. const int16_t **chrVSrc, int chrFilterSize, \
  981. const int16_t **alpSrc, uint8_t *dest, int dstW, \
  982. int y) \
  983. { \
  984. name ## base ## _X_c_template(c, lumFilter, lumSrc, lumFilterSize, \
  985. chrFilter, chrUSrc, chrVSrc, chrFilterSize, \
  986. alpSrc, dest, dstW, y, fmt, hasAlpha); \
  987. }
  988. #define YUV2RGBWRAPPER(name, base, ext, fmt, hasAlpha) \
  989. YUV2RGBWRAPPERX(name, base, ext, fmt, hasAlpha) \
  990. static void name ## ext ## _2_c(SwsContext *c, const int16_t *buf[2], \
  991. const int16_t *ubuf[2], const int16_t *vbuf[2], \
  992. const int16_t *abuf[2], uint8_t *dest, int dstW, \
  993. int yalpha, int uvalpha, int y) \
  994. { \
  995. name ## base ## _2_c_template(c, buf, ubuf, vbuf, abuf, \
  996. dest, dstW, yalpha, uvalpha, y, fmt, hasAlpha); \
  997. } \
  998. \
  999. static void name ## ext ## _1_c(SwsContext *c, const int16_t *buf0, \
  1000. const int16_t *ubuf[2], const int16_t *vbuf[2], \
  1001. const int16_t *abuf0, uint8_t *dest, int dstW, \
  1002. int uvalpha, int y) \
  1003. { \
  1004. name ## base ## _1_c_template(c, buf0, ubuf, vbuf, abuf0, dest, \
  1005. dstW, uvalpha, y, fmt, hasAlpha); \
  1006. }
  1007. #if CONFIG_SMALL
  1008. YUV2RGBWRAPPER(yuv2rgb,, 32_1, PIX_FMT_RGB32_1, CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
  1009. YUV2RGBWRAPPER(yuv2rgb,, 32, PIX_FMT_RGB32, CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
  1010. #else
  1011. #if CONFIG_SWSCALE_ALPHA
  1012. YUV2RGBWRAPPER(yuv2rgb,, a32_1, PIX_FMT_RGB32_1, 1)
  1013. YUV2RGBWRAPPER(yuv2rgb,, a32, PIX_FMT_RGB32, 1)
  1014. #endif
  1015. YUV2RGBWRAPPER(yuv2rgb,, x32_1, PIX_FMT_RGB32_1, 0)
  1016. YUV2RGBWRAPPER(yuv2rgb,, x32, PIX_FMT_RGB32, 0)
  1017. #endif
  1018. YUV2RGBWRAPPER(yuv2, rgb, rgb24, PIX_FMT_RGB24, 0)
  1019. YUV2RGBWRAPPER(yuv2, rgb, bgr24, PIX_FMT_BGR24, 0)
  1020. YUV2RGBWRAPPER(yuv2rgb,, 16, PIX_FMT_RGB565, 0)
  1021. YUV2RGBWRAPPER(yuv2rgb,, 15, PIX_FMT_RGB555, 0)
  1022. YUV2RGBWRAPPER(yuv2rgb,, 12, PIX_FMT_RGB444, 0)
  1023. YUV2RGBWRAPPER(yuv2rgb,, 8, PIX_FMT_RGB8, 0)
  1024. YUV2RGBWRAPPER(yuv2rgb,, 4, PIX_FMT_RGB4, 0)
  1025. YUV2RGBWRAPPER(yuv2rgb,, 4b, PIX_FMT_RGB4_BYTE, 0)
  1026. static av_always_inline void
  1027. yuv2rgb_full_X_c_template(SwsContext *c, const int16_t *lumFilter,
  1028. const int16_t **lumSrc, int lumFilterSize,
  1029. const int16_t *chrFilter, const int16_t **chrUSrc,
  1030. const int16_t **chrVSrc, int chrFilterSize,
  1031. const int16_t **alpSrc, uint8_t *dest,
  1032. int dstW, int y, enum PixelFormat target, int hasAlpha)
  1033. {
  1034. int i;
  1035. int step = (target == PIX_FMT_RGB24 || target == PIX_FMT_BGR24) ? 3 : 4;
  1036. for (i = 0; i < dstW; i++) {
  1037. int j;
  1038. int Y = 0;
  1039. int U = -128 << 19;
  1040. int V = -128 << 19;
  1041. int R, G, B, A;
  1042. for (j = 0; j < lumFilterSize; j++) {
  1043. Y += lumSrc[j][i] * lumFilter[j];
  1044. }
  1045. for (j = 0; j < chrFilterSize; j++) {
  1046. U += chrUSrc[j][i] * chrFilter[j];
  1047. V += chrVSrc[j][i] * chrFilter[j];
  1048. }
  1049. Y >>= 10;
  1050. U >>= 10;
  1051. V >>= 10;
  1052. if (hasAlpha) {
  1053. A = 1 << 21;
  1054. for (j = 0; j < lumFilterSize; j++) {
  1055. A += alpSrc[j][i] * lumFilter[j];
  1056. }
  1057. A >>= 19;
  1058. if (A & 0x100)
  1059. A = av_clip_uint8(A);
  1060. }
  1061. Y -= c->yuv2rgb_y_offset;
  1062. Y *= c->yuv2rgb_y_coeff;
  1063. Y += 1 << 21;
  1064. R = Y + V*c->yuv2rgb_v2r_coeff;
  1065. G = Y + V*c->yuv2rgb_v2g_coeff + U*c->yuv2rgb_u2g_coeff;
  1066. B = Y + U*c->yuv2rgb_u2b_coeff;
  1067. if ((R | G | B) & 0xC0000000) {
  1068. R = av_clip_uintp2(R, 30);
  1069. G = av_clip_uintp2(G, 30);
  1070. B = av_clip_uintp2(B, 30);
  1071. }
  1072. switch(target) {
  1073. case PIX_FMT_ARGB:
  1074. dest[0] = hasAlpha ? A : 255;
  1075. dest[1] = R >> 22;
  1076. dest[2] = G >> 22;
  1077. dest[3] = B >> 22;
  1078. break;
  1079. case PIX_FMT_RGB24:
  1080. dest[0] = R >> 22;
  1081. dest[1] = G >> 22;
  1082. dest[2] = B >> 22;
  1083. break;
  1084. case PIX_FMT_RGBA:
  1085. dest[0] = R >> 22;
  1086. dest[1] = G >> 22;
  1087. dest[2] = B >> 22;
  1088. dest[3] = hasAlpha ? A : 255;
  1089. break;
  1090. case PIX_FMT_ABGR:
  1091. dest[0] = hasAlpha ? A : 255;
  1092. dest[1] = B >> 22;
  1093. dest[2] = G >> 22;
  1094. dest[3] = R >> 22;
  1095. dest += 4;
  1096. break;
  1097. case PIX_FMT_BGR24:
  1098. dest[0] = B >> 22;
  1099. dest[1] = G >> 22;
  1100. dest[2] = R >> 22;
  1101. break;
  1102. case PIX_FMT_BGRA:
  1103. dest[0] = B >> 22;
  1104. dest[1] = G >> 22;
  1105. dest[2] = R >> 22;
  1106. dest[3] = hasAlpha ? A : 255;
  1107. break;
  1108. }
  1109. dest += step;
  1110. }
  1111. }
  1112. #if CONFIG_SMALL
  1113. YUV2RGBWRAPPERX(yuv2, rgb_full, bgra32_full, PIX_FMT_BGRA, CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
  1114. YUV2RGBWRAPPERX(yuv2, rgb_full, abgr32_full, PIX_FMT_ABGR, CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
  1115. YUV2RGBWRAPPERX(yuv2, rgb_full, rgba32_full, PIX_FMT_RGBA, CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
  1116. YUV2RGBWRAPPERX(yuv2, rgb_full, argb32_full, PIX_FMT_ARGB, CONFIG_SWSCALE_ALPHA && c->alpPixBuf)
  1117. #else
  1118. #if CONFIG_SWSCALE_ALPHA
  1119. YUV2RGBWRAPPERX(yuv2, rgb_full, bgra32_full, PIX_FMT_BGRA, 1)
  1120. YUV2RGBWRAPPERX(yuv2, rgb_full, abgr32_full, PIX_FMT_ABGR, 1)
  1121. YUV2RGBWRAPPERX(yuv2, rgb_full, rgba32_full, PIX_FMT_RGBA, 1)
  1122. YUV2RGBWRAPPERX(yuv2, rgb_full, argb32_full, PIX_FMT_ARGB, 1)
  1123. #endif
  1124. YUV2RGBWRAPPERX(yuv2, rgb_full, bgrx32_full, PIX_FMT_BGRA, 0)
  1125. YUV2RGBWRAPPERX(yuv2, rgb_full, xbgr32_full, PIX_FMT_ABGR, 0)
  1126. YUV2RGBWRAPPERX(yuv2, rgb_full, rgbx32_full, PIX_FMT_RGBA, 0)
  1127. YUV2RGBWRAPPERX(yuv2, rgb_full, xrgb32_full, PIX_FMT_ARGB, 0)
  1128. #endif
  1129. YUV2RGBWRAPPERX(yuv2, rgb_full, bgr24_full, PIX_FMT_BGR24, 0)
  1130. YUV2RGBWRAPPERX(yuv2, rgb_full, rgb24_full, PIX_FMT_RGB24, 0)
  1131. void ff_sws_init_output_funcs(SwsContext *c,
  1132. yuv2planar1_fn *yuv2plane1,
  1133. yuv2planarX_fn *yuv2planeX,
  1134. yuv2interleavedX_fn *yuv2nv12cX,
  1135. yuv2packed1_fn *yuv2packed1,
  1136. yuv2packed2_fn *yuv2packed2,
  1137. yuv2packedX_fn *yuv2packedX)
  1138. {
  1139. enum PixelFormat dstFormat = c->dstFormat;
  1140. if (is16BPS(dstFormat)) {
  1141. *yuv2planeX = isBE(dstFormat) ? yuv2planeX_16BE_c : yuv2planeX_16LE_c;
  1142. *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_16BE_c : yuv2plane1_16LE_c;
  1143. } else if (is9_OR_10BPS(dstFormat)) {
  1144. if (av_pix_fmt_descriptors[dstFormat].comp[0].depth_minus1 == 8) {
  1145. *yuv2planeX = isBE(dstFormat) ? yuv2planeX_9BE_c : yuv2planeX_9LE_c;
  1146. *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_9BE_c : yuv2plane1_9LE_c;
  1147. } else {
  1148. *yuv2planeX = isBE(dstFormat) ? yuv2planeX_10BE_c : yuv2planeX_10LE_c;
  1149. *yuv2plane1 = isBE(dstFormat) ? yuv2plane1_10BE_c : yuv2plane1_10LE_c;
  1150. }
  1151. } else {
  1152. *yuv2plane1 = yuv2plane1_8_c;
  1153. *yuv2planeX = yuv2planeX_8_c;
  1154. if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21)
  1155. *yuv2nv12cX = yuv2nv12cX_c;
  1156. }
  1157. if(c->flags & SWS_FULL_CHR_H_INT) {
  1158. switch (dstFormat) {
  1159. case PIX_FMT_RGBA:
  1160. #if CONFIG_SMALL
  1161. *yuv2packedX = yuv2rgba32_full_X_c;
  1162. #else
  1163. #if CONFIG_SWSCALE_ALPHA
  1164. if (c->alpPixBuf) {
  1165. *yuv2packedX = yuv2rgba32_full_X_c;
  1166. } else
  1167. #endif /* CONFIG_SWSCALE_ALPHA */
  1168. {
  1169. *yuv2packedX = yuv2rgbx32_full_X_c;
  1170. }
  1171. #endif /* !CONFIG_SMALL */
  1172. break;
  1173. case PIX_FMT_ARGB:
  1174. #if CONFIG_SMALL
  1175. *yuv2packedX = yuv2argb32_full_X_c;
  1176. #else
  1177. #if CONFIG_SWSCALE_ALPHA
  1178. if (c->alpPixBuf) {
  1179. *yuv2packedX = yuv2argb32_full_X_c;
  1180. } else
  1181. #endif /* CONFIG_SWSCALE_ALPHA */
  1182. {
  1183. *yuv2packedX = yuv2xrgb32_full_X_c;
  1184. }
  1185. #endif /* !CONFIG_SMALL */
  1186. break;
  1187. case PIX_FMT_BGRA:
  1188. #if CONFIG_SMALL
  1189. *yuv2packedX = yuv2bgra32_full_X_c;
  1190. #else
  1191. #if CONFIG_SWSCALE_ALPHA
  1192. if (c->alpPixBuf) {
  1193. *yuv2packedX = yuv2bgra32_full_X_c;
  1194. } else
  1195. #endif /* CONFIG_SWSCALE_ALPHA */
  1196. {
  1197. *yuv2packedX = yuv2bgrx32_full_X_c;
  1198. }
  1199. #endif /* !CONFIG_SMALL */
  1200. break;
  1201. case PIX_FMT_ABGR:
  1202. #if CONFIG_SMALL
  1203. *yuv2packedX = yuv2abgr32_full_X_c;
  1204. #else
  1205. #if CONFIG_SWSCALE_ALPHA
  1206. if (c->alpPixBuf) {
  1207. *yuv2packedX = yuv2abgr32_full_X_c;
  1208. } else
  1209. #endif /* CONFIG_SWSCALE_ALPHA */
  1210. {
  1211. *yuv2packedX = yuv2xbgr32_full_X_c;
  1212. }
  1213. #endif /* !CONFIG_SMALL */
  1214. break;
  1215. case PIX_FMT_RGB24:
  1216. *yuv2packedX = yuv2rgb24_full_X_c;
  1217. break;
  1218. case PIX_FMT_BGR24:
  1219. *yuv2packedX = yuv2bgr24_full_X_c;
  1220. break;
  1221. }
  1222. } else {
  1223. switch (dstFormat) {
  1224. case PIX_FMT_RGB48LE:
  1225. *yuv2packed1 = yuv2rgb48le_1_c;
  1226. *yuv2packed2 = yuv2rgb48le_2_c;
  1227. *yuv2packedX = yuv2rgb48le_X_c;
  1228. break;
  1229. case PIX_FMT_RGB48BE:
  1230. *yuv2packed1 = yuv2rgb48be_1_c;
  1231. *yuv2packed2 = yuv2rgb48be_2_c;
  1232. *yuv2packedX = yuv2rgb48be_X_c;
  1233. break;
  1234. case PIX_FMT_BGR48LE:
  1235. *yuv2packed1 = yuv2bgr48le_1_c;
  1236. *yuv2packed2 = yuv2bgr48le_2_c;
  1237. *yuv2packedX = yuv2bgr48le_X_c;
  1238. break;
  1239. case PIX_FMT_BGR48BE:
  1240. *yuv2packed1 = yuv2bgr48be_1_c;
  1241. *yuv2packed2 = yuv2bgr48be_2_c;
  1242. *yuv2packedX = yuv2bgr48be_X_c;
  1243. break;
  1244. case PIX_FMT_RGB32:
  1245. case PIX_FMT_BGR32:
  1246. #if CONFIG_SMALL
  1247. *yuv2packed1 = yuv2rgb32_1_c;
  1248. *yuv2packed2 = yuv2rgb32_2_c;
  1249. *yuv2packedX = yuv2rgb32_X_c;
  1250. #else
  1251. #if CONFIG_SWSCALE_ALPHA
  1252. if (c->alpPixBuf) {
  1253. *yuv2packed1 = yuv2rgba32_1_c;
  1254. *yuv2packed2 = yuv2rgba32_2_c;
  1255. *yuv2packedX = yuv2rgba32_X_c;
  1256. } else
  1257. #endif /* CONFIG_SWSCALE_ALPHA */
  1258. {
  1259. *yuv2packed1 = yuv2rgbx32_1_c;
  1260. *yuv2packed2 = yuv2rgbx32_2_c;
  1261. *yuv2packedX = yuv2rgbx32_X_c;
  1262. }
  1263. #endif /* !CONFIG_SMALL */
  1264. break;
  1265. case PIX_FMT_RGB32_1:
  1266. case PIX_FMT_BGR32_1:
  1267. #if CONFIG_SMALL
  1268. *yuv2packed1 = yuv2rgb32_1_1_c;
  1269. *yuv2packed2 = yuv2rgb32_1_2_c;
  1270. *yuv2packedX = yuv2rgb32_1_X_c;
  1271. #else
  1272. #if CONFIG_SWSCALE_ALPHA
  1273. if (c->alpPixBuf) {
  1274. *yuv2packed1 = yuv2rgba32_1_1_c;
  1275. *yuv2packed2 = yuv2rgba32_1_2_c;
  1276. *yuv2packedX = yuv2rgba32_1_X_c;
  1277. } else
  1278. #endif /* CONFIG_SWSCALE_ALPHA */
  1279. {
  1280. *yuv2packed1 = yuv2rgbx32_1_1_c;
  1281. *yuv2packed2 = yuv2rgbx32_1_2_c;
  1282. *yuv2packedX = yuv2rgbx32_1_X_c;
  1283. }
  1284. #endif /* !CONFIG_SMALL */
  1285. break;
  1286. case PIX_FMT_RGB24:
  1287. *yuv2packed1 = yuv2rgb24_1_c;
  1288. *yuv2packed2 = yuv2rgb24_2_c;
  1289. *yuv2packedX = yuv2rgb24_X_c;
  1290. break;
  1291. case PIX_FMT_BGR24:
  1292. *yuv2packed1 = yuv2bgr24_1_c;
  1293. *yuv2packed2 = yuv2bgr24_2_c;
  1294. *yuv2packedX = yuv2bgr24_X_c;
  1295. break;
  1296. case PIX_FMT_RGB565LE:
  1297. case PIX_FMT_RGB565BE:
  1298. case PIX_FMT_BGR565LE:
  1299. case PIX_FMT_BGR565BE:
  1300. *yuv2packed1 = yuv2rgb16_1_c;
  1301. *yuv2packed2 = yuv2rgb16_2_c;
  1302. *yuv2packedX = yuv2rgb16_X_c;
  1303. break;
  1304. case PIX_FMT_RGB555LE:
  1305. case PIX_FMT_RGB555BE:
  1306. case PIX_FMT_BGR555LE:
  1307. case PIX_FMT_BGR555BE:
  1308. *yuv2packed1 = yuv2rgb15_1_c;
  1309. *yuv2packed2 = yuv2rgb15_2_c;
  1310. *yuv2packedX = yuv2rgb15_X_c;
  1311. break;
  1312. case PIX_FMT_RGB444LE:
  1313. case PIX_FMT_RGB444BE:
  1314. case PIX_FMT_BGR444LE:
  1315. case PIX_FMT_BGR444BE:
  1316. *yuv2packed1 = yuv2rgb12_1_c;
  1317. *yuv2packed2 = yuv2rgb12_2_c;
  1318. *yuv2packedX = yuv2rgb12_X_c;
  1319. break;
  1320. case PIX_FMT_RGB8:
  1321. case PIX_FMT_BGR8:
  1322. *yuv2packed1 = yuv2rgb8_1_c;
  1323. *yuv2packed2 = yuv2rgb8_2_c;
  1324. *yuv2packedX = yuv2rgb8_X_c;
  1325. break;
  1326. case PIX_FMT_RGB4:
  1327. case PIX_FMT_BGR4:
  1328. *yuv2packed1 = yuv2rgb4_1_c;
  1329. *yuv2packed2 = yuv2rgb4_2_c;
  1330. *yuv2packedX = yuv2rgb4_X_c;
  1331. break;
  1332. case PIX_FMT_RGB4_BYTE:
  1333. case PIX_FMT_BGR4_BYTE:
  1334. *yuv2packed1 = yuv2rgb4b_1_c;
  1335. *yuv2packed2 = yuv2rgb4b_2_c;
  1336. *yuv2packedX = yuv2rgb4b_X_c;
  1337. break;
  1338. }
  1339. }
  1340. switch (dstFormat) {
  1341. case PIX_FMT_MONOWHITE:
  1342. *yuv2packed1 = yuv2monowhite_1_c;
  1343. *yuv2packed2 = yuv2monowhite_2_c;
  1344. *yuv2packedX = yuv2monowhite_X_c;
  1345. break;
  1346. case PIX_FMT_MONOBLACK:
  1347. *yuv2packed1 = yuv2monoblack_1_c;
  1348. *yuv2packed2 = yuv2monoblack_2_c;
  1349. *yuv2packedX = yuv2monoblack_X_c;
  1350. break;
  1351. case PIX_FMT_YUYV422:
  1352. *yuv2packed1 = yuv2yuyv422_1_c;
  1353. *yuv2packed2 = yuv2yuyv422_2_c;
  1354. *yuv2packedX = yuv2yuyv422_X_c;
  1355. break;
  1356. case PIX_FMT_UYVY422:
  1357. *yuv2packed1 = yuv2uyvy422_1_c;
  1358. *yuv2packed2 = yuv2uyvy422_2_c;
  1359. *yuv2packedX = yuv2uyvy422_X_c;
  1360. break;
  1361. }
  1362. }