Bagikan melalui


Mengikat Simpul Output ke Sink Media

Topik ini menjelaskan cara menginisialisasi simpul output dalam topologi, jika Anda menggunakan pemuat topologi di luar Sesi Media. Simpul output awalnya berisi salah satu dari yang berikut ini:

Dalam kasus terakhir, penunjuk IMFActivate harus dikonversi ke penunjuk IMFStreamSink sebelum pemuat topologi menyelesaikan topologi. Dalam sebagian besar skenario, prosesnya berfungsi sebagai berikut:

  1. Aplikasi mengantrekan topologi parsial pada Sesi Media.
  2. Untuk semua simpul output, Sesi Media mengonversi penunjuk IMFActivate ke penunjuk IMFStreamSink . Proses ini disebut mengikat simpul output ke sink media.
  3. Sesi Media mengirimkan topologi yang dimodifikasi ke metode IMFTopoLoader::Load .

Namun, jika Anda menggunakan pemuat topologi secara langsung (di luar sessi media), aplikasi Anda harus mengikat simpul output sebelum memanggil IMFTopoLoader::Load. Untuk mengikat simpul output, lakukan hal berikut:

  1. Panggil IMFTopologyNode::GetObject untuk mendapatkan penunjuk objek simpul.
  2. Kueri penunjuk objek untuk antarmuka IMFStreamSink . Jika panggilan ini berhasil, tidak ada lagi yang harus dilakukan, jadi lewati langkah-langkah yang tersisa.
  3. Jika langkah sebelumnya gagal, kueri penunjuk objek untuk antarmuka IMFActivate .
  4. Buat sink media dengan memanggil IMFActivate::ActivateObject. Tentukan IID_IMFMediaSink untuk mendapatkan penunjuk ke antarmuka IMFMediaSink sink media.
  5. Kueri simpul untuk atribut MF_TOPONODE_STREAMID . Nilai atribut ini adalah pengidentifikasi sink aliran untuk simpul ini. Jika atribut MF_TOPONODE_STREAMID tidak diatur, pengidentifikasi aliran default adalah nol.
  6. Sink aliran yang sesuai mungkin sudah ada di sink media. Untuk memeriksa, panggil IMFMediaSink::GetStreamSinkById di sink media. Jika sink aliran ada, metode mengembalikan penunjuk ke antarmuka IMFStreamSink-nya . Jika panggilan ini gagal, coba tambahkan sink streaming baru dengan memanggil IMFMediaSink::AddStreamSink. Jika kedua panggilan gagal, itu berarti sink media tidak mendukung pengidentifikasi aliran yang diminta, dan simpul topologi ini tidak dikonfigurasi dengan benar. Kembalikan kode kesalahan dan lewati langkah berikutnya.
  7. Panggil IMFTopologyNode::SetObject, melewati pointer IMFStreamSink dari langkah sebelumnya. Panggilan ini menggantikan penunjuk objek simpul, sehingga simpul berisi penunjuk ke sink aliran, bukan penunjuk ke objek aktivasi.

Kode berikut menunjukkan cara mengikat simpul output.

// BindOutputNode
// Sets the IMFStreamSink pointer on an output node.

HRESULT BindOutputNode(IMFTopologyNode *pNode)
{
    IUnknown *pNodeObject = NULL;
    IMFActivate *pActivate = NULL;
    IMFStreamSink *pStream = NULL;
    IMFMediaSink *pSink = NULL;

    // Get the node's object pointer.
    HRESULT hr = pNode->GetObject(&pNodeObject);
    if (FAILED(hr))
    {
        return hr;
    }

    // The object pointer should be one of the following:
    // 1. An activation object for the media sink.
    // 2. The stream sink.

    // If it's #2, then we're already done.

    // First, check if it's an activation object.
    hr = pNodeObject->QueryInterface(IID_PPV_ARGS(&pActivate));

    if (SUCCEEDED(hr))
    {
        DWORD dwStreamID = 0;

        // The object pointer is an activation object. 
        
        // Try to create the media sink.
        hr = pActivate->ActivateObject(IID_PPV_ARGS(&pSink));

        // Look up the stream ID. (Default to zero.)

        if (SUCCEEDED(hr))
        {
           dwStreamID = MFGetAttributeUINT32(pNode, MF_TOPONODE_STREAMID, 0);
        }

        // Now try to get or create the stream sink.

        // Check if the media sink already has a stream sink with the requested ID.

        if (SUCCEEDED(hr))
        {
            hr = pSink->GetStreamSinkById(dwStreamID, &pStream);
            if (FAILED(hr))
            {
                // Try to add a new stream sink.
                hr = pSink->AddStreamSink(dwStreamID, NULL, &pStream);
            }
        }

        // Replace the node's object pointer with the stream sink. 
        if (SUCCEEDED(hr))
        {
            hr = pNode->SetObject(pStream);
        }
    }
    else
    {
        // Not an activation object. Is it a stream sink?
        hr = pNodeObject->QueryInterface(IID_PPV_ARGS(&pStream));
    }

    SafeRelease(&pNodeObject);
    SafeRelease(&pActivate);
    SafeRelease(&pStream);
    SafeRelease(&pSink);
    return hr;
}

Catatan

Contoh ini menggunakan fungsi SafeRelease untuk merilis penunjuk antarmuka.

 

Contoh berikutnya menunjukkan cara mengikat semua simpul output dalam topologi. Contoh ini menggunakan metode IMFTopology::GetOutputNodeCollection untuk mendapatkan kumpulan simpul output dari topologi. Kemudian memanggil fungsi yang ditunjukkan dalam contoh sebelumnya pada setiap simpul tersebut secara bergantian.

// BindOutputNodes
// Sets the IMFStreamSink pointers on all of the output nodes in a topology.

HRESULT BindOutputNodes(IMFTopology *pTopology)
{
    DWORD cNodes = 0;

    IMFCollection *pCol = NULL;
    IUnknown *pUnk = NULL;
    IMFTopologyNode *pNode = NULL;

    // Get the collection of output nodes. 
    HRESULT hr = pTopology->GetOutputNodeCollection(&pCol);
    
    // Enumerate all of the nodes in the collection.
    if (SUCCEEDED(hr))
    {
        hr = pCol->GetElementCount(&cNodes);
    }

    if (SUCCEEDED(hr))
    {
        for (DWORD i = 0; i < cNodes; i++)
        {
            hr = pCol->GetElement(i, &pUnk);

            if (FAILED(hr)) { break; }

            hr = pUnk->QueryInterface(IID_IMFTopologyNode, (void**)&pNode);

            if (FAILED(hr)) { break; }

            // Bind this node.
            hr = BindOutputNode(pNode);

            if (FAILED(hr)) { break; }
        }
    }

    SafeRelease(&pCol);
    SafeRelease(&pUnk);
    SafeRelease(&pNode);
    return hr;
}

Bangunan Topologi Tingkat Lanjut

Sink Media

IMFTopoLoader