【问题标题】:Visual C++ AVI writer function to push bitmaps (640x480) to AVI file?将位图(640x480)推送到 AVI 文件的 Visual C++ AVI 编写器功能?
【发布时间】:2009-07-22 17:53:21
【问题描述】:

我有一个带有 SDK for Visual C++ 的视频采集卡。在 SDK 的回调中,我可以以 30 fps 的速度使用彩色帧 (640 x 480)。目前,我正在将整个图像序列作为单独的 bmp 文件一次写入一个单独的线程中——即一小时内 108,000 个文件,或每小时约 100 GB,这是无法管理的。我想将这些传入的帧推送到一个 AVI 文件,并可选择压缩。我什至从哪里开始?到目前为止,翻阅 MSDN DirectShow 文档让我感到困惑。那里有更好的例子吗? OpenCV 是答案吗?我看过一些例子,但我不确定 OpenCV 是否会将卡识别为捕获设备,我也不明白它是如何识别捕获设备的。另外,我已经得到了帧 in,我只需要将它们 out 放到一些不支持我的生产者线程的消费者线程中的 AVI 中。感谢您的帮助。

【问题讨论】:

  • 总的问题但是卡/SDK的名称是什么?我自己也想很快研究一下这种东西。

标签: visual-c++ opencv directshow avi


【解决方案1】:

我以前用过CAviFile。它工作得很好,我不得不稍微调整一下以允许用户选择编解码器。我从CAviGenerator 获取了该代码。 CAviFile 的接口很简单,下面是一些示例代码:

CAviFile *Avi = new CAviFile(fileName.c_str(), 0, 10);

HRESULT res = Avi->AppendNewFrame(Width, Height, ImageBuffer, BitsPerPixel);
if (FAILED(res))
{
    std::cout << "Error recording AVI: " << Avi->GetLastErrorMessage() << std::endl;
}

delete Avi;

显然,您必须确保您的 ImageBuffer 包含正确格式的数据等。但是,一旦我把这些东西都整理好,它就很好用了。

【讨论】:

  • @JCoenia,我只是用它来捕捉 1600x1200 的视频,所以如果对 VFW 有限制,那么它们是相当高的。
【解决方案2】:

您可以使用 Video for Windows 或 DirectShow。每个都有自己的编解码器集。 (并且可以扩展)

虽然微软认为 VfW 已被弃用,但它仍然完全可用,并且比 DirectShow 更容易设置。

【讨论】:

    【解决方案3】:

    您需要将 AVI Mux (CLSID_AviDest) 附加到您的采集卡。然后您需要附加一个文件写入器 (CLSID_FileWriter),它会为您写出所有内容。

    诚然,设置捕获图并不一定容易,因为 DirectShow 会让您跳过一百万又一圈。

    使用 ICaptureGraphBuilder2 接口更容易。值得庆幸的是,微软已经给出了如何做到这一点的非常好的纲要......

    http://msdn.microsoft.com/en-us/library/dd318627.aspx

    虽然添加编码器并不容易,并且方便地在该链接中掩盖了。

    这是一个示例,说明如何枚举我为我的 MFC 应用程序编写的系统中的所有视频压缩器。

    BOOL LiveInputDlg::EnumerateVideoCompression()
    {
        CComboBox* pVideoCompression    = (CComboBox*)GetDlgItem( IDC_COMBO_VIDEOCOMPRESSION );
        pVideoCompression->SetExtendedUI( TRUE );
    
        pVideoCompression->SetCurSel( pVideoCompression->AddString( _T( "<None>" ) ) );
    
    
        ICreateDevEnum* pDevEnum    = NULL;
        IEnumMoniker*   pEnum       = NULL;
    
        HRESULT hr = S_OK;
        hr  = CoCreateInstance( CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pDevEnum );
        if ( FAILED( hr ) )
        {
            return FALSE;
        }
    
        hr  = pDevEnum->CreateClassEnumerator( CLSID_VideoCompressorCategory, &pEnum, 0 );
    
        pDevEnum->Release();
        if ( FAILED( hr ) )
        {
            return FALSE;
        }
    
        if ( pEnum )
        {
            IMoniker* pMoniker  = NULL;
            hr = pEnum->Next( 1, &pMoniker, NULL );
            while( hr == S_OK )
            {
                IPropertyBag* pPropertyBag  = NULL;
                hr = pMoniker->BindToStorage( NULL, NULL, IID_IPropertyBag, (void**)&pPropertyBag );
                if ( FAILED( hr ) )
                {
                    pMoniker->Release();
                    pEnum->Release();
                    return FALSE;
                }
    
                VARIANT varName;
                VariantInit( &varName );
                hr = pPropertyBag->Read( L"Description", &varName, NULL );
                if ( FAILED( hr ) )
                {
                    hr = pPropertyBag->Read( L"FriendlyName", &varName, NULL );
                    if ( FAILED( hr ) )
                    {
                        pPropertyBag->Release();
                        pMoniker->Release();
                        pEnum->Release();
    
                        return FALSE;
                    }
                }
    
                IBaseFilter* pBaseFilter    = NULL;
                pMoniker->BindToObject( NULL, NULL, IID_IBaseFilter, (void**)&pBaseFilter );
    
                {
                    USES_CONVERSION;
                    TCHAR* pName    = OLE2T( varName.bstrVal );
                    int index       = pVideoCompression->AddString( pName );
                    pVideoCompression->SetItemDataPtr( index, pMoniker );
    
                    VariantClear( &varName );
                    pPropertyBag->Release();
                }
    
                hr = pEnum->Next( 1, &pMoniker, NULL );
            }
    
            pEnum->Release();
        }
        return TRUE;
    }
    

    祝你好运! :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 2013-05-12
      • 2015-07-01
      • 2012-11-24
      • 1970-01-01
      • 1970-01-01
      • 2012-08-01
      相关资源
      最近更新 更多