render.c
来自「VLC媒体播放程序」· C语言 代码 · 共 1,920 行 · 第 1/5 页
C
1,920 行
/***************************************************************************** * render.c : Philips OGT and CVD (VCD Subtitle) blending routines. * stuff from here might be pulled out, abstracted or used * by DVD subtitles. ***************************************************************************** * Copyright (C) 2003, 2004 VideoLAN * $Id: render.c,v 1.29 2004/02/02 12:53:20 fenrir Exp $ * * Author: Rocky Bernstein <rocky@panix.com> * based on code from: * Sam Hocevar <sam@zoy.org> * Rudolf Cornelissen <rag.cornelissen@inter.nl.net> * Roine Gustafsson <roine@popstar.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//*#define TESTING_TRANSPARENCY 1*//***************************************************************************** * Preamble *****************************************************************************/#include <vlc/vlc.h>#include <vlc/vout.h>#include <vlc/decoder.h>#include "pixmap.h"#include "subtitle.h"#include "render.h"/* We use 4 bits for an transparency value: 0..15, 15 is completely transparent and 0 completely opaque. Note that although SVCD allow 8-bits, for these routines pixels should previously have been be scaled down to 4 bits (the range used by DVDs).*/#define TRANS_BITS (4)#define MAX_TRANS ((1<<TRANS_BITS) - 1) #define TRANS_SCALEDOWN (8-TRANS_BITS)/* We use a fixed-point arithmetic in scaling ratios so that we can use integer arithmetic and still get fairly precise results. ASCALE is a left shift amount. */#define ASCALE 6 /* 2^6 = 32 *//* Horrible hack to get dbg_print to do the right thing */#define p_dec p_vout/** Take two 8-bit RGB values and a transparency and do a weighted average of them. The "weight" comes from i_trans which is in the range 0..MAX_TRANS. To have greater precision using integer arithmetic, the RGB values are scaled. The uint16_t cast below is to make sure we don't overflow the product in the multiplication (MAX_TRANS - i_trans) is the additive "inverse" of i_trans, i.e. i_trans + (MAX_TRANS - i_trans) = MAX_TRANS. So the resulting sum of rgb1*i_trans + rgb2*(MAX_TRANS-i_trans) will be scaled by MAX_TRANS. To reduce the value back down to 8 bits, we shift by TRANS_BITS, noting that 1 << TRANS_BITS is roughly MAX_TRANS. (Actually it is MAX_TRANS - 1).*/#define avg_8bit_rgb(rgb_vout, rgb_sub, i_trans) \{ \ int i; \ for (i=0; i < RGB_SIZE; i++) { \ rgb_vout[i] = ( (uint16_t) rgb_vout[i]*(MAX_TRANS-i_trans) + \ (uint16_t) rgb_sub [i]*i_trans ) >> TRANS_BITS; \ } \}/***************************************************************************** * Local prototypes *****************************************************************************/static void BlendI420( vout_thread_t *, picture_t *, const subpicture_t *, vlc_bool_t );static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu, vlc_bool_t b_crop );static 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 );static void BlendRV24( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu, vlc_bool_t b_crop );static void BlendRV32( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu, vlc_bool_t b_crop );static void BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu, vlc_bool_t b_crop );/***************************************************************************** * BlendSPU: blend a subtitle into a picture ***************************************************************************** This blends subtitles (a subpicture) into the underlying picture. Subtitle data has been preprocessed as YUV + transparancy or 4 bytes per pixel with interleaving of rows in the subtitle removed. *****************************************************************************/void VCDSubBlend( vout_thread_t *p_vout, picture_t *p_pic, const subpicture_t *p_spu ){ struct subpicture_sys_t *p_sys = p_spu->p_sys; dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), "chroma %x", p_vout->output.i_chroma ); switch( p_vout->output.i_chroma ) { /* I420 target, no scaling */ case VLC_FOURCC('I','4','2','0'): case VLC_FOURCC('I','Y','U','V'): case VLC_FOURCC('Y','V','1','2'): BlendI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop ); break; /* RGB 555 - scaled */ case VLC_FOURCC('R','V','1','5'): BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop, VLC_TRUE ); break; case VLC_FOURCC('R','V','1','6'): BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop, /* Not sure under what conditions RV16 is really RV16 and not RV15. */#if 0 VLC_FALSE );#else VLC_TRUE );#endif break; /* RV24 target, scaling */ case VLC_FOURCC('R','V','2','4'): BlendRV24( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop ); break; /* RV32 target, scaling */ case VLC_FOURCC('R','V','3','2'): BlendRV32( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop ); break; /* NVidia overlay, no scaling */ case VLC_FOURCC('Y','U','Y','2'): BlendYUY2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop ); break; /* Palettized 8 bits per pixel (256 colors). Each pixel is an uint8_t index in the palette Used in ASCII Art. */ case VLC_FOURCC('R','G','B','2'): BlendRGB2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop ); break; default: msg_Err( p_vout, "unknown chroma, can't render SPU" ); break; }}/* Following functions are local *//* YV12 format: All Y samples are found first in memory as an array of bytes (possibly with a larger stride for memory alignment), followed immediately by all Cr (=U) samples (with half the stride of the Y lines, and half the number of lines), then followed immediately by all Cb (=V) samples in a similar fashion.*/static void BlendI420( 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_Y, *p_pixel_base_V, *p_pixel_base_U; ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */ int i_x, i_y; vlc_bool_t even_scanline = VLC_FALSE; /* Crop-specific */ int i_x_start, i_y_start, i_x_end, i_y_end; /* int i=0; */ 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), yuv pitch (%d,%d,%d)", p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y, p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH ); p_pixel_base_Y = p_pic->p[Y_PLANE].p_pixels + p_spu->i_x + p_pic->p[Y_PLANE].i_pitch * p_spu->i_y; p_pixel_base_U = p_pic->p[U_PLANE].p_pixels + p_spu->i_x/2 + p_pic->p[U_PLANE].i_pitch * p_spu->i_y/2; p_pixel_base_V = p_pic->p[V_PLANE].p_pixels + p_spu->i_x/2 + p_pic->p[V_PLANE].i_pitch * p_spu->i_y/2; i_x_start = p_sys->i_x_start; i_y_start = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_start; i_x_end = p_sys->i_x_end; i_y_end = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_end; p_source = (ogt_yuvt_t *)p_sys->p_data; /* 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_y = p_pixel_base_Y + i_y; uint8_t *p_pixel_base_U_y = p_pixel_base_U + i_y/4; uint8_t *p_pixel_base_V_y = p_pixel_base_V + i_y/4; 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; } } even_scanline = !even_scanline; /* Draw until we reach the end of the line */ for( ; i_x < p_spu->i_width; i_x++, p_source++ ) { 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; } }#ifdef TESTING_TRANSPARENCY if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 1;#endif switch( p_source->s.t ) { 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_Y = p_pixel_base_Y_y + i_x; *p_pixel_Y = p_source->plane[Y_PLANE]; if ( even_scanline && i_x % 2 == 0 ) { uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2; uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2; *p_pixel_U = p_source->plane[U_PLANE]; *p_pixel_V = p_source->plane[V_PLANE]; } break; } default: { /* Blend in underlying subtitle pixel. */ /* This is the location that's going to get changed. */ uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x; /* This is the weighted part of the subtitle. 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_Y = (uint16_t) ( p_source->plane[Y_PLANE] * (uint16_t) (p_source->s.t) ); /* This is the weighted part of the underlying pixel. 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_pixel_color_Y = (uint16_t) ( *p_pixel_Y * (uint16_t) (MAX_TRANS - p_source->s.t) ) ; /* 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_Y = ( i_sub_color_Y + i_pixel_color_Y ) >> TRANS_BITS; if ( even_scanline && i_x % 2 == 0 ) { uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2 - p_pic->p[U_PLANE].i_pitch / 2; uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2 - p_pic->p[V_PLANE].i_pitch / 2; uint16_t i_sub_color_U = (uint16_t) ( p_source->plane[U_PLANE] * (uint16_t) (p_source->s.t) ); uint16_t i_sub_color_V = (uint16_t) ( p_source->plane[V_PLANE] * (uint16_t) (p_source->s.t) ); uint16_t i_pixel_color_U = (uint16_t) ( *p_pixel_U * (uint16_t) (MAX_TRANS - p_source->s.t) ) ; uint16_t i_pixel_color_V = (uint16_t) ( *p_pixel_V * (uint16_t) (MAX_TRANS - p_source->s.t) ) ; *p_pixel_U = ( i_sub_color_U + i_pixel_color_U )>>TRANS_BITS; *p_pixel_V = ( i_sub_color_V + i_pixel_color_V )>>TRANS_BITS; } break; } } } }}/* YUY2 Format: Data is found in memory as an array of bytes in which the first byte contains the first sample of Y, the second byte contains the first sample of Cb (=U), the third byte contains the second sample of Y, the fourth byte contains the first sample of Cr (=V); and so on. Each 32-bit word then contains information for two contiguous horizontal pixels, two 8-bit Y values plus a single Cb and Cr which spans the two pixels.*/#define BYTES_PER_PIXEL 4static void BlendYUY2( 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; /* This is the where the subtitle pixels come from */ ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data; ogt_yuvt_t *p_source_end = (ogt_yuvt_t *)p_spu->p_sys->p_data +
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?