Hi,
I am new in using libav and cannot find a solution to my problem. We have a
server program that can capture video from webcam and save the stream into
an flv file (on linux). This program was not written by us, we cannot modify
it. My task is to write a program that listens to a target directory, and if
new flv file appears, start processing it immediately. I use libavformat and
libavcodec to read from flv and decode frames.
The problem is that I start reading the flv file before it is finished. When
av_read_frame reaches EOF, it will not continue any more, even if new data
arrive later. This is because av_find_stream_info reads the packets into a
buffer at the beginning (when the flv file is small), and when the end of
this buffer is reached, it is not updated, no new data are added to it. I
did not find the solution how to update the buffer, or how to treat the file
as an endless stream.
The corresponding part of my code is attached.
Thanks for help in advance,
Zsolt
bool FrameManager::open(const char *video)
{
// Open video file
if (avformat_open_input(&m_pFormatCtx, video, NULL, NULL) != 0)
{
cerr << "Error: [" << video << "] cannot open to read" << endl;
return false;
}
// Retrieve stream information
if (av_find_stream_info(m_pFormatCtx) < 0)
{
cerr << "Error: [" << video << "] cannot find stream information" << endl;
return false;
}
// Dump information about file onto standard error
//dump_format(pFormatCtx, 0, video, false);
// Find the first video stream
m_videoStream = -1;
for (uint i = 0; i < m_pFormatCtx->nb_streams; ++i)
if(m_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
m_videoStream = i;
break;
}
if (m_videoStream == -1)
{
cerr << "Error: [" << video << "] cannot find a video stream" << endl;
return false;
}
// Get a pointer to the codec context for the video stream
m_pCodecCtx = m_pFormatCtx->streams[m_videoStream]->codec;
// Find the decoder for the video stream
m_pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id);
if (m_pCodec == NULL)
{
cerr << "Error: [" << video << "] codec not found" << endl;
return false;
}
// Open codec
if (avcodec_open(m_pCodecCtx, m_pCodec)<0)
{
cerr << "Error: [" << video << "] cannot open codec" << endl;
return false;
}
// Hack to correct wrong frame rates that seem to be generated by some codecs
if (m_pCodecCtx->time_base.num > 1000 && m_pCodecCtx->time_base.den == 1)
m_pCodecCtx->time_base.den = 1000;
return true;
}
bool FrameManager::getNextFrame(Frame &frame, bool &eof)
{
// Allocate video frame
AVFrame *pFrame = avcodec_alloc_frame();
// Allocate an AVFrame structure
AVFrame *pFrameRGB = avcodec_alloc_frame();
if (!pFrame || !pFrameRGB)
{
cerr << "Error: cannot allocate AVFrame structure" << endl;
return false;
}
// Determine required buffer size and allocate buffer
int numBytes = avpicture_get_size(PIX_FMT_RGB24,
m_pCodecCtx->width, m_pCodecCtx->height);
uint8_t *buffer = new uint8_t[numBytes];
// Assign appropriate parts of buffer to image planes in pFrameRGB
avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
m_pCodecCtx->width, m_pCodecCtx->height);
AVPacket packet;
bool reterror = false;
while (true)
{
int ret = av_read_frame(m_pFormatCtx, &packet);
if (ret < 0)
{
// error or end of file
if (ret == AVERROR_EOF)
eof = true;
else
reterror = true;
break;
}
// ... do something useful with the packet ...
av_free_packet(&packet);
break;
}
delete [] buffer;
av_free(pFrameRGB);
av_free(pFrame);
return !reterror;
}
void FrameManager::close()
{
// Close the codec
avcodec_close(m_pCodecCtx);
// Close the video file
av_close_input_file(m_pFormatCtx);
m_pFormatCtx = NULL;
m_pCodecCtx = NULL;
m_pCodec = NULL;
}
_______________________________________________
libav-api mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-api