使用媒體緩衝區 (Microsoft Media Foundation)

本主題描述如何使用 IMFMediaBuffer 介面來存取媒體緩衝區中的資料。 所有媒體緩衝區都會公開 IMFMediaBuffer,這是針對任何類型的資料所設計。 未壓縮的視訊畫面是一種特殊案例,如 未壓縮的視訊緩衝區主題所述。

緩衝區大小

媒體緩衝區有兩個與其相關聯的大小:

  • 最大長度是配置給緩衝區的記憶體實體大小。 建立緩衝區且在緩衝區存留期間不會變更時,就會設定此值。 最大長度表示可以儲存在緩衝區中的資料量。 若要尋找大小上限,請呼叫 IMFMediaBuffer::GetMaxLength

  • 目前的長度是目前在緩衝區中的有效資料量。 第一次配置緩衝區時,目前的長度為零,因為緩衝區中沒有有效的資料。 如果您將任何資料寫入緩衝區,則必須呼叫 IMFMediaBuffer::SetCurrentLength來更新目前的長度。 例如,如果您將資料 100 個位元組寫入緩衝區,請以值 100 呼叫 SetCurrentLength 。 如果您從媒體緩衝區讀取資料,請呼叫 IMFMediaBuffer::GetCurrentLength 來找出緩衝區中目前有多少資料。 請勿讀取超過目前的長度。 目前長度永遠不能超過緩衝區的最大長度。

存取緩衝區記憶體

若要存取緩衝區中的記憶體,請呼叫 IMFMediaBuffer::Lock。 這個方法會傳回記憶體區塊開頭的指標。 它也會傳回最大長度和目前的長度。 當您使用指標完成時,請呼叫 IMFMediaBuffer::Unlock

若要將資料寫入媒體緩衝區:

  1. 呼叫 IMFMediaBuffer::Lock 以取得記憶體的指標。 方法也會傳回緩衝區的最大長度。
  2. 將資料寫入記憶體中,最多到緩衝區的最大長度。
  3. 呼叫 IMFMediaBuffer::SetCurrentLength 以更新目前的長度。 將目前的長度設定為等於您在步驟 2 中撰寫的資料量。
  4. 呼叫 IMFMediaBuffer::Unlock 以解除鎖定緩衝區。

若要從媒體緩衝區讀取資料:

  1. 呼叫 IMFMediaBuffer::Lock 以取得記憶體的指標。 方法也會傳回緩衝區的目前長度, (緩衝區) 的有效資料量。
  2. 讀取記憶體的內容,最多到目前的長度。
  3. 呼叫 IMFMediaBuffer::Unlock 以解除鎖定緩衝區。

建立系統記憶體緩衝區

系統記憶體緩衝區是管理系統記憶體區塊的媒體緩衝區。 若要建立此物件的實例,請呼叫 MFCreateMemoryBufferMFCreateAlignedMemoryBuffer 並指定緩衝區大小。 這兩個函式都會配置記憶體區塊,並傳回 IMFMediaBuffer 指標。 當媒體緩衝區的參考計數達到零且物件終結時,會自動釋放記憶體。

下列範例示範如何建立系統記憶體緩衝區並寫入緩衝區。

HRESULT CreateSystemMemoryBuffer(
    BYTE *pSrc, 
    DWORD cbData, 
    IMFMediaBuffer **ppBuffer
    )
{
    HRESULT hr = S_OK;
    BYTE *pData = NULL;

    IMFMediaBuffer *pBuffer = NULL;

    // Create the media buffer.
    hr = MFCreateMemoryBuffer(
        cbData,   // Amount of memory to allocate, in bytes.
        &pBuffer        
        );

    // Lock the buffer to get a pointer to the memory.
    if (SUCCEEDED(hr))
    {
        hr = pBuffer->Lock(&pData, NULL, NULL);
    }

    if (SUCCEEDED(hr))
    {
        memcpy_s(pData, cbData, pSrc, cbData);
    }

    // Update the current length.
    if (SUCCEEDED(hr))
    {
        hr = pBuffer->SetCurrentLength(cbData);
    }

    // Unlock the buffer.
    if (pData)
    {
        hr = pBuffer->Unlock();
    }

    if (SUCCEEDED(hr))
    {
        *ppBuffer = pBuffer;
        (*ppBuffer)->AddRef();
    }

    return hr;
}

媒體緩衝區

媒體基礎平臺 API