📄 transcode.c
字号:
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 */ for( i = 0; i < id->i_filter; i++ ) { p_audio_block = id->pp_filter[i]->pf_audio_filter( id->pp_filter[i], 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; p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf ); 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 ); if( p_buffer ) 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) ); 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 ){ if( p_buffer && p_buffer->p_sys ) block_Release( p_buffer->p_sys ); if( p_buffer ) free( p_buffer );}/* * video */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 = 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) ); 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; /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */ id->p_decoder->p_module = module_Need( id->p_decoder, "decoder", "$codec", 0 ); if( !id->p_decoder->p_module ) { msg_Err( p_stream, "cannot find decoder" ); return VLC_EGENERIC; } /* * Open encoder. * Because some info about the decoded input will only be available * once the first frame is decoded, we actually only test the availability * of the encoder here. */ /* 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.video.i_chroma = id->p_decoder->fmt_out.i_codec; /* The dimensions will be set properly later on. * Just put sensible values so we can test an encoder is available. */ id->p_encoder->fmt_in.video.i_width = id->p_encoder->fmt_out.video.i_width ? id->p_encoder->fmt_out.video.i_width : id->p_decoder->fmt_in.video.i_width ? id->p_decoder->fmt_in.video.i_width : 16; id->p_encoder->fmt_in.video.i_height = id->p_encoder->fmt_out.video.i_height ? id->p_encoder->fmt_out.video.i_height : id->p_decoder->fmt_in.video.i_height ? id->p_decoder->fmt_in.video.i_height : 16; id->p_encoder->fmt_in.video.i_frame_rate = 25; id->p_encoder->fmt_in.video.i_frame_rate_base = 1; id->p_encoder->i_threads = p_sys->i_threads; id->p_encoder->p_cfg = p_sys->p_video_cfg; id->p_encoder->p_module = module_Need( id->p_encoder, "encoder", p_sys->psz_venc, VLC_TRUE ); if( !id->p_encoder->p_module ) { msg_Err( p_stream, "cannot find encoder (%s)", p_sys->psz_venc ); module_Unneed( id->p_decoder, id->p_decoder->p_module ); id->p_decoder->p_module = 0; return VLC_EGENERIC; } /* Close the encoder. * We'll open it only when we have the first frame. */ module_Unneed( id->p_encoder, id->p_encoder->p_module ); if( id->p_encoder->fmt_out.p_extra ) free( id->p_encoder->fmt_out.p_extra ); id->p_encoder->p_module = NULL; if( p_sys->i_threads >= 1 ) { int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT : VLC_THREAD_PRIORITY_VIDEO; p_sys->id_video = id; vlc_mutex_init( p_stream, &p_sys->lock_out ); vlc_cond_init( p_stream, &p_sys->cond ); memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) ); p_sys->i_first_pic = 0; p_sys->i_last_pic = 0; p_sys->p_buffers = NULL; p_sys->b_die = p_sys->b_error = 0; if( vlc_thread_create( p_sys, "encoder", EncoderThread, i_priority, VLC_FALSE ) ) { msg_Err( p_stream, "cannot spawn encoder thread" ); module_Unneed( id->p_decoder, id->p_decoder->p_module ); id->p_decoder->p_module = 0; return VLC_EGENERIC; } } return VLC_SUCCESS;}static int transcode_video_encoder_open( sout_stream_t *p_stream, sout_stream_id_t *id ){ sout_stream_sys_t *p_sys = p_stream->p_sys; /* Calculate scaling, padding, cropping etc. */ /* width/height of source */ int i_src_width = id->p_decoder->fmt_out.video.i_width; int i_src_height = id->p_decoder->fmt_out.video.i_height; /* with/height scaling */ float f_scale_width = 1; float f_scale_height = 1; /* width/height of output stream */ int i_dst_width; int i_dst_height; /* aspect ratio */ float f_aspect = (float)id->p_decoder->fmt_out.video.i_aspect / VOUT_ASPECT_FACTOR; msg_Dbg( p_stream, "decoder aspect is %i:%i", id->p_decoder->fmt_out.video.i_aspect, VOUT_ASPECT_FACTOR ); /* Change f_aspect from source frame to source pixel */ f_aspect = f_aspect * i_src_height / i_src_width; msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect ); /* width/height after cropping */ p_sys->i_src_x_offset = p_sys->i_crop_left & ~1; p_sys->i_src_y_offset = p_sys->i_crop_top & ~1; p_sys->i_crop_width = i_src_width - ( p_sys->i_crop_left & ~1 ) - ( p_sys->i_crop_right & ~1 ); p_sys->i_crop_height = i_src_height - ( p_sys->i_crop_top & ~1 ) - ( p_sys->i_crop_bottom & ~1 ); /* Calculate scaling factor for specified parameters */ if( id->p_encoder->fmt_out.video.i_width <= 0 && id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale ) { /* Global scaling. Make sure width will remain a factor of 16 */ float f_real_scale; int i_new_height; int i_new_width = i_src_width * p_sys->f_scale; if( i_new_width % 16 <= 7 && i_new_width >= 16 ) i_new_width -= i_new_width % 16; else i_new_width += 16 - i_new_width % 16; f_real_scale = (float)( i_new_width ) / (float) i_src_width; i_new_height = __MAX( 16, i_src_height * (float)f_real_scale ); f_scale_width = f_real_scale; f_scale_height = (float) i_new_height / (float) i_src_height; } else if( id->p_encoder->fmt_out.video.i_width > 0 && id->p_encoder->fmt_out.video.i_height <= 0 ) { /* Only width specified */ f_scale_width = (float)id->p_encoder->fmt_out.video.i_width / p_sys->i_crop_width; f_scale_height = f_scale_width; } else if( id->p_encoder->fmt_out.video.i_width <= 0 && id->p_encoder->fmt_out.video.i_height > 0 ) { /* Only height specified */ f_scale_height = (float)id->p_encoder->fmt_out.video.i_height / p_sys->i_crop_height; f_scale_width = f_scale_height; } else if( id->p_encoder->fmt_out.video.i_width > 0 && id->p_encoder->fmt_out.video.i_height > 0 ) { /* Width and height specified */ f_scale_width = (float)id->p_encoder->fmt_out.video.i_width / p_sys->i_crop_width; f_scale_height = (float)id->p_encoder->fmt_out.video.i_height / p_sys->i_crop_height; } /* check maxwidth and maxheight */ /* note: maxwidth and maxheight currently does not handle * canvas and padding, just scaling and cropping. */ if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth / p_sys->i_crop_width ) { f_scale_width = (float)p_sys->i_maxwidth / p_sys->i_crop_width; } if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight / p_sys->i_crop_height ) { f_scale_height = (float)p_sys->i_maxheight / p_sys->i_crop_height; } /* Change aspect ratio from source pixel to scaled pixel */ f_aspect = f_aspect * f_scale_height / f_scale_width; msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect ); /* Correct scaling for target aspect ratio */ /* Shrink video if necessary */ if ( p_sys->i_canvas_aspect > 0 ) { float f_target_aspect = (float)p_sys->i_canvas_aspect / VOUT_ASPECT_FACTOR; if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0) { /* Calculate pixel aspect of canvas */ f_target_aspect = f_target_aspect / p_sys->i_canvas_width * p_sys->i_canvas_height; } if( f_target_aspect > f_aspect ) { /* Reduce width scale to increase aspect */ f_scale_width = f_scale_width * f_aspect / f_target_aspect; } else { /* Reduce height scale to decrease aspect */ f_scale_height = f_scale_height * f_target_aspect / f_aspect; } f_aspect = f_target_aspect; msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect ); } /* f_scale_width and f_scale_height are now final */ /* Calculate width, height from scaling */ /* Make sure its multiple of 2 */ i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 ); i_dst_height = 2 * (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 ); p_sys->i_nopadd_width = i_dst_width; p_sys->i_nopadd_height = i_dst_height; p_sys->i_dst_x_offset = 0; p_sys->i_dst_y_offset = 0; /* Handle canvas and padding */ if( p_sys->i_canvas_width <= 0 ) { /* No canvas width set, add explicit padding border */ i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) + ( p_sys->i_padd_right & ~1 ); p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 ); } else { /* Canvas set, check if we have to padd or crop */ if( p_sys->i_canvas_width < p_sys->i_nopadd_width ) { /* need to crop more, but keep same scaling */ int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) / f_scale_width / 2 + 0.5 ); p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 ) & ~1; p_sys->i_crop_width = i_crop; i_dst_width = p_sys->i_canvas_width & ~1; p_sys->i_nopadd_width = i_dst_width; } else if( p_sys->i_canvas_width > p_sys->i_nopadd_width ) { /* need to padd */ i_dst_width = p_sys->i_canvas_width & ~1; p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2; p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -