2 * @file vp_stages_yuv2rgb.c
3 * @brief VP Stages. YUV to RGB converter stage declaration
6 #ifdef _INCLUDED_FOR_DOXYGEN_
7 #else // ! _INCLUDED_FOR_DOXYGEN_
9 ///////////////////////////////////////////////
12 #include <VP_Stages/vp_stages_yuv2rgb.h>
13 #include <VP_Api/vp_api_config.h>
14 #include <VP_Api/vp_api_picture.h>
15 #include <VP_Os/vp_os_print.h>
16 #include <VP_Os/vp_os_malloc.h>
17 #include <VP_Os/vp_os_assert.h>
19 #endif // < _INCLUDED_FOR_DOXYGEN_
22 #ifdef USE_YUV2RGB_STRETCH
24 static C_RESULT vp_stages_yuv2rgb_open(vp_stages_yuv2rgb_config_t *cfg);
25 static C_RESULT vp_stages_yuv2rgb_close(vp_stages_yuv2rgb_config_t *cfg);
26 static void vp_stages_yuv2rgb_hresample(uint32_t sample0, uint32_t sample1, int8_t cov, int8_t* frac, uint32_t* line0, uint32_t* line1, int* dx);
27 static void vp_stages_yuv2rgb_hstretch(uint8_t* y_base, int32_t y_rbytes, uint8_t* cb_base, uint8_t* cr_base, uint32_t* line0, uint32_t* line1);
28 static void vp_stages_yuv2rgb_vstretch(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes, int8_t cov, int8_t* frac, uint32_t* line, int* dy);
29 static void vp_stages_yuv2rgb_flushline_565(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes, int y);
33 #define SRC_HEIGHT 144
35 #define DST_HEIGHT 240
37 /******************************************************************************/
39 /* 176*144 (YCbCr, 4:2:0) -> 320*240 (RGB-16bits, 5:6:5) */
41 /******************************************************************************/
43 static int8_t htable[SRC_WIDTH] =
45 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E,
46 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
47 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
48 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E,
49 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E,
50 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
51 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F,
52 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E,
53 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E,
54 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F,
55 0x0E, 0x0F, 0x0E, 0x0F, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0E, 0x0F, 0x0F
58 static int8_t vtable[SRC_HEIGHT] =
60 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D,
61 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D,
62 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E,
63 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D,
64 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D,
65 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E,
66 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D,
67 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D,
68 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E, 0x0D, 0x0D, 0x0E
71 /******************************************************************************/
73 #endif // < USE_YUV2RGB_STRETCH
77 * @def VP_STAGES_YUV2RGB_LIMIT(x)
78 * @brief Macro used for ARGB32 saturation
80 * Moves x in a limited range of values (between 0 and 0xff).
82 //#define VP_STAGES_YUV2ARGB_LIMIT(x) ( (x) > 0xffff ? 0xff : ( (x) <= 0xff ? 0 : ( (x) >> 8 ) ) )
83 #define VP_STAGES_YUV2ARGB_LIMIT(dst, x) \
85 dst = (dst > 0 ? ( ((dst) >> 8) > 0xff ? 0xff : ((dst) >> 8) ) : 0);
88 * @def VP_STAGES_YUV2RGB_SAT5U(a)
89 * @brief 5 bits saturation
91 #define VP_STAGES_YUV2RGB_SAT5U(a) \
92 if((a) < 0) (a) = 0; \
93 else if((a) > 0x1F) (a) = 0x1F;
96 * @def VP_STAGES_YUV2RGB_SAT6U(a)
97 * @brief 6 bits saturation
99 #define VP_STAGES_YUV2RGB_SAT6U(a) \
100 if((a) < 0) (a) = 0; \
101 else if((a) > 0x3F) (a) = 0x3F;
103 /** Pointer to a YUV to RGB conversion function
105 static vp_stages_YUV_to_RGB_t vp_stages_YUV_to_RGB;
108 /** YUV to RGB conversion functions
110 void vp_stages_YUV420P_to_RGB565(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
111 void vp_stages_YUV420P_to_RGB24(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
112 void vp_stages_YUV420P_to_ARGB32(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
113 #else // ! QCIF_TO_QVGA
114 /** YUV to RGB conversion + resizing
116 #ifdef USE_YUV2RGB_STRETCH
117 static void vp_stages_YUV420P_to_RGB565_QCIF_to_QVGA_stretch(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
118 #else // ! USE_YUV2RGB_STRETCH
119 static void vp_stages_YUV420P_to_RGB565_QCIF_to_QVGA(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
120 static void vp_stages_YUV420P_to_RGB24_QCIF_to_QVGA(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
121 static void vp_stages_YUV420P_to_ARGB32_QCIF_to_QVGA(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes);
122 #endif // < USE_YUV2RGB_STRETCH
123 #endif // < QCIF_TO_QVGA
127 void vp_stages_YUV420P_to_RGB565(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
132 width = picture->width >> 1;
133 height = picture->height >> 1;
135 for (h = 0; h < height; h++)
143 s0 = picture->y_buf + (h * picture->y_line_size * 2);
144 s1 = picture->cb_buf + (h * picture->cb_line_size);
145 s2 = picture->cr_buf + (h * picture->cr_line_size);
146 d0 = (uint16_t*) (dst + (h * dst_rbytes * 2));
147 d1 = (uint16_t*) (dst + (h * dst_rbytes * 2) + dst_rbytes);
149 for (w = 0; w < width; w++)
152 int32_t c_r, c_g, c_b;
155 cb = ((uint32_t) *(s1++)) - 0x80L;
156 cr = ((uint32_t) *(s2++)) - 0x80L;
158 c_g = (cb * -88L) + (cr * -183L);
161 y = ((uint32_t) s0[0]) << 8;
162 r = (int16_t) ((y + c_r + 0x000) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
163 g = (int16_t) ((y + c_g + 0x000) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
164 b = (int16_t) ((y + c_b + 0x000) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
165 d0[0] = (r << 11) | (g << 5) | (b << 0);
167 y = ((uint32_t) s0[1]) << 8;
168 r = (int16_t) ((y + c_r + 0x400) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
169 g = (int16_t) ((y + c_g + 0x200) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
170 b = (int16_t) ((y + c_b + 0x400) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
171 d0[1] = (r << 11) | (g << 5) | (b << 0);
173 y = ((uint32_t) s0[picture->y_line_size + 0]) << 8;
174 r = (int16_t) ((y + c_r + 0x600) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
175 g = (int16_t) ((y + c_g + 0x300) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
176 b = (int16_t) ((y + c_b + 0x600) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
177 d1[0] = (r << 11) | (g << 5) | (b << 0);
179 y = ((uint32_t) s0[picture->y_line_size + 1]) << 8;
180 r = (int16_t) ((y + c_r + 0x200) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
181 g = (int16_t) ((y + c_g + 0x100) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
182 b = (int16_t) ((y + c_b + 0x200) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
183 d1[1] = (r << 11) | (g << 5) | (b << 0);
191 #endif // < QCIF_TO_QVGA
195 void vp_stages_YUV420P_to_RGB24(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
197 uint32_t width, height;
198 int32_t line, col, linewidth;
199 int32_t y, u, v, r, g, b;
200 int32_t vr, ug, vg, ub;
201 uint8_t *py, *pu, *pv;
203 int32_t lineSz0 = picture->y_line_size;
204 int32_t lineSz1 = picture->cb_line_size;
205 int32_t lineSz2 = picture->cr_line_size;
207 width = picture->width;
208 height = picture->height;
210 linewidth = width - (width >> 1);
212 if(cfg->mode == VP_STAGES_YUV2RGB_MODE_UPSIDE_DOWN)
214 py = picture->y_buf+lineSz0*(height-1)+width-1;
215 pu = picture->cb_buf+lineSz1*((height>>1)-1)+((width>>1)-1);
216 pv = picture->cr_buf+lineSz2*((height>>1)-1)+((width>>1)-1);
218 for (line = height-1; line >= 0; line--) {
219 for (col = width-1; col >= 0; col--) {
229 VP_STAGES_YUV2ARGB_LIMIT(r, y + vr);
230 VP_STAGES_YUV2ARGB_LIMIT(g, y - ug - vg);
231 VP_STAGES_YUV2ARGB_LIMIT(b, y + ub );
257 py -= lineSz0 - width;
263 pu = picture->cb_buf;
264 pv = picture->cr_buf;
266 for (line = 0; line < (int32_t)height; line++) {
267 for (col = 0; col < (int32_t)width; col++) {
277 VP_STAGES_YUV2ARGB_LIMIT(r, y + vr);
278 VP_STAGES_YUV2ARGB_LIMIT(g, y - ug - vg);
279 VP_STAGES_YUV2ARGB_LIMIT(b, y + ub );
305 py += lineSz0 - width;
309 #endif // < QCIF_TO_QVGA
313 void vp_stages_YUV420P_to_ARGB32(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
315 uint32_t width, height;
316 int32_t line, col, linewidth;
317 int32_t y, u, v, r, g, b;
318 int32_t vr, ug, vg, ub;
319 uint8_t *py, *pu, *pv;
321 int32_t lineSz0 = picture->y_line_size;
322 int32_t lineSz1 = picture->cb_line_size;
323 int32_t lineSz2 = picture->cr_line_size;
325 width = picture->width;
326 height = picture->height;
328 linewidth = width - (width >> 1);
331 pu = picture->cb_buf;
332 pv = picture->cr_buf;
334 for (line = 0; line < (int32_t)height; line++) {
335 for (col = 0; col < (int32_t)width; col++) {
345 VP_STAGES_YUV2ARGB_LIMIT(r, y + vr);
346 VP_STAGES_YUV2ARGB_LIMIT(g, y - ug - vg);
347 VP_STAGES_YUV2ARGB_LIMIT(b, y + ub);
354 dst+=2; //skip Alpha value
373 py += lineSz0 - width;
376 #endif // < QCIF_TO_QVGA
380 #ifdef USE_YUV2RGB_STRETCH
381 static void vp_stages_YUV420P_to_RGB565_QCIF_to_QVGA_stretch(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
390 vp_os_memset(cfg->vline, 0, dst_rbytes);
393 cb = picture->cb_buf;
394 cr = picture->cr_buf;
397 for (h = 0; h < SRC_HEIGHT; h += 2)
399 vp_stages_yuv2rgb_hstretch(y, picture->y_line_size, cb, cr, cfg->hline0, cfg->hline1);
400 vp_stages_yuv2rgb_vstretch(cfg, picture, dst, dst_rbytes, vtable[h + 0], &vfrac, cfg->hline0, &dy);
401 vp_stages_yuv2rgb_vstretch(cfg, picture, dst, dst_rbytes, vtable[h + 1], &vfrac, cfg->hline1, &dy);
402 y += (picture->y_line_size * 2);
403 cb += picture->cb_line_size;
404 cr += picture->cr_line_size;
407 #endif // < USE_YUV2RGB_STRETCH
408 #endif // < QCIF_TO_QVGA
412 #ifndef USE_YUV2RGB_STRETCH
413 static void vp_stages_YUV420P_to_RGB565_QCIF_to_QVGA(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
423 int32_t c_r, c_g, c_b;
426 width = QVGA_WIDTH >> 2;
427 height = QVGA_HEIGHT >> 2;
429 for (h = 0; h < height; h++)
431 s0 = picture->y_buf + ((h * picture->y_line_size)<<1);
432 s1 = picture->cb_buf + (h * picture->cb_line_size);
433 s2 = picture->cr_buf + (h * picture->cr_line_size);
434 d0 = (uint16_t*) (dst + ((h * QVGA_WIDTH) << 3));
435 d1 = (uint16_t*) (dst + ((h * QVGA_WIDTH) << 3) + (QVGA_WIDTH << 2));
437 for (w = 0; w < width; w++)
439 cb = ((uint32_t) *(s1++)) - 0x80L;
440 cr = ((uint32_t) *(s2++)) - 0x80L;
442 c_g = (cb * -88L) + (cr * -183L);
445 y = ((uint32_t) s0[0]) << 8;
446 r = (int16_t) ((y + c_r + 0x000) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
447 g = (int16_t) ((y + c_g + 0x000) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
448 b = (int16_t) ((y + c_b + 0x000) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
449 d0[0] = (r << 11) | (g << 5) | (b << 0);
452 y = ((uint32_t) s0[1]) << 8;
453 r = (int16_t) ((y + c_r + 0x400) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
454 g = (int16_t) ((y + c_g + 0x200) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
455 b = (int16_t) ((y + c_b + 0x400) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
456 d0[2] = (r << 11) | (g << 5) | (b << 0);
459 y = ((uint32_t) s0[picture->y_line_size + 0]) << 8;
460 r = (int16_t) ((y + c_r + 0x600) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
461 g = (int16_t) ((y + c_g + 0x300) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
462 b = (int16_t) ((y + c_b + 0x600) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
463 d1[0] = (r << 11) | (g << 5) | (b << 0);
466 y = ((uint32_t) s0[picture->y_line_size + 1]) << 8;
467 r = (int16_t) ((y + c_r + 0x200) >> 11); VP_STAGES_YUV2RGB_SAT5U(r);
468 g = (int16_t) ((y + c_g + 0x100) >> 10); VP_STAGES_YUV2RGB_SAT6U(g);
469 b = (int16_t) ((y + c_b + 0x200) >> 11); VP_STAGES_YUV2RGB_SAT5U(b);
470 d1[2] = (r << 11) | (g << 5) | (b << 0);
477 vp_os_memcpy(dst + ((h * QVGA_WIDTH) << 3) + (QVGA_WIDTH<<1), dst + ((h * QVGA_WIDTH) << 3), QVGA_WIDTH<<1);
478 vp_os_memcpy(dst + ((h * QVGA_WIDTH) << 3) + (QVGA_WIDTH<<1)*3, dst + ((h * QVGA_WIDTH) << 3) + (QVGA_WIDTH<<2), QVGA_WIDTH<<1);
481 #endif // < USE_YUV2RGB_STRETCH
482 #endif // < QCIF_TO_QVGA
486 #ifndef USE_YUV2RGB_STRETCH
487 static void vp_stages_YUV420P_to_RGB24_QCIF_to_QVGA(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
490 #endif // < USE_YUV2RGB_STRETCH
491 #endif // < QCIF_TO_QVGA
495 #ifndef USE_YUV2RGB_STRETCH
496 static void vp_stages_YUV420P_to_ARGB32_QCIF_to_QVGA(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes)
498 uint32_t width, height;
499 int32_t line, col, linewidth;
500 int32_t y, u, v, r, g, b;
501 int32_t vr, ug, vg, ub;
502 uint8_t *py, *pu, *pv;
504 int32_t lineSz0 = picture->y_line_size;
505 int32_t lineSz1 = picture->cb_line_size;
506 int32_t lineSz2 = picture->cr_line_size;
508 width = picture->width;
509 height = picture->height;
511 linewidth = width - (width >> 1);
514 pu = picture->cb_buf;
515 pv = picture->cr_buf;
517 for (line = 0; line < (QVGA_HEIGHT >> 1); line++) {
518 for (col = 0; col < (QVGA_WIDTH >> 1); col++) {
528 VP_STAGES_YUV2ARGB_LIMIT(r, y + vr);
529 VP_STAGES_YUV2ARGB_LIMIT(g, y - ug - vg);
530 VP_STAGES_YUV2ARGB_LIMIT(b, y + ub);
537 dst+=2; //skip Alpha value
554 pu -= (QVGA_WIDTH >> 2);
555 pv -= (QVGA_WIDTH >> 2);
562 py += lineSz0 - (QVGA_WIDTH >> 1);
564 vp_os_memcpy(dst, dst - (QVGA_WIDTH<<2), QVGA_WIDTH<<2);
565 dst += (QVGA_WIDTH<<2);
568 #endif // < USE_YUV2RGB_STRETCH
569 #endif // < QCIF_TO_QVGA
572 /******************************************************************************/
574 #ifdef USE_YUV2RGB_STRETCH
575 static C_RESULT vp_stages_yuv2rgb_open(vp_stages_yuv2rgb_config_t *cfg)
577 C_RESULT res = VP_SUCCESS;
579 cfg->hline0 = (uint32_t*) vp_os_malloc(DST_WIDTH * sizeof(uint32_t));
580 cfg->hline1 = (uint32_t*) vp_os_malloc(DST_WIDTH * sizeof(uint32_t));
581 cfg->vline = (uint32_t*) vp_os_malloc(DST_WIDTH * sizeof(uint32_t));
582 if (cfg->hline0 && cfg->hline1 && cfg->vline)
588 vp_stages_yuv2rgb_close(cfg);
595 /******************************************************************************/
597 static C_RESULT vp_stages_yuv2rgb_close(vp_stages_yuv2rgb_config_t *cfg)
601 vp_os_free(cfg->hline0);
606 vp_os_free(cfg->hline1);
611 vp_os_free(cfg->vline);
617 /******************************************************************************/
619 static void vp_stages_yuv2rgb_hresample(uint32_t sample0, uint32_t sample1, int8_t cov, int8_t* frac, uint32_t* line0, uint32_t* line1, int* dx)
647 line0[i] += (sample0 >> 3) & 0x1F1F1F1FUL;
648 line1[i] += (sample1 >> 3) & 0x1F1F1F1FUL;
652 line0[i] += (sample0 >> 2) & 0x3F3F3F3FUL;
653 line1[i] += (sample1 >> 2) & 0x3F3F3F3FUL;
657 line0[i] += ((sample0 >> 1) & 0x7F7F7F7FUL) - ((sample0 >> 3) & 0x1F1F1F1FUL);
658 line1[i] += ((sample1 >> 1) & 0x7F7F7F7FUL) - ((sample1 >> 3) & 0x1F1F1F1FUL);
662 line0[i] += (sample0 >> 1) & 0x7F7F7F7FUL;
663 line1[i] += (sample1 >> 1) & 0x7F7F7F7FUL;
667 line0[i] += ((sample0 >> 1) & 0x7F7F7F7FUL) + ((sample0 >> 3) & 0x1F1F1F1FUL);
668 line1[i] += ((sample1 >> 1) & 0x7F7F7F7FUL) + ((sample1 >> 3) & 0x1F1F1F1FUL);
672 line0[i] += sample0 - ((sample0 >> 2) & 0x3F3F3F3FUL);
673 line1[i] += sample1 - ((sample1 >> 2) & 0x3F3F3F3FUL);
677 line0[i] += sample0 - ((sample0 >> 3) & 0x1F1F1F1FUL);
678 line1[i] += sample1 - ((sample1 >> 3) & 0x1F1F1F1FUL);
702 /*----------------------------------------------------------------------------*/
704 static void vp_stages_yuv2rgb_hstretch(uint8_t* y_base, int32_t y_rbytes, uint8_t* cb_base, uint8_t* cr_base, uint32_t* line0, uint32_t* line1)
719 for (sx = 0; sx < 176; sx += 2)
722 uint32_t cr_cg_cb, smp0, smp1;
724 cb = (int32_t) ((uint32_t) *(s1++));
725 cr = (int32_t) ((uint32_t) *(s2++));
726 cr_cg_cb = ((cr * 180L) << 8) & 0xFF0000UL;
727 cr_cg_cb |= ((cb * 44L) + (cr * 91L)) & 0xFF00UL;
728 cr_cg_cb |= ((cb * 227L) >> 8) & 0xFFUL;
730 smp0 = cr_cg_cb | (((uint32_t) s0[0]) << 24);
731 smp1 = cr_cg_cb | (((uint32_t) s0[y_rbytes + 0]) << 24);
732 vp_stages_yuv2rgb_hresample(smp0, smp1, htable[sx], &frac, line0, line1, &dx);
734 smp0 = cr_cg_cb | (((uint32_t) s0[1]) << 24);
735 smp1 = cr_cg_cb | (((uint32_t) s0[y_rbytes + 1]) << 24);
736 vp_stages_yuv2rgb_hresample(smp0, smp1, htable[sx], &frac, line0, line1, &dx);
741 /*----------------------------------------------------------------------------*/
743 static void vp_stages_yuv2rgb_vstretch(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst_base, uint32_t dst_rbytes, int8_t cov, int8_t* frac, uint32_t* line, int* dy)
773 for (dx = 0; dx < DST_WIDTH; dx++)
783 for (dx = 0; dx < DST_WIDTH; dx++)
788 dst[dx] += (ycc) - ((ycc >> 3) & 0x1F1F1F1FUL);
793 for (dx = 0; dx < DST_WIDTH; dx++)
798 dst[dx] += (ycc) - ((ycc >> 2) & 0x3F3F3F3FUL);
803 for (dx = 0; dx < DST_WIDTH; dx++)
808 dst[dx] += ((ycc >> 1) & 0x7F7F7F7FUL) + ((ycc >> 3) & 0x1F1F1F1FUL);
813 for (dx = 0; dx < DST_WIDTH; dx++)
818 dst[dx] += ((ycc >> 1) & 0x7F7F7F7FUL);
823 for (dx = 0; dx < DST_WIDTH; dx++)
828 dst[dx] += ((ycc >> 1) & 0x7F7F7F7FUL) - ((ycc >> 3) & 0x1F1F1F1FUL);
833 for (dx = 0; dx < DST_WIDTH; dx++)
838 dst[dx] += ((ycc >> 2) & 0x3F3F3F3FUL);
843 for (dx = 0; dx < DST_WIDTH; dx++)
848 dst[dx] += ((ycc >> 3) & 0x1F1F1F1FUL);
859 vp_stages_yuv2rgb_flushline_565(cfg, picture, dst_base, dst_rbytes, y++);
868 /*----------------------------------------------------------------------------*/
870 static void vp_stages_yuv2rgb_flushline_565(vp_stages_yuv2rgb_config_t *cfg, vp_api_picture_t *picture, uint8_t *dst, uint32_t dst_rbytes, int y)
878 d = (uint16_t*) (dst + (dst_rbytes * y));
886 for (i = 0; i < DST_WIDTH; i += 2)
891 int32_t c_r, c_g, c_b;
894 y = ((uint32_t) ycc) >> 24;
895 c_r = ycc << 8; c_r = ((uint32_t) c_r) >> 23; c_r -= 180;
896 c_g = ycc << 16; c_g = ((uint32_t) c_g) >> 23; c_g -= 135;
897 c_b = ycc << 24; c_b = ((uint32_t) c_b) >> 23; c_b -= 227;
898 r = (even + y + c_r) >> 3; VP_STAGES_YUV2RGB_SAT5U(r);
899 g = ((even >> 1) + y - c_g) >> 2; VP_STAGES_YUV2RGB_SAT6U(g);
900 b = (even + y + c_b) >> 3; VP_STAGES_YUV2RGB_SAT5U(b);
901 d[0] = (r << 11) | (g << 5) | (b << 0);
904 y = ((uint32_t) ycc) >> 24;
905 c_r = ycc << 8; c_r = ((uint32_t) c_r) >> 23; c_r -= 180;
906 c_g = ycc << 16; c_g = ((uint32_t) c_g) >> 23; c_g -= 135;
907 c_b = ycc << 24; c_b = ((uint32_t) c_b) >> 23; c_b -= 227;
908 r = (odd + y + c_r) >> 3; VP_STAGES_YUV2RGB_SAT5U(r);
909 g = ((odd >> 1) + y - c_g) >> 2; VP_STAGES_YUV2RGB_SAT6U(g);
910 b = (odd + y + c_b) >> 3; VP_STAGES_YUV2RGB_SAT5U(b);
911 d[1] = (r << 11) | (g << 5) | (b << 0);
919 asm_yuvrgb565(dst, dst_rbytes, cfg->vline, y);
920 //static void flushline_565(uint16_t* dst, int32_t dst_rbytes, uint32_t* src, int y);
924 /******************************************************************************/
925 #endif // < USE_YUV2RGB_STRETCH
928 C_RESULT vp_stages_yuv2rgb_stage_open(vp_stages_yuv2rgb_config_t *cfg)
930 C_RESULT res = VP_SUCCESS;
932 #ifdef USE_YUV2RGB_STRETCH
933 if(VP_FAILED(vp_stages_yuv2rgb_open(cfg))) {
936 #endif // < USE_YUV2RGB_STRETCH
942 C_RESULT vp_stages_yuv2rgb_stage_transform(vp_stages_yuv2rgb_config_t *cfg, vp_api_io_data_t *in, vp_api_io_data_t *out)
944 uint32_t width, height;
945 static uint32_t bytesPerPixel = 0;
947 vp_api_picture_t *picture;
949 vp_os_mutex_lock(&out->lock);
953 picture = (vp_api_picture_t *) in->buffers; //&in->buffers[in->indexBuffer];
956 width = picture->width;
957 height = picture->height;
958 #else // QCIF_TO_QVGA
960 height = QVGA_HEIGHT;
961 #endif // < QCIF_TO_QVGA
963 if(out->status == VP_API_STATUS_INIT)
965 switch(cfg->rgb_format)
967 case VP_STAGES_RGB_FORMAT_RGB565:
970 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_RGB565;
971 #else // QCIF_TO_QVGA
972 # ifndef USE_YUV2RGB_STRETCH
973 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_RGB565_QCIF_to_QVGA;
974 # else // USE_YUV2RGB_STRETCH
975 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_RGB565_QCIF_to_QVGA_stretch;
976 # endif // < USE_YUV2RGB_STRETCH
977 #endif // < QCIF_TO_QVGA
980 case VP_STAGES_RGB_FORMAT_RGB24:
983 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_RGB24;
984 #else // QCIF_TO_QVGA
985 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_RGB24_QCIF_to_QVGA;
986 #endif // < QCIF_TO_QVGA
989 case VP_STAGES_RGB_FORMAT_ARGB32:
992 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_ARGB32;
993 #else // QCIF_TO_QVGA
994 vp_stages_YUV_to_RGB = vp_stages_YUV420P_to_ARGB32_QCIF_to_QVGA;
995 #endif // < QCIF_TO_QVGA
999 vp_stages_YUV_to_RGB = NULL;
1003 VP_OS_ASSERT(vp_stages_YUV_to_RGB != NULL);
1004 VP_OS_ASSERT(bytesPerPixel != 0);
1006 out->numBuffers = 1;
1007 out->indexBuffer = 0;
1008 out->size = width * height * bytesPerPixel;
1009 out->buffers = (int8_t **) vp_os_malloc(sizeof(int8_t *)+out->size*sizeof(int8_t));
1010 out->buffers[out->indexBuffer] = (int8_t *)(out->buffers+1);
1011 out->lineSize = (int32_t *) vp_os_malloc(out->numBuffers * sizeof(int32_t *));
1012 out->lineSize[out->indexBuffer] = width*bytesPerPixel;
1013 vp_os_memset(out->buffers[out->indexBuffer], 0, out->size);
1015 out->status = VP_API_STATUS_PROCESSING;
1018 if( out->status == VP_API_STATUS_PROCESSING )
1020 dst = (uint8_t*)out->buffers[out->indexBuffer];
1022 vp_stages_YUV_to_RGB(cfg, picture, dst, width * bytesPerPixel);
1023 out->size = width * height * bytesPerPixel;
1031 if(in->status == VP_API_STATUS_STILL_RUNNING) {
1032 out->status = VP_API_STATUS_PROCESSING;
1035 out->status = in->status;
1038 vp_os_mutex_unlock(&out->lock);
1040 return (VP_SUCCESS);
1044 C_RESULT vp_stages_yuv2rgb_stage_close(vp_stages_yuv2rgb_config_t *cfg)
1046 C_RESULT res = VP_SUCCESS;
1048 #ifdef USE_YUV2RGB_STRETCH
1049 if(VP_FAILED(vp_stages_yuv2rgb_close(cfg))) {
1052 #endif // < USE_YUV2RGB_STRETCH