共用方式為


處理 DVD 文字字串

[與此頁面相關聯的功能,DirectShow是舊版功能。 它已被 MediaPlayerIMFMediaEngine和媒體基礎中的音訊/視訊擷取 取代。 這些功能已針對 Windows 10 和 Windows 11 進行優化。 Microsoft強烈建議新程式代碼盡可能在媒體 基礎中使用 MediaPlayerIMFMediaEngine 音訊/視訊擷取,而不是 DirectShow。 Microsoft建議使用舊版 API 的現有程式代碼,盡可能改寫成使用新的 API。]

某些 DVD 光碟,特別是卡拉OK光碟,可能包含一份文字字串清單,以補充視訊或音訊內容。 這些文字字串包含內容的相關元數據,例如歌曲標題、藝術家名稱、內容類型資訊等等。 文字字串可以存在於多種語言中。 這些字串是選擇性的,而且許多光碟沒有這些字串。

若要從 DVD 取得文字字串,請使用 IDvdInfo2 介面,這個介面由 DVD 導覽器提供。 您實際上不需要建置 DVD 播放圖形來擷取文字字串。 您可以直接建立 DVD 導覽器、設定 DVD 磁碟區,然後呼叫相關的文字字串方法:

方法 描述
IDvdInfo2::GetDVDTextNumberOfLanguages 取得有文字字串的語言數目。
IDvdInfo2:GetDVDTextLanguageInfo 取得單一語言文字字串的相關信息。
IDvdInfo2::GetDVDTextStringAsUnicode 依索引取得指定語言的文字字串。
IDvdInfo2::GetDVDTextStringAsNative 取得文字字串做為原始位元組陣列。 如果文字字串使用 GetDVDTextStringAsUnicode不支援的字元編碼,請使用這個方法。

 

以下是取得文字字串的基本程式:

  1. 呼叫 IDvdInfo2::GetDVDTextNumberOfLanguages,以尋找文字字元串出現的語言總數。 如果數位為零,表示 DVD 沒有任何文字字串。 (事實上,這可能是最常見的情況。
  2. 如果語言數目至少為一種,請呼叫 IDvdInfo2::GetDVDTextLanguageInfo 以取得每個語言的相關信息。 語言是由索引所指定。 方法會傳回該語言的文字字串總數、語言的地區設定標識碼(LCID),以及字元編碼(Unicode 或其他)。 DVD 文字字串可以使用數個不同的字元集:這些會列在 DVD_TextCharSet 列舉中。
  3. 若要取得文字字串,請呼叫 IDvdInfo2::GetDVDTextStringAsUnicodeIDvdInfo2::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” 第二個標題的名稱。

 

GetDVDTextStringAsUnicodeGetDVDTextStringAsNative 方法會將結構識別符和內容識別符視為相同。 唯一的差別在於結構標識符,相關聯的文字緩衝區是空的。 應用程式必須追蹤文字字串與 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 文字字串的基本步驟。

DVD 應用程式