使用 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