1 #include "../libzmpeg3.h"
4 /* r = (int)(*y + 1.371 * (*cr - 128)); */
5 /* g = (int)(*y - 0.698 * (*cr - 128) - 0.336 * (*cb - 128)); */
6 /* b = (int)(*y + 1.732 * (*cb - 128)); */
10 int yi = y_table[h] + in_y; int uvi = (yi >> 1) * chrom_width; \
11 uint8_t *y_in = &yy[yi * coded_picture_width] + in_x; \
12 uint8_t *cb_in = &uu[uvi] + in_x1; \
13 uint8_t *cr_in = &vv[uvi] + in_x1
16 int yi = y_table[h] + in_y; int uvi = yi * chrom_width; \
17 uint8_t *y_in = &yy[yi * coded_picture_width] + in_x; \
18 uint8_t *cb_in = &uu[uvi] + in_x1; \
19 uint8_t *cr_in = &vv[uvi] + in_x1
22 uint8_t *y_out = output_rows[h]; int h1 = h >> 1; \
23 uint8_t *u_out = output_rows[h1+offset0]; \
24 uint8_t *v_out = output_rows[h1+offset2]
27 uint8_t *y_out = output_rows[h]; \
28 uint8_t *u_out = output_rows[h+offset0]; \
29 uint8_t *v_out = output_rows[h+offset1]
33 #define Y_601(v) z601[v]
37 #define RGB_HEAD(fmt) \
38 for( int h=0; h<ht; ++h ) { INPUT_##fmt; \
39 uint8_t *rgb = output_rows[h];
44 #define RGB_UNSCALED(out,csp) \
45 for( int w=0, iuv=0; w<wd; w+=2, ++iuv ) { \
46 int cr = cr_in[iuv], cb = cb_in[iuv]; \
47 int y_l = Y_##csp(y_in[w+0]) << 16; { \
48 STORE_##out##_R(y_l + cr2r[cr]); \
49 STORE_##out##_G(y_l + crb2g[(cr<<8)|cb]); \
50 STORE_##out##_B(y_l + cb2b[cb]); \
51 STORE_##out##_A(0); } \
52 if( w+1 >= wd ) break; \
53 y_l = y_in[w+1] << 16; { \
54 STORE_##out##_R(y_l + cr2r[cr]); \
55 STORE_##out##_G(y_l + crb2g[(cr<<8)|cb]); \
56 STORE_##out##_B(y_l + cb2b[cb]); \
57 STORE_##out##_A(0); } \
60 #define RGB_SCALED(out,csp) \
61 for( int w=0; w<wd; ++w ) { \
62 int ix = x_table[w]; int iuv = ix >> 1; \
63 int cr = cr_in[iuv], cb = cb_in[iuv]; \
64 int y_l = Y_##csp(y_in[ix]) << 16; \
65 STORE_##out##_R(y_l + cr2r[cr]); \
66 STORE_##out##_G(y_l + crb2g[(cr<<8)|cb]); \
67 STORE_##out##_B(y_l + cb2b[cb]); \
71 #define STORE_BGR888_R(v) rgb[2] = clip((v) >> 16)
72 #define STORE_BGR888_G(v) rgb[1] = clip((v) >> 16)
73 #define STORE_BGR888_B(v) rgb[0] = clip((v) >> 16)
74 #define STORE_BGR888_A(v) rgb += 3
76 #define STORE_BGRA8888_R(v) rgb[2] = clip((v) >> 16)
77 #define STORE_BGRA8888_G(v) rgb[1] = clip((v) >> 16)
78 #define STORE_BGRA8888_B(v) rgb[0] = clip((v) >> 16)
79 #define STORE_BGRA8888_A(v) rgb[3] = 255; rgb += 4
81 #define STORE_RGB565_R(v) int r = clip((v) >> 16)
82 #define STORE_RGB565_G(v) int g = clip((v) >> 16)
83 #define STORE_RGB565_B(v) int b = clip((v) >> 16)
84 #define STORE_RGB565_A(v) *((uint16_t*)rgb) = \
85 ((r&0xf8)<<8) | ((g&0xfc)<<3) | ((b&0xf8)>>3); \
88 #define STORE_RGB888_R(v) rgb[0] = clip((v) >> 16)
89 #define STORE_RGB888_G(v) rgb[1] = clip((v) >> 16)
90 #define STORE_RGB888_B(v) rgb[2] = clip((v) >> 16)
91 #define STORE_RGB888_A(v) rgb += 3
93 #define STORE_RGBA8888_R(v) rgb[0] = clip((v) >> 16)
94 #define STORE_RGBA8888_G(v) rgb[1] = clip((v) >> 16)
95 #define STORE_RGBA8888_B(v) rgb[2] = clip((v) >> 16)
96 #define STORE_RGBA8888_A(v) rgb[3] = 255; rgb += 4
98 #define STORE_RGBA16161616_R(v) rgb_s[0] = clip((v) >> 8, -32768, 32767)
99 #define STORE_RGBA16161616_G(v) rgb_s[1] = clip((v) >> 8, -32768, 32767)
100 #define STORE_RGBA16161616_B(v) rgb_s[2] = clip((v) >> 8, -32768, 32767)
101 #define STORE_RGBA16161616_A(v) rgb_s[3] = 32767; rgb_s += 4
106 #define YUV_HEAD_420 \
107 for( int h=0; h<ht; ++h ) { INPUT_420; \
108 uint8_t *yuv_out = output_rows[h];
110 #define YUV_HEAD_422 \
111 for( int h=0; h<ht; ++h ) { INPUT_422; \
112 uint8_t *yuv_out = output_rows[h];
117 #define YUV_SCALED_YUV888(csp) \
118 for( int w=0; w<wd; ) { \
119 int ix = x_table[w++]; int iuv = ix >> 1; \
120 STORE_Y(Y_##csp(y_in[ix])); STORE_U(cb_in[iuv]); \
121 STORE_V(cr_in[iuv]); \
124 #define YUV_SCALED_YUVA8888(csp) \
125 for( int w=0; w<wd; ) { \
126 int ix = x_table[w++]; int iuv = ix >> 1; \
127 STORE_Y(Y_##csp(y_in[ix])); STORE_U(cb_in[iuv]); \
128 STORE_V(cr_in[iuv]); STORE_A(255); \
131 #define YUV_SCALED_YUYV(csp) \
132 for( int w=0; w<wd; ) { \
133 int ix = x_table[w++]; int iuv = ix >> 1; \
134 STORE_Y(Y_##csp(y_in[ix])); STORE_U(cb_in[iuv]); \
135 ix = x_table[w++]; iuv = ix >> 1; \
136 STORE_Y(Y_##csp(y_in[ix])); STORE_V(cr_in[iuv]); \
139 #define YUV_SCALED_UYVY(csp) \
140 for( int w=0; w<wd; ) { \
141 int ix = x_table[w++]; int iuv = ix >> 1; \
142 STORE_U(cb_in[iuv]); STORE_Y(Y_##csp(y_in[ix])); \
143 ix = x_table[w++]; iuv = ix >> 1; \
144 STORE_V(cr_in[iuv]); STORE_Y(Y_##csp(y_in[ix])); \
147 #define YUV_UNSCALED_YUV888(csp) \
148 for( int w=0, iuv=0; w<wd; w+=2, ++iuv ) { \
149 STORE_Y(Y_##csp(y_in[w+0])); STORE_U(cb_in[iuv]); STORE_V(cr_in[iuv]); \
150 if( w+1 >= wd ) break; \
151 STORE_Y(Y_##csp(y_in[w+1])); STORE_U(cb_in[iuv]); STORE_V(cr_in[iuv]); \
154 #define YUV_UNSCALED_YUVA8888(csp) \
155 for( int w=0, iuv=0; w<wd; w+=2, ++iuv ) { \
156 STORE_Y(Y_##csp(y_in[w+0])); STORE_U(cb_in[iuv]); \
157 STORE_V(cr_in[iuv]); STORE_A(255); \
158 if( w+1 >= wd ) break; \
159 STORE_Y(Y_##csp(y_in[w+1])); STORE_U(cb_in[iuv]); \
160 STORE_V(cr_in[iuv]); STORE_A(255); \
163 #define YUV_UNSCALED_YUYV(csp) \
164 for( int w=0, iuv=0; w<wd; ++iuv ) { \
165 STORE_Y(Y_##csp(y_in[w++])); STORE_U(cb_in[iuv]); \
166 STORE_Y(Y_##csp(y_in[w++])); STORE_V(cr_in[iuv]); \
169 #define YUV_UNSCALED_UYVY(csp) \
170 for( int w=0, iuv=0; w<wd; ++iuv ) { \
171 STORE_U(cb_in[iuv]); STORE_Y(Y_##csp(y_in[w++])); \
172 STORE_V(cr_in[iuv]); STORE_Y(Y_##csp(y_in[w++])); \
175 #define STORE_Y(v) *yuv_out++ = (v)
176 #define STORE_U(v) *yuv_out++ = (v)
177 #define STORE_V(v) *yuv_out++ = (v)
178 #define STORE_A(v) *yuv_out++ = (v)
183 #define YUV420P_HEAD_420 \
184 for( int h=0; h<ht; ++h ) { INPUT_420; OUTPUT_420;
186 #define YUV422P_HEAD_420 \
187 for( int h=0; h<ht; ++h ) { INPUT_420; OUTPUT_422;
189 #define YUV420P_HEAD_422 \
190 for( int h=0; h<ht; ++h ) { INPUT_422; OUTPUT_420;
192 #define YUV422P_HEAD_422 \
193 for( int h=0; h<ht; ++h ) { INPUT_422; OUTPUT_422;
198 #define YUV_SCALED_YUVP(CSP) \
199 for( int w=0; w<wd; ) { \
200 int ix = x_table[w++]; int iuv = ix >> 1; \
201 STORE_UP(cb_in[iuv]); STORE_YP(Y_##CSP(y_in[ix])); \
202 ix = x_table[w++]; iuv = ix >> 1; \
203 STORE_VP(cr_in[iuv]); STORE_YP(Y_##CSP(y_in[ix])); \
206 #define YUV_UNSCALED_YUVP(CSP) \
207 for( int w=0, iuv=0; w<wd; ++iuv ) { \
208 STORE_UP(cb_in[iuv]); STORE_YP(Y_##CSP(y_in[w++])); \
209 STORE_VP(cr_in[iuv]); STORE_YP(Y_##CSP(y_in[w++])); \
212 #define STORE_YP(v) *y_out++ = (v)
213 #define STORE_UP(v) *u_out++ = (v)
214 #define STORE_VP(v) *v_out++ = (v)
216 /* transfer macros */
217 /* CSP = input colorspace */
218 /* FMT = input format */
219 /* OUT = output colorspace/format */
221 #define SCALED_RGB(CSP,FMT,OUT) case cmdl_##CSP##_##OUT: { \
223 RGB_SCALED(OUT,CSP) \
227 #define UNSCALED_RGB(CSP,FMT,OUT) case cmdl_##CSP##_##OUT: { \
229 RGB_UNSCALED(OUT,CSP) \
233 #define SCALED_YUV(CSP,FMT,OUT) case cmdl_##CSP##_##OUT: { \
235 YUV_SCALED_##OUT(CSP) \
239 #define UNSCALED_YUV(CSP,FMT,OUT) case cmdl_##CSP##_##OUT: { \
241 YUV_UNSCALED_##OUT(CSP) \
246 /* naming equivalances */
248 #define YUV_UNSCALED_YUV420P YUV_UNSCALED_YUVP
249 #define YUV_UNSCALED_YUV422P YUV_UNSCALED_YUVP
250 #define YUV_SCALED_YUV420P YUV_SCALED_YUVP
251 #define YUV_SCALED_YUV422P YUV_SCALED_YUVP
253 #define YUYV_HEAD(fmt) YUV_HEAD_##fmt
254 #define UYVY_HEAD(fmt) YUV_HEAD_##fmt
255 #define YUV888_HEAD(fmt) YUV_HEAD_##fmt
256 #define YUVA8888_HEAD(fmt) YUV_HEAD_##fmt
257 #define YUV420P_HEAD(fmt) YUV420P_HEAD_##fmt
258 #define YUV422P_HEAD(fmt) YUV422P_HEAD_##fmt
260 #define cmdl_YUV_BGR888 cmdl_BGR888
261 #define cmdl_YUV_BGRA8888 cmdl_BGRA8888
262 #define cmdl_YUV_RGB565 cmdl_RGB565
263 #define cmdl_YUV_RGB888 cmdl_RGB888
264 #define cmdl_YUV_RGBA8888 cmdl_RGBA8888
266 #define cmdl_YUV_YUV888 cmdl_YUV888
267 #define cmdl_YUV_YUVA8888 cmdl_YUVA8888
268 #define cmdl_YUV_YUV420P cmdl_YUV420P
269 #define cmdl_YUV_YUV422P cmdl_YUV422P
270 #define cmdl_YUV_YUYV cmdl_YUYV
271 #define cmdl_YUV_UYVY cmdl_UYVY
274 dither_frame(uint8_t *yy, uint8_t *uu, uint8_t *vv, uint8_t **output_rows)
277 int *crb2g = crb_to_g;
279 int wd = out_w, ht = out_h;
280 int offset0 = ht, in_x1 = in_x >> 1;
281 int offset1 = offset0 + ht;
282 int offset2 = offset0 + ht/2;
283 if( chroma_format == cfmt_420 ) {
284 if( out_w != horizontal_size ) {
285 switch( color_model ) {
286 SCALED_RGB(YUV,420,BGR888);
287 SCALED_RGB(YUV,420,BGRA8888);
288 SCALED_RGB(YUV,420,RGB565);
289 SCALED_RGB(YUV,420,RGB888);
290 SCALED_RGB(YUV,420,RGBA8888);
291 SCALED_RGB(601,420,BGR888);
292 SCALED_RGB(601,420,BGRA8888);
293 SCALED_RGB(601,420,RGB565);
294 SCALED_RGB(601,420,RGB888);
295 SCALED_RGB(601,420,RGBA8888);
297 SCALED_YUV(YUV,420,YUV420P);
298 SCALED_YUV(YUV,420,YUV422P);
299 SCALED_YUV(YUV,420,YUYV);
300 SCALED_YUV(YUV,420,UYVY);
301 SCALED_YUV(YUV,420,YUV888);
302 SCALED_YUV(YUV,420,YUVA8888);
303 SCALED_YUV(601,420,YUV420P);
304 SCALED_YUV(601,420,YUV422P);
305 SCALED_YUV(601,420,YUYV);
306 SCALED_YUV(601,420,UYVY);
307 SCALED_YUV(601,420,YUV888);
308 SCALED_YUV(601,420,YUVA8888);
310 case cmdl_RGBA16161616: {
312 uint16_t *rgb_s = (uint16_t*)rgb;
313 RGB_SCALED(RGBA16161616,YUV)
320 switch( color_model ) {
321 UNSCALED_RGB(YUV,420,BGR888);
322 UNSCALED_RGB(YUV,420,BGRA8888);
323 UNSCALED_RGB(YUV,420,RGB565);
324 UNSCALED_RGB(YUV,420,RGB888);
325 UNSCALED_RGB(YUV,420,RGBA8888);
326 UNSCALED_RGB(601,420,BGR888);
327 UNSCALED_RGB(601,420,BGRA8888);
328 UNSCALED_RGB(601,420,RGB565);
329 UNSCALED_RGB(601,420,RGB888);
330 UNSCALED_RGB(601,420,RGBA8888);
332 UNSCALED_YUV(YUV,420,YUV420P);
333 UNSCALED_YUV(YUV,420,YUV422P);
334 UNSCALED_YUV(YUV,420,YUYV);
335 UNSCALED_YUV(YUV,420,UYVY);
336 UNSCALED_YUV(YUV,420,YUV888);
337 UNSCALED_YUV(YUV,420,YUVA8888);
338 UNSCALED_YUV(601,420,YUV420P);
339 UNSCALED_YUV(601,420,YUV422P);
340 UNSCALED_YUV(601,420,YUYV);
341 UNSCALED_YUV(601,420,UYVY);
342 UNSCALED_YUV(601,420,YUV888);
343 UNSCALED_YUV(601,420,YUVA8888);
345 case cmdl_RGBA16161616: {
347 uint16_t *rgb_s = (uint16_t*)rgb;
348 RGB_UNSCALED(RGBA16161616,YUV)
356 if( out_w != horizontal_size ) {
357 switch( color_model ) {
358 SCALED_RGB(YUV,422,BGR888);
359 SCALED_RGB(YUV,422,BGRA8888);
360 SCALED_RGB(YUV,422,RGB565);
361 SCALED_RGB(YUV,422,RGB888);
362 SCALED_RGB(YUV,422,RGBA8888);
363 SCALED_RGB(601,422,BGR888);
364 SCALED_RGB(601,422,BGRA8888);
365 SCALED_RGB(601,422,RGB565);
366 SCALED_RGB(601,422,RGB888);
367 SCALED_RGB(601,422,RGBA8888);
369 SCALED_YUV(YUV,422,YUV420P);
370 SCALED_YUV(YUV,422,YUV422P);
371 SCALED_YUV(YUV,422,YUYV);
372 SCALED_YUV(YUV,422,UYVY);
373 SCALED_YUV(YUV,422,YUV888);
374 SCALED_YUV(YUV,422,YUVA8888);
375 SCALED_YUV(601,422,YUV420P);
376 SCALED_YUV(601,422,YUV422P);
377 SCALED_YUV(601,422,YUYV);
378 SCALED_YUV(601,422,UYVY);
379 SCALED_YUV(601,422,YUV888);
380 SCALED_YUV(601,422,YUVA8888);
382 case cmdl_RGBA16161616: {
384 uint16_t *rgb_s = (uint16_t*)rgb;
385 RGB_SCALED(RGBA16161616,YUV)
392 switch( color_model ) {
393 UNSCALED_RGB(YUV,422,BGR888);
394 UNSCALED_RGB(YUV,422,BGRA8888);
395 UNSCALED_RGB(YUV,422,RGB565);
396 UNSCALED_RGB(YUV,422,RGB888);
397 UNSCALED_RGB(YUV,422,RGBA8888);
398 UNSCALED_RGB(601,422,BGR888);
399 UNSCALED_RGB(601,422,BGRA8888);
400 UNSCALED_RGB(601,422,RGB565);
401 UNSCALED_RGB(601,422,RGB888);
402 UNSCALED_RGB(601,422,RGBA8888);
404 UNSCALED_YUV(YUV,422,YUV420P);
405 UNSCALED_YUV(YUV,422,YUV422P);
406 UNSCALED_YUV(YUV,422,YUYV);
407 UNSCALED_YUV(YUV,422,UYVY);
408 UNSCALED_YUV(YUV,422,YUV888);
409 UNSCALED_YUV(YUV,422,YUVA8888);
410 UNSCALED_YUV(601,422,YUV420P);
411 UNSCALED_YUV(601,422,YUV422P);
412 UNSCALED_YUV(601,422,YUYV);
413 UNSCALED_YUV(601,422,UYVY);
414 UNSCALED_YUV(601,422,YUV888);
415 UNSCALED_YUV(601,422,YUVA8888);
417 case cmdl_RGBA16161616: {
419 uint16_t *rgb_s = (uint16_t*)rgb;
420 RGB_UNSCALED(RGBA16161616,YUV)
431 dither_frame444(uint8_t *yy, uint8_t *uu, uint8_t *vv)
437 dithertop(uint8_t *yy, uint8_t *uu, uint8_t *vv)
439 return dither_frame(yy, uu, vv, output_rows);
443 dithertop444(uint8_t *yy, uint8_t *uu, uint8_t *vv)
449 ditherbot(uint8_t *yy, uint8_t *uu, uint8_t *vv)
455 ditherbot444(uint8_t *yy, uint8_t *uu, uint8_t *vv)
464 for( i=0; i<256; ++i ) {
465 value = (int)(1.1644 * i - 255 * 0.0627 + 0.5);
466 z601[i] = clip(value) << 16;
472 present_frame(uint8_t *yy, uint8_t *uu, uint8_t *vv)
478 /* Copy YUV buffers */
481 long offset0, offset1;
482 int chroma_denominator;
484 if( !y_output ) return 0;
486 chroma_denominator = chroma_format == cfmt_420 ? 2 : 1;
490 if( in_x == 0 && in_w >= coded_picture_width &&
491 row_span == coded_picture_width ) {
492 size0 = coded_picture_width * in_h;
493 size1 = chrom_width * (int)((float)in_h / chroma_denominator + 0.5);
494 offset0 = coded_picture_width * in_y;
495 offset1 = chrom_width * (int)((float)in_y / chroma_denominator + 0.5);
501 * offset[1] += chrom_width / 2;
502 * size[1] += chrom_width / 2;
506 memcpy(y_output, yy + offset0, size0);
507 memcpy(u_output, uu + offset1, size1);
508 memcpy(v_output, vv + offset1, size1);
511 /* One block per row */
512 //zmsgs("2 %d %d %d\n", in_w, coded_picture_width, chrom_width);
520 row_span0 = row_span;
521 row_span1 = (row_span >> 1);
524 offset0 = coded_picture_width * in_y;
525 offset1 = chrom_width * in_y / chroma_denominator;
527 for( i=0; i<in_h; ++i ) {
528 memcpy(y_output + i*row_span0, yy + offset0 + in_x, size0);
529 offset0 += coded_picture_width;
530 if( chroma_denominator == 1 || !(i % 2) ) {
531 sofs = offset1 + (in_x>>1);
532 dofs = i/chroma_denominator * row_span1;
533 memcpy(u_output + dofs, uu + sofs, size1);
534 memcpy(v_output + dofs, vv + sofs, size1);
535 if( horizontal_size < in_w ) {
536 dofs = i/chroma_denominator * row_span1 + (horizontal_size>>1);
537 sofs = (in_w>>1) - (horizontal_size>>1);
538 memset(u_output + dofs, 0x80, sofs);
539 memset(v_output + dofs, 0x80, sofs);
544 if( chroma_denominator == 1 || (i%2) )
545 offset1 += chrom_width;
552 /* Want RGB buffer */
553 /* Copy the frame to the output with YUV to RGB conversion */
555 if( chroma_format != cfmt_444 )
556 dither_frame(yy, uu, vv, output_rows);
558 dither_frame444(yy, uu, vv);
561 if( (pict_struct == pics_FRAME_PICTURE && topfirst) ||
562 pict_struct == pics_BOTTOM_FIELD) {
563 /* top field first */
564 if( chroma_format != cfmt_444 ) {
565 dithertop(yy, uu, vv);
566 ditherbot(yy, uu, vv);
569 dithertop444(yy, uu, vv);
570 ditherbot444(yy, uu, vv);
574 /* bottom field first */
575 if( chroma_format != cfmt_444 ) {
576 ditherbot(yy, uu, vv);
577 dithertop(yy, uu, vv);
580 ditherbot444(yy, uu, vv);
581 dithertop444(yy, uu, vv);