首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理来自内存缓冲区的视频流

处理来自内存缓冲区的视频流
EN

Stack Overflow用户
提问于 2011-03-09 03:17:08
回答 2查看 20.6K关注 0票数 14

我需要从专有的网络协议(我已经知道如何做)解析一个视频流(mpeg ),然后我想使用OpenCV将视频流处理成帧。我知道如何从文件或标准URL中使用cv::VideoCapture,但我想将OpenCV设置为从内存中的缓冲区读取,以便在需要时存储视频流数据。有没有办法设置一个回调方法(或任何其他接口),让我仍然可以使用cv::VideoCapture对象?有没有更好的方法来完成对视频的处理,而不是将其写到文件中,然后重新读取它。如果FFMPEG是更好的选择,我也会考虑直接使用FFMPEG。如果需要的话,我想我可以把AVFrames转换成Mat。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-07 01:18:16

我最近也有类似的需求。我正在寻找一种在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类添加了一个新函数:

代码语言:javascript
复制
virtual bool openBuffer( unsigned char* pBuffer, unsigned int bufLen );

我在highgui DLL中通过一个新的API调用提供了对它的访问,类似于cvCreateFileCapture。新的openBuffer函数与open( const char* _filename )函数基本相同,区别如下:

代码语言:javascript
复制
err = av_open_input_file(&ic, _filename, NULL, 0, NULL);

替换为:

代码语言:javascript
复制
ic = avformat_alloc_context();
ic->pb = avio_alloc_context(pBuffer, bufLen, 0, pBuffer, read_buffer, NULL, NULL);

if(!ic->pb) {
    // handle error
}

// Need to probe buffer for input format unless you already know it
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);

// cleanup
free(probe_data.buf);
probe_data.buf = NULL;

if(!pAVInputFormat) {
    // handle error
}

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

现在传递给avio_alloc_contextread_buffer回调函数定义如下:

代码语言:javascript
复制
static int read_buffer(void *opaque, uint8_t *buf, int buf_size)
{
    // This function must fill the buffer with data and return number of bytes copied.
    // opaque is the pointer to private_data in the call to avio_alloc_context (4th param)
    
    memcpy(buf, opaque, buf_size);
    return buf_size;
}

此解决方案假设整个视频都包含在内存缓冲区中,并且可能必须进行调整才能处理流数据。

就是这样!顺便说一句,我使用的是OpenCV 2.1版本,所以YMMV。

票数 18
EN

Stack Overflow用户

发布于 2020-01-26 01:26:09

对于opencv 4.2.0,执行类似上述操作的代码位于:https://github.com/jcdutton/opencv分支: 4.2.0-jcd1

将整个文件加载到缓冲区指向的内存中,大小为buffer_size。示例代码:

代码语言:javascript
复制
VideoCapture d_reader1;
d_reader1.open_buffer(buffer, buffer_size);
d_reader1.read(input1);

上面的代码读取视频的第一帧。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5237175

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档