ffmpeg libx264 Настройки AVCodecContext - PullRequest
2 голосов
/ 07 февраля 2012

Я использую недавнюю сборку ffmpeg для Windows (январь 2011 г.) и пытаюсь записать видео в H264. Это хорошо записывает в MPEG4, используя следующие настройки:

c->codec_id = CODEC_ID_MPEG4;
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->width = VIDEO_WIDTH;
c->height = VIDEO_HEIGHT;
c->bit_rate = c->width * c->height * 4;
c->time_base.den = FRAME_RATE;
c->time_base.num = 1;
c->gop_size = 12;
c->pix_fmt = PIX_FMT_YUV420P;

Простое изменение идентификатора кодека на H264 приводит к сбою avcodec_open () (-1). Я нашел список возможных настроек Как кодировать h.264 с помощью libavcodec / x264? . Я пробовал это, без установки pix_fmt, avcodec_open () по-прежнему не удается, но если я дополнительно установить c-> pix_fmt = PIX_FMT_YUV420P; тогда я получаю деление на ноль исключений.

Затем я наткнулся на несколько постов, в которых говорится, что я ничего не должен устанавливать (за исключением code_id, codec_type, width, height и, возможно, bit_rate и pix_fmt), поскольку библиотека теперь сама выбирает лучшие настройки. Я пробовал различные комбинации, но avcode_open () не работает.

У кого-нибудь есть советы по поводу того, что делать или какие текущие настройки?

Спасибо.

Вот один набор настроек H264, которые описывают проблему, которую я описываю:

static AVStream* AddVideoStream(AVFormatContext *pOutputFmtCtx, 
int frameWidth, int frameHeight, int fps)
{
AVCodecContext* ctx;
AVStream* stream;

stream = av_new_stream(pOutputFmtCtx, 0);
if (!stream) 
{
    return NULL;
}

ctx = stream->codec;

ctx->codec_id = pOutputFmtCtx->oformat->video_codec; //CODEC_ID_H264
ctx->codec_type = AVMEDIA_TYPE_VIDEO;
ctx->width = frameWidth;             //704
ctx->height = frameHeight;           //576
ctx->bit_rate = frameWidth * frameHeight * 4;

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;
ctx->flags2^=CODEC_FLAG2_8X8DCT;    // flags2=-dct8x8

// if set this get divide by 0 error on avcodec_open()
// if don't set it get -1 error on avcodec_open()
//ctx->pix_fmt = PIX_FMT_YUV420P; 

return stream;

}

1 Ответ

1 голос
/ 21 мая 2014

По моему опыту, вы должны предоставить FFMPEG как можно меньше информации при инициализации вашего кодека.Это может показаться нелогичным, но это означает, что FFMPEG будет использовать настройки по умолчанию, которые с большей вероятностью сработают, чем ваши собственные догадки.Посмотрите, что я включил бы ниже:

AVStream *stream;
m_video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
stream = avformat_new_stream(_outputCodec, m_video_codec);
ctx = stream->codec;
ctx->codec_id = m_fmt->video_codec;
ctx->bit_rate = m_AVIMOV_BPS;           //Bits Per Second 
ctx->width    = m_AVIMOV_WIDTH;         //Note Resolution must be a multiple of 2!!
ctx->height   = m_AVIMOV_HEIGHT;        //Note Resolution must be a multiple of 2!!
ctx->time_base.den = m_AVIMOV_FPS;      //Frames per second
ctx->time_base.num = 1;
ctx->gop_size      = m_AVIMOV_GOB;      // Intra frames per x P frames
ctx->pix_fmt       = AV_PIX_FMT_YUV420P;//Do not change this, H264 needs YUV format not RGB

Как и в предыдущих ответах, вот рабочий пример библиотеки FFMPEG, кодирующей кадры RGB в видео H264:

http://www.imc-store.com.au/Articles.asp?ID=276

Дополнительная мысль о вашем коде:

  • Вы звонили, регистрировали все как показано ниже?

    avcodec_register_all ();

    av_register_all ();

    Если вы не вызовете эти две функции в начале кода, ваши последующие вызовы FFMPEG завершатся неудачно иСкорее всего, вы обнаружите ошибку.

Посмотрите на связанный пример, я проверил его на VC ++ 2010, и он отлично работает.

...