📄 video_output.c
字号:
***************************************************************************** * This function is called when the thread ends after a sucessful * initialization. It frees all resources allocated by InitThread. *****************************************************************************/static void EndThread( vout_thread_t *p_vout ){ int i_index; /* index in heap */#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 if( !p_vout->b_direct ) { module_Unneed( p_vout, p_vout->chroma.p_module ); } /* Destroy all remaining pictures */ for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES + 1; i_index++ ) { if ( p_vout->p_picture[i_index].i_type == MEMORY_PICTURE ) { free( p_vout->p_picture[i_index].p_data_orig ); } } /* Destroy subpicture unit */ spu_Attach( p_vout->p_spu, VLC_OBJECT(p_vout), VLC_FALSE ); spu_Destroy( p_vout->p_spu ); /* Destroy translation tables */ p_vout->pf_end( p_vout ); /* Release the change lock */ vlc_mutex_unlock( &p_vout->change_lock );}/***************************************************************************** * DestroyThread: thread destruction ***************************************************************************** * This function is called when the thread ends. It frees all ressources * allocated by CreateThread. Status is available at this stage. *****************************************************************************/static void DestroyThread( vout_thread_t *p_vout ){ /* Destroy the locks */ vlc_mutex_destroy( &p_vout->picture_lock ); vlc_mutex_destroy( &p_vout->change_lock ); /* Release the module */ if( p_vout && p_vout->p_module ) { module_Unneed( p_vout, p_vout->p_module ); }}/* 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;}/***************************************************************************** * BinaryLog: computes the base 2 log of a binary value ***************************************************************************** * This functions is used by MaskToShift, to get a bit index from a binary * value. *****************************************************************************/static int BinaryLog( uint32_t i ){ int i_log = 0; if( i == 0 ) return -31337; if( i & 0xffff0000 ) i_log += 16; if( i & 0xff00ff00 ) i_log += 8; if( i & 0xf0f0f0f0 ) i_log += 4; if( i & 0xcccccccc ) i_log += 2; if( i & 0xaaaaaaaa ) i_log += 1; return i_log;}/***************************************************************************** * MaskToShift: transform a color mask into right and left shifts ***************************************************************************** * This function is used for obtaining color shifts from masks. *****************************************************************************/static void MaskToShift( int *pi_left, int *pi_right, uint32_t i_mask ){ uint32_t i_low, i_high; /* lower hand higher bits of the mask */ if( !i_mask ) { *pi_left = *pi_right = 0; return; } /* Get bits */ i_low = i_mask & (- (int32_t)i_mask); /* lower bit of the mask */ i_high = i_mask + i_low; /* higher bit of the mask */ /* Transform bits into an index */ i_low = BinaryLog (i_low); i_high = BinaryLog (i_high); /* Update pointers and return */ *pi_left = i_low; *pi_right = (8 - i_high + i_low);}/***************************************************************************** * InitWindowSize: find the initial dimensions the video window should have. ***************************************************************************** * This function will check the "width", "height" and "zoom" config options and * will calculate the size that the video window should have. *****************************************************************************/static void InitWindowSize( vout_thread_t *p_vout, int *pi_width, int *pi_height ){ vlc_value_t val; int i_width, i_height; uint64_t ll_zoom;#define FP_FACTOR 1000 /* our fixed point factor */ var_Get( p_vout, "align", &val ); p_vout->i_alignment = val.i_int; var_Get( p_vout, "width", &val ); i_width = val.i_int; var_Get( p_vout, "height", &val ); i_height = val.i_int; var_Get( p_vout, "zoom", &val ); ll_zoom = (uint64_t)( FP_FACTOR * val.f_float ); if( i_width > 0 && i_height > 0) { *pi_width = (int)( i_width * ll_zoom / FP_FACTOR ); *pi_height = (int)( i_height * ll_zoom / FP_FACTOR ); return; } else if( i_width > 0 ) { *pi_width = (int)( i_width * ll_zoom / FP_FACTOR ); *pi_height = (int)( i_width * ll_zoom * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect / FP_FACTOR ); return; } else if( i_height > 0 ) { *pi_height = (int)( i_height * ll_zoom / FP_FACTOR ); *pi_width = (int)( i_height * ll_zoom * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR / FP_FACTOR ); return; } if( p_vout->render.i_height * p_vout->render.i_aspect >= p_vout->render.i_width * VOUT_ASPECT_FACTOR ) { *pi_width = (int)( p_vout->render.i_height * ll_zoom * p_vout->render.i_aspect / VOUT_ASPECT_FACTOR / FP_FACTOR ); *pi_height = (int)( p_vout->render.i_height * ll_zoom / FP_FACTOR ); } else { *pi_width = (int)( p_vout->render.i_width * ll_zoom / FP_FACTOR ); *pi_height = (int)( p_vout->render.i_width * ll_zoom * VOUT_ASPECT_FACTOR / p_vout->render.i_aspect / FP_FACTOR ); }#undef FP_FACTOR}/***************************************************************************** * vout_VarCallback: generic callback for intf variables *****************************************************************************/int vout_VarCallback( vlc_object_t * p_this, const char * psz_variable, vlc_value_t old_value, vlc_value_t new_value, void * unused ){ vout_thread_t * p_vout = (vout_thread_t *)p_this; vlc_value_t val; val.b_bool = VLC_TRUE; var_Set( p_vout, "intf-change", val ); return VLC_SUCCESS;}/***************************************************************************** * 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( suxor_thread_t *p_this ){ vlc_value_t val; vlc_thread_ready( p_this ); /* Now restart current video stream */ var_Get( p_this->p_input, "video-es", &val ); if( val.i_int >= 0 ) { vlc_value_t val_es; val_es.i_int = -VIDEO_ES; var_Set( p_this->p_input, "video-es", val_es ); var_Set( p_this->p_input, "video-es", val ); } vlc_object_release( p_this->p_input );#ifdef WIN32 CloseHandle( p_this->thread_id );#endif vlc_object_destroy( p_this );}/***************************************************************************** * 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; 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 = VLC_TRUE; var_Set( p_vout, "intf-change", val ); val.psz_string = psz_filter; var_Set( p_vout, "vout-filter", val ); if( psz_filter ) 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; 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 = VLC_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 ) { suxor_thread_t *p_suxor = vlc_object_create( p_vout, sizeof(suxor_thread_t) ); p_suxor->p_input = p_input; p_vout->b_filter_change = VLC_TRUE; vlc_object_yield( p_input ); vlc_thread_create( p_suxor, "suxor", SuxorRestartVideoES, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ); } vlc_object_release( p_input ); return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -