📄 fbosd.c
字号:
p_sys->p_blend->fmt_out.video.i_height = p_sys->p_blend->fmt_out.video.i_visible_height = p_fmt_dst->i_height; i_x_offset = __MAX( i_x_offset, 0 ); i_y_offset = __MAX( i_y_offset, 0 ); p_sys->p_blend->pf_video_blend( p_sys->p_blend, p_pic_dst, p_pic_src, p_pic_dst, i_x_offset, i_y_offset, p_sys->i_alpha ); return VLC_SUCCESS; } return VLC_EGENERIC;}static int InvertAlpha( intf_thread_t *p_intf, picture_t **p_pic, video_format_t fmt ){ uint8_t *p_begin = NULL, *p_end = NULL; uint8_t i_skip = 0; if( *p_pic && ((*p_pic)->i_planes != 1) ) { msg_Err( p_intf, "cannot invert alpha channel too many planes %d (only 1 supported)", (*p_pic)->i_planes ); return VLC_EGENERIC; } switch( fmt.i_chroma ) { case VLC_FOURCC('R','V','2','4'): p_begin = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels; p_end = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels + ( fmt.i_height * (*p_pic)->p[Y_PLANE].i_pitch ); i_skip = 3; break; case VLC_FOURCC('R','V','3','2'): p_begin = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels; p_end = (uint8_t *)(*p_pic)->p[Y_PLANE].p_pixels + ( fmt.i_height * (*p_pic)->p[Y_PLANE].i_pitch ); i_skip = 4; break; default: msg_Err( p_intf, "cannot invert alpha channel chroma not supported %4.4s", (char *)&fmt.i_chroma ); return VLC_EGENERIC; } for( ; p_begin < p_end; p_begin += i_skip ) { uint8_t i_opacity = 0; if( *p_begin != 0xFF ) i_opacity = 255 - *p_begin; *p_begin = i_opacity; } /* end of kludge */ return VLC_SUCCESS;}#endif/***************************************************************************** * RenderPicture: Render the picture into the p_dest buffer. * We don't take transparent pixels into account, so we don't have to blend * the two images together. *****************************************************************************/static int RenderPicture( intf_thread_t *p_intf, int i_x_offset, int i_y_offset, picture_t *p_src, picture_t *p_dest ){ int i; VLC_UNUSED( p_intf ); if( !p_dest && !p_src ) return VLC_EGENERIC; for( i = 0; i < p_src->i_planes ; i++ ) { if( p_src->p[i].i_pitch == p_dest->p[i].i_pitch ) { /* There are margins, but with the same width : perfect ! */ vlc_memcpy( p_dest->p[i].p_pixels, p_src->p[i].p_pixels, p_src->p[i].i_pitch * p_src->p[i].i_visible_lines ); } else { /* We need to proceed line by line */ uint8_t *p_in = p_src->p[i].p_pixels; uint8_t *p_out = p_dest->p[i].p_pixels; int i_x = i_x_offset * p_src->p[i].i_pixel_pitch; int i_x_clip, i_y_clip; /* Check boundaries, clip the image if necessary */ i_x_clip = ( i_x + p_src->p[i].i_visible_pitch ) - p_dest->p[i].i_visible_pitch; i_x_clip = ( i_x_clip > 0 ) ? i_x_clip : 0; i_y_clip = ( i_y_offset + p_src->p[i].i_visible_lines ) - p_dest->p[i].i_visible_lines; i_y_clip = ( i_y_clip > 0 ) ? i_y_clip : 0;#if defined(FBOSD_DEBUG) msg_Dbg( p_intf, "i_pitch (%d,%d), (%d,%d)/(%d,%d)", p_dest->p[i].i_visible_pitch, p_src->p[i].i_visible_pitch, i_x_offset, i_y_offset, i_x, i_x_clip );#endif if( ( i_y_offset <= p_dest->p[i].i_visible_lines ) && ( i_x <= p_dest->p[i].i_visible_pitch ) ) { int i_line; p_out += ( i_y_offset * p_dest->p[i].i_pitch ); for( i_line = 0; i_line < ( p_src->p[i].i_visible_lines - i_y_clip ); i_line++ ) { vlc_memcpy( p_out + i_x, p_in, p_src->p[i].i_visible_pitch - i_x_clip ); p_in += p_src->p[i].i_pitch; p_out += p_dest->p[i].i_pitch; } } } } return VLC_SUCCESS;}/***************************************************************************** * RenderText - Render text to the desired picture format *****************************************************************************/static picture_t *RenderText( intf_thread_t *p_intf, const char *psz_string, text_style_t *p_style, video_format_t *p_fmt ){ intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys; subpicture_region_t *p_region; picture_t *p_dest = NULL; if( !psz_string ) return p_dest; if( p_sys->p_text && p_sys->p_text->p_module ) { p_region = (subpicture_region_t *) malloc( sizeof(subpicture_region_t) ); if( !p_region ) return p_dest; memset( p_region, 0, sizeof(subpicture_region_t) ); p_region->psz_text = strdup( psz_string ); if( !p_region->psz_text ) { free( p_region ); return NULL; } p_region->p_style = p_style; p_region->fmt.i_chroma = VLC_FOURCC('T','E','X','T'); p_region->fmt.i_aspect = 0; p_region->fmt.i_width = p_region->fmt.i_visible_width = 0; p_region->fmt.i_height = p_region->fmt.i_visible_height = 0; p_region->fmt.i_x_offset = 0; p_region->fmt.i_y_offset = 0; p_region->i_align = OSD_ALIGN_LEFT | OSD_ALIGN_TOP; if( p_sys->p_text->pf_render_text ) { video_format_t fmt_out; memset( &fmt_out, 0, sizeof(video_format_t) ); p_sys->p_text->pf_render_text( p_sys->p_text, p_region, p_region );#if defined(FBOSD_BLENDING) fmt_out = p_region->fmt; fmt_out.i_bits_per_pixel = 32; vlc_memcpy( p_fmt, &fmt_out, sizeof(video_format_t) ); p_dest = AllocatePicture( VLC_OBJECT(p_intf), &fmt_out ); if( !p_dest ) { if( p_region->picture.pf_release ) p_region->picture.pf_release( &p_region->picture ); free( p_region->psz_text ); free( p_region ); return NULL; } vout_CopyPicture( VLC_OBJECT(p_intf), p_dest, &p_region->picture );#else fmt_out.i_chroma = p_fmt->i_chroma; p_dest = ConvertImage( p_intf, &p_region->picture, &p_region->fmt, &fmt_out );#endif if( p_region->picture.pf_release ) p_region->picture.pf_release( &p_region->picture ); free( p_region->psz_text ); free( p_region ); return p_dest; } free( p_region->psz_text ); free( p_region ); } return p_dest;}/***************************************************************************** * LoadImage: Load an image from file into a picture buffer. *****************************************************************************/static picture_t *LoadImage( intf_thread_t *p_intf, video_format_t *p_fmt, char *psz_file ){ picture_t *p_pic = NULL; if( psz_file && p_intf->p_sys->p_image ) { video_format_t fmt_in, fmt_out; memset( &fmt_in, 0, sizeof(fmt_in) ); memset( &fmt_out, 0, sizeof(fmt_out) ); fmt_out.i_chroma = p_fmt->i_chroma; p_pic = image_ReadUrl( p_intf->p_sys->p_image, psz_file, &fmt_in, &fmt_out ); msg_Dbg( p_intf, "image size %dx%d chroma %4.4s", fmt_out.i_width, fmt_out.i_height, (char *)&p_fmt->i_chroma ); } return p_pic;}#if ! defined(FBOSD_BLENDING)/***************************************************************************** * Convertmage: Convert image to another fourcc *****************************************************************************/static picture_t *ConvertImage( intf_thread_t *p_intf, picture_t *p_pic, video_format_t *p_fmt_in, video_format_t *p_fmt_out ){ intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys; picture_t *p_old = NULL; if( p_sys->p_image ) { p_old = image_Convert( p_sys->p_image, p_pic, p_fmt_in, p_fmt_out ); msg_Dbg( p_intf, "converted image size %dx%d chroma %4.4s", p_fmt_out->i_width, p_fmt_out->i_height, (char *)&p_fmt_out->i_chroma ); } return p_old;}#endif/***************************************************************************** * Init: initialize framebuffer video thread output method *****************************************************************************/static int Init( intf_thread_t *p_intf ){ intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys; /* Initialize the output structure: RGB with square pixels, whatever * the input format is, since it's the only format we know */ switch( p_sys->var_info.bits_per_pixel ) { case 8: /* FIXME: set the palette */ p_sys->fmt_out.i_chroma = VLC_FOURCC('R','G','B','2'); break; case 15: p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','5'); break; case 16: p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','1','6'); break; case 24: p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','2','4'); break; case 32: p_sys->fmt_out.i_chroma = VLC_FOURCC('R','V','3','2'); break; default: msg_Err( p_intf, "unknown screen depth %i", p_sys->var_info.bits_per_pixel ); return VLC_EGENERIC; } p_sys->fmt_out.i_bits_per_pixel = p_sys->var_info.bits_per_pixel; p_sys->fmt_out.i_width = p_sys->i_width; p_sys->fmt_out.i_height = p_sys->i_height; /* Assume we have square pixels */ if( p_sys->i_aspect < 0 ) { p_sys->fmt_out.i_aspect = ( p_sys->i_width * VOUT_ASPECT_FACTOR ) / p_sys->i_height; } else p_sys->fmt_out.i_aspect = p_sys->i_aspect; p_sys->fmt_out.i_sar_num = p_sys->fmt_out.i_sar_den = 1; /* Allocate overlay buffer */ p_sys->p_overlay = AllocatePicture( VLC_OBJECT(p_intf), &p_sys->fmt_out ); if( !p_sys->p_overlay ) return VLC_EGENERIC; SetOverlayTransparency( p_intf, true ); /* We know the chroma, allocate a buffer which will be used * to write to the overlay framebuffer */ p_sys->p_overlay->p->i_pixel_pitch = p_sys->i_bytes_per_pixel; p_sys->p_overlay->p->i_lines = p_sys->var_info.yres; p_sys->p_overlay->p->i_visible_lines = p_sys->var_info.yres; if( p_sys->var_info.xres_virtual ) { p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres_virtual * p_sys->i_bytes_per_pixel; } else { p_sys->p_overlay->p->i_pitch = p_sys->var_info.xres * p_sys->i_bytes_per_pixel; } p_sys->p_overlay->p->i_visible_pitch = p_sys->var_info.xres * p_sys->i_bytes_per_pixel; p_sys->p_overlay->i_planes = 1; return VLC_SUCCESS;}/***************************************************************************** * End: terminate framebuffer interface *****************************************************************************/static void End( intf_thread_t *p_intf ){ intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys; /* CleanUp */ SetOverlayTransparency( p_intf, false ); if( p_sys->p_overlay ) { int ret; ret = write( p_sys->i_fd, p_sys->p_overlay->p[0].p_pixels, p_sys->i_page_size ); if( ret < 0 ) msg_Err( p_intf, "unable to clear overlay" ); } DeAllocatePicture( VLC_OBJECT(p_intf), p_intf->p_sys->p_overlay, &p_intf->p_sys->fmt_out ); p_intf->p_sys->p_overlay = NULL;}/***************************************************************************** * OpenDisplay: initialize framebuffer *****************************************************************************/static int OpenDisplay( intf_thread_t *p_intf ){ intf_sys_t *p_sys = (intf_sys_t *) p_intf->p_sys; char *psz_device; /* framebuffer device path */ struct fb_fix_screeninfo fix_info; /* framebuffer fix information */ /* Open framebuffer device */ if( !(psz_device = config_GetPsz( p_intf, "fbosd-dev" )) ) { msg_Err( p_intf, "don't know which fb osd/overlay device to open" ); return VLC_EGENERIC; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -