Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VFW:avirstreamgetframeopen()返回NULL 我试图用Windows的视频来编写一个C++视频类,它基于概念,但是有更多的现代代码(对于OpenGL 3/4)。在我最初加载视频(而不是检索帧)的函数中,我参考了avirstreamgetframeopen(),它根据以下内容:_C++_Opengl_Video_Avi_Vfw - Fatal编程技术网

VFW:avirstreamgetframeopen()返回NULL 我试图用Windows的视频来编写一个C++视频类,它基于概念,但是有更多的现代代码(对于OpenGL 3/4)。在我最初加载视频(而不是检索帧)的函数中,我参考了avirstreamgetframeopen(),它根据以下内容:

VFW:avirstreamgetframeopen()返回NULL 我试图用Windows的视频来编写一个C++视频类,它基于概念,但是有更多的现代代码(对于OpenGL 3/4)。在我最初加载视频(而不是检索帧)的函数中,我参考了avirstreamgetframeopen(),它根据以下内容:,c++,opengl,video,avi,vfw,C++,Opengl,Video,Avi,Vfw,返回可与AVIStreamGetFrame函数一起使用的GetFrame对象 同一页还说: 如果系统找不到可以将流解压缩为给定格式或任何RGB格式的解压器,则函数将返回NULL 我的问题是AVIStreamGetFrameOpen()返回NULL,如上所述,这意味着找不到与文件匹配的解压缩程序。但是,我的文件可以用Windows Media Player播放,没有任何问题,我相信这意味着应该有一个解压器 当涉及到VFW时,似乎缺少文档,MSDN页面并不总是非常有用。有人知道是什么导致了这个问题吗

返回可与AVIStreamGetFrame函数一起使用的GetFrame对象

同一页还说:

如果系统找不到可以将流解压缩为给定格式或任何RGB格式的解压器,则函数将返回NULL

我的问题是
AVIStreamGetFrameOpen()
返回
NULL
,如上所述,这意味着找不到与文件匹配的解压缩程序。但是,我的文件可以用Windows Media Player播放,没有任何问题,我相信这意味着应该有一个解压器

当涉及到VFW时,似乎缺少文档,MSDN页面并不总是非常有用。有人知道是什么导致了这个问题吗

下面是有关函数的代码:

bool Video::Load(std::string FileName) {
    try {
        if (this->bLoaded)
            this->UnLoad();

        AVIFileInit();

        if (AVIStreamOpenFromFile(&pavi, FileName.c_str(), streamtypeVIDEO, 0, OF_READ, NULL) != 0)
            throw "Failed to open the AVI video stream.";

        AVIStreamInfo(pavi, &psi, sizeof(psi));             // Reads Information About The Stream Into psi
        this->szWidth = psi.rcFrame.right - psi.rcFrame.left;           // Width Is Right Side Of Frame Minus Left
        this->szHeight = psi.rcFrame.bottom - psi.rcFrame.top;          // Height Is Bottom Of Frame Minus Top

        ulnLastFrame = AVIStreamLength(pavi);                // The Last Frame Of The Stream

        this->dDuration = AVIStreamSampleToTime(pavi, ulnLastFrame) / 1000.0f;
        this->dSecondsPerFrame = this->dDuration / ulnLastFrame;

        pgf = AVIStreamGetFrameOpen(pavi, NULL);              // Create The PGETFRAME Using Our Request Mode
        if (pgf == NULL)
            // ===== ERROR THROWN HERE =====
            throw "Failed to open the AVI GetFrame object.";

        glGenTextures(1, &this->unTexID);
        glBindTexture(GL_TEXTURE_2D, this->unTexID);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, this->szWidth, this->szHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
        glBindTexture(GL_TEXTURE_2D, 0);
    }
    catch (const char* e) {
        Message((std::string("Error: ") + e + "\nFile: \"" + FileName + "\"").c_str(), "Error");
        return false;
    }


    this->bLoaded = true;
    return true;
}
忽略我奇怪的变量前缀

我的问题是AVIStreamGetFrameOpen()返回NULL,如上所述,这意味着找不到与文件匹配的解压缩程序。但是,我的文件可以用Windows Media Player播放,没有任何问题,我相信这意味着应该有一个解压器

您认为解压器应该可用的假设是错误的

Windows提供了与视频和音频相关的几个基本API:Windows、DirectShow、MediaFoundation、Windows Media等视频。除此之外还有其他层(音频视频播放、MediaElement等)

API之间存在一定的互操作性:有时编解码器和其他对象在API之间共享,或者一个API在其他对象上提供兼容性包装

但是在你的场景中不是这样的。Windows的视频是一个遗留的API,它不能使用新的API的编解码器。Windows Media播放器反过来使用Media Foundation作为主要API,而DirectShow作为复杂场景的回退API,它提供了第二次尝试播放文件。基本上,唯一的原因是视频。Windows仍然存在于当前版本的Windows中,它支持旧版应用程序:VFW无法使用新的视频/音频相关功能,不仅是Microsoft,还有第三方

此外,32位编解码器和64位编解码器是独立的,某些代码段只能使用相应位的编解码器


也就是说,就使用相同的API而言,Windows Media Player和您的代码之间没有交叉点。Windows Media Player播放该文件并不意味着您的VFW代码也应该能够播放。您遇到的问题是,没有安装合适的解码器来读取和解码文件中的视频(你没有提到格式,这里有一个盲目的猜测,那就是它是带有H.264视频的AVI)。

VFW非常古老/传统/不推荐使用

根据,VFW仅支持以下格式:

  • msrle
  • msvideo1
  • cinepak
  • indeo 3.2
我也在阅读NeHe教程。第35课中使用的avi是以
cinepak
格式编码的

E:\>ffmpeg -i Face2.avi -hide_banner
Input #0, avi, from 'Face2.avi':
  Duration: 00:00:03.04, start: 0.000000, bitrate: 1116 kb/s
    Stream #0:0: Video: cinepak (cvid / 0x64697663), rgb24, 160x120, 29.97 tbr, 29.97 tbn, 29.97 tbc
                        ~~~~~~~
如果必须使用VFW,可以使用将视频转换为
cinepak
msvideo1
格式:

ffmpeg -i your_video.xxx -vcodec cinepak output.avi

(转换到
cinepak
msvideo1
需要更长的时间,但会产生更好的质量。)

Windows Media Player使用DirectShow制作所有视频内容,而不是Windows视频(这是一项过时的老技术)。现在,大多数视频编解码器纯粹是作为DirectShow过滤器提供的。因此,要么使用它,要么使您的程序完全独立于特定于操作系统的多媒体库,并使用跨平台的编解码器框架(如gstreamer或ffmpeg/libavcodec。@datenwolf感谢您的回复。我听说DirectShow学习起来很复杂,但我会努力学习。您会推荐任何特定的来源,还是我应该浏览MSDN页面?我没有找到太多其他内容。坦白地说,我甚至不会使用DirectShow,而是使用ffmpeg/libavcodec;这是唯一的缺点当然,API不是很稳定,但跟踪变化通常并不困难。几年前,我写了一篇文章,其初衷是在纹理上获取视频帧。我已经很长时间没有更新它了,所以它可能不会用当前版本的ffmpeg立即编译。@datenwolf Tha我现在对ffmpeg不太了解,但我会研究一下,看看是否能在我的类中实现它。