当前位置: 代码迷 >> 综合 >> Microsoft Media Foundation官方文档翻译(22)《Media Samples》
  详细解决方案

Microsoft Media Foundation官方文档翻译(22)《Media Samples》

热度:14   发布时间:2024-01-06 15:46:18.0

官方英文文档链接:https://docs.microsoft.com/en-us/windows/desktop/medfound/media-samples

基于05/31/2018

 

本篇包含了 Media Sample 的所有内容

Media Samples

  • 05/31/2018
  • 2 minutes to read

media sample 是一种包含零或多个有序 buffer 的对象。Media samples 公开 IMFSample 接口。一个 sample 中包含的数据量取决于创建这个 sample 的组件和 buffer 中的数据类型。对于未压缩的视频帧,一个 sample 通常只包含一帧图像。对于未压缩的音频,数据量可能会有所不同(没理解),但通常一个音频帧不会跨越两个 sample。对于压缩过的数据,这些准则可能不适用。

出于效率原因考虑,一个 sample 可能包含多个 buffer。例如,在 ASF 文件里,一帧视频可能被分在多个 ASF 包里。media source 会将这些包读进不同的 buffer 中,而不是将他们拼到一个 buffer 中,source 只是简单地把这些 buffer 放到同一个 sample 中。然后,下游的组件可以决定是否将这些小的 buffer 合并到一个大的 buffer 中。通常,如果要编写 pipeline 组件,就应该假定任何 sample 都可能存有多个 buffer。

下面介绍以下两方面内容

Topic Description
Working with Media Samples 介绍 media samples 的一些方法。
Video Samples 介绍一种专门为存储未压缩视频帧而设计的 IMFSample 实现。

 

Working with Media Samples

  • 05/31/2018
  • 2 minutes to read

此部分介绍如何使用 IMFSample 接口来操作 media sample 对象。media samples 的概述,参考 Media Samples。

要创建一个新的 media sample,调用 MFCreateSample 方法。最开始,sample 的 buffer 列表是空的。要添加一个 buffer,调用 IMFSample::AddBuffer

下面展示了如何创建一个 sample 以及添加一个 buffer。

HRESULT CreateMediaSample(DWORD cbData, IMFSample **ppSample)
{HRESULT hr = S_OK;IMFSample *pSample = NULL;IMFMediaBuffer *pBuffer = NULL;hr = MFCreateSample(&pSample);if (SUCCEEDED(hr)){hr = MFCreateMemoryBuffer(cbData, &pBuffer);}if (SUCCEEDED(hr)){hr = pSample->AddBuffer(pBuffer);}if (SUCCEEDED(hr)){*ppSample = pSample;(*ppSample)->AddRef();}SafeRelease(&pSample);SafeRelease(&pBuffer);return hr;
}

要从 sample 中获取 buffer,建议调用 IMFSample::ConvertToContiguousBuffer。此方法会返回一个 (contiguous)buffer。

要遍历列表中的 buffer,先调用 IMFSample::GetBufferCount。这个方法返回 buffer 的数量。然后使用序号调用 IMFSample::GetBufferByIndex。buffer 从 0 开始编号。

下面的代码演示了如何遍历一个 sample 中的 buffer。

IMFMediaBuffer *pBuffer = NULL;
DWORD cBuffers = 0;hr = pSample->GetBufferCount(&cBuffers);if (SUCCEEDED(hr))
{for (DWORD i = 0; i < cBuffers; i++){hr = pSample->GetBufferByIndex(i, &pBuffer);// Use buffer (not shown).SafeRelease(&pBuffer);if (FAILED(hr)){break;}}
}

samples 有一个时间戳(time stamp)和持续时间(duration)。时间戳表示了这个 sample 应该何时被渲染(相对于 presentation clock)。持续时长表示一个 sample 显示的持续时间。通常是生成数据的组件来设置时间戳和持续时间。这些值可能会被 Media Session 修改。要设置时间戳,调用 IMFSample::SetSampleTime。要设置持续时间,调用 IMFSample::SetSampleDuration

Sample 也可以有 attributes,包含一些 sample 的额外信息。关于 sample attributes 的详细信息,参考 Sample Attributes。要使用 attribute,使用 IMFAttributes Interface 接口,IMFSample 继承了前者。

 

Video Samples

  • 05/31/2018
  • 2 minutes to read

video sample 是一种为了与 Enhanced Video Renderer (EVR) 一起使用,IMFSample 接口的专门实现。要创建一个这种实例,调用 MFCreateVideoSampleFromSurface 方法。此方法接受一个 Direct3D surface 指针,返回一个指向 IMFSample 接口的指针。以下几种对象应该使用此方法来申请 sample:

  • 自定义的 EVR presenters(演示器?)。一个 presenter 申请 video samples 然后把它们传递给 mixer(混合器?) 的 IMFTransform::ProcessOutput 方法。更多信息参考 How to Write an EVR Presenter。

  • 支持视频加速(硬件?还是单纯的播放速度video acceleration)的视频解码器。更多信息参考 Supporting DXVA 2.0 in Media Foundation。

video sample 实现了以下接口:

  • IMFSample

  • IMFDesiredSample

  • IMFTrackedSample

如果 MFCreateVideoSampleFromSurface 的 pUnkSurface 参数为非NULL,那么这个 video sample 会包含一个封装了  Direct3D surface 的 buffer。这个 buffer 会有以下限制:

  • 这个 buffer 的 IMFMediaBuffer::Lock 方法会返回 E_NOTIMPL。

  • 这个 buffer 没有实现 IMF2DBuffer 接口。

从 buffer 访问 surface 的唯一方法是调用 IMFGetService::GetService,使用标识 MR_BUFFER_SERVICE。

如果 pUnkSurface 参数为 NULL,则这个 video sample 就不包含 buffer。要添加一个 buffer,按下面的步骤:

  1. 创建一个 Direct3D surface。

  2. 通过调用 MFCreateDXSurfaceBuffer 来通过 surface 创建一个 buffer。详细信息参考 DirectX Surface Buffer。

  3. 调用 IMFSample::AddBuffer 来把 buffer 添加到 sample。

如果要通过 IMF2DBuffer 接口访问 surface,请使用此方法。(?没看懂,后面少了内容还是指的上面的方法?)

 

  相关解决方案