使用同步读取器读取文件

[与此页面关联的功能 Windows Media Format 11 SDK 是旧版功能。 它已被源读取器和接收器编写器取代。 源读取器和接收器编写器已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用源读取器和接收器编写器,而不是 Windows Media Format 11 SDK。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

可以使用同步读取器(而不是读取器对象中的异步方法)来读取 ASF 文件。 使用同步调用可以减少读取文件所需的线程数。 异步读取器使用多个线程来处理流。 对于具有多个流的文件,使用的线程数可能会变得非常大。 同步读取器仅使用一个线程。

同步读取器旨在满足内容创建和文件编辑应用程序的需求。 可以将同步读取器用于其他应用程序,但其功能有限。

同步读取器可以使用 UNC 路径名称 ((例如“\\someshare\somedirectory\somefile.wmv”) )打开本地文件或网络上的文件。 不能将文件流式传输到同步读取器,也不能从 Internet 位置打开文件。 同步读取器还支持使用 IStream COM 接口作为源。

与异步读取器相比,同步读取器为从 ASF 文件检索样本提供了更多的通用性。 同步读取器可以按流号和输出提供示例。 可以通过流编号传递的示例进行压缩或取消压缩。 同步读取器还可以在播放期间在压缩和未压缩传递之间切换;此功能称为“快速编辑”。此功能使编辑应用程序能够读取基于 Windows Media 的内容,并将其直接传递给编写器,直到达到所需的帧。 此时,应用程序可以告知读取者开始传送未压缩的内容,然后应用程序可以对其进行修改并传递给编写器进行重新压缩。 当应用程序完成对指定帧的修改后,它可以告知读取器再次开始传送压缩帧。

同步读取器对象的最基本的功能可以分解为以下步骤。 在这些步骤中,“应用程序”是指使用 Windows 媒体格式 SDK 编写的程序。

  1. 应用程序会将要读取的文件的名称传递给同步读取器。 同步读取器打开文件时,会为每个流分配一个输出编号。 如果文件使用互斥,则读取器为所有互斥流分配单个输出。
  2. 应用程序从读取器获取有关各种输出的配置的信息。 收集的信息将使应用程序能够正确呈现媒体示例。
  3. 应用程序开始从同步读取器一次请求一个示例。 同步读取器在提供 INSSBuffer 接口的缓冲区对象中传递每个示例。
  4. 应用程序负责在读取器传送数据后呈现数据。 Windows 媒体格式 SDK 不提供任何呈现例程。 通常,应用程序将使用其他 SDK 来呈现数据,例如 Microsoft Direct X SDK 或 Microsoft Windows 平台 SDK的多媒体功能。

WMSyncReader 示例应用程序中演示了这些步骤。 有关详细信息,请参阅 示例应用程序

同步读取器还支持更高级的功能。 使用同步读取器可以执行以下操作:

  • 指定要按时间或帧编号检索的样本范围。
  • 控制互斥流的流选择。
  • 使用标准 COM 接口 IStream 打开文件。
  • 从文件标头读取配置文件数据。
  • 从文件标头读取元数据。
  • 播放期间在流和输出示例之间切换。
  • 播放期间,在压缩和未压缩流样本之间切换。

以下部分详细介绍了同步读取器对象的使用。

示例代码

以下示例代码演示如何使用同步读取器从 ASF 文件读取示例。 它按帧编号指定要传递的样本范围。

IWMSyncReader* pSyncReader = NULL;
INSSBuffer*    pMyBuffer   = NULL;

QWORD cnsSampleTime = 0;
QWORD cnsSampleDuration = 0;
DWORD dwFlags = 0;
DWORD dwOutputNumber;
HRESULT hr = S_OK;

// Initialize COM.
hr = CoInitialize(NULL);

// Create a synchronous reader.
hr = WMCreateSyncReader(NULL, WMT_RIGHT_PLAYBACK, &pSyncReader);

// Open an ASF file.
hr = pSyncReader->Open(L"c:\\somefile.wmv");

// TODO: Identify the properties for each output. This works 
// exactly as it does with the asynchronous reader.

// Specify a playback range from frame number 100 of the video 
// stream to the end of the file. Assume that the video stream 
// is stream number 2.
hr = pSyncReader->SetRangeByFrame(2, 100, 0);

// Loop through all the samples in the specified range.
do
{
   // Get the next sample, regardless of its stream number.
   hr = pSyncReader->GetNextSample(0,
                                   &pMyBuffer,
                                   &cnsSampleTime,
                                   &cnsSampleDuration,
                                   &dwFlags,
                                   &dwOutputNumber,
                                   NULL);

   if(SUCCEEDED(hr))
   {
      // TODO: Process the sample in whatever way is appropriate 
      // to your application. When finished, clean up.
      pMyBuffer->Release();
      pMyBuffer = NULL;
      cnsSampleTime     = 0;
      cnsSampleDuration = 0;
      dwFlags           = 0;
      dwOutputNumber    = 0;
   }
} 
while (SUCCEEDED(hr));

pSyncReader->Release();
pSyncReader = NULL;

IWMSyncReader 接口

读取 ASF 文件

同步读取器对象