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.

834 lines
24KB

  1. /*
  2. * Misc image convertion routines
  3. * Copyright (c) 2001, 2002 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. /* XXX: totally non optimized */
  25. static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  26. UINT8 *src, int width, int height)
  27. {
  28. int x, y;
  29. UINT8 *p = src;
  30. for(y=0;y<height;y+=2) {
  31. for(x=0;x<width;x+=2) {
  32. lum[0] = p[0];
  33. cb[0] = p[1];
  34. lum[1] = p[2];
  35. cr[0] = p[3];
  36. p += 4;
  37. lum += 2;
  38. cb++;
  39. cr++;
  40. }
  41. for(x=0;x<width;x+=2) {
  42. lum[0] = p[0];
  43. lum[1] = p[2];
  44. p += 4;
  45. lum += 2;
  46. }
  47. }
  48. }
  49. #define SCALEBITS 8
  50. #define ONE_HALF (1 << (SCALEBITS - 1))
  51. #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
  52. static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  53. UINT8 *src, int width, int height)
  54. {
  55. int wrap, wrap3, x, y;
  56. int r, g, b, r1, g1, b1;
  57. UINT8 *p;
  58. wrap = width;
  59. wrap3 = width * 3;
  60. p = src;
  61. for(y=0;y<height;y+=2) {
  62. for(x=0;x<width;x+=2) {
  63. r = p[0];
  64. g = p[1];
  65. b = p[2];
  66. r1 = r;
  67. g1 = g;
  68. b1 = b;
  69. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  70. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  71. r = p[3];
  72. g = p[4];
  73. b = p[5];
  74. r1 += r;
  75. g1 += g;
  76. b1 += b;
  77. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  78. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  79. p += wrap3;
  80. lum += wrap;
  81. r = p[0];
  82. g = p[1];
  83. b = p[2];
  84. r1 += r;
  85. g1 += g;
  86. b1 += b;
  87. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  88. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  89. r = p[3];
  90. g = p[4];
  91. b = p[5];
  92. r1 += r;
  93. g1 += g;
  94. b1 += b;
  95. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  96. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  97. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  98. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  99. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  100. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  101. cb++;
  102. cr++;
  103. p += -wrap3 + 2 * 3;
  104. lum += -wrap + 2;
  105. }
  106. p += wrap3;
  107. lum += wrap;
  108. }
  109. }
  110. static void rgba32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  111. UINT8 *src, int width, int height)
  112. {
  113. int wrap, wrap4, x, y;
  114. int r, g, b, r1, g1, b1;
  115. UINT8 *p;
  116. wrap = width;
  117. wrap4 = width * 4;
  118. p = src;
  119. for(y=0;y<height;y+=2) {
  120. for(x=0;x<width;x+=2) {
  121. r = p[0];
  122. g = p[1];
  123. b = p[2];
  124. r1 = r;
  125. g1 = g;
  126. b1 = b;
  127. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  128. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  129. r = p[4];
  130. g = p[5];
  131. b = p[6];
  132. r1 += r;
  133. g1 += g;
  134. b1 += b;
  135. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  136. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  137. p += wrap4;
  138. lum += wrap;
  139. r = p[0];
  140. g = p[1];
  141. b = p[2];
  142. r1 += r;
  143. g1 += g;
  144. b1 += b;
  145. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  146. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  147. r = p[4];
  148. g = p[5];
  149. b = p[6];
  150. r1 += r;
  151. g1 += g;
  152. b1 += b;
  153. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  154. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  155. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  156. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  157. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  158. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  159. cb++;
  160. cr++;
  161. p += -wrap4 + 2 * 4;
  162. lum += -wrap + 2;
  163. }
  164. p += wrap4;
  165. lum += wrap;
  166. }
  167. }
  168. static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  169. UINT8 *src, int width, int height)
  170. {
  171. int wrap, wrap3, x, y;
  172. int r, g, b, r1, g1, b1;
  173. UINT8 *p;
  174. wrap = width;
  175. wrap3 = width * 3;
  176. p = src;
  177. for(y=0;y<height;y+=2) {
  178. for(x=0;x<width;x+=2) {
  179. b = p[0];
  180. g = p[1];
  181. r = p[2];
  182. r1 = r;
  183. g1 = g;
  184. b1 = b;
  185. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  186. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  187. b = p[3];
  188. g = p[4];
  189. r = p[5];
  190. r1 += r;
  191. g1 += g;
  192. b1 += b;
  193. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  194. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  195. p += wrap3;
  196. lum += wrap;
  197. b = p[0];
  198. g = p[1];
  199. r = p[2];
  200. r1 += r;
  201. g1 += g;
  202. b1 += b;
  203. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  204. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  205. b = p[3];
  206. g = p[4];
  207. r = p[5];
  208. r1 += r;
  209. g1 += g;
  210. b1 += b;
  211. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  212. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  213. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  214. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  215. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  216. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  217. cb++;
  218. cr++;
  219. p += -wrap3 + 2 * 3;
  220. lum += -wrap + 2;
  221. }
  222. p += wrap3;
  223. lum += wrap;
  224. }
  225. }
  226. static void bgra32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  227. UINT8 *src, int width, int height)
  228. {
  229. int wrap, wrap4, x, y;
  230. int r, g, b, r1, g1, b1;
  231. UINT8 *p;
  232. wrap = width;
  233. wrap4 = width * 4;
  234. p = src;
  235. for(y=0;y<height;y+=2) {
  236. for(x=0;x<width;x+=2) {
  237. b = p[0];
  238. g = p[1];
  239. r = p[2];
  240. r1 = r;
  241. g1 = g;
  242. b1 = b;
  243. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  244. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  245. b = p[4];
  246. g = p[5];
  247. r = p[6];
  248. r1 += r;
  249. g1 += g;
  250. b1 += b;
  251. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  252. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  253. p += wrap4;
  254. lum += wrap;
  255. b = p[0];
  256. g = p[1];
  257. r = p[2];
  258. r1 += r;
  259. g1 += g;
  260. b1 += b;
  261. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  262. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  263. b = p[4];
  264. g = p[5];
  265. r = p[6];
  266. r1 += r;
  267. g1 += g;
  268. b1 += b;
  269. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  270. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  271. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  272. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  273. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  274. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  275. cb++;
  276. cr++;
  277. p += -wrap4 + 2 * 4;
  278. lum += -wrap + 2;
  279. }
  280. p += wrap4;
  281. lum += wrap;
  282. }
  283. }
  284. /* XXX: use generic filter ? */
  285. /* 1x2 -> 1x1 */
  286. static void shrink2(UINT8 *dst, int dst_wrap,
  287. UINT8 *src, int src_wrap,
  288. int width, int height)
  289. {
  290. int w;
  291. UINT8 *s1, *s2, *d;
  292. for(;height > 0; height--) {
  293. s1 = src;
  294. s2 = s1 + src_wrap;
  295. d = dst;
  296. for(w = width;w >= 4; w-=4) {
  297. d[0] = (s1[0] + s2[0]) >> 1;
  298. d[1] = (s1[1] + s2[1]) >> 1;
  299. d[2] = (s1[2] + s2[2]) >> 1;
  300. d[3] = (s1[3] + s2[3]) >> 1;
  301. s1 += 4;
  302. s2 += 4;
  303. d += 4;
  304. }
  305. for(;w > 0; w--) {
  306. d[0] = (s1[0] + s2[0]) >> 1;
  307. s1++;
  308. s2++;
  309. d++;
  310. }
  311. src += 2 * src_wrap;
  312. dst += dst_wrap;
  313. }
  314. }
  315. /* 2x2 -> 1x1 */
  316. static void shrink22(UINT8 *dst, int dst_wrap,
  317. UINT8 *src, int src_wrap,
  318. int width, int height)
  319. {
  320. int w;
  321. UINT8 *s1, *s2, *d;
  322. for(;height > 0; height--) {
  323. s1 = src;
  324. s2 = s1 + src_wrap;
  325. d = dst;
  326. for(w = width;w >= 4; w-=4) {
  327. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  328. d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
  329. d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
  330. d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
  331. s1 += 8;
  332. s2 += 8;
  333. d += 4;
  334. }
  335. for(;w > 0; w--) {
  336. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  337. s1 += 2;
  338. s2 += 2;
  339. d++;
  340. }
  341. src += 2 * src_wrap;
  342. dst += dst_wrap;
  343. }
  344. }
  345. /* 1x1 -> 2x2 */
  346. static void grow22(UINT8 *dst, int dst_wrap,
  347. UINT8 *src, int src_wrap,
  348. int width, int height)
  349. {
  350. int w;
  351. UINT8 *s1, *d;
  352. for(;height > 0; height--) {
  353. s1 = src;
  354. d = dst;
  355. for(w = width;w >= 4; w-=4) {
  356. d[1] = d[0] = s1[0];
  357. d[3] = d[2] = s1[1];
  358. s1 += 2;
  359. d += 4;
  360. }
  361. for(;w > 0; w--) {
  362. d[0] = s1[0];
  363. s1 ++;
  364. d++;
  365. }
  366. if (height%2)
  367. src += src_wrap;
  368. dst += dst_wrap;
  369. }
  370. }
  371. static void img_copy(UINT8 *dst, int dst_wrap,
  372. UINT8 *src, int src_wrap,
  373. int width, int height)
  374. {
  375. for(;height > 0; height--) {
  376. memcpy(dst, src, width);
  377. dst += dst_wrap;
  378. src += src_wrap;
  379. }
  380. }
  381. #define SCALE_BITS 10
  382. #define C_Y (76309 >> (16 - SCALE_BITS))
  383. #define C_RV (117504 >> (16 - SCALE_BITS))
  384. #define C_BU (138453 >> (16 - SCALE_BITS))
  385. #define C_GU (13954 >> (16 - SCALE_BITS))
  386. #define C_GV (34903 >> (16 - SCALE_BITS))
  387. #define RGBOUT(r, g, b, y1)\
  388. {\
  389. y = (y1 - 16) * C_Y;\
  390. r = cm[(y + r_add) >> SCALE_BITS];\
  391. g = cm[(y + g_add) >> SCALE_BITS];\
  392. b = cm[(y + b_add) >> SCALE_BITS];\
  393. }
  394. /* XXX: no chroma interpolating is done */
  395. static void yuv420p_to_bgra32(AVPicture *dst, AVPicture *src,
  396. int width, int height)
  397. {
  398. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  399. int w, y, cb, cr, r_add, g_add, b_add, width2;
  400. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  401. d = dst->data[0];
  402. y1_ptr = src->data[0];
  403. cb_ptr = src->data[1];
  404. cr_ptr = src->data[2];
  405. width2 = width >> 1;
  406. for(;height > 0; height -= 2) {
  407. d1 = d;
  408. d2 = d + dst->linesize[0];
  409. y2_ptr = y1_ptr + src->linesize[0];
  410. for(w = width2; w > 0; w --) {
  411. cb = cb_ptr[0] - 128;
  412. cr = cr_ptr[0] - 128;
  413. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  414. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  415. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  416. /* output 4 pixels */
  417. RGBOUT(d1[2], d1[1], d1[0], y1_ptr[0]);
  418. RGBOUT(d1[6], d1[5], d1[4], y1_ptr[1]);
  419. RGBOUT(d2[2], d2[1], d2[0], y2_ptr[0]);
  420. RGBOUT(d2[6], d2[5], d2[4], y2_ptr[1]);
  421. d1[3] = d1[7] = d2[3] = d2[7] = 255;
  422. d1 += 8;
  423. d2 += 8;
  424. y1_ptr += 2;
  425. y2_ptr += 2;
  426. cb_ptr++;
  427. cr_ptr++;
  428. }
  429. d += 2 * dst->linesize[0];
  430. y1_ptr += 2 * src->linesize[0] - width;
  431. cb_ptr += src->linesize[1] - width2;
  432. cr_ptr += src->linesize[2] - width2;
  433. }
  434. }
  435. /* XXX: no chroma interpolating is done */
  436. static void yuv420p_to_rgba32(AVPicture *dst, AVPicture *src,
  437. int width, int height)
  438. {
  439. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  440. int w, y, cb, cr, r_add, g_add, b_add, width2;
  441. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  442. d = dst->data[0];
  443. y1_ptr = src->data[0];
  444. cb_ptr = src->data[1];
  445. cr_ptr = src->data[2];
  446. width2 = width >> 1;
  447. for(;height > 0; height -= 2) {
  448. d1 = d;
  449. d2 = d + dst->linesize[0];
  450. y2_ptr = y1_ptr + src->linesize[0];
  451. for(w = width2; w > 0; w --) {
  452. cb = cb_ptr[0] - 128;
  453. cr = cr_ptr[0] - 128;
  454. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  455. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  456. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  457. /* output 4 pixels */
  458. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  459. RGBOUT(d1[4], d1[5], d1[6], y1_ptr[1]);
  460. RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
  461. RGBOUT(d2[4], d2[5], d2[6], y2_ptr[1]);
  462. d1[3] = d1[7] = d2[3] = d2[7] = 255;
  463. d1 += 8;
  464. d2 += 8;
  465. y1_ptr += 2;
  466. y2_ptr += 2;
  467. cb_ptr++;
  468. cr_ptr++;
  469. }
  470. d += 2 * dst->linesize[0];
  471. y1_ptr += 2 * src->linesize[0] - width;
  472. cb_ptr += src->linesize[1] - width2;
  473. cr_ptr += src->linesize[2] - width2;
  474. }
  475. }
  476. /* XXX: no chroma interpolating is done */
  477. static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src,
  478. int width, int height)
  479. {
  480. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  481. int w, y, cb, cr, r_add, g_add, b_add, width2;
  482. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  483. d = dst->data[0];
  484. y1_ptr = src->data[0];
  485. cb_ptr = src->data[1];
  486. cr_ptr = src->data[2];
  487. width2 = width >> 1;
  488. for(;height > 0; height -= 2) {
  489. d1 = d;
  490. d2 = d + dst->linesize[0];
  491. y2_ptr = y1_ptr + src->linesize[0];
  492. for(w = width2; w > 0; w --) {
  493. cb = cb_ptr[0] - 128;
  494. cr = cr_ptr[0] - 128;
  495. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  496. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  497. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  498. /* output 4 pixels */
  499. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  500. RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  501. RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
  502. RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]);
  503. d1 += 6;
  504. d2 += 6;
  505. y1_ptr += 2;
  506. y2_ptr += 2;
  507. cb_ptr++;
  508. cr_ptr++;
  509. }
  510. d += 2 * dst->linesize[0];
  511. y1_ptr += 2 * src->linesize[0] - width;
  512. cb_ptr += src->linesize[1] - width2;
  513. cr_ptr += src->linesize[2] - width2;
  514. }
  515. }
  516. /* XXX: no chroma interpolating is done */
  517. static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src,
  518. int width, int height)
  519. {
  520. UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;
  521. int w, y, cb, cr, r_add, g_add, b_add, width2;
  522. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  523. d = dst->data[0];
  524. y1_ptr = src->data[0];
  525. cb_ptr = src->data[1];
  526. cr_ptr = src->data[2];
  527. width2 = width >> 1;
  528. for(;height > 0; height --) {
  529. d1 = d;
  530. for(w = width2; w > 0; w --) {
  531. cb = cb_ptr[0] - 128;
  532. cr = cr_ptr[0] - 128;
  533. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  534. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  535. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  536. /* output 2 pixels */
  537. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  538. RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  539. d1 += 6;
  540. y1_ptr += 2;
  541. cb_ptr++;
  542. cr_ptr++;
  543. }
  544. d += dst->linesize[0];
  545. y1_ptr += src->linesize[0] - width;
  546. cb_ptr += src->linesize[1] - width2;
  547. cr_ptr += src->linesize[2] - width2;
  548. }
  549. }
  550. /* XXX: always use linesize. Return -1 if not supported */
  551. int img_convert(AVPicture *dst, int dst_pix_fmt,
  552. AVPicture *src, int pix_fmt,
  553. int width, int height)
  554. {
  555. int i;
  556. assert(pix_fmt != PIX_FMT_ANY && dst_pix_fmt != PIX_FMT_ANY);
  557. if (dst_pix_fmt == pix_fmt) {
  558. switch(pix_fmt) {
  559. case PIX_FMT_YUV420P:
  560. for(i=0;i<3;i++) {
  561. if (i == 1) {
  562. width >>= 1;
  563. height >>= 1;
  564. }
  565. img_copy(dst->data[i], dst->linesize[i],
  566. src->data[i], src->linesize[i],
  567. width, height);
  568. }
  569. break;
  570. default:
  571. return -1;
  572. }
  573. } else if (dst_pix_fmt == PIX_FMT_YUV420P) {
  574. switch(pix_fmt) {
  575. case PIX_FMT_YUV410P:
  576. img_copy(dst->data[0], dst->linesize[0],
  577. src->data[0], src->linesize[0],
  578. width, height);
  579. grow22(dst->data[1], dst->linesize[1],
  580. src->data[1], src->linesize[1],
  581. width/2, height/2);
  582. grow22(dst->data[2], dst->linesize[2],
  583. src->data[2], src->linesize[2],
  584. width/2, height/2);
  585. break;
  586. case PIX_FMT_YUV420P:
  587. for(i=0;i<3;i++) {
  588. img_copy(dst->data[i], dst->linesize[i],
  589. src->data[i], src->linesize[i],
  590. width, height);
  591. }
  592. break;
  593. case PIX_FMT_YUV422P:
  594. img_copy(dst->data[0], dst->linesize[0],
  595. src->data[0], src->linesize[0],
  596. width, height);
  597. width >>= 1;
  598. height >>= 1;
  599. for(i=1;i<3;i++) {
  600. shrink2(dst->data[i], dst->linesize[i],
  601. src->data[i], src->linesize[i],
  602. width, height);
  603. }
  604. break;
  605. case PIX_FMT_YUV444P:
  606. img_copy(dst->data[0], dst->linesize[0],
  607. src->data[0], src->linesize[0],
  608. width, height);
  609. width >>= 1;
  610. height >>= 1;
  611. for(i=1;i<3;i++) {
  612. shrink22(dst->data[i], dst->linesize[i],
  613. src->data[i], src->linesize[i],
  614. width, height);
  615. }
  616. break;
  617. case PIX_FMT_YUV422:
  618. yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  619. src->data[0], width, height);
  620. break;
  621. case PIX_FMT_RGB24:
  622. rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  623. src->data[0], width, height);
  624. break;
  625. case PIX_FMT_RGBA32:
  626. rgba32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  627. src->data[0], width, height);
  628. break;
  629. case PIX_FMT_BGR24:
  630. bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  631. src->data[0], width, height);
  632. break;
  633. case PIX_FMT_BGRA32:
  634. bgra32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  635. src->data[0], width, height);
  636. break;
  637. default:
  638. return -1;
  639. }
  640. } else if (dst_pix_fmt == PIX_FMT_RGB24) {
  641. switch(pix_fmt) {
  642. case PIX_FMT_YUV420P:
  643. yuv420p_to_rgb24(dst, src, width, height);
  644. break;
  645. case PIX_FMT_YUV422P:
  646. yuv422p_to_rgb24(dst, src, width, height);
  647. break;
  648. default:
  649. return -1;
  650. }
  651. } else if (dst_pix_fmt == PIX_FMT_RGBA32) {
  652. switch(pix_fmt) {
  653. case PIX_FMT_YUV420P:
  654. yuv420p_to_rgba32(dst, src, width, height);
  655. break;
  656. default:
  657. return -1;
  658. }
  659. } else if (dst_pix_fmt == PIX_FMT_BGRA32) {
  660. switch(pix_fmt) {
  661. case PIX_FMT_YUV420P:
  662. yuv420p_to_bgra32(dst, src, width, height);
  663. break;
  664. default:
  665. return -1;
  666. }
  667. } else {
  668. return -1;
  669. }
  670. return 0;
  671. }
  672. /* filter parameters: [-1 4 2 4 -1] // 8 */
  673. static void deinterlace_line(UINT8 *dst, UINT8 *src, int src_wrap,
  674. int size)
  675. {
  676. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  677. int sum;
  678. UINT8 *s;
  679. for(;size > 0;size--) {
  680. s = src;
  681. sum = -s[0];
  682. s += src_wrap;
  683. sum += s[0] << 2;
  684. s += src_wrap;
  685. sum += s[0] << 1;
  686. s += src_wrap;
  687. sum += s[0] << 2;
  688. s += src_wrap;
  689. sum += -s[0];
  690. dst[0] = cm[(sum + 4) >> 3];
  691. dst++;
  692. src++;
  693. }
  694. }
  695. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  696. top field is copied as is, but the bottom field is deinterlaced
  697. against the top field. */
  698. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  699. UINT8 *src1, int src_wrap,
  700. int width, int height)
  701. {
  702. UINT8 *src, *ptr;
  703. int y, y1, i;
  704. UINT8 *buf;
  705. buf = (UINT8*)av_malloc(5 * width);
  706. src = src1;
  707. for(y=0;y<height;y+=2) {
  708. /* copy top field line */
  709. memcpy(dst, src, width);
  710. dst += dst_wrap;
  711. src += (1 - 2) * src_wrap;
  712. y1 = y - 2;
  713. if (y1 >= 0 && (y1 + 4) < height) {
  714. /* fast case : no edges */
  715. deinterlace_line(dst, src, src_wrap, width);
  716. } else {
  717. /* in order to use the same function, we use an intermediate buffer */
  718. ptr = buf;
  719. for(i=0;i<5;i++) {
  720. if (y1 < 0)
  721. memcpy(ptr, src1, width);
  722. else if (y1 >= height)
  723. memcpy(ptr, src1 + (height - 1) * src_wrap, width);
  724. else
  725. memcpy(ptr, src1 + y1 * src_wrap, width);
  726. y1++;
  727. ptr += width;
  728. }
  729. deinterlace_line(dst, buf, width, width);
  730. }
  731. dst += dst_wrap;
  732. src += (2 + 1) * src_wrap;
  733. }
  734. av_free(buf);
  735. }
  736. /* deinterlace, return -1 if format not handled */
  737. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  738. int pix_fmt, int width, int height)
  739. {
  740. int i;
  741. if (pix_fmt != PIX_FMT_YUV420P &&
  742. pix_fmt != PIX_FMT_YUV422P &&
  743. pix_fmt != PIX_FMT_YUV444P)
  744. return -1;
  745. if ((width & 1) != 0 || (height & 3) != 0)
  746. return -1;
  747. for(i=0;i<3;i++) {
  748. if (i == 1) {
  749. switch(pix_fmt) {
  750. case PIX_FMT_YUV420P:
  751. width >>= 1;
  752. height >>= 1;
  753. break;
  754. case PIX_FMT_YUV422P:
  755. width >>= 1;
  756. break;
  757. default:
  758. break;
  759. }
  760. }
  761. deinterlace_bottom_field(dst->data[i], dst->linesize[i],
  762. src->data[i], src->linesize[i],
  763. width, height);
  764. }
  765. return 0;
  766. }
  767. #undef FIX