render.c
来自「VLC媒体播放程序」· C语言 代码 · 共 1,920 行 · 第 1/5 页
C
1,920 行
(p_spu->i_width * p_spu->i_height); uint16_t i_x, i_y; /* Make sure we start on a word (4-byte) boundary. */ uint16_t i_spu_x = (p_spu->i_x & 0xFFFE) * 2; /* Crop-specific */ int i_x_start, i_y_start, i_x_end, i_y_end; const struct subpicture_sys_t *p_sys = p_spu->p_sys; dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), "spu width x height: (%dx%d), (x,y)=(%d,%d), pitch: %d", p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y, p_pic->p->i_pitch ); p_pixel_base = p_pic->p->p_pixels + + ( p_spu->i_y * p_pic->p->i_pitch ) + i_spu_x; i_x_start = p_sys->i_x_start; i_y_start = p_sys->i_y_start * p_pic->p->i_pitch; i_x_end = p_sys->i_x_end; i_y_end = p_sys->i_y_end * p_pic->p->i_pitch; /* Draw until we reach the bottom of the subtitle */ for( i_y = 0; i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ; i_y += p_pic->p[Y_PLANE].i_pitch ) { uint8_t *p_pixel_base_y = p_pixel_base + i_y; i_x = 0; if ( b_crop ) { if ( i_y > i_y_end ) break; if (i_x_start) { i_x = i_x_start; p_source += (i_x_start*2); } } /* Draw until we reach the end of the line. Each output pixel is a combination of two source pixels. */ for( i_x = 0; i_x < p_spu->i_width / 2; i_x++, p_source +=2 ) { uint16_t i_avg_tr; /* transparancy sort of averaged over 2 pixels*/ if (p_source > p_source_end-1) { msg_Err( p_vout, "Trying to access beyond subtitle x: %d y: %d", i_x, i_y); return; } if( b_crop ) { /* FIXME: y cropping should be dealt with outside of this loop.*/ if ( i_y < i_y_start) continue; if ( i_x > i_x_end ) { p_source += p_spu->i_width - (i_x*2); break; } } /* Favor opaque subtitle pixels. */ if ( (p_source->s.t == 0) && (p_source+1)->s.t == MAX_TRANS ) i_avg_tr = (p_source+1)->s.t; else if ( (p_source->s.t == MAX_TRANS) && (p_source+1)->s.t == 0 ) i_avg_tr = p_source->s.t; else i_avg_tr = ( p_source->s.t + (p_source+1)->s.t ) / 2; #ifdef TESTING_TRANSPARENCY if (i_avg_tr == MAX_TRANS) i_avg_tr >>= 1;#endif switch( i_avg_tr ) { case 0: /* Completely transparent. Don't change pixel. */ break; case MAX_TRANS: { /* Completely opaque. Completely overwrite underlying pixel with subtitle pixel. */ /* This is the location that's going to get changed. */ uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL; uint8_t i_avg_u; uint8_t i_avg_v; /* Favor opaque subtitle pixel. */ if (p_source->s.t == MAX_TRANS ) { i_avg_u = p_source->plane[U_PLANE] ; i_avg_v = p_source->plane[V_PLANE] ; } else if ( (p_source+1)->s.t == MAX_TRANS ) { i_avg_u = (p_source+1)->plane[U_PLANE] ; i_avg_v = (p_source+1)->plane[V_PLANE] ; } else { i_avg_u = ( p_source->plane[U_PLANE] + (p_source+1)->plane[U_PLANE] ) / 2; i_avg_v = ( p_source->plane[V_PLANE] + (p_source+1)->plane[V_PLANE] ) / 2; } /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */ *p_pixel++ = p_source->plane[Y_PLANE] ; *p_pixel++ = i_avg_u; *p_pixel++ = (p_source+1)->plane[Y_PLANE] ; *p_pixel++ = i_avg_v; break; } default: { /* Blend in underlying subtitle pixels. */ /* This is the location that's going to get changed. */ uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL; uint8_t i_avg_u = ( p_source->plane[U_PLANE] + (p_source+1)->plane[U_PLANE] ) / 2; uint8_t i_avg_v = ( p_source->plane[V_PLANE] + (p_source+1)->plane[V_PLANE] ) / 2; /* This is the weighted part of the two subtitle pixels. The color plane is 8 bits and transparancy is 4 bits so when multiplied we get up to 12 bits. */ uint16_t i_sub_color_Y1 = (uint16_t) ( p_source->plane[Y_PLANE] * (uint16_t) (p_source->s.t) ); uint16_t i_sub_color_Y2 = (uint16_t) ( (p_source+1)->plane[Y_PLANE] * (uint16_t) ((p_source+1)->s.t) ); /* This is the weighted part of the underlying pixels. For the same reasons above, the result is up to 12 bits. However since the transparancies are inverses, the sum of i_sub_color and i_pixel_color will not exceed 12 bits. */ uint16_t i_sub_color_U = (uint16_t) ( i_avg_u * (uint16_t) i_avg_tr ); uint16_t i_sub_color_V = (uint16_t) ( i_avg_v * (uint16_t) i_avg_tr ); uint16_t i_pixel_color_Y1 = (uint16_t) ( *(p_pixel) * (uint16_t) (MAX_TRANS - i_avg_tr) ) ; uint16_t i_pixel_color_Y2 = (uint16_t) ( *(p_pixel+2) * (uint16_t) (MAX_TRANS - i_avg_tr) ) ; uint16_t i_pixel_color_U = (uint16_t) ( *(p_pixel+1) * (uint16_t) (MAX_TRANS - i_avg_tr) ) ; uint16_t i_pixel_color_V = (uint16_t) ( *(p_pixel+3) * (uint16_t) (MAX_TRANS - i_avg_tr) ) ; /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */ /* Scale the 12-bit result back down to 8 bits. A precise scaling after adding the two components, would divide by one less than a power of 2. However to simplify and speed things we use a power of 2. This means the boundaries (either all transparent and all opaque) aren't handled properly. But we deal with them in special cases above. */ *p_pixel++ = ( i_sub_color_Y1 + i_pixel_color_Y1 )>>TRANS_BITS; *p_pixel++ = ( i_sub_color_U + i_pixel_color_U ) >>TRANS_BITS; *p_pixel++ = ( i_sub_color_Y2 + i_pixel_color_Y2 )>>TRANS_BITS; *p_pixel++ = ( i_sub_color_V + i_pixel_color_V ) >>TRANS_BITS; break; } } } /* For an odd width source, we'll just have to drop off a pixel. */ if (p_spu->i_width % 2) p_source++; }}/** Convert a YUV pixel into a 16-bit RGB 5-5-5 pixel. A RGB 5-5-5 pixel looks like this: RGB 5-5-5 bit (MSB) 7 6 5 4 3 2 1 0 (LSB) p ? B4 B3 B2 B1 B0 R4 R3 q R2 R1 R0 G4 G3 G2 G1 G0**/static inline voidyuv2rgb555(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 ){ uint8_t rgb[RGB_SIZE]; yuv2rgb(p_yuv, rgb); /* Scale RGB from 8 bits down to 5. */ rgb[RED_PIXEL] >>= (8-5); rgb[GREEN_PIXEL] >>= (8-5); rgb[BLUE_PIXEL] >>= (8-5); *p_rgb1 = ( (rgb[BLUE_PIXEL] << 2)&0x7c ) | ( (rgb[RED_PIXEL]>>3) & 0x03 ); *p_rgb2 = ( (rgb[RED_PIXEL] << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );#if 0 printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), " "rgb1: %02x, rgb2 %02x\n", p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t, rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL], *p_rgb1, *p_rgb2);#endif}/** Convert a YUV pixel into a 16-bit RGB 5-6-5 pixel. A RGB 5-6-5 pixel looks like this: RGB 5-6-5 bit (MSB) 7 6 5 4 3 2 1 0 (LSB) p B4 B3 B2 B1 B0 R5 R4 R3 q R2 R1 R0 G4 G3 G2 G1 G0**/static inline voidyuv2rgb565(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 ){ uint8_t rgb[RGB_SIZE]; yuv2rgb(p_yuv, rgb); /* Scale RGB from 8 bits down to 5 or 6 bits. */ rgb[RED_PIXEL] >>= (8-6); rgb[GREEN_PIXEL] >>= (8-5); rgb[BLUE_PIXEL] >>= (8-5); *p_rgb1 = ( (rgb[BLUE_PIXEL] << 3)&0xF8 ) | ( (rgb[RED_PIXEL]>>3) & 0x07 ); *p_rgb2 = ( (rgb[RED_PIXEL] << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );#if 0 printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), " "rgb1: %02x, rgb2 %02x\n", p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t, rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL], *p_rgb1, *p_rgb2);#endif}static inline voidrv16_pack_blend(uint8_t *p_pixel, ogt_yuvt_t *p_source, uint8_t *p_rgb1, uint8_t *p_rgb2, vlc_bool_t b_15bpp, uint8_t i_trans, int a_scale_down ){ uint8_t rgb_sub[3]; uint8_t rgb_vout[RGB_SIZE]; int i; yuv2rgb(p_source, rgb_sub); /* Scale RGB from 8 bits down to 6 or 5. */ rgb_sub[GREEN_PIXEL] >>= (8-5); rgb_sub[BLUE_PIXEL] >>= (8-5); rgb_vout[GREEN_PIXEL] = *(p_pixel+1) & 0x1f; if (b_15bpp) { rgb_sub[RED_PIXEL] >>= (8-5); rgb_vout[BLUE_PIXEL] = ((*p_pixel)>>2) & 0x1f; rgb_vout[RED_PIXEL] = ((*p_pixel & 0x03) << 3) | ((*(p_pixel+1)&0xe0)>>5); } else { rgb_sub[RED_PIXEL] >>= (8-6); rgb_vout[BLUE_PIXEL] = ((*p_pixel)>>3) & 0x1f; rgb_vout[RED_PIXEL] = ((*p_pixel & 0x07) << 3) | ((*(p_pixel+1)&0xe0)>>5); } #if 0 printf("r,g,b=(%d,%d,%d), sub r,g,b=(%d,%d,%d), trans %d, inv_trans %d\n", rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL], rgb_sub[RED_PIXEL], rgb_sub[GREEN_PIXEL], rgb_sub[BLUE_PIXEL], i_trans, i_inv_trans);#endif#ifdef FIXED_RV16_TRANSPARENCY avg_8bit_rgb(rgb_vout, rgb_sub, i_trans);#else for (i=0; i < RGB_SIZE; i++) { /* For now the Best we can do is fade the color. Picking up video underneath doesn't work. */ /* rgb_vout[i] = ( (uint16_t) rgb_vout[i]*i_inv_trans ) >> TRANS_BITS; */ rgb_vout[i] = ( (uint16_t) rgb_sub[i]*i_trans ) >> TRANS_BITS;#endif } #if 0 printf("avg r,g,b=(%d,%d,%d)\n", rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL] );#endif#if 0 if (b_15bpp) { *p_rgb1 = ( (rgb_vout[BLUE_PIXEL] << 2)&0x7c )|( (rgb_vout[RED_PIXEL]>>3)&0x03 ); } else { *p_rgb1 = ( (rgb_vout[BLUE_PIXEL] << 3)&0xF8 )|( (rgb_vout[RED_PIXEL]>>3)&0x07 ); } *p_rgb2 = ( (rgb_vout[RED_PIXEL] << 5)&0xe0 ) | ( rgb_vout[GREEN_PIXEL]&0x1f );#else *p_rgb1 = (*p_rgb1)+1; *p_rgb2 = (*p_rgb2)+1;#endif }#undef BYTES_PER_PIXEL#define BYTES_PER_PIXEL 2static void BlendRV16( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu, vlc_bool_t b_crop, vlc_bool_t b_15bpp ){ /* Common variables */ uint8_t *p_pixel_base; ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data; ogt_yuvt_t *p_src_end = &p_src_start[p_spu->i_height * p_spu->i_width]; ogt_yuvt_t *p_source; int i_x, i_y; int i_y_src; /* Chroma specific */ uint32_t i_xscale; /* Amount we scale subtitle in the x direction, multiplied by 2**ASCALE. */ uint32_t i_yscale; /* Amount we scale subtitle in the y direction. multiplied by 2**ASCALE. */ int i_width, i_height, i_ytmp, i_ynext; /* Crop-specific */ int i_x_start, i_y_start, i_x_end, i_y_end; struct subpicture_sys_t *p_sys = p_spu->p_sys; i_xscale = ( p_vout->output.i_width << ASCALE ) / p_vout->render.i_width; i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height; dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", p_spu->i_width, p_spu->i_height, p_vout->output.i_width, p_vout->output.i_height, p_vout->render.i_width, p_vout->render.i_height, i_xscale, i_yscale ); i_width = p_spu->i_width * i_xscale; i_height = p_spu->i_height * i_yscale; /* Set where we will start blending subtitle from using the picture coordinates subtitle offsets */ p_pixel_base = p_pic->p->p_pixels + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch; i_x_start = p_sys->i_x_start; i_y_start = i_yscale * p_sys->i_y_start;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?