使用 DVD 文本字符串
[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayer、 IMFMediaEngine 和 Media Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayer、 IMFMediaEngine 和 音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]
某些 DVD 光盘(尤其是卡拉OK光盘)可能包含文本字符串列表,以补充视频或音频内容。 这些文本字符串包含有关内容的元数据,例如歌曲标题、艺术家姓名、流派信息等。 文本字符串可以以多种语言提供。 这些字符串是可选的,许多光盘没有这些字符串。
若要从 DVD 检索文本字符串,请使用由 DVD 导航器公开的 IDvdInfo2 接口。 实际上不需要生成 DVD 播放图来检索文本字符串。 只需创建 DVD 导航器、设置 DVD 卷,然后调用相关的文本字符串方法:
方法 | 说明 |
---|---|
IDvdInfo2::GetDVDTextNumberOfLanguages | 获取具有文本字符串的语言数。 |
IDvdInfo2::GetDVDTextLanguageInfo | 获取有关一种语言的文本字符串的信息。 |
IDvdInfo2::GetDVDTextStringAsUnicode | 按索引获取指定语言的文本字符串。 |
IDvdInfo2::GetDVDTextStringAsNative | 获取文本字符串作为原始字节数组。 如果文本字符串使用 GetDVDTextStringAsUnicode 不支持的字符编码,请使用此方法。 |
下面是获取文本字符串的基本过程:
- 调用 IDvdInfo2::GetDVDTextNumberOfLanguages 查找文本字符串所显示语言的总数。 如果数字为零,则表示 DVD 没有任何文本字符串。 (这也许是最常见的情况,事实上。)
- 如果语言数量至少为一种,请调用 IDvdInfo2::GetDVDTextLanguageInfo 以获取有关每种语言的信息。 语言由索引指定。 方法返回该语言的文本字符串总数、语言的区域设置标识符 (LCID) ,以及字符编码 (Unicode 或其他) 。 DVD 文本字符串可以使用多个不同的字符集;这些项列在 DVD_TextCharSet枚举中。
- 若要获取文本字符串,请调用 IDvdInfo2::GetDVDTextStringAsUnicode 或 IDvdInfo2::GetDVDTextStringAsNative。 第一个方法返回宽字符字符串,但不支持每个字符集。 第二个方法返回包含原始文本数据的字节数组。 对于这两种方法,可以使用 NULL 缓冲区指针调用 方法,以查找字符串的大小和文本类型。 然后分配缓冲区并再次调用 方法以获取字符串。
每个文本字符串都有一个关联的标识符代码,该代码指示文本字符串的含义。 标识符作为 DVD_TextStringType 值返回。 标识符有两个类别: 结构标识符 和 内容标识符。 结构标识符在0x00-0x02F范围内具有数字代码。 内容标识符的范围0x30及更高。 (DVD_TextStringType 枚举定义最常见标识符的子集,但 IDvdInfo2 方法可以返回任何标识符代码。) 结构标识符描述 DVD 的逻辑部分,例如卷、游戏或部分游戏 (PTT) 。 内容标识符指示特定文本字符串的含义,例如电影标题、歌曲标题或流派。
结构标识符没有关联的文本字符串。 当结构标识符出现在文本字符串数据中时,它会指示以下文本字符串应用于 DVD 的逻辑部分,直到下一个结构标识符。 结构标识符在文本数据中的位置对应于 DVD 卷的逻辑层次结构。 例如,DVD_Struct_Title标识符的第一个匹配项 (0x02) 表示卷中的第一个标题,下一个匹配项表示第二个标题。
下表显示了如何为具有两个标题的 DVD 定义文本字符串。
DVD_TextStringType | 文本字符串 | 说明 |
---|---|---|
DVD_Struct_Volume (0x01) | "" | 整个光盘端的结构标识符。 |
DVD_General_Name (0x30) | “DVD 卷” | DVD 卷名称。 |
DVD_Struct_Title (0x02) | "" | 第一个游戏的结构标识符。 |
DVD_General_Name (0x30) | “标题 1” | 第一个游戏的名称。 |
DVD_Struct_Title (0x02) | "" | 第二个游戏的结构标识符。 |
DVD_General_Name (0x30) | “标题 2” | 第二个标题的名称。 |
GetDVDTextStringAsUnicode 和 GetDVDTextStringAsNative 方法将结构标识符和内容标识符视为相同。 唯一的区别在于,对于结构标识符,关联的文本缓冲区为空。 由应用程序来跟踪文本字符串与 DVD 逻辑部分之间的关系。
以下示例演示如何从 DVD 获取文本字符串。 此示例忽略实际应用程序需要的某些详细信息。 (例如,它忽略结构标识符。) 该示例仅用于显示正确的调用序列。
#define CHECK_HR(hr) if (FAILED(hr)) { goto done; }
#define SAFE_ARRAY_DELETE(x) { if (x != NULL) { delete [] x; x = NULL; } }
HRESULT GetDVDTextStrings()
{
HRESULT hr = S_OK;
ULONG cLangs = 0; // Number of languages.
ULONG cStrings = 0; // Number of text strings.
ULONG cchBuffer = 0; // Buffer size.
ULONG cchActual = 0; // Actual string size.
LCID lcid; // Locale identifier.
DVD_TextCharSet characterSet;
DVD_TextStringType stringType;
WCHAR *pszBuffer = NULL;
CComPtr<IBaseFilter> pFilter;
CComPtr<IDvdInfo2> pInfo;
CComPtr<IDvdControl2> pControl;
// Set up the DVD Navigator.
CHECK_HR(hr = pFilter.CoCreateInstance(CLSID_DVDNavigator));
CHECK_HR(hr = pFilter.QueryInterface(&pInfo));
CHECK_HR(hr = pFilter.QueryInterface(&pControl));
CHECK_HR(hr = pControl->SetDVDDirectory(NULL));
// Find the number of text-string languages.
CHECK_HR(hr = pInfo->GetDVDTextNumberOfLanguages(&cLangs));
if (cLangs == 0)
{
return S_FALSE; // No text strings.
}
// Get information about the 0'th language.
CHECK_HR(hr = pInfo->GetDVDTextLanguageInfo(
0, &cStrings, &lcid, &characterSet));
// First check if this character set is compatible with the
// GetDVDTextStringAsUnicode method.
if (characterSet == DVD_CharSet_Unicode ||
characterSet == DVD_CharSet_ISO646)
{
// Loop through all of the strings.
for (ULONG i = 0; i < cStrings; i++)
{
// Get the i'th string for the 0'th language.
// Find the required buffer size and the string type.
CHECK_HR(hr = pInfo->GetDVDTextStringAsUnicode(
0, // Language index.
i, // String index.
NULL, // Pass NULL pointer to get the buffer size.
0, // Size of the buffer we are passing in.
&cchBuffer, // Receives the required buffer size.
&stringType // Receives the identifier code.
));
// Skip structure identifiers (0x00 - 0x2F).
if ((cchBuffer > 0) && (stringType >= 0x30))
{
// Allocate a buffer and get the text string.
pszBuffer = new WCHAR[cchBuffer];
if (pszBuffer == NULL)
{
CHECK_HR(hr = E_OUTOFMEMORY);
}
CHECK_HR(hr = pInfo->GetDVDTextStringAsUnicode(
0, i, pszBuffer, cchBuffer, &cchActual, &stringType));
// TODO: Display the text string.
SAFE_ARRAY_DELETE(pszBuffer);
}
}
}
done:
SAFE_ARRAY_DELETE(pszBuffer);
return hr;
}
有关 DVD 文本字符串的信息,请参阅 DVD 论坛的网站。
DVDSample 应用程序中的 CDvdCore::GetDvdText 方法演示枚举和显示 DVD 文本字符串的基本步骤。
相关主题