1

SDK for Visual C++ を備えたビデオ キャプチャ カードを持っています。SDK からのコールバックで、カラー フレーム (640 x 480) を 30 fps で使用できるようになりました。現在、イメージ シーケンス全体を個別の bmp ファイルとして一度に 1 つずつ別のスレッドに書き込んでいます。これは 1 時間に 108,000 ファイル、つまり 1 時間あたり約 100 GB であり、管理できません。オプションの圧縮を使用して、これらの着信フレームを 1 つの AVI ファイルにプッシュしたいと考えています。どこから始めればいいですか?これまでのところ、MSDN DirectShow のドキュメントをざっと見ていて混乱してきました。もっと良い例はありますか?OpenCVは答えですか?いくつかの例を見てきましたが、OpenCV がカードをキャプチャ デバイスとして認識するかどうかもわかりませんし、そもそもキャプチャ デバイスをどのように認識するかもわかりません。また、私はすでにフレームを取得しています、プロデューサースレッドをバックアップしないコンシューマースレッドでAVIに出力する必要があります。助けてくれてありがとう。

4

3 に答える 3

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に正しい形式のデータが含まれていることなどを確認する必要があります。しかし、そのようなものをすべて整理すると、うまくいきました。

于 2009-07-22T18:01:39.183 に答える
0

キャプチャ カードに AVI Mux (CLSID_AviDest) を接続する必要があります。次に、File Writer (CLSID_FileWriter) をアタッチする必要があります。これにより、すべてが書き出されます。

確かに、キャプチャ グラフの設定は必ずしも簡単ではありません。

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;
}

幸運を!:)

于 2009-07-24T08:32:40.810 に答える
0

Video for Windows または DirectShow のいずれかを使用できます。それぞれに独自のコーデック セットが付属しています。(しかも延長可能)

Microsoft は VfW を非推奨と見なしていますが、それでも完全に使用可能で、DirectShow よりもセットアップが簡単です。

于 2009-07-22T17:58:19.330 に答える