ffmpeg 4.0 декодировал h264 медленнее, чем старая версия один (n2.8.14) - PullRequest
0 голосов
/ 23 мая 2018

Я использую ffmpeg для декодирования h264 и транскодирования в jpeg.Раньше я пользовался версией 2.8, теперь меняюсь на 4.0.Новая версия avcodec_decode_video2 устарела, поэтому я использую новый API (отправка, получение).Я обнаружил, что новая версия ffmpeg намного медленнее старой при декодировании h264.это почему?Как достичь оригинальной скорости?

Вот коды инициализации декодера: версия 2.8

//2.8
if (avformat_open_input(&format_, path, NULL, &options) != 0) {
    printf("FileMediaBase: open input failed\n");
    return -1;
}
if (avformat_find_stream_info(format_, NULL) < 0) {
    printf("FileMediaBase: avformat_find_stream_info failed\n");
    avformat_close_input(&format_);
    return -1;
}
AVCodecContext *code_ctx = 0;
AVCodec *codec = 0;
// Find the first audio and video stream
for (int i = 0; i < format_->nb_streams; i++) {
    code_ctx = format_->streams[i]->codec;
    codec = avcodec_find_decoder(code_ctx->codec_id);
    if (code_ctx->codec_type == AVMEDIA_TYPE_VIDEO) {
        vcode_ctx_ = code_ctx;
        vstream_ = format_->streams[i];
    }else if (code_ctx->codec_type == AVMEDIA_TYPE_AUDIO) {
        acode_ctx_ = code_ctx;
        astream_ = format_->streams[i];
    }
    // Open the codec
    if (!codec || (avcodec_open2(code_ctx, codec, NULL) < 0)) {
        printf("avcodec_open2() failed\n");
        avformat_close_input(&format_);
        return -1;
    }

версия 4.0

if (avformat_open_input(&format_, path, NULL, &options) != 0) {
    printf("FileMediaBase: open input failed\n");
    return -1;
}
if (avformat_find_stream_info(format_, NULL) < 0) {
    printf("FileMediaBase: avformat_find_stream_info failed\n");
    avformat_close_input(&format_);
    return -1;
}
AVStream *st;
AVCodec *dec = NULL;
AVDictionary *opts = NULL;

ret = av_find_best_stream(format_, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
if (ret < 0) {
    return ret;
}
else {
    stream_index = ret;
    st = format_->streams[stream_index];

    /* find decoder for the stream */
    dec = avcodec_find_decoder(st->codecpar->codec_id);
    if (!dec) {
        fprintf(stderr, "Failed to find %s codec\n",
            av_get_media_type_string(type));
        return AVERROR(EINVAL);
    }

    /* Allocate a codec context for the decoder */
    *dec_ctx = avcodec_alloc_context3(dec);
    if (!*dec_ctx) {
        fprintf(stderr, "Failed to allocate the %s codec context\n",
            av_get_media_type_string(type));
        return AVERROR(ENOMEM);
    }

    /* Copy codec parameters from input stream to output codec context */
    if ((ret = avcodec_parameters_to_context(*dec_ctx, st->codecpar)) < 0) {
        fprintf(stderr, "Failed to copy %s codec parameters to decoder context\n",
            av_get_media_type_string(type));
        avcodec_free_context(dec_ctx);
        return ret;
    }

    /*if (dec->id == AV_CODEC_ID_H264) {
        (*dec_ctx)->flags |= AV_CODEC_FLAG_TRUNCATED;
    }*/

    /* Init the decoders, with or without reference counting */
    //av_dict_set(&opts, "refcounted_frames", refcount ? "1" : "0", 0);
    if ((ret = avcodec_open2(*dec_ctx, dec, &opts)) < 0) {
        fprintf(stderr, "Failed to open %s codec\n",
            av_get_media_type_string(type));
        avcodec_free_context(dec_ctx);
        return ret;
    }

Я распечатываю время, потраченное на некоторый APIenter image description here

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Я столкнулся с той же проблемой при декодировании видеопотока h264 с использованием версий ffmpeg 2.8.14 и 4.0.1.В обоих случаях при доступе к контексту кодека после avformat_find_stream_info ()

AVFormatContext *pFormatCtx;
AVCodecContext* pCodecCtxOrig;
...
avformat_find_stream_info(pFormatCtx, NULL)
...
for (uint i = 0; i < pFormatCtx->nb_streams; i++)
{
  if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
  {
    pCodecCtxOrig = pFormatCtx->streams[i]->codec;
    ...

  }
}

тогда pCodecCtxOrig :: thread_count фактически устанавливается в 0, что означает, что библиотека ffmpeg сама находит подходящий thread_count на основе ядер ЦП при открытии кодекаконтекст с avcodec_open2().В моем случае счетчик потоков был установлен на 5.

В случае 2.8.14 pCodecCtxOrig :: thread_count установлен на 0, а при копировании с него

AVCodecContext* pCodecCtxOrig;
AVCodecContext* pCodecCtx;
....
avcodec_copy_context(pCodecCtx, pCodecCtxOrig)

поток_счеттакже копируется.

В случае 4.0.1 avcodec_copy_context() не рекомендуется, и вместо него следует использовать avcodec_parameters_to_context().Копирующая структура AVCodecParameters не содержит thread_count, поэтому информация теряется.Количество потоков остается значением по умолчанию 1, которое устанавливается avcodec_alloc_context3.Чтобы решить эту проблему, установите thread_count в 0, прежде чем открывать контекст кодека.

0 голосов
/ 24 мая 2018

Я решил эту проблему, изменив количество потоков декодирования (по умолчанию 1 в версии 4.0) на 6 (по умолчанию 6 в версии 2.8).

(*dec_ctx)->thread_count = 6;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...