avcodec receive AVERROR(EAGAIN) for h264

For the developers that use FFmpeg in their software.
Post Reply
Ksilon
Posts: 1
Joined: Fri Mar 29, 2019 4:40 pm

avcodec receive AVERROR(EAGAIN) for h264

Post by Ksilon » Fri Mar 29, 2019 4:53 pm

Hi
I'm working with ffmpeg 4.1 and I'm showing live streams of multiple cameras, h264 and h265. My program collects packets of the same frame and then calls decodeVideo function. Actually it sends all packets of a frame at once.

Program works well if there is no missing packets. When I remove packet in random I-frames, both h264 and h265 streams work as expected (jumps some seconds but continues streaming).

When I remove packet in random P-frame from h265 streams, avcodec_send_packet function gives AVERROR_INVALIDDATA and streams continue.

However when I remove packet in random P-frame from h264 streams, avcodec_send_packet function gives 0. Then avcodec_receive_frame function gives AVERROR(EAGAIN) continuously and streams freeze.

Code: Select all

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;
}

When I add avcodec_flush_buffers like shown, my problem is temporarily solved. However it freeze again after a while.

Code: Select all

if(receive_frame == AVERROR(EAGAIN))
{
    Utility::Log->ErrorFormat("avcodec_receive_frame() returns AVERROR(EAGAIN)");
    avcodec_flush_buffers((AVCodecContext*)context);
}
Tested with ffmpeg version 4.1.1 same results.

Find an ffmpeg version like 2.5 decode function is different but there is no problem when i remove packets. However I'm working with h265 streams too.

EDIT

Code: Select all

AVCodecID id = AVCodecID::AV_CODEC_ID_H264;
AVCodec* dec = avcodec_find_decoder(id);
AVCodecContext* decContext = avcodec_alloc_context3(dec);
After these lines, my code included the following lines. When i delete them, there is no problem now.

Code: Select all

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

decContext->flags2 |= AV_CODEC_FLAG2_CHUNKS;

Post Reply
'