首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >VFW: AVIStreamGetFrameOpen()返回空

VFW: AVIStreamGetFrameOpen()返回空
EN

Stack Overflow用户
提问于 2016-08-21 00:51:09
回答 2查看 1.7K关注 0票数 2

我正在尝试使用基于来自C++的概念的本NeHe教程接口编写一个OpenGL视频类,但使用更现代的代码(用于OpenGL 3/4)。在最初加载视频(而不是检索帧)的函数中,我引用了AVIStreamGetFrameOpen() (根据MSDN )

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

同一页还说:

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

我的问题是 AVIStreamGetFrameOpen()返回NULL,如前所述,这意味着没有找到与文件匹配的解压缩程序。但是,我的文件可以在Windows中播放,没有问题,我认为这意味着应该可以使用解压缩器。

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

下面是该函数的代码:

代码语言:javascript
复制
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;
}

忽略我奇怪的变量前缀。

EN

回答 2

Stack Overflow用户

发布于 2016-08-30 18:53:22

我的问题是,AVIStreamGetFrameOpen()返回NULL,如前所述,这意味着没有找到与文件匹配的解压缩程序。但是,我的文件可以在Windows中播放,没有问题,我认为这意味着应该可以使用解压缩器。

您认为应该提供解压缩器的假设是错误的。

Windows提供了几个与视频和音频相关的基线API:用于Windows的视频、DirectShow、媒体基金会、以及Windows。上面也有层(AudioVideoPlayback,MediaElement等)。

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

然而,在您的场景中,情况并非如此。是一个遗留的API,它无法为更新的API使用编解码器。反过来使用Media作为主API,而DirectShow作为复杂场景的备用API,在这种情况下,它提供了第二次尝试播放文件的机会。基本上,Windows当前版本中仍然存在的唯一原因是对遗留应用程序的支持:新提供的视频/音频相关功能不适用于VFW,不仅是微软的,还有第三方。

另外,32位编解码器和64位编解码器是独立的,某些代码只能使用各自比特的编解码器。

也就是说,Windows和您的代码在消耗相同的API方面没有交集。播放该文件并不意味着您的VFW代码也应该能够播放。您遇到的问题是,没有安装合适的解码器从文件中读取和解码视频(您没有提到格式,盲目猜测这里是AVI与H.264视频)。

票数 1
EN

Stack Overflow用户

发布于 2019-02-13 14:28:24

VFW是非常古老的/遗留的/废弃的。

根据视窗,VFW只支持以下格式:

  • 味精
  • msvideo1
  • 雪雀
  • indeo 3.2

我也在阅读NeHe教程。第35课中使用的Face2.avi是用cinepak格式编码的。

代码语言:javascript
复制
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,可以使用用于Windows的ffmpeg将视频转换为cinepakmsvideo1格式:

代码语言:javascript
复制
ffmpeg -i your_video.xxx -vcodec cinepak output.avi

(转换到cinepakmsvideo1花费的时间要长得多,但它的质量要好得多。)

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

https://stackoverflow.com/questions/39059959

复制
相关文章

相似问题

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