FFmpeg AVERROR (EAGAIN) ошибка при получении вызова avcodec для h264 - PullRequest
0 голосов
/ 29 марта 2019

Я работаю с ffmpeg 4.1 и показываю прямые трансляции с нескольких камер, h264 и h265.

Моя программа собирает пакеты одного кадра и затем вызывает функцию decodeVideo.На самом деле он отправляет все пакеты кадра сразу.

Программа работает хорошо, если нет пропущенных пакетов.Когда я удаляю пакет в случайных I-кадрах, потоки h264 и h265 работают должным образом (несколько секунд прыгает, но продолжает потоковую передачу).

Когда я удаляю пакет в случайном P-кадре из потоков h265, функция avcodec_send_packet выдает AVERROR_INVALIDDATAи потоки продолжаются.

Однако, когда я удаляю пакет в случайном P-кадре из потоков h264, функция avcodec_send_packet дает 0. Затем функция avcodec_receive_frame непрерывно дает AVERROR (EAGAIN) и блокирует потоки.

void decodeVideo(array<uint8_t>^ data, int length, AvFrame^ finishedFrame)
{   
    AVPacket* videoPacket = new AVPacket();
    av_init_packet(videoPacket);
    pin_ptr<unsigned char> dataPtr = &data[0];
    videoPacket->data = dataPtr;
    videoPacket->size = length;             

    int retVal = avcodec_send_packet((AVCodecContext*)context, videoPacket);
    if(retVal < 0)
    {
        if (retVal == AVERROR_EOF)
            Utility::Log->ErrorFormat("avcodec_send_packet() return value is AVERROR_EOF.");
        else if( retVal == AVERROR_INVALIDDATA)
            Utility::Log->ErrorFormat("avcodec_send_packet() INVALID DATA!");
        else
            Utility::Log->ErrorFormat("avcodec_send_packet() return value is negative:{0}",retVal);
    }
    else
    {                   
        int receive_frame = avcodec_receive_frame((AVCodecContext*)context, (AVFrame*)finishedFrame);

        if (receive_frame == AVERROR(EAGAIN))
            Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(EAGAIN)");
        else if(receive_frame == AVERROR_EOF)
            Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(AVERROR_EOF)");
        else
            Utility::Log->ErrorFormat("avcodec_receive_frame() return value is negative:{0}",receive_frame);
    }   

    av_packet_unref(videoPacket);
    delete videoPacket;
}

EDIT

Когда я добавляю avcodec_flush_buffers, как показано, моя проблема временно решается.Однако через некоторое время он снова зависает.

if(receive_frame == AVERROR(EAGAIN))
{
    Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(EAGAIN)");
    avcodec_flush_buffers((AVCodecContext*)context);
}

Протестировано с ffmpeg версии 4.1.1 с такими же результатами.

Найдите версию ffmpeg, такую ​​как функция декодирования 2.5отличается, но нет проблем, когда я удаляю пакеты.Однако я тоже работаю с потоками h265.

EDIT2

AVCodecID id = AVCodecID::AV_CODEC_ID_H264;
AVCodec* dec = avcodec_find_decoder(id);
AVCodecContext* decContext = avcodec_alloc_context3(dec);

После этих строк мой код включал следующие строки. Когда я их удаляю, проблем теперь нет.

if(dec->capabilities & AV_CODEC_CAP_TRUNCATED)
    decContext->flags |= AV_CODEC_FLAG_TRUNCATED;

decContext->flags2 |= AV_CODEC_FLAG2_CHUNKS;
...