📄 video_output.c
字号:
*****************************************************************************/static void EndThread( vout_thread_t *p_vout ){#ifdef STATS { struct tms cpu_usage; times( &cpu_usage ); msg_Dbg( p_vout, "cpu usage (user: %d, system: %d)", cpu_usage.tms_utime, cpu_usage.tms_stime ); }#endif /* FIXME does that function *really* need to be called inside the thread ? */ /* Destroy subpicture unit */ spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), false ); spu_Destroy( p_vout->p_spu ); /* Destroy the video filters2 */ filter_chain_Delete( p_vout->p_vf2_chain );}/* Thread helpers */static picture_t *ChromaGetPicture( filter_t *p_filter ){ picture_t *p_pic = (picture_t *)p_filter->p_owner; p_filter->p_owner = NULL; return p_pic;}static int ChromaCreate( vout_thread_t *p_vout ){ static const char typename[] = "chroma"; filter_t *p_chroma; /* Choose the best module */ p_chroma = p_vout->p_chroma = vlc_custom_create( p_vout, sizeof(filter_t), VLC_OBJECT_GENERIC, typename ); vlc_object_attach( p_chroma, p_vout ); /* TODO: Set the fmt_in and fmt_out stuff here */ p_chroma->fmt_in.video = p_vout->fmt_render; p_chroma->fmt_out.video = p_vout->fmt_out; VideoFormatImportRgb( &p_chroma->fmt_in.video, &p_vout->render ); VideoFormatImportRgb( &p_chroma->fmt_out.video, &p_vout->output ); p_chroma->p_module = module_Need( p_chroma, "video filter2", NULL, 0 ); if( p_chroma->p_module == NULL ) { msg_Err( p_vout, "no chroma module for %4.4s to %4.4s i=%dx%d o=%dx%d", (char*)&p_vout->render.i_chroma, (char*)&p_vout->output.i_chroma, p_chroma->fmt_in.video.i_width, p_chroma->fmt_in.video.i_height, p_chroma->fmt_out.video.i_width, p_chroma->fmt_out.video.i_height ); vlc_object_release( p_vout->p_chroma ); p_vout->p_chroma = NULL; return VLC_EGENERIC; } p_chroma->pf_vout_buffer_new = ChromaGetPicture; return VLC_SUCCESS;}static void ChromaDestroy( vout_thread_t *p_vout ){ assert( !p_vout->b_direct ); if( !p_vout->p_chroma ) return; module_Unneed( p_vout->p_chroma, p_vout->p_chroma->p_module ); vlc_object_release( p_vout->p_chroma ); p_vout->p_chroma = NULL;}static void DropPicture( vout_thread_t *p_vout, picture_t *p_picture ){ vlc_mutex_lock( &p_vout->picture_lock ); if( p_picture->i_refcount ) { /* Pretend we displayed the picture, but don't destroy * it since the decoder might still need it. */ p_picture->i_status = DISPLAYED_PICTURE; } else { /* Destroy the picture without displaying it */ p_picture->i_status = DESTROYED_PICTURE; p_vout->i_heap_size--; } vlc_mutex_unlock( &p_vout->picture_lock );}/* following functions are local */static int ReduceHeight( int i_ratio ){ int i_dummy = VOUT_ASPECT_FACTOR; int i_pgcd = 1; if( !i_ratio ) { return i_pgcd; } /* VOUT_ASPECT_FACTOR is (2^7 * 3^3 * 5^3), we just check for 2, 3 and 5 */ while( !(i_ratio & 1) && !(i_dummy & 1) ) { i_ratio >>= 1; i_dummy >>= 1; i_pgcd <<= 1; } while( !(i_ratio % 3) && !(i_dummy % 3) ) { i_ratio /= 3; i_dummy /= 3; i_pgcd *= 3; } while( !(i_ratio % 5) && !(i_dummy % 5) ) { i_ratio /= 5; i_dummy /= 5; i_pgcd *= 5; } return i_pgcd;}static void AspectRatio( int i_aspect, int *i_aspect_x, int *i_aspect_y ){ unsigned int i_pgcd = ReduceHeight( i_aspect ); *i_aspect_x = i_aspect / i_pgcd; *i_aspect_y = VOUT_ASPECT_FACTOR / i_pgcd;}/** * This function copies all RGB informations from a picture_heap_t into * a video_format_t */static void VideoFormatImportRgb( video_format_t *p_fmt, const picture_heap_t *p_heap ){ p_fmt->i_rmask = p_heap->i_rmask; p_fmt->i_gmask = p_heap->i_gmask; p_fmt->i_bmask = p_heap->i_bmask; p_fmt->i_rrshift = p_heap->i_rrshift; p_fmt->i_lrshift = p_heap->i_lrshift; p_fmt->i_rgshift = p_heap->i_rgshift; p_fmt->i_lgshift = p_heap->i_lgshift; p_fmt->i_rbshift = p_heap->i_rbshift; p_fmt->i_lbshift = p_heap->i_lbshift;}/** * This funtion copes all RGB informations from a video_format_t into * a picture_heap_t */static void VideoFormatExportRgb( const video_format_t *p_fmt, picture_heap_t *p_heap ){ p_heap->i_rmask = p_fmt->i_rmask; p_heap->i_gmask = p_fmt->i_gmask; p_heap->i_bmask = p_fmt->i_bmask; p_heap->i_rrshift = p_fmt->i_rrshift; p_heap->i_lrshift = p_fmt->i_lrshift; p_heap->i_rgshift = p_fmt->i_rgshift; p_heap->i_lgshift = p_fmt->i_lgshift; p_heap->i_rbshift = p_fmt->i_rbshift; p_heap->i_lbshift = p_fmt->i_lbshift;}/** * This function computes rgb shifts from masks */static void PictureHeapFixRgb( picture_heap_t *p_heap ){ video_format_t fmt; /* */ fmt.i_chroma = p_heap->i_chroma; VideoFormatImportRgb( &fmt, p_heap ); /* */ video_format_FixRgb( &fmt ); VideoFormatExportRgb( &fmt, p_heap );}/***************************************************************************** * Helper thread for object variables callbacks. * Only used to avoid deadlocks when using the video embedded mode. *****************************************************************************/typedef struct suxor_thread_t{ VLC_COMMON_MEMBERS input_thread_t *p_input;} suxor_thread_t;static void* SuxorRestartVideoES( vlc_object_t * p_vlc_t ){ suxor_thread_t *p_this = (suxor_thread_t *) p_vlc_t; /* Now restart current video stream */ int val = var_GetInteger( p_this->p_input, "video-es" ); if( val >= 0 ) { var_SetInteger( p_this->p_input, "video-es", -VIDEO_ES ); var_SetInteger( p_this->p_input, "video-es", val ); } vlc_object_release( p_this->p_input ); vlc_object_release( p_this ); return NULL;}/***************************************************************************** * object variables callbacks: a bunch of object variables are used by the * interfaces to interact with the vout. *****************************************************************************/static int DeinterlaceCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; input_thread_t *p_input; vlc_value_t val; char *psz_mode = newval.psz_string; char *psz_filter, *psz_deinterlace = NULL; (void)psz_cmd; (void)oldval; (void)p_data; var_Get( p_vout, "vout-filter", &val ); psz_filter = val.psz_string; if( psz_filter ) psz_deinterlace = strstr( psz_filter, "deinterlace" ); if( !psz_mode || !*psz_mode ) { if( psz_deinterlace ) { char *psz_src = psz_deinterlace + sizeof("deinterlace") - 1; if( psz_src[0] == ':' ) psz_src++; memmove( psz_deinterlace, psz_src, strlen(psz_src) + 1 ); } } else if( !psz_deinterlace ) { psz_filter = realloc( psz_filter, strlen( psz_filter ) + sizeof(":deinterlace") ); if( psz_filter && *psz_filter ) strcat( psz_filter, ":" ); strcat( psz_filter, "deinterlace" ); } p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT ); if( !p_input ) return VLC_EGENERIC; if( psz_mode && *psz_mode ) { /* Modify input as well because the vout might have to be restarted */ val.psz_string = psz_mode; var_Create( p_input, "deinterlace-mode", VLC_VAR_STRING ); var_Set( p_input, "deinterlace-mode", val ); } vlc_object_release( p_input ); val.b_bool = true; var_Set( p_vout, "intf-change", val ); val.psz_string = psz_filter; var_Set( p_vout, "vout-filter", val ); free( psz_filter ); return VLC_SUCCESS;}static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; input_thread_t *p_input; vlc_value_t val; (void)psz_cmd; (void)oldval; (void)p_data; p_input = (input_thread_t *)vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_PARENT ); if (!p_input) { msg_Err( p_vout, "Input not found" ); return( VLC_EGENERIC ); } val.b_bool = true; var_Set( p_vout, "intf-change", val ); /* Modify input as well because the vout might have to be restarted */ val.psz_string = newval.psz_string; var_Create( p_input, "vout-filter", VLC_VAR_STRING ); var_Set( p_input, "vout-filter", val ); /* Now restart current video stream */ var_Get( p_input, "video-es", &val ); if( val.i_int >= 0 ) { static const char typename[] = "kludge"; suxor_thread_t *p_suxor = vlc_custom_create( p_vout, sizeof(suxor_thread_t), VLC_OBJECT_GENERIC, typename ); p_suxor->p_input = p_input; p_vout->b_filter_change = true; vlc_object_yield( p_input ); vlc_thread_create( p_suxor, "suxor", SuxorRestartVideoES, VLC_THREAD_PRIORITY_LOW, false ); } vlc_object_release( p_input ); return VLC_SUCCESS;}/***************************************************************************** * Video Filter2 stuff *****************************************************************************/static int VideoFilter2Callback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; (void)psz_cmd; (void)oldval; (void)p_data; vlc_mutex_lock( &p_vout->vfilter_lock ); p_vout->psz_vf2 = strdup( newval.psz_string ); vlc_mutex_unlock( &p_vout->vfilter_lock ); return VLC_SUCCESS;}static void DisplayTitleOnOSD( vout_thread_t *p_vout ){ input_thread_t *p_input; mtime_t i_now, i_stop; if( !config_GetInt( p_vout, "osd" ) ) return; p_input = (input_thread_t *)vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_ANYWHERE ); if( p_input ) { i_now = mdate(); i_stop = i_now + (mtime_t)(p_vout->i_title_timeout * 1000); char *psz_nowplaying = input_item_GetNowPlaying( input_GetItem( p_input ) ); char *psz_artist = input_item_GetArtist( input_GetItem( p_input ) ); char *psz_name = input_item_GetTitle( input_GetItem( p_input ) ); if( EMPTY_STR( psz_name ) ) { free( psz_name ); psz_name = input_item_GetName( input_GetItem( p_input ) ); } if( !EMPTY_STR( psz_nowplaying ) ) { vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, psz_nowplaying, NULL, p_vout->i_title_position, 30 + p_vout->fmt_in.i_width - p_vout->fmt_in.i_visible_width - p_vout->fmt_in.i_x_offset, 20 + p_vout->fmt_in.i_y_offset, i_now, i_stop ); } else if( !EMPTY_STR( psz_artist ) ) { char *psz_string = NULL; if( asprintf( &psz_string, "%s - %s", psz_name, psz_artist ) != -1 ) { vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, psz_string, NULL, p_vout->i_title_position, 30 + p_vout->fmt_in.i_width - p_vout->fmt_in.i_visible_width - p_vout->fmt_in.i_x_offset, 20 + p_vout->fmt_in.i_y_offset, i_now, i_stop ); free( psz_string ); } } else { vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN, psz_name, NULL, p_vout->i_title_position, 30 + p_vout->fmt_in.i_width - p_vout->fmt_in.i_visible_width - p_vout->fmt_in.i_x_offset, 20 + p_vout->fmt_in.i_y_offset, i_now, i_stop ); } vlc_object_release( p_input ); free( psz_artist ); free( psz_name ); free( psz_nowplaying ); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -