📄 mosaic_bridge.c
字号:
if( p_sys->p_decoder->p_module ) module_Unneed( p_sys->p_decoder, p_sys->p_decoder->p_module ); vlc_object_detach( p_sys->p_decoder ); vlc_object_release( p_sys->p_decoder ); picture_t **pp_ring = p_owner->pp_pics; for( i = 0; i < PICTURE_RING_SIZE; i++ ) { if ( pp_ring[i] != NULL ) { free( pp_ring[i]->p_data_orig ); free( pp_ring[i]->p_sys ); free( pp_ring[i] ); } } free( p_owner ); } /* Destroy user specified video filters */ if( p_sys->p_vf2 ) filter_chain_Delete( p_sys->p_vf2 ); vlc_mutex_lock( p_sys->p_lock ); p_bridge = GetBridge( p_stream ); p_es = p_sys->p_es; p_es->b_empty = true; while ( p_es->p_picture ) { picture_t *p_next = p_es->p_picture->p_next; p_es->p_picture->pf_release( p_es->p_picture ); p_es->p_picture = p_next; } for ( i = 0; i < p_bridge->i_es_num; i++ ) { if ( !p_bridge->pp_es[i]->b_empty ) { b_last_es = false; break; } } if ( b_last_es ) { vlc_object_t *p_libvlc = VLC_OBJECT( p_stream->p_libvlc ); for ( i = 0; i < p_bridge->i_es_num; i++ ) free( p_bridge->pp_es[i] ); free( p_bridge->pp_es ); free( p_bridge ); var_Destroy( p_libvlc, "mosaic-struct" ); } vlc_mutex_unlock( p_sys->p_lock ); if ( p_sys->p_image ) { image_HandlerDelete( p_sys->p_image ); } p_sys->b_inited = false; return VLC_SUCCESS;}/***************************************************************************** * PushPicture : push a picture in the mosaic-struct structure *****************************************************************************/static void PushPicture( sout_stream_t *p_stream, picture_t *p_picture ){ sout_stream_sys_t *p_sys = p_stream->p_sys; bridged_es_t *p_es = p_sys->p_es; vlc_mutex_lock( p_sys->p_lock ); *p_es->pp_last = p_picture; p_picture->p_next = NULL; p_es->pp_last = &p_picture->p_next; vlc_mutex_unlock( p_sys->p_lock );}static int Send( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *p_buffer ){ sout_stream_sys_t *p_sys = p_stream->p_sys; picture_t *p_pic; if ( (sout_stream_sys_t *)id != p_sys ) { block_ChainRelease( p_buffer ); return VLC_SUCCESS; } while ( (p_pic = p_sys->p_decoder->pf_decode_video( p_sys->p_decoder, &p_buffer )) ) { picture_t *p_new_pic; if( p_sys->i_height || p_sys->i_width ) { video_format_t fmt_out, fmt_in; memset( &fmt_in, 0, sizeof(video_format_t) ); memset( &fmt_out, 0, sizeof(video_format_t) ); fmt_in = p_sys->p_decoder->fmt_out.video; if( p_sys->i_chroma ) fmt_out.i_chroma = p_sys->i_chroma; else fmt_out.i_chroma = VLC_FOURCC('I','4','2','0'); if ( !p_sys->i_height ) { fmt_out.i_width = p_sys->i_width; fmt_out.i_height = (p_sys->i_width * VOUT_ASPECT_FACTOR * p_sys->i_sar_num / p_sys->i_sar_den / fmt_in.i_aspect) & ~0x1; } else if ( !p_sys->i_width ) { fmt_out.i_height = p_sys->i_height; fmt_out.i_width = (p_sys->i_height * fmt_in.i_aspect * p_sys->i_sar_den / p_sys->i_sar_num / VOUT_ASPECT_FACTOR) & ~0x1; } else { fmt_out.i_width = p_sys->i_width; fmt_out.i_height = p_sys->i_height; } fmt_out.i_visible_width = fmt_out.i_width; fmt_out.i_visible_height = fmt_out.i_height; p_new_pic = image_Convert( p_sys->p_image, p_pic, &fmt_in, &fmt_out ); if ( p_new_pic == NULL ) { msg_Err( p_stream, "image conversion failed" ); picture_Release( p_pic ); continue; } } else { /* TODO: chroma conversion if needed */ p_new_pic = (picture_t*)malloc( sizeof(picture_t) ); if( p_new_pic == NULL ) { msg_Err( p_stream, "image conversion failed" ); continue; } if( vout_AllocatePicture( p_stream, p_new_pic, p_pic->format.i_chroma, p_pic->format.i_width, p_pic->format.i_height, p_sys->p_decoder->fmt_out.video.i_aspect ) != VLC_SUCCESS ) { picture_Release( p_pic ); free( p_new_pic ); msg_Err( p_stream, "image allocation failed" ); continue; } vout_CopyPicture( p_stream, p_new_pic, p_pic ); } p_new_pic->i_refcount = 1; p_new_pic->i_status = DESTROYED_PICTURE; p_new_pic->i_type = DIRECT_PICTURE; p_new_pic->p_sys = (picture_sys_t *)p_new_pic->pf_release; p_new_pic->pf_release = ReleasePicture; p_new_pic->date = p_pic->date; picture_Release( p_pic ); if( p_sys->p_vf2 ) p_new_pic = filter_chain_VideoFilter( p_sys->p_vf2, p_new_pic ); PushPicture( p_stream, p_new_pic ); } return VLC_SUCCESS;}struct picture_sys_t{ vlc_object_t *p_owner; bool b_dead;};static void video_release_buffer_decoder( picture_t *p_pic ){ assert( p_pic && p_pic->p_sys ); if( --p_pic->i_refcount > 0 ) return; video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic );}static void video_release_buffer_filter( picture_t *p_pic ){ assert( p_pic ); if( --p_pic->i_refcount > 0 ) return; assert( p_pic->p_sys ); video_del_buffer_filter( (filter_t *)p_pic->p_sys->p_owner, p_pic );}inline static picture_t *video_new_buffer_decoder( decoder_t *p_dec ){ return video_new_buffer( VLC_OBJECT( p_dec ), (decoder_owner_sys_t *)p_dec->p_owner, &p_dec->fmt_out, video_release_buffer_decoder );}inline static picture_t *video_new_buffer_filter( filter_t *p_filter ){ return video_new_buffer( VLC_OBJECT( p_filter ), (decoder_owner_sys_t *)p_filter->p_owner, &p_filter->fmt_out, video_release_buffer_filter );}static picture_t *video_new_buffer( vlc_object_t *p_this, decoder_owner_sys_t *p_sys, es_format_t *fmt_out, void ( *pf_release )( picture_t * ) ){ picture_t **pp_ring = p_sys->pp_pics; picture_t *p_pic; int i; if( fmt_out->video.i_width != p_sys->video.i_width || fmt_out->video.i_height != p_sys->video.i_height || fmt_out->video.i_chroma != p_sys->video.i_chroma || fmt_out->video.i_aspect != p_sys->video.i_aspect ) { if( !fmt_out->video.i_sar_num || !fmt_out->video.i_sar_den ) { fmt_out->video.i_sar_num = fmt_out->video.i_aspect * fmt_out->video.i_height; fmt_out->video.i_sar_den = VOUT_ASPECT_FACTOR * fmt_out->video.i_width; } vlc_ureduce( &fmt_out->video.i_sar_num, &fmt_out->video.i_sar_den, fmt_out->video.i_sar_num, fmt_out->video.i_sar_den, 0 ); if( !fmt_out->video.i_visible_width || !fmt_out->video.i_visible_height ) { fmt_out->video.i_visible_width = fmt_out->video.i_width; fmt_out->video.i_visible_height = fmt_out->video.i_height; } fmt_out->video.i_chroma = fmt_out->i_codec; p_sys->video = fmt_out->video; for( i = 0; i < PICTURE_RING_SIZE; i++ ) { if ( pp_ring[i] != NULL ) { if ( pp_ring[i]->i_status == DESTROYED_PICTURE ) { free( pp_ring[i]->p_data_orig ); free( pp_ring[i]->p_sys ); free( pp_ring[i] ); } else { pp_ring[i]->p_sys->b_dead = true; } pp_ring[i] = NULL; } } } /* Find an empty space in the picture ring buffer */ for( i = 0; i < PICTURE_RING_SIZE; i++ ) { if( pp_ring[i] != NULL && pp_ring[i]->i_status == DESTROYED_PICTURE ) { pp_ring[i]->i_status = RESERVED_PICTURE; pp_ring[i]->i_refcount = 1; return pp_ring[i]; } } for( i = 0; i < PICTURE_RING_SIZE; i++ ) { if( pp_ring[i] == NULL ) break; } if( i == PICTURE_RING_SIZE ) { msg_Err( p_this, "decoder/filter is leaking pictures, " "resetting its ring buffer" ); for( i = 0; i < PICTURE_RING_SIZE; i++ ) { pp_ring[i]->p_sys->b_dead = true; pp_ring[i]->pf_release( pp_ring[i] ); pp_ring[i] = NULL; } i = 0; } p_pic = malloc( sizeof(picture_t) ); if( !p_pic ) return NULL; fmt_out->video.i_chroma = fmt_out->i_codec; if( vout_AllocatePicture( p_this, p_pic, fmt_out->video.i_chroma, fmt_out->video.i_width, fmt_out->video.i_height, fmt_out->video.i_aspect ) != VLC_SUCCESS ) { free( p_pic ); return NULL; } if( !p_pic->i_planes ) { free( p_pic ); return NULL; } p_pic->pf_release = pf_release; p_pic->i_refcount = 1; p_pic->p_sys = malloc( sizeof(picture_sys_t) ); p_pic->p_sys->p_owner = p_this; p_pic->p_sys->b_dead = false; p_pic->i_status = RESERVED_PICTURE; pp_ring[i] = p_pic; return p_pic;}inline static void video_del_buffer_decoder( decoder_t *p_this, picture_t *p_pic ){ VLC_UNUSED(p_this); video_del_buffer( p_pic );}inline static void video_del_buffer_filter( filter_t *p_this, picture_t *p_pic ){ VLC_UNUSED(p_this); video_del_buffer( p_pic );}static void video_del_buffer( picture_t *p_pic ){ p_pic->i_refcount = 0; p_pic->i_status = DESTROYED_PICTURE; if ( p_pic->p_sys->b_dead ) { free( p_pic->p_data_orig ); free( p_pic->p_sys ); free( p_pic ); }}static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic ){ VLC_UNUSED(p_dec); p_pic->i_refcount++;}static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic ){ VLC_UNUSED(p_dec); video_release_buffer_decoder( p_pic );}/********************************************************************** * Callback to update (some) params on the fly **********************************************************************/static int HeightCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var); sout_stream_t *p_stream = (sout_stream_t *)p_data; sout_stream_sys_t *p_sys = p_stream->p_sys; /* We create the handler before updating the value in p_sys * so we don't have to worry about locking */ if( !p_sys->p_image && newval.i_int ) p_sys->p_image = image_HandlerCreate( p_stream ); p_sys->i_height = newval.i_int; return VLC_SUCCESS;}static int WidthCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var); sout_stream_t *p_stream = (sout_stream_t *)p_data; sout_stream_sys_t *p_sys = p_stream->p_sys; /* We create the handler before updating the value in p_sys * so we don't have to worry about locking */ if( !p_sys->p_image && newval.i_int ) p_sys->p_image = image_HandlerCreate( p_stream ); p_sys->i_width = newval.i_int; return VLC_SUCCESS;}static int alphaCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var); sout_stream_t *p_stream = (sout_stream_t *)p_data; sout_stream_sys_t *p_sys = p_stream->p_sys; if( p_sys->p_es ) p_sys->p_es->i_alpha = newval.i_int; return VLC_SUCCESS;}static int xCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var); sout_stream_t *p_stream = (sout_stream_t *)p_data; sout_stream_sys_t *p_sys = p_stream->p_sys; if( p_sys->p_es ) p_sys->p_es->i_x = newval.i_int; return VLC_SUCCESS;}static int yCallback( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ VLC_UNUSED(p_this); VLC_UNUSED(oldval); VLC_UNUSED(psz_var); sout_stream_t *p_stream = (sout_stream_t *)p_data; sout_stream_sys_t *p_sys = p_stream->p_sys; if( p_sys->p_es ) p_sys->p_es->i_y = newval.i_int; return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -