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.

1644 lines
57KB

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