65.9K
CodeProject 正在变化。 阅读更多。
Home

无代码单色 AVI 读取器

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.86/5 (4投票s)

2006年5月15日

1分钟阅读

viewsIcon

46763

downloadIcon

1660

无需安装编解码器驱动即可读取 AVI 文件的方法。

Sample Image - CodeclessAviReader.jpg

引言

当我使用 C++ 项目处理单色 AVI 文件时,我注意到在某些机器上,我需要管理员权限才能安装编解码器驱动程序。

由于我在学校计算机实验室工作,获取这些权限非常困难,我选择通过直接使用 DLL 驱动程序来解决问题,而不是通过操作系统使用它。

背景

本文使用了 Ben Rudiak-Gould 在 GPL 许可下开发的无损 Win32 视频编解码器 Huffyuv 的代码。

它还使用了开源计算机视觉库 OPENCV 来查看帧。

使用代码

AVI 读取器被封装在一个名为 CMonochromeAviReader 的类中。

读取器使用从原始 Huffyuv 代码编译的编解码器库。对 Ben 代码所做的修改是向编解码器主结构 CodeInst 添加了关键字 __declspec(dllexport)

    struct __declspec(dllexport) CodecInst {
      ...
    };

创建了两个实例:第一个 CodecInst m_codec 用于编解码器,另一个 ICDECOMPRESS m_icinfo 必须跟踪一个帧的压缩和未压缩数据。

    typedef struct { 
        DWORD              dwFlags; 
        LPBITMAPINFOHEADER lpbiInput; 
        LPVOID             lpInput; 
        LPBITMAPINFOHEADER lpbiOutput; 
        LPVOID             lpOutput; 
        DWORD              ckid; 
    } ICDECOMPRESS;

字段 lpInput 用于从未压缩的数据中提取数据,而 lpOutput 用于压缩数据。

IplImage* CMonochromeAviReader::ReadFrame(unsigned int index)
{
    AVIStreamRead(m_pAviStream, index, 1, m_icinfo.lpInput, 
                  m_frameStreamLength, NULL, NULL);
    if(... compressed data ...)
    {
        m_codec.Decompress(&m_icinfo, 0);
        m_codec.DecompressEnd();
            
        cvSetImageData(m_pFrameRGB,m_icinfo.lpOutput,m_width*3);
        ...
        return m_pFrame;
    }
    else if(... uncompressed data ...)
    {
        cvSetImageData(m_pFrame,m_icinfo.lpInput,m_width*1);
        return m_pFrame;
    }
    else 
    {
        return NULL;
    }
}

请注意,OPENCV 函数 cvSetImageData( IplImage* image, void* data, width) 也可以替换为 memcpy(IplImage* image->imageData,void *data, width*height),但 cvSetImageData 更好,因为它针对 Intel 处理器进行了优化,并且它不会复制所有数据;它只是一个指向,而 memcpy 必须将内存复制到新分配的空间中。

修订历史

16-05-2006

  • 修复了 Close 方法中的错误。

15-05-2006

  • 原始文章。

就这样,各位!

© . All rights reserved.