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