Кодирование x264 с помощью libav

Я пытаюсь кодировать необработанные данные изображения в x264 с помощью libav:

AVPacket vpkt = { 0 };
av_init_packet(&vpkt);

int got;
int ret = avcodec_encode_video2(vcodec, &vpkt, frameyuv.get(), &got);

if (!ret && got && vpkt.size) {
    if (vpkt.pts != AV_NOPTS_VALUE) {
        vpkt.pts = av_rescale_q(vpkt.pts, vcodec->time_base, videost->time_base);
    }
    if (vpkt.dts != AV_NOPTS_VALUE) {
        vpkt.dts = av_rescale_q(vpkt.dts, vcodec->time_base, videost->time_base);
    }

    vpkt.stream_index = videost->index;

    if(vcodec->coded_frame->key_frame) {
        vpkt.flags |= AV_PKT_FLAG_KEY;
    }
    /* -> will return -22 if max_b_frames > 0 */
    ret = av_interleaved_write_frame(oc, &vpkt);
}

Работает нормально, когда vcodec->max_b_frames установлен в 0, но при любом другом значении av_interleaved_write_frame возвращает -22 (неверный аргумент).

/* will fail */
c->max_b_frames = 3;
/* -> ok*/
c->max_b_frames = 0;

Зачем? Я что-то пропустил?

Варианты кодека

AVDictionary *opts = NULL;
av_dict_set(&opts, "vprofile", "baseline", 0);

/* ... */
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->bit_rate = 500 * 1000;
c->width = VideoWidth;
c->height = VideoHeight;
c->time_base.den = fps;
c->time_base.num = 1;
c->pix_fmt = AV_PIX_FMT_YUV420P;

Формат контейнера - mp4.

1 ответ

Решение

Вам нужно av_rescale_q в временной базе вашего выходного контекста, а не в видеопотоке. Похоже, что вы делаете, ничего с av_rescale_q. Пытаться:

av_rescale_q(vpkt.pts, vcodec->time_base, [output context]->time_base);

Если у вас продолжают возникать проблемы, почти всегда проблемы с кадрами B указывают на плохое значение DTS. Рассмотрите возможность установки DTS в AV_NOPTS_VALUE и дайте демультиплексору решить ее самостоятельно.

Помните, что для декодирования B-кадра вы должны знать кадры по обе стороны от него, поэтому сначала они должны быть демультиплексированы, рассмотрим 3 кадра:

I B I

Первый кадр должен быть декодирован первым, затем третий и, наконец, второй. Эта информация получена из DTS.

Наконец, выясните, почему вы получаете -22, следуя этому переполнению стека. Я был бы шокирован, если бы это не было "немонотонно увеличивающейся ошибкой PTS/DTS".

Другие вопросы по тегам