Wie codiere ich H.264 mit libavcodec/x264?
-
30-09-2019 - |
Frage
Ich versuche, Video mit Libavcodec/libavformat zu codieren. Audio funktioniert großartig, aber wenn ich versuche, Video zu codieren, erhalte ich die folgenden Fehler:
[libx264 @ 0x10182a000]broken ffmpeg default settings detected
[libx264 @ 0x10182a000]use an encoding preset (vpre)
Einfach zu beheben mit der Befehlszeile FFMPEG, aber ich versuche dies in C zu tun. Meine Optionen sind
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;
Aber avcodec_open () schlägt fehl.
Welche anderen Werte muss ich festlegen, um X264 glücklich zu machen?
Lösung
Ich bin mir nicht sicher, ob Sie es zum Laufen gebracht haben, aber die folgenden Parameter funktionieren für mich.
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;
Die Fehlermeldung broken ffmpeg default settings detected
wird in der X264 -Bibliothek in angezeigt x264/Encoder/Encoder.c Wenn zu viele Einstellungen die Standard -FFMPEG -Einstellungen sind (z. qmin = 2, qmax = 31, qcompress = 0.5
), ändern Sie diese drei Werte in etwas anderes, z. B. qmin = 10, qmax = 51, qcompress = 0.6
, löst den Fehler auf.
Andere Tipps
Vergessen Sie nicht, x264 private Optionen zu verwenden. Sie können jederzeit ein Profil festlegen:
av_dict_set(&This->opts, "vprofile", "baseline", 0)
Oder setzen Sie die niedrigste Codierungslatenz:
av_dict_set(&This->opts, "tune", "zerolatency", 0);
Oder wählen Sie eine Voreinstellung:
av_dict_set(&This->opts, "preset","ultrafast",0);
Vor dem Öffnen eines Codecs
avcodec_open2(This->context, This->codec, &This->opts)
Das Folgende ist, wie die X264 -Voreinstellungen des FFMPEG interpretiert werden.
Leider weiß ich keine einfache Möglichkeit, die Voreinstellungen wie FFMPEG zu importieren. Sie können die X264-Voreinstellungswerte suchen, die alle in /usr/local/share/ffmpeg/libx264- <name}.ffpreset gespeichert sind, wobei {Name} für FFMPEG als Argument -vpre {Name} angegeben wird. Daher würde FFMPEG typischerweise libx264 -medium.ffpreset und dann libx264 -main
Sie können alle Optionen (wie in den libx264- {namens} .ffreset-Dateien) suchen, um ihre Strukturnamen zu erhalten, indem Sie in die Datei libavcodec/options.c suchen, die in den FFMPEG SVN-Repositories zu finden ist.
So würden die mittleren und Hauptvoreinstellungen in C -Code übersetzt:
// 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
Sie müssen sich den FFMPEG -Quellcode ansehen, wenn Sie diese Voreinstellungen automatisch analysieren möchten.
Ich hoffe, dass die Informationen, die ich gerade gegeben habe, Ihnen ein bisschen mehr helfen würden :)
Ich codiere YUV420P -Bilder in verschiedenen Formaten unter Verwendung verschiedener Codecs. Codecid Ich habe nach der Verwendung von Rate_Format (...) von Avoutputformat genommen. Andere Codec -Einstellungen sind jedoch (alle wurden aus dem Quellcode von FFMPEG -Beispielen entnommen):
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;
Diese Einstellung muss für die meisten Codecs funktionieren, aber ich hatte ein Problem mit FPS: Nicht alle Codecs unterstützen FPS -Werte (und einige andere Parameter).
Scheint, dass die FFMPEG -Version 20130302 so etwas wie erfordert
c->profile = FF_PROFILE_H264_BASELINE;