colorspace.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:27k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /**************************************************************************
  2.  *
  3.  * XVID MPEG-4 VIDEO CODEC
  4.  * colorspace conversions
  5.  *
  6.  * This program is an implementation of a part of one or more MPEG-4
  7.  * Video tools as specified in ISO/IEC 14496-2 standard.  Those intending
  8.  * to use this software module in hardware or software products are
  9.  * advised that its use may infringe existing patents or copyrights, and
  10.  * any such use would be at such party's own risk.  The original
  11.  * developer of this software module and his/her company, and subsequent
  12.  * editors and their companies, will have no liability for use of this
  13.  * software or modifications or derivatives thereof.
  14.  *
  15.  * This program is free software; you can redistribute it and/or modify
  16.  * it under the terms of the GNU General Public License as published by
  17.  * the Free Software Foundation; either version 2 of the License, or
  18.  * (at your option) any later version.
  19.  *
  20.  * This program is distributed in the hope that it will be useful,
  21.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23.  * GNU General Public License for more details.
  24.  *
  25.  * You should have received a copy of the GNU General Public License
  26.  * along with this program; if not, write to the Free Software
  27.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  28.  *
  29.  *************************************************************************/
  30. /**************************************************************************
  31.  *
  32.  * History:
  33.  *
  34.  * 30.02.2002 out_yuv dst_stride2 fix
  35.  * 26.02.2002 rgb555, rgb565
  36.  * 24.11.2001 accuracy improvement to yuyv/vyuy conversion
  37.  * 28.10.2001 total rewrite <pross@cs.rmit.edu.au>
  38.  *
  39.  **************************************************************************/
  40. #include <string.h> // memcpy
  41. #include "colorspace.h"
  42. // function pointers
  43. /* input */
  44. color_inputFuncPtr rgb555_to_yv12;
  45. color_inputFuncPtr rgb565_to_yv12;
  46. color_inputFuncPtr rgb24_to_yv12;
  47. color_inputFuncPtr rgb32_to_yv12;
  48. color_inputFuncPtr yuv_to_yv12;
  49. color_inputFuncPtr yuyv_to_yv12;
  50. color_inputFuncPtr uyvy_to_yv12;
  51. /* output */
  52. color_outputFuncPtr yv12_to_rgb555;
  53. color_outputFuncPtr yv12_to_rgb565;
  54. color_outputFuncPtr yv12_to_rgb24;
  55. color_outputFuncPtr yv12_to_rgb32;
  56. color_outputFuncPtr yv12_to_yuv;
  57. color_outputFuncPtr yv12_to_yuyv;
  58. color_outputFuncPtr yv12_to_uyvy;
  59. #define MIN(A,B) ((A)<(B)?(A):(B))
  60. #define MAX(A,B) ((A)>(B)?(A):(B))
  61. /* rgb -> yuv def's
  62. this following constants are "official spec"
  63. Video Demystified" (ISBN 1-878707-09-4)
  64. rgb<->yuv _is_ lossy, since most programs do the conversion differently
  65. SCALEBITS/FIX taken from  ffmpeg
  66. */
  67. #define Y_R_IN 0.257
  68. #define Y_G_IN 0.504
  69. #define Y_B_IN 0.098
  70. #define Y_ADD_IN 16
  71. #define U_R_IN 0.148
  72. #define U_G_IN 0.291
  73. #define U_B_IN 0.439
  74. #define U_ADD_IN 128
  75. #define V_R_IN 0.439
  76. #define V_G_IN 0.368
  77. #define V_B_IN 0.071
  78. #define V_ADD_IN 128
  79. #define SCALEBITS_IN 8
  80. #define FIX_IN(x) ((uint16_t) ((x) * (1L<<SCALEBITS_IN) + 0.5))
  81. int32_t RGB_Y_tab[256];
  82. int32_t B_U_tab[256];
  83. int32_t G_U_tab[256];
  84. int32_t G_V_tab[256];
  85. int32_t R_V_tab[256];
  86. /* rgb555 -> yuv 4:2:0 planar */
  87. void rgb555_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  88. uint8_t *src, int width, int height, int y_stride)
  89. {
  90. int32_t src_stride = width * 2;
  91. uint32_t y_dif = y_stride - width;
  92. uint32_t uv_dif = (y_stride - width) / 2;
  93. uint32_t x, y;
  94. if (height < 0)
  95. {
  96. height = -height;
  97. src += (height - 1) * src_stride;
  98. src_stride = -src_stride;
  99. }
  100. for (y = height / 2; y; y--) 
  101. {
  102. // process one 2x2 block per iteration
  103. for (x = 0; x < (uint32_t)width; x += 2)
  104. {
  105. int rgb, r, g, b, r4, g4, b4;
  106. rgb = *(uint16_t*)(src+x*2);
  107. b4 = b = (rgb << 3) & 0xf8;
  108. g4 = g = (rgb >> 2) & 0xf8;
  109. r4 = r = (rgb >> 7) & 0xf8;
  110.             y_out[0] =(uint8_t)((
  111.   FIX_IN(Y_R_IN) * r 
  112. + FIX_IN(Y_G_IN) * g 
  113. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  114. rgb = *(uint16_t*)(src+x*2+src_stride);
  115. b4 += b = (rgb << 3) & 0xf8;
  116. g4 += g = (rgb >> 2) & 0xf8;
  117. r4 += r = (rgb >> 7) & 0xf8;
  118.             y_out[y_stride] =(uint8_t)((
  119.   FIX_IN(Y_R_IN) * r 
  120. + FIX_IN(Y_G_IN) * g 
  121. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  122. rgb = *(uint16_t*)(src+x*2+2);
  123. b4 += b = (rgb << 3) & 0xf8;
  124. g4 += g = (rgb >> 2) & 0xf8;
  125. r4 += r = (rgb >> 7) & 0xf8;
  126.             y_out[1] =(uint8_t)((
  127.   FIX_IN(Y_R_IN) * r 
  128. + FIX_IN(Y_G_IN) * g 
  129. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  130. rgb = *(uint16_t*)(src+x*2+src_stride+2);
  131. b4 += b = (rgb << 3) & 0xf8;
  132. g4 += g = (rgb >> 2) & 0xf8;
  133. r4 += r = (rgb >> 7) & 0xf8;
  134.             y_out[y_stride + 1] =(uint8_t)((
  135.   FIX_IN(Y_R_IN) * r 
  136. + FIX_IN(Y_G_IN) * g 
  137. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  138. *u_out++ = (uint8_t)((
  139. - FIX_IN(U_R_IN) * r4 
  140. - FIX_IN(U_G_IN) * g4
  141. + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN;
  142.             *v_out++ = (uint8_t)((
  143.   FIX_IN(V_R_IN) * r4
  144. - FIX_IN(V_G_IN) * g4
  145. - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; 
  146. y_out += 2;
  147. }
  148. src += src_stride * 2;
  149. y_out += y_dif + y_stride;
  150. u_out += uv_dif;
  151. v_out += uv_dif;
  152. }
  153. }
  154. /* rgb565_to_yuv_c
  155. NOTE: identical to rgb555 except for shift/mask 
  156. not tested */
  157. void rgb565_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  158. uint8_t *src, int width, int height, int y_stride)
  159. {
  160. int32_t src_stride = width * 2;
  161. uint32_t y_dif = y_stride - width;
  162. uint32_t uv_dif = (y_stride - width) / 2;
  163. uint32_t x, y;
  164. if (height < 0)
  165. {
  166. height = -height;
  167. src += (height - 1) * src_stride;
  168. src_stride = -src_stride;
  169. }
  170. for (y = height / 2; y; y--) 
  171. {
  172. // process one 2x2 block per iteration
  173. for (x = 0; x < (uint32_t)width; x += 2)
  174. {
  175. int rgb, r, g, b, r4, g4, b4;
  176. rgb = *(uint16_t*)(src+x*2);
  177. b4 = b = (rgb << 3) & 0xf8;
  178. g4 = g = (rgb >> 3) & 0xfc;
  179. r4 = r = (rgb >> 8) & 0xf8;
  180.             y_out[0] =(uint8_t)((
  181.   FIX_IN(Y_R_IN) * r 
  182. + FIX_IN(Y_G_IN) * g 
  183. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  184. rgb = *(uint16_t*)(src+x*2+src_stride);
  185. b4 += b = (rgb << 3) & 0xf8;
  186. g4 += g = (rgb >> 3) & 0xfc;
  187. r4 += r = (rgb >> 8) & 0xf8;
  188.             y_out[y_stride] =(uint8_t)((
  189.   FIX_IN(Y_R_IN) * r 
  190. + FIX_IN(Y_G_IN) * g 
  191. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  192. rgb = *(uint16_t*)(src+x*2+2);
  193. b4 += b = (rgb << 3) & 0xf8;
  194. g4 += g = (rgb >> 3) & 0xfc;
  195. r4 += r = (rgb >> 8) & 0xf8;
  196.             y_out[1] =(uint8_t)((
  197.   FIX_IN(Y_R_IN) * r 
  198. + FIX_IN(Y_G_IN) * g 
  199. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  200. rgb = *(uint16_t*)(src+x*2+src_stride+2);
  201. b4 += b = (rgb << 3) & 0xf8;
  202. g4 += g = (rgb >> 3) & 0xfc;
  203. r4 += r = (rgb >> 8) & 0xf8;
  204.             y_out[y_stride + 1] =(uint8_t)((
  205.   FIX_IN(Y_R_IN) * r 
  206. + FIX_IN(Y_G_IN) * g 
  207. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  208. *u_out++ = (uint8_t)((
  209. - FIX_IN(U_R_IN) * r4 
  210. - FIX_IN(U_G_IN) * g4
  211. + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN;
  212.             *v_out++ = (uint8_t)((
  213.   FIX_IN(V_R_IN) * r4
  214. - FIX_IN(V_G_IN) * g4
  215. - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; 
  216. y_out += 2;
  217. }
  218. src += src_stride * 2;
  219. y_out += y_dif + y_stride;
  220. u_out += uv_dif;
  221. v_out += uv_dif;
  222. }
  223. }
  224. /* rgb24 -> yuv 4:2:0 planar 
  225. NOTE: always flips.
  226. */
  227. void rgb24_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  228. uint8_t *src, int width, int height, int stride)
  229. {
  230.     uint32_t width3 = (width << 1) + width; /* width * 3 */
  231. uint32_t src_dif = (width << 3) + width; /* width3 * 3 */
  232. uint32_t y_dif = (stride << 1) - width;
  233. uint32_t uv_dif = (stride - width) >> 1;
  234.     uint32_t x, y;
  235. src += (height - 2) * width3;
  236.     for(y = height >> 1; y; y--) {
  237. for(x = width >> 1; x; x--) {
  238. uint32_t r, g, b, r4, g4, b4;
  239.             b4 = b = src[0];
  240.             g4 = g = src[1];
  241.             r4 = r = src[2];
  242.             y_out[stride + 0] =(uint8_t)((
  243.   FIX_IN(Y_R_IN) * r 
  244. + FIX_IN(Y_G_IN) * g 
  245. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN; 
  246.             b4 += (b = src[3]);
  247.             g4 += (g = src[4]);
  248.             r4 += (r = src[5]);
  249.             y_out[stride + 1] = (uint8_t)((
  250.   FIX_IN(Y_R_IN) * r 
  251. + FIX_IN(Y_G_IN) * g 
  252. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  253.             b4 += (b = src[width3 + 0]);
  254.             g4 += (g = src[width3 + 1]);
  255.             r4 += (r = src[width3 + 2]);
  256.             y_out[0] = (uint8_t)((
  257. FIX_IN(Y_R_IN) * r + 
  258. FIX_IN(Y_G_IN) * g + 
  259. FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  260.             b4 += (b = src[width3 + 3]);
  261.             g4 += (g = src[width3 + 4]);
  262.             r4 += (r = src[width3 + 5]);
  263.             y_out[1] = (uint8_t)((
  264.   FIX_IN(Y_R_IN) * r
  265. + FIX_IN(Y_G_IN) * g
  266. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  267.             
  268. *u_out++ = (uint8_t)((
  269. - FIX_IN(U_R_IN) * r4 
  270. - FIX_IN(U_G_IN) * g4
  271. + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN;
  272.             *v_out++ = (uint8_t)((
  273.   FIX_IN(V_R_IN) * r4
  274. - FIX_IN(V_G_IN) * g4
  275. - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN; 
  276. src += 6;
  277. y_out += 2;
  278. }
  279. src -= src_dif;
  280. y_out += y_dif;
  281. u_out += uv_dif;
  282. v_out += uv_dif;
  283.     }
  284. }
  285. /* rgb32 -> yuv 4:2:0 planar 
  286. NOTE: always flips
  287. */
  288. void rgb32_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  289. uint8_t *src, int width, int height, int stride)
  290. {
  291.     uint32_t width4 = (width << 2); /* width * 4 */
  292. uint32_t src_dif = 3 * width4;
  293. uint32_t y_dif = (stride << 1) - width;
  294. uint32_t uv_dif = (stride - width) >> 1;
  295.     uint32_t x, y;
  296. src += (height - 2) * width4;
  297.     for(y = height >> 1; y; y--) {
  298. for(x = width >> 1; x; x--) {
  299. uint32_t r, g, b, r4, g4, b4;
  300.             b4 = b = src[0];
  301.             g4 = g = src[1];
  302.             r4 = r = src[2];
  303.             y_out[stride + 0] =(uint8_t)((
  304.   FIX_IN(Y_R_IN) * r 
  305. + FIX_IN(Y_G_IN) * g 
  306. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  307.             b4 += (b = src[4]);
  308.             g4 += (g = src[5]);
  309.             r4 += (r = src[6]);
  310.             y_out[stride + 1] =(uint8_t)((
  311.   FIX_IN(Y_R_IN) * r 
  312. + FIX_IN(Y_G_IN) * g 
  313. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  314.             b4 += (b = src[width4 + 0]);
  315.             g4 += (g = src[width4 + 1]);
  316.             r4 += (r = src[width4 + 2]);
  317.             y_out[0] =(uint8_t)((
  318.   FIX_IN(Y_R_IN) * r 
  319. + FIX_IN(Y_G_IN) * g 
  320. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  321.             
  322.             b4 += (b = src[width4 + 4]);
  323.             g4 += (g = src[width4 + 5]);
  324.             r4 += (r = src[width4 + 6]);
  325.             y_out[1] =(uint8_t)((
  326.   FIX_IN(Y_R_IN) * r 
  327. + FIX_IN(Y_G_IN) * g 
  328. + FIX_IN(Y_B_IN) * b) >> SCALEBITS_IN) + Y_ADD_IN;
  329.             
  330. *u_out++ = (uint8_t)((
  331. - FIX_IN(U_R_IN) * r4 
  332. - FIX_IN(U_G_IN) * g4
  333. + FIX_IN(U_B_IN) * b4) >> (SCALEBITS_IN + 2)) + U_ADD_IN;
  334.             *v_out++ = (uint8_t)((
  335.   FIX_IN(V_R_IN) * r4
  336. - FIX_IN(V_G_IN) * g4
  337. - FIX_IN(V_B_IN) * b4) >> (SCALEBITS_IN + 2)) + V_ADD_IN;
  338. src += 8;
  339. y_out += 2;
  340. }
  341. src -= src_dif;
  342. y_out += y_dif;
  343. u_out += uv_dif;
  344. v_out += uv_dif;
  345.     }
  346. }
  347. /* yuv planar -> yuv 4:2:0 planar
  348.    
  349. NOTE: does not flip */
  350. void yuv_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  351. uint8_t *src, int width, int height, int stride)
  352. {
  353. uint32_t stride2 = stride >> 1;
  354. uint32_t width2 = width >> 1;
  355.     uint32_t y;
  356. for (y = height; y; y--) {
  357.     memcpy(y_out, src, width);
  358.     src += width;
  359. y_out += stride;
  360. }
  361. for (y = height >> 1; y; y--) {
  362.     memcpy(u_out, src, width2);
  363. src += width2;
  364. u_out += stride2;
  365. }
  366. for (y = height >> 1; y; y--) {
  367.     memcpy(v_out, src, width2);
  368. src += width2;
  369. v_out+= stride2;
  370. }
  371. }
  372. #ifdef MPEG4IP
  373. void yuv_to_yv12_clip_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  374. uint8_t *src, int width, int height, int raw_height, int stride)
  375. {
  376. uint32_t stride2 = stride >> 1;
  377. uint32_t width2 = width >> 1;
  378.     uint32_t y;
  379. uint32_t yoffset = ((raw_height - height) / 2) * width;
  380. src += yoffset;
  381. for (y = height; y; y--) {
  382.     memcpy(y_out, src, width);
  383.     src += width;
  384. y_out += stride;
  385. }
  386. src += yoffset + (yoffset / 4);
  387. for (y = height >> 1; y; y--) {
  388.     memcpy(u_out, src, width2);
  389. src += width2;
  390. u_out += stride2;
  391. }
  392. src += yoffset / 2;
  393. for (y = height >> 1; y; y--) {
  394.     memcpy(v_out, src, width2);
  395. src += width2;
  396. v_out+= stride2;
  397. }
  398. }
  399. #endif
  400. /* yuyv (yuv2) packed -> yuv 4:2:0 planar
  401.    
  402.    NOTE: does not flip */
  403. void yuyv_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  404. uint8_t *src, int width, int height, int stride)
  405. {
  406. uint32_t width2 = width + width;
  407. uint32_t y_dif = stride - width;
  408. uint32_t uv_dif = y_dif >> 1;
  409. uint32_t x, y;
  410. for (y = height >> 1; y; y--) {
  411.         
  412. for (x = width >> 1; x; x--) {
  413.             *y_out++ = *src++;
  414. //*u_out++ = *src++;
  415. *u_out++ = (*(src+width2) + *src) >> 1; src++;
  416. *y_out++ = *src++;
  417. //*v_out++ = *src++;
  418. *v_out++ = (*(src+width2) + *src) >> 1; src++;
  419. }
  420. y_out += y_dif;
  421. u_out += uv_dif;
  422. v_out += uv_dif; 
  423. for (x = width >> 1; x; x--) {
  424. *y_out++ = *src++;
  425. src++;
  426. *y_out++ = *src++;
  427. src++;
  428. }
  429. y_out += y_dif;
  430.     }
  431. }
  432. /* uyvy packed -> yuv 4:2:0 planar
  433.    
  434.    NOTE: does not flip */
  435. void uyvy_to_yv12_c(uint8_t *y_out, uint8_t *u_out, uint8_t *v_out,
  436. uint8_t *src, int width, int height, int stride)
  437. {
  438. uint32_t width2 = width + width;
  439. uint32_t y_dif = stride - width;
  440. uint32_t uv_dif = y_dif >> 1;
  441.     uint32_t x, y;
  442. for (y = height >> 1; y; y--) {
  443.         
  444. for (x = width >> 1; x; x--) {
  445. *u_out++ = *src++;
  446.             // *u_out++ = (*(src+width2) + *src++) >> 1;
  447. *y_out++ = *src++;
  448. //*v_out++ = *src++;
  449. *v_out++ = (*(src+width2) + *src) >> 1; src++;
  450. *y_out++ = *src++;
  451.          }
  452. y_out += y_dif;
  453. u_out += uv_dif;;
  454. v_out += uv_dif;; 
  455. for (x = width >> 1; x; x--) {
  456. src++;
  457. *y_out++ = *src++;
  458. src++;
  459. *y_out++ = *src++;
  460. }
  461. y_out += y_dif;
  462.     }
  463. }
  464. /* yuv -> rgb def's */
  465. #define RGB_Y_OUT 1.164
  466. #define B_U_OUT 2.018
  467. #define Y_ADD_OUT 16
  468. #define G_U_OUT 0.391
  469. #define G_V_OUT 0.813
  470. #define U_ADD_OUT 128
  471. #define R_V_OUT 1.596
  472. #define V_ADD_OUT 128
  473. #define SCALEBITS_OUT 13
  474. #define FIX_OUT(x) ((uint16_t) ((x) * (1L<<SCALEBITS_OUT) + 0.5))
  475. /* initialize rgb lookup tables */
  476. void colorspace_init(void) {
  477. int32_t i;
  478.     for(i = 0; i < 256; i++) {
  479. RGB_Y_tab[i] = FIX_OUT(RGB_Y_OUT) * (i - Y_ADD_OUT);
  480. B_U_tab[i] = FIX_OUT(B_U_OUT) * (i - U_ADD_OUT);
  481. G_U_tab[i] = FIX_OUT(G_U_OUT) * (i - U_ADD_OUT);
  482. G_V_tab[i] = FIX_OUT(G_V_OUT) * (i - V_ADD_OUT);
  483. R_V_tab[i] = FIX_OUT(R_V_OUT) * (i - V_ADD_OUT);
  484. }
  485. }
  486. /* yuv 4:2:0 planar -> rgb555 + very simple error diffusion
  487. */
  488. #define MK_RGB555(R,G,B) ((MAX(0,MIN(255, R)) << 7) & 0x7c00) | 
  489. ((MAX(0,MIN(255, G)) << 2) & 0x03e0) | 
  490. ((MAX(0,MIN(255, B)) >> 3) & 0x001f)
  491. void yv12_to_rgb555_c(uint8_t *dst, int dst_stride,
  492.  uint8_t *y_src, uint8_t *u_src, uint8_t * v_src, 
  493.  int y_stride, int uv_stride,
  494.  int width, int height)
  495. {
  496. const uint32_t dst_dif = 4 * dst_stride - 2 * width;
  497. int32_t y_dif = 2 * y_stride - width;
  498. uint8_t *dst2 = dst + 2 * dst_stride;
  499. uint8_t *y_src2 = y_src + y_stride;
  500. uint32_t x, y;
  501. if (height < 0) {
  502. height = -height;
  503. y_src += (height - 1) * y_stride;
  504. y_src2 = y_src - y_stride;
  505. u_src += (height / 2 - 1) * uv_stride;
  506. v_src += (height / 2 - 1) * uv_stride;
  507. y_dif = -width - 2 * y_stride;
  508. uv_stride = -uv_stride;
  509. }
  510. for (y = height / 2; y; y--) 
  511. {
  512. int r, g, b;
  513. int r2, g2, b2;
  514. r = g = b = 0;
  515. r2 = g2 = b2 = 0;
  516. // process one 2x2 block per iteration
  517. for (x = 0; x < (uint32_t)width / 2; x++)
  518. {
  519. int u, v;
  520. int b_u, g_uv, r_v, rgb_y;
  521. u = u_src[x];
  522. v = v_src[x];
  523. b_u = B_U_tab[u];
  524. g_uv = G_U_tab[u] + G_V_tab[v];
  525. r_v = R_V_tab[v];
  526. rgb_y = RGB_Y_tab[*y_src];
  527. b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  528. g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  529. r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  530. *(uint16_t*)dst = MK_RGB555(r,g,b);
  531. y_src++;
  532. rgb_y = RGB_Y_tab[*y_src];
  533. b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  534. g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  535. r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  536. *(uint16_t*)(dst+2) = MK_RGB555(r,g,b);
  537. y_src++;
  538. rgb_y = RGB_Y_tab[*y_src2];
  539. b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  540. g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  541. r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  542. *(uint16_t*)(dst2) = MK_RGB555(r2,g2,b2);
  543. y_src2++;
  544. rgb_y = RGB_Y_tab[*y_src2];
  545. b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  546. g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  547. r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  548. *(uint16_t*)(dst2+2) = MK_RGB555(r2,g2,b2);
  549. y_src2++;
  550. dst += 4;
  551. dst2 += 4;
  552. }
  553. dst += dst_dif;
  554. dst2 += dst_dif;
  555. y_src += y_dif;
  556. y_src2 += y_dif;
  557. u_src += uv_stride;
  558. v_src += uv_stride;
  559. }
  560. }
  561. /* yuv 4:2:0 planar -> rgb565 + very simple error diffusion
  562. NOTE: identical to rgb555 except for shift/mask  */
  563. #define MK_RGB565(R,G,B) ((MAX(0,MIN(255, R)) << 8) & 0xf800) | 
  564. ((MAX(0,MIN(255, G)) << 3) & 0x07e0) | 
  565. ((MAX(0,MIN(255, B)) >> 3) & 0x001f)
  566. void yv12_to_rgb565_c(uint8_t *dst, int dst_stride,
  567.  uint8_t *y_src, uint8_t *u_src, uint8_t * v_src, 
  568.  int y_stride, int uv_stride,
  569.  int width, int height)
  570. {
  571. const uint32_t dst_dif = 4 * dst_stride - 2 * width;
  572. int32_t y_dif = 2 * y_stride - width;
  573. uint8_t *dst2 = dst + 2 * dst_stride;
  574. uint8_t *y_src2 = y_src + y_stride;
  575. uint32_t x, y;
  576. if (height < 0) { // flip image?
  577. height = -height;
  578. y_src += (height - 1) * y_stride;
  579. y_src2 = y_src - y_stride;
  580. u_src += (height / 2 - 1) * uv_stride;
  581. v_src += (height / 2 - 1) * uv_stride;
  582. y_dif = -width - 2 * y_stride;
  583. uv_stride = -uv_stride;
  584. }
  585. for (y = height / 2; y; y--) 
  586. {
  587. int r, g, b;
  588. int r2, g2, b2;
  589. r = g = b = 0;
  590. r2 = g2 = b2 = 0;
  591. // process one 2x2 block per iteration
  592. for (x = 0; x < (uint32_t)width / 2; x++)
  593. {
  594. int u, v;
  595. int b_u, g_uv, r_v, rgb_y;
  596. u = u_src[x];
  597. v = v_src[x];
  598. b_u = B_U_tab[u];
  599. g_uv = G_U_tab[u] + G_V_tab[v];
  600. r_v = R_V_tab[v];
  601. rgb_y = RGB_Y_tab[*y_src];
  602. b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  603. g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  604. r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  605. *(uint16_t*)dst = MK_RGB565(r,g,b);
  606. y_src++;
  607. rgb_y = RGB_Y_tab[*y_src];
  608. b = (b & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  609. g = (g & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  610. r = (r & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  611. *(uint16_t*)(dst+2) = MK_RGB565(r,g,b);
  612. y_src++;
  613. rgb_y = RGB_Y_tab[*y_src2];
  614. b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  615. g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  616. r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  617. *(uint16_t*)(dst2) = MK_RGB565(r2,g2,b2);
  618. y_src2++;
  619. rgb_y = RGB_Y_tab[*y_src2];
  620. b2 = (b2 & 0x7) + ((rgb_y + b_u) >> SCALEBITS_OUT);
  621. g2 = (g2 & 0x7) + ((rgb_y - g_uv) >> SCALEBITS_OUT);
  622. r2 = (r2 & 0x7) + ((rgb_y + r_v) >> SCALEBITS_OUT);
  623. *(uint16_t*)(dst2+2) = MK_RGB565(r2,g2,b2);
  624. y_src2++;
  625. dst += 4;
  626. dst2 += 4;
  627. }
  628. dst += dst_dif;
  629. dst2 += dst_dif;
  630. y_src += y_dif;
  631. y_src2 += y_dif;
  632. u_src += uv_stride;
  633. v_src += uv_stride;
  634. }
  635. }
  636. /* yuv 4:2:0 planar -> rgb24 */
  637. void yv12_to_rgb24_c(uint8_t *dst, int dst_stride,
  638.  uint8_t *y_src, uint8_t *u_src, uint8_t * v_src, 
  639.  int y_stride, int uv_stride,
  640.  int width, int height)
  641. {
  642. const uint32_t dst_dif = 6 * dst_stride - 3 * width;
  643. int32_t y_dif = 2 * y_stride - width;
  644. uint8_t *dst2 = dst + 3 * dst_stride;
  645. uint8_t *y_src2 = y_src + y_stride;
  646. uint32_t x, y;
  647. if (height < 0) { // flip image?
  648. height = -height;
  649. y_src += (height - 1) * y_stride;
  650. y_src2 = y_src - y_stride;
  651. u_src += (height / 2 - 1) * uv_stride;
  652. v_src += (height / 2 - 1) * uv_stride;
  653. y_dif = -width - 2 * y_stride;
  654. uv_stride = -uv_stride;
  655. }
  656. for (y = height / 2; y; y--) 
  657. {
  658. // process one 2x2 block per iteration
  659. for (x = 0; x < (uint32_t)width / 2; x++)
  660. {
  661. int u, v;
  662. int b_u, g_uv, r_v, rgb_y;
  663. int r, g, b;
  664. u = u_src[x];
  665. v = v_src[x];
  666. b_u = B_U_tab[u];
  667. g_uv = G_U_tab[u] + G_V_tab[v];
  668. r_v = R_V_tab[v];
  669. rgb_y = RGB_Y_tab[*y_src];
  670. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  671. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  672. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  673. dst[0] = MAX(0,MIN(255, b));
  674. dst[1] = MAX(0,MIN(255, g));
  675. dst[2] = MAX(0,MIN(255, r));
  676. y_src++;
  677. rgb_y = RGB_Y_tab[*y_src];
  678. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  679. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  680. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  681. dst[3] = MAX(0,MIN(255, b));
  682. dst[4] = MAX(0,MIN(255, g));
  683. dst[5] = MAX(0,MIN(255, r));
  684. y_src++;
  685. rgb_y = RGB_Y_tab[*y_src2];
  686. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  687. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  688. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  689. dst2[0] = MAX(0,MIN(255, b));
  690. dst2[1] = MAX(0,MIN(255, g));
  691. dst2[2] = MAX(0,MIN(255, r));
  692. y_src2++;
  693. rgb_y = RGB_Y_tab[*y_src2];
  694. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  695. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  696. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  697. dst2[3] = MAX(0,MIN(255, b));
  698. dst2[4] = MAX(0,MIN(255, g));
  699. dst2[5] = MAX(0,MIN(255, r));
  700. y_src2++;
  701. dst += 6;
  702. dst2 += 6;
  703. }
  704. dst += dst_dif;
  705. dst2 += dst_dif;
  706. y_src += y_dif;
  707. y_src2 += y_dif;
  708. u_src += uv_stride;
  709. v_src += uv_stride;
  710. }
  711. }
  712. /* yuv 4:2:0 planar -> rgb32 */
  713. void yv12_to_rgb32_c(uint8_t *dst, int dst_stride,
  714.  uint8_t *y_src, uint8_t *v_src, uint8_t * u_src,
  715.  int y_stride, int uv_stride,
  716.  int width, int height)
  717. {
  718. const uint32_t dst_dif = 8 * dst_stride - 4 * width;
  719. int32_t y_dif = 2 * y_stride - width;
  720. uint8_t *dst2 = dst + 4 * dst_stride;
  721. uint8_t *y_src2 = y_src + y_stride;
  722. uint32_t x, y;
  723. if (height < 0) { // flip image?
  724. height = -height;
  725. y_src += (height - 1) * y_stride;
  726. y_src2 = y_src - y_stride;
  727. u_src += (height / 2 - 1) * uv_stride;
  728. v_src += (height / 2 - 1) * uv_stride;
  729. y_dif = -width - 2 * y_stride;
  730. uv_stride = -uv_stride;
  731. }
  732. for (y = height / 2; y; y--) 
  733. {
  734. // process one 2x2 block per iteration
  735. for (x = 0; x < (uint32_t)width / 2; x++)
  736. {
  737. int u, v;
  738. int b_u, g_uv, r_v, rgb_y;
  739. int r, g, b;
  740. u = u_src[x];
  741. v = v_src[x];
  742. b_u = B_U_tab[u];
  743. g_uv = G_U_tab[u] + G_V_tab[v];
  744. r_v = R_V_tab[v];
  745. rgb_y = RGB_Y_tab[*y_src];
  746. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  747. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  748. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  749. dst[0] = MAX(0,MIN(255, r));
  750. dst[1] = MAX(0,MIN(255, g));
  751. dst[2] = MAX(0,MIN(255, b));
  752. dst[3] = 0;
  753. y_src++;
  754. rgb_y = RGB_Y_tab[*y_src];
  755. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  756. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  757. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  758. dst[4] = MAX(0,MIN(255, r));
  759. dst[5] = MAX(0,MIN(255, g));
  760. dst[6] = MAX(0,MIN(255, b));
  761. dst[7] = 0;
  762. y_src++;
  763. rgb_y = RGB_Y_tab[*y_src2];
  764. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  765. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  766. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  767. dst2[0] = MAX(0,MIN(255, r));
  768. dst2[1] = MAX(0,MIN(255, g));
  769. dst2[2] = MAX(0,MIN(255, b));
  770. dst2[3] = 0;
  771. y_src2++;
  772. rgb_y = RGB_Y_tab[*y_src2];
  773. b = (rgb_y + b_u) >> SCALEBITS_OUT;
  774. g = (rgb_y - g_uv) >> SCALEBITS_OUT;
  775. r = (rgb_y + r_v) >> SCALEBITS_OUT;
  776. dst2[4] = MAX(0,MIN(255, r));
  777. dst2[5] = MAX(0,MIN(255, g));
  778. dst2[6] = MAX(0,MIN(255, b));
  779. dst2[7] = 0;
  780. y_src2++;
  781. dst += 8;
  782. dst2 += 8;
  783. }
  784. dst += dst_dif;
  785. dst2 += dst_dif;
  786. y_src += y_dif;
  787. y_src2 += y_dif;
  788. u_src += uv_stride;
  789. v_src += uv_stride;
  790. }
  791. }
  792. /* yuv 4:2:0 planar -> yuv planar */
  793. void yv12_to_yuv_c(uint8_t *dst, int dst_stride,
  794.  uint8_t *y_src, uint8_t *u_src, uint8_t * v_src, 
  795.  int y_stride, int uv_stride,
  796.  int width, int height)
  797. {
  798. uint32_t dst_stride2 = dst_stride >> 1;
  799. uint32_t width2 = width >> 1;
  800.     uint32_t y;
  801. if (height < 0) {
  802. height = -height;
  803. y_src += (height - 1) * y_stride ;
  804. u_src += (height / 2 - 1) * uv_stride;
  805. v_src += (height / 2 - 1) * uv_stride;
  806. y_stride = -y_stride;
  807. uv_stride = -uv_stride;
  808. }
  809. for (y = height; y; y--) {
  810.     memcpy(dst, y_src, width);
  811.     dst += dst_stride;
  812. y_src += y_stride;
  813. }
  814. for (y = height >> 1; y; y--) {
  815.     memcpy(dst, u_src, width2);
  816. dst += dst_stride2;
  817. u_src += uv_stride;
  818. }
  819. for (y = height >> 1; y; y--) {
  820.     memcpy(dst, v_src, width2);
  821. dst += dst_stride2;
  822. v_src += uv_stride;
  823. }
  824. }
  825. /* yuv 4:2:0 planar -> yuyv (yuv2) packed */
  826. void yv12_to_yuyv_c(uint8_t *dst, int dst_stride,
  827.  uint8_t *y_src, uint8_t *u_src, uint8_t * v_src, 
  828.  int y_stride, int uv_stride,
  829.  int width, int height)
  830. {
  831. const uint32_t dst_dif = 2*(dst_stride - width);
  832. uint32_t x, y;
  833. if (height < 0) {
  834. height = -height;
  835. y_src += (height   - 1) * y_stride ;
  836. u_src += (height / 2 - 1) * uv_stride;
  837. v_src += (height / 2 - 1) * uv_stride;
  838. y_stride = -y_stride;
  839. uv_stride = -uv_stride;
  840. }
  841. for (y = 0; y < (uint32_t)height; y++)
  842. {
  843. for (x = 0; x < (uint32_t)width / 2; x++)
  844. {
  845. dst[0] = y_src[2*x];
  846. dst[1] = u_src[x];
  847. dst[2] = y_src[2*x + 1];
  848. dst[3] = v_src[x];
  849. dst += 4;
  850. }
  851. dst += dst_dif;
  852. y_src += y_stride;
  853. if (y&1)
  854. {
  855. u_src += uv_stride;
  856. v_src += uv_stride;
  857. }
  858. }
  859. }
  860. /* yuv 4:2:0 planar -> uyvy packed */
  861. void yv12_to_uyvy_c(uint8_t *dst, int dst_stride,
  862.  uint8_t *y_src, uint8_t *u_src, uint8_t * v_src, 
  863.  int y_stride, int uv_stride,
  864.  int width, int height)
  865. {
  866. const uint32_t dst_dif = 2*(dst_stride - width);
  867. uint32_t x, y;
  868. if (height < 0) {
  869. height = -height;
  870. y_src += (height   - 1) * y_stride ;
  871. u_src += (height / 2 - 1) * uv_stride;
  872. v_src += (height / 2 - 1) * uv_stride;
  873. y_stride = -y_stride;
  874. uv_stride = -uv_stride;
  875. }
  876. for (y = 0; y < (uint32_t)height; y++)
  877. {
  878. for (x = 0; x < (uint32_t)width / 2; x++)
  879. {
  880. dst[0] = u_src[x];
  881. dst[1] = y_src[2*x];
  882. dst[2] = v_src[x];
  883. dst[3] = y_src[2*x + 1];
  884. dst += 4;
  885. }
  886. dst += dst_dif;
  887. y_src += y_stride;
  888. if (y&1)
  889. {
  890. u_src += uv_stride;
  891. v_src += uv_stride;
  892. }
  893. }
  894. }