render.c

来自「VLC媒体播放程序」· C语言 代码 · 共 1,920 行 · 第 1/5 页

C
1,920
字号
                    uint8_t rgb[RGB_SIZE];                    yuv2rgb(p_source, rgb);                     for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )                    {                      /* Completely opaque. Completely overwrite underlying                         pixel with subtitle pixel. */                                            /* This is the location that's going to get changed. */                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;                                            for ( len = i_xlast - i_xdest; len ; len--) {                        put_rgb24_pixel(rgb, p_dest);                      }                    }                    break;		  }#ifdef TRANSPARENCY_FINISHED                default:                   {                                        uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)                                          * BYTES_PER_PIXEL );                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)                                         * BYTES_PER_PIXEL );                    uint32_t len     = i_xlast - i_xdest;                    uint8_t rgb[RGB_SIZE];                    yuv2rgb(p_source, rgb);                    for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )                    {		      /* Blend in underlying pixel subtitle pixel. */		                            /* This is the location that's going to get changed. */                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;		      /* To be able to scale correctly for full opaqueness, we			 add 1 to the alpha.  This means alpha value 0 won't			 be completely transparent and is not correct, but			 that's handled in a special case above anyway. */                      uint8_t i_destalpha = MAX_TRANS - p_source->s.t;                      rv32_pack_blend(p_dest, rgb, dest_alpha,                                      TRANS_SCALEDOWN);                    }                    break;#endif /*TRANSPARENCY_FINISHED*/		}	    }	}    }}/* 4-entry array of colormap indices */static  uint8_t cmap[NUM_SUBTITLE_COLORS];/* Actual RGB values for above; this is used in blending.*/static uint8_t cmap_rgb[NUM_SUBTITLE_COLORS][RGB_SIZE];/*  Return the colormap index for the average of i_pixel and a subtitle  pixel whose subtitle palette entry is i_cmap.  */static inline cmap_tavg_rgb2(const vout_thread_t *p_vout, uint8_t i_pixel, uint8_t i_trans,          int i_cmap, mtime_t i_pts){  uint8_t rgb_vout[RGB_SIZE];  /* Cache the average of a vout colormap entry and a subtitle palette     entry. There are not too many of these 256*4 = 1024.   */  static cmap_t avg_cache[CMAP_RGB2_SIZE][NUM_SUBTITLE_COLORS];  /* subtitle palettes might change between two subtitles. i_last_pts     will be used to figure out if the subtitle has changed, and     we have to invalidate the cache. */  static mtime_t i_last_pts = -1;  if (i_pts != i_last_pts)     {      /* Hack: We rely on the fact that INVALID_CMAP_ENTRY is repeated         0xFF.       */      memset(avg_cache, 0xFF, sizeof(avg_cache));      i_last_pts = i_pts;    }  if ( avg_cache[i_pixel][i_cmap] != INVALID_CMAP_ENTRY )     return avg_cache[i_pixel][i_cmap];  if ( !query_color(p_vout, i_pixel, rgb_vout) ) return INVALID_CMAP_ENTRY;  avg_8bit_rgb(rgb_vout, cmap_rgb[i_cmap], i_trans);#if 0 {  uint8_t rgb_approx[RGB_SIZE];  avg_cache[i_pixel][i_cmap] =     find_cmap_rgb8_nearest(p_vout, rgb_vout, rgb_approx);  printf(         "cmap old %0x avg approx 0%x sub: %d sub=(%0x, %0x, %0x) "         "approx=(%0x, %0x, %0x) avg vout=(%0x, %0x, %0x)\n",          i_pixel, avg_cache[i_pixel][i_cmap], i_cmap,         cmap_rgb[i_cmap][RED_PIXEL], cmap_rgb[i_cmap][GREEN_PIXEL],          cmap_rgb[i_cmap][BLUE_PIXEL],         rgb_approx[RED_PIXEL], rgb_approx[GREEN_PIXEL], rgb_approx[BLUE_PIXEL],         rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL]); }  #else   avg_cache[i_pixel][i_cmap] =     find_cmap_rgb8_nearest(p_vout, rgb_vout, NULL);#endif  return avg_cache[i_pixel][i_cmap];}#undef  BYTES_PER_PIXEL#define BYTES_PER_PIXEL 1static void BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,            const subpicture_t *p_spu, vlc_bool_t b_crop ){    /* Common variables */    uint8_t *p_pixel_base;    uint8_t *p_src_start = (uint8_t *)p_spu->p_sys->p_data;    uint8_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];    uint8_t *p_source; /* This is the where the subtitle pixels come from */    int i;    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;    /* 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;    unsigned int i_aspect_x, i_aspect_y;    vout_AspectRatio( p_vout->render.i_aspect, &i_aspect_y,                       &i_aspect_x );        i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)      / (i_aspect_y * 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;    /** FIXME: do once per subtitle in subtitle processing, not here        each time we render.  */    /* Find a corresponding colormap entries for our palette entries. */    for( i = 0; i < NUM_SUBTITLE_COLORS; i++ )    {      if ( p_sys->p_palette[i].s.t != 0 ) {        uint8_t rgb[RGB_SIZE];         yuv2rgb(&(p_sys->p_palette[i]), rgb);        cmap[i] =           find_cmap_rgb8_nearest(p_vout, rgb, cmap_rgb[i]);        dbg_print( (DECODE_DBG_RENDER),                    "palette %d RGB=(%0x, %0x, %0x)\n", i,                   rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL]);      }    }    /* 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;    i_x_end   = p_sys->i_x_end;    i_y_end   = i_yscale * p_sys->i_y_end;    p_source = (uint8_t *)p_sys->p_data;      /* Draw until we reach the bottom of the subtitle */    i_y = 0;    for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width;          i_y_src += p_spu->i_width )      {	uint8_t *p_pixel_base_y;        i_ytmp = i_y >> ASCALE;        i_y += i_yscale;	p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);	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;          }        }                /* Check whether we need to draw one line or more than one */        if( i_ytmp + 1 >= ( i_y >> ASCALE ) )        {          /* Draw until we reach the end of the line */          for( ; i_x < p_spu->i_width; i_x ++, p_source++ )            {              ogt_yuvt_t p_yuvt;              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;                    break;                  }              }                            if (p_source >= p_src_end) {                msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",                         i_x, i_y / i_yscale, i_height);                return;              }                            p_yuvt = p_sys->p_palette[*p_source & 0x3];#ifdef TESTING_TRANSPARENCY              if (p_yuvt.s.t == MAX_TRANS) p_yuvt.s.t >>= 1;#endif              switch ( p_yuvt.s.t )                 {                case 0:		  /* Completely transparent. Don't change pixel. */#if 0                  printf(" "); /*++++*/#endif                  break;                case MAX_TRANS:                   {                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)                                          * BYTES_PER_PIXEL );                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)                                         * BYTES_PER_PIXEL );                    /* This is the pixel that's going to change;*/                    uint8_t *p_dest = p_pixel_base_y + i_xdest;                    memset( p_dest, cmap[*p_source & 0x3], i_xlast - i_xdest );#if 0                    printf("%1d", *p_source); /*++++*/#endif                    break;                  }                default:                  {                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)                                          * BYTES_PER_PIXEL );                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)                                         * BYTES_PER_PIXEL );                    /* This is the pixel that's going to change;*/                    uint8_t *p_pixel = p_pixel_base_y + i_xdest;                    uint32_t len     = i_xlast - i_xdest;#if FULL_TRANSPARENCY                    /* This is what should be done, but it may be too		       slow.  */                    for ( len = i_xlast - i_xdest -1; len >= 0; len-- )                       {                        cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t,                                                  *p_source, p_sys->i_pts);                                                                          if (i_cmap != INVALID_CMAP_ENTRY)                           *p_pixel= (uint8_t) i_cmap;                        p_pixel++;                      }#else                    cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t,                                              *p_source, p_sys->i_pts);                    if (i_cmap != INVALID_CMAP_ENTRY)                       memset(p_pixel, i_cmap, len);#endif #if 0                    printf("%1d", *p_source); /*++++*/#endif                  }                }            }#if 0          printf("\n"); /*++++*/#endif        } else {          /* Have to scale over many lines. */          int i_yreal = p_pic->p->i_pitch * i_ytmp;          int i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;           /* Draw until we reach the end of the line */           for( ; i_x < p_spu->i_width; i_x ++, p_source++ )             {              ogt_yuvt_t p_yuvt = p_sys->p_palette[*p_source & 0x3];              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;                    break;                  }              }                            if (p_source >= p_src_end) {                msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",                         i_x, i_y / i_yscale, i_height);                return;              }              #ifdef TESTING_TRANSPARENCY              if (p_yuvt.s.t == MAX_TRANS) p_yuvt.s.t >>= 1;#endif              switch ( p_yuvt.s.t )                 {                case 0:		  /* Completely transparent. Don't change pixel. */#if 0                  printf(" "); /*++++*/#endif                  break;                case MAX_TRANS:                   {                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)                                          * BYTES_PER_PIXEL );                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)                                         * BYTES_PER_PIXEL );                    uint32_t len     = i_xlast - i_xdest;#if 0                    printf("%1d", *p_source); /*++++*/#endif                    for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;                         i_ytmp += p_pic->p->i_pitch ) {                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;                      memset( p_dest, cmap[*p_source & 0x3], len );                    }                    break;                  }                default:                  {                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE)                                          * BYTES_PER_PIXEL );                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)                                         * BYTES_PER_PIXEL );                    int32_t len = i_xlast - i_xdest;#if 0                    printf("%1d", *p_source); /*++++*/#endif                    for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;               

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?