📄 transcode.c
字号:
if( !id->p_decoder->p_module ) { msg_Err( p_stream, "cannot find audio decoder" ); return VLC_EGENERIC; } id->p_decoder->fmt_out.audio.i_bitspersample = aout_BitsPerSample( id->p_decoder->fmt_out.i_codec ); fmt_last = id->p_decoder->fmt_out; /* Fix AAC SBR changing number of channels and sampling rate */ if( !(id->p_decoder->fmt_in.i_codec == VLC_FOURCC('m','p','4','a') && fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate && fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) ) fmt_last.audio.i_rate = id->p_decoder->fmt_in.audio.i_rate; /* * Open encoder */ /* Initialization of encoder format structures */ es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat, id->p_decoder->fmt_out.i_codec ); id->p_encoder->fmt_in.audio.i_format = id->p_decoder->fmt_out.i_codec; id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate;//id->p_encoder->fmt_out.audio.i_rate; id->p_encoder->fmt_in.audio.i_physical_channels = id->p_encoder->fmt_out.audio.i_physical_channels; id->p_encoder->fmt_in.audio.i_original_channels = id->p_encoder->fmt_out.audio.i_original_channels; id->p_encoder->fmt_in.audio.i_channels = id->p_encoder->fmt_out.audio.i_channels; id->p_encoder->fmt_in.audio.i_bitspersample = aout_BitsPerSample( id->p_encoder->fmt_in.i_codec ); id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg; id->p_encoder->p_module = module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, true ); if( !id->p_encoder->p_module ) { msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)", p_sys->psz_aenc ? p_sys->psz_aenc : "any", (char *)&p_sys->i_acodec ); module_Unneed( id->p_decoder, id->p_decoder->p_module ); id->p_decoder->p_module = NULL; return VLC_EGENERIC; } id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec; id->p_encoder->fmt_in.audio.i_bitspersample = aout_BitsPerSample( id->p_encoder->fmt_in.i_codec ); /* Init filter chain */ id->p_f_chain = filter_chain_New( p_stream, "audio filter2", true, transcode_audio_filter_allocation_init, NULL, NULL ); filter_chain_Reset( id->p_f_chain, &fmt_last, &id->p_encoder->fmt_in ); /* Load conversion filters */ if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels || fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate ) { /* We'll have to go through fl32 first */ fmt_last.i_codec = fmt_last.audio.i_format = VLC_FOURCC('f','l','3','2'); fmt_last.audio.i_bitspersample = aout_BitsPerSample( fmt_last.i_codec ); filter_chain_AppendFilter( id->p_f_chain, NULL, NULL, NULL, &fmt_last ); fmt_last = *filter_chain_GetFmtOut( id->p_f_chain ); } for( i = 0; i < 4; i++ ) { if( (fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels) || (fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate) || (fmt_last.i_codec != id->p_encoder->fmt_in.i_codec) ) { msg_Dbg( p_stream, "Looking for filter " "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)", (char *)&fmt_last.i_codec, (char *)&id->p_encoder->fmt_in.i_codec, fmt_last.audio.i_channels, id->p_encoder->fmt_in.audio.i_channels, fmt_last.audio.i_rate, id->p_encoder->fmt_in.audio.i_rate ); filter_chain_AppendFilter( id->p_f_chain, NULL, NULL, &fmt_last, &id->p_encoder->fmt_in ); fmt_last = *filter_chain_GetFmtOut( id->p_f_chain ); } else break; } /* Final checks to see if conversions were successful */ if( fmt_last.i_codec != id->p_encoder->fmt_in.i_codec ) { msg_Err( p_stream, "no audio filter found " "(%4.4s->%4.4s, channels %d->%d, rate %d->%d)", (char *)&fmt_last.i_codec, (char *)&id->p_encoder->fmt_in.i_codec, fmt_last.audio.i_channels, id->p_encoder->fmt_in.audio.i_channels, fmt_last.audio.i_rate, id->p_encoder->fmt_in.audio.i_rate ); transcode_audio_close( id ); return VLC_EGENERIC; } /* Load user specified audio filters now */ if( p_sys->psz_af2 ) { id->p_uf_chain = filter_chain_New( p_stream, "audio filter2", false, transcode_audio_filter_allocation_init, NULL, NULL ); filter_chain_Reset( id->p_uf_chain, &fmt_last, &id->p_encoder->fmt_in ); filter_chain_AppendFromString( id->p_uf_chain, p_sys->psz_af2 ); fmt_last = *filter_chain_GetFmtOut( id->p_uf_chain ); } if( fmt_last.audio.i_channels != id->p_encoder->fmt_in.audio.i_channels ) {#if 1 module_Unneed( id->p_encoder, id->p_encoder->p_module ); id->p_encoder->p_module = NULL; /* This might work, but only if the encoder is restarted */ id->p_encoder->fmt_in.audio.i_channels = fmt_last.audio.i_channels; id->p_encoder->fmt_out.audio.i_channels = fmt_last.audio.i_channels; id->p_encoder->fmt_in.audio.i_physical_channels = id->p_encoder->fmt_in.audio.i_original_channels = fmt_last.audio.i_physical_channels; id->p_encoder->fmt_out.audio.i_physical_channels = id->p_encoder->fmt_out.audio.i_original_channels = fmt_last.audio.i_physical_channels; msg_Dbg( p_stream, "number of audio channels for mixing changed, " "trying to reopen the encoder for mixing %i to %i channels", fmt_last.audio.i_channels, id->p_encoder->fmt_in.audio.i_channels ); /* reload encoder */ id->p_encoder->p_cfg = p_stream->p_sys->p_audio_cfg; id->p_encoder->p_module = module_Need( id->p_encoder, "encoder", p_sys->psz_aenc, true ); if( !id->p_encoder->p_module ) { msg_Err( p_stream, "cannot find audio encoder (module:%s fourcc:%4.4s)", p_sys->psz_aenc ? p_sys->psz_aenc : "any", (char *)&p_sys->i_acodec ); transcode_audio_close( id ); return VLC_EGENERIC; } id->p_encoder->fmt_in.audio.i_format = id->p_encoder->fmt_in.i_codec; id->p_encoder->fmt_in.audio.i_bitspersample = aout_BitsPerSample( id->p_encoder->fmt_in.i_codec );#else msg_Err( p_stream, "no audio filter found for mixing from" " %i to %i channels", fmt_last.audio.i_channels, id->p_encoder->fmt_in.audio.i_channels ); transcode_audio_close( id ); return VLC_EGENERIC;#endif } if( fmt_last.audio.i_rate != id->p_encoder->fmt_in.audio.i_rate ) { msg_Err( p_stream, "no audio filter found for resampling from" " %iHz to %iHz", fmt_last.audio.i_rate, id->p_encoder->fmt_in.audio.i_rate );#if 0 /* FIXME : this might work, but only if the encoder is restarted */ id->p_encoder->fmt_in.audio.i_rate = fmt_last.audio.i_rate; id->p_encoder->fmt_out.audio.i_rate = fmt_last.audio.i_rate;#else transcode_audio_close( id ); return VLC_EGENERIC;#endif } /* FIXME: Hack for mp3 transcoding support */ if( id->p_encoder->fmt_out.i_codec == VLC_FOURCC( 'm','p','3',' ' ) ) id->p_encoder->fmt_out.i_codec = VLC_FOURCC( 'm','p','g','a' ); return VLC_SUCCESS;}static void transcode_audio_close( sout_stream_id_t *id ){ audio_timer_close( id->p_encoder ); /* Close decoder */ if( id->p_decoder->p_module ) module_Unneed( id->p_decoder, id->p_decoder->p_module ); id->p_decoder->p_module = NULL; /* Close encoder */ if( id->p_encoder->p_module ) module_Unneed( id->p_encoder, id->p_encoder->p_module ); id->p_encoder->p_module = NULL; /* Close filters */ if( id->p_f_chain ) filter_chain_Delete( id->p_f_chain ); if( id->p_uf_chain ) filter_chain_Delete( id->p_uf_chain );}static int transcode_audio_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; aout_buffer_t *p_audio_buf; block_t *p_block, *p_audio_block; *out = NULL; while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder, &in )) ) { sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 ); if( p_sys->b_master_sync ) { mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1; if ( p_audio_buf->start_date - i_dts > MASTER_SYNC_MAX_DRIFT || p_audio_buf->start_date - i_dts < -MASTER_SYNC_MAX_DRIFT ) { msg_Dbg( p_stream, "drift is too high, resetting master sync" ); date_Set( &id->interpolated_pts, p_audio_buf->start_date ); i_dts = p_audio_buf->start_date + 1; } p_sys->i_master_drift = p_audio_buf->start_date - i_dts; date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples ); p_audio_buf->start_date -= p_sys->i_master_drift; p_audio_buf->end_date -= p_sys->i_master_drift; } p_audio_block = p_audio_buf->p_sys; p_audio_block->i_buffer = p_audio_buf->i_nb_bytes; p_audio_block->i_dts = p_audio_block->i_pts = p_audio_buf->start_date; p_audio_block->i_length = p_audio_buf->end_date - p_audio_buf->start_date; p_audio_block->i_samples = p_audio_buf->i_nb_samples; /* Run filter chain */ p_audio_block = filter_chain_AudioFilter( id->p_f_chain, p_audio_block ); if( id->p_uf_chain ) p_audio_block = filter_chain_AudioFilter( id->p_uf_chain, p_audio_block ); assert( p_audio_block ); p_audio_buf->p_buffer = p_audio_block->p_buffer; p_audio_buf->i_nb_bytes = p_audio_block->i_buffer; p_audio_buf->i_nb_samples = p_audio_block->i_samples; p_audio_buf->start_date = p_audio_block->i_dts; p_audio_buf->end_date = p_audio_block->i_dts + p_audio_block->i_length; audio_timer_start( id->p_encoder ); p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf ); audio_timer_stop( id->p_encoder ); block_ChainAppend( out, p_block ); block_Release( p_audio_block ); free( p_audio_buf ); } return VLC_SUCCESS;}static void audio_release_buffer( aout_buffer_t *p_buffer ){ if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys ); free( p_buffer );}static aout_buffer_t *audio_new_buffer( decoder_t *p_dec, int i_samples ){ aout_buffer_t *p_buffer; block_t *p_block; int i_size; if( p_dec->fmt_out.audio.i_bitspersample ) { i_size = i_samples * p_dec->fmt_out.audio.i_bitspersample / 8 * p_dec->fmt_out.audio.i_channels; } else if( p_dec->fmt_out.audio.i_bytes_per_frame && p_dec->fmt_out.audio.i_frame_length ) { i_size = i_samples * p_dec->fmt_out.audio.i_bytes_per_frame / p_dec->fmt_out.audio.i_frame_length; } else { i_size = i_samples * 4 * p_dec->fmt_out.audio.i_channels; } p_buffer = malloc( sizeof(aout_buffer_t) ); if( !p_buffer ) return NULL; p_buffer->b_discontinuity = false; p_buffer->pf_release = audio_release_buffer; p_buffer->p_sys = p_block = block_New( p_dec, i_size ); p_buffer->p_buffer = p_block->p_buffer; p_buffer->i_size = p_buffer->i_nb_bytes = p_block->i_buffer; p_buffer->i_nb_samples = i_samples; p_block->i_samples = i_samples; return p_buffer;}static void audio_del_buffer( decoder_t *p_dec, aout_buffer_t *p_buffer ){ VLC_UNUSED(p_dec); if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys ); free( p_buffer );}/* * video */static int transcode_video_filter_allocation_init( filter_t *p_filter, void *p_data ){ sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_data; int i; p_filter->pf_vout_buffer_new = video_new_buffer_filter; p_filter->pf_vout_buffer_del = video_del_buffer_filter; p_filter->p_owner = malloc( sizeof(filter_owner_sys_t) ); if( !p_filter->p_owner ) return VLC_EGENERIC; for( i = 0; i < PICTURE_RING_SIZE; i++ ) p_filter->p_owner->pp_pics[i] = 0; p_filter->p_owner->p_sys = p_sys; return VLC_SUCCESS;}static void transcode_video_filter_allocation_clear( filter_t *p_filter ){ int j; /* Clean-up pictures ring buffer */ for( j = 0; j < PICTURE_RING_SIZE; j++ ) { if( p_filter->p_owner->pp_pics[j] ) video_del_buffer( VLC_OBJECT(p_filter), p_filter->p_owner->pp_pics[j] ); } free( p_filter->p_owner );}static int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id ){ sout_stream_sys_t *p_sys = p_stream->p_sys; int i; /* Open decoder * Initialization of decoder structures */ id->p_decoder->fmt_out = id->p_decoder->fmt_in; id->p_decoder->fmt_out.i_extra = 0; id->p_decoder->fmt_out.p_extra = 0; id->p_decoder->pf_decode_video = NULL; id->p_decoder->pf_get_cc = NULL; id->p_decoder->pf_get_cc = 0; id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder; id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder; id->p_decoder->pf_picture_link = video_link_picture_decoder; id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder; id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) ); if( !id->p_decoder->p_owner ) return VLC_EGENERIC; for( i = 0; i < PICTURE_RING_SIZE; i++ ) id->p_decoder->p_owner->pp_pics[i] = 0; id->p_decoder->p_owner->p_sys = p_sys;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -