如何从avi文件中读取YUV8数据?

时间:2013-09-03 11:35:55

标签: c++ opencv video ffmpeg

我的avi文件包含未压缩的灰色视频数据。我需要从中提取帧。文件大小为22 Gb。

我该怎么做?

我已经尝试了ffmpeg,但它给了我“无法找到视频流的编解码器参数”消息 - 因为没有编解码器在工作,只是帧。

由于Opencv只使用ffmpeg来读取视频,因此也排除了opencv。

似乎剩下的唯一途径是尝试挖掘原始数据,但我不知道如何。

编辑:这是我用opencv从文件中读取的代码。失败发生在第二个if内。在文件上运行ffmpeg二进制文件也会失败并显示上面的消息(无法找到编解码器参数等)

/* register all formats and codecs */
av_register_all();

/* open input file, and allocate format context */
if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
    fprintf(stderr, "Could not open source file %s\n", src_filename);
    ret = 1;
    goto end;
}
fmt_ctx->seek2any = true;
/* retrieve stream information */
int res = avformat_find_stream_info(fmt_ctx, NULL);
if (res < 0) {
    fprintf(stderr, "Could not find stream information\n");
    ret = 1;
    goto end;
}

编辑:

以下是我尝试进行提取的示例代码:pastebin。我得到的结果是每次调用AVIStreamRead后都是一个不变的缓冲区。

1 个答案:

答案 0 :(得分:2)

如果您不需要跨平台功能Video for Windows(VFW)API是一个不错的选择(http://msdn.microsoft.com/en-us/library/windows/desktop/dd756808(v=vs.85).aspx),我不会放置整个代码块,因为有很多事要做,但你应该是能够从参考链接中找出它。基本上,您执行AVIFileOpen,然后使用AVIFileGetStream通过streamtypeVIDEO获取视频流,或者使用AVIStreamOpenFromFile立即执行此操作,然后使用{ {1}}。如果你到了失败的地步,我可以尝试提供帮助,但它应该非常简单。

另外,不确定为什么ffmpeg失败了,我一直在用ffmpeg进行原始AVI读取而不涉及任何编解码器,你能发布什么调用ffpeg实际上失败了吗?

编辑:

对于读取数据大小为0时看到的问题.AVI文件每秒有N个插槽,其中N是视频的fps。在现实生活中,样本不会准确地达到该速度(例如IP监控摄像机),因此实际数据样本索引可以是非连续的,如1,5,11,......并且VFW会在它们之间插入空样本(即从那里你读取一个零大小的样本)。你需要做的是调用AVIStreamRead,其中NULL为缓冲区,0为大小,直到AVIStreamRead不为0或者你运行的是最后一个样本。当您获得实际大小时,您可以再次使用缓冲区指针和大小调用该样本索引上的bRead。我通常做压缩视频所以我不使用建议的大小,但至少根据你的代码snipplet我会做这样的事情:

AVIStreamRead

编辑2:

由于这可能会让某人或你自己在VFW和FFMPEG之间做出选择,我也更新了你的FFMPEG示例,以便它解析相同的文件(对不起代码质量,因为它没有错误检查,但我想你可以看逻辑流程:

...
bRead = 0;
do 
{
    aviOpRes = AVIStreamRead(ppavi,smpS,1,NULL,0,&bRead,&smpN);
} while (bRead == 0 && ++smpS < si.dwLength + si.dwStart);
if(smpS >= si.dwLength + si.dwStart)
    break;
PUCHAR tempBuffer = new UCHAR[bRead];
aviOpRes = AVIStreamRead(ppavi,smpS,1,tempBuffer,bRead,&bRead,&smpN);
/* do whatever you need */
delete tempBuffer;
...

基本上你打开上下文并从中读取数据包。您将获得音频和视频数据包,因此您应该检查数据包是否属于感兴趣的流。 FFMPEG将为您节省空帧的麻烦,并只提供那些包含数据的样本。