Micka
Micka

Reputation: 20130

Decode compressed frame to memory using LibAV: avcodec_decode_video2?

I am completely new to libAV.

I have a single video frame coming from somewhere else (it's in memory, not in a file). It should be H.264 encoded keyframe.

I'm trying to decode with avcodec_decode_video2 is that the right function for my needs?

I'm encountering a problem using this code (basically taken from FFmpeg decode raw buffer with avcodec_decode_video2 ):

AVCodecContext  *m_pCodecCtx;
AVCodec         *m_pCodec;
AVFrame         *m_pFrame;

m_pCodec= avcodec_find_decoder(CODEC_ID_H264);
m_pCodecCtx = avcodec_alloc_context3(m_pCodec);
avcodec_open2(m_pCodecCtx,m_pCodec,0);

// since avcodec_alloc_frame() isn't existing anymore, I changed to following:
//m_pFrame=m_fc.avcodec_alloc_frame(); // and what is/was m_fc?!?
m_pFrame = av_frame_alloc();


AVPacket        packet;
av_init_packet(&packet);

packet.data = (unsigned char*)mData;
packet.size=(int)mDataSize;

// this is for decoding a keyframe?
packet.flags |= AV_PKT_FLAG_KEY;

int framefinished=0;
int nres=avcodec_decode_video2(m_pCodecCtx,m_pFrame,&framefinished,&packet);

if(framefinished)
{
    std::cout << "decoded frame" << std::endl
}

unfortunately framefinished always returns 0 while nres is 18331 which equals mDataSize

Where's my fault? Do I have to specify codec information more clearly? Is my packet broken or incomplete? Am I using the wrong libAV function?

In the sample code of the framework I'm using, the image data is succesfully streamed to a file, using av_interleaved_write_frame (and a AvFormatContext). Can this help me configuring my packet or the codec?

Upvotes: 1

Views: 6394

Answers (1)

biskitt
biskitt

Reputation: 1431

With nres being positive, and equal to mDataSize means that everything is ok, your decoding is done with this packet. framefinished == 0 only means that the frame was not written.

It may be because your frame data is shared between several packets, so you need to call avcodec_decode_video2with the following packets, until you have a full frame.

Another possible explanation: your codec have a delay between input and output: it gives you nothing on the first call, and need a last call with an empty packet to get the last frame. What you need to do is call something like

AVPacket emptyPacket;
av_init_packet(&emptyPacket);
emptyPacket.data = NULL;
emptyPacket.size = 0;
emptyPacket.stream_index = packet.stream_index;
nres=avcodec_decode_video2(m_pCodecCtx,m_pFrame,&framefinished,&emptyPacket);

See the note on CODEC_CAP_DELAY here

Upvotes: 2

Related Questions