Чрезвычайно высокий битрейт при кодировании видео с помощью libavcodec

Я пытаюсь захватить вывод камеры и сделать видео с помощью libavcodec. В качестве примера того, как это сделать, я использовал пример мультиплексирования ffmpeg.

Проблема в том, что 4-секундное видео имеет размер ~ 15 МБ и битрейт ~ 30000 кбит / с, хотя я установил битрейт на AVCodecContext равным 400000 (я считаю, что это значение в бит / сек, а не кбит / с) .

Я также пытался записать видео с помощью ffmpeg из командной строки, и его битрейт составляет ~ 700 кбит / с.

У кого-нибудь есть идея, почему битрейт не сохраняется и, следовательно, результирующий файл очень большой? Код, который я использовал для инициализации контекста кодека, приведен ниже:

часть инициализации:

avformat_alloc_output_context2(&m_formatContext, NULL, NULL, filename);
outputFormat = m_formatContext->oformat;

codec = avcodec_find_encoder(outputFormat->video_codec);

m_videoStream = avformat_new_stream(m_formatContext, codec);

m_videoStream->id = m_formatContext->nb_streams - 1;

codecContext = m_videoStream->codec;

codecContext->codec_id = outputFormat->video_codec;

codecContext->width = m_videoResolution.width();
codecContext->height = m_videoResolution.height();

int m_bitRate = 400000;
codecContext->bit_rate = m_bitRate;
codecContext->rc_min_rate = m_bitRate;
codecContext->rc_max_rate = m_bitRate;
codecContext->bit_rate_tolerance = 0;

codecContext->time_base.den = 20;
codecContext->time_base.num = 1;

codecContext->pix_fmt = AV_PIX_FMT_YUV422P;

if (m_formatContext->oformat->flags & AVFMT_GLOBALHEADER)
    codecContext->flags |= CODEC_FLAG_GLOBAL_HEADER;
/* open it */
ret = avcodec_open2(codecContext, codec, NULL);

avFrame = avcodec_alloc_frame();

ret = avpicture_alloc(&avPicture, codecContext->pix_fmt, codecContext->width, codecContext->height);

*((AVPicture *)avFrame) = avPicture;

av_dump_format(m_formatContext, 0, filename, 1);

if (!(outputFormat->flags & AVFMT_NOFILE)) {
    ret = avio_open(&m_formatContext->pb, filename, AVIO_FLAG_WRITE);
}

ret = avformat_write_header(m_formatContext, NULL);

if (avFrame)
    avFrame->pts = 0;

person niculare    schedule 18.10.2013    source источник


Ответы (1)


Потому что у каждого энкодера свой профиль и указанный вами битрейт - это подсказка. Если ваш битрейт является допустимым значением (не слишком маленьким и не слишком большим), кодек просто выберет поддерживаемый битрейт в своем списке профилей.

«Возможности» кодека также могут влиять на битрейт, но это, насколько я знаю.

Профили кодеков определяют корреляцию между как минимум:

  • Размер рамы (ширина, высота)
  • битрейт
  • формат пикселей
  • частота кадров

Я все еще изо всех сил пытаюсь найти способ получить битрейт от кодека с помощью API, но вы можете узнать его профили, указав очень низкий битрейт перед открытием кодека.

с кодом

codecContext->bit_rate = 1;
avcodec_open2(codecContext, codec, NULL);

Кодек FFmpeg зарегистрирует жалобу и список допустимых кортежей, перечисленных выше.

Примечание. Пробовал только с кодеками, для которых не требуются внешние библиотеки.

person UmNyobe    schedule 10.01.2014