ファイルの形式の検出

デバイスにファイルを送信する前に、アプリケーションはデバイスがそのファイル形式をサポートしているかどうかを判断する必要があります。

ファイルの形式の検出は複雑な場合があります。 最も簡単な方法は、特定のWMDM_FORMATCODE列挙値にマップされたファイル拡張子のリストを作成することです。 ただし、このシステムにはいくつかの問題があります。1 つは、1 つの形式に複数の拡張子 (JPEG 画像の場合は .jpg、.jpe、.jpeg など) を含めることができるということです。 また、同じファイル拡張子は、さまざまな形式に対応するさまざまなプログラムで使用できます。

厳密なマッピングの制限を克服するには、アプリケーションで形式が拡張機能と一致することを確認することをお勧めします。 DirectShow SDK には、アプリケーションがほとんどのメディア ファイルの種類に関する限られた詳細セットを検出できるようにするツールが用意されています。 Windows Media Format SDK では、多数の詳細が公開されますが、ASF ファイルについてのみ公開されます。 すべてのファイルの種類には、可能であればフォーマット コードを検証する必要があるため、DirectShowを使用して基本的なフォーマット コードを検出または検証し、Windows Media Format SDK を使用して、ASF ファイルに関して必要な追加のメタデータを検出することをお勧めします。 DirectShowを使用して、ASF 以外のファイルの基本的なメタデータを検出することもできます。

拡張機能マッピングとDirectShowを使用してファイル形式を検出する方法の 1 つを次に示します。

まず、ファイル名拡張子を既知の拡張子の一覧と比較します。 比較では大文字と小文字を区別しないようにしてください。 拡張機能がマップされていない場合は、形式をWMDM_FORMATCODE_UNDEFINEDに設定します。

  • フォーマット コードが見つからない場合 (または、ファイルがメディア ファイルであることを確認する場合) は、次の手順を実行できます。
    1. CoCreateInstance(CLSID_MediaDet) を使用して DirectShow Media Detector オブジェクトを作成し、IMediaDet インターフェイスを取得します。
    2. IMediaDet::p ut_Filename を呼び出してファイルを開きます。 ファイルが保護されている場合、この呼び出しは失敗します。
    3. AM_MEDIA_TYPEを返す IMediaDet::get_StreamMediaType を呼び出して、既定のストリームのメディアの種類を取得します。
    4. IMediaDet::get_OutputStreams を呼び出してストリームの数を取得します。
      • ストリームが 1 つのみでオーディオの場合、ファイルの種類はWMDM_FORMATCODE_UNDEFINEDAUDIO
      • ストリームが 1 つのみでビデオの場合、ファイルの種類はWMDM_FORMATCODE_UNDEFINEDVIDEO
      • ストリームが 1 つのみで、ビデオでビット レートが 0 の場合、ファイルの種類はWMDM_FORMATCODE_WINDOWSIMAGEFORMAT。

また、get_StreamMediaTypeから取得した VIDEOINFOHEADER または WAVEFORMATEX メンバーからオーディオまたはビデオ コーデックを照合することもできます。

次の C++ 関数は、ファイル拡張子の照合とDirectShowを使用して不明なファイルを分析する方法を示しています。

