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.

1302 lines
40KB

  1. /*
  2. * Misc image convertion routines
  3. * Copyright (c) 2001, 2002, 2003 Fabrice Bellard.
  4. *
  5. * This library is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2 of the License, or (at your option) any later version.
  9. *
  10. * This library is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with this library; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #include "avcodec.h"
  20. #include "dsputil.h"
  21. #ifdef USE_FASTMEMCPY
  22. #include "fastmemcpy.h"
  23. #endif
  24. #ifdef HAVE_MMX
  25. #include "i386/mmx.h"
  26. #endif
  27. typedef struct PixFmtInfo {
  28. const char *name;
  29. UINT8 nb_components; /* number of components in AVPicture array */
  30. UINT8 is_yuv : 1; /* true if YUV instead of RGB color space */
  31. UINT8 is_packed : 1; /* true if multiple components in same word */
  32. UINT8 is_paletted : 1; /* true if paletted */
  33. UINT8 is_alpha : 1; /* true if alpha can be specified */
  34. UINT8 is_gray : 1; /* true if gray or monochrome format */
  35. UINT8 x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
  36. UINT8 y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
  37. } PixFmtInfo;
  38. /* this table gives more information about formats */
  39. static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
  40. /* YUV formats */
  41. [PIX_FMT_YUV420P] = {
  42. name: "yuv420p",
  43. nb_components: 3, is_yuv: 1,
  44. x_chroma_shift: 1, y_chroma_shift: 1,
  45. },
  46. [PIX_FMT_YUV422P] = {
  47. name: "yuv422p",
  48. nb_components: 3, is_yuv: 1,
  49. x_chroma_shift: 1, y_chroma_shift: 0,
  50. },
  51. [PIX_FMT_YUV444P] = {
  52. name: "yuv444p",
  53. nb_components: 3, is_yuv: 1,
  54. x_chroma_shift: 0, y_chroma_shift: 0,
  55. },
  56. [PIX_FMT_YUV422] = {
  57. name: "yuv422",
  58. nb_components: 1, is_yuv: 1, is_packed: 1,
  59. x_chroma_shift: 1, y_chroma_shift: 0,
  60. },
  61. [PIX_FMT_YUV410P] = {
  62. name: "yuv410p",
  63. nb_components: 3, is_yuv: 1,
  64. x_chroma_shift: 2, y_chroma_shift: 2,
  65. },
  66. [PIX_FMT_YUV411P] = {
  67. name: "yuv411p",
  68. nb_components: 3, is_yuv: 1,
  69. x_chroma_shift: 2, y_chroma_shift: 0,
  70. },
  71. /* RGB formats */
  72. [PIX_FMT_RGB24] = {
  73. name: "rgb24",
  74. nb_components: 1, is_packed: 1,
  75. },
  76. [PIX_FMT_BGR24] = {
  77. name: "bgr24",
  78. nb_components: 1, is_packed: 1,
  79. },
  80. [PIX_FMT_RGBA32] = {
  81. name: "rgba32",
  82. nb_components: 1, is_packed: 1, is_alpha: 1,
  83. },
  84. [PIX_FMT_RGB565] = {
  85. name: "rgb565",
  86. nb_components: 1, is_packed: 1,
  87. },
  88. [PIX_FMT_RGB555] = {
  89. name: "rgb555",
  90. nb_components: 1, is_packed: 1, is_alpha : 1,
  91. },
  92. /* gray / mono formats */
  93. [PIX_FMT_GRAY8] = {
  94. name: "gray",
  95. nb_components: 1, is_gray: 1,
  96. },
  97. [PIX_FMT_MONOWHITE] = {
  98. name: "monow",
  99. nb_components: 1, is_packed: 1, is_gray: 1,
  100. },
  101. [PIX_FMT_MONOBLACK] = {
  102. name: "monob",
  103. nb_components: 1, is_packed: 1, is_gray: 1,
  104. },
  105. };
  106. void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
  107. {
  108. if (pix_fmt_info[pix_fmt].is_yuv) {
  109. *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
  110. *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
  111. } else {
  112. *h_shift=0;
  113. *v_shift=0;
  114. }
  115. }
  116. const char *avcodec_get_pix_fmt_name(int pix_fmt)
  117. {
  118. if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
  119. return "???";
  120. else
  121. return pix_fmt_info[pix_fmt].name;
  122. }
  123. /* XXX: totally non optimized */
  124. static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src,
  125. int width, int height)
  126. {
  127. UINT8 *lum, *cb, *cr;
  128. int x, y;
  129. const UINT8 *p;
  130. lum = dst->data[0];
  131. cb = dst->data[1];
  132. cr = dst->data[2];
  133. p = src->data[0];
  134. for(y=0;y<height;y+=2) {
  135. for(x=0;x<width;x+=2) {
  136. lum[0] = p[0];
  137. cb[0] = p[1];
  138. lum[1] = p[2];
  139. cr[0] = p[3];
  140. p += 4;
  141. lum += 2;
  142. cb++;
  143. cr++;
  144. }
  145. for(x=0;x<width;x+=2) {
  146. lum[0] = p[0];
  147. lum[1] = p[2];
  148. p += 4;
  149. lum += 2;
  150. }
  151. }
  152. }
  153. #define SCALEBITS 8
  154. #define ONE_HALF (1 << (SCALEBITS - 1))
  155. #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
  156. /* XXX: use generic filter ? */
  157. /* 1x2 -> 1x1 */
  158. static void shrink2(UINT8 *dst, int dst_wrap,
  159. UINT8 *src, int src_wrap,
  160. int width, int height)
  161. {
  162. int w;
  163. UINT8 *s1, *s2, *d;
  164. for(;height > 0; height--) {
  165. s1 = src;
  166. s2 = s1 + src_wrap;
  167. d = dst;
  168. for(w = width;w >= 4; w-=4) {
  169. d[0] = (s1[0] + s2[0]) >> 1;
  170. d[1] = (s1[1] + s2[1]) >> 1;
  171. d[2] = (s1[2] + s2[2]) >> 1;
  172. d[3] = (s1[3] + s2[3]) >> 1;
  173. s1 += 4;
  174. s2 += 4;
  175. d += 4;
  176. }
  177. for(;w > 0; w--) {
  178. d[0] = (s1[0] + s2[0]) >> 1;
  179. s1++;
  180. s2++;
  181. d++;
  182. }
  183. src += 2 * src_wrap;
  184. dst += dst_wrap;
  185. }
  186. }
  187. /* 2x2 -> 1x1 */
  188. static void shrink22(UINT8 *dst, int dst_wrap,
  189. UINT8 *src, int src_wrap,
  190. int width, int height)
  191. {
  192. int w;
  193. UINT8 *s1, *s2, *d;
  194. for(;height > 0; height--) {
  195. s1 = src;
  196. s2 = s1 + src_wrap;
  197. d = dst;
  198. for(w = width;w >= 4; w-=4) {
  199. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  200. d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
  201. d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
  202. d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
  203. s1 += 8;
  204. s2 += 8;
  205. d += 4;
  206. }
  207. for(;w > 0; w--) {
  208. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  209. s1 += 2;
  210. s2 += 2;
  211. d++;
  212. }
  213. src += 2 * src_wrap;
  214. dst += dst_wrap;
  215. }
  216. }
  217. /* 1x1 -> 2x2 */
  218. static void grow22(UINT8 *dst, int dst_wrap,
  219. UINT8 *src, int src_wrap,
  220. int width, int height)
  221. {
  222. int w;
  223. UINT8 *s1, *d;
  224. for(;height > 0; height--) {
  225. s1 = src;
  226. d = dst;
  227. for(w = width;w >= 4; w-=4) {
  228. d[1] = d[0] = s1[0];
  229. d[3] = d[2] = s1[1];
  230. s1 += 2;
  231. d += 4;
  232. }
  233. for(;w > 0; w--) {
  234. d[0] = s1[0];
  235. s1 ++;
  236. d++;
  237. }
  238. if (height%2)
  239. src += src_wrap;
  240. dst += dst_wrap;
  241. }
  242. }
  243. /* 1x2 -> 2x1 */
  244. static void conv411(UINT8 *dst, int dst_wrap,
  245. UINT8 *src, int src_wrap,
  246. int width, int height)
  247. {
  248. int w, c;
  249. UINT8 *s1, *s2, *d;
  250. for(;height > 0; height--) {
  251. s1 = src;
  252. s2 = src + src_wrap;
  253. d = dst;
  254. for(w = width;w > 0; w--) {
  255. c = (s1[0] + s2[0]) >> 1;
  256. d[0] = c;
  257. d[1] = c;
  258. s1++;
  259. s2++;
  260. d += 2;
  261. }
  262. src += src_wrap * 2;
  263. dst += dst_wrap;
  264. }
  265. }
  266. static void img_copy(UINT8 *dst, int dst_wrap,
  267. UINT8 *src, int src_wrap,
  268. int width, int height)
  269. {
  270. for(;height > 0; height--) {
  271. memcpy(dst, src, width);
  272. dst += dst_wrap;
  273. src += src_wrap;
  274. }
  275. }
  276. #define SCALE_BITS 10
  277. #define C_Y (76309 >> (16 - SCALE_BITS))
  278. #define C_RV (117504 >> (16 - SCALE_BITS))
  279. #define C_BU (138453 >> (16 - SCALE_BITS))
  280. #define C_GU (13954 >> (16 - SCALE_BITS))
  281. #define C_GV (34903 >> (16 - SCALE_BITS))
  282. #define YUV_TO_RGB2(r, g, b, y1)\
  283. {\
  284. y = (y1 - 16) * C_Y;\
  285. r = cm[(y + r_add) >> SCALE_BITS];\
  286. g = cm[(y + g_add) >> SCALE_BITS];\
  287. b = cm[(y + b_add) >> SCALE_BITS];\
  288. }
  289. /* XXX: no chroma interpolating is done */
  290. #define RGB_FUNCTIONS(rgb_name) \
  291. \
  292. static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
  293. int width, int height) \
  294. { \
  295. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \
  296. int w, y, cb, cr, r_add, g_add, b_add, width2; \
  297. UINT8 *cm = cropTbl + MAX_NEG_CROP; \
  298. unsigned int r, g, b; \
  299. \
  300. d = dst->data[0]; \
  301. y1_ptr = src->data[0]; \
  302. cb_ptr = src->data[1]; \
  303. cr_ptr = src->data[2]; \
  304. width2 = width >> 1; \
  305. for(;height > 0; height -= 2) { \
  306. d1 = d; \
  307. d2 = d + dst->linesize[0]; \
  308. y2_ptr = y1_ptr + src->linesize[0]; \
  309. for(w = width2; w > 0; w --) { \
  310. cb = cb_ptr[0] - 128; \
  311. cr = cr_ptr[0] - 128; \
  312. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  313. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  314. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  315. \
  316. /* output 4 pixels */ \
  317. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  318. RGB_OUT(d1, r, g, b); \
  319. \
  320. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  321. RGB_OUT(d1 + BPP, r, g, b); \
  322. \
  323. YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
  324. RGB_OUT(d2, r, g, b); \
  325. \
  326. YUV_TO_RGB2(r, g, b, y2_ptr[1]); \
  327. RGB_OUT(d2 + BPP, r, g, b); \
  328. \
  329. d1 += 2 * BPP; \
  330. d2 += 2 * BPP; \
  331. \
  332. y1_ptr += 2; \
  333. y2_ptr += 2; \
  334. cb_ptr++; \
  335. cr_ptr++; \
  336. } \
  337. d += 2 * dst->linesize[0]; \
  338. y1_ptr += 2 * src->linesize[0] - width; \
  339. cb_ptr += src->linesize[1] - width2; \
  340. cr_ptr += src->linesize[2] - width2; \
  341. } \
  342. } \
  343. \
  344. /* XXX: no chroma interpolating is done */ \
  345. static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
  346. int width, int height) \
  347. { \
  348. UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; \
  349. int w, y, cb, cr, r_add, g_add, b_add, width2; \
  350. UINT8 *cm = cropTbl + MAX_NEG_CROP; \
  351. unsigned int r, g, b; \
  352. \
  353. d = dst->data[0]; \
  354. y1_ptr = src->data[0]; \
  355. cb_ptr = src->data[1]; \
  356. cr_ptr = src->data[2]; \
  357. width2 = width >> 1; \
  358. for(;height > 0; height --) { \
  359. d1 = d; \
  360. for(w = width2; w > 0; w --) { \
  361. cb = cb_ptr[0] - 128; \
  362. cr = cr_ptr[0] - 128; \
  363. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  364. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  365. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  366. \
  367. /* output 2 pixels */ \
  368. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  369. RGB_OUT(d, r, g, b); \
  370. \
  371. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  372. RGB_OUT(d + BPP, r, g, b); \
  373. \
  374. d += 2 * BPP; \
  375. \
  376. y1_ptr += 2; \
  377. cb_ptr++; \
  378. cr_ptr++; \
  379. } \
  380. d += dst->linesize[0]; \
  381. y1_ptr += src->linesize[0] - width; \
  382. cb_ptr += src->linesize[1] - width2; \
  383. cr_ptr += src->linesize[2] - width2; \
  384. } \
  385. } \
  386. \
  387. static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \
  388. int width, int height) \
  389. { \
  390. int wrap, wrap3, x, y; \
  391. int r, g, b, r1, g1, b1; \
  392. UINT8 *lum, *cb, *cr; \
  393. const UINT8 *p; \
  394. \
  395. lum = dst->data[0]; \
  396. cb = dst->data[1]; \
  397. cr = dst->data[2]; \
  398. \
  399. wrap = width; \
  400. wrap3 = width * 3; \
  401. p = src->data[0]; \
  402. for(y=0;y<height;y+=2) { \
  403. for(x=0;x<width;x+=2) { \
  404. RGB_IN(r, g, b, p); \
  405. r1 = r; \
  406. g1 = g; \
  407. b1 = b; \
  408. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  409. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  410. RGB_IN(r, g, b, p + BPP); \
  411. r1 += r; \
  412. g1 += g; \
  413. b1 += b; \
  414. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  415. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  416. p += wrap3; \
  417. lum += wrap; \
  418. \
  419. RGB_IN(r, g, b, p); \
  420. r1 += r; \
  421. g1 += g; \
  422. b1 += b; \
  423. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  424. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  425. \
  426. RGB_IN(r, g, b, p + BPP); \
  427. r1 += r; \
  428. g1 += g; \
  429. b1 += b; \
  430. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  431. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  432. \
  433. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
  434. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> \
  435. (SCALEBITS + 2)) + 128; \
  436. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
  437. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> \
  438. (SCALEBITS + 2)) + 128; \
  439. \
  440. cb++; \
  441. cr++; \
  442. p += -wrap3 + 2 * 3; \
  443. lum += -wrap + 2; \
  444. } \
  445. p += wrap3; \
  446. lum += wrap; \
  447. } \
  448. }
  449. /* copy bit n to bits 0 ... n - 1 */
  450. static inline unsigned int bitcopy_n(unsigned int a, int n)
  451. {
  452. int mask;
  453. mask = (1 << n) - 1;
  454. return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
  455. }
  456. /* rgb555 handling */
  457. #define RGB_IN(r, g, b, s)\
  458. {\
  459. unsigned int v = ((UINT16 *)(s))[0];\
  460. r = bitcopy_n(v >> (10 - 3), 3);\
  461. g = bitcopy_n(v >> (5 - 3), 3);\
  462. b = bitcopy_n(v << 3, 3);\
  463. }
  464. #define RGB_OUT(d, r, g, b)\
  465. {\
  466. ((UINT16 *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
  467. }
  468. #define BPP 2
  469. RGB_FUNCTIONS(rgb555)
  470. #undef RGB_IN
  471. #undef RGB_OUT
  472. #undef BPP
  473. /* rgb565 handling */
  474. #define RGB_IN(r, g, b, s)\
  475. {\
  476. unsigned int v = ((UINT16 *)(s))[0];\
  477. r = bitcopy_n(v >> (11 - 3), 3);\
  478. g = bitcopy_n(v >> (5 - 2), 2);\
  479. b = bitcopy_n(v << 3, 3);\
  480. }
  481. #define RGB_OUT(d, r, g, b)\
  482. {\
  483. ((UINT16 *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
  484. }
  485. #define BPP 2
  486. RGB_FUNCTIONS(rgb565)
  487. #undef RGB_IN
  488. #undef RGB_OUT
  489. #undef BPP
  490. /* bgr24 handling */
  491. #define RGB_IN(r, g, b, s)\
  492. {\
  493. b = (s)[0];\
  494. g = (s)[1];\
  495. r = (s)[2];\
  496. }
  497. #define RGB_OUT(d, r, g, b)\
  498. {\
  499. (d)[0] = b;\
  500. (d)[1] = g;\
  501. (d)[2] = r;\
  502. }
  503. #define BPP 3
  504. RGB_FUNCTIONS(bgr24)
  505. #undef RGB_IN
  506. #undef RGB_OUT
  507. #undef BPP
  508. /* rgb24 handling */
  509. #define RGB_IN(r, g, b, s)\
  510. {\
  511. r = (s)[0];\
  512. g = (s)[1];\
  513. b = (s)[2];\
  514. }
  515. #define RGB_OUT(d, r, g, b)\
  516. {\
  517. (d)[0] = r;\
  518. (d)[1] = g;\
  519. (d)[2] = b;\
  520. }
  521. #define BPP 3
  522. RGB_FUNCTIONS(rgb24)
  523. #undef RGB_IN
  524. #undef RGB_OUT
  525. #undef BPP
  526. /* rgba32 handling */
  527. #define RGB_IN(r, g, b, s)\
  528. {\
  529. unsigned int v = ((UINT32 *)(s))[0];\
  530. r = (v >> 16) & 0xff;\
  531. g = (v >> 8) & 0xff;\
  532. b = v & 0xff;\
  533. }
  534. #define RGB_OUT(d, r, g, b)\
  535. {\
  536. ((UINT32 *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
  537. }
  538. #define BPP 4
  539. RGB_FUNCTIONS(rgba32)
  540. #undef RGB_IN
  541. #undef RGB_OUT
  542. #undef BPP
  543. static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src,
  544. int width, int height)
  545. {
  546. const unsigned char *p;
  547. unsigned char *q;
  548. int r, g, b, dst_wrap, src_wrap;
  549. int x, y;
  550. p = src->data[0];
  551. src_wrap = src->linesize[0] - 3 * width;
  552. q = dst->data[0];
  553. dst_wrap = dst->linesize[0] - 2 * width;
  554. for(y=0;y<height;y++) {
  555. for(x=0;x<width;x++) {
  556. r = p[0];
  557. g = p[1];
  558. b = p[2];
  559. ((unsigned short *)q)[0] =
  560. ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  561. q += 2;
  562. p += 3;
  563. }
  564. p += src_wrap;
  565. q += dst_wrap;
  566. }
  567. }
  568. /* NOTE: we also add a dummy alpha bit */
  569. static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
  570. int width, int height)
  571. {
  572. const unsigned char *p;
  573. unsigned char *q;
  574. int r, g, b, dst_wrap, src_wrap;
  575. int x, y;
  576. p = src->data[0];
  577. src_wrap = src->linesize[0] - 3 * width;
  578. q = dst->data[0];
  579. dst_wrap = dst->linesize[0] - 2 * width;
  580. for(y=0;y<height;y++) {
  581. for(x=0;x<width;x++) {
  582. r = p[0];
  583. g = p[1];
  584. b = p[2];
  585. ((unsigned short *)q)[0] =
  586. ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;
  587. q += 2;
  588. p += 3;
  589. }
  590. p += src_wrap;
  591. q += dst_wrap;
  592. }
  593. }
  594. static void rgb24_to_gray(AVPicture *dst, AVPicture *src,
  595. int width, int height)
  596. {
  597. const unsigned char *p;
  598. unsigned char *q;
  599. int r, g, b, dst_wrap, src_wrap;
  600. int x, y;
  601. p = src->data[0];
  602. src_wrap = src->linesize[0] - 3 * width;
  603. q = dst->data[0];
  604. dst_wrap = dst->linesize[0] - width;
  605. for(y=0;y<height;y++) {
  606. for(x=0;x<width;x++) {
  607. r = p[0];
  608. g = p[1];
  609. b = p[2];
  610. q[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  611. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  612. q++;
  613. p += 3;
  614. }
  615. p += src_wrap;
  616. q += dst_wrap;
  617. }
  618. }
  619. static void gray_to_rgb24(AVPicture *dst, AVPicture *src,
  620. int width, int height)
  621. {
  622. const unsigned char *p;
  623. unsigned char *q;
  624. int r, dst_wrap, src_wrap;
  625. int x, y;
  626. p = src->data[0];
  627. src_wrap = src->linesize[0] - width;
  628. q = dst->data[0];
  629. dst_wrap = dst->linesize[0] - 3 * width;
  630. for(y=0;y<height;y++) {
  631. for(x=0;x<width;x++) {
  632. r = p[0];
  633. q[0] = r;
  634. q[1] = r;
  635. q[2] = r;
  636. q += 3;
  637. p ++;
  638. }
  639. p += src_wrap;
  640. q += dst_wrap;
  641. }
  642. }
  643. static void monowhite_to_rgb24(AVPicture *dst, AVPicture *src,
  644. int width, int height)
  645. {
  646. const unsigned char *p;
  647. unsigned char *q;
  648. int v, dst_wrap, src_wrap;
  649. int y, w;
  650. p = src->data[0];
  651. src_wrap = src->linesize[0] - ((width + 7) >> 3);
  652. q = dst->data[0];
  653. dst_wrap = dst->linesize[0] - 3 * width;
  654. for(y=0;y<height;y++) {
  655. w = width;
  656. while (w >= 8) {
  657. v = *p++ ^ 0xff;
  658. q[0] = q[1] = q[2] = -(v >> 7); q += 3;
  659. q[0] = q[1] = q[2] = -((v >> 6) & 1); q += 3;
  660. q[0] = q[1] = q[2] = -((v >> 5) & 1); q += 3;
  661. q[0] = q[1] = q[2] = -((v >> 4) & 1); q += 3;
  662. q[0] = q[1] = q[2] = -((v >> 3) & 1); q += 3;
  663. q[0] = q[1] = q[2] = -((v >> 2) & 1); q += 3;
  664. q[0] = q[1] = q[2] = -((v >> 1) & 1); q += 3;
  665. q[0] = q[1] = q[2] = -((v >> 0) & 1); q += 3;
  666. w -= 8;
  667. }
  668. if (w > 0) {
  669. v = *p++ ^ 0xff;
  670. do {
  671. q[0] = q[1] = q[2] = -((v >> 7) & 1); q += 3;
  672. v <<= 1;
  673. } while (--w);
  674. }
  675. p += src_wrap;
  676. q += dst_wrap;
  677. }
  678. }
  679. static void monoblack_to_rgb24(AVPicture *dst, AVPicture *src,
  680. int width, int height)
  681. {
  682. const unsigned char *p;
  683. unsigned char *q;
  684. int v, dst_wrap, src_wrap;
  685. int y, w;
  686. p = src->data[0];
  687. src_wrap = src->linesize[0] - ((width + 7) >> 3);
  688. q = dst->data[0];
  689. dst_wrap = dst->linesize[0] - 3 * width;
  690. for(y=0;y<height;y++) {
  691. w = width;
  692. while (w >= 8) {
  693. v = *p++;
  694. q[0] = q[1] = q[2] = -(v >> 7); q += 3;
  695. q[0] = q[1] = q[2] = -((v >> 6) & 1); q += 3;
  696. q[0] = q[1] = q[2] = -((v >> 5) & 1); q += 3;
  697. q[0] = q[1] = q[2] = -((v >> 4) & 1); q += 3;
  698. q[0] = q[1] = q[2] = -((v >> 3) & 1); q += 3;
  699. q[0] = q[1] = q[2] = -((v >> 2) & 1); q += 3;
  700. q[0] = q[1] = q[2] = -((v >> 1) & 1); q += 3;
  701. q[0] = q[1] = q[2] = -((v >> 0) & 1); q += 3;
  702. w -= 8;
  703. }
  704. if (w > 0) {
  705. v = *p++;
  706. do {
  707. q[0] = q[1] = q[2] = -((v >> 7) & 1); q += 3;
  708. v <<= 1;
  709. } while (--w);
  710. }
  711. p += src_wrap;
  712. q += dst_wrap;
  713. }
  714. }
  715. typedef struct ConvertEntry {
  716. void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
  717. } ConvertEntry;
  718. /* add each new convertion function in this table */
  719. /* constraints;
  720. - all non YUV modes must convert at least to and from PIX_FMT_RGB24
  721. */
  722. static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
  723. [PIX_FMT_YUV420P] = {
  724. [PIX_FMT_RGB555] = {
  725. convert: yuv420p_to_rgb555
  726. },
  727. [PIX_FMT_RGB565] = {
  728. convert: yuv420p_to_rgb565
  729. },
  730. [PIX_FMT_BGR24] = {
  731. convert: yuv420p_to_bgr24
  732. },
  733. [PIX_FMT_RGB24] = {
  734. convert: yuv420p_to_rgb24
  735. },
  736. [PIX_FMT_RGBA32] = {
  737. convert: yuv420p_to_rgba32
  738. },
  739. },
  740. [PIX_FMT_YUV422P] = {
  741. [PIX_FMT_RGB555] = {
  742. convert: yuv422p_to_rgb555
  743. },
  744. [PIX_FMT_RGB565] = {
  745. convert: yuv422p_to_rgb565
  746. },
  747. [PIX_FMT_BGR24] = {
  748. convert: yuv422p_to_bgr24
  749. },
  750. [PIX_FMT_RGB24] = {
  751. convert: yuv422p_to_rgb24
  752. },
  753. [PIX_FMT_RGBA32] = {
  754. convert: yuv422p_to_rgba32
  755. },
  756. },
  757. [PIX_FMT_YUV422] = {
  758. [PIX_FMT_YUV420P] = {
  759. convert: yuv422_to_yuv420p,
  760. },
  761. },
  762. [PIX_FMT_RGB24] = {
  763. [PIX_FMT_YUV420P] = {
  764. convert: rgb24_to_yuv420p
  765. },
  766. [PIX_FMT_RGB565] = {
  767. convert: rgb24_to_rgb565
  768. },
  769. [PIX_FMT_RGB555] = {
  770. convert: rgb24_to_rgb555
  771. },
  772. [PIX_FMT_GRAY8] = {
  773. convert: rgb24_to_gray
  774. },
  775. },
  776. [PIX_FMT_RGBA32] = {
  777. [PIX_FMT_YUV420P] = {
  778. convert: rgba32_to_yuv420p
  779. },
  780. },
  781. [PIX_FMT_BGR24] = {
  782. [PIX_FMT_YUV420P] = {
  783. convert: bgr24_to_yuv420p
  784. },
  785. },
  786. [PIX_FMT_RGB555] = {
  787. [PIX_FMT_YUV420P] = {
  788. convert: rgb555_to_yuv420p
  789. },
  790. },
  791. [PIX_FMT_RGB565] = {
  792. [PIX_FMT_YUV420P] = {
  793. convert: rgb565_to_yuv420p
  794. },
  795. },
  796. [PIX_FMT_GRAY8] = {
  797. [PIX_FMT_RGB24] = {
  798. convert: gray_to_rgb24
  799. },
  800. },
  801. [PIX_FMT_MONOWHITE] = {
  802. [PIX_FMT_RGB24] = {
  803. convert: monowhite_to_rgb24
  804. },
  805. },
  806. [PIX_FMT_MONOBLACK] = {
  807. [PIX_FMT_RGB24] = {
  808. convert: monoblack_to_rgb24
  809. },
  810. },
  811. };
  812. static int avpicture_alloc(AVPicture *picture,
  813. int pix_fmt, int width, int height)
  814. {
  815. int size;
  816. void *ptr;
  817. size = avpicture_get_size(pix_fmt, width, height);
  818. if (size < 0)
  819. goto fail;
  820. ptr = av_malloc(size);
  821. if (!ptr)
  822. goto fail;
  823. avpicture_fill(picture, ptr, pix_fmt, width, height);
  824. return 0;
  825. fail:
  826. memset(picture, 0, sizeof(AVPicture));
  827. return -1;
  828. }
  829. static void avpicture_free(AVPicture *picture)
  830. {
  831. free(picture->data[0]);
  832. }
  833. /* XXX: always use linesize. Return -1 if not supported */
  834. int img_convert(AVPicture *dst, int dst_pix_fmt,
  835. AVPicture *src, int src_pix_fmt,
  836. int src_width, int src_height)
  837. {
  838. int i, ret, dst_width, dst_height;
  839. PixFmtInfo *src_pix, *dst_pix;
  840. ConvertEntry *ce;
  841. AVPicture tmp1, *tmp = &tmp1;
  842. if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
  843. dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
  844. return -1;
  845. if (src_width <= 0 || src_height <= 0)
  846. return 0;
  847. dst_width = src_width;
  848. dst_height = src_height;
  849. dst_pix = &pix_fmt_info[dst_pix_fmt];
  850. src_pix = &pix_fmt_info[src_pix_fmt];
  851. if (src_pix_fmt == dst_pix_fmt) {
  852. /* same format: just copy */
  853. for(i = 0; i < dst_pix->nb_components; i++) {
  854. int w, h;
  855. w = dst_width;
  856. h = dst_height;
  857. if (dst_pix->is_yuv && (i == 1 || i == 2)) {
  858. w >>= dst_pix->x_chroma_shift;
  859. h >>= dst_pix->y_chroma_shift;
  860. }
  861. img_copy(dst->data[i], dst->linesize[i],
  862. src->data[i], src->linesize[i],
  863. w, h);
  864. }
  865. return 0;
  866. }
  867. ce = &convert_table[src_pix_fmt][dst_pix_fmt];
  868. if (ce->convert) {
  869. /* specific convertion routine */
  870. ce->convert(dst, src, dst_width, dst_height);
  871. return 0;
  872. }
  873. /* if both format are not YUV, try to use RGB24 as common
  874. format */
  875. if (!dst_pix->is_yuv && !src_pix->is_yuv) {
  876. if (avpicture_alloc(tmp, PIX_FMT_RGB24, dst_width, dst_height) < 0)
  877. return -1;
  878. ret = -1;
  879. if (img_convert(tmp, PIX_FMT_RGB24,
  880. src, src_pix_fmt, src_width, src_height) < 0)
  881. goto fail1;
  882. if (img_convert(dst, dst_pix_fmt,
  883. tmp, PIX_FMT_RGB24, dst_width, dst_height) < 0)
  884. goto fail1;
  885. ret = 0;
  886. fail1:
  887. avpicture_free(tmp);
  888. return ret;
  889. }
  890. /* gray to YUV */
  891. if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
  892. int w, h, y;
  893. uint8_t *d;
  894. img_copy(dst->data[0], dst->linesize[0],
  895. src->data[0], src->linesize[0],
  896. dst_width, dst_height);
  897. /* fill U and V with 128 */
  898. w = dst_width;
  899. h = dst_height;
  900. w >>= dst_pix->x_chroma_shift;
  901. h >>= dst_pix->y_chroma_shift;
  902. for(i = 1; i <= 2; i++) {
  903. d = dst->data[i];
  904. for(y = 0; y<h; y++) {
  905. memset(d, 128, 0);
  906. d += dst->linesize[i];
  907. }
  908. }
  909. return 0;
  910. }
  911. /* YUV to gray */
  912. if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
  913. img_copy(dst->data[0], dst->linesize[0],
  914. src->data[0], src->linesize[0],
  915. dst_width, dst_height);
  916. return 0;
  917. }
  918. /* YUV to YUV */
  919. if (dst_pix->is_yuv && src_pix->is_yuv) {
  920. int x_shift, y_shift, w, h;
  921. void (*resize_func)(UINT8 *dst, int dst_wrap,
  922. UINT8 *src, int src_wrap,
  923. int width, int height);
  924. /* compute chroma size of the smallest dimensions */
  925. w = dst_width;
  926. h = dst_height;
  927. if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
  928. w >>= dst_pix->x_chroma_shift;
  929. else
  930. w >>= src_pix->x_chroma_shift;
  931. if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
  932. h >>= dst_pix->y_chroma_shift;
  933. else
  934. h >>= src_pix->y_chroma_shift;
  935. x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
  936. y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
  937. if (x_shift == 0 && y_shift == 0) {
  938. resize_func = img_copy; /* should never happen */
  939. } else if (x_shift == 0 && y_shift == 1) {
  940. resize_func = shrink2;
  941. } else if (x_shift == 1 && y_shift == 1) {
  942. resize_func = shrink22;
  943. } else if (x_shift == -1 && y_shift == -1) {
  944. resize_func = grow22;
  945. } else if (x_shift == -1 && y_shift == 1) {
  946. resize_func = conv411;
  947. } else {
  948. /* currently not handled */
  949. return -1;
  950. }
  951. img_copy(dst->data[0], dst->linesize[0],
  952. src->data[0], src->linesize[0],
  953. dst_width, dst_height);
  954. for(i = 1;i <= 2; i++)
  955. resize_func(dst->data[1], dst->linesize[1],
  956. src->data[1], src->linesize[1],
  957. w, h);
  958. }
  959. /* cannot convert yet */
  960. return -1;
  961. }
  962. #ifdef HAVE_MMX
  963. #define DEINT_INPLACE_LINE_LUM \
  964. movd_m2r(lum_m4[0],mm0);\
  965. movd_m2r(lum_m3[0],mm1);\
  966. movd_m2r(lum_m2[0],mm2);\
  967. movd_m2r(lum_m1[0],mm3);\
  968. movd_m2r(lum[0],mm4);\
  969. punpcklbw_r2r(mm7,mm0);\
  970. movd_r2m(mm2,lum_m4[0]);\
  971. punpcklbw_r2r(mm7,mm1);\
  972. punpcklbw_r2r(mm7,mm2);\
  973. punpcklbw_r2r(mm7,mm3);\
  974. punpcklbw_r2r(mm7,mm4);\
  975. paddw_r2r(mm3,mm1);\
  976. psllw_i2r(1,mm2);\
  977. paddw_r2r(mm4,mm0);\
  978. psllw_i2r(2,mm1);\
  979. paddw_r2r(mm6,mm2);\
  980. paddw_r2r(mm2,mm1);\
  981. psubusw_r2r(mm0,mm1);\
  982. psrlw_i2r(3,mm1);\
  983. packuswb_r2r(mm7,mm1);\
  984. movd_r2m(mm1,lum_m2[0]);
  985. #define DEINT_LINE_LUM \
  986. movd_m2r(lum_m4[0],mm0);\
  987. movd_m2r(lum_m3[0],mm1);\
  988. movd_m2r(lum_m2[0],mm2);\
  989. movd_m2r(lum_m1[0],mm3);\
  990. movd_m2r(lum[0],mm4);\
  991. punpcklbw_r2r(mm7,mm0);\
  992. punpcklbw_r2r(mm7,mm1);\
  993. punpcklbw_r2r(mm7,mm2);\
  994. punpcklbw_r2r(mm7,mm3);\
  995. punpcklbw_r2r(mm7,mm4);\
  996. paddw_r2r(mm3,mm1);\
  997. psllw_i2r(1,mm2);\
  998. paddw_r2r(mm4,mm0);\
  999. psllw_i2r(2,mm1);\
  1000. paddw_r2r(mm6,mm2);\
  1001. paddw_r2r(mm2,mm1);\
  1002. psubusw_r2r(mm0,mm1);\
  1003. psrlw_i2r(3,mm1);\
  1004. packuswb_r2r(mm7,mm1);\
  1005. movd_r2m(mm1,dst[0]);
  1006. #endif
  1007. /* filter parameters: [-1 4 2 4 -1] // 8 */
  1008. static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  1009. int size)
  1010. {
  1011. #ifndef HAVE_MMX
  1012. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  1013. int sum;
  1014. for(;size > 0;size--) {
  1015. sum = -lum_m4[0];
  1016. sum += lum_m3[0] << 2;
  1017. sum += lum_m2[0] << 1;
  1018. sum += lum_m1[0] << 2;
  1019. sum += -lum[0];
  1020. dst[0] = cm[(sum + 4) >> 3];
  1021. lum_m4++;
  1022. lum_m3++;
  1023. lum_m2++;
  1024. lum_m1++;
  1025. lum++;
  1026. dst++;
  1027. }
  1028. #else
  1029. for (;size > 3; size-=4) {
  1030. DEINT_LINE_LUM
  1031. lum_m4+=4;
  1032. lum_m3+=4;
  1033. lum_m2+=4;
  1034. lum_m1+=4;
  1035. lum+=4;
  1036. dst+=4;
  1037. }
  1038. #endif
  1039. }
  1040. static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  1041. int size)
  1042. {
  1043. #ifndef HAVE_MMX
  1044. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  1045. int sum;
  1046. for(;size > 0;size--) {
  1047. sum = -lum_m4[0];
  1048. sum += lum_m3[0] << 2;
  1049. sum += lum_m2[0] << 1;
  1050. lum_m4[0]=lum_m2[0];
  1051. sum += lum_m1[0] << 2;
  1052. sum += -lum[0];
  1053. lum_m2[0] = cm[(sum + 4) >> 3];
  1054. lum_m4++;
  1055. lum_m3++;
  1056. lum_m2++;
  1057. lum_m1++;
  1058. lum++;
  1059. }
  1060. #else
  1061. for (;size > 3; size-=4) {
  1062. DEINT_INPLACE_LINE_LUM
  1063. lum_m4+=4;
  1064. lum_m3+=4;
  1065. lum_m2+=4;
  1066. lum_m1+=4;
  1067. lum+=4;
  1068. }
  1069. #endif
  1070. }
  1071. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  1072. top field is copied as is, but the bottom field is deinterlaced
  1073. against the top field. */
  1074. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  1075. UINT8 *src1, int src_wrap,
  1076. int width, int height)
  1077. {
  1078. UINT8 *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  1079. int y;
  1080. src_m2 = src1;
  1081. src_m1 = src1;
  1082. src_0=&src_m1[src_wrap];
  1083. src_p1=&src_0[src_wrap];
  1084. src_p2=&src_p1[src_wrap];
  1085. for(y=0;y<(height-2);y+=2) {
  1086. memcpy(dst,src_m1,width);
  1087. dst += dst_wrap;
  1088. deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  1089. src_m2 = src_0;
  1090. src_m1 = src_p1;
  1091. src_0 = src_p2;
  1092. src_p1 += 2*src_wrap;
  1093. src_p2 += 2*src_wrap;
  1094. dst += dst_wrap;
  1095. }
  1096. memcpy(dst,src_m1,width);
  1097. dst += dst_wrap;
  1098. /* do last line */
  1099. deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  1100. }
  1101. static void deinterlace_bottom_field_inplace(UINT8 *src1, int src_wrap,
  1102. int width, int height)
  1103. {
  1104. UINT8 *src_m1, *src_0, *src_p1, *src_p2;
  1105. int y;
  1106. UINT8 *buf;
  1107. buf = (UINT8*)av_malloc(width);
  1108. src_m1 = src1;
  1109. memcpy(buf,src_m1,width);
  1110. src_0=&src_m1[src_wrap];
  1111. src_p1=&src_0[src_wrap];
  1112. src_p2=&src_p1[src_wrap];
  1113. for(y=0;y<(height-2);y+=2) {
  1114. deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  1115. src_m1 = src_p1;
  1116. src_0 = src_p2;
  1117. src_p1 += 2*src_wrap;
  1118. src_p2 += 2*src_wrap;
  1119. }
  1120. /* do last line */
  1121. deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  1122. av_free(buf);
  1123. }
  1124. /* deinterlace - if not supported return -1 */
  1125. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  1126. int pix_fmt, int width, int height)
  1127. {
  1128. int i;
  1129. if (pix_fmt != PIX_FMT_YUV420P &&
  1130. pix_fmt != PIX_FMT_YUV422P &&
  1131. pix_fmt != PIX_FMT_YUV444P)
  1132. return -1;
  1133. if ((width & 3) != 0 || (height & 3) != 0)
  1134. return -1;
  1135. #ifdef HAVE_MMX
  1136. {
  1137. mmx_t rounder;
  1138. rounder.uw[0]=4;
  1139. rounder.uw[1]=4;
  1140. rounder.uw[2]=4;
  1141. rounder.uw[3]=4;
  1142. pxor_r2r(mm7,mm7);
  1143. movq_m2r(rounder,mm6);
  1144. }
  1145. #endif
  1146. for(i=0;i<3;i++) {
  1147. if (i == 1) {
  1148. switch(pix_fmt) {
  1149. case PIX_FMT_YUV420P:
  1150. width >>= 1;
  1151. height >>= 1;
  1152. break;
  1153. case PIX_FMT_YUV422P:
  1154. width >>= 1;
  1155. break;
  1156. default:
  1157. break;
  1158. }
  1159. }
  1160. if (src == dst) {
  1161. deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
  1162. width, height);
  1163. } else {
  1164. deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  1165. src->data[i], src->linesize[i],
  1166. width, height);
  1167. }
  1168. }
  1169. #ifdef HAVE_MMX
  1170. emms();
  1171. #endif
  1172. return 0;
  1173. }
  1174. #undef FIX