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.

1646 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. 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. printf("%d %d\n", width, height);
  908. for(y=0;y<height;y++) {
  909. n = width;
  910. while (n >= 8) {
  911. v = 0;
  912. for(j=0;j<8;j++) {
  913. b = s[0];
  914. s++;
  915. v = (v << 1) | (b >> 7);
  916. }
  917. d[0] = v ^ xor_mask;
  918. d++;
  919. n -= 8;
  920. }
  921. if (n > 0) {
  922. n1 = n;
  923. v = 0;
  924. while (n > 0) {
  925. b = s[0];
  926. s++;
  927. v = (v << 1) | (b >> 7);
  928. n--;
  929. }
  930. d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
  931. d++;
  932. }
  933. s += src_wrap;
  934. d += dst_wrap;
  935. }
  936. }
  937. static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
  938. int width, int height)
  939. {
  940. gray_to_mono(dst, src, width, height, 0xff);
  941. }
  942. static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
  943. int width, int height)
  944. {
  945. gray_to_mono(dst, src, width, height, 0x00);
  946. }
  947. /* this is maybe slow, but allows for extensions */
  948. static inline unsigned char gif_clut_index(uint8_t r, uint8_t g, uint8_t b)
  949. {
  950. return ((((r)/47)%6)*6*6+(((g)/47)%6)*6+(((b)/47)%6));
  951. }
  952. /* XXX: put jpeg quantize code instead */
  953. static void rgb24_to_pal8(AVPicture *dst, AVPicture *src,
  954. int width, int height)
  955. {
  956. const unsigned char *p;
  957. unsigned char *q;
  958. int r, g, b, dst_wrap, src_wrap;
  959. int x, y, i;
  960. static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
  961. uint32_t *pal;
  962. p = src->data[0];
  963. src_wrap = src->linesize[0] - 3 * width;
  964. q = dst->data[0];
  965. dst_wrap = dst->linesize[0] - width;
  966. for(y=0;y<height;y++) {
  967. for(x=0;x<width;x++) {
  968. r = p[0];
  969. g = p[1];
  970. b = p[2];
  971. q[0] = gif_clut_index(r, g, b);
  972. q++;
  973. p += 3;
  974. }
  975. p += src_wrap;
  976. q += dst_wrap;
  977. }
  978. /* build palette */
  979. pal = (uint32_t *)dst->data[1];
  980. i = 0;
  981. for(r = 0; r < 6; r++) {
  982. for(g = 0; g < 6; g++) {
  983. for(b = 0; b < 6; b++) {
  984. pal[i++] = (0xff << 24) | (pal_value[r] << 16) |
  985. (pal_value[g] << 8) | pal_value[b];
  986. }
  987. }
  988. }
  989. while (i < 256)
  990. pal[i++] = 0;
  991. }
  992. typedef struct ConvertEntry {
  993. void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
  994. } ConvertEntry;
  995. /* add each new convertion function in this table */
  996. /* constraints;
  997. - all non YUV modes must convert at least to and from PIX_FMT_RGB24
  998. */
  999. static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
  1000. [PIX_FMT_YUV420P] = {
  1001. [PIX_FMT_RGB555] = {
  1002. .convert = yuv420p_to_rgb555
  1003. },
  1004. [PIX_FMT_RGB565] = {
  1005. .convert = yuv420p_to_rgb565
  1006. },
  1007. [PIX_FMT_BGR24] = {
  1008. .convert = yuv420p_to_bgr24
  1009. },
  1010. [PIX_FMT_RGB24] = {
  1011. .convert = yuv420p_to_rgb24
  1012. },
  1013. [PIX_FMT_RGBA32] = {
  1014. .convert = yuv420p_to_rgba32
  1015. },
  1016. },
  1017. [PIX_FMT_YUV422P] = {
  1018. [PIX_FMT_RGB555] = {
  1019. .convert = yuv422p_to_rgb555
  1020. },
  1021. [PIX_FMT_RGB565] = {
  1022. .convert = yuv422p_to_rgb565
  1023. },
  1024. [PIX_FMT_BGR24] = {
  1025. .convert = yuv422p_to_bgr24
  1026. },
  1027. [PIX_FMT_RGB24] = {
  1028. .convert = yuv422p_to_rgb24
  1029. },
  1030. [PIX_FMT_RGBA32] = {
  1031. .convert = yuv422p_to_rgba32
  1032. },
  1033. },
  1034. [PIX_FMT_YUV422] = {
  1035. [PIX_FMT_YUV420P] = {
  1036. .convert = yuv422_to_yuv420p,
  1037. },
  1038. },
  1039. [PIX_FMT_RGB24] = {
  1040. [PIX_FMT_YUV420P] = {
  1041. .convert = rgb24_to_yuv420p
  1042. },
  1043. [PIX_FMT_RGB565] = {
  1044. .convert = rgb24_to_rgb565
  1045. },
  1046. [PIX_FMT_RGB555] = {
  1047. .convert = rgb24_to_rgb555
  1048. },
  1049. [PIX_FMT_GRAY8] = {
  1050. .convert = rgb24_to_gray
  1051. },
  1052. [PIX_FMT_PAL8] = {
  1053. .convert = rgb24_to_pal8
  1054. },
  1055. },
  1056. [PIX_FMT_RGBA32] = {
  1057. [PIX_FMT_YUV420P] = {
  1058. .convert = rgba32_to_yuv420p
  1059. },
  1060. [PIX_FMT_GRAY8] = {
  1061. .convert = rgba32_to_gray
  1062. },
  1063. },
  1064. [PIX_FMT_BGR24] = {
  1065. [PIX_FMT_YUV420P] = {
  1066. .convert = bgr24_to_yuv420p
  1067. },
  1068. [PIX_FMT_GRAY8] = {
  1069. .convert = bgr24_to_gray
  1070. },
  1071. },
  1072. [PIX_FMT_RGB555] = {
  1073. [PIX_FMT_YUV420P] = {
  1074. .convert = rgb555_to_yuv420p
  1075. },
  1076. [PIX_FMT_GRAY8] = {
  1077. .convert = rgb555_to_gray
  1078. },
  1079. },
  1080. [PIX_FMT_RGB565] = {
  1081. [PIX_FMT_YUV420P] = {
  1082. .convert = rgb565_to_yuv420p
  1083. },
  1084. [PIX_FMT_GRAY8] = {
  1085. .convert = rgb565_to_gray
  1086. },
  1087. },
  1088. [PIX_FMT_GRAY8] = {
  1089. [PIX_FMT_RGB555] = {
  1090. .convert = gray_to_rgb555
  1091. },
  1092. [PIX_FMT_RGB565] = {
  1093. .convert = gray_to_rgb565
  1094. },
  1095. [PIX_FMT_RGB24] = {
  1096. .convert = gray_to_rgb24
  1097. },
  1098. [PIX_FMT_BGR24] = {
  1099. .convert = gray_to_bgr24
  1100. },
  1101. [PIX_FMT_RGBA32] = {
  1102. .convert = gray_to_rgba32
  1103. },
  1104. [PIX_FMT_MONOWHITE] = {
  1105. .convert = gray_to_monowhite
  1106. },
  1107. [PIX_FMT_MONOBLACK] = {
  1108. .convert = gray_to_monoblack
  1109. },
  1110. },
  1111. [PIX_FMT_MONOWHITE] = {
  1112. [PIX_FMT_GRAY8] = {
  1113. .convert = monowhite_to_gray
  1114. },
  1115. },
  1116. [PIX_FMT_MONOBLACK] = {
  1117. [PIX_FMT_GRAY8] = {
  1118. .convert = monoblack_to_gray
  1119. },
  1120. },
  1121. [PIX_FMT_PAL8] = {
  1122. [PIX_FMT_RGB555] = {
  1123. .convert = pal8_to_rgb555
  1124. },
  1125. [PIX_FMT_RGB565] = {
  1126. .convert = pal8_to_rgb565
  1127. },
  1128. [PIX_FMT_BGR24] = {
  1129. .convert = pal8_to_bgr24
  1130. },
  1131. [PIX_FMT_RGB24] = {
  1132. .convert = pal8_to_rgb24
  1133. },
  1134. [PIX_FMT_RGBA32] = {
  1135. .convert = pal8_to_rgba32
  1136. },
  1137. },
  1138. };
  1139. static int avpicture_alloc(AVPicture *picture,
  1140. int pix_fmt, int width, int height)
  1141. {
  1142. unsigned int size;
  1143. void *ptr;
  1144. size = avpicture_get_size(pix_fmt, width, height);
  1145. if (size < 0)
  1146. goto fail;
  1147. ptr = av_malloc(size);
  1148. if (!ptr)
  1149. goto fail;
  1150. avpicture_fill(picture, ptr, pix_fmt, width, height);
  1151. return 0;
  1152. fail:
  1153. memset(picture, 0, sizeof(AVPicture));
  1154. return -1;
  1155. }
  1156. static void avpicture_free(AVPicture *picture)
  1157. {
  1158. av_free(picture->data[0]);
  1159. }
  1160. /* XXX: always use linesize. Return -1 if not supported */
  1161. int img_convert(AVPicture *dst, int dst_pix_fmt,
  1162. AVPicture *src, int src_pix_fmt,
  1163. int src_width, int src_height)
  1164. {
  1165. int i, ret, dst_width, dst_height, int_pix_fmt;
  1166. PixFmtInfo *src_pix, *dst_pix;
  1167. ConvertEntry *ce;
  1168. AVPicture tmp1, *tmp = &tmp1;
  1169. if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
  1170. dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
  1171. return -1;
  1172. if (src_width <= 0 || src_height <= 0)
  1173. return 0;
  1174. dst_width = src_width;
  1175. dst_height = src_height;
  1176. dst_pix = &pix_fmt_info[dst_pix_fmt];
  1177. src_pix = &pix_fmt_info[src_pix_fmt];
  1178. if (src_pix_fmt == dst_pix_fmt) {
  1179. /* XXX: incorrect */
  1180. /* same format: just copy */
  1181. for(i = 0; i < dst_pix->nb_components; i++) {
  1182. int w, h;
  1183. w = dst_width;
  1184. h = dst_height;
  1185. if (dst_pix->is_yuv && (i == 1 || i == 2)) {
  1186. w >>= dst_pix->x_chroma_shift;
  1187. h >>= dst_pix->y_chroma_shift;
  1188. }
  1189. img_copy(dst->data[i], dst->linesize[i],
  1190. src->data[i], src->linesize[i],
  1191. w, h);
  1192. }
  1193. return 0;
  1194. }
  1195. ce = &convert_table[src_pix_fmt][dst_pix_fmt];
  1196. if (ce->convert) {
  1197. /* specific convertion routine */
  1198. ce->convert(dst, src, dst_width, dst_height);
  1199. return 0;
  1200. }
  1201. /* gray to YUV */
  1202. if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
  1203. int w, h, y;
  1204. uint8_t *d;
  1205. img_copy(dst->data[0], dst->linesize[0],
  1206. src->data[0], src->linesize[0],
  1207. dst_width, dst_height);
  1208. /* fill U and V with 128 */
  1209. w = dst_width;
  1210. h = dst_height;
  1211. w >>= dst_pix->x_chroma_shift;
  1212. h >>= dst_pix->y_chroma_shift;
  1213. for(i = 1; i <= 2; i++) {
  1214. d = dst->data[i];
  1215. for(y = 0; y< h; y++) {
  1216. memset(d, 128, w);
  1217. d += dst->linesize[i];
  1218. }
  1219. }
  1220. return 0;
  1221. }
  1222. /* YUV to gray */
  1223. if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
  1224. img_copy(dst->data[0], dst->linesize[0],
  1225. src->data[0], src->linesize[0],
  1226. dst_width, dst_height);
  1227. return 0;
  1228. }
  1229. /* YUV to YUV */
  1230. if (dst_pix->is_yuv && src_pix->is_yuv) {
  1231. int x_shift, y_shift, w, h;
  1232. void (*resize_func)(uint8_t *dst, int dst_wrap,
  1233. uint8_t *src, int src_wrap,
  1234. int width, int height);
  1235. /* compute chroma size of the smallest dimensions */
  1236. w = dst_width;
  1237. h = dst_height;
  1238. if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
  1239. w >>= dst_pix->x_chroma_shift;
  1240. else
  1241. w >>= src_pix->x_chroma_shift;
  1242. if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
  1243. h >>= dst_pix->y_chroma_shift;
  1244. else
  1245. h >>= src_pix->y_chroma_shift;
  1246. x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
  1247. y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
  1248. if (x_shift == 0 && y_shift == 0) {
  1249. resize_func = img_copy; /* should never happen */
  1250. } else if (x_shift == 0 && y_shift == 1) {
  1251. resize_func = shrink2;
  1252. } else if (x_shift == 1 && y_shift == 1) {
  1253. resize_func = shrink22;
  1254. } else if (x_shift == -1 && y_shift == -1) {
  1255. resize_func = grow22;
  1256. } else if (x_shift == -1 && y_shift == 1) {
  1257. resize_func = conv411;
  1258. } else {
  1259. /* currently not handled */
  1260. return -1;
  1261. }
  1262. img_copy(dst->data[0], dst->linesize[0],
  1263. src->data[0], src->linesize[0],
  1264. dst_width, dst_height);
  1265. for(i = 1;i <= 2; i++)
  1266. resize_func(dst->data[i], dst->linesize[i],
  1267. src->data[i], src->linesize[i],
  1268. dst_width>>dst_pix->x_chroma_shift, dst_height>>dst_pix->y_chroma_shift);
  1269. return 0;
  1270. }
  1271. /* try to use an intermediate format */
  1272. if (src_pix_fmt == PIX_FMT_MONOWHITE ||
  1273. src_pix_fmt == PIX_FMT_MONOBLACK ||
  1274. dst_pix_fmt == PIX_FMT_MONOWHITE ||
  1275. dst_pix_fmt == PIX_FMT_MONOBLACK) {
  1276. int_pix_fmt = PIX_FMT_GRAY8;
  1277. } else {
  1278. int_pix_fmt = PIX_FMT_RGB24;
  1279. }
  1280. if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1281. return -1;
  1282. ret = -1;
  1283. if (img_convert(tmp, int_pix_fmt,
  1284. src, src_pix_fmt, src_width, src_height) < 0)
  1285. goto fail1;
  1286. if (img_convert(dst, dst_pix_fmt,
  1287. tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1288. goto fail1;
  1289. ret = 0;
  1290. fail1:
  1291. avpicture_free(tmp);
  1292. return ret;
  1293. }
  1294. #ifdef HAVE_MMX
  1295. #define DEINT_INPLACE_LINE_LUM \
  1296. movd_m2r(lum_m4[0],mm0);\
  1297. movd_m2r(lum_m3[0],mm1);\
  1298. movd_m2r(lum_m2[0],mm2);\
  1299. movd_m2r(lum_m1[0],mm3);\
  1300. movd_m2r(lum[0],mm4);\
  1301. punpcklbw_r2r(mm7,mm0);\
  1302. movd_r2m(mm2,lum_m4[0]);\
  1303. punpcklbw_r2r(mm7,mm1);\
  1304. punpcklbw_r2r(mm7,mm2);\
  1305. punpcklbw_r2r(mm7,mm3);\
  1306. punpcklbw_r2r(mm7,mm4);\
  1307. paddw_r2r(mm3,mm1);\
  1308. psllw_i2r(1,mm2);\
  1309. paddw_r2r(mm4,mm0);\
  1310. psllw_i2r(2,mm1);\
  1311. paddw_r2r(mm6,mm2);\
  1312. paddw_r2r(mm2,mm1);\
  1313. psubusw_r2r(mm0,mm1);\
  1314. psrlw_i2r(3,mm1);\
  1315. packuswb_r2r(mm7,mm1);\
  1316. movd_r2m(mm1,lum_m2[0]);
  1317. #define DEINT_LINE_LUM \
  1318. movd_m2r(lum_m4[0],mm0);\
  1319. movd_m2r(lum_m3[0],mm1);\
  1320. movd_m2r(lum_m2[0],mm2);\
  1321. movd_m2r(lum_m1[0],mm3);\
  1322. movd_m2r(lum[0],mm4);\
  1323. punpcklbw_r2r(mm7,mm0);\
  1324. punpcklbw_r2r(mm7,mm1);\
  1325. punpcklbw_r2r(mm7,mm2);\
  1326. punpcklbw_r2r(mm7,mm3);\
  1327. punpcklbw_r2r(mm7,mm4);\
  1328. paddw_r2r(mm3,mm1);\
  1329. psllw_i2r(1,mm2);\
  1330. paddw_r2r(mm4,mm0);\
  1331. psllw_i2r(2,mm1);\
  1332. paddw_r2r(mm6,mm2);\
  1333. paddw_r2r(mm2,mm1);\
  1334. psubusw_r2r(mm0,mm1);\
  1335. psrlw_i2r(3,mm1);\
  1336. packuswb_r2r(mm7,mm1);\
  1337. movd_r2m(mm1,dst[0]);
  1338. #endif
  1339. /* filter parameters: [-1 4 2 4 -1] // 8 */
  1340. 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,
  1341. int size)
  1342. {
  1343. #ifndef HAVE_MMX
  1344. uint8_t *cm = cropTbl + MAX_NEG_CROP;
  1345. int sum;
  1346. for(;size > 0;size--) {
  1347. sum = -lum_m4[0];
  1348. sum += lum_m3[0] << 2;
  1349. sum += lum_m2[0] << 1;
  1350. sum += lum_m1[0] << 2;
  1351. sum += -lum[0];
  1352. dst[0] = cm[(sum + 4) >> 3];
  1353. lum_m4++;
  1354. lum_m3++;
  1355. lum_m2++;
  1356. lum_m1++;
  1357. lum++;
  1358. dst++;
  1359. }
  1360. #else
  1361. {
  1362. mmx_t rounder;
  1363. rounder.uw[0]=4;
  1364. rounder.uw[1]=4;
  1365. rounder.uw[2]=4;
  1366. rounder.uw[3]=4;
  1367. pxor_r2r(mm7,mm7);
  1368. movq_m2r(rounder,mm6);
  1369. }
  1370. for (;size > 3; size-=4) {
  1371. DEINT_LINE_LUM
  1372. lum_m4+=4;
  1373. lum_m3+=4;
  1374. lum_m2+=4;
  1375. lum_m1+=4;
  1376. lum+=4;
  1377. dst+=4;
  1378. }
  1379. #endif
  1380. }
  1381. static void deinterlace_line_inplace(uint8_t *lum_m4, uint8_t *lum_m3, uint8_t *lum_m2, uint8_t *lum_m1, uint8_t *lum,
  1382. int size)
  1383. {
  1384. #ifndef HAVE_MMX
  1385. uint8_t *cm = cropTbl + MAX_NEG_CROP;
  1386. int sum;
  1387. for(;size > 0;size--) {
  1388. sum = -lum_m4[0];
  1389. sum += lum_m3[0] << 2;
  1390. sum += lum_m2[0] << 1;
  1391. lum_m4[0]=lum_m2[0];
  1392. sum += lum_m1[0] << 2;
  1393. sum += -lum[0];
  1394. lum_m2[0] = cm[(sum + 4) >> 3];
  1395. lum_m4++;
  1396. lum_m3++;
  1397. lum_m2++;
  1398. lum_m1++;
  1399. lum++;
  1400. }
  1401. #else
  1402. {
  1403. mmx_t rounder;
  1404. rounder.uw[0]=4;
  1405. rounder.uw[1]=4;
  1406. rounder.uw[2]=4;
  1407. rounder.uw[3]=4;
  1408. pxor_r2r(mm7,mm7);
  1409. movq_m2r(rounder,mm6);
  1410. }
  1411. for (;size > 3; size-=4) {
  1412. DEINT_INPLACE_LINE_LUM
  1413. lum_m4+=4;
  1414. lum_m3+=4;
  1415. lum_m2+=4;
  1416. lum_m1+=4;
  1417. lum+=4;
  1418. }
  1419. #endif
  1420. }
  1421. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  1422. top field is copied as is, but the bottom field is deinterlaced
  1423. against the top field. */
  1424. static void deinterlace_bottom_field(uint8_t *dst, int dst_wrap,
  1425. uint8_t *src1, int src_wrap,
  1426. int width, int height)
  1427. {
  1428. uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  1429. int y;
  1430. src_m2 = src1;
  1431. src_m1 = src1;
  1432. src_0=&src_m1[src_wrap];
  1433. src_p1=&src_0[src_wrap];
  1434. src_p2=&src_p1[src_wrap];
  1435. for(y=0;y<(height-2);y+=2) {
  1436. memcpy(dst,src_m1,width);
  1437. dst += dst_wrap;
  1438. deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  1439. src_m2 = src_0;
  1440. src_m1 = src_p1;
  1441. src_0 = src_p2;
  1442. src_p1 += 2*src_wrap;
  1443. src_p2 += 2*src_wrap;
  1444. dst += dst_wrap;
  1445. }
  1446. memcpy(dst,src_m1,width);
  1447. dst += dst_wrap;
  1448. /* do last line */
  1449. deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  1450. }
  1451. static void deinterlace_bottom_field_inplace(uint8_t *src1, int src_wrap,
  1452. int width, int height)
  1453. {
  1454. uint8_t *src_m1, *src_0, *src_p1, *src_p2;
  1455. int y;
  1456. uint8_t *buf;
  1457. buf = (uint8_t*)av_malloc(width);
  1458. src_m1 = src1;
  1459. memcpy(buf,src_m1,width);
  1460. src_0=&src_m1[src_wrap];
  1461. src_p1=&src_0[src_wrap];
  1462. src_p2=&src_p1[src_wrap];
  1463. for(y=0;y<(height-2);y+=2) {
  1464. deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  1465. src_m1 = src_p1;
  1466. src_0 = src_p2;
  1467. src_p1 += 2*src_wrap;
  1468. src_p2 += 2*src_wrap;
  1469. }
  1470. /* do last line */
  1471. deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  1472. av_free(buf);
  1473. }
  1474. /* deinterlace - if not supported return -1 */
  1475. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  1476. int pix_fmt, int width, int height)
  1477. {
  1478. int i;
  1479. if (pix_fmt != PIX_FMT_YUV420P &&
  1480. pix_fmt != PIX_FMT_YUV422P &&
  1481. pix_fmt != PIX_FMT_YUV444P)
  1482. return -1;
  1483. if ((width & 3) != 0 || (height & 3) != 0)
  1484. return -1;
  1485. for(i=0;i<3;i++) {
  1486. if (i == 1) {
  1487. switch(pix_fmt) {
  1488. case PIX_FMT_YUV420P:
  1489. width >>= 1;
  1490. height >>= 1;
  1491. break;
  1492. case PIX_FMT_YUV422P:
  1493. width >>= 1;
  1494. break;
  1495. default:
  1496. break;
  1497. }
  1498. }
  1499. if (src == dst) {
  1500. deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
  1501. width, height);
  1502. } else {
  1503. deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  1504. src->data[i], src->linesize[i],
  1505. width, height);
  1506. }
  1507. }
  1508. #ifdef HAVE_MMX
  1509. emms();
  1510. #endif
  1511. return 0;
  1512. }
  1513. #undef FIX