Reputation: 20130
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
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_video2
with 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