📄 encoder.c
字号:
p_sys->i_luma_elim = val.i_int; var_Get( p_enc, ENC_CFG_PREFIX "chroma-elim-threshold", &val ); p_sys->i_chroma_elim = val.i_int;#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4) var_Get( p_enc, ENC_CFG_PREFIX "aac-profile", &val ); p_sys->i_aac_profile = FF_PROFILE_AAC_LOW; if( val.psz_string && *val.psz_string ) { if( !strncmp( val.psz_string, "main", 4 ) ) p_sys->i_aac_profile = FF_PROFILE_AAC_MAIN; else if( !strncmp( val.psz_string, "low", 3 ) ) p_sys->i_aac_profile = FF_PROFILE_AAC_LOW;#if 0 /* Not supported by FAAC encoder */ else if( !strncmp( val.psz_string, "ssr", 3 ) ) p_sys->i_aac_profile = FF_PROFILE_AAC_SSR;#endif else if( !strncmp( val.psz_string, "ltp", 3 ) ) p_sys->i_aac_profile = FF_PROFILE_AAC_LTP; else { msg_Warn( p_enc, "unknown AAC profile requested, setting it to low" ); p_sys->i_aac_profile = FF_PROFILE_AAC_LOW; } } free( val.psz_string );#endif if( p_enc->fmt_in.i_cat == VIDEO_ES ) { int i_aspect_num, i_aspect_den; if( !p_enc->fmt_in.video.i_width || !p_enc->fmt_in.video.i_height ) { msg_Warn( p_enc, "invalid size %ix%i", p_enc->fmt_in.video.i_width, p_enc->fmt_in.video.i_height ); free( p_sys ); return VLC_EGENERIC; } p_context->width = p_enc->fmt_in.video.i_width; p_context->height = p_enc->fmt_in.video.i_height; if( p_enc->fmt_out.i_codec == VLC_FOURCC('m', 'p', '2', 'v') && (p_context->width > 720 || p_context->height > 576) ) p_context->level = 4; /* High level */ p_context->time_base.num = p_enc->fmt_in.video.i_frame_rate_base; p_context->time_base.den = p_enc->fmt_in.video.i_frame_rate; /* Defaults from ffmpeg.c */ p_context->qblur = 0.5; p_context->qcompress = 0.5; p_context->b_quant_offset = 1.25; p_context->b_quant_factor = 1.25; p_context->i_quant_offset = 0.0; p_context->i_quant_factor = -0.8; p_context->lumi_masking = p_sys->f_lumi_masking; p_context->dark_masking = p_sys->f_dark_masking; p_context->p_masking = p_sys->f_p_masking; p_context->border_masking = p_sys->f_border_masking; p_context->luma_elim_threshold = p_sys->i_luma_elim; p_context->chroma_elim_threshold = p_sys->i_chroma_elim; if( p_sys->i_key_int > 0 ) p_context->gop_size = p_sys->i_key_int; p_context->max_b_frames = __MAX( __MIN( p_sys->i_b_frames, FF_MAX_B_FRAMES ), 0 ); p_context->b_frame_strategy = 0; if( !p_context->max_b_frames && ( p_enc->fmt_out.i_codec == VLC_FOURCC('m', 'p', '2', 'v') || p_enc->fmt_out.i_codec == VLC_FOURCC('m', 'p', '1', 'v') ) ) p_context->flags |= CODEC_FLAG_LOW_DELAY; av_reduce( &i_aspect_num, &i_aspect_den, p_enc->fmt_in.video.i_aspect, VOUT_ASPECT_FACTOR, 1 << 30 /* something big */ ); av_reduce( &p_context->sample_aspect_ratio.num, &p_context->sample_aspect_ratio.den, i_aspect_num * (int64_t)p_context->height, i_aspect_den * (int64_t)p_context->width, 1 << 30 ); p_sys->i_buffer_out = p_context->height * p_context->width * 3; if( p_sys->i_buffer_out < FF_MIN_BUFFER_SIZE ) p_sys->i_buffer_out = FF_MIN_BUFFER_SIZE; p_sys->p_buffer_out = malloc( p_sys->i_buffer_out ); p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0'); p_enc->fmt_in.video.i_chroma = p_enc->fmt_in.i_codec; GetFfmpegChroma( &p_context->pix_fmt, p_enc->fmt_in.video ); if( p_codec->pix_fmts ) { const enum PixelFormat *p = p_codec->pix_fmts; for( ; *p != -1; p++ ) { if( *p == p_context->pix_fmt ) break; } if( *p == -1 ) p_context->pix_fmt = p_codec->pix_fmts[0]; GetVlcChroma( &p_enc->fmt_in.video, p_context->pix_fmt ); p_enc->fmt_in.i_codec = p_enc->fmt_in.video.i_chroma; } if ( p_sys->f_i_quant_factor != 0.0 ) p_context->i_quant_factor = p_sys->f_i_quant_factor; p_context->noise_reduction = p_sys->i_noise_reduction; if ( p_sys->b_mpeg4_matrix ) { p_context->intra_matrix = mpeg4_default_intra_matrix; p_context->inter_matrix = mpeg4_default_non_intra_matrix; } if ( p_sys->b_pre_me ) { p_context->pre_me = 1; p_context->me_pre_cmp = FF_CMP_CHROMA; } if ( p_sys->b_interlace ) { if ( p_context->height <= 280 ) { if ( p_context->height != 16 || p_context->width != 16 ) msg_Warn( p_enc, "disabling interlaced video because height=%d <= 280", p_context->height ); } else { p_context->flags |= CODEC_FLAG_INTERLACED_DCT; if ( p_sys->b_interlace_me ) p_context->flags |= CODEC_FLAG_INTERLACED_ME; } }#if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0) if ( p_sys->b_trellis ) p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;#else p_context->trellis = p_sys->b_trellis;#endif if ( p_sys->i_qmin > 0 && p_sys->i_qmin == p_sys->i_qmax ) p_context->flags |= CODEC_FLAG_QSCALE; if ( p_enc->i_threads >= 1 ) p_context->thread_count = p_enc->i_threads; if( p_sys->i_vtolerance > 0 ) p_context->bit_rate_tolerance = p_sys->i_vtolerance; /* usually if someone sets bitrate, he likes more to get that bitrate * over quality should help 'normal' user to get asked bitrate */ if( p_enc->fmt_out.i_bitrate > 0 && p_sys->i_qmax == 0 && p_sys->i_qmin == 0 ) { p_sys->i_qmax = 51; p_sys->i_qmin = 3; } if( p_sys->i_qmin > 0 ) { p_context->mb_qmin = p_context->qmin = p_sys->i_qmin; p_context->mb_lmin = p_context->lmin = p_sys->i_qmin * FF_QP2LAMBDA; } if( p_sys->i_qmax > 0 ) { p_context->mb_qmax = p_context->qmax = p_sys->i_qmax; p_context->mb_lmax = p_context->lmax = p_sys->i_qmax * FF_QP2LAMBDA; } p_context->max_qdiff = 3; p_context->mb_decision = p_sys->i_hq; if( p_sys->i_quality ) { p_context->flags |= CODEC_FLAG_QSCALE; p_context->global_quality = p_sys->i_quality; } else { p_context->rc_qsquish = 1.0; p_context->rc_max_rate = p_enc->fmt_out.i_bitrate; p_context->rc_min_rate = p_enc->fmt_out.i_bitrate; p_context->rc_buffer_size = p_sys->i_rc_buffer_size; /* This is from ffmpeg's ffmpeg.c : */ p_context->rc_initial_buffer_occupancy = p_sys->i_rc_buffer_size * 3/4; p_context->rc_buffer_aggressivity = p_sys->f_rc_buffer_aggressivity; } } else if( p_enc->fmt_in.i_cat == AUDIO_ES ) { /* work around bug in libmp3lame encoding */ if( i_codec_id == CODEC_ID_MP3 && p_enc->fmt_in.audio.i_channels > 2 ) p_enc->fmt_in.audio.i_channels = 2; p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE; p_context->sample_rate = p_enc->fmt_out.audio.i_rate; p_context->channels = p_enc->fmt_out.audio.i_channels; if ( p_enc->fmt_out.i_codec == VLC_FOURCC('m','p','4','a') ) { /* XXX: FAAC does resample only when setting the INPUT samplerate * to the desired value (-R option of the faac frontend) p_enc->fmt_in.audio.i_rate = p_context->sample_rate;*/#if LIBAVCODEC_VERSION_INT >= ((51<<16)+(40<<8)+4) /* Ignore FF_PROFILE_UNKNOWN */ if( p_sys->i_aac_profile >= FF_PROFILE_AAC_MAIN ) p_context->profile = p_sys->i_aac_profile;#endif } } /* Misc parameters */ p_context->bit_rate = p_enc->fmt_out.i_bitrate; if( i_codec_id == CODEC_ID_RAWVIDEO ) { /* XXX: hack: Force same codec (will be handled by transcode) */ p_enc->fmt_in.video.i_chroma = p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec; GetFfmpegChroma( &p_context->pix_fmt, p_enc->fmt_in.video ); } /* Make sure we get extradata filled by the encoder */ p_context->extradata_size = 0; p_context->extradata = NULL; p_context->flags |= CODEC_FLAG_GLOBAL_HEADER; vlc_mutex_t *lock = var_AcquireMutex( "avcodec" ); if( avcodec_open( p_context, p_codec ) ) { vlc_mutex_unlock( lock ); if( p_enc->fmt_in.i_cat == AUDIO_ES && (p_context->channels > 2 || i_codec_id == CODEC_ID_MP2 || i_codec_id == CODEC_ID_MP3) ) { if( p_context->channels > 2 ) { p_context->channels = 2; p_enc->fmt_in.audio.i_channels = 2; // FIXME msg_Warn( p_enc, "stereo mode selected (codec limitation)" ); } if( i_codec_id == CODEC_ID_MP2 || i_codec_id == CODEC_ID_MP3 ) { int i_frequency, i; for ( i_frequency = 0; i_frequency < 6; i_frequency++ ) { if ( p_enc->fmt_out.audio.i_rate == mpa_freq_tab[i_frequency] ) break; } if ( i_frequency == 6 ) { msg_Err( p_enc, "MPEG audio doesn't support frequency=%d", p_enc->fmt_out.audio.i_rate ); free( p_sys ); return VLC_EGENERIC; } for ( i = 1; i < 14; i++ ) { if ( p_enc->fmt_out.i_bitrate / 1000 <= mpa_bitrate_tab[i_frequency / 3][i] ) break; } if ( p_enc->fmt_out.i_bitrate / 1000 != mpa_bitrate_tab[i_frequency / 3][i] ) { msg_Warn( p_enc, "MPEG audio doesn't support bitrate=%d, using %d", p_enc->fmt_out.i_bitrate, mpa_bitrate_tab[i_frequency / 3][i] * 1000 ); p_enc->fmt_out.i_bitrate = mpa_bitrate_tab[i_frequency / 3][i] * 1000; p_context->bit_rate = p_enc->fmt_out.i_bitrate; } } p_context->codec = NULL; vlc_mutex_lock( lock ); if( avcodec_open( p_context, p_codec ) ) { vlc_mutex_unlock( lock ); msg_Err( p_enc, "cannot open encoder" ); intf_UserFatal( p_enc, false, _("Streaming / Transcoding failed"), _("VLC could not open the encoder.") ); free( p_sys ); return VLC_EGENERIC; } } else { msg_Err( p_enc, "cannot open encoder" ); intf_UserFatal( p_enc, false, _("Streaming / Transcoding failed"), _("VLC could not open the encoder.") ); free( p_sys ); return VLC_EGENERIC; } } vlc_mutex_unlock( lock); p_enc->fmt_out.i_extra = p_context->extradata_size; if( p_enc->fmt_out.i_extra ) { p_enc->fmt_out.p_extra = malloc( p_enc->fmt_out.i_extra ); memcpy( p_enc->fmt_out.p_extra, p_context->extradata, p_enc->fmt_out.i_extra ); } p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER; if( p_enc->fmt_in.i_cat == AUDIO_ES ) { p_sys->i_buffer_out = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE; p_sys->p_buffer_out = malloc( p_sys->i_buffer_out ); p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels; p_sys->p_buffer = malloc( p_sys->i_frame_size ); p_enc->fmt_out.audio.i_blockalign = p_context->block_align; } msg_Dbg( p_enc, "found encoder %s", psz_namecodec ); return VLC_SUCCESS;}/**************************************************************************** * Ffmpeg threading system ****************************************************************************/static void* FfmpegThread( vlc_object_t *p_this ){ struct thread_context_t *p_context = (struct thread_context_t *)p_this; while ( vlc_object_alive (p_context) && !p_context->b_error ) { vlc_mutex_lock( &p_context->lock ); while ( !p_context->b_work && vlc_object_alive (p_context) && !p_context->b_error ) { vlc_cond_wait( &p_context->cond, &p_context->lock ); } p_context->b_work = 0; vlc_mutex_unlock( &p_context->lock ); if ( !vlc_object_alive (p_context) || p_context->b_error ) break; if ( p_context->pf_func ) { p_context->i_ret = p_context->pf_func( p_context->p_context, p_context->arg ); } vlc_mutex_lock( &p_context->lock ); p_context->b_done = 1; vlc_cond_signal( &p_context->cond ); vlc_mutex_unlock( &p_context->lock ); } return NULL;}static int FfmpegExecute( AVCodecContext *s, int (*pf_func)(AVCodecContext *c2, void *arg2), void **arg, int *ret, int count ){ struct thread_context_t ** pp_contexts = (struct thread_context_t **)s->thread_opaque; int i; /* Note, we can be certain that this is not called with the same
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -