DVD テキスト文字列の操作

[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayerIMFMediaEngineAudio/Video Capture を使用することを強くお勧めします。 Microsoft は、レガシ API を使用する既存のコードを、可能であれば新しい API を使用するように書き換えるよう提案しています。]

一部の DVD ディスク (特にカラオケ ディスク) には、ビデオまたはオーディオ コンテンツを補完するテキスト文字列の一覧が含まれている場合があります。 これらのテキスト文字列には、曲のタイトル、アーティスト名、ジャンル情報など、コンテンツに関するメタデータが含まれています。 テキスト文字列は、複数の言語で存在できます。 これらの文字列は省略可能であり、多くのディスクには含まれていません。

DVD からテキスト文字列を取得するには、DVD ナビゲーターによって公開される IDvdInfo2 インターフェイスを使用 します。 実際には、テキスト文字列を取得するために DVD 再生グラフを作成する必要はありません。 DVD ナビゲーターを作成し、DVD ボリュームを設定してから、関連するテキスト文字列メソッドを呼び出すことができます。

メソッド 説明
IDvdInfo2::GetDVDTextNumberOfLanguages テキスト文字列がある言語の数を取得します。
IDvdInfo2::GetDVDTextLanguageInfo 1 つの言語のテキスト文字列に関する情報を取得します。
IDvdInfo2::GetDVDTextStringAsUnicode 指定した言語のテキスト文字列をインデックスで取得します。
IDvdInfo2::GetDVDTextStringAsNative テキスト文字列を生のバイト配列として取得します。 テキスト文字列で GetDVDTextStringAsUnicode でサポートされていない文字エンコードを使用する場合は、このメソッドを使用します。

 

テキスト文字列を取得するための基本的な手順を次に示します。

  1. IDvdInfo2::GetDVDTextNumberOfLanguages を呼び出して、テキスト文字列が表示される言語の合計数を検索します。 数値が 0 の場合は、DVD にテキスト文字列がないことを意味します。 (これはおそらく最も一般的なケースです。実際には)。
  2. 言語の数が 1 つ以上の場合は、 IDvdInfo2::GetDVDTextLanguageInfo を呼び出して、各言語に関する情報を取得します。 言語はインデックスによって指定されます。 メソッドは、その言語のテキスト文字列の合計数、言語のロケール識別子 (LCID)、および文字エンコード (Unicode またはその他) を返します。 DVD テキスト文字列では、いくつかの異なる文字セットを使用できます。これらは、「 DVD_TextCharSet列挙」に記載されています。
  3. テキスト文字列を取得するには、 IDvdInfo2::GetDVDTextStringAsUnicode または IDvdInfo2::GetDVDTextStringAsNative を呼び出します。 最初のメソッドはワイド文字列を返しますが、すべての文字セットをサポートしているわけではありません。 2 番目のメソッドは、生テキスト データを含むバイト配列を返します。 どちらのメソッドでも、 NULL バッファー ポインターを使用して メソッドを呼び出して、文字列のサイズとテキスト型を検索できます。 次に、バッファーを割り当て、 メソッドをもう一度呼び出して文字列を取得します。

各テキスト文字列には、テキスト文字列の意味を示す識別子コードが関連付けられています。 識別子は、 DVD_TextStringType 値として返されます。 識別子には、構造体識別子とコンテンツ 識別子の 2 つのカテゴリ があります。 構造体識別子には、0x00から0x02Fの範囲に数値コードがあります。 コンテンツ識別子には、0x30以上の範囲があります。 ( DVD_TextStringType 列挙は最も一般的な識別子のサブセットを定義しますが、 IDvdInfo2 メソッドは任意の識別子コードを返すことができます)。構造体識別子は、DVD の論理部分 (ボリューム、タイトル、タイトルの一部 (PTT) など) を表します。 コンテンツ識別子は、映画のタイトル、曲のタイトル、ジャンルなど、特定のテキスト文字列の意味を示します。

構造体識別子には、関連付けられたテキスト文字列がありません。 構造体識別子がテキスト文字列データに表示されると、次の構造体識別子まで、次のテキスト文字列が DVD の論理部分に適用されることを通知します。 テキスト・データ内の構造体 ID の位置は、DVD ボリュームの論理階層に対応します。 たとえば、DVD_Struct_Title識別子 (0x02) の最初の出現箇所はボリューム内の最初のタイトルを表し、次の出現箇所は 2 番目のタイトルを表します。

次の表は、2 つのタイトルを持つ 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) "" 2 番目のタイトルの構造体識別子。
DVD_General_Name (0x30) "Title 2" 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 フォーラムの Web サイトを参照してください。

DVDSample アプリケーションの CDvdCore::GetDvdText メソッドは、DVD テキスト文字列を列挙および表示する基本的な手順を示しています。

DVD アプリケーション