ファイルの形式の検出

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

ファイルの形式の検出は複雑になる可能性があります。 最も簡単な方法は、特定のWMDM_FORMATCODE列挙値にマップされたファイル拡張子のリストを作成することです。 ただし、このシステムにはいくつかの問題があります。1 つは、1 つの形式に複数の拡張子 (.jpg、.jpe、JPEG 画像の場合は .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) を使用して、IMediaDet インターフェイスを取得して DirectShow Media Detector オブジェクトを作成します。
    2. IMediaDet::p ut_Filename を呼び出してファイルを開きます。 ファイルが保護されている場合、この呼び出しは失敗します。
    3. IMediaDet::get_StreamMediaType を呼び出して、既定のストリームのメディアの種類を取得します。これは、AM_MEDIA_TYPEを返します。
    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;
}

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