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 + -
显示快捷键?