// For IMediaDet, you must link to strmiids.lib. Also include the following:
//#include <Qedit.h>  // for IMediaDet declaration.
//#include <Dshow.h>  // for VIDEOINFOHEADER declaration.
WMDM_FORMATCODE CWMDMController::myGetWMDM_FORMATCODE(LPCWSTR pFileName)
{
    HRESULT hr = S_OK;

    // Declare the variable to hold the WMDM format code.
    WMDM_FORMATCODE fmt = WMDM_FORMATCODE_UNDEFINED;
    
    // Get the file extension.
    wstring ext = pFileName;
    ext = ext.substr(ext.find_last_of(L".") + 1);

    // This is not an exhaustive list. 
    // It is also case-sensitive.
    if (ext == L"js" || ext == L"vb")
        fmt = WMDM_FORMATCODE_SCRIPT;
    else if (ext == L".exe")
        fmt = WMDM_FORMATCODE_EXECUTABLE;
    else if (ext == L"txt")
        fmt = WMDM_FORMATCODE_TEXT;
    else if (ext == L"html" || ext == L"htm" || ext == L"shtm")
        fmt = WMDM_FORMATCODE_HTML;
    else if (ext == L"aiff")
        fmt = WMDM_FORMATCODE_AIFF;
    else if (ext == L"wav")
        fmt = WMDM_FORMATCODE_WAVE;
    else if (ext == L"mp3")
        fmt = WMDM_FORMATCODE_MP3;
    else if (ext == L"mpg" || ext == L"mpeg" || ext == L"mp2")
        fmt = WMDM_FORMATCODE_MPEG;
    else if (ext == L"bmp")
        fmt = WMDM_FORMATCODE_IMAGE_BMP;
    else if (ext == L"avi")
        fmt = WMDM_FORMATCODE_AVI;
    else if (ext == L"asf")
        fmt = WMDM_FORMATCODE_ASF;
    else if (ext == L"tif")
        fmt = WMDM_FORMATCODE_IMAGE_TIFF;
    else if (ext == L"gif")
        fmt = WMDM_FORMATCODE_IMAGE_GIF;
    else if (ext == L"pct")
        fmt = WMDM_FORMATCODE_IMAGE_PICT;
    else if (ext == L"png")
        fmt = WMDM_FORMATCODE_IMAGE_PNG;
    else if (ext == L"wma")
        fmt = WMDM_FORMATCODE_WMA;
    else if (ext == L"wpl")
        fmt = WMDM_FORMATCODE_WPLPLAYLIST;
    else if (ext == L"asx")
        fmt = WMDM_FORMATCODE_ASXPLAYLIST;
    else if (ext == L"m3u")
        fmt = WMDM_FORMATCODE_M3UPLAYLIST;
    else if (ext == L"wmv")
        fmt = WMDM_FORMATCODE_WMV;
    else if (ext == L"jpg" || ext == L"jpeg" || ext == L"jpe")
        fmt = WMDM_FORMATCODE_IMAGE_EXIF;
    else if (ext == L"jp2")
        fmt = WMDM_FORMATCODE_IMAGE_JP2;
    else if (ext == L"jpx" || ext == L"jpf")
        fmt = WMDM_FORMATCODE_IMAGE_JPX;

    // If we couldn't get the type from the extension, perhaps DirectShow 
    // can determine the type. You could also modify this to verify that 
    // the major media type matches the file extension (for example, that 
    // a .gif file has a video image stream with a bit rate of zero).
    if (fmt == WMDM_FORMATCODE_UNDEFINED)
    {
        CComPtr<IMediaDet> pIMediaDet;
        hr = pIMediaDet.CoCreateInstance(CLSID_MediaDet, NULL);
        if (hr == S_OK && pIMediaDet != NULL)
        {
            hr = pIMediaDet->put_Filename(BSTR(pFileName));
            if (FAILED(hr)) return WMDM_FORMATCODE_UNDEFINED;

            AM_MEDIA_TYPE mediaType;
            if (hr == S_OK)
            {
                hr = pIMediaDet->get_StreamMediaType(&mediaType);
                CHECK_HR(hr, 
                  "get_StreamMediaType succeeded in myGetWMDM_FORMATCODE.", 
                  "get_StreamMediaType failed in myGetWMDM_FORMATCODE.");
            }

            if (hr == S_OK)
            {
                LONG numStreams = 0;
                hr = pIMediaDet->get_OutputStreams(&numStreams);

                // If there is at least one video stream, the file is video. 
                // If there are only audio streams, it is audio.
                // Loop through all streams or until first video stream is found.
                for (int i = 0; i < numStreams; i++)
                {
                    // Choices are either VIDEOINFOHEADER or WAVEFORMATEX. 
                    // VIDEOINFOHEADER2 is not supported.
                    if (IsEqualGUID(mediaType.formattype, 
                        FORMAT_VideoInfo))
                    {
                        VIDEOINFOHEADER* data = 
                            (VIDEOINFOHEADER*) mediaType.pbFormat;

                        // If only one stream and there was no matching 
                        // extension, it is undefined video. If no 
                        // bit rate, it's a still image.
                        if (data->dwBitRate == 0) fmt = 
                            WMDM_FORMATCODE_WINDOWSIMAGEFORMAT;
                        else fmt = WMDM_FORMATCODE_UNDEFINEDVIDEO;
                        break; // Found video--any additional streams are soundtracks.
                    }
                    if (IsEqualGUID(mediaType.formattype, FORMAT_WaveFormatEx))
                    {
                        // If only one stream and there was no matching 
                        // extension, it is undefined audio. 
                        if (fmt == WMDM_FORMATCODE_UNDEFINED)
                        {
                            fmt = WMDM_FORMATCODE_UNDEFINEDAUDIO;
                        }
                        WAVEFORMATEX* data = 
                            (WAVEFORMATEX*) mediaType.pbFormat;
                    }
                } // Loop through streams.
            }     // Got a stream media type.
        }         // Created a media detector object.
    }
    return fmt;
}

デバイスへのファイルの書き込み