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.

1437 lines
44KB

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