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.

1637 lines
56KB

  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. /* paletted formats */
  106. [PIX_FMT_PAL8] = {
  107. .name = "pal8",
  108. .nb_components = 1, .is_packed = 1, .is_paletted = 1,
  109. },
  110. };
  111. void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift)
  112. {
  113. if (pix_fmt_info[pix_fmt].is_yuv) {
  114. *h_shift = pix_fmt_info[pix_fmt].x_chroma_shift;
  115. *v_shift = pix_fmt_info[pix_fmt].y_chroma_shift;
  116. } else {
  117. *h_shift=0;
  118. *v_shift=0;
  119. }
  120. }
  121. const char *avcodec_get_pix_fmt_name(int pix_fmt)
  122. {
  123. if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB)
  124. return "???";
  125. else
  126. return pix_fmt_info[pix_fmt].name;
  127. }
  128. /* Picture field are filled with 'ptr' addresses. Also return size */
  129. int avpicture_fill(AVPicture *picture, UINT8 *ptr,
  130. int pix_fmt, int width, int height)
  131. {
  132. int size, w2, h2, size2;
  133. PixFmtInfo *pinfo;
  134. pinfo = &pix_fmt_info[pix_fmt];
  135. size = width * height;
  136. switch(pix_fmt) {
  137. case PIX_FMT_YUV420P:
  138. case PIX_FMT_YUV422P:
  139. case PIX_FMT_YUV444P:
  140. case PIX_FMT_YUV410P:
  141. case PIX_FMT_YUV411P:
  142. w2 = (width + (1 << pinfo->x_chroma_shift) - 1) >> pinfo->x_chroma_shift;
  143. h2 = (height + (1 << pinfo->y_chroma_shift) - 1) >> pinfo->y_chroma_shift;
  144. size2 = w2 * h2;
  145. picture->data[0] = ptr;
  146. picture->data[1] = picture->data[0] + size;
  147. picture->data[2] = picture->data[1] + size2;
  148. picture->linesize[0] = width;
  149. picture->linesize[1] = w2;
  150. picture->linesize[2] = w2;
  151. return size + 2 * size2;
  152. case PIX_FMT_RGB24:
  153. case PIX_FMT_BGR24:
  154. picture->data[0] = ptr;
  155. picture->data[1] = NULL;
  156. picture->data[2] = NULL;
  157. picture->linesize[0] = width * 3;
  158. return size * 3;
  159. case PIX_FMT_RGBA32:
  160. picture->data[0] = ptr;
  161. picture->data[1] = NULL;
  162. picture->data[2] = NULL;
  163. picture->linesize[0] = width * 4;
  164. return size * 4;
  165. case PIX_FMT_RGB555:
  166. case PIX_FMT_RGB565:
  167. case PIX_FMT_YUV422:
  168. picture->data[0] = ptr;
  169. picture->data[1] = NULL;
  170. picture->data[2] = NULL;
  171. picture->linesize[0] = width * 2;
  172. return size * 2;
  173. case PIX_FMT_GRAY8:
  174. picture->data[0] = ptr;
  175. picture->data[1] = NULL;
  176. picture->data[2] = NULL;
  177. picture->linesize[0] = width;
  178. return size;
  179. case PIX_FMT_MONOWHITE:
  180. case PIX_FMT_MONOBLACK:
  181. picture->data[0] = ptr;
  182. picture->data[1] = NULL;
  183. picture->data[2] = NULL;
  184. picture->linesize[0] = (width + 7) >> 3;
  185. return picture->linesize[0] * height;
  186. case PIX_FMT_PAL8:
  187. size2 = (size + 3) & ~3;
  188. picture->data[0] = ptr;
  189. picture->data[1] = ptr + size2; /* palette is stored here as 256 32 bit words */
  190. picture->data[2] = NULL;
  191. picture->linesize[0] = width;
  192. picture->linesize[1] = 4;
  193. return size2 + 256 * 4;
  194. default:
  195. picture->data[0] = NULL;
  196. picture->data[1] = NULL;
  197. picture->data[2] = NULL;
  198. picture->data[3] = NULL;
  199. return -1;
  200. }
  201. }
  202. int avpicture_get_size(int pix_fmt, int width, int height)
  203. {
  204. AVPicture dummy_pict;
  205. return avpicture_fill(&dummy_pict, NULL, pix_fmt, width, height);
  206. }
  207. /* XXX: totally non optimized */
  208. static void yuv422_to_yuv420p(AVPicture *dst, AVPicture *src,
  209. int width, int height)
  210. {
  211. UINT8 *lum, *cb, *cr;
  212. int x, y;
  213. const UINT8 *p;
  214. lum = dst->data[0];
  215. cb = dst->data[1];
  216. cr = dst->data[2];
  217. p = src->data[0];
  218. for(y=0;y<height;y+=2) {
  219. for(x=0;x<width;x+=2) {
  220. lum[0] = p[0];
  221. cb[0] = p[1];
  222. lum[1] = p[2];
  223. cr[0] = p[3];
  224. p += 4;
  225. lum += 2;
  226. cb++;
  227. cr++;
  228. }
  229. for(x=0;x<width;x+=2) {
  230. lum[0] = p[0];
  231. lum[1] = p[2];
  232. p += 4;
  233. lum += 2;
  234. }
  235. }
  236. }
  237. #define SCALEBITS 8
  238. #define ONE_HALF (1 << (SCALEBITS - 1))
  239. #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
  240. /* XXX: use generic filter ? */
  241. /* 1x2 -> 1x1 */
  242. static void shrink2(UINT8 *dst, int dst_wrap,
  243. UINT8 *src, int src_wrap,
  244. int width, int height)
  245. {
  246. int w;
  247. UINT8 *s1, *s2, *d;
  248. for(;height > 0; height--) {
  249. s1 = src;
  250. s2 = s1 + src_wrap;
  251. d = dst;
  252. for(w = width;w >= 4; w-=4) {
  253. d[0] = (s1[0] + s2[0]) >> 1;
  254. d[1] = (s1[1] + s2[1]) >> 1;
  255. d[2] = (s1[2] + s2[2]) >> 1;
  256. d[3] = (s1[3] + s2[3]) >> 1;
  257. s1 += 4;
  258. s2 += 4;
  259. d += 4;
  260. }
  261. for(;w > 0; w--) {
  262. d[0] = (s1[0] + s2[0]) >> 1;
  263. s1++;
  264. s2++;
  265. d++;
  266. }
  267. src += 2 * src_wrap;
  268. dst += dst_wrap;
  269. }
  270. }
  271. /* 2x2 -> 1x1 */
  272. static void shrink22(UINT8 *dst, int dst_wrap,
  273. UINT8 *src, int src_wrap,
  274. int width, int height)
  275. {
  276. int w;
  277. UINT8 *s1, *s2, *d;
  278. for(;height > 0; height--) {
  279. s1 = src;
  280. s2 = s1 + src_wrap;
  281. d = dst;
  282. for(w = width;w >= 4; w-=4) {
  283. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  284. d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
  285. d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
  286. d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
  287. s1 += 8;
  288. s2 += 8;
  289. d += 4;
  290. }
  291. for(;w > 0; w--) {
  292. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  293. s1 += 2;
  294. s2 += 2;
  295. d++;
  296. }
  297. src += 2 * src_wrap;
  298. dst += dst_wrap;
  299. }
  300. }
  301. /* 1x1 -> 2x2 */
  302. static void grow22(UINT8 *dst, int dst_wrap,
  303. UINT8 *src, int src_wrap,
  304. int width, int height)
  305. {
  306. int w;
  307. UINT8 *s1, *d;
  308. for(;height > 0; height--) {
  309. s1 = src;
  310. d = dst;
  311. for(w = width;w >= 4; w-=4) {
  312. d[1] = d[0] = s1[0];
  313. d[3] = d[2] = s1[1];
  314. s1 += 2;
  315. d += 4;
  316. }
  317. for(;w > 0; w--) {
  318. d[0] = s1[0];
  319. s1 ++;
  320. d++;
  321. }
  322. if (height%2)
  323. src += src_wrap;
  324. dst += dst_wrap;
  325. }
  326. }
  327. /* 1x2 -> 2x1 */
  328. static void conv411(UINT8 *dst, int dst_wrap,
  329. UINT8 *src, int src_wrap,
  330. int width, int height)
  331. {
  332. int w, c;
  333. UINT8 *s1, *s2, *d;
  334. for(;height > 0; height--) {
  335. s1 = src;
  336. s2 = src + src_wrap;
  337. d = dst;
  338. for(w = width;w > 0; w--) {
  339. c = (s1[0] + s2[0]) >> 1;
  340. d[0] = c;
  341. d[1] = c;
  342. s1++;
  343. s2++;
  344. d += 2;
  345. }
  346. src += src_wrap * 2;
  347. dst += dst_wrap;
  348. }
  349. }
  350. static void img_copy(UINT8 *dst, int dst_wrap,
  351. UINT8 *src, int src_wrap,
  352. int width, int height)
  353. {
  354. for(;height > 0; height--) {
  355. memcpy(dst, src, width);
  356. dst += dst_wrap;
  357. src += src_wrap;
  358. }
  359. }
  360. #define SCALE_BITS 10
  361. #define C_Y (76309 >> (16 - SCALE_BITS))
  362. #define C_RV (117504 >> (16 - SCALE_BITS))
  363. #define C_BU (138453 >> (16 - SCALE_BITS))
  364. #define C_GU (13954 >> (16 - SCALE_BITS))
  365. #define C_GV (34903 >> (16 - SCALE_BITS))
  366. #define YUV_TO_RGB2(r, g, b, y1)\
  367. {\
  368. y = (y1 - 16) * C_Y;\
  369. r = cm[(y + r_add) >> SCALE_BITS];\
  370. g = cm[(y + g_add) >> SCALE_BITS];\
  371. b = cm[(y + b_add) >> SCALE_BITS];\
  372. }
  373. /* XXX: no chroma interpolating is done */
  374. #define RGB_FUNCTIONS(rgb_name) \
  375. \
  376. static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
  377. int width, int height) \
  378. { \
  379. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \
  380. int w, y, cb, cr, r_add, g_add, b_add, width2; \
  381. UINT8 *cm = cropTbl + MAX_NEG_CROP; \
  382. unsigned int r, g, b; \
  383. \
  384. d = dst->data[0]; \
  385. y1_ptr = src->data[0]; \
  386. cb_ptr = src->data[1]; \
  387. cr_ptr = src->data[2]; \
  388. width2 = (width + 1) >> 1; \
  389. for(;height >= 2; height -= 2) { \
  390. d1 = d; \
  391. d2 = d + dst->linesize[0]; \
  392. y2_ptr = y1_ptr + src->linesize[0]; \
  393. for(w = width; w >= 2; w -= 2) { \
  394. cb = cb_ptr[0] - 128; \
  395. cr = cr_ptr[0] - 128; \
  396. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  397. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  398. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  399. \
  400. /* output 4 pixels */ \
  401. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  402. RGB_OUT(d1, r, g, b); \
  403. \
  404. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  405. RGB_OUT(d1 + BPP, r, g, b); \
  406. \
  407. YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
  408. RGB_OUT(d2, r, g, b); \
  409. \
  410. YUV_TO_RGB2(r, g, b, y2_ptr[1]); \
  411. RGB_OUT(d2 + BPP, r, g, b); \
  412. \
  413. d1 += 2 * BPP; \
  414. d2 += 2 * BPP; \
  415. \
  416. y1_ptr += 2; \
  417. y2_ptr += 2; \
  418. cb_ptr++; \
  419. cr_ptr++; \
  420. } \
  421. /* handle odd width */ \
  422. if (w) { \
  423. cb = cb_ptr[0] - 128; \
  424. cr = cr_ptr[0] - 128; \
  425. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  426. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  427. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  428. \
  429. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  430. RGB_OUT(d1, r, g, b); \
  431. \
  432. YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
  433. RGB_OUT(d2, r, g, b); \
  434. d1 += BPP; \
  435. d2 += BPP; \
  436. y1_ptr++; \
  437. y2_ptr++; \
  438. cb_ptr++; \
  439. cr_ptr++; \
  440. } \
  441. d += 2 * dst->linesize[0]; \
  442. y1_ptr += 2 * src->linesize[0] - width; \
  443. cb_ptr += src->linesize[1] - width2; \
  444. cr_ptr += src->linesize[2] - width2; \
  445. } \
  446. /* handle odd height */ \
  447. if (height) { \
  448. d1 = d; \
  449. for(w = width; w >= 2; w -= 2) { \
  450. cb = cb_ptr[0] - 128; \
  451. cr = cr_ptr[0] - 128; \
  452. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  453. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  454. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  455. \
  456. /* output 2 pixels */ \
  457. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  458. RGB_OUT(d1, r, g, b); \
  459. \
  460. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  461. RGB_OUT(d1 + BPP, r, g, b); \
  462. \
  463. d1 += 2 * BPP; \
  464. \
  465. y1_ptr += 2; \
  466. cb_ptr++; \
  467. cr_ptr++; \
  468. } \
  469. /* handle width */ \
  470. if (w) { \
  471. cb = cb_ptr[0] - 128; \
  472. cr = cr_ptr[0] - 128; \
  473. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  474. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  475. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  476. \
  477. /* output 2 pixels */ \
  478. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  479. RGB_OUT(d1, r, g, b); \
  480. d1 += BPP; \
  481. \
  482. y1_ptr++; \
  483. cb_ptr++; \
  484. cr_ptr++; \
  485. } \
  486. } \
  487. } \
  488. \
  489. /* XXX: no chroma interpolating is done */ \
  490. static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
  491. int width, int height) \
  492. { \
  493. UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; \
  494. int w, y, cb, cr, r_add, g_add, b_add, width2; \
  495. UINT8 *cm = cropTbl + MAX_NEG_CROP; \
  496. unsigned int r, g, b; \
  497. \
  498. d = dst->data[0]; \
  499. y1_ptr = src->data[0]; \
  500. cb_ptr = src->data[1]; \
  501. cr_ptr = src->data[2]; \
  502. width2 = (width + 1) >> 1; \
  503. for(;height > 0; height --) { \
  504. d1 = d; \
  505. for(w = width; w >= 2; w -= 2) { \
  506. cb = cb_ptr[0] - 128; \
  507. cr = cr_ptr[0] - 128; \
  508. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  509. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  510. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  511. \
  512. /* output 2 pixels */ \
  513. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  514. RGB_OUT(d1, r, g, b); \
  515. \
  516. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  517. RGB_OUT(d1 + BPP, r, g, b); \
  518. \
  519. d1 += 2 * BPP; \
  520. \
  521. y1_ptr += 2; \
  522. cb_ptr++; \
  523. cr_ptr++; \
  524. } \
  525. /* handle width */ \
  526. if (w) { \
  527. cb = cb_ptr[0] - 128; \
  528. cr = cr_ptr[0] - 128; \
  529. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  530. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  531. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  532. \
  533. /* output 2 pixels */ \
  534. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  535. RGB_OUT(d1, r, g, b); \
  536. d1 += BPP; \
  537. \
  538. y1_ptr++; \
  539. cb_ptr++; \
  540. cr_ptr++; \
  541. } \
  542. d += dst->linesize[0]; \
  543. y1_ptr += src->linesize[0] - width; \
  544. cb_ptr += src->linesize[1] - width2; \
  545. cr_ptr += src->linesize[2] - width2; \
  546. } \
  547. } \
  548. \
  549. static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \
  550. int width, int height) \
  551. { \
  552. int wrap, wrap3, x, y; \
  553. int r, g, b, r1, g1, b1; \
  554. UINT8 *lum, *cb, *cr; \
  555. const UINT8 *p; \
  556. \
  557. lum = dst->data[0]; \
  558. cb = dst->data[1]; \
  559. cr = dst->data[2]; \
  560. \
  561. wrap = dst->linesize[0]; \
  562. wrap3 = src->linesize[0]; \
  563. p = src->data[0]; \
  564. for(y=0;y<height;y+=2) { \
  565. for(x=0;x<width;x+=2) { \
  566. RGB_IN(r, g, b, p); \
  567. r1 = r; \
  568. g1 = g; \
  569. b1 = b; \
  570. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  571. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  572. RGB_IN(r, g, b, p + BPP); \
  573. r1 += r; \
  574. g1 += g; \
  575. b1 += b; \
  576. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  577. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  578. p += wrap3; \
  579. lum += wrap; \
  580. \
  581. RGB_IN(r, g, b, p); \
  582. r1 += r; \
  583. g1 += g; \
  584. b1 += b; \
  585. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  586. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  587. \
  588. RGB_IN(r, g, b, p + BPP); \
  589. r1 += r; \
  590. g1 += g; \
  591. b1 += b; \
  592. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  593. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  594. \
  595. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
  596. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> \
  597. (SCALEBITS + 2)) + 128; \
  598. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
  599. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> \
  600. (SCALEBITS + 2)) + 128; \
  601. \
  602. cb++; \
  603. cr++; \
  604. p += -wrap3 + 2 * BPP; \
  605. lum += -wrap + 2; \
  606. } \
  607. p += wrap3 + (wrap3 - width * BPP); \
  608. lum += wrap + (wrap - width); \
  609. cb += dst->linesize[1] - width / 2; \
  610. cr += dst->linesize[2] - width / 2; \
  611. } \
  612. } \
  613. \
  614. static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src, \
  615. int width, int height) \
  616. { \
  617. const unsigned char *p; \
  618. unsigned char *q; \
  619. int r, g, b, dst_wrap, src_wrap; \
  620. int x, y; \
  621. \
  622. p = src->data[0]; \
  623. src_wrap = src->linesize[0] - BPP * width; \
  624. \
  625. q = dst->data[0]; \
  626. dst_wrap = dst->linesize[0] - width; \
  627. \
  628. for(y=0;y<height;y++) { \
  629. for(x=0;x<width;x++) { \
  630. RGB_IN(r, g, b, p); \
  631. q[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  632. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  633. q++; \
  634. p += BPP; \
  635. } \
  636. p += src_wrap; \
  637. q += dst_wrap; \
  638. } \
  639. } \
  640. \
  641. static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
  642. int width, int height) \
  643. { \
  644. const unsigned char *p; \
  645. unsigned char *q; \
  646. int r, dst_wrap, src_wrap; \
  647. int x, y; \
  648. \
  649. p = src->data[0]; \
  650. src_wrap = src->linesize[0] - width; \
  651. \
  652. q = dst->data[0]; \
  653. dst_wrap = dst->linesize[0] - BPP * width; \
  654. \
  655. for(y=0;y<height;y++) { \
  656. for(x=0;x<width;x++) { \
  657. r = p[0]; \
  658. RGB_OUT(q, r, r, r); \
  659. q += BPP; \
  660. p ++; \
  661. } \
  662. p += src_wrap; \
  663. q += dst_wrap; \
  664. } \
  665. } \
  666. \
  667. static void pal8_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
  668. int width, int height) \
  669. { \
  670. const unsigned char *p; \
  671. unsigned char *q; \
  672. int r, g, b, dst_wrap, src_wrap; \
  673. int x, y; \
  674. uint32_t v;\
  675. const uint32_t *palette;\
  676. \
  677. p = src->data[0]; \
  678. src_wrap = src->linesize[0] - width; \
  679. palette = (uint32_t *)src->data[1];\
  680. \
  681. q = dst->data[0]; \
  682. dst_wrap = dst->linesize[0] - BPP * width; \
  683. \
  684. for(y=0;y<height;y++) { \
  685. for(x=0;x<width;x++) { \
  686. v = palette[p[0]];\
  687. r = (v >> 16) & 0xff;\
  688. g = (v >> 8) & 0xff;\
  689. b = (v) & 0xff;\
  690. RGB_OUT(q, r, g, b); \
  691. q += BPP; \
  692. p ++; \
  693. } \
  694. p += src_wrap; \
  695. q += dst_wrap; \
  696. } \
  697. }
  698. /* copy bit n to bits 0 ... n - 1 */
  699. static inline unsigned int bitcopy_n(unsigned int a, int n)
  700. {
  701. int mask;
  702. mask = (1 << n) - 1;
  703. return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
  704. }
  705. /* rgb555 handling */
  706. #define RGB_IN(r, g, b, s)\
  707. {\
  708. unsigned int v = ((UINT16 *)(s))[0];\
  709. r = bitcopy_n(v >> (10 - 3), 3);\
  710. g = bitcopy_n(v >> (5 - 3), 3);\
  711. b = bitcopy_n(v << 3, 3);\
  712. }
  713. #define RGB_OUT(d, r, g, b)\
  714. {\
  715. ((UINT16 *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
  716. }
  717. #define BPP 2
  718. RGB_FUNCTIONS(rgb555)
  719. #undef RGB_IN
  720. #undef RGB_OUT
  721. #undef BPP
  722. /* rgb565 handling */
  723. #define RGB_IN(r, g, b, s)\
  724. {\
  725. unsigned int v = ((UINT16 *)(s))[0];\
  726. r = bitcopy_n(v >> (11 - 3), 3);\
  727. g = bitcopy_n(v >> (5 - 2), 2);\
  728. b = bitcopy_n(v << 3, 3);\
  729. }
  730. #define RGB_OUT(d, r, g, b)\
  731. {\
  732. ((UINT16 *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
  733. }
  734. #define BPP 2
  735. RGB_FUNCTIONS(rgb565)
  736. #undef RGB_IN
  737. #undef RGB_OUT
  738. #undef BPP
  739. /* bgr24 handling */
  740. #define RGB_IN(r, g, b, s)\
  741. {\
  742. b = (s)[0];\
  743. g = (s)[1];\
  744. r = (s)[2];\
  745. }
  746. #define RGB_OUT(d, r, g, b)\
  747. {\
  748. (d)[0] = b;\
  749. (d)[1] = g;\
  750. (d)[2] = r;\
  751. }
  752. #define BPP 3
  753. RGB_FUNCTIONS(bgr24)
  754. #undef RGB_IN
  755. #undef RGB_OUT
  756. #undef BPP
  757. /* rgb24 handling */
  758. #define RGB_IN(r, g, b, s)\
  759. {\
  760. r = (s)[0];\
  761. g = (s)[1];\
  762. b = (s)[2];\
  763. }
  764. #define RGB_OUT(d, r, g, b)\
  765. {\
  766. (d)[0] = r;\
  767. (d)[1] = g;\
  768. (d)[2] = b;\
  769. }
  770. #define BPP 3
  771. RGB_FUNCTIONS(rgb24)
  772. #undef RGB_IN
  773. #undef RGB_OUT
  774. #undef BPP
  775. /* rgba32 handling */
  776. #define RGB_IN(r, g, b, s)\
  777. {\
  778. unsigned int v = ((UINT32 *)(s))[0];\
  779. r = (v >> 16) & 0xff;\
  780. g = (v >> 8) & 0xff;\
  781. b = v & 0xff;\
  782. }
  783. #define RGB_OUT(d, r, g, b)\
  784. {\
  785. ((UINT32 *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
  786. }
  787. #define BPP 4
  788. RGB_FUNCTIONS(rgba32)
  789. #undef RGB_IN
  790. #undef RGB_OUT
  791. #undef BPP
  792. static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src,
  793. int width, int height)
  794. {
  795. const unsigned char *p;
  796. unsigned char *q;
  797. int r, g, b, dst_wrap, src_wrap;
  798. int x, y;
  799. p = src->data[0];
  800. src_wrap = src->linesize[0] - 3 * width;
  801. q = dst->data[0];
  802. dst_wrap = dst->linesize[0] - 2 * width;
  803. for(y=0;y<height;y++) {
  804. for(x=0;x<width;x++) {
  805. r = p[0];
  806. g = p[1];
  807. b = p[2];
  808. ((unsigned short *)q)[0] =
  809. ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  810. q += 2;
  811. p += 3;
  812. }
  813. p += src_wrap;
  814. q += dst_wrap;
  815. }
  816. }
  817. /* NOTE: we also add a dummy alpha bit */
  818. static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
  819. int width, int height)
  820. {
  821. const unsigned char *p;
  822. unsigned char *q;
  823. int r, g, b, dst_wrap, src_wrap;
  824. int x, y;
  825. p = src->data[0];
  826. src_wrap = src->linesize[0] - 3 * width;
  827. q = dst->data[0];
  828. dst_wrap = dst->linesize[0] - 2 * width;
  829. for(y=0;y<height;y++) {
  830. for(x=0;x<width;x++) {
  831. r = p[0];
  832. g = p[1];
  833. b = p[2];
  834. ((unsigned short *)q)[0] =
  835. ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;
  836. q += 2;
  837. p += 3;
  838. }
  839. p += src_wrap;
  840. q += dst_wrap;
  841. }
  842. }
  843. static void mono_to_gray(AVPicture *dst, AVPicture *src,
  844. int width, int height, int xor_mask)
  845. {
  846. const unsigned char *p;
  847. unsigned char *q;
  848. int v, dst_wrap, src_wrap;
  849. int y, w;
  850. p = src->data[0];
  851. src_wrap = src->linesize[0] - ((width + 7) >> 3);
  852. q = dst->data[0];
  853. dst_wrap = dst->linesize[0] - width;
  854. for(y=0;y<height;y++) {
  855. w = width;
  856. while (w >= 8) {
  857. v = *p++ ^ xor_mask;
  858. q[0] = -(v >> 7);
  859. q[1] = -((v >> 6) & 1);
  860. q[2] = -((v >> 5) & 1);
  861. q[3] = -((v >> 4) & 1);
  862. q[4] = -((v >> 3) & 1);
  863. q[5] = -((v >> 2) & 1);
  864. q[6] = -((v >> 1) & 1);
  865. q[7] = -((v >> 0) & 1);
  866. w -= 8;
  867. q += 8;
  868. }
  869. if (w > 0) {
  870. v = *p++ ^ xor_mask;
  871. do {
  872. q[0] = -((v >> 7) & 1);
  873. q++;
  874. v <<= 1;
  875. } while (--w);
  876. }
  877. p += src_wrap;
  878. q += dst_wrap;
  879. }
  880. }
  881. static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
  882. int width, int height)
  883. {
  884. mono_to_gray(dst, src, width, height, 0xff);
  885. }
  886. static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
  887. int width, int height)
  888. {
  889. mono_to_gray(dst, src, width, height, 0x00);
  890. }
  891. static void gray_to_mono(AVPicture *dst, AVPicture *src,
  892. int width, int height, int xor_mask)
  893. {
  894. int n;
  895. const UINT8 *s;
  896. UINT8 *d;
  897. int j, b, v, n1, src_wrap, dst_wrap, y;
  898. s = src->data[0];
  899. src_wrap = src->linesize[0] - width;
  900. d = dst->data[0];
  901. dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
  902. printf("%d %d\n", width, height);
  903. for(y=0;y<height;y++) {
  904. n = width;
  905. while (n >= 8) {
  906. v = 0;
  907. for(j=0;j<8;j++) {
  908. b = s[0];
  909. s++;
  910. v = (v << 1) | (b >> 7);
  911. }
  912. d[0] = v ^ xor_mask;
  913. d++;
  914. n -= 8;
  915. }
  916. if (n > 0) {
  917. n1 = n;
  918. v = 0;
  919. while (n > 0) {
  920. b = s[0];
  921. s++;
  922. v = (v << 1) | (b >> 7);
  923. n--;
  924. }
  925. d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
  926. d++;
  927. }
  928. s += src_wrap;
  929. d += dst_wrap;
  930. }
  931. }
  932. static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
  933. int width, int height)
  934. {
  935. gray_to_mono(dst, src, width, height, 0xff);
  936. }
  937. static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
  938. int width, int height)
  939. {
  940. gray_to_mono(dst, src, width, height, 0x00);
  941. }
  942. /* this is maybe slow, but allows for extensions */
  943. static inline unsigned char gif_clut_index(UINT8 r, UINT8 g, UINT8 b)
  944. {
  945. return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
  946. }
  947. /* XXX: put jpeg quantize code instead */
  948. static void rgb24_to_pal8(AVPicture *dst, AVPicture *src,
  949. int width, int height)
  950. {
  951. const unsigned char *p;
  952. unsigned char *q;
  953. int r, g, b, dst_wrap, src_wrap;
  954. int x, y, i;
  955. static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
  956. uint32_t *pal;
  957. p = src->data[0];
  958. src_wrap = src->linesize[0] - 3 * width;
  959. q = dst->data[0];
  960. dst_wrap = dst->linesize[0] - width;
  961. for(y=0;y<height;y++) {
  962. for(x=0;x<width;x++) {
  963. r = p[0];
  964. g = p[1];
  965. b = p[2];
  966. q[0] = gif_clut_index(r, g, b);
  967. q++;
  968. p += 3;
  969. }
  970. p += src_wrap;
  971. q += dst_wrap;
  972. }
  973. /* build palette */
  974. pal = (uint32_t *)dst->data[1];
  975. i = 0;
  976. for(r = 0; r < 6; r++) {
  977. for(g = 0; g < 6; g++) {
  978. for(b = 0; b < 6; b++) {
  979. pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
  980. (pal_value[g] << 8) | pal_value[b];
  981. }
  982. }
  983. }
  984. while (i < 256)
  985. pal[i++] = 0;
  986. }
  987. typedef struct ConvertEntry {
  988. void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
  989. } ConvertEntry;
  990. /* add each new convertion function in this table */
  991. /* constraints;
  992. - all non YUV modes must convert at least to and from PIX_FMT_RGB24
  993. */
  994. static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
  995. [PIX_FMT_YUV420P] = {
  996. [PIX_FMT_RGB555] = {
  997. .convert = yuv420p_to_rgb555
  998. },
  999. [PIX_FMT_RGB565] = {
  1000. .convert = yuv420p_to_rgb565
  1001. },
  1002. [PIX_FMT_BGR24] = {
  1003. .convert = yuv420p_to_bgr24
  1004. },
  1005. [PIX_FMT_RGB24] = {
  1006. .convert = yuv420p_to_rgb24
  1007. },
  1008. [PIX_FMT_RGBA32] = {
  1009. .convert = yuv420p_to_rgba32
  1010. },
  1011. },
  1012. [PIX_FMT_YUV422P] = {
  1013. [PIX_FMT_RGB555] = {
  1014. .convert = yuv422p_to_rgb555
  1015. },
  1016. [PIX_FMT_RGB565] = {
  1017. .convert = yuv422p_to_rgb565
  1018. },
  1019. [PIX_FMT_BGR24] = {
  1020. .convert = yuv422p_to_bgr24
  1021. },
  1022. [PIX_FMT_RGB24] = {
  1023. .convert = yuv422p_to_rgb24
  1024. },
  1025. [PIX_FMT_RGBA32] = {
  1026. .convert = yuv422p_to_rgba32
  1027. },
  1028. },
  1029. [PIX_FMT_YUV422] = {
  1030. [PIX_FMT_YUV420P] = {
  1031. .convert = yuv422_to_yuv420p,
  1032. },
  1033. },
  1034. [PIX_FMT_RGB24] = {
  1035. [PIX_FMT_YUV420P] = {
  1036. .convert = rgb24_to_yuv420p
  1037. },
  1038. [PIX_FMT_RGB565] = {
  1039. .convert = rgb24_to_rgb565
  1040. },
  1041. [PIX_FMT_RGB555] = {
  1042. .convert = rgb24_to_rgb555
  1043. },
  1044. [PIX_FMT_GRAY8] = {
  1045. .convert = rgb24_to_gray
  1046. },
  1047. [PIX_FMT_PAL8] = {
  1048. .convert = rgb24_to_pal8
  1049. },
  1050. },
  1051. [PIX_FMT_RGBA32] = {
  1052. [PIX_FMT_YUV420P] = {
  1053. .convert = rgba32_to_yuv420p
  1054. },
  1055. [PIX_FMT_GRAY8] = {
  1056. .convert = rgba32_to_gray
  1057. },
  1058. },
  1059. [PIX_FMT_BGR24] = {
  1060. [PIX_FMT_YUV420P] = {
  1061. .convert = bgr24_to_yuv420p
  1062. },
  1063. [PIX_FMT_GRAY8] = {
  1064. .convert = bgr24_to_gray
  1065. },
  1066. },
  1067. [PIX_FMT_RGB555] = {
  1068. [PIX_FMT_YUV420P] = {
  1069. .convert = rgb555_to_yuv420p
  1070. },
  1071. [PIX_FMT_GRAY8] = {
  1072. .convert = rgb555_to_gray
  1073. },
  1074. },
  1075. [PIX_FMT_RGB565] = {
  1076. [PIX_FMT_YUV420P] = {
  1077. .convert = rgb565_to_yuv420p
  1078. },
  1079. [PIX_FMT_GRAY8] = {
  1080. .convert = rgb565_to_gray
  1081. },
  1082. },
  1083. [PIX_FMT_GRAY8] = {
  1084. [PIX_FMT_RGB555] = {
  1085. .convert = gray_to_rgb555
  1086. },
  1087. [PIX_FMT_RGB565] = {
  1088. .convert = gray_to_rgb565
  1089. },
  1090. [PIX_FMT_RGB24] = {
  1091. .convert = gray_to_rgb24
  1092. },
  1093. [PIX_FMT_BGR24] = {
  1094. .convert = gray_to_bgr24
  1095. },
  1096. [PIX_FMT_RGBA32] = {
  1097. .convert = gray_to_rgba32
  1098. },
  1099. [PIX_FMT_MONOWHITE] = {
  1100. .convert = gray_to_monowhite
  1101. },
  1102. [PIX_FMT_MONOBLACK] = {
  1103. .convert = gray_to_monoblack
  1104. },
  1105. },
  1106. [PIX_FMT_MONOWHITE] = {
  1107. [PIX_FMT_GRAY8] = {
  1108. .convert = monowhite_to_gray
  1109. },
  1110. },
  1111. [PIX_FMT_MONOBLACK] = {
  1112. [PIX_FMT_GRAY8] = {
  1113. .convert = monoblack_to_gray
  1114. },
  1115. },
  1116. [PIX_FMT_PAL8] = {
  1117. [PIX_FMT_RGB555] = {
  1118. .convert = pal8_to_rgb555
  1119. },
  1120. [PIX_FMT_RGB565] = {
  1121. .convert = pal8_to_rgb565
  1122. },
  1123. [PIX_FMT_BGR24] = {
  1124. .convert = pal8_to_bgr24
  1125. },
  1126. [PIX_FMT_RGB24] = {
  1127. .convert = pal8_to_rgb24
  1128. },
  1129. [PIX_FMT_RGBA32] = {
  1130. .convert = pal8_to_rgba32
  1131. },
  1132. },
  1133. };
  1134. static int avpicture_alloc(AVPicture *picture,
  1135. int pix_fmt, int width, int height)
  1136. {
  1137. int size;
  1138. void *ptr;
  1139. size = avpicture_get_size(pix_fmt, width, height);
  1140. if (size < 0)
  1141. goto fail;
  1142. ptr = av_malloc(size);
  1143. if (!ptr)
  1144. goto fail;
  1145. avpicture_fill(picture, ptr, pix_fmt, width, height);
  1146. return 0;
  1147. fail:
  1148. memset(picture, 0, sizeof(AVPicture));
  1149. return -1;
  1150. }
  1151. static void avpicture_free(AVPicture *picture)
  1152. {
  1153. av_free(picture->data[0]);
  1154. }
  1155. /* XXX: always use linesize. Return -1 if not supported */
  1156. int img_convert(AVPicture *dst, int dst_pix_fmt,
  1157. AVPicture *src, int src_pix_fmt,
  1158. int src_width, int src_height)
  1159. {
  1160. int i, ret, dst_width, dst_height, int_pix_fmt;
  1161. PixFmtInfo *src_pix, *dst_pix;
  1162. ConvertEntry *ce;
  1163. AVPicture tmp1, *tmp = &tmp1;
  1164. if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
  1165. dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
  1166. return -1;
  1167. if (src_width <= 0 || src_height <= 0)
  1168. return 0;
  1169. dst_width = src_width;
  1170. dst_height = src_height;
  1171. dst_pix = &pix_fmt_info[dst_pix_fmt];
  1172. src_pix = &pix_fmt_info[src_pix_fmt];
  1173. if (src_pix_fmt == dst_pix_fmt) {
  1174. /* XXX: incorrect */
  1175. /* same format: just copy */
  1176. for(i = 0; i < dst_pix->nb_components; i++) {
  1177. int w, h;
  1178. w = dst_width;
  1179. h = dst_height;
  1180. if (dst_pix->is_yuv && (i == 1 || i == 2)) {
  1181. w >>= dst_pix->x_chroma_shift;
  1182. h >>= dst_pix->y_chroma_shift;
  1183. }
  1184. img_copy(dst->data[i], dst->linesize[i],
  1185. src->data[i], src->linesize[i],
  1186. w, h);
  1187. }
  1188. return 0;
  1189. }
  1190. ce = &convert_table[src_pix_fmt][dst_pix_fmt];
  1191. if (ce->convert) {
  1192. /* specific convertion routine */
  1193. ce->convert(dst, src, dst_width, dst_height);
  1194. return 0;
  1195. }
  1196. /* gray to YUV */
  1197. if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
  1198. int w, h, y;
  1199. uint8_t *d;
  1200. img_copy(dst->data[0], dst->linesize[0],
  1201. src->data[0], src->linesize[0],
  1202. dst_width, dst_height);
  1203. /* fill U and V with 128 */
  1204. w = dst_width;
  1205. h = dst_height;
  1206. w >>= dst_pix->x_chroma_shift;
  1207. h >>= dst_pix->y_chroma_shift;
  1208. for(i = 1; i <= 2; i++) {
  1209. d = dst->data[i];
  1210. for(y = 0; y< h; y++) {
  1211. memset(d, 128, w);
  1212. d += dst->linesize[i];
  1213. }
  1214. }
  1215. return 0;
  1216. }
  1217. /* YUV to gray */
  1218. if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
  1219. img_copy(dst->data[0], dst->linesize[0],
  1220. src->data[0], src->linesize[0],
  1221. dst_width, dst_height);
  1222. return 0;
  1223. }
  1224. /* YUV to YUV */
  1225. if (dst_pix->is_yuv && src_pix->is_yuv) {
  1226. int x_shift, y_shift, w, h;
  1227. void (*resize_func)(UINT8 *dst, int dst_wrap,
  1228. UINT8 *src, int src_wrap,
  1229. int width, int height);
  1230. /* compute chroma size of the smallest dimensions */
  1231. w = dst_width;
  1232. h = dst_height;
  1233. if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
  1234. w >>= dst_pix->x_chroma_shift;
  1235. else
  1236. w >>= src_pix->x_chroma_shift;
  1237. if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
  1238. h >>= dst_pix->y_chroma_shift;
  1239. else
  1240. h >>= src_pix->y_chroma_shift;
  1241. x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
  1242. y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
  1243. if (x_shift == 0 && y_shift == 0) {
  1244. resize_func = img_copy; /* should never happen */
  1245. } else if (x_shift == 0 && y_shift == 1) {
  1246. resize_func = shrink2;
  1247. } else if (x_shift == 1 && y_shift == 1) {
  1248. resize_func = shrink22;
  1249. } else if (x_shift == -1 && y_shift == -1) {
  1250. resize_func = grow22;
  1251. } else if (x_shift == -1 && y_shift == 1) {
  1252. resize_func = conv411;
  1253. } else {
  1254. /* currently not handled */
  1255. return -1;
  1256. }
  1257. img_copy(dst->data[0], dst->linesize[0],
  1258. src->data[0], src->linesize[0],
  1259. dst_width, dst_height);
  1260. for(i = 1;i <= 2; i++)
  1261. resize_func(dst->data[i], dst->linesize[i],
  1262. src->data[i], src->linesize[i],
  1263. w, h);
  1264. return 0;
  1265. }
  1266. /* try to use an intermediate format */
  1267. if (src_pix_fmt == PIX_FMT_MONOWHITE ||
  1268. src_pix_fmt == PIX_FMT_MONOBLACK ||
  1269. dst_pix_fmt == PIX_FMT_MONOWHITE ||
  1270. dst_pix_fmt == PIX_FMT_MONOBLACK) {
  1271. int_pix_fmt = PIX_FMT_GRAY8;
  1272. } else {
  1273. int_pix_fmt = PIX_FMT_RGB24;
  1274. }
  1275. if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1276. return -1;
  1277. ret = -1;
  1278. if (img_convert(tmp, int_pix_fmt,
  1279. src, src_pix_fmt, src_width, src_height) < 0)
  1280. goto fail1;
  1281. if (img_convert(dst, dst_pix_fmt,
  1282. tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1283. goto fail1;
  1284. ret = 0;
  1285. fail1:
  1286. avpicture_free(tmp);
  1287. return ret;
  1288. }
  1289. #ifdef HAVE_MMX
  1290. #define DEINT_INPLACE_LINE_LUM \
  1291. movd_m2r(lum_m4[0],mm0);\
  1292. movd_m2r(lum_m3[0],mm1);\
  1293. movd_m2r(lum_m2[0],mm2);\
  1294. movd_m2r(lum_m1[0],mm3);\
  1295. movd_m2r(lum[0],mm4);\
  1296. punpcklbw_r2r(mm7,mm0);\
  1297. movd_r2m(mm2,lum_m4[0]);\
  1298. punpcklbw_r2r(mm7,mm1);\
  1299. punpcklbw_r2r(mm7,mm2);\
  1300. punpcklbw_r2r(mm7,mm3);\
  1301. punpcklbw_r2r(mm7,mm4);\
  1302. paddw_r2r(mm3,mm1);\
  1303. psllw_i2r(1,mm2);\
  1304. paddw_r2r(mm4,mm0);\
  1305. psllw_i2r(2,mm1);\
  1306. paddw_r2r(mm6,mm2);\
  1307. paddw_r2r(mm2,mm1);\
  1308. psubusw_r2r(mm0,mm1);\
  1309. psrlw_i2r(3,mm1);\
  1310. packuswb_r2r(mm7,mm1);\
  1311. movd_r2m(mm1,lum_m2[0]);
  1312. #define DEINT_LINE_LUM \
  1313. movd_m2r(lum_m4[0],mm0);\
  1314. movd_m2r(lum_m3[0],mm1);\
  1315. movd_m2r(lum_m2[0],mm2);\
  1316. movd_m2r(lum_m1[0],mm3);\
  1317. movd_m2r(lum[0],mm4);\
  1318. punpcklbw_r2r(mm7,mm0);\
  1319. punpcklbw_r2r(mm7,mm1);\
  1320. punpcklbw_r2r(mm7,mm2);\
  1321. punpcklbw_r2r(mm7,mm3);\
  1322. punpcklbw_r2r(mm7,mm4);\
  1323. paddw_r2r(mm3,mm1);\
  1324. psllw_i2r(1,mm2);\
  1325. paddw_r2r(mm4,mm0);\
  1326. psllw_i2r(2,mm1);\
  1327. paddw_r2r(mm6,mm2);\
  1328. paddw_r2r(mm2,mm1);\
  1329. psubusw_r2r(mm0,mm1);\
  1330. psrlw_i2r(3,mm1);\
  1331. packuswb_r2r(mm7,mm1);\
  1332. movd_r2m(mm1,dst[0]);
  1333. #endif
  1334. /* filter parameters: [-1 4 2 4 -1] // 8 */
  1335. static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  1336. int size)
  1337. {
  1338. #ifndef HAVE_MMX
  1339. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  1340. int sum;
  1341. for(;size > 0;size--) {
  1342. sum = -lum_m4[0];
  1343. sum += lum_m3[0] << 2;
  1344. sum += lum_m2[0] << 1;
  1345. sum += lum_m1[0] << 2;
  1346. sum += -lum[0];
  1347. dst[0] = cm[(sum + 4) >> 3];
  1348. lum_m4++;
  1349. lum_m3++;
  1350. lum_m2++;
  1351. lum_m1++;
  1352. lum++;
  1353. dst++;
  1354. }
  1355. #else
  1356. {
  1357. mmx_t rounder;
  1358. rounder.uw[0]=4;
  1359. rounder.uw[1]=4;
  1360. rounder.uw[2]=4;
  1361. rounder.uw[3]=4;
  1362. pxor_r2r(mm7,mm7);
  1363. movq_m2r(rounder,mm6);
  1364. }
  1365. for (;size > 3; size-=4) {
  1366. DEINT_LINE_LUM
  1367. lum_m4+=4;
  1368. lum_m3+=4;
  1369. lum_m2+=4;
  1370. lum_m1+=4;
  1371. lum+=4;
  1372. dst+=4;
  1373. }
  1374. #endif
  1375. }
  1376. static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  1377. int size)
  1378. {
  1379. #ifndef HAVE_MMX
  1380. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  1381. int sum;
  1382. for(;size > 0;size--) {
  1383. sum = -lum_m4[0];
  1384. sum += lum_m3[0] << 2;
  1385. sum += lum_m2[0] << 1;
  1386. lum_m4[0]=lum_m2[0];
  1387. sum += lum_m1[0] << 2;
  1388. sum += -lum[0];
  1389. lum_m2[0] = cm[(sum + 4) >> 3];
  1390. lum_m4++;
  1391. lum_m3++;
  1392. lum_m2++;
  1393. lum_m1++;
  1394. lum++;
  1395. }
  1396. #else
  1397. {
  1398. mmx_t rounder;
  1399. rounder.uw[0]=4;
  1400. rounder.uw[1]=4;
  1401. rounder.uw[2]=4;
  1402. rounder.uw[3]=4;
  1403. pxor_r2r(mm7,mm7);
  1404. movq_m2r(rounder,mm6);
  1405. }
  1406. for (;size > 3; size-=4) {
  1407. DEINT_INPLACE_LINE_LUM
  1408. lum_m4+=4;
  1409. lum_m3+=4;
  1410. lum_m2+=4;
  1411. lum_m1+=4;
  1412. lum+=4;
  1413. }
  1414. #endif
  1415. }
  1416. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  1417. top field is copied as is, but the bottom field is deinterlaced
  1418. against the top field. */
  1419. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  1420. UINT8 *src1, int src_wrap,
  1421. int width, int height)
  1422. {
  1423. UINT8 *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  1424. int y;
  1425. src_m2 = src1;
  1426. src_m1 = src1;
  1427. src_0=&src_m1[src_wrap];
  1428. src_p1=&src_0[src_wrap];
  1429. src_p2=&src_p1[src_wrap];
  1430. for(y=0;y<(height-2);y+=2) {
  1431. memcpy(dst,src_m1,width);
  1432. dst += dst_wrap;
  1433. deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  1434. src_m2 = src_0;
  1435. src_m1 = src_p1;
  1436. src_0 = src_p2;
  1437. src_p1 += 2*src_wrap;
  1438. src_p2 += 2*src_wrap;
  1439. dst += dst_wrap;
  1440. }
  1441. memcpy(dst,src_m1,width);
  1442. dst += dst_wrap;
  1443. /* do last line */
  1444. deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  1445. }
  1446. static void deinterlace_bottom_field_inplace(UINT8 *src1, int src_wrap,
  1447. int width, int height)
  1448. {
  1449. UINT8 *src_m1, *src_0, *src_p1, *src_p2;
  1450. int y;
  1451. UINT8 *buf;
  1452. buf = (UINT8*)av_malloc(width);
  1453. src_m1 = src1;
  1454. memcpy(buf,src_m1,width);
  1455. src_0=&src_m1[src_wrap];
  1456. src_p1=&src_0[src_wrap];
  1457. src_p2=&src_p1[src_wrap];
  1458. for(y=0;y<(height-2);y+=2) {
  1459. deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  1460. src_m1 = src_p1;
  1461. src_0 = src_p2;
  1462. src_p1 += 2*src_wrap;
  1463. src_p2 += 2*src_wrap;
  1464. }
  1465. /* do last line */
  1466. deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  1467. av_free(buf);
  1468. }
  1469. /* deinterlace - if not supported return -1 */
  1470. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  1471. int pix_fmt, int width, int height)
  1472. {
  1473. int i;
  1474. if (pix_fmt != PIX_FMT_YUV420P &&
  1475. pix_fmt != PIX_FMT_YUV422P &&
  1476. pix_fmt != PIX_FMT_YUV444P)
  1477. return -1;
  1478. if ((width & 3) != 0 || (height & 3) != 0)
  1479. return -1;
  1480. for(i=0;i<3;i++) {
  1481. if (i == 1) {
  1482. switch(pix_fmt) {
  1483. case PIX_FMT_YUV420P:
  1484. width >>= 1;
  1485. height >>= 1;
  1486. break;
  1487. case PIX_FMT_YUV422P:
  1488. width >>= 1;
  1489. break;
  1490. default:
  1491. break;
  1492. }
  1493. }
  1494. if (src == dst) {
  1495. deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
  1496. width, height);
  1497. } else {
  1498. deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  1499. src->data[i], src->linesize[i],
  1500. width, height);
  1501. }
  1502. }
  1503. #ifdef HAVE_MMX
  1504. emms();
  1505. #endif
  1506. return 0;
  1507. }
  1508. #undef FIX