使用媒体缓冲区 (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;
}

媒体缓冲区

Media Foundation 平台 API