ffmpeg libx264 настройки AVCodecContext

Я использую недавнюю сборку 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;

Простое изменение идентификатора CODEC на 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;

}


person integra753    schedule 07.02.2012    source источник
comment
Вы уверены, что кодек h.264 включен в сборку ffmpeg?   -  person ciphor    schedule 07.02.2012
comment
Я использую сборки ffmpeg.zeranoe.com/builds. они утверждают, что он был собран с --enable-libx264.   -  person integra753    schedule 07.02.2012
comment
Пожалуйста, опубликуйте свой код для CODEC_ID_H264.   -  person ciphor    schedule 08.02.2012
comment
установите для avcodeccontext avrational правильное значение.   -  person Sureshkumar Menon    schedule 09.03.2012
comment
У меня точно такая же проблема: - источник скачан с ffmpeg.zeranoe.com/builds - avcodec_open( ) возвращает -1 для CODEC_ID_H264 - avcodec_open() отлично работает для CODEC_ID_MPEG2VIDEO - ffmpeg.zeranoe.com/builds указывает, что библиотеки были собраны с --enable-libx264 Итак, вы нашли решение?   -  person    schedule 10.10.2012
comment
@integra753 Пожалуйста, опубликуйте свой тип полезной нагрузки для H264. Я имею в виду что-то вроде этого: {34, H263, AVMEDIA_TYPE_VIDEO, CODEC_ID_H263, 90000, -1}   -  person Dr.jacky    schedule 12.10.2015


Ответы (1)


По моему опыту, вы должны предоставить 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, и он отлично работает.

person ALM865    schedule 20.05.2014