使用标记

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

标记是 ASF 文件中的命名点。 每个标记由一个名称和一个关联时间组成,以与文件开头的偏移量度量。 应用程序可以使用标记为内容中的不同点分配名称,向用户显示这些名称,然后查找标记位置。 应用程序可以在现有 ASF 文件中添加或删除标记。

IWMHeaderInfo 接口包含用于处理标记的方法。 元数据编辑器对象支持添加和删除标记。 编写器和读取器对象可以检索标记,但不能添加或删除标记。

添加标记

若要添加标记,请在元数据编辑器中查询 IWMHeaderInfo 接口。 然后调用 IWMHeaderInfo::AddMarker 方法,将标记名称指定为宽字符字符串,时间以 100 纳秒为单位。 时间不得超过文件持续时间。 两个标记可以具有相同的时间。

以下示例将多个标记添加到文件:

IWMMetadataEditor *pEdit = 0;
IWMHeaderInfo     *pInfo = 0;

// Create the metadata editor object.

WMCreateEditor(&pEdit);
pEdit->Open(L"C:\\example.wmv");
pEdit->QueryInterface(IID_IWMHeaderInfo, (void**)&pInfo);

// Add the markers. Note that we add the last ones first. Do this when possible
// for improved performance when writing the markers to the file.
hr = pInfo->AddMarker(L"End",  520000000);   // 52 sec.
hr = pInfo->AddMarker(L"Segue",  350000000); // 35 sec.
hr = pInfo->AddMarker(L"Intro",  15000000);  // 1.5 sec.

// Commit changes and clean up.

pEdit->Flush();
pEdit->Close(); 
pInfo->Release();
pEdit->Release();

删除标记

若要删除标记,请调用 IWMHeaderInfo::RemoveMarker,指定要删除的标记的索引。 标记按时间顺序自动排序,因此索引 0 始终是第一个标记。 请注意,调用 RemoveMarker 会更改后续任何标记的索引号。 以下代码(其中 pInfo 是指向 IWMHeaderInfo 接口的指针)从文件中删除所有标记:

WORD count = 0;
pInfo->GetMarkerCount(&count);
while (count--)
{
    pInfo->RemoveMarker(0);
}

检索标记

若要检索标记的名称和时间,请执行以下步骤:

  1. 调用 IWMHeaderInfo::GetMarkerCount 方法以确定文件包含的标记数。
  2. 检索包含标记名称所需的字符串大小。 为此,请调用 IWMHeaderInfo::GetMarker 方法。 指定要检索的标记的索引, (pwszMarkerName 参数) 为字符串缓冲区的 NULL。 方法返回字符串的长度,包括 pcchMarkerNameLen 参数中的终止“\0”字符。
  3. 分配一个宽字符字符串以接收名称。
  4. 再次调用 GetMarker ,但这次传递 pwszMarkerName 参数中字符串的地址。 方法将标记名称写入字符串,并在 pcnsMarkerTime 参数中返回标记时间。

以下代码按顺序循环访问每个标记,并检索名称和时间:

WORD cMarkers = 0;
HRESULT hr = pInfo->GetMarkerCount(&cMarkers);

WCHAR *wszName = 0;
WORD  len = 0;
for (WORD iMarker = 0; iMarker < cMarkers; ++iMarker)
{
    QWORD rtTime = 0;
    WORD req_len = 0;
    hr = pInfo->GetMarker(iMarker, 0, &req_len, &rtTime);
    
    // Reallocate if necessary.
    if (len < req_len)
    {
        delete[] wszName;
        wszName = new WCHAR[req_len];
        len = req_len;
    }
    hr = pInfo->GetMarker(iMarker, wszName, &req_len, &rtTime);
    // Display the name...
}
delete[] wszName;

查找标记

若要从标记位置开始播放,请调用读取器对象的 IWMReaderAdvanced2::StartAtMarker 方法,指定标记的索引。 其余参数与 IWMReader::Start 方法的参数相同。 以下示例查询 IWMReaderAdvanced2 接口的读取器,并查找第一个标记。

IWMReaderAdvanced2 *pReader2 = 0
WORD iMarkerIndex = 0;
hr = pReader->QueryInterface(IID_IWMReaderAdvanced2, (void**)&pReader2);
if (SUCCEEDED(hr))
{
    hr = pPlayer2->StartAtMarker(iMarkerIndex, 0, 1.0, 0);
    pPlayer2->Release();
}

IWMHeaderInfo 接口

IWMReaderAdvanced2::StartAtMarker

使用元数据