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.

1676 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_alpha = 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. width>>=1;
  339. for(;height > 0; height--) {
  340. s1 = src;
  341. s2 = src + src_wrap;
  342. d = dst;
  343. for(w = width;w > 0; w--) {
  344. c = (s1[0] + s2[0]) >> 1;
  345. d[0] = c;
  346. d[1] = c;
  347. s1++;
  348. s2++;
  349. d += 2;
  350. }
  351. src += src_wrap * 2;
  352. dst += dst_wrap;
  353. }
  354. }
  355. static void img_copy(uint8_t *dst, int dst_wrap,
  356. uint8_t *src, int src_wrap,
  357. int width, int height)
  358. {
  359. for(;height > 0; height--) {
  360. memcpy(dst, src, width);
  361. dst += dst_wrap;
  362. src += src_wrap;
  363. }
  364. }
  365. #define SCALE_BITS 10
  366. #define C_Y (76309 >> (16 - SCALE_BITS))
  367. #define C_RV (117504 >> (16 - SCALE_BITS))
  368. #define C_BU (138453 >> (16 - SCALE_BITS))
  369. #define C_GU (13954 >> (16 - SCALE_BITS))
  370. #define C_GV (34903 >> (16 - SCALE_BITS))
  371. #define YUV_TO_RGB2(r, g, b, y1)\
  372. {\
  373. y = (y1 - 16) * C_Y;\
  374. r = cm[(y + r_add) >> SCALE_BITS];\
  375. g = cm[(y + g_add) >> SCALE_BITS];\
  376. b = cm[(y + b_add) >> SCALE_BITS];\
  377. }
  378. /* XXX: no chroma interpolating is done */
  379. #define RGB_FUNCTIONS(rgb_name) \
  380. \
  381. static void yuv420p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
  382. int width, int height) \
  383. { \
  384. uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2; \
  385. int w, y, cb, cr, r_add, g_add, b_add, width2; \
  386. uint8_t *cm = cropTbl + MAX_NEG_CROP; \
  387. unsigned int r, g, b; \
  388. \
  389. d = dst->data[0]; \
  390. y1_ptr = src->data[0]; \
  391. cb_ptr = src->data[1]; \
  392. cr_ptr = src->data[2]; \
  393. width2 = (width + 1) >> 1; \
  394. for(;height >= 2; height -= 2) { \
  395. d1 = d; \
  396. d2 = d + dst->linesize[0]; \
  397. y2_ptr = y1_ptr + src->linesize[0]; \
  398. for(w = width; w >= 2; w -= 2) { \
  399. cb = cb_ptr[0] - 128; \
  400. cr = cr_ptr[0] - 128; \
  401. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  402. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  403. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  404. \
  405. /* output 4 pixels */ \
  406. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  407. RGB_OUT(d1, r, g, b); \
  408. \
  409. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  410. RGB_OUT(d1 + BPP, r, g, b); \
  411. \
  412. YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
  413. RGB_OUT(d2, r, g, b); \
  414. \
  415. YUV_TO_RGB2(r, g, b, y2_ptr[1]); \
  416. RGB_OUT(d2 + BPP, r, g, b); \
  417. \
  418. d1 += 2 * BPP; \
  419. d2 += 2 * BPP; \
  420. \
  421. y1_ptr += 2; \
  422. y2_ptr += 2; \
  423. cb_ptr++; \
  424. cr_ptr++; \
  425. } \
  426. /* handle odd width */ \
  427. if (w) { \
  428. cb = cb_ptr[0] - 128; \
  429. cr = cr_ptr[0] - 128; \
  430. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  431. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  432. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  433. \
  434. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  435. RGB_OUT(d1, r, g, b); \
  436. \
  437. YUV_TO_RGB2(r, g, b, y2_ptr[0]); \
  438. RGB_OUT(d2, r, g, b); \
  439. d1 += BPP; \
  440. d2 += BPP; \
  441. y1_ptr++; \
  442. y2_ptr++; \
  443. cb_ptr++; \
  444. cr_ptr++; \
  445. } \
  446. d += 2 * dst->linesize[0]; \
  447. y1_ptr += 2 * src->linesize[0] - width; \
  448. cb_ptr += src->linesize[1] - width2; \
  449. cr_ptr += src->linesize[2] - width2; \
  450. } \
  451. /* handle odd height */ \
  452. if (height) { \
  453. d1 = d; \
  454. for(w = width; w >= 2; w -= 2) { \
  455. cb = cb_ptr[0] - 128; \
  456. cr = cr_ptr[0] - 128; \
  457. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  458. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  459. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  460. \
  461. /* output 2 pixels */ \
  462. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  463. RGB_OUT(d1, r, g, b); \
  464. \
  465. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  466. RGB_OUT(d1 + BPP, r, g, b); \
  467. \
  468. d1 += 2 * BPP; \
  469. \
  470. y1_ptr += 2; \
  471. cb_ptr++; \
  472. cr_ptr++; \
  473. } \
  474. /* handle width */ \
  475. if (w) { \
  476. cb = cb_ptr[0] - 128; \
  477. cr = cr_ptr[0] - 128; \
  478. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  479. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  480. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  481. \
  482. /* output 2 pixels */ \
  483. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  484. RGB_OUT(d1, r, g, b); \
  485. d1 += BPP; \
  486. \
  487. y1_ptr++; \
  488. cb_ptr++; \
  489. cr_ptr++; \
  490. } \
  491. } \
  492. } \
  493. \
  494. /* XXX: no chroma interpolating is done */ \
  495. static void yuv422p_to_ ## rgb_name (AVPicture *dst, AVPicture *src, \
  496. int width, int height) \
  497. { \
  498. uint8_t *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1; \
  499. int w, y, cb, cr, r_add, g_add, b_add, width2; \
  500. uint8_t *cm = cropTbl + MAX_NEG_CROP; \
  501. unsigned int r, g, b; \
  502. \
  503. d = dst->data[0]; \
  504. y1_ptr = src->data[0]; \
  505. cb_ptr = src->data[1]; \
  506. cr_ptr = src->data[2]; \
  507. width2 = (width + 1) >> 1; \
  508. for(;height > 0; height --) { \
  509. d1 = d; \
  510. for(w = width; w >= 2; w -= 2) { \
  511. cb = cb_ptr[0] - 128; \
  512. cr = cr_ptr[0] - 128; \
  513. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  514. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  515. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  516. \
  517. /* output 2 pixels */ \
  518. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  519. RGB_OUT(d1, r, g, b); \
  520. \
  521. YUV_TO_RGB2(r, g, b, y1_ptr[1]); \
  522. RGB_OUT(d1 + BPP, r, g, b); \
  523. \
  524. d1 += 2 * BPP; \
  525. \
  526. y1_ptr += 2; \
  527. cb_ptr++; \
  528. cr_ptr++; \
  529. } \
  530. /* handle width */ \
  531. if (w) { \
  532. cb = cb_ptr[0] - 128; \
  533. cr = cr_ptr[0] - 128; \
  534. r_add = C_RV * cr + (1 << (SCALE_BITS - 1)); \
  535. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1)); \
  536. b_add = C_BU * cb + (1 << (SCALE_BITS - 1)); \
  537. \
  538. /* output 2 pixels */ \
  539. YUV_TO_RGB2(r, g, b, y1_ptr[0]); \
  540. RGB_OUT(d1, r, g, b); \
  541. d1 += BPP; \
  542. \
  543. y1_ptr++; \
  544. cb_ptr++; \
  545. cr_ptr++; \
  546. } \
  547. d += dst->linesize[0]; \
  548. y1_ptr += src->linesize[0] - width; \
  549. cb_ptr += src->linesize[1] - width2; \
  550. cr_ptr += src->linesize[2] - width2; \
  551. } \
  552. } \
  553. \
  554. static void rgb_name ## _to_yuv420p(AVPicture *dst, AVPicture *src, \
  555. int width, int height) \
  556. { \
  557. int wrap, wrap3, x, y; \
  558. int r, g, b, r1, g1, b1; \
  559. uint8_t *lum, *cb, *cr; \
  560. const uint8_t *p; \
  561. \
  562. lum = dst->data[0]; \
  563. cb = dst->data[1]; \
  564. cr = dst->data[2]; \
  565. \
  566. wrap = dst->linesize[0]; \
  567. wrap3 = src->linesize[0]; \
  568. p = src->data[0]; \
  569. for(y=0;y<height;y+=2) { \
  570. for(x=0;x<width;x+=2) { \
  571. RGB_IN(r, g, b, p); \
  572. r1 = r; \
  573. g1 = g; \
  574. b1 = b; \
  575. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  576. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  577. RGB_IN(r, g, b, p + BPP); \
  578. r1 += r; \
  579. g1 += g; \
  580. b1 += b; \
  581. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  582. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  583. p += wrap3; \
  584. lum += wrap; \
  585. \
  586. RGB_IN(r, g, b, p); \
  587. r1 += r; \
  588. g1 += g; \
  589. b1 += b; \
  590. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  591. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  592. \
  593. RGB_IN(r, g, b, p + BPP); \
  594. r1 += r; \
  595. g1 += g; \
  596. b1 += b; \
  597. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  598. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  599. \
  600. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \
  601. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> \
  602. (SCALEBITS + 2)) + 128; \
  603. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \
  604. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> \
  605. (SCALEBITS + 2)) + 128; \
  606. \
  607. cb++; \
  608. cr++; \
  609. p += -wrap3 + 2 * BPP; \
  610. lum += -wrap + 2; \
  611. } \
  612. p += wrap3 + (wrap3 - width * BPP); \
  613. lum += wrap + (wrap - width); \
  614. cb += dst->linesize[1] - width / 2; \
  615. cr += dst->linesize[2] - width / 2; \
  616. } \
  617. } \
  618. \
  619. static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src, \
  620. int width, int height) \
  621. { \
  622. const unsigned char *p; \
  623. unsigned char *q; \
  624. int r, g, b, dst_wrap, src_wrap; \
  625. int x, y; \
  626. \
  627. p = src->data[0]; \
  628. src_wrap = src->linesize[0] - BPP * width; \
  629. \
  630. q = dst->data[0]; \
  631. dst_wrap = dst->linesize[0] - width; \
  632. \
  633. for(y=0;y<height;y++) { \
  634. for(x=0;x<width;x++) { \
  635. RGB_IN(r, g, b, p); \
  636. q[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  637. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  638. q++; \
  639. p += BPP; \
  640. } \
  641. p += src_wrap; \
  642. q += dst_wrap; \
  643. } \
  644. } \
  645. \
  646. static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
  647. int width, int height) \
  648. { \
  649. const unsigned char *p; \
  650. unsigned char *q; \
  651. int r, dst_wrap, src_wrap; \
  652. int x, y; \
  653. \
  654. p = src->data[0]; \
  655. src_wrap = src->linesize[0] - width; \
  656. \
  657. q = dst->data[0]; \
  658. dst_wrap = dst->linesize[0] - BPP * width; \
  659. \
  660. for(y=0;y<height;y++) { \
  661. for(x=0;x<width;x++) { \
  662. r = p[0]; \
  663. RGB_OUT(q, r, r, r); \
  664. q += BPP; \
  665. p ++; \
  666. } \
  667. p += src_wrap; \
  668. q += dst_wrap; \
  669. } \
  670. } \
  671. \
  672. static void pal8_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
  673. int width, int height) \
  674. { \
  675. const unsigned char *p; \
  676. unsigned char *q; \
  677. int r, g, b, dst_wrap, src_wrap; \
  678. int x, y; \
  679. uint32_t v;\
  680. const uint32_t *palette;\
  681. \
  682. p = src->data[0]; \
  683. src_wrap = src->linesize[0] - width; \
  684. palette = (uint32_t *)src->data[1];\
  685. \
  686. q = dst->data[0]; \
  687. dst_wrap = dst->linesize[0] - BPP * width; \
  688. \
  689. for(y=0;y<height;y++) { \
  690. for(x=0;x<width;x++) { \
  691. v = palette[p[0]];\
  692. r = (v >> 16) & 0xff;\
  693. g = (v >> 8) & 0xff;\
  694. b = (v) & 0xff;\
  695. RGB_OUT(q, r, g, b); \
  696. q += BPP; \
  697. p ++; \
  698. } \
  699. p += src_wrap; \
  700. q += dst_wrap; \
  701. } \
  702. }
  703. /* copy bit n to bits 0 ... n - 1 */
  704. static inline unsigned int bitcopy_n(unsigned int a, int n)
  705. {
  706. int mask;
  707. mask = (1 << n) - 1;
  708. return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
  709. }
  710. /* rgb555 handling */
  711. #define RGB_IN(r, g, b, s)\
  712. {\
  713. unsigned int v = ((const uint16_t *)(s))[0];\
  714. r = bitcopy_n(v >> (10 - 3), 3);\
  715. g = bitcopy_n(v >> (5 - 3), 3);\
  716. b = bitcopy_n(v << 3, 3);\
  717. }
  718. #define RGB_OUT(d, r, g, b)\
  719. {\
  720. ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
  721. }
  722. #define BPP 2
  723. RGB_FUNCTIONS(rgb555)
  724. #undef RGB_IN
  725. #undef RGB_OUT
  726. #undef BPP
  727. /* rgb565 handling */
  728. #define RGB_IN(r, g, b, s)\
  729. {\
  730. unsigned int v = ((const uint16_t *)(s))[0];\
  731. r = bitcopy_n(v >> (11 - 3), 3);\
  732. g = bitcopy_n(v >> (5 - 2), 2);\
  733. b = bitcopy_n(v << 3, 3);\
  734. }
  735. #define RGB_OUT(d, r, g, b)\
  736. {\
  737. ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
  738. }
  739. #define BPP 2
  740. RGB_FUNCTIONS(rgb565)
  741. #undef RGB_IN
  742. #undef RGB_OUT
  743. #undef BPP
  744. /* bgr24 handling */
  745. #define RGB_IN(r, g, b, s)\
  746. {\
  747. b = (s)[0];\
  748. g = (s)[1];\
  749. r = (s)[2];\
  750. }
  751. #define RGB_OUT(d, r, g, b)\
  752. {\
  753. (d)[0] = b;\
  754. (d)[1] = g;\
  755. (d)[2] = r;\
  756. }
  757. #define BPP 3
  758. RGB_FUNCTIONS(bgr24)
  759. #undef RGB_IN
  760. #undef RGB_OUT
  761. #undef BPP
  762. /* rgb24 handling */
  763. #define RGB_IN(r, g, b, s)\
  764. {\
  765. r = (s)[0];\
  766. g = (s)[1];\
  767. b = (s)[2];\
  768. }
  769. #define RGB_OUT(d, r, g, b)\
  770. {\
  771. (d)[0] = r;\
  772. (d)[1] = g;\
  773. (d)[2] = b;\
  774. }
  775. #define BPP 3
  776. RGB_FUNCTIONS(rgb24)
  777. #undef RGB_IN
  778. #undef RGB_OUT
  779. #undef BPP
  780. /* rgba32 handling */
  781. #define RGB_IN(r, g, b, s)\
  782. {\
  783. unsigned int v = ((const uint32_t *)(s))[0];\
  784. r = (v >> 16) & 0xff;\
  785. g = (v >> 8) & 0xff;\
  786. b = v & 0xff;\
  787. }
  788. #define RGB_OUT(d, r, g, b)\
  789. {\
  790. ((uint32_t *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
  791. }
  792. #define BPP 4
  793. RGB_FUNCTIONS(rgba32)
  794. #undef RGB_IN
  795. #undef RGB_OUT
  796. #undef BPP
  797. static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src,
  798. int width, int height)
  799. {
  800. const unsigned char *p;
  801. unsigned char *q;
  802. int r, g, b, dst_wrap, src_wrap;
  803. int x, y;
  804. p = src->data[0];
  805. src_wrap = src->linesize[0] - 3 * width;
  806. q = dst->data[0];
  807. dst_wrap = dst->linesize[0] - 2 * width;
  808. for(y=0;y<height;y++) {
  809. for(x=0;x<width;x++) {
  810. r = p[0];
  811. g = p[1];
  812. b = p[2];
  813. ((unsigned short *)q)[0] =
  814. ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  815. q += 2;
  816. p += 3;
  817. }
  818. p += src_wrap;
  819. q += dst_wrap;
  820. }
  821. }
  822. /* NOTE: we also add a dummy alpha bit */
  823. static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
  824. int width, int height)
  825. {
  826. const unsigned char *p;
  827. unsigned char *q;
  828. int r, g, b, dst_wrap, src_wrap;
  829. int x, y;
  830. p = src->data[0];
  831. src_wrap = src->linesize[0] - 3 * width;
  832. q = dst->data[0];
  833. dst_wrap = dst->linesize[0] - 2 * width;
  834. for(y=0;y<height;y++) {
  835. for(x=0;x<width;x++) {
  836. r = p[0];
  837. g = p[1];
  838. b = p[2];
  839. ((unsigned short *)q)[0] =
  840. ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;
  841. q += 2;
  842. p += 3;
  843. }
  844. p += src_wrap;
  845. q += dst_wrap;
  846. }
  847. }
  848. static void mono_to_gray(AVPicture *dst, AVPicture *src,
  849. int width, int height, int xor_mask)
  850. {
  851. const unsigned char *p;
  852. unsigned char *q;
  853. int v, dst_wrap, src_wrap;
  854. int y, w;
  855. p = src->data[0];
  856. src_wrap = src->linesize[0] - ((width + 7) >> 3);
  857. q = dst->data[0];
  858. dst_wrap = dst->linesize[0] - width;
  859. for(y=0;y<height;y++) {
  860. w = width;
  861. while (w >= 8) {
  862. v = *p++ ^ xor_mask;
  863. q[0] = -(v >> 7);
  864. q[1] = -((v >> 6) & 1);
  865. q[2] = -((v >> 5) & 1);
  866. q[3] = -((v >> 4) & 1);
  867. q[4] = -((v >> 3) & 1);
  868. q[5] = -((v >> 2) & 1);
  869. q[6] = -((v >> 1) & 1);
  870. q[7] = -((v >> 0) & 1);
  871. w -= 8;
  872. q += 8;
  873. }
  874. if (w > 0) {
  875. v = *p++ ^ xor_mask;
  876. do {
  877. q[0] = -((v >> 7) & 1);
  878. q++;
  879. v <<= 1;
  880. } while (--w);
  881. }
  882. p += src_wrap;
  883. q += dst_wrap;
  884. }
  885. }
  886. static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
  887. int width, int height)
  888. {
  889. mono_to_gray(dst, src, width, height, 0xff);
  890. }
  891. static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
  892. int width, int height)
  893. {
  894. mono_to_gray(dst, src, width, height, 0x00);
  895. }
  896. static void gray_to_mono(AVPicture *dst, AVPicture *src,
  897. int width, int height, int xor_mask)
  898. {
  899. int n;
  900. const uint8_t *s;
  901. uint8_t *d;
  902. int j, b, v, n1, src_wrap, dst_wrap, y;
  903. s = src->data[0];
  904. src_wrap = src->linesize[0] - width;
  905. d = dst->data[0];
  906. dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
  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. static void rgba32_to_rgb24(AVPicture *dst, AVPicture *src,
  992. int width, int height)
  993. {
  994. const uint8_t *s;
  995. uint8_t *d;
  996. int src_wrap, dst_wrap, j, y;
  997. unsigned int v;
  998. s = src->data[0];
  999. src_wrap = src->linesize[0] - width * 4;
  1000. d = dst->data[0];
  1001. dst_wrap = dst->linesize[0] - width * 3;
  1002. for(y=0;y<height;y++) {
  1003. for(j = 0;j < width; j++) {
  1004. v = *(uint32_t *)s;
  1005. s += 4;
  1006. d[0] = v >> 16;
  1007. d[1] = v >> 8;
  1008. d[2] = v;
  1009. d += 3;
  1010. }
  1011. s += src_wrap;
  1012. d += dst_wrap;
  1013. }
  1014. }
  1015. typedef struct ConvertEntry {
  1016. void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
  1017. } ConvertEntry;
  1018. /* add each new convertion function in this table */
  1019. /* constraints;
  1020. - all non YUV modes must convert at least to and from PIX_FMT_RGB24
  1021. */
  1022. static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
  1023. [PIX_FMT_YUV420P] = {
  1024. [PIX_FMT_RGB555] = {
  1025. .convert = yuv420p_to_rgb555
  1026. },
  1027. [PIX_FMT_RGB565] = {
  1028. .convert = yuv420p_to_rgb565
  1029. },
  1030. [PIX_FMT_BGR24] = {
  1031. .convert = yuv420p_to_bgr24
  1032. },
  1033. [PIX_FMT_RGB24] = {
  1034. .convert = yuv420p_to_rgb24
  1035. },
  1036. [PIX_FMT_RGBA32] = {
  1037. .convert = yuv420p_to_rgba32
  1038. },
  1039. },
  1040. [PIX_FMT_YUV422P] = {
  1041. [PIX_FMT_RGB555] = {
  1042. .convert = yuv422p_to_rgb555
  1043. },
  1044. [PIX_FMT_RGB565] = {
  1045. .convert = yuv422p_to_rgb565
  1046. },
  1047. [PIX_FMT_BGR24] = {
  1048. .convert = yuv422p_to_bgr24
  1049. },
  1050. [PIX_FMT_RGB24] = {
  1051. .convert = yuv422p_to_rgb24
  1052. },
  1053. [PIX_FMT_RGBA32] = {
  1054. .convert = yuv422p_to_rgba32
  1055. },
  1056. },
  1057. [PIX_FMT_YUV422] = {
  1058. [PIX_FMT_YUV420P] = {
  1059. .convert = yuv422_to_yuv420p,
  1060. },
  1061. },
  1062. [PIX_FMT_RGB24] = {
  1063. [PIX_FMT_YUV420P] = {
  1064. .convert = rgb24_to_yuv420p
  1065. },
  1066. [PIX_FMT_RGB565] = {
  1067. .convert = rgb24_to_rgb565
  1068. },
  1069. [PIX_FMT_RGB555] = {
  1070. .convert = rgb24_to_rgb555
  1071. },
  1072. [PIX_FMT_GRAY8] = {
  1073. .convert = rgb24_to_gray
  1074. },
  1075. [PIX_FMT_PAL8] = {
  1076. .convert = rgb24_to_pal8
  1077. },
  1078. },
  1079. [PIX_FMT_RGBA32] = {
  1080. [PIX_FMT_YUV420P] = {
  1081. .convert = rgba32_to_yuv420p
  1082. },
  1083. [PIX_FMT_GRAY8] = {
  1084. .convert = rgba32_to_gray
  1085. },
  1086. [PIX_FMT_RGB24] = {
  1087. .convert = rgba32_to_rgb24
  1088. },
  1089. },
  1090. [PIX_FMT_BGR24] = {
  1091. [PIX_FMT_YUV420P] = {
  1092. .convert = bgr24_to_yuv420p
  1093. },
  1094. [PIX_FMT_GRAY8] = {
  1095. .convert = bgr24_to_gray
  1096. },
  1097. },
  1098. [PIX_FMT_RGB555] = {
  1099. [PIX_FMT_YUV420P] = {
  1100. .convert = rgb555_to_yuv420p
  1101. },
  1102. [PIX_FMT_GRAY8] = {
  1103. .convert = rgb555_to_gray
  1104. },
  1105. },
  1106. [PIX_FMT_RGB565] = {
  1107. [PIX_FMT_YUV420P] = {
  1108. .convert = rgb565_to_yuv420p
  1109. },
  1110. [PIX_FMT_GRAY8] = {
  1111. .convert = rgb565_to_gray
  1112. },
  1113. },
  1114. [PIX_FMT_GRAY8] = {
  1115. [PIX_FMT_RGB555] = {
  1116. .convert = gray_to_rgb555
  1117. },
  1118. [PIX_FMT_RGB565] = {
  1119. .convert = gray_to_rgb565
  1120. },
  1121. [PIX_FMT_RGB24] = {
  1122. .convert = gray_to_rgb24
  1123. },
  1124. [PIX_FMT_BGR24] = {
  1125. .convert = gray_to_bgr24
  1126. },
  1127. [PIX_FMT_RGBA32] = {
  1128. .convert = gray_to_rgba32
  1129. },
  1130. [PIX_FMT_MONOWHITE] = {
  1131. .convert = gray_to_monowhite
  1132. },
  1133. [PIX_FMT_MONOBLACK] = {
  1134. .convert = gray_to_monoblack
  1135. },
  1136. },
  1137. [PIX_FMT_MONOWHITE] = {
  1138. [PIX_FMT_GRAY8] = {
  1139. .convert = monowhite_to_gray
  1140. },
  1141. },
  1142. [PIX_FMT_MONOBLACK] = {
  1143. [PIX_FMT_GRAY8] = {
  1144. .convert = monoblack_to_gray
  1145. },
  1146. },
  1147. [PIX_FMT_PAL8] = {
  1148. [PIX_FMT_RGB555] = {
  1149. .convert = pal8_to_rgb555
  1150. },
  1151. [PIX_FMT_RGB565] = {
  1152. .convert = pal8_to_rgb565
  1153. },
  1154. [PIX_FMT_BGR24] = {
  1155. .convert = pal8_to_bgr24
  1156. },
  1157. [PIX_FMT_RGB24] = {
  1158. .convert = pal8_to_rgb24
  1159. },
  1160. [PIX_FMT_RGBA32] = {
  1161. .convert = pal8_to_rgba32
  1162. },
  1163. },
  1164. };
  1165. static int avpicture_alloc(AVPicture *picture,
  1166. int pix_fmt, int width, int height)
  1167. {
  1168. unsigned int size;
  1169. void *ptr;
  1170. size = avpicture_get_size(pix_fmt, width, height);
  1171. if (size < 0)
  1172. goto fail;
  1173. ptr = av_malloc(size);
  1174. if (!ptr)
  1175. goto fail;
  1176. avpicture_fill(picture, ptr, pix_fmt, width, height);
  1177. return 0;
  1178. fail:
  1179. memset(picture, 0, sizeof(AVPicture));
  1180. return -1;
  1181. }
  1182. static void avpicture_free(AVPicture *picture)
  1183. {
  1184. av_free(picture->data[0]);
  1185. }
  1186. /* XXX: always use linesize. Return -1 if not supported */
  1187. int img_convert(AVPicture *dst, int dst_pix_fmt,
  1188. AVPicture *src, int src_pix_fmt,
  1189. int src_width, int src_height)
  1190. {
  1191. int i, ret, dst_width, dst_height, int_pix_fmt;
  1192. PixFmtInfo *src_pix, *dst_pix;
  1193. ConvertEntry *ce;
  1194. AVPicture tmp1, *tmp = &tmp1;
  1195. if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
  1196. dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
  1197. return -1;
  1198. if (src_width <= 0 || src_height <= 0)
  1199. return 0;
  1200. dst_width = src_width;
  1201. dst_height = src_height;
  1202. dst_pix = &pix_fmt_info[dst_pix_fmt];
  1203. src_pix = &pix_fmt_info[src_pix_fmt];
  1204. if (src_pix_fmt == dst_pix_fmt) {
  1205. /* XXX: incorrect */
  1206. /* same format: just copy */
  1207. for(i = 0; i < dst_pix->nb_components; i++) {
  1208. int w, h;
  1209. w = dst_width;
  1210. h = dst_height;
  1211. if (dst_pix->is_yuv && (i == 1 || i == 2)) {
  1212. w >>= dst_pix->x_chroma_shift;
  1213. h >>= dst_pix->y_chroma_shift;
  1214. }
  1215. img_copy(dst->data[i], dst->linesize[i],
  1216. src->data[i], src->linesize[i],
  1217. w, h);
  1218. }
  1219. return 0;
  1220. }
  1221. ce = &convert_table[src_pix_fmt][dst_pix_fmt];
  1222. if (ce->convert) {
  1223. /* specific convertion routine */
  1224. ce->convert(dst, src, dst_width, dst_height);
  1225. return 0;
  1226. }
  1227. /* gray to YUV */
  1228. if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
  1229. int w, h, y;
  1230. uint8_t *d;
  1231. img_copy(dst->data[0], dst->linesize[0],
  1232. src->data[0], src->linesize[0],
  1233. dst_width, dst_height);
  1234. /* fill U and V with 128 */
  1235. w = dst_width;
  1236. h = dst_height;
  1237. w >>= dst_pix->x_chroma_shift;
  1238. h >>= dst_pix->y_chroma_shift;
  1239. for(i = 1; i <= 2; i++) {
  1240. d = dst->data[i];
  1241. for(y = 0; y< h; y++) {
  1242. memset(d, 128, w);
  1243. d += dst->linesize[i];
  1244. }
  1245. }
  1246. return 0;
  1247. }
  1248. /* YUV to gray */
  1249. if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
  1250. img_copy(dst->data[0], dst->linesize[0],
  1251. src->data[0], src->linesize[0],
  1252. dst_width, dst_height);
  1253. return 0;
  1254. }
  1255. /* YUV to YUV */
  1256. if (dst_pix->is_yuv && src_pix->is_yuv) {
  1257. int x_shift, y_shift, w, h;
  1258. void (*resize_func)(uint8_t *dst, int dst_wrap,
  1259. uint8_t *src, int src_wrap,
  1260. int width, int height);
  1261. /* compute chroma size of the smallest dimensions */
  1262. w = dst_width;
  1263. h = dst_height;
  1264. if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
  1265. w >>= dst_pix->x_chroma_shift;
  1266. else
  1267. w >>= src_pix->x_chroma_shift;
  1268. if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
  1269. h >>= dst_pix->y_chroma_shift;
  1270. else
  1271. h >>= src_pix->y_chroma_shift;
  1272. x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
  1273. y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
  1274. if (x_shift == 0 && y_shift == 0) {
  1275. resize_func = img_copy; /* should never happen */
  1276. } else if (x_shift == 0 && y_shift == 1) {
  1277. resize_func = shrink2;
  1278. } else if (x_shift == 1 && y_shift == 1) {
  1279. resize_func = shrink22;
  1280. } else if (x_shift == -1 && y_shift == -1) {
  1281. resize_func = grow22;
  1282. } else if (x_shift == -1 && y_shift == 1) {
  1283. resize_func = conv411;
  1284. } else {
  1285. /* currently not handled */
  1286. return -1;
  1287. }
  1288. img_copy(dst->data[0], dst->linesize[0],
  1289. src->data[0], src->linesize[0],
  1290. dst_width, dst_height);
  1291. for(i = 1;i <= 2; i++)
  1292. resize_func(dst->data[i], dst->linesize[i],
  1293. src->data[i], src->linesize[i],
  1294. dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
  1295. return 0;
  1296. }
  1297. /* try to use an intermediate format */
  1298. if (src_pix_fmt == PIX_FMT_MONOWHITE ||
  1299. src_pix_fmt == PIX_FMT_MONOBLACK ||
  1300. dst_pix_fmt == PIX_FMT_MONOWHITE ||
  1301. dst_pix_fmt == PIX_FMT_MONOBLACK) {
  1302. int_pix_fmt = PIX_FMT_GRAY8;
  1303. } else {
  1304. int_pix_fmt = PIX_FMT_RGB24;
  1305. }
  1306. if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1307. return -1;
  1308. ret = -1;
  1309. if (img_convert(tmp, int_pix_fmt,
  1310. src, src_pix_fmt, src_width, src_height) < 0)
  1311. goto fail1;
  1312. if (img_convert(dst, dst_pix_fmt,
  1313. tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1314. goto fail1;
  1315. ret = 0;
  1316. fail1:
  1317. avpicture_free(tmp);
  1318. return ret;
  1319. }
  1320. #ifdef HAVE_MMX
  1321. #define DEINT_INPLACE_LINE_LUM \
  1322. movd_m2r(lum_m4[0],mm0);\
  1323. movd_m2r(lum_m3[0],mm1);\
  1324. movd_m2r(lum_m2[0],mm2);\
  1325. movd_m2r(lum_m1[0],mm3);\
  1326. movd_m2r(lum[0],mm4);\
  1327. punpcklbw_r2r(mm7,mm0);\
  1328. movd_r2m(mm2,lum_m4[0]);\
  1329. punpcklbw_r2r(mm7,mm1);\
  1330. punpcklbw_r2r(mm7,mm2);\
  1331. punpcklbw_r2r(mm7,mm3);\
  1332. punpcklbw_r2r(mm7,mm4);\
  1333. paddw_r2r(mm3,mm1);\
  1334. psllw_i2r(1,mm2);\
  1335. paddw_r2r(mm4,mm0);\
  1336. psllw_i2r(2,mm1);\
  1337. paddw_r2r(mm6,mm2);\
  1338. paddw_r2r(mm2,mm1);\
  1339. psubusw_r2r(mm0,mm1);\
  1340. psrlw_i2r(3,mm1);\
  1341. packuswb_r2r(mm7,mm1);\
  1342. movd_r2m(mm1,lum_m2[0]);
  1343. #define DEINT_LINE_LUM \
  1344. movd_m2r(lum_m4[0],mm0);\
  1345. movd_m2r(lum_m3[0],mm1);\
  1346. movd_m2r(lum_m2[0],mm2);\
  1347. movd_m2r(lum_m1[0],mm3);\
  1348. movd_m2r(lum[0],mm4);\
  1349. punpcklbw_r2r(mm7,mm0);\
  1350. punpcklbw_r2r(mm7,mm1);\
  1351. punpcklbw_r2r(mm7,mm2);\
  1352. punpcklbw_r2r(mm7,mm3);\
  1353. punpcklbw_r2r(mm7,mm4);\
  1354. paddw_r2r(mm3,mm1);\
  1355. psllw_i2r(1,mm2);\
  1356. paddw_r2r(mm4,mm0);\
  1357. psllw_i2r(2,mm1);\
  1358. paddw_r2r(mm6,mm2);\
  1359. paddw_r2r(mm2,mm1);\
  1360. psubusw_r2r(mm0,mm1);\
  1361. psrlw_i2r(3,mm1);\
  1362. packuswb_r2r(mm7,mm1);\
  1363. movd_r2m(mm1,dst[0]);
  1364. #endif
  1365. /* filter parameters: [-1 4 2 4 -1] // 8 */
  1366. 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,
  1367. int size)
  1368. {
  1369. #ifndef HAVE_MMX
  1370. uint8_t *cm = cropTbl + MAX_NEG_CROP;
  1371. int sum;
  1372. for(;size > 0;size--) {
  1373. sum = -lum_m4[0];
  1374. sum += lum_m3[0] << 2;
  1375. sum += lum_m2[0] << 1;
  1376. sum += lum_m1[0] << 2;
  1377. sum += -lum[0];
  1378. dst[0] = cm[(sum + 4) >> 3];
  1379. lum_m4++;
  1380. lum_m3++;
  1381. lum_m2++;
  1382. lum_m1++;
  1383. lum++;
  1384. dst++;
  1385. }
  1386. #else
  1387. {
  1388. mmx_t rounder;
  1389. rounder.uw[0]=4;
  1390. rounder.uw[1]=4;
  1391. rounder.uw[2]=4;
  1392. rounder.uw[3]=4;
  1393. pxor_r2r(mm7,mm7);
  1394. movq_m2r(rounder,mm6);
  1395. }
  1396. for (;size > 3; size-=4) {
  1397. DEINT_LINE_LUM
  1398. lum_m4+=4;
  1399. lum_m3+=4;
  1400. lum_m2+=4;
  1401. lum_m1+=4;
  1402. lum+=4;
  1403. dst+=4;
  1404. }
  1405. #endif
  1406. }
  1407. static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
  1408. int size)
  1409. {
  1410. #ifndef HAVE_MMX
  1411. uint8_t *cm = cropTbl + MAX_NEG_CROP;
  1412. int sum;
  1413. for(;size > 0;size--) {
  1414. sum = -lum_m4[0];
  1415. sum += lum_m3[0] << 2;
  1416. sum += lum_m2[0] << 1;
  1417. lum_m4[0]=lum_m2[0];
  1418. sum += lum_m1[0] << 2;
  1419. sum += -lum[0];
  1420. lum_m2[0] = cm[(sum + 4) >> 3];
  1421. lum_m4++;
  1422. lum_m3++;
  1423. lum_m2++;
  1424. lum_m1++;
  1425. lum++;
  1426. }
  1427. #else
  1428. {
  1429. mmx_t rounder;
  1430. rounder.uw[0]=4;
  1431. rounder.uw[1]=4;
  1432. rounder.uw[2]=4;
  1433. rounder.uw[3]=4;
  1434. pxor_r2r(mm7,mm7);
  1435. movq_m2r(rounder,mm6);
  1436. }
  1437. for (;size > 3; size-=4) {
  1438. DEINT_INPLACE_LINE_LUM
  1439. lum_m4+=4;
  1440. lum_m3+=4;
  1441. lum_m2+=4;
  1442. lum_m1+=4;
  1443. lum+=4;
  1444. }
  1445. #endif
  1446. }
  1447. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  1448. top field is copied as is, but the bottom field is deinterlaced
  1449. against the top field. */
  1450. static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
  1451. uint8_t *src1, int src_wrap,
  1452. int width, int height)
  1453. {
  1454. uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  1455. int y;
  1456. src_m2 = src1;
  1457. src_m1 = src1;
  1458. src_0=&src_m1[src_wrap];
  1459. src_p1=&src_0[src_wrap];
  1460. src_p2=&src_p1[src_wrap];
  1461. for(y=0;y<(height-2);y+=2) {
  1462. memcpy(dst,src_m1,width);
  1463. dst += dst_wrap;
  1464. deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  1465. src_m2 = src_0;
  1466. src_m1 = src_p1;
  1467. src_0 = src_p2;
  1468. src_p1 += 2*src_wrap;
  1469. src_p2 += 2*src_wrap;
  1470. dst += dst_wrap;
  1471. }
  1472. memcpy(dst,src_m1,width);
  1473. dst += dst_wrap;
  1474. /* do last line */
  1475. deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  1476. }
  1477. static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
  1478. int width, int height)
  1479. {
  1480. uint8_t *src_m1, *src_0, *src_p1, *src_p2;
  1481. int y;
  1482. uint8_t *buf;
  1483. buf = (uint8_t*)av_malloc(width);
  1484. src_m1 = src1;
  1485. memcpy(buf,src_m1,width);
  1486. src_0=&src_m1[src_wrap];
  1487. src_p1=&src_0[src_wrap];
  1488. src_p2=&src_p1[src_wrap];
  1489. for(y=0;y<(height-2);y+=2) {
  1490. deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  1491. src_m1 = src_p1;
  1492. src_0 = src_p2;
  1493. src_p1 += 2*src_wrap;
  1494. src_p2 += 2*src_wrap;
  1495. }
  1496. /* do last line */
  1497. deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  1498. av_free(buf);
  1499. }
  1500. /* deinterlace - if not supported return -1 */
  1501. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  1502. int pix_fmt, int width, int height)
  1503. {
  1504. int i;
  1505. if (pix_fmt != PIX_FMT_YUV420P &&
  1506. pix_fmt != PIX_FMT_YUV422P &&
  1507. pix_fmt != PIX_FMT_YUV444P)
  1508. return -1;
  1509. if ((width & 3) != 0 || (height & 3) != 0)
  1510. return -1;
  1511. for(i=0;i<3;i++) {
  1512. if (i == 1) {
  1513. switch(pix_fmt) {
  1514. case PIX_FMT_YUV420P:
  1515. width >>= 1;
  1516. height >>= 1;
  1517. break;
  1518. case PIX_FMT_YUV422P:
  1519. width >>= 1;
  1520. break;
  1521. default:
  1522. break;
  1523. }
  1524. }
  1525. if (src == dst) {
  1526. deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
  1527. width, height);
  1528. } else {
  1529. deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  1530. src->data[i], src->linesize[i],
  1531. width, height);
  1532. }
  1533. }
  1534. #ifdef HAVE_MMX
  1535. emms();
  1536. #endif
  1537. return 0;
  1538. }
  1539. #undef FIX