📄 transcode.c
字号:
/* Close encoder */ if( id->p_encoder->p_module ) module_Unneed( id->p_encoder, id->p_encoder->p_module ); /* Close filters */ for( i = 0; i < id->i_filter; i++ ) { vlc_object_detach( id->pp_filter[i] ); if( id->pp_filter[i]->p_module ) module_Unneed( id->pp_filter[i], id->pp_filter[i]->p_module ); /* Clean-up pictures ring buffer */ for( j = 0; j < PICTURE_RING_SIZE; j++ ) { if( id->pp_filter[i]->p_owner->pp_pics[j] ) video_del_buffer( VLC_OBJECT(id->pp_filter[i]), id->pp_filter[i]->p_owner->pp_pics[j] ); } free( id->pp_filter[i]->p_owner ); vlc_object_destroy( id->pp_filter[i] ); }}static int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_t *id, block_t *in, block_t **out ){ sout_stream_sys_t *p_sys = p_stream->p_sys; int i_duplicate = 1, i; picture_t *p_pic; *out = NULL; while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) ) { subpicture_t *p_subpic = 0; if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up ) { mtime_t current_date = mdate(); if( current_date + 50000 > p_pic->date ) { msg_Dbg( p_stream, "late picture skipped ("I64Fd")", current_date + 50000 - p_pic->date ); p_pic->pf_release( p_pic ); continue; } } if( p_sys->b_master_sync ) { mtime_t i_video_drift; mtime_t i_master_drift = p_sys->i_master_drift; mtime_t i_pts; if( !i_master_drift ) { /* No audio track ? */ p_sys->i_master_drift = i_master_drift = p_pic->date; } i_pts = date_Get( &id->interpolated_pts ) + 1; i_video_drift = p_pic->date - i_pts; i_duplicate = 1; /* Set the pts of the frame being encoded */ p_pic->date = i_pts; if( i_video_drift < i_master_drift - 50000 ) {#if 0 msg_Dbg( p_stream, "dropping frame (%i)", (int)(i_video_drift - i_master_drift) );#endif p_pic->pf_release( p_pic ); continue; } else if( i_video_drift > i_master_drift + 50000 ) {#if 0 msg_Dbg( p_stream, "adding frame (%i)", (int)(i_video_drift - i_master_drift) );#endif i_duplicate = 2; } } if( !id->p_encoder->p_module ) { if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS ) { p_pic->pf_release( p_pic ); transcode_video_close( p_stream, id ); id->b_transcode = VLC_FALSE; return VLC_EGENERIC; } /* Deinterlace */ if( p_stream->p_sys->b_deinterlace ) { id->pp_filter[id->i_filter] = vlc_object_create( p_stream, VLC_OBJECT_FILTER ); vlc_object_attach( id->pp_filter[id->i_filter], p_stream ); id->pp_filter[id->i_filter]->pf_vout_buffer_new = video_new_buffer_filter; id->pp_filter[id->i_filter]->pf_vout_buffer_del = video_del_buffer_filter; id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out; id->pp_filter[id->i_filter]->fmt_out = id->p_decoder->fmt_out; id->pp_filter[id->i_filter]->p_cfg = p_sys->p_deinterlace_cfg; id->pp_filter[id->i_filter]->p_module = module_Need( id->pp_filter[id->i_filter], "video filter2", p_sys->psz_deinterlace, 0 ); if( id->pp_filter[id->i_filter]->p_module ) { id->pp_filter[id->i_filter]->p_owner = malloc( sizeof(filter_owner_sys_t) ); for( i = 0; i < PICTURE_RING_SIZE; i++ ) id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0; id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys; id->i_filter++; } else { msg_Dbg( p_stream, "no video filter found" ); vlc_object_detach( id->pp_filter[id->i_filter] ); vlc_object_destroy( id->pp_filter[id->i_filter] ); } } /* Check if we need a filter for chroma conversion or resizing */ if( id->p_decoder->fmt_out.video.i_chroma != id->p_encoder->fmt_in.video.i_chroma || id->p_decoder->fmt_out.video.i_width != id->p_encoder->fmt_out.video.i_width || id->p_decoder->fmt_out.video.i_height != id->p_encoder->fmt_out.video.i_height || p_sys->i_crop_top > 0 || p_sys->i_crop_bottom > 0 || p_sys->i_crop_left > 0 || p_sys->i_crop_right > 0 ) { id->pp_filter[id->i_filter] = vlc_object_create( p_stream, VLC_OBJECT_FILTER ); vlc_object_attach( id->pp_filter[id->i_filter], p_stream ); id->pp_filter[id->i_filter]->pf_vout_buffer_new = video_new_buffer_filter; id->pp_filter[id->i_filter]->pf_vout_buffer_del = video_del_buffer_filter; id->pp_filter[id->i_filter]->fmt_in = id->p_decoder->fmt_out; id->pp_filter[id->i_filter]->fmt_out = id->p_encoder->fmt_in; id->pp_filter[id->i_filter]->p_cfg = NULL; id->pp_filter[id->i_filter]->p_module = module_Need( id->pp_filter[id->i_filter], "video filter2", 0, 0 ); if( id->pp_filter[id->i_filter]->p_module ) { id->pp_filter[id->i_filter]->p_owner = malloc( sizeof(filter_owner_sys_t) ); for( i = 0; i < PICTURE_RING_SIZE; i++ ) id->pp_filter[id->i_filter]->p_owner->pp_pics[i] = 0; id->pp_filter[id->i_filter]->p_owner->p_sys = p_sys; id->i_filter++; } else { msg_Dbg( p_stream, "no video filter found" ); vlc_object_detach( id->pp_filter[id->i_filter] ); vlc_object_destroy( id->pp_filter[id->i_filter] ); p_pic->pf_release( p_pic ); transcode_video_close( p_stream, id ); id->b_transcode = VLC_FALSE; return VLC_EGENERIC; } } } /* Run filter chain */ for( i = 0; i < id->i_filter; i++ ) { p_pic = id->pp_filter[i]->pf_video_filter(id->pp_filter[i], p_pic); } /* * Encoding */ /* Check if we have a subpicture to overlay */ if( p_sys->p_spu ) { p_subpic = spu_SortSubpictures( p_sys->p_spu, p_pic->date ); /* TODO: get another pic */ } /* Overlay subpicture */ if( p_subpic ) { int i_scale_width, i_scale_height; video_format_t *p_fmt; i_scale_width = id->p_encoder->fmt_in.video.i_width * 1000 / id->p_decoder->fmt_out.video.i_width; i_scale_height = id->p_encoder->fmt_in.video.i_height * 1000 / id->p_decoder->fmt_out.video.i_height; if( p_pic->i_refcount && !id->i_filter ) { /* We can't modify the picture, we need to duplicate it */ picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder ); if( p_tmp ) { vout_CopyPicture( p_stream, p_tmp, p_pic ); p_pic->pf_release( p_pic ); p_pic = p_tmp; } } if( id->i_filter ) p_fmt = &id->pp_filter[id->i_filter -1]->fmt_out.video; else p_fmt = &id->p_decoder->fmt_out.video; /* FIXME (shouldn't have to be done here) */ p_fmt->i_sar_num = p_fmt->i_aspect * p_fmt->i_height / p_fmt->i_width; p_fmt->i_sar_den = VOUT_ASPECT_FACTOR; spu_RenderSubpictures( p_sys->p_spu, p_fmt, p_pic, p_pic, p_subpic, i_scale_width, i_scale_height ); } if( p_sys->i_threads >= 1 ) { vlc_mutex_lock( &p_sys->lock_out ); p_sys->pp_pics[p_sys->i_last_pic++] = p_pic; p_sys->i_last_pic %= PICTURE_RING_SIZE; *out = p_sys->p_buffers; p_sys->p_buffers = NULL; vlc_cond_signal( &p_sys->cond ); vlc_mutex_unlock( &p_sys->lock_out ); } else { block_t *p_block; p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic ); block_ChainAppend( out, p_block ); if( p_sys->b_master_sync ) date_Increment( &id->interpolated_pts, 1 ); if( p_sys->b_master_sync && i_duplicate > 1 ) { mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1; date_Increment( &id->interpolated_pts, 1 ); p_pic->date = i_pts; p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic); block_ChainAppend( out, p_block ); } p_pic->pf_release( p_pic ); } } return VLC_SUCCESS;}static int EncoderThread( sout_stream_sys_t *p_sys ){ sout_stream_id_t *id = p_sys->id_video; picture_t *p_pic; while( !p_sys->b_die && !p_sys->b_error ) { block_t *p_block; vlc_mutex_lock( &p_sys->lock_out ); while( p_sys->i_last_pic == p_sys->i_first_pic ) { vlc_cond_wait( &p_sys->cond, &p_sys->lock_out ); if( p_sys->b_die || p_sys->b_error ) break; } if( p_sys->b_die || p_sys->b_error ) { vlc_mutex_unlock( &p_sys->lock_out ); break; } p_pic = p_sys->pp_pics[p_sys->i_first_pic++]; p_sys->i_first_pic %= PICTURE_RING_SIZE; vlc_mutex_unlock( &p_sys->lock_out ); p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic ); vlc_mutex_lock( &p_sys->lock_out ); block_ChainAppend( &p_sys->p_buffers, p_block ); if( p_sys->b_master_sync ) date_Increment( &id->interpolated_pts, 1 );#if 0 if( p_sys->b_master_sync && i_duplicate > 1 ) { mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1; date_Increment( &id->interpolated_pts, 1 ); p_pic->date = i_pts; p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic); block_ChainAppend( &p_sys->p_buffers, p_block ); }#endif vlc_mutex_unlock( &p_sys->lock_out ); p_pic->pf_release( p_pic ); } while( p_sys->i_last_pic != p_sys->i_first_pic ) { p_pic = p_sys->pp_pics[p_sys->i_first_pic++]; p_sys->i_first_pic %= PICTURE_RING_SIZE; p_pic->pf_release( p_pic ); } block_ChainRelease( p_sys->p_buffers ); return 0;}struct picture_sys_t{ vlc_object_t *p_owner;};static void video_release_buffer( picture_t *p_pic ){ if( p_pic && !p_pic->i_refcount && p_pic->pf_release && p_pic->p_sys ) { video_del_buffer_decoder( (decoder_t *)p_pic->p_sys->p_owner, p_pic ); } else if( p_pic && p_pic->i_refcount > 0 ) p_pic->i_refcount--;}static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring, sout_stream_sys_t *p_sys ){ decoder_t *p_dec = (decoder_t *)p_this; picture_t *p_pic; int i; /* Find an empty space in the picture ring buffer */ for( i = 0; i < PICTURE_RING_SIZE; i++ ) { if( pp_ring[i] != 0 && pp_ring[i]->i_status == DESTROYED_PICTURE ) { pp_ring[i]->i_status = RESERVED_PICTURE; return pp_ring[i]; } } for( i = 0; i < PICTURE_RING_SIZE; i++ ) { if( pp_ring[i] == 0 ) break; } if( i == PICTURE_RING_SIZE && p_sys->i_threads >= 1 ) { int i_first_pic = p_sys->i_first_pic; if( p_sys->i_first_pic != p_sys->i_last_pic ) { /* Encoder still has stuff to encod
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -