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.

550 lines
16KB

  1. /*
  2. * Misc image convertion routines
  3. * Copyright (c) 2001 Gerard Lantau.
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program 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
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include "avcodec.h"
  23. #include "dsputil.h"
  24. #ifdef USE_FASTMEMCPY
  25. #include "fastmemcpy.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 bgr24_to_yuv420p(UINT8 *lum, UINT8 *cb, UINT8 *cr,
  114. UINT8 *src, int width, int height)
  115. {
  116. int wrap, wrap3, x, y;
  117. int r, g, b, r1, g1, b1;
  118. UINT8 *p;
  119. wrap = width;
  120. wrap3 = width * 3;
  121. p = src;
  122. for(y=0;y<height;y+=2) {
  123. for(x=0;x<width;x+=2) {
  124. b = p[0];
  125. g = p[1];
  126. r = 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. b = p[3];
  133. g = p[4];
  134. r = p[5];
  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 += wrap3;
  141. lum += wrap;
  142. b = p[0];
  143. g = p[1];
  144. r = 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. b = p[3];
  151. g = p[4];
  152. r = p[5];
  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 += -wrap3 + 2 * 3;
  165. lum += -wrap + 2;
  166. }
  167. p += wrap3;
  168. lum += wrap;
  169. }
  170. }
  171. /* XXX: use generic filter ? */
  172. /* 1x2 -> 1x1 */
  173. static void shrink2(UINT8 *dst, int dst_wrap,
  174. UINT8 *src, int src_wrap,
  175. int width, int height)
  176. {
  177. int w;
  178. UINT8 *s1, *s2, *d;
  179. for(;height > 0; height--) {
  180. s1 = src;
  181. s2 = s1 + src_wrap;
  182. d = dst;
  183. for(w = width;w >= 4; w-=4) {
  184. d[0] = (s1[0] + s2[0]) >> 1;
  185. d[1] = (s1[1] + s2[1]) >> 1;
  186. d[2] = (s1[2] + s2[2]) >> 1;
  187. d[3] = (s1[3] + s2[3]) >> 1;
  188. s1 += 4;
  189. s2 += 4;
  190. d += 4;
  191. }
  192. for(;w > 0; w--) {
  193. d[0] = (s1[0] + s2[0]) >> 1;
  194. s1++;
  195. s2++;
  196. d++;
  197. }
  198. src += 2 * src_wrap;
  199. dst += dst_wrap;
  200. }
  201. }
  202. /* 2x2 -> 1x1 */
  203. static void shrink22(UINT8 *dst, int dst_wrap,
  204. UINT8 *src, int src_wrap,
  205. int width, int height)
  206. {
  207. int w;
  208. UINT8 *s1, *s2, *d;
  209. for(;height > 0; height--) {
  210. s1 = src;
  211. s2 = s1 + src_wrap;
  212. d = dst;
  213. for(w = width;w >= 4; w-=4) {
  214. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  215. d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 1;
  216. d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 1;
  217. d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 1;
  218. s1 += 8;
  219. s2 += 8;
  220. d += 4;
  221. }
  222. for(;w > 0; w--) {
  223. d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 1;
  224. s1 += 2;
  225. s2 += 2;
  226. d++;
  227. }
  228. src += 2 * src_wrap;
  229. dst += dst_wrap;
  230. }
  231. }
  232. static void img_copy(UINT8 *dst, int dst_wrap,
  233. UINT8 *src, int src_wrap,
  234. int width, int height)
  235. {
  236. for(;height > 0; height--) {
  237. memcpy(dst, src, width);
  238. dst += dst_wrap;
  239. src += src_wrap;
  240. }
  241. }
  242. #define SCALE_BITS 10
  243. #define C_Y (76309 >> (16 - SCALE_BITS))
  244. #define C_RV (117504 >> (16 - SCALE_BITS))
  245. #define C_BU (138453 >> (16 - SCALE_BITS))
  246. #define C_GU (13954 >> (16 - SCALE_BITS))
  247. #define C_GV (34903 >> (16 - SCALE_BITS))
  248. #define RGBOUT(r, g, b, y1)\
  249. {\
  250. y = (y1 - 16) * C_Y;\
  251. r = cm[(y + r_add) >> SCALE_BITS];\
  252. g = cm[(y + g_add) >> SCALE_BITS];\
  253. b = cm[(y + b_add) >> SCALE_BITS];\
  254. }
  255. /* XXX: no chroma interpolating is done */
  256. static void yuv420p_to_rgb24(AVPicture *dst, AVPicture *src,
  257. int width, int height)
  258. {
  259. UINT8 *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *d, *d1, *d2;
  260. int w, y, cb, cr, r_add, g_add, b_add, width2;
  261. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  262. d = dst->data[0];
  263. y1_ptr = src->data[0];
  264. cb_ptr = src->data[1];
  265. cr_ptr = src->data[2];
  266. width2 = width >> 1;
  267. for(;height > 0; height -= 2) {
  268. d1 = d;
  269. d2 = d + dst->linesize[0];
  270. y2_ptr = y1_ptr + src->linesize[0];
  271. for(w = width2; w > 0; w --) {
  272. cb = cb_ptr[0] - 128;
  273. cr = cr_ptr[0] - 128;
  274. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  275. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  276. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  277. /* output 4 pixels */
  278. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  279. RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  280. RGBOUT(d2[0], d2[1], d2[2], y2_ptr[0]);
  281. RGBOUT(d2[3], d2[4], d2[5], y2_ptr[1]);
  282. d1 += 6;
  283. d2 += 6;
  284. y1_ptr += 2;
  285. y2_ptr += 2;
  286. cb_ptr++;
  287. cr_ptr++;
  288. }
  289. d += 2 * dst->linesize[0];
  290. y1_ptr += 2 * src->linesize[0] - width;
  291. cb_ptr += src->linesize[1] - width2;
  292. cr_ptr += src->linesize[2] - width2;
  293. }
  294. }
  295. /* XXX: no chroma interpolating is done */
  296. static void yuv422p_to_rgb24(AVPicture *dst, AVPicture *src,
  297. int width, int height)
  298. {
  299. UINT8 *y1_ptr, *cb_ptr, *cr_ptr, *d, *d1;
  300. int w, y, cb, cr, r_add, g_add, b_add, width2;
  301. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  302. d = dst->data[0];
  303. y1_ptr = src->data[0];
  304. cb_ptr = src->data[1];
  305. cr_ptr = src->data[2];
  306. width2 = width >> 1;
  307. for(;height > 0; height --) {
  308. d1 = d;
  309. for(w = width2; w > 0; w --) {
  310. cb = cb_ptr[0] - 128;
  311. cr = cr_ptr[0] - 128;
  312. r_add = C_RV * cr + (1 << (SCALE_BITS - 1));
  313. g_add = - C_GU * cb - C_GV * cr + (1 << (SCALE_BITS - 1));
  314. b_add = C_BU * cb + (1 << (SCALE_BITS - 1));
  315. /* output 2 pixels */
  316. RGBOUT(d1[0], d1[1], d1[2], y1_ptr[0]);
  317. RGBOUT(d1[3], d1[4], d1[5], y1_ptr[1]);
  318. d1 += 6;
  319. y1_ptr += 2;
  320. cb_ptr++;
  321. cr_ptr++;
  322. }
  323. d += dst->linesize[0];
  324. y1_ptr += src->linesize[0] - width;
  325. cb_ptr += src->linesize[1] - width2;
  326. cr_ptr += src->linesize[2] - width2;
  327. }
  328. }
  329. /* XXX: always use linesize. Return -1 if not supported */
  330. int img_convert(AVPicture *dst, int dst_pix_fmt,
  331. AVPicture *src, int pix_fmt,
  332. int width, int height)
  333. {
  334. int i;
  335. if (dst_pix_fmt == pix_fmt) {
  336. switch(pix_fmt) {
  337. case PIX_FMT_YUV420P:
  338. for(i=0;i<3;i++) {
  339. if (i == 1) {
  340. width >>= 1;
  341. height >>= 1;
  342. }
  343. img_copy(dst->data[i], dst->linesize[i],
  344. src->data[i], src->linesize[i],
  345. width, height);
  346. }
  347. break;
  348. default:
  349. return -1;
  350. }
  351. } else if (dst_pix_fmt == PIX_FMT_YUV420P) {
  352. switch(pix_fmt) {
  353. case PIX_FMT_YUV420P:
  354. for(i=0;i<3;i++) {
  355. img_copy(dst->data[i], dst->linesize[i],
  356. src->data[i], src->linesize[i],
  357. width, height);
  358. }
  359. break;
  360. case PIX_FMT_YUV422P:
  361. img_copy(dst->data[0], dst->linesize[0],
  362. src->data[0], src->linesize[0],
  363. width, height);
  364. width >>= 1;
  365. height >>= 1;
  366. for(i=1;i<3;i++) {
  367. shrink2(dst->data[i], dst->linesize[i],
  368. src->data[i], src->linesize[i],
  369. width, height);
  370. }
  371. break;
  372. case PIX_FMT_YUV444P:
  373. img_copy(dst->data[0], dst->linesize[0],
  374. src->data[0], src->linesize[0],
  375. width, height);
  376. width >>= 1;
  377. height >>= 1;
  378. for(i=1;i<3;i++) {
  379. shrink22(dst->data[i], dst->linesize[i],
  380. src->data[i], src->linesize[i],
  381. width, height);
  382. }
  383. break;
  384. case PIX_FMT_YUV422:
  385. yuv422_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  386. src->data[0], width, height);
  387. break;
  388. case PIX_FMT_RGB24:
  389. rgb24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  390. src->data[0], width, height);
  391. break;
  392. case PIX_FMT_BGR24:
  393. bgr24_to_yuv420p(dst->data[0], dst->data[1], dst->data[2],
  394. src->data[0], width, height);
  395. break;
  396. default:
  397. return -1;
  398. }
  399. } else if (dst_pix_fmt == PIX_FMT_RGB24) {
  400. switch(pix_fmt) {
  401. case PIX_FMT_YUV420P:
  402. yuv420p_to_rgb24(dst, src, width, height);
  403. break;
  404. case PIX_FMT_YUV422P:
  405. yuv422p_to_rgb24(dst, src, width, height);
  406. break;
  407. default:
  408. return -1;
  409. }
  410. } else {
  411. return -1;
  412. }
  413. return 0;
  414. }
  415. /* filter parameters: [-1 4 2 4 -1] // 8 */
  416. static void deinterlace_line(UINT8 *dst, UINT8 *src, int src_wrap,
  417. int size)
  418. {
  419. UINT8 *cm = cropTbl + MAX_NEG_CROP;
  420. int sum;
  421. UINT8 *s;
  422. for(;size > 0;size--) {
  423. s = src;
  424. sum = -s[0];
  425. s += src_wrap;
  426. sum += s[0] << 2;
  427. s += src_wrap;
  428. sum += s[0] << 1;
  429. s += src_wrap;
  430. sum += s[0] << 2;
  431. s += src_wrap;
  432. sum += -s[0];
  433. dst[0] = cm[(sum + 4) >> 3];
  434. dst++;
  435. src++;
  436. }
  437. }
  438. /* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The
  439. top field is copied as is, but the bottom field is deinterlaced
  440. against the top field. */
  441. static void deinterlace_bottom_field(UINT8 *dst, int dst_wrap,
  442. UINT8 *src1, int src_wrap,
  443. int width, int height)
  444. {
  445. UINT8 *src, *ptr;
  446. int y, y1, i;
  447. UINT8 buf[5 * width];
  448. src = src1;
  449. for(y=0;y<height;y+=2) {
  450. /* copy top field line */
  451. memcpy(dst, src, width);
  452. dst += dst_wrap;
  453. src += (1 - 2) * src_wrap;
  454. y1 = y - 2;
  455. if (y1 >= 0 && (y1 + 4) < height) {
  456. /* fast case : no edges */
  457. deinterlace_line(dst, src, src_wrap, width);
  458. } else {
  459. /* in order to use the same function, we use an intermediate buffer */
  460. ptr = buf;
  461. for(i=0;i<5;i++) {
  462. if (y1 < 0)
  463. memcpy(ptr, src1, width);
  464. else if (y1 >= height)
  465. memcpy(ptr, src1 + (height - 1) * src_wrap, width);
  466. else
  467. memcpy(ptr, src1 + y1 * src_wrap, width);
  468. y1++;
  469. ptr += width;
  470. }
  471. deinterlace_line(dst, buf, width, width);
  472. }
  473. dst += dst_wrap;
  474. src += (2 + 1) * src_wrap;
  475. }
  476. }
  477. /* deinterlace, return -1 if format not handled */
  478. int avpicture_deinterlace(AVPicture *dst, AVPicture *src,
  479. int pix_fmt, int width, int height)
  480. {
  481. int i;
  482. if (pix_fmt != PIX_FMT_YUV420P &&
  483. pix_fmt != PIX_FMT_YUV422P &&
  484. pix_fmt != PIX_FMT_YUV444P)
  485. return -1;
  486. if ((width & 1) != 0 || (height & 3) != 0)
  487. return -1;
  488. for(i=0;i<3;i++) {
  489. if (i == 1) {
  490. switch(pix_fmt) {
  491. case PIX_FMT_YUV420P:
  492. width >>= 1;
  493. height >>= 1;
  494. break;
  495. case PIX_FMT_YUV422P:
  496. width >>= 1;
  497. break;
  498. default:
  499. break;
  500. }
  501. }
  502. deinterlace_bottom_field(dst->data[i], dst->linesize[i],
  503. src->data[i], src->linesize[i],
  504. width, height);
  505. }
  506. return 0;
  507. }