Hi all,
I am decoding a H264 video stream converting each frame into a raw bitmap
data. Maybe I am missing something: the problem is that I am analyzing all
the frames and, as I have seen, every 16 frames I get an wrong frame. Is
there any kind of issue or encoding problem that causes possible problems
every 16 frame?
Here is the code I have implemented,
int VideoExtract::startDecoding(char* videoData, const int videoLen)
{
// If not initialized, initialize right now
if (!_initialized)
{
av_register_all();
avcodec_register_all();
_initialized = 1;
}
// Init variables and objects
_context = avformat_alloc_context();
// Save the video in a file
FILE* f = fopen(_filename, "wb");
if (!f) return 0;
fwrite(videoData, 1, videoLen, f);
fclose(f);
if (avformat_open_input(&_context, _filename, NULL, NULL) < 0)
{
// Error
avformat_free_context(_context);
// Remove the temporal file
remove(_filename);
return 0;
}
if (avformat_find_stream_info(_context, NULL) < 0)
{
// Error
avformat_free_context(_context);
// Remove the temporal file
remove(_filename);
return 0;
}
// Obtain the video stream of the total set of streams
for (unsigned int k = 0; k < _context->nb_streams; ++k)
{
if (_context->streams[k]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
_video_stream_index = k;
_context->streams[k]->codec->time_base.den = 90000;
}
_pCodecCtx = _context->streams[_video_stream_index]->codec;
_pCodec = avcodec_find_decoder(_pCodecCtx->codec_id);
avcodec_open(_pCodecCtx, _pCodec);
return 1;
}
int VideoExtract::getNext(VideoFrame& videoFrame)
{
int video_stream_index;
AVPacket packet;
av_init_packet(&packet);
int got_picture = 0;
int res = 0;
// Allocate video frame
AVFrame* pFrame = avcodec_alloc_frame();
while (av_read_frame(_context, &packet) >= 0 && !got_picture)
{
// Everything is OK, continue
if (packet.stream_index == _video_stream_index)
{
if (avcodec_decode_video2(_pCodecCtx, pFrame, &got_picture, &packet) < 0)
{
// Error
}
if (got_picture)
{
// For each image, conversion...
////////////////////////////////////////////////
// Prepare the conversion parameters
int srcWidth = pFrame->width;
int srcHeight = pFrame->height;
int dstWidth = srcWidth;
int dstHeight = srcHeight;
AVPixelFormat srcFormat = _pCodecCtx->pix_fmt;
AVPixelFormat dstFormat = AV_PIX_FMT_BGR24;
////////////////////////////////////////////////
// Calculate the bytes needed for the output image
int dstBytes = avpicture_get_size(dstFormat, dstWidth, dstHeight);
// Create buffer for the output image and input image
uint8_t* outbuffer = (uint8_t*) av_malloc(dstBytes);
// Create ffmpeg frame structures, these do not allocate space for image
data,
// just the pointers and other information about the image
AVFrame* outpic = avcodec_alloc_frame();
// This will set the pointers in the frame structures to the right points in
// the input and output buffers
avpicture_fill((AVPicture*) outpic, outbuffer, dstFormat, dstWidth,
dstHeight);
// Create the conversion context
SwsContext* fooContext = sws_getContext(srcWidth, srcHeight, srcFormat,
dstWidth, dstHeight, dstFormat, SWS_BICUBIC, NULL, NULL, NULL);
// Perform the conversion
sws_scale(fooContext, pFrame->data, pFrame->linesize, 0, srcHeight,
outpic->data, outpic->linesize);
unsigned int length = dstWidth * dstHeight * 3;
// Copy the data from the output buffer
char* data = (char*) malloc(length);
memcpy(data, outbuffer, length);
// Create a new VideoFrame object and init it using the friend method 'init'
videoFrame.load(_nFrame, pFrame->pkt_pts, data, length, pFrame->width,
pFrame->height, 3);
++_nFrame;
sws_freeContext(fooContext);
avcodec_free_frame(&outpic);
av_free(outbuffer);
res = 1;
}
}
}
// Free frame
avcodec_free_frame(&pFrame);
// Free packet
av_free_packet(&packet);
return res;
}
int VideoExtract::stopDecoding()
{
// Free everything
avcodec_close(_pCodecCtx);
avformat_close_input(&_context);
avformat_free_context(_context);
// Remove the temporal file
remove(_filename);
return 1;
}
Cheers,
--
Dídac Pérez
_______________________________________________
libav-api mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-api