📄 fbosd.c
字号:
p_sys->i_fd = open( psz_device, O_RDWR ); if( p_sys->i_fd == -1 ) { msg_Err( p_intf, "cannot open %s (%s)", psz_device, strerror(errno) ); free( psz_device ); return VLC_EGENERIC; } free( psz_device ); /* Get framebuffer device information */ if( ioctl( p_sys->i_fd, FBIOGET_VSCREENINFO, &p_sys->var_info ) ) { msg_Err( p_intf, "cannot get fb info (%s)", strerror(errno) ); close( p_sys->i_fd ); return VLC_EGENERIC; } /* Get some info on the framebuffer itself */ if( ioctl( p_sys->i_fd, FBIOGET_FSCREENINFO, &fix_info ) == 0 ) { p_sys->i_width = p_sys->fmt_out.i_width = p_sys->var_info.xres; p_sys->i_height = p_sys->fmt_out.i_height = p_sys->var_info.yres; } /* FIXME: if the image is full-size, it gets cropped on the left * because of the xres / xres_virtual slight difference */ msg_Dbg( p_intf, "%ix%i (virtual %ix%i)", p_sys->var_info.xres, p_sys->var_info.yres, p_sys->var_info.xres_virtual, p_sys->var_info.yres_virtual ); p_sys->fmt_out.i_width = p_sys->i_width; p_sys->fmt_out.i_height = p_sys->i_height; p_sys->p_palette = NULL; p_sys->b_pan = ( fix_info.ypanstep || fix_info.ywrapstep ); switch( p_sys->var_info.bits_per_pixel ) { case 8: p_sys->p_palette = malloc( 8 * 256 * sizeof( uint16_t ) ); if( !p_sys->p_palette ) { close( p_sys->i_fd ); return VLC_ENOMEM; } p_sys->fb_cmap.start = 0; p_sys->fb_cmap.len = 256; p_sys->fb_cmap.red = p_sys->p_palette; p_sys->fb_cmap.green = p_sys->p_palette + 256 * sizeof( uint16_t ); p_sys->fb_cmap.blue = p_sys->p_palette + 2 * 256 * sizeof( uint16_t ); p_sys->fb_cmap.transp = p_sys->p_palette + 3 * 256 * sizeof( uint16_t ); /* Save the colormap */ ioctl( p_sys->i_fd, FBIOGETCMAP, &p_sys->fb_cmap ); p_sys->i_bytes_per_pixel = 1; break; case 15: case 16: p_sys->i_bytes_per_pixel = 2; break; case 24: p_sys->i_bytes_per_pixel = 3; break; case 32: p_sys->i_bytes_per_pixel = 4; break; default: msg_Err( p_intf, "screen depth %d is not supported", p_sys->var_info.bits_per_pixel ); close( p_sys->i_fd ); return VLC_EGENERIC; } p_sys->i_page_size = p_sys->i_width * p_sys->i_height * p_sys->i_bytes_per_pixel; msg_Dbg( p_intf, "framebuffer type=%d, visual=%d, ypanstep=%d, " "ywrap=%d, accel=%d", fix_info.type, fix_info.visual, fix_info.ypanstep, fix_info.ywrapstep, fix_info.accel ); return VLC_SUCCESS;}/***************************************************************************** * CloseDisplay: terminate FB interface thread *****************************************************************************/static void CloseDisplay( intf_thread_t *p_intf ){ intf_sys_t *p_sys = (intf_sys_t *) p_intf; /* Restore palette */ if( p_sys->var_info.bits_per_pixel == 8 ) { ioctl( p_sys->i_fd, FBIOPUTCMAP, &p_sys->fb_cmap ); free( p_sys->p_palette ); p_sys->p_palette = NULL; } /* Close fb */ close( p_sys->i_fd );}static void Render( intf_thread_t *p_intf, struct fbosd_render_t *render ){ intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; if( render->i_state != FBOSD_STATE_RENDER ) return; if( !render->psz_string ) return; if( render->i_type == FBOSD_RENDER_IMAGE ) { picture_t *p_pic; p_pic = LoadImage( p_intf, &p_sys->fmt_out, render->psz_string ); if( p_pic ) { RenderPicture( p_intf, render->i_x, render->i_y, p_pic, p_sys->p_overlay ); picture_Release( p_pic ); } } else if( render->i_type == FBOSD_RENDER_TEXT ) { picture_t *p_text;#if defined(FBOSD_BLENDING) video_format_t fmt_in; memset( &fmt_in, 0, sizeof(video_format_t) ); p_text = RenderText( p_intf, render->psz_string, &render->text_style, &fmt_in ); if( p_text ) { BlendPicture( p_intf, &fmt_in, &p_sys->fmt_out, p_text, p_sys->p_overlay ); msg_Dbg( p_intf, "releasing picture" ); DeAllocatePicture( VLC_OBJECT( p_intf ), p_text, &fmt_in ); }#else p_text = RenderText( p_intf, render->psz_string, &render->text_style, &p_sys->fmt_out ); if( p_text ) { RenderPicture( p_intf, render->i_x, render->i_y, p_text, p_sys->p_overlay ); picture_Release( p_text ); }#endif }}static void RenderClear( intf_thread_t *p_intf, struct fbosd_render_t *render ){ intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; vlc_memcpy( &render->text_style, &default_text_style, sizeof( text_style_t ) ); free( render->psz_string ); render->psz_string = NULL; render->i_x = p_sys->i_x; render->i_y = p_sys->i_y; render->i_pos = p_sys->i_pos; render->i_alpha = p_sys->i_alpha; render->b_absolute = p_sys->b_absolute; render->i_state = FBOSD_STATE_FREE;}static bool isRendererReady( intf_thread_t *p_intf ){ intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; int i; /* Check if there are more items to render */ for( i = 0; i < FBOSD_RENDER_MAX; i++ ) { if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED ) return false; } return true;}/***************************************************************************** * Run: thread ***************************************************************************** * This part of the interface is in a separate thread so that we can call * exec() from within it without annoying the rest of the program. *****************************************************************************/static void Run( intf_thread_t *p_intf ){ intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; while( !intf_ShouldDie( p_intf ) ) { int i; /* Is there somthing to render? */ for( i = 0; i < FBOSD_RENDER_MAX; i++ ) { if( p_sys->render[i].i_state == FBOSD_STATE_RENDER ) { Render( p_intf, &p_sys->render[i] ); RenderClear( p_intf, &p_sys->render[i] ); } } if( p_sys->b_clear ) { SetOverlayTransparency( p_intf, true ); var_SetString( p_intf, "fbosd-image", "" ); var_SetString( p_intf, "fbosd-text", "" ); p_sys->b_clear = false; p_sys->b_need_update = true; } if( p_sys->b_need_update && p_sys->p_overlay && isRendererReady( p_intf ) ) { int ret;#if defined(FBOSD_BLENDING) /* Reverse alpha channel to work around FPGA bug */ InvertAlpha( p_intf, &p_sys->p_overlay, p_sys->fmt_out );#endif 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 write to overlay" ); lseek( p_sys->i_fd, 0, SEEK_SET ); /* clear the picture */ memset( p_sys->p_overlay->p[0].p_pixels, 0xFF, p_sys->i_page_size ); p_sys->b_need_update = false; } if( vlc_CPU() & CPU_CAPABILITY_FPU ) msleep( INTF_IDLE_SLEEP ); else msleep( 500 ); } End( p_intf );}static int OverlayCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ intf_thread_t *p_intf = (intf_thread_t *) p_this; intf_sys_t *p_sys = (intf_sys_t*) p_intf->p_sys; VLC_UNUSED(oldval); VLC_UNUSED(p_data); if( !strncmp( psz_cmd, "fbosd-display", 13 ) ) { p_sys->b_need_update = true; } else if( !strncmp( psz_cmd, "fbosd-clear", 11 ) ) { int i; /* Clear the entire render list */ for( i = 0; i < FBOSD_RENDER_MAX; i++ ) { RenderClear( p_intf, &p_sys->render[i] ); } p_sys->b_clear = true; } else if( !strncmp( psz_cmd, "fbosd-render", 12 ) ) { int i; /* Are we already busy with on slot ? */ for( i = 0; i < FBOSD_RENDER_MAX; i++ ) { if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED ) { p_sys->render[i].i_state = FBOSD_STATE_RENDER; break; } } } else { int i; /* Are we already busy with on slot ? */ for( i = 0; i < FBOSD_RENDER_MAX; i++ ) { if( p_sys->render[i].i_state == FBOSD_STATE_RESERVED ) break; } /* No, then find first FREE slot */ if( p_sys->render[i].i_state != FBOSD_STATE_RESERVED ) { for( i = 0; i < FBOSD_RENDER_MAX; i++ ) { if( p_sys->render[i].i_state == FBOSD_STATE_FREE ) break; } if( p_sys->render[i].i_state != FBOSD_STATE_FREE ) { msg_Warn( p_this, "render space depleated" ); return VLC_SUCCESS; } } /* Found a free slot */ p_sys->render[i].i_state = FBOSD_STATE_RESERVED; if( !strncmp( psz_cmd, "fbosd-image", 11 ) ) { free( p_sys->render[i].psz_string ); p_sys->render[i].psz_string = strdup( newval.psz_string ); p_sys->render[i].i_type = FBOSD_RENDER_IMAGE; } else if( !strncmp( psz_cmd, "fbosd-text", 10 ) ) { free( p_sys->render[i].psz_string ); p_sys->render[i].psz_string = strdup( newval.psz_string ); p_sys->render[i].i_type = FBOSD_RENDER_TEXT; } else if( !strncmp( psz_cmd, "fbosd-x", 7 ) ) { p_sys->render[i].b_absolute = false; p_sys->render[i].i_x = (newval.i_int < p_sys->i_width) ? newval.i_int : p_sys->i_width; } else if( !strncmp( psz_cmd, "fbosd-y", 7 ) ) { p_sys->render[i].b_absolute = false; p_sys->render[i].i_y = (newval.i_int < p_sys->i_height) ? newval.i_int : p_sys->i_height; } else if( !strncmp( psz_cmd, "fbosd-position", 14 ) ) { p_sys->render[i].b_absolute = true; p_sys->render[i].i_pos = newval.i_int; } else if( !strncmp( psz_cmd, "fbosd-font-size", 15 ) ) { p_sys->render[i].text_style.i_font_size = newval.i_int; } else if( !strncmp( psz_cmd, "fbosd-font-color", 16 ) ) { p_sys->render[i].text_style.i_font_color = newval.i_int; } else if( !strncmp( psz_cmd, "fbosd-font-opacity", 18 ) ) { p_sys->render[i].text_style.i_font_alpha = 255 - newval.i_int; } else if( !strncmp( psz_cmd, "fbosd-alpha", 11 ) ) { p_sys->render[i].i_alpha = newval.i_int; } } return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -