我最近也有类似的需求。我正在寻找一种在OpenCV中播放已经存在于内存中的视频的方法,但是不需要将视频文件写入磁盘。我发现FFMPEG接口已经支持这一点,通过使用
av_open_input_stream
。与OpenCV用于打开文件的
av_open_input_file
调用相比,需要进行更多的准备工作。
通过以下两个网站之间的交流,我能够组合出一个使用ffmpeg调用的可行解决方案。请参考这些网站上的信息以获取更多详细信息:
http://ffmpeg.arrozcru.org/forum/viewtopic.php?f=8&t=1170
http://cdry.wordpress.com/2009/09/09/using-custom-io-callbacks-with-ffmpeg/
为了在OpenCV中使其正常工作,我最终向CvCapture_FFMPEG类添加了一个新的函数:
virtual bool openBuffer( unsigned char* pBuffer, unsigned int bufLen );
我在highgui DLL中提供了一个新的API调用来访问它,类似于cvCreateFileCapture
。新的openBuffer
函数基本上与open(const char *_filename)
函数相同,唯一的区别是:
err = av_open_input_file(&ic, _filename, NULL, 0, NULL);
被替换为:
ic = avformat_alloc_context();
ic->pb = avio_alloc_context(pBuffer, bufLen, 0, pBuffer, read_buffer, NULL, NULL);
if(!ic->pb) {
}
AVProbeData probe_data;
probe_data.buf_size = (bufLen < 4096) ? bufLen : 4096;
probe_data.filename = "stream";
probe_data.buf = (unsigned char *) malloc(probe_data.buf_size);
memcpy(probe_data.buf, pBuffer, probe_data.buf_size);
AVInputFormat *pAVInputFormat = av_probe_input_format(&probe_data, 1);
if(!pAVInputFormat)
pAVInputFormat = av_probe_input_format(&probe_data, 0);
free(probe_data.buf);
probe_data.buf = NULL;
if(!pAVInputFormat) {
}
pAVInputFormat->flags |= AVFMT_NOFILE;
err = av_open_input_stream(&ic , ic->pb, "stream", pAVInputFormat, NULL);
此外,在
CvCapture_FFMPEG::close()
函数中,请确保调用
av_close_input_stream
而不是
av_close_input_file
。
现在,我将read_buffer
回调函数定义为传递给avio_alloc_context
的:
static int read_buffer(void *opaque, uint8_t *buf, int buf_size)
{
memcpy(buf, opaque, buf_size);
return buf_size;
}
这个解决方案假设整个视频都包含在内存缓冲区中,并且可能需要进行调整才能与流数据一起使用。
就是这样!顺便说一下,我正在使用 OpenCV 版本 2.1,所以你的情况可能会有所不同。