#include "../libmpeg3.h" #include "mpeg3video.h" #include #define CLIP(x) ((x) >= 0 ? ((x) < 255 ? (x) : 255) : 0) static unsigned char mpeg3_601_to_rgb[256]; /* Algorithm */ /* r = (int)(*y + 1.371 * (*cr - 128)); */ /* g = (int)(*y - 0.698 * (*cr - 128) - 0.336 * (*cb - 128)); */ /* b = (int)(*y + 1.732 * (*cb - 128)); */ #define DITHER_ROW_HEAD \ for(h = 0; h < video->out_h; h++) \ { \ y_in = &src[0][(video->y_table[h] + video->in_y) * \ video->coded_picture_width] + \ video->in_x; \ if(video->chroma_format == CHROMA420) \ { \ cb_in = &src[1][((video->y_table[h] + video->in_y) >> 1) * \ video->chrom_width] + \ (video->in_x >> 1); \ cr_in = &src[2][((video->y_table[h] + video->in_y) >> 1) * \ video->chrom_width] + \ (video->in_x >> 1); \ } \ else \ { \ cb_in = &src[1][(video->y_table[h] + video->in_y) * \ video->chrom_width] + \ (video->in_x >> 1); \ cr_in = &src[2][(video->y_table[h] + video->in_y) * \ video->chrom_width] + \ (video->in_x >> 1); \ } \ data = output_rows[h]; #define DITHER_ROW_TAIL \ } #define DITHER_SCALE_HEAD \ for(w = 0; w < video->out_w; w++) \ { \ uv_subscript = video->x_table[w] / 2; \ y_l = y_in[video->x_table[w]]; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; #define DITHER_SCALE_601_HEAD \ for(w = 0; w < video->out_w; w++) \ { \ uv_subscript = video->x_table[w] / 2; \ y_l = mpeg3_601_to_rgb[y_in[video->x_table[w]]]; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[cr_in[uv_subscript]]) >> 16; \ g_l = (y_l + video->cr_to_g[cr_in[uv_subscript]] + video->cb_to_g[cb_in[uv_subscript]]) >> 16; \ b_l = (y_l + video->cb_to_b[cb_in[uv_subscript]]) >> 16; #define DITHER_SCALE_TAIL \ } #define DITHER_HEAD \ for(w = 0; w < video->horizontal_size; w++) \ { \ y_l = *y_in++; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; #define DITHER_601_HEAD \ for(w = 0; w < video->horizontal_size; w++) \ { \ y_l = mpeg3_601_to_rgb[*y_in++]; \ y_l <<= 16; \ r_l = (y_l + video->cr_to_r[*cr_in]) >> 16; \ g_l = (y_l + video->cr_to_g[*cr_in] + video->cb_to_g[*cb_in]) >> 16; \ b_l = (y_l + video->cb_to_b[*cb_in]) >> 16; #define DITHER_TAIL \ if(w & 1) \ { \ cr_in++; \ cb_in++; \ } \ } #define STORE_PIXEL_BGR888 \ *data++ = CLIP(b_l); \ *data++ = CLIP(g_l); \ *data++ = CLIP(r_l); #define STORE_PIXEL_BGRA8888 \ *data++ = CLIP(b_l); \ *data++ = CLIP(g_l); \ *data++ = CLIP(r_l); \ *data++ = 0; #define STORE_PIXEL_RGB565 \ *((unsigned short*)data) = \ ((CLIP(r_l) & 0xf8) << 8) | \ ((CLIP(g_l) & 0xfc) << 3) | \ ((CLIP(b_l) & 0xf8) >> 3); \ data += 2; #define STORE_PIXEL_RGB888 \ *data++ = CLIP(r_l); \ *data++ = CLIP(g_l); \ *data++ = CLIP(b_l); #define STORE_PIXEL_RGBA8888 \ *data++ = CLIP(r_l); \ *data++ = CLIP(g_l); \ *data++ = CLIP(b_l); \ *data++ = 0; #define STORE_PIXEL_RGBA16161616 \ *data_s++ = CLIP(r_l); \ *data_s++ = CLIP(g_l); \ *data_s++ = CLIP(b_l); \ *data_s++ = 0; /* Only good for YUV 4:2:0 */ int mpeg3video_ditherframe(mpeg3video_t *video, unsigned char **src, unsigned char **output_rows) { int h = 0; unsigned char *y_in, *cb_in, *cr_in; int y_l, r_l, b_l, g_l; unsigned char *data; int uv_subscript, step, w = -1; DITHER_ROW_HEAD /* Transfer row with scaling */ if(video->out_w != video->horizontal_size) { switch(video->color_model) { case MPEG3_BGR888: DITHER_SCALE_HEAD STORE_PIXEL_BGR888 DITHER_SCALE_TAIL break; case MPEG3_BGRA8888: DITHER_SCALE_HEAD STORE_PIXEL_BGRA8888 DITHER_SCALE_TAIL break; case MPEG3_RGB565: DITHER_SCALE_HEAD STORE_PIXEL_RGB565 DITHER_SCALE_TAIL break; case MPEG3_RGB888: DITHER_SCALE_HEAD STORE_PIXEL_RGB888 DITHER_SCALE_TAIL break; case MPEG3_RGBA8888: DITHER_SCALE_HEAD STORE_PIXEL_RGBA8888 DITHER_SCALE_TAIL break; case MPEG3_601_BGR888: DITHER_SCALE_601_HEAD STORE_PIXEL_BGR888 DITHER_SCALE_TAIL break; case MPEG3_601_BGRA8888: DITHER_SCALE_601_HEAD STORE_PIXEL_BGRA8888 DITHER_SCALE_TAIL break; case MPEG3_601_RGB565: DITHER_SCALE_601_HEAD STORE_PIXEL_RGB565 DITHER_SCALE_TAIL break; case MPEG3_601_RGB888: DITHER_SCALE_601_HEAD STORE_PIXEL_RGB888 DITHER_SCALE_TAIL break; case MPEG3_601_RGBA8888: DITHER_SCALE_601_HEAD STORE_PIXEL_RGBA8888 DITHER_SCALE_TAIL break; case MPEG3_RGBA16161616: { register unsigned short *data_s = (unsigned short*)data; DITHER_SCALE_HEAD STORE_PIXEL_RGBA16161616 DITHER_SCALE_TAIL } break; } } else { /* Transfer row unscaled */ switch(video->color_model) { case MPEG3_BGR888: DITHER_HEAD STORE_PIXEL_BGR888 DITHER_TAIL break; case MPEG3_BGRA8888: DITHER_HEAD STORE_PIXEL_BGRA8888 DITHER_TAIL break; case MPEG3_RGB565: DITHER_HEAD STORE_PIXEL_RGB565 DITHER_TAIL break; case MPEG3_RGB888: DITHER_HEAD STORE_PIXEL_RGB888 DITHER_TAIL break; case MPEG3_RGBA8888: DITHER_HEAD STORE_PIXEL_RGBA8888 DITHER_TAIL break; case MPEG3_601_BGR888: DITHER_601_HEAD STORE_PIXEL_BGR888 DITHER_TAIL break; case MPEG3_601_BGRA8888: DITHER_601_HEAD STORE_PIXEL_BGRA8888 DITHER_TAIL break; case MPEG3_601_RGB565: DITHER_601_HEAD STORE_PIXEL_RGB565 DITHER_TAIL break; case MPEG3_601_RGB888: DITHER_601_HEAD STORE_PIXEL_RGB888 DITHER_TAIL break; case MPEG3_601_RGBA8888: DITHER_601_HEAD STORE_PIXEL_RGBA8888 DITHER_TAIL break; case MPEG3_RGBA16161616: { register unsigned short *data_s = (unsigned short*)data; DITHER_HEAD STORE_PIXEL_RGBA16161616 DITHER_TAIL } break; } } DITHER_ROW_TAIL return 0; } int mpeg3video_ditherframe444(mpeg3video_t *video, unsigned char *src[]) { return 0; } int mpeg3video_dithertop(mpeg3video_t *video, unsigned char *src[]) { return mpeg3video_ditherframe(video, src, video->output_rows); } int mpeg3video_dithertop444(mpeg3video_t *video, unsigned char *src[]) { return 0; } int mpeg3video_ditherbot(mpeg3video_t *video, unsigned char *src[]) { return 0; } int mpeg3video_ditherbot444(mpeg3video_t *video, unsigned char *src[]) { return 0; } void memcpy_fast(unsigned char *output, unsigned char *input, long len) { int i, len2; /* 8 byte alignment */ /* * if(!((long)input & 0x7)) * { * len2 = len >> 4; * for(i = 0; i < len2; ) * { * ((int64_t*)output)[i] = ((int64_t*)input)[i]; * i++; * ((int64_t*)output)[i] = ((int64_t*)input)[i]; * i++; * } * * for(i *= 16; i < len; i++) * { * output[i] = input[i]; * } * } * else */ memcpy(output, input, len); } int mpeg3video_init_output() { int i, value; for(i = 0; i < 256; i++) { value = (int)(1.1644 * i - 255 * 0.0627 + 0.5); if(value < 0) value = 0; else if(value > 255) value = 255; mpeg3_601_to_rgb[i] = value; } return 0; } int mpeg3video_present_frame(mpeg3video_t *video) { int i, j, k, l; unsigned char *src[3]; src[0] = video->output_src[0]; src[1] = video->output_src[1]; src[2] = video->output_src[2]; /* Copy YUV buffers */ if(video->want_yvu) { long size0, size1; long offset0, offset1; int chroma_denominator; if(video->chroma_format == CHROMA420) chroma_denominator = 2; else chroma_denominator = 1; /* Drop a frame */ if(!video->y_output) return 0; /* Copy a frame */ /* Three blocks */ if(video->in_x == 0 && video->in_w >= video->coded_picture_width && video->row_span == video->coded_picture_width) { size0 = video->coded_picture_width * video->in_h; size1 = video->chrom_width * (int)((float)video->in_h / chroma_denominator + 0.5); offset0 = video->coded_picture_width * video->in_y; offset1 = video->chrom_width * (int)((float)video->in_y / chroma_denominator + 0.5); printf("mpeg3video_present_frame 1\n"); /* * if(video->in_y > 0) * { * offset[1] += video->chrom_width / 2; * size[1] += video->chrom_width / 2; * } */ memcpy(video->y_output, src[0] + offset0, size0); memcpy(video->u_output, src[1] + offset1, size1); memcpy(video->v_output, src[2] + offset1, size1); } else /* One block per row */ { //printf("mpeg3video_present_frame 2 %d %d %d\n", video->in_w, video->coded_picture_width, video->chrom_width); int row_span = video->in_w; int row_span0; int row_span1; if(video->row_span) row_span = video->row_span; row_span0 = row_span; row_span1 = (row_span >> 1); size0 = video->in_w; size1 = (video->in_w >> 1); offset0 = video->coded_picture_width * video->in_y; offset1 = video->chrom_width * video->in_y / chroma_denominator; for(i = 0; i < video->in_h; i++) { memcpy(video->y_output + i * row_span0, src[0] + offset0 + video->in_x, size0); offset0 += video->coded_picture_width; if(chroma_denominator == 1 || !(i % 2)) { memcpy(video->u_output + i / chroma_denominator * row_span1, src[1] + offset1 + (video->in_x >> 1), size1); memcpy(video->v_output + i / chroma_denominator * row_span1, src[2] + offset1 + (video->in_x >> 1), size1); if(video->horizontal_size < video->in_w) { memset(video->u_output + i / chroma_denominator * row_span1 + (video->horizontal_size >> 1), 0x80, (video->in_w >> 1) - (video->horizontal_size >> 1)); memset(video->v_output + i / chroma_denominator * row_span1 + (video->horizontal_size >> 1), 0x80, (video->in_w >> 1) - (video->horizontal_size >> 1)); } } if(chroma_denominator == 1 || (i % 2)) offset1 += video->chrom_width; } } return 0; } /* Want RGB buffer */ /* Copy the frame to the output with YUV to RGB conversion */ if(video->prog_seq) { if(video->chroma_format != CHROMA444) { mpeg3video_ditherframe(video, src, video->output_rows); } else mpeg3video_ditherframe444(video, src); } else { if((video->pict_struct == FRAME_PICTURE && video->topfirst) || video->pict_struct == BOTTOM_FIELD) { /* top field first */ if(video->chroma_format != CHROMA444) { mpeg3video_dithertop(video, src); mpeg3video_ditherbot(video, src); } else { mpeg3video_dithertop444(video, src); mpeg3video_ditherbot444(video, src); } } else { /* bottom field first */ if(video->chroma_format != CHROMA444) { mpeg3video_ditherbot(video, src); mpeg3video_dithertop(video, src); } else { mpeg3video_ditherbot444(video, src); mpeg3video_dithertop444(video, src); } } } return 0; } int mpeg3video_display_second_field(mpeg3video_t *video) { /* Not used */ return 0; }