使用同步读取器读取文件
[与此页面关联的功能 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 编写的程序。
- 应用程序会将要读取的文件的名称传递给同步读取器。 同步读取器打开文件时,会为每个流分配一个输出编号。 如果文件使用互斥,则读取器为所有互斥流分配单个输出。
- 应用程序从读取器获取有关各种输出的配置的信息。 收集的信息将使应用程序能够正确呈现媒体示例。
- 应用程序开始从同步读取器一次请求一个示例。 同步读取器在提供 INSSBuffer 接口的缓冲区对象中传递每个示例。
- 应用程序负责在读取器传送数据后呈现数据。 Windows 媒体格式 SDK 不提供任何呈现例程。 通常,应用程序将使用其他 SDK 来呈现数据,例如 Microsoft Direct X SDK 或 Microsoft Windows 平台 SDK的多媒体功能。
WMSyncReader 示例应用程序中演示了这些步骤。 有关详细信息,请参阅 示例应用程序。
同步读取器还支持更高级的功能。 使用同步读取器可以执行以下操作:
- 指定要按时间或帧编号检索的样本范围。
- 控制互斥流的流选择。
- 使用标准 COM 接口 IStream 打开文件。
- 从文件标头读取配置文件数据。
- 从文件标头读取元数据。
- 播放期间在流和输出示例之间切换。
- 播放期间,在压缩和未压缩流样本之间切换。
以下部分详细介绍了同步读取器对象的使用。
- 创建同步读取器并打开文件
- 查找流编号和输出编号
- 使用同步读取器检索媒体示例
- 使用同步读取器按时间查找
- 使用同步读取器按帧编号查找
- 使用同步读取器按 SMPTE 时间代码查找
- 使用同步读取器检索流示例
- 使用同步读取器检索压缩样本
示例代码
以下示例代码演示如何使用同步读取器从 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;
相关主题