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.

1110 lines
34KB

  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. #ifdef HAVE_MMX
  25. #include "i386/mmx.h"
  26. #endif
  27. /* XXX: totally non optimized */
  28. static void yuv422_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  29. UINT8 *src, int width, int height)
  30. {
  31. int x, y;
  32. UINT8 *p = src;
  33. for(y=0;y<height;y+=2) {
  34. for(x=0;x<width;x+=2) {
  35. lum[0] = p[0];
  36. cb[0] = p[1];
  37. lum[1] = p[2];
  38. cr[0] = p[3];
  39. p += 4;
  40. lum += 2;
  41. cb++;
  42. cr++;
  43. }
  44. for(x=0;x<width;x+=2) {
  45. lum[0] = p[0];
  46. lum[1] = p[2];
  47. p += 4;
  48. lum += 2;
  49. }
  50. }
  51. }
  52. #define SCALEBITS 8
  53. #define ONE_HALF (1 << (SCALEBITS - 1))
  54. #define FIX(x) ((int) ((x) * (1L<<SCALEBITS) + 0.5))
  55. static void rgb24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  56. UINT8 *src, int width, int height)
  57. {
  58. int wrap, wrap3, x, y;
  59. int r, g, b, r1, g1, b1;
  60. UINT8 *p;
  61. wrap = width;
  62. wrap3 = width * 3;
  63. p = src;
  64. for(y=0;y<height;y+=2) {
  65. for(x=0;x<width;x+=2) {
  66. r = p[0];
  67. g = p[1];
  68. b = p[2];
  69. r1 = r;
  70. g1 = g;
  71. b1 = b;
  72. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  73. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  74. r = p[3];
  75. g = p[4];
  76. b = p[5];
  77. r1 += r;
  78. g1 += g;
  79. b1 += b;
  80. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  81. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  82. p += wrap3;
  83. lum += wrap;
  84. r = p[0];
  85. g = p[1];
  86. b = p[2];
  87. r1 += r;
  88. g1 += g;
  89. b1 += b;
  90. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  91. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  92. r = p[3];
  93. g = p[4];
  94. b = p[5];
  95. r1 += r;
  96. g1 += g;
  97. b1 += b;
  98. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  99. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  100. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  101. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  102. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  103. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  104. cb++;
  105. cr++;
  106. p += -wrap3 + 2 * 3;
  107. lum += -wrap + 2;
  108. }
  109. p += wrap3;
  110. lum += wrap;
  111. }
  112. }
  113. static void rgba32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  114. UINT8 *src, int width, int height)
  115. {
  116. int wrap, wrap4, x, y;
  117. int r, g, b, r1, g1, b1;
  118. UINT8 *p;
  119. wrap = width;
  120. wrap4 = width * 4;
  121. p = src;
  122. for(y=0;y<height;y+=2) {
  123. for(x=0;x<width;x+=2) {
  124. r = p[0];
  125. g = p[1];
  126. b = p[2];
  127. r1 = r;
  128. g1 = g;
  129. b1 = b;
  130. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  131. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  132. r = p[4];
  133. g = p[5];
  134. b = p[6];
  135. r1 += r;
  136. g1 += g;
  137. b1 += b;
  138. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  139. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  140. p += wrap4;
  141. lum += wrap;
  142. r = p[0];
  143. g = p[1];
  144. b = p[2];
  145. r1 += r;
  146. g1 += g;
  147. b1 += b;
  148. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  149. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  150. r = p[4];
  151. g = p[5];
  152. b = p[6];
  153. r1 += r;
  154. g1 += g;
  155. b1 += b;
  156. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  157. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  158. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  159. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  160. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  161. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  162. cb++;
  163. cr++;
  164. p += -wrap4 + 2 * 4;
  165. lum += -wrap + 2;
  166. }
  167. p += wrap4;
  168. lum += wrap;
  169. }
  170. }
  171. #define rgb565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0800,31, 0x0020,63,0x0001,31)
  172. #define rgb555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0400,31, 0x0020,31,0x0001,31)
  173. #define rgb5551_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0800,31, 0x0040,31,0x0002,31)
  174. #define bgr565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0020,63,0x0800,31)
  175. #define bgr555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0020,31,0x0400,31)
  176. #define gbr565_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0800,31,0x0040,63)
  177. #define gbr555_to_yuv420p(lum,cb,cr,src,width,height) rgbmisc_to_yuv420p((lum),(cb),(cr),(src),(width),(height),0x0001,31, 0x0400,31,0x0020,31)
  178. static void rgbmisc_to_yuv420p
  179. (UINT8 *lum, UINT8 *cb, UINT8 *cr,
  180. UINT8 *src, int width, int height,
  181. UINT16 R_LOWMASK, UINT16 R_MAX,
  182. UINT16 G_LOWMASK, UINT16 G_MAX,
  183. UINT16 B_LOWMASK, UINT16 B_MAX
  184. )
  185. {
  186. int wrap, wrap2, x, y;
  187. int r, g, b, r1, g1, b1;
  188. UINT8 *p;
  189. UINT16 pixel;
  190. wrap = width;
  191. wrap2 = width * 2;
  192. p = src;
  193. for(y=0;y<height;y+=2) {
  194. for(x=0;x<width;x+=2) {
  195. pixel = p[0] | (p[1]<<8);
  196. r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
  197. g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
  198. b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
  199. r1 = r;
  200. g1 = g;
  201. b1 = b;
  202. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  203. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  204. pixel = p[2] | (p[3]<<8);
  205. r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
  206. g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
  207. b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
  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. p += wrap2;
  214. lum += wrap;
  215. pixel = p[0] | (p[1]<<8);
  216. r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
  217. g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
  218. b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
  219. r1 += r;
  220. g1 += g;
  221. b1 += b;
  222. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  223. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  224. pixel = p[2] | (p[3]<<8);
  225. r = (((pixel/R_LOWMASK) & R_MAX) * (0x100 / (R_MAX+1)));
  226. g = (((pixel/G_LOWMASK) & G_MAX) * (0x100 / (G_MAX+1)));
  227. b = (((pixel/B_LOWMASK) & B_MAX) * (0x100 / (B_MAX+1)));
  228. r1 += r;
  229. g1 += g;
  230. b1 += b;
  231. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  232. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  233. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  234. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  235. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  236. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  237. cb++;
  238. cr++;
  239. p += -wrap2 + 2 * 2;
  240. lum += -wrap + 2;
  241. }
  242. p += wrap2;
  243. lum += wrap;
  244. }
  245. }
  246. static void bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  247. UINT8 *src, int width, int height)
  248. {
  249. int wrap, wrap3, x, y;
  250. int r, g, b, r1, g1, b1;
  251. UINT8 *p;
  252. wrap = width;
  253. wrap3 = width * 3;
  254. p = src;
  255. for(y=0;y<height;y+=2) {
  256. for(x=0;x<width;x+=2) {
  257. b = p[0];
  258. g = p[1];
  259. r = p[2];
  260. r1 = r;
  261. g1 = g;
  262. b1 = b;
  263. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  264. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  265. b = p[3];
  266. g = p[4];
  267. r = p[5];
  268. r1 += r;
  269. g1 += g;
  270. b1 += b;
  271. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  272. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  273. p += wrap3;
  274. lum += wrap;
  275. b = p[0];
  276. g = p[1];
  277. r = p[2];
  278. r1 += r;
  279. g1 += g;
  280. b1 += b;
  281. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  282. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  283. b = p[3];
  284. g = p[4];
  285. r = p[5];
  286. r1 += r;
  287. g1 += g;
  288. b1 += b;
  289. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  290. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  291. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  292. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  293. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  294. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  295. cb++;
  296. cr++;
  297. p += -wrap3 + 2 * 3;
  298. lum += -wrap + 2;
  299. }
  300. p += wrap3;
  301. lum += wrap;
  302. }
  303. }
  304. static void bgra32_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  305. UINT8 *src, int width, int height)
  306. {
  307. int wrap, wrap4, x, y;
  308. int r, g, b, r1, g1, b1;
  309. UINT8 *p;
  310. wrap = width;
  311. wrap4 = width * 4;
  312. p = src;
  313. for(y=0;y<height;y+=2) {
  314. for(x=0;x<width;x+=2) {
  315. b = p[0];
  316. g = p[1];
  317. r = p[2];
  318. r1 = r;
  319. g1 = g;
  320. b1 = b;
  321. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  322. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  323. b = p[4];
  324. g = p[5];
  325. r = p[6];
  326. r1 += r;
  327. g1 += g;
  328. b1 += b;
  329. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  330. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  331. p += wrap4;
  332. lum += wrap;
  333. b = p[0];
  334. g = p[1];
  335. r = p[2];
  336. r1 += r;
  337. g1 += g;
  338. b1 += b;
  339. lum[0] = (FIX(0.29900) * r + FIX(0.58700) * g +
  340. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  341. b = p[4];
  342. g = p[5];
  343. r = p[6];
  344. r1 += r;
  345. g1 += g;
  346. b1 += b;
  347. lum[1] = (FIX(0.29900) * r + FIX(0.58700) * g +
  348. FIX(0.11400) * b + ONE_HALF) >> SCALEBITS;
  349. cb[0] = ((- FIX(0.16874) * r1 - FIX(0.33126) * g1 +
  350. FIX(0.50000) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  351. cr[0] = ((FIX(0.50000) * r1 - FIX(0.41869) * g1 -
  352. FIX(0.08131) * b1 + 4 * ONE_HALF - 1) >> (SCALEBITS + 2)) + 128;
  353. cb++;
  354. cr++;
  355. p += -wrap4 + 2 * 4;
  356. lum += -wrap + 2;
  357. }
  358. p += wrap4;
  359. lum += wrap;
  360. }
  361. }
  362. /* XXX: use generic filter ? */
  363. /* 1x2 -> 1x1 */
  364. static void shrink2(UINT8 *dst, int dst_wrap,
  365. UINT8 *src, int src_wrap,
  366. int width, int height)
  367. {
  368. int w;
  369. UINT8 *s1, *s2, *d;
  370. for(;height > 0; height--) {
  371. s1 = src;
  372. s2 = s1 + src_wrap;
  373. d = dst;
  374. for(w = width;w >= 4; w-=4) {
  375. d[0] = (s1[0] + s2[0]) >> 1;
  376. d[1] = (s1[1] + s2[1]) >> 1;
  377. d[2] = (s1[2] + s2[2]) >> 1;
  378. d[3] = (s1[3] + s2[3]) >> 1;
  379. s1 += 4;
  380. s2 += 4;
  381. d += 4;
  382. }
  383. for(;w > 0; w--) {
  384. d[0] = (s1[0] + s2[0]) >> 1;
  385. s1++;
  386. s2++;
  387. d++;
  388. }
  389. src += 2 * src_wrap;
  390. dst += dst_wrap;
  391. }
  392. }
  393. /* 2x2 -> 1x1 */
  394. static void shrink22(UINT8 *dst, int dst_wrap,
  395. UINT8 *src, int src_wrap,
  396. int width, int height)
  397. {
  398. int w;
  399. UINT8 *s1, *s2, *d;
  400. for(;height > 0; height--) {
  401. s1 = src;
  402. s2 = s1 + src_wrap;
  403. d = dst;
  404. for(w = width;w >= 4; w-=4) {
  405. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  406. d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
  407. d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
  408. d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
  409. s1 += 8;
  410. s2 += 8;
  411. d += 4;
  412. }
  413. for(;w > 0; w--) {
  414. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  415. s1 += 2;
  416. s2 += 2;
  417. d++;
  418. }
  419. src += 2 * src_wrap;
  420. dst += dst_wrap;
  421. }
  422. }
  423. /* 1x1 -> 2x2 */
  424. static void grow22(UINT8 *dst, int dst_wrap,
  425. UINT8 *src, int src_wrap,
  426. int width, int height)
  427. {
  428. int w;
  429. UINT8 *s1, *d;
  430. for(;height > 0; height--) {
  431. s1 = src;
  432. d = dst;
  433. for(w = width;w >= 4; w-=4) {
  434. d[1] = d[0] = s1[0];
  435. d[3] = d[2] = s1[1];
  436. s1 += 2;
  437. d += 4;
  438. }
  439. for(;w > 0; w--) {
  440. d[0] = s1[0];
  441. s1 ++;
  442. d++;
  443. }
  444. if (height%2)
  445. src += src_wrap;
  446. dst += dst_wrap;
  447. }
  448. }
  449. /* 1x2 -> 2x1. width and height are given for the source picture */
  450. static void conv411(UINT8 *dst, int dst_wrap,
  451. UINT8 *src, int src_wrap,
  452. int width, int height)
  453. {
  454. int w, c;
  455. UINT8 *s1, *s2, *d;
  456. for(;height > 0; height -= 2) {
  457. s1 = src;
  458. s2 = src + src_wrap;
  459. d = dst;
  460. for(w = width;w > 0; w--) {
  461. c = (s1[0] + s2[0]) >> 1;
  462. d[0] = c;
  463. d[1] = c;
  464. s1++;
  465. s2++;
  466. d += 2;
  467. }
  468. src += src_wrap * 2;
  469. dst += dst_wrap;
  470. }
  471. }
  472. static void img_copy(UINT8 *dst, int dst_wrap,
  473. UINT8 *src, int src_wrap,
  474. int width, int height)
  475. {
  476. for(;height > 0; height--) {
  477. memcpy(dst, src, width);
  478. dst += dst_wrap;
  479. src += src_wrap;
  480. }
  481. }
  482. #define SCALE_BITS 10
  483. #define C_Y (76309 >> (16 - SCALE_BITS))
  484. #define C_RV (117504 >> (16 - SCALE_BITS))
  485. #define C_BU (138453 >> (16 - SCALE_BITS))
  486. #define C_GU (13954 >> (16 - SCALE_BITS))
  487. #define C_GV (34903 >> (16 - SCALE_BITS))
  488. #define RGBOUT(r, g, b, y1)\
  489. {\
  490. y = (y1 - 16) * C_Y;\
  491. r = cm[(y + r_add) >> SCALE_BITS];\
  492. g = cm[(y + g_add) >> SCALE_BITS];\
  493. b = cm[(y + b_add) >> SCALE_BITS];\
  494. }
  495. /* XXX: no chroma interpolating is done */
  496. static void yuv420p_to_bgra32(AVPicture *dst, AVPicture *src,
  497. int width, int height)
  498. {
  499. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  500. int w, y, cb, cr, r_add, g_add, b_add, width2;
  501. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  502. d = dst->data[0];
  503. y1_ptr = src->data[0];
  504. cb_ptr = src->data[1];
  505. cr_ptr = src->data[2];
  506. width2 = width >> 1;
  507. for(;height > 0; height -= 2) {
  508. d1 = d;
  509. d2 = d + dst->linesize[0];
  510. y2_ptr = y1_ptr + src->linesize[0];
  511. for(w = width2; w > 0; w --) {
  512. cb = cb_ptr[0] - 128;
  513. cr = cr_ptr[0] - 128;
  514. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  515. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  516. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  517. /* output 4 pixels */
  518. RGBOUT(d1[2], d1[1], d1[0], y1_ptr[0]);
  519. RGBOUT(d1[6], d1[5], d1[4], y1_ptr[1]);
  520. RGBOUT(d2[2], d2[1], d2[0], y2_ptr[0]);
  521. RGBOUT(d2[6], d2[5], d2[4], y2_ptr[1]);
  522. d1[3] = d1[7] = d2[3] = d2[7] = 255;
  523. d1 += 8;
  524. d2 += 8;
  525. y1_ptr += 2;
  526. y2_ptr += 2;
  527. cb_ptr++;
  528. cr_ptr++;
  529. }
  530. d += 2 * dst->linesize[0];
  531. y1_ptr += 2 * src->linesize[0] - width;
  532. cb_ptr += src->linesize[1] - width2;
  533. cr_ptr += src->linesize[2] - width2;
  534. }
  535. }
  536. /* XXX: no chroma interpolating is done */
  537. static void yuv420p_to_rgba32(AVPicture *dst, AVPicture *src,
  538. int width, int height)
  539. {
  540. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  541. int w, y, cb, cr, r_add, g_add, b_add, width2;
  542. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  543. d = dst->data[0];
  544. y1_ptr = src->data[0];
  545. cb_ptr = src->data[1];
  546. cr_ptr = src->data[2];
  547. width2 = width >> 1;
  548. for(;height > 0; height -= 2) {
  549. d1 = d;
  550. d2 = d + dst->linesize[0];
  551. y2_ptr = y1_ptr + src->linesize[0];
  552. for(w = width2; w > 0; w --) {
  553. cb = cb_ptr[0] - 128;
  554. cr = cr_ptr[0] - 128;
  555. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  556. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  557. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  558. /* output 4 pixels */
  559. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  560. RGBOUT(d1[4], d1[5], d1[6], y1_ptr[1]);
  561. RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
  562. RGBOUT(d2[4], d2[5], d2[6], y2_ptr[1]);
  563. d1[3] = d1[7] = d2[3] = d2[7] = 255;
  564. d1 += 8;
  565. d2 += 8;
  566. y1_ptr += 2;
  567. y2_ptr += 2;
  568. cb_ptr++;
  569. cr_ptr++;
  570. }
  571. d += 2 * dst->linesize[0];
  572. y1_ptr += 2 * src->linesize[0] - width;
  573. cb_ptr += src->linesize[1] - width2;
  574. cr_ptr += src->linesize[2] - width2;
  575. }
  576. }
  577. /* XXX: no chroma interpolating is done */
  578. static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src,
  579. int width, int height)
  580. {
  581. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  582. int w, y, cb, cr, r_add, g_add, b_add, width2;
  583. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  584. d = dst->data[0];
  585. y1_ptr = src->data[0];
  586. cb_ptr = src->data[1];
  587. cr_ptr = src->data[2];
  588. width2 = width >> 1;
  589. for(;height > 0; height -= 2) {
  590. d1 = d;
  591. d2 = d + dst->linesize[0];
  592. y2_ptr = y1_ptr + src->linesize[0];
  593. for(w = width2; w > 0; w --) {
  594. cb = cb_ptr[0] - 128;
  595. cr = cr_ptr[0] - 128;
  596. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  597. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  598. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  599. /* output 4 pixels */
  600. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  601. RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  602. RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
  603. RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]);
  604. d1 += 6;
  605. d2 += 6;
  606. y1_ptr += 2;
  607. y2_ptr += 2;
  608. cb_ptr++;
  609. cr_ptr++;
  610. }
  611. d += 2 * dst->linesize[0];
  612. y1_ptr += 2 * src->linesize[0] - width;
  613. cb_ptr += src->linesize[1] - width2;
  614. cr_ptr += src->linesize[2] - width2;
  615. }
  616. }
  617. /* XXX: no chroma interpolating is done */
  618. static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src,
  619. int width, int height)
  620. {
  621. UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;
  622. int w, y, cb, cr, r_add, g_add, b_add, width2;
  623. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  624. d = dst->data[0];
  625. y1_ptr = src->data[0];
  626. cb_ptr = src->data[1];
  627. cr_ptr = src->data[2];
  628. width2 = width >> 1;
  629. for(;height > 0; height --) {
  630. d1 = d;
  631. for(w = width2; w > 0; w --) {
  632. cb = cb_ptr[0] - 128;
  633. cr = cr_ptr[0] - 128;
  634. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  635. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  636. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  637. /* output 2 pixels */
  638. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  639. RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  640. d1 += 6;
  641. y1_ptr += 2;
  642. cb_ptr++;
  643. cr_ptr++;
  644. }
  645. d += dst->linesize[0];
  646. y1_ptr += src->linesize[0] - width;
  647. cb_ptr += src->linesize[1] - width2;
  648. cr_ptr += src->linesize[2] - width2;
  649. }
  650. }
  651. /* XXX: always use linesize. Return -1 if not supported */
  652. int img_convert(AVPicture *dst, int dst_pix_fmt,
  653. AVPicture *src, int pix_fmt,
  654. int width, int height)
  655. {
  656. int i;
  657. if (dst_pix_fmt == pix_fmt) {
  658. switch(pix_fmt) {
  659. case PIX_FMT_YUV420P:
  660. for(i=0;i<3;i++) {
  661. if (i == 1) {
  662. width >>= 1;
  663. height >>= 1;
  664. }
  665. img_copy(dst->data[i], dst->linesize[i],
  666. src->data[i], src->linesize[i],
  667. width, height);
  668. }
  669. break;
  670. default:
  671. return -1;
  672. }
  673. } else if (dst_pix_fmt == PIX_FMT_YUV420P) {
  674. switch(pix_fmt) {
  675. case PIX_FMT_YUV411P:
  676. img_copy(dst->data[0], dst->linesize[0],
  677. src->data[0], src->linesize[0],
  678. width, height);
  679. conv411(dst->data[1], dst->linesize[1],
  680. src->data[1], src->linesize[1],
  681. width / 4, height);
  682. conv411(dst->data[2], dst->linesize[2],
  683. src->data[2], src->linesize[2],
  684. width / 4, height);
  685. break;
  686. case PIX_FMT_YUV410P:
  687. img_copy(dst->data[0], dst->linesize[0],
  688. src->data[0], src->linesize[0],
  689. width, height);
  690. grow22(dst->data[1], dst->linesize[1],
  691. src->data[1], src->linesize[1],
  692. width/2, height/2);
  693. grow22(dst->data[2], dst->linesize[2],
  694. src->data[2], src->linesize[2],
  695. width/2, height/2);
  696. break;
  697. case PIX_FMT_YUV420P:
  698. for(i=0;i<3;i++) {
  699. img_copy(dst->data[i], dst->linesize[i],
  700. src->data[i], src->linesize[i],
  701. width, height);
  702. }
  703. break;
  704. case PIX_FMT_YUV422P:
  705. img_copy(dst->data[0], dst->linesize[0],
  706. src->data[0], src->linesize[0],
  707. width, height);
  708. width >>= 1;
  709. height >>= 1;
  710. for(i=1;i<3;i++) {
  711. shrink2(dst->data[i], dst->linesize[i],
  712. src->data[i], src->linesize[i],
  713. width, height);
  714. }
  715. break;
  716. case PIX_FMT_YUV444P:
  717. img_copy(dst->data[0], dst->linesize[0],
  718. src->data[0], src->linesize[0],
  719. width, height);
  720. width >>= 1;
  721. height >>= 1;
  722. for(i=1;i<3;i++) {
  723. shrink22(dst->data[i], dst->linesize[i],
  724. src->data[i], src->linesize[i],
  725. width, height);
  726. }
  727. break;
  728. case PIX_FMT_YUV422:
  729. yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  730. src->data[0], width, height);
  731. break;
  732. case PIX_FMT_RGB24:
  733. rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  734. src->data[0], width, height);
  735. break;
  736. case PIX_FMT_RGBA32:
  737. rgba32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  738. src->data[0], width, height);
  739. break;
  740. case PIX_FMT_BGR24:
  741. bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  742. src->data[0], width, height);
  743. break;
  744. case PIX_FMT_BGRA32:
  745. bgra32_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  746. src->data[0], width, height);
  747. break;
  748. case PIX_FMT_RGB565:
  749. rgb565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  750. src->data[0], width, height);
  751. break;
  752. case PIX_FMT_RGB555:
  753. rgb555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  754. src->data[0], width, height);
  755. break;
  756. /* case PIX_FMT_RGB5551:
  757. rgb5551_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  758. src->data[0], width, height);
  759. break;*/
  760. case PIX_FMT_BGR565:
  761. bgr565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  762. src->data[0], width, height);
  763. break;
  764. case PIX_FMT_BGR555:
  765. bgr555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  766. src->data[0], width, height);
  767. break;
  768. /* case PIX_FMT_GBR565:
  769. gbr565_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  770. src->data[0], width, height);
  771. break;
  772. case PIX_FMT_GBR555:
  773. gbr555_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  774. src->data[0], width, height);
  775. break;*/
  776. default:
  777. return -1;
  778. }
  779. } else if (dst_pix_fmt == PIX_FMT_RGB24) {
  780. switch(pix_fmt) {
  781. case PIX_FMT_YUV420P:
  782. yuv420p_to_rgb24(dst, src, width, height);
  783. break;
  784. case PIX_FMT_YUV422P:
  785. yuv422p_to_rgb24(dst, src, width, height);
  786. break;
  787. default:
  788. return -1;
  789. }
  790. } else if (dst_pix_fmt == PIX_FMT_RGBA32) {
  791. switch(pix_fmt) {
  792. case PIX_FMT_YUV420P:
  793. yuv420p_to_rgba32(dst, src, width, height);
  794. break;
  795. default:
  796. return -1;
  797. }
  798. } else if (dst_pix_fmt == PIX_FMT_BGRA32) {
  799. switch(pix_fmt) {
  800. case PIX_FMT_YUV420P:
  801. yuv420p_to_bgra32(dst, src, width, height);
  802. break;
  803. default:
  804. return -1;
  805. }
  806. } else {
  807. return -1;
  808. }
  809. return 0;
  810. }
  811. #ifdef HAVE_MMX
  812. #define DEINT_INPLACE_LINE_LUM \
  813. movd_m2r(lum_m4[0],mm0);\
  814. movd_m2r(lum_m3[0],mm1);\
  815. movd_m2r(lum_m2[0],mm2);\
  816. movd_m2r(lum_m1[0],mm3);\
  817. movd_m2r(lum[0],mm4);\
  818. punpcklbw_r2r(mm7,mm0);\
  819. movd_r2m(mm2,lum_m4[0]);\
  820. punpcklbw_r2r(mm7,mm1);\
  821. punpcklbw_r2r(mm7,mm2);\
  822. punpcklbw_r2r(mm7,mm3);\
  823. punpcklbw_r2r(mm7,mm4);\
  824. paddw_r2r(mm3,mm1);\
  825. psllw_i2r(1,mm2);\
  826. paddw_r2r(mm4,mm0);\
  827. psllw_i2r(2,mm1);\
  828. paddw_r2r(mm6,mm2);\
  829. paddw_r2r(mm2,mm1);\
  830. psubusw_r2r(mm0,mm1);\
  831. psrlw_i2r(3,mm1);\
  832. packuswb_r2r(mm7,mm1);\
  833. movd_r2m(mm1,lum_m2[0]);
  834. #define DEINT_LINE_LUM \
  835. movd_m2r(lum_m4[0],mm0);\
  836. movd_m2r(lum_m3[0],mm1);\
  837. movd_m2r(lum_m2[0],mm2);\
  838. movd_m2r(lum_m1[0],mm3);\
  839. movd_m2r(lum[0],mm4);\
  840. punpcklbw_r2r(mm7,mm0);\
  841. punpcklbw_r2r(mm7,mm1);\
  842. punpcklbw_r2r(mm7,mm2);\
  843. punpcklbw_r2r(mm7,mm3);\
  844. punpcklbw_r2r(mm7,mm4);\
  845. paddw_r2r(mm3,mm1);\
  846. psllw_i2r(1,mm2);\
  847. paddw_r2r(mm4,mm0);\
  848. psllw_i2r(2,mm1);\
  849. paddw_r2r(mm6,mm2);\
  850. paddw_r2r(mm2,mm1);\
  851. psubusw_r2r(mm0,mm1);\
  852. psrlw_i2r(3,mm1);\
  853. packuswb_r2r(mm7,mm1);\
  854. movd_r2m(mm1,dst[0]);
  855. #endif
  856. /* filter parameters: [-1 4 2 4 -1] // 8 */
  857. static void deinterlace_line(UINT8 *dst, UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  858. int size)
  859. {
  860. #ifndef HAVE_MMX
  861. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  862. int sum;
  863. for(;size > 0;size--) {
  864. sum = -lum_m4[0];
  865. sum += lum_m3[0] << 2;
  866. sum += lum_m2[0] << 1;
  867. sum += lum_m1[0] << 2;
  868. sum += -lum[0];
  869. dst[0] = cm[(sum + 4) >> 3];
  870. lum_m4++;
  871. lum_m3++;
  872. lum_m2++;
  873. lum_m1++;
  874. lum++;
  875. dst++;
  876. }
  877. #else
  878. for (;size > 3; size-=4) {
  879. DEINT_LINE_LUM
  880. lum_m4+=4;
  881. lum_m3+=4;
  882. lum_m2+=4;
  883. lum_m1+=4;
  884. lum+=4;
  885. dst+=4;
  886. }
  887. #endif
  888. }
  889. static void deinterlace_line_inplace(UINT8 *lum_m4, UINT8 *lum_m3, UINT8 *lum_m2, UINT8 *lum_m1, UINT8 *lum,
  890. int size)
  891. {
  892. #ifndef HAVE_MMX
  893. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  894. int sum;
  895. for(;size > 0;size--) {
  896. sum = -lum_m4[0];
  897. sum += lum_m3[0] << 2;
  898. sum += lum_m2[0] << 1;
  899. lum_m4[0]=lum_m2[0];
  900. sum += lum_m1[0] << 2;
  901. sum += -lum[0];
  902. lum_m2[0] = cm[(sum + 4) >> 3];
  903. lum_m4++;
  904. lum_m3++;
  905. lum_m2++;
  906. lum_m1++;
  907. lum++;
  908. }
  909. #else
  910. for (;size > 3; size-=4) {
  911. DEINT_INPLACE_LINE_LUM
  912. lum_m4+=4;
  913. lum_m3+=4;
  914. lum_m2+=4;
  915. lum_m1+=4;
  916. lum+=4;
  917. }
  918. #endif
  919. }
  920. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  921. top field is copied as is, but the bottom field is deinterlaced
  922. against the top field. */
  923. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  924. UINT8 *src1, int src_wrap,
  925. int width, int height)
  926. {
  927. UINT8 *src_m2, *src_m1, *src_0, *src_p1, *src_p2;
  928. int y;
  929. src_m2 = src1;
  930. src_m1 = src1;
  931. src_0=&src_m1[src_wrap];
  932. src_p1=&src_0[src_wrap];
  933. src_p2=&src_p1[src_wrap];
  934. for(y=0;y<(height-2);y+=2) {
  935. memcpy(dst,src_m1,width);
  936. dst += dst_wrap;
  937. deinterlace_line(dst,src_m2,src_m1,src_0,src_p1,src_p2,width);
  938. src_m2 = src_0;
  939. src_m1 = src_p1;
  940. src_0 = src_p2;
  941. src_p1 += 2*src_wrap;
  942. src_p2 += 2*src_wrap;
  943. dst += dst_wrap;
  944. }
  945. memcpy(dst,src_m1,width);
  946. dst += dst_wrap;
  947. /* do last line */
  948. deinterlace_line(dst,src_m2,src_m1,src_0,src_0,src_0,width);
  949. }
  950. static void deinterlace_bottom_field_inplace(UINT8 *src1, int src_wrap,
  951. int width, int height)
  952. {
  953. UINT8 *src_m1, *src_0, *src_p1, *src_p2;
  954. int y;
  955. UINT8 *buf;
  956. buf = (UINT8*)av_malloc(width);
  957. src_m1 = src1;
  958. memcpy(buf,src_m1,width);
  959. src_0=&src_m1[src_wrap];
  960. src_p1=&src_0[src_wrap];
  961. src_p2=&src_p1[src_wrap];
  962. for(y=0;y<(height-2);y+=2) {
  963. deinterlace_line_inplace(buf,src_m1,src_0,src_p1,src_p2,width);
  964. src_m1 = src_p1;
  965. src_0 = src_p2;
  966. src_p1 += 2*src_wrap;
  967. src_p2 += 2*src_wrap;
  968. }
  969. /* do last line */
  970. deinterlace_line_inplace(buf,src_m1,src_0,src_0,src_0,width);
  971. av_free(buf);
  972. }
  973. /* deinterlace - if not supported return -1 */
  974. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  975. int pix_fmt, int width, int height)
  976. {
  977. int i;
  978. if (pix_fmt != PIX_FMT_YUV420P &&
  979. pix_fmt != PIX_FMT_YUV422P &&
  980. pix_fmt != PIX_FMT_YUV444P)
  981. return -1;
  982. if ((width & 3) != 0 || (height & 3) != 0)
  983. return -1;
  984. #ifdef HAVE_MMX
  985. {
  986. mmx_t rounder;
  987. rounder.uw[0]=4;
  988. rounder.uw[1]=4;
  989. rounder.uw[2]=4;
  990. rounder.uw[3]=4;
  991. pxor_r2r(mm7,mm7);
  992. movq_m2r(rounder,mm6);
  993. }
  994. #endif
  995. for(i=0;i<3;i++) {
  996. if (i == 1) {
  997. switch(pix_fmt) {
  998. case PIX_FMT_YUV420P:
  999. width >>= 1;
  1000. height >>= 1;
  1001. break;
  1002. case PIX_FMT_YUV422P:
  1003. width >>= 1;
  1004. break;
  1005. default:
  1006. break;
  1007. }
  1008. }
  1009. if (src == dst) {
  1010. deinterlace_bottom_field_inplace(src->data[i], src->linesize[i],
  1011. width, height);
  1012. } else {
  1013. deinterlace_bottom_field(dst->data[i],dst->linesize[i],
  1014. src->data[i], src->linesize[i],
  1015. width, height);
  1016. }
  1017. }
  1018. #ifdef HAVE_MMX
  1019. emms();
  1020. #endif
  1021. return 0;
  1022. }
  1023. #undef FIX