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.

1456 lines
47KB

  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 * BPP; \
  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 * BPP; \
  536. lum += -wrap + 2; \
  537. } \
  538. p += wrap3; \
  539. lum += wrap; \
  540. } \
  541. } \
  542. \
  543. static void rgb_name ## _to_gray(AVPicture *dst, AVPicture *src, \
  544. int width, int height) \
  545. { \
  546. const unsigned char *p; \
  547. unsigned char *q; \
  548. int r, g, b, dst_wrap, src_wrap; \
  549. int x, y; \
  550. \
  551. p = src->data[0]; \
  552. src_wrap = src->linesize[0] - BPP * width; \
  553. \
  554. q = dst->data[0]; \
  555. dst_wrap = dst->linesize[0] - width; \
  556. \
  557. for(y=0;y<height;y++) { \
  558. for(x=0;x<width;x++) { \
  559. RGB_IN(r, g, b, p); \
  560. q[0] = (FIX(0.29900) * r + FIX(0.58700) * g + \
  561. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS; \
  562. q++; \
  563. p += BPP; \
  564. } \
  565. p += src_wrap; \
  566. q += dst_wrap; \
  567. } \
  568. } \
  569. \
  570. static void gray_to_ ## rgb_name(AVPicture *dst, AVPicture *src, \
  571. int width, int height) \
  572. { \
  573. const unsigned char *p; \
  574. unsigned char *q; \
  575. int r, dst_wrap, src_wrap; \
  576. int x, y; \
  577. \
  578. p = src->data[0]; \
  579. src_wrap = src->linesize[0] - width; \
  580. \
  581. q = dst->data[0]; \
  582. dst_wrap = dst->linesize[0] - BPP * width; \
  583. \
  584. for(y=0;y<height;y++) { \
  585. for(x=0;x<width;x++) { \
  586. r = p[0]; \
  587. RGB_OUT(q, r, r, r); \
  588. q += BPP; \
  589. p ++; \
  590. } \
  591. p += src_wrap; \
  592. q += dst_wrap; \
  593. } \
  594. }
  595. /* copy bit n to bits 0 ... n - 1 */
  596. static inline unsigned int bitcopy_n(unsigned int a, int n)
  597. {
  598. int mask;
  599. mask = (1 << n) - 1;
  600. return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask);
  601. }
  602. /* rgb555 handling */
  603. #define RGB_IN(r, g, b, s)\
  604. {\
  605. unsigned int v = ((UINT16 *)(s))[0];\
  606. r = bitcopy_n(v >> (10 - 3), 3);\
  607. g = bitcopy_n(v >> (5 - 3), 3);\
  608. b = bitcopy_n(v << 3, 3);\
  609. }
  610. #define RGB_OUT(d, r, g, b)\
  611. {\
  612. ((UINT16 *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;\
  613. }
  614. #define BPP 2
  615. RGB_FUNCTIONS(rgb555)
  616. #undef RGB_IN
  617. #undef RGB_OUT
  618. #undef BPP
  619. /* rgb565 handling */
  620. #define RGB_IN(r, g, b, s)\
  621. {\
  622. unsigned int v = ((UINT16 *)(s))[0];\
  623. r = bitcopy_n(v >> (11 - 3), 3);\
  624. g = bitcopy_n(v >> (5 - 2), 2);\
  625. b = bitcopy_n(v << 3, 3);\
  626. }
  627. #define RGB_OUT(d, r, g, b)\
  628. {\
  629. ((UINT16 *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\
  630. }
  631. #define BPP 2
  632. RGB_FUNCTIONS(rgb565)
  633. #undef RGB_IN
  634. #undef RGB_OUT
  635. #undef BPP
  636. /* bgr24 handling */
  637. #define RGB_IN(r, g, b, s)\
  638. {\
  639. b = (s)[0];\
  640. g = (s)[1];\
  641. r = (s)[2];\
  642. }
  643. #define RGB_OUT(d, r, g, b)\
  644. {\
  645. (d)[0] = b;\
  646. (d)[1] = g;\
  647. (d)[2] = r;\
  648. }
  649. #define BPP 3
  650. RGB_FUNCTIONS(bgr24)
  651. #undef RGB_IN
  652. #undef RGB_OUT
  653. #undef BPP
  654. /* rgb24 handling */
  655. #define RGB_IN(r, g, b, s)\
  656. {\
  657. r = (s)[0];\
  658. g = (s)[1];\
  659. b = (s)[2];\
  660. }
  661. #define RGB_OUT(d, r, g, b)\
  662. {\
  663. (d)[0] = r;\
  664. (d)[1] = g;\
  665. (d)[2] = b;\
  666. }
  667. #define BPP 3
  668. RGB_FUNCTIONS(rgb24)
  669. #undef RGB_IN
  670. #undef RGB_OUT
  671. #undef BPP
  672. /* rgba32 handling */
  673. #define RGB_IN(r, g, b, s)\
  674. {\
  675. unsigned int v = ((UINT32 *)(s))[0];\
  676. r = (v >> 16) & 0xff;\
  677. g = (v >> 8) & 0xff;\
  678. b = v & 0xff;\
  679. }
  680. #define RGB_OUT(d, r, g, b)\
  681. {\
  682. ((UINT32 *)(d))[0] = (0xff << 24) | (r << 16) | (g << 8) | b;\
  683. }
  684. #define BPP 4
  685. RGB_FUNCTIONS(rgba32)
  686. #undef RGB_IN
  687. #undef RGB_OUT
  688. #undef BPP
  689. static void rgb24_to_rgb565(AVPicture *dst, AVPicture *src,
  690. int width, int height)
  691. {
  692. const unsigned char *p;
  693. unsigned char *q;
  694. int r, g, b, dst_wrap, src_wrap;
  695. int x, y;
  696. p = src->data[0];
  697. src_wrap = src->linesize[0] - 3 * width;
  698. q = dst->data[0];
  699. dst_wrap = dst->linesize[0] - 2 * width;
  700. for(y=0;y<height;y++) {
  701. for(x=0;x<width;x++) {
  702. r = p[0];
  703. g = p[1];
  704. b = p[2];
  705. ((unsigned short *)q)[0] =
  706. ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  707. q += 2;
  708. p += 3;
  709. }
  710. p += src_wrap;
  711. q += dst_wrap;
  712. }
  713. }
  714. /* NOTE: we also add a dummy alpha bit */
  715. static void rgb24_to_rgb555(AVPicture *dst, AVPicture *src,
  716. int width, int height)
  717. {
  718. const unsigned char *p;
  719. unsigned char *q;
  720. int r, g, b, dst_wrap, src_wrap;
  721. int x, y;
  722. p = src->data[0];
  723. src_wrap = src->linesize[0] - 3 * width;
  724. q = dst->data[0];
  725. dst_wrap = dst->linesize[0] - 2 * width;
  726. for(y=0;y<height;y++) {
  727. for(x=0;x<width;x++) {
  728. r = p[0];
  729. g = p[1];
  730. b = p[2];
  731. ((unsigned short *)q)[0] =
  732. ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | 0x8000;
  733. q += 2;
  734. p += 3;
  735. }
  736. p += src_wrap;
  737. q += dst_wrap;
  738. }
  739. }
  740. static void mono_to_gray(AVPicture *dst, AVPicture *src,
  741. int width, int height, int xor_mask)
  742. {
  743. const unsigned char *p;
  744. unsigned char *q;
  745. int v, dst_wrap, src_wrap;
  746. int y, w;
  747. p = src->data[0];
  748. src_wrap = src->linesize[0] - ((width + 7) >> 3);
  749. q = dst->data[0];
  750. dst_wrap = dst->linesize[0] - width;
  751. for(y=0;y<height;y++) {
  752. w = width;
  753. while (w >= 8) {
  754. v = *p++ ^ xor_mask;
  755. q[0] = -(v >> 7);
  756. q[1] = -((v >> 6) & 1);
  757. q[2] = -((v >> 5) & 1);
  758. q[3] = -((v >> 4) & 1);
  759. q[4] = -((v >> 3) & 1);
  760. q[5] = -((v >> 2) & 1);
  761. q[6] = -((v >> 1) & 1);
  762. q[7] = -((v >> 0) & 1);
  763. w -= 8;
  764. q += 8;
  765. }
  766. if (w > 0) {
  767. v = *p++ ^ xor_mask;
  768. do {
  769. q[0] = -((v >> 7) & 1);
  770. q++;
  771. v <<= 1;
  772. } while (--w);
  773. }
  774. p += src_wrap;
  775. q += dst_wrap;
  776. }
  777. }
  778. static void monowhite_to_gray(AVPicture *dst, AVPicture *src,
  779. int width, int height)
  780. {
  781. mono_to_gray(dst, src, width, height, 0xff);
  782. }
  783. static void monoblack_to_gray(AVPicture *dst, AVPicture *src,
  784. int width, int height)
  785. {
  786. mono_to_gray(dst, src, width, height, 0x00);
  787. }
  788. static void gray_to_mono(AVPicture *dst, AVPicture *src,
  789. int width, int height, int xor_mask)
  790. {
  791. int n;
  792. const UINT8 *s;
  793. UINT8 *d;
  794. int j, b, v, n1, src_wrap, dst_wrap, y;
  795. s = src->data[0];
  796. src_wrap = src->linesize[0] - width;
  797. d = dst->data[0];
  798. dst_wrap = dst->linesize[0] - ((width + 7) >> 3);
  799. printf("%d %d\n", width, height);
  800. for(y=0;y<height;y++) {
  801. n = width;
  802. while (n >= 8) {
  803. v = 0;
  804. for(j=0;j<8;j++) {
  805. b = s[0];
  806. s++;
  807. v = (v << 1) | (b >> 7);
  808. }
  809. d[0] = v ^ xor_mask;
  810. d++;
  811. n -= 8;
  812. }
  813. if (n > 0) {
  814. n1 = n;
  815. v = 0;
  816. while (n > 0) {
  817. b = s[0];
  818. s++;
  819. v = (v << 1) | (b >> 7);
  820. n--;
  821. }
  822. d[0] = (v << (8 - (n1 & 7))) ^ xor_mask;
  823. d++;
  824. }
  825. s += src_wrap;
  826. d += dst_wrap;
  827. }
  828. }
  829. static void gray_to_monowhite(AVPicture *dst, AVPicture *src,
  830. int width, int height)
  831. {
  832. gray_to_mono(dst, src, width, height, 0xff);
  833. }
  834. static void gray_to_monoblack(AVPicture *dst, AVPicture *src,
  835. int width, int height)
  836. {
  837. gray_to_mono(dst, src, width, height, 0x00);
  838. }
  839. typedef struct ConvertEntry {
  840. void (*convert)(AVPicture *dst, AVPicture *src, int width, int height);
  841. } ConvertEntry;
  842. /* add each new convertion function in this table */
  843. /* constraints;
  844. - all non YUV modes must convert at least to and from PIX_FMT_RGB24
  845. */
  846. static ConvertEntry convert_table[PIX_FMT_NB][PIX_FMT_NB] = {
  847. [PIX_FMT_YUV420P] = {
  848. [PIX_FMT_RGB555] = {
  849. .convert = yuv420p_to_rgb555
  850. },
  851. [PIX_FMT_RGB565] = {
  852. .convert = yuv420p_to_rgb565
  853. },
  854. [PIX_FMT_BGR24] = {
  855. .convert = yuv420p_to_bgr24
  856. },
  857. [PIX_FMT_RGB24] = {
  858. .convert = yuv420p_to_rgb24
  859. },
  860. [PIX_FMT_RGBA32] = {
  861. .convert = yuv420p_to_rgba32
  862. },
  863. },
  864. [PIX_FMT_YUV422P] = {
  865. [PIX_FMT_RGB555] = {
  866. .convert = yuv422p_to_rgb555
  867. },
  868. [PIX_FMT_RGB565] = {
  869. .convert = yuv422p_to_rgb565
  870. },
  871. [PIX_FMT_BGR24] = {
  872. .convert = yuv422p_to_bgr24
  873. },
  874. [PIX_FMT_RGB24] = {
  875. .convert = yuv422p_to_rgb24
  876. },
  877. [PIX_FMT_RGBA32] = {
  878. .convert = yuv422p_to_rgba32
  879. },
  880. },
  881. [PIX_FMT_YUV422] = {
  882. [PIX_FMT_YUV420P] = {
  883. .convert = yuv422_to_yuv420p,
  884. },
  885. },
  886. [PIX_FMT_RGB24] = {
  887. [PIX_FMT_YUV420P] = {
  888. .convert = rgb24_to_yuv420p
  889. },
  890. [PIX_FMT_RGB565] = {
  891. .convert = rgb24_to_rgb565
  892. },
  893. [PIX_FMT_RGB555] = {
  894. .convert = rgb24_to_rgb555
  895. },
  896. [PIX_FMT_GRAY8] = {
  897. .convert = rgb24_to_gray
  898. },
  899. },
  900. [PIX_FMT_RGBA32] = {
  901. [PIX_FMT_YUV420P] = {
  902. .convert = rgba32_to_yuv420p
  903. },
  904. [PIX_FMT_GRAY8] = {
  905. .convert = rgba32_to_gray
  906. },
  907. },
  908. [PIX_FMT_BGR24] = {
  909. [PIX_FMT_YUV420P] = {
  910. .convert = bgr24_to_yuv420p
  911. },
  912. [PIX_FMT_GRAY8] = {
  913. .convert = bgr24_to_gray
  914. },
  915. },
  916. [PIX_FMT_RGB555] = {
  917. [PIX_FMT_YUV420P] = {
  918. .convert = rgb555_to_yuv420p
  919. },
  920. [PIX_FMT_GRAY8] = {
  921. .convert = rgb555_to_gray
  922. },
  923. },
  924. [PIX_FMT_RGB565] = {
  925. [PIX_FMT_YUV420P] = {
  926. .convert = rgb565_to_yuv420p
  927. },
  928. [PIX_FMT_GRAY8] = {
  929. .convert = rgb565_to_gray
  930. },
  931. },
  932. [PIX_FMT_GRAY8] = {
  933. [PIX_FMT_RGB555] = {
  934. .convert = gray_to_rgb555
  935. },
  936. [PIX_FMT_RGB565] = {
  937. .convert = gray_to_rgb565
  938. },
  939. [PIX_FMT_RGB24] = {
  940. .convert = gray_to_rgb24
  941. },
  942. [PIX_FMT_BGR24] = {
  943. .convert = gray_to_bgr24
  944. },
  945. [PIX_FMT_RGBA32] = {
  946. .convert = gray_to_rgba32
  947. },
  948. [PIX_FMT_MONOWHITE] = {
  949. .convert = gray_to_monowhite
  950. },
  951. [PIX_FMT_MONOBLACK] = {
  952. .convert = gray_to_monoblack
  953. },
  954. },
  955. [PIX_FMT_MONOWHITE] = {
  956. [PIX_FMT_GRAY8] = {
  957. .convert = monowhite_to_gray
  958. },
  959. },
  960. [PIX_FMT_MONOBLACK] = {
  961. [PIX_FMT_GRAY8] = {
  962. .convert = monoblack_to_gray
  963. },
  964. },
  965. };
  966. static int avpicture_alloc(AVPicture *picture,
  967. int pix_fmt, int width, int height)
  968. {
  969. int size;
  970. void *ptr;
  971. size = avpicture_get_size(pix_fmt, width, height);
  972. if (size < 0)
  973. goto fail;
  974. ptr = av_malloc(size);
  975. if (!ptr)
  976. goto fail;
  977. avpicture_fill(picture, ptr, pix_fmt, width, height);
  978. return 0;
  979. fail:
  980. memset(picture, 0, sizeof(AVPicture));
  981. return -1;
  982. }
  983. static void avpicture_free(AVPicture *picture)
  984. {
  985. free(picture->data[0]);
  986. }
  987. /* XXX: always use linesize. Return -1 if not supported */
  988. int img_convert(AVPicture *dst, int dst_pix_fmt,
  989. AVPicture *src, int src_pix_fmt,
  990. int src_width, int src_height)
  991. {
  992. int i, ret, dst_width, dst_height, int_pix_fmt;
  993. PixFmtInfo *src_pix, *dst_pix;
  994. ConvertEntry *ce;
  995. AVPicture tmp1, *tmp = &tmp1;
  996. if (src_pix_fmt < 0 || src_pix_fmt >= PIX_FMT_NB ||
  997. dst_pix_fmt < 0 || dst_pix_fmt >= PIX_FMT_NB)
  998. return -1;
  999. if (src_width <= 0 || src_height <= 0)
  1000. return 0;
  1001. dst_width = src_width;
  1002. dst_height = src_height;
  1003. dst_pix = &pix_fmt_info[dst_pix_fmt];
  1004. src_pix = &pix_fmt_info[src_pix_fmt];
  1005. if (src_pix_fmt == dst_pix_fmt) {
  1006. /* XXX: incorrect */
  1007. /* same format: just copy */
  1008. for(i = 0; i < dst_pix->nb_components; i++) {
  1009. int w, h;
  1010. w = dst_width;
  1011. h = dst_height;
  1012. if (dst_pix->is_yuv && (i == 1 || i == 2)) {
  1013. w >>= dst_pix->x_chroma_shift;
  1014. h >>= dst_pix->y_chroma_shift;
  1015. }
  1016. img_copy(dst->data[i], dst->linesize[i],
  1017. src->data[i], src->linesize[i],
  1018. w, h);
  1019. }
  1020. return 0;
  1021. }
  1022. ce = &convert_table[src_pix_fmt][dst_pix_fmt];
  1023. if (ce->convert) {
  1024. /* specific convertion routine */
  1025. ce->convert(dst, src, dst_width, dst_height);
  1026. return 0;
  1027. }
  1028. /* gray to YUV */
  1029. if (dst_pix->is_yuv && src_pix_fmt == PIX_FMT_GRAY8) {
  1030. int w, h, y;
  1031. uint8_t *d;
  1032. img_copy(dst->data[0], dst->linesize[0],
  1033. src->data[0], src->linesize[0],
  1034. dst_width, dst_height);
  1035. /* fill U and V with 128 */
  1036. w = dst_width;
  1037. h = dst_height;
  1038. w >>= dst_pix->x_chroma_shift;
  1039. h >>= dst_pix->y_chroma_shift;
  1040. for(i = 1; i <= 2; i++) {
  1041. d = dst->data[i];
  1042. for(y = 0; y< h; y++) {
  1043. memset(d, 128, w);
  1044. d += dst->linesize[i];
  1045. }
  1046. }
  1047. return 0;
  1048. }
  1049. /* YUV to gray */
  1050. if (src_pix->is_yuv && dst_pix_fmt == PIX_FMT_GRAY8) {
  1051. img_copy(dst->data[0], dst->linesize[0],
  1052. src->data[0], src->linesize[0],
  1053. dst_width, dst_height);
  1054. return 0;
  1055. }
  1056. /* YUV to YUV */
  1057. if (dst_pix->is_yuv && src_pix->is_yuv) {
  1058. int x_shift, y_shift, w, h;
  1059. void (*resize_func)(UINT8 *dst, int dst_wrap,
  1060. UINT8 *src, int src_wrap,
  1061. int width, int height);
  1062. /* compute chroma size of the smallest dimensions */
  1063. w = dst_width;
  1064. h = dst_height;
  1065. if (dst_pix->x_chroma_shift >= src_pix->x_chroma_shift)
  1066. w >>= dst_pix->x_chroma_shift;
  1067. else
  1068. w >>= src_pix->x_chroma_shift;
  1069. if (dst_pix->y_chroma_shift >= src_pix->y_chroma_shift)
  1070. h >>= dst_pix->y_chroma_shift;
  1071. else
  1072. h >>= src_pix->y_chroma_shift;
  1073. x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift);
  1074. y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift);
  1075. if (x_shift == 0 && y_shift == 0) {
  1076. resize_func = img_copy; /* should never happen */
  1077. } else if (x_shift == 0 && y_shift == 1) {
  1078. resize_func = shrink2;
  1079. } else if (x_shift == 1 && y_shift == 1) {
  1080. resize_func = shrink22;
  1081. } else if (x_shift == -1 && y_shift == -1) {
  1082. resize_func = grow22;
  1083. } else if (x_shift == -1 && y_shift == 1) {
  1084. resize_func = conv411;
  1085. } else {
  1086. /* currently not handled */
  1087. return -1;
  1088. }
  1089. img_copy(dst->data[0], dst->linesize[0],
  1090. src->data[0], src->linesize[0],
  1091. dst_width, dst_height);
  1092. for(i = 1;i <= 2; i++)
  1093. resize_func(dst->data[i], dst->linesize[i],
  1094. src->data[i], src->linesize[i],
  1095. w, h);
  1096. return 0;
  1097. }
  1098. /* try to use an intermediate format */
  1099. if (src_pix_fmt == PIX_FMT_MONOWHITE ||
  1100. src_pix_fmt == PIX_FMT_MONOBLACK ||
  1101. dst_pix_fmt == PIX_FMT_MONOWHITE ||
  1102. dst_pix_fmt == PIX_FMT_MONOBLACK) {
  1103. int_pix_fmt = PIX_FMT_GRAY8;
  1104. } else {
  1105. int_pix_fmt = PIX_FMT_RGB24;
  1106. }
  1107. if (avpicture_alloc(tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1108. return -1;
  1109. ret = -1;
  1110. if (img_convert(tmp, int_pix_fmt,
  1111. src, src_pix_fmt, src_width, src_height) < 0)
  1112. goto fail1;
  1113. if (img_convert(dst, dst_pix_fmt,
  1114. tmp, int_pix_fmt, dst_width, dst_height) < 0)
  1115. goto fail1;
  1116. ret = 0;
  1117. fail1:
  1118. avpicture_free(tmp);
  1119. return ret;
  1120. }
  1121. #ifdef HAVE_MMX
  1122. #define DEINT_INPLACE_LINE_LUM \
  1123. movd_m2r(lum_m4[0],mm0);\
  1124. movd_m2r(lum_m3[0],mm1);\
  1125. movd_m2r(lum_m2[0],mm2);\
  1126. movd_m2r(lum_m1[0],mm3);\
  1127. movd_m2r(lum[0],mm4);\
  1128. punpcklbw_r2r(mm7,mm0);\
  1129. movd_r2m(mm2,lum_m4[0]);\
  1130. punpcklbw_r2r(mm7,mm1);\
  1131. punpcklbw_r2r(mm7,mm2);\
  1132. punpcklbw_r2r(mm7,mm3);\
  1133. punpcklbw_r2r(mm7,mm4);\
  1134. paddw_r2r(mm3,mm1);\
  1135. psllw_i2r(1,mm2);\
  1136. paddw_r2r(mm4,mm0);\
  1137. psllw_i2r(2,mm1);\
  1138. paddw_r2r(mm6,mm2);\
  1139. paddw_r2r(mm2,mm1);\
  1140. psubusw_r2r(mm0,mm1);\
  1141. psrlw_i2r(3,mm1);\
  1142. packuswb_r2r(mm7,mm1);\
  1143. movd_r2m(mm1,lum_m2[0]);
  1144. #define DEINT_LINE_LUM \
  1145. movd_m2r(lum_m4[0],mm0);\
  1146. movd_m2r(lum_m3[0],mm1);\
  1147. movd_m2r(lum_m2[0],mm2);\
  1148. movd_m2r(lum_m1[0],mm3);\
  1149. movd_m2r(lum[0],mm4);\
  1150. punpcklbw_r2r(mm7,mm0);\
  1151. punpcklbw_r2r(mm7,mm1);\
  1152. punpcklbw_r2r(mm7,mm2);\
  1153. punpcklbw_r2r(mm7,mm3);\
  1154. punpcklbw_r2r(mm7,mm4);\
  1155. paddw_r2r(mm3,mm1);\
  1156. psllw_i2r(1,mm2);\
  1157. paddw_r2r(mm4,mm0);\
  1158. psllw_i2r(2,mm1);\
  1159. paddw_r2r(mm6,mm2);\
  1160. paddw_r2r(mm2,mm1);\
  1161. psubusw_r2r(mm0,mm1);\
  1162. psrlw_i2r(3,mm1);\
  1163. packuswb_r2r(mm7,mm1);\
  1164. movd_r2m(mm1,dst[0]);
  1165. #endif
  1166. /* filter parameters: [-1 4 2 4 -1] // 8 */
  1167. static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  1168. int size)
  1169. {
  1170. #ifndef HAVE_MMX
  1171. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  1172. int sum;
  1173. for(;size > 0;size--) {
  1174. sum = -lum_m4[0];
  1175. sum += lum_m3[0] << 2;
  1176. sum += lum_m2[0] << 1;
  1177. sum += lum_m1[0] << 2;
  1178. sum += -lum[0];
  1179. dst[0] = cm[(sum + 4) >> 3];
  1180. lum_m4++;
  1181. lum_m3++;
  1182. lum_m2++;
  1183. lum_m1++;
  1184. lum++;
  1185. dst++;
  1186. }
  1187. #else
  1188. for (;size > 3; size-=4) {
  1189. DEINT_LINE_LUM
  1190. lum_m4+=4;
  1191. lum_m3+=4;
  1192. lum_m2+=4;
  1193. lum_m1+=4;
  1194. lum+=4;
  1195. dst+=4;
  1196. }
  1197. #endif
  1198. }
  1199. static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  1200. int size)
  1201. {
  1202. #ifndef HAVE_MMX
  1203. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  1204. int sum;
  1205. for(;size > 0;size--) {
  1206. sum = -lum_m4[0];
  1207. sum += lum_m3[0] << 2;
  1208. sum += lum_m2[0] << 1;
  1209. lum_m4[0]=lum_m2[0];
  1210. sum += lum_m1[0] << 2;
  1211. sum += -lum[0];
  1212. lum_m2[0] = cm[(sum + 4) >> 3];
  1213. lum_m4++;
  1214. lum_m3++;
  1215. lum_m2++;
  1216. lum_m1++;
  1217. lum++;
  1218. }
  1219. #else
  1220. for (;size > 3; size-=4) {
  1221. DEINT_INPLACE_LINE_LUM
  1222. lum_m4+=4;
  1223. lum_m3+=4;
  1224. lum_m2+=4;
  1225. lum_m1+=4;
  1226. lum+=4;
  1227. }
  1228. #endif
  1229. }
  1230. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  1231. top field is copied as is, but the bottom field is deinterlaced
  1232. against the top field. */
  1233. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  1234. UINT8 *src1, int src_wrap,
  1235. int width, int height)
  1236. {
  1237. UINT8 *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  1238. int y;
  1239. src_m2 = src1;
  1240. src_m1 = src1;
  1241. src_0=&src_m1[src_wrap];
  1242. src_p1=&src_0[src_wrap];
  1243. src_p2=&src_p1[src_wrap];
  1244. for(y=0;y<(height-2);y+=2) {
  1245. memcpy(dst,src_m1,width);
  1246. dst += dst_wrap;
  1247. deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  1248. src_m2 = src_0;
  1249. src_m1 = src_p1;
  1250. src_0 = src_p2;
  1251. src_p1 += 2*src_wrap;
  1252. src_p2 += 2*src_wrap;
  1253. dst += dst_wrap;
  1254. }
  1255. memcpy(dst,src_m1,width);
  1256. dst += dst_wrap;
  1257. /* do last line */
  1258. deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  1259. }
  1260. static void deinterlace_bottom_field_inplace(UINT8 *src1, int src_wrap,
  1261. int width, int height)
  1262. {
  1263. UINT8 *src_m1, *src_0, *src_p1, *src_p2;
  1264. int y;
  1265. UINT8 *buf;
  1266. buf = (UINT8*)av_malloc(width);
  1267. src_m1 = src1;
  1268. memcpy(buf,src_m1,width);
  1269. src_0=&src_m1[src_wrap];
  1270. src_p1=&src_0[src_wrap];
  1271. src_p2=&src_p1[src_wrap];
  1272. for(y=0;y<(height-2);y+=2) {
  1273. deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  1274. src_m1 = src_p1;
  1275. src_0 = src_p2;
  1276. src_p1 += 2*src_wrap;
  1277. src_p2 += 2*src_wrap;
  1278. }
  1279. /* do last line */
  1280. deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  1281. av_free(buf);
  1282. }
  1283. /* deinterlace - if not supported return -1 */
  1284. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  1285. int pix_fmt, int width, int height)
  1286. {
  1287. int i;
  1288. if (pix_fmt != PIX_FMT_YUV420P &&
  1289. pix_fmt != PIX_FMT_YUV422P &&
  1290. pix_fmt != PIX_FMT_YUV444P)
  1291. return -1;
  1292. if ((width & 3) != 0 || (height & 3) != 0)
  1293. return -1;
  1294. #ifdef HAVE_MMX
  1295. {
  1296. mmx_t rounder;
  1297. rounder.uw[0]=4;
  1298. rounder.uw[1]=4;
  1299. rounder.uw[2]=4;
  1300. rounder.uw[3]=4;
  1301. pxor_r2r(mm7,mm7);
  1302. movq_m2r(rounder,mm6);
  1303. }
  1304. #endif
  1305. for(i=0;i<3;i++) {
  1306. if (i == 1) {
  1307. switch(pix_fmt) {
  1308. case PIX_FMT_YUV420P:
  1309. width >>= 1;
  1310. height >>= 1;
  1311. break;
  1312. case PIX_FMT_YUV422P:
  1313. width >>= 1;
  1314. break;
  1315. default:
  1316. break;
  1317. }
  1318. }
  1319. if (src == dst) {
  1320. deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
  1321. width, height);
  1322. } else {
  1323. deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  1324. src->data[i], src->linesize[i],
  1325. width, height);
  1326. }
  1327. }
  1328. #ifdef HAVE_MMX
  1329. emms();
  1330. #endif
  1331. return 0;
  1332. }
  1333. #undef FIX