I have a source code in C++ using libavcodec for decoding h264 rtsp stream frames. This source code was written using ffmpeg 1.1. Now when I upgraded to ffmpeg 3.3, all things seem to work correctly except that decoding frames not work. In old version, I was using avcodec_decode_video2. After upgrading, avcodec_decode_video2 always sets got_picture to 0 and return value is equal to the size of the input packet (which means all data is used). And never a frame is decoded. I have also removed avcodec_decode_video2 and done decoding with avcodec_send_packet and avcodec_receive_frame, but avcodec_send_packet always returns 0 and avcodec_receive_frame always returns -11 (EAGAIN).
This is the code I use for decoding:
#include "stdafx.h"
#include <stdlib.h>
#include <string>
#include <iostream>
using namespace std;
extern "C"{
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libavutil/pixfmt.h"
}
int extraDataSize;
static const int MaxExtraDataSize = 1024;
uint8_t extraDataBuffer[MaxExtraDataSize];
void AddExtraData(uint8_t* data, int size)
{
auto newSize = extraDataSize + size;
if (newSize > MaxExtraDataSize){
throw "extradata exceeds size limit";
}
memcpy(extraDataBuffer + extraDataSize, data, size);
extraDataSize = newSize;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::string strFramesPath("g:\\frames\\");
AVCodec* avCodec;
AVCodecContext* avCodecContext;
AVFrame* avFrame;
AVCodecID codecId = AV_CODEC_ID_H264;
unsigned char sprops_part_1[9] = { 0x27, 0x42, 0x80, 0x1f, 0xda, 0x02, 0xd0, 0x49, 0x10 };
unsigned char sprops_part_2[4] = { 0x28, 0xce, 0x3c, 0x80 };
av_register_all();
avcodec_register_all();
avCodec = avcodec_find_decoder(codecId);
avCodecContext = avcodec_alloc_context3(avCodec);
if (!avCodecContext)
{
cout << "avcodec_alloc_context3 failed." << endl;
return 0;
}
uint8_t startCode[] = { 0x00, 0x00, 0x01 };
// sprops
{
// sprops 1
AddExtraData(startCode, sizeof(startCode));
AddExtraData(sprops_part_1, 9);
// sprops 2
AddExtraData(startCode, sizeof(startCode));
AddExtraData(sprops_part_2, 4);
avCodecContext->extradata = extraDataBuffer;
avCodecContext->extradata_size = extraDataSize;
}
AddExtraData(startCode, sizeof(startCode));
avCodecContext->flags = 0;
if (avcodec_open2(avCodecContext, avCodec, NULL) < 0)
{
cout << "failed to open codec" << endl;
return 0;
}
avFrame = av_frame_alloc();
if (!avFrame)
{
cout << "failed to alloc frame" << endl;
return 0;
}
void *buffer = malloc(100 * 1024); // 100 KB buffer - all frames fit in this buffer
for (int nFrameIndex = 0; nFrameIndex < 257; nFrameIndex++)
{
std::string strFilename = std::string("g:\\frames\\" + std::to_string(nFrameIndex));
FILE* f = fopen(strFilename.c_str(), "rb");
fseek(f, 0, SEEK_END);
long nFileSize = ftell(f);
fseek(f, 0, SEEK_SET);
size_t nReadSize = fread(buffer, 1, nFileSize, f);
// cout << strFilename << endl;
if (nReadSize != nFileSize)
{
cout << "Error reading file data" << endl;
continue;
}
AVPacket avpkt;
avpkt.data = (uint8_t*)buffer;
avpkt.size = nReadSize;
while (avpkt.size > 0)
{
int got_frame = 0;
auto len = avcodec_decode_video2(avCodecContext, avFrame, &got_frame, &avpkt);
if (len < 0) {
//TODO: log error
cout << "Error decoding - error code: " << len << endl;
break;
}
if (got_frame)
{
cout << "* Got 1 Decoded Frame" << endl;
}
avpkt.size -= len;
avpkt.data += len;
}
}
getchar();
return 0;
}
Test frames data can be downloaded from this link: Frames.zip (~3.7MB)
I have used windows builds from Builds - Zeranoe FFmpeg If you copy paste this code into your IDE, the code compiles successfully. Using libavcodec new versions, no frame is decoded. Using old version of libavcodec (20141216-git-92a596f), decoding starts when feed frame 2.
Any ideas?