libavcodec/x264でH.264をエンコードする方法は?
-
30-09-2019 - |
質問
libavcodec/libavformatを使用してビデオをエンコードしようとしています。オーディオはうまく機能しますが、ビデオをエンコードしようとすると、次のエラーが表示されます。
[libx264 @ 0x10182a000]broken ffmpeg default settings detected
[libx264 @ 0x10182a000]use an encoding preset (vpre)
コマンドラインFFMPEGを使用して簡単に修正できますが、Cでこれを実行しようとしています。
AVStream *pVideoOutStream = av_new_stream(pOutFormatCtx, 0);
AVCodecContext *pVideoOutCodecCtx = pVideoOutStream->codec;
pVideoOutCodecCtx->codec_id = CODEC_ID_H264;
pVideoOutCodecCtx->codec_type = CODEC_TYPE_VIDEO;
pVideoOutCodecCtx->bit_rate = pVideoInCodecCtx->bit_rate;
pVideoOutCodecCtx->width = pVideoInCodecCtx->width;
pVideoOutCodecCtx->height = pVideoInCodecCtx->height;
pVideoOutCodecCtx->pix_fmt = pVideoInCodecCtx->pix_fmt;
pVideoOutCodecCtx->sample_rate = pVideoInCodecCtx->sample_rate;
pVideoOutCodecCtx->gop_size = 30;
しかし、avcodec_open()は失敗します。
x264を幸せにするために、他にどのような価値を設定する必要がありますか?
解決
あなたがそれを機能させたかどうかはわかりませんが、次のパラメーターが私のために機能します。
ctx->bit_rate = 500*1000;
ctx->bit_rate_tolerance = 0;
ctx->rc_max_rate = 0;
ctx->rc_buffer_size = 0;
ctx->gop_size = 40;
ctx->max_b_frames = 3;
ctx->b_frame_strategy = 1;
ctx->coder_type = 1;
ctx->me_cmp = 1;
ctx->me_range = 16;
ctx->qmin = 10;
ctx->qmax = 51;
ctx->scenechange_threshold = 40;
ctx->flags |= CODEC_FLAG_LOOP_FILTER;
ctx->me_method = ME_HEX;
ctx->me_subpel_quality = 5;
ctx->i_quant_factor = 0.71;
ctx->qcompress = 0.6;
ctx->max_qdiff = 4;
ctx->directpred = 1;
ctx->flags2 |= CODEC_FLAG2_FASTPSKIP;
エラーメッセージ broken ffmpeg default settings detected
x264ライブラリに表示されます x264/encoder/encoder.c 設定が多すぎる場合、デフォルトのFFMPEG設定(例: qmin = 2, qmax = 31, qcompress = 0.5
)、これらの3つの値を何か他のものに変更します。 qmin = 10, qmax = 51, qcompress = 0.6
, 、エラーを解決します。
他のヒント
X264プライベートオプションを使用することを忘れないでください。いつでもプロファイルを設定できます。
av_dict_set(&This->opts, "vprofile", "baseline", 0)
または、最低エンコーディングレイテンシを設定します。
av_dict_set(&This->opts, "tune", "zerolatency", 0);
または、プリセットを選択します。
av_dict_set(&This->opts, "preset","ultrafast",0);
コーデックを開く前
avcodec_open2(This->context, This->codec, &This->opts)
以下は、FFMPEGのX264プリセットを解釈する方法です。
残念ながら、FFMPEGのようにプリセットをインポートする簡単な方法がわかりません。すべて/usr/local/share/ffmpeg/libx264- {name} ffpresetに保存されているx264プリセット値を検索できます。ここで、{name}はffmpegに-vpre {name}コマンドライン引数として指定されます。したがって、通常、ffmpegにはlibx264-medium.ffpreset、libx264-main.ffpresetが含まれます。
すべてのオプション(libx264- {name} .ffpresetファイルで定義されているように)を検索して、libavcodec/options.cファイルを見ることで構造名を取得できます。
メディアとメインのプリセットがCコードに変換される方法は次のとおりです。
// libx264-medium.ffpreset preset
ctx->coder_type = 1; // coder = 1
ctx->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop
ctx->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1
ctx->partitions|=X264_PART_I8X8+X264_PART_I4X4+X264_PART_P8X8+X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8
ctx->me_method=ME_HEX; // me_method=hex
ctx->me_subpel_quality = 7; // subq=7
ctx->me_range = 16; // me_range=16
ctx->gop_size = 250; // g=250
ctx->keyint_min = 25; // keyint_min=25
ctx->scenechange_threshold = 40; // sc_threshold=40
ctx->i_quant_factor = 0.71; // i_qfactor=0.71
ctx->b_frame_strategy = 1; // b_strategy=1
ctx->qcompress = 0.6; // qcomp=0.6
ctx->qmin = 10; // qmin=10
ctx->qmax = 51; // qmax=51
ctx->max_qdiff = 4; // qdiff=4
ctx->max_b_frames = 3; // bf=3
ctx->refs = 3; // refs=3
ctx->directpred = 1; // directpred=1
ctx->trellis = 1; // trellis=1
ctx->flags2|=CODEC_FLAG2_BPYRAMID+CODEC_FLAG2_MIXED_REFS+CODEC_FLAG2_WPRED+CODEC_FLAG2_8X8DCT+CODEC_FLAG2_FASTPSKIP; // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip
ctx->weighted_p_pred = 2; // wpredp=2
// libx264-main.ffpreset preset
ctx->flags2|=CODEC_FLAG2_8X8DCT;c->flags2^=CODEC_FLAG2_8X8DCT; // flags2=-dct8x8
これらのプリセットを自動的に解析する場合は、FFMPEGソースコードを確認する必要があります。
私がちょうど与えた情報があなたをもう少し助けることを願っています:)
Yuv420p写真を異なるコーデックを使用して、さまざまな形式にエンコードします。 codecid avoutputformatからsavoutputformatから取得したのは、buess_format(...)関数を使用した後です。しかし、他のコーデック設定は(それらはすべてFFMPEGの例のソースコードから取得されています):
c->codec_id = (CodecID)CODEC_ID_H264; //This is your codec id
c->codec_type = CODEC_TYPE_VIDEO;
c->bit_rate = 1000000;
c->width = <...>;
c->height = <...>;
c->time_base.den = 25;
c->time_base.num = 1;
c->gop_size = 12;
c->pix_fmt = PIX_FMT_YUV420P;
if (c->codec_id == CODEC_ID_MPEG1VIDEO) //It not necessary for you
c->mb_decision=2;
// some formats want stream headers to be separate
if(oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
この設定はほとんどのコーデックに動作する必要がありますが、FPSに問題がありました。すべてのコーデックがFPS値(および他のパラメーターも)をサポートするわけではありません。
FFMPEGバージョン20130302には、ようなものが必要なようです
c->profile = FF_PROFILE_H264_BASELINE;