共用方式為


探索檔案的格式

將檔案傳送到裝置之前,應用程式應該先判斷裝置是否支援該檔案格式。

探索檔案的格式可能十分複雜。 最簡單的方法是建立對應至特定WMDM_FORMATCODE列舉值的副檔名清單。 不過,此系統有一些問題:一種是單一格式可以有多個延伸模組 (,例如.jpg、.jpe 和 .jpeg,適用于 JPEG 映射) 。 此外,不同的程式也可以針對不同的格式使用相同的副檔名。

若要克服嚴格對應的限制,最好讓應用程式確認格式符合延伸模組。 DirectShow SDK 提供工具,可讓應用程式探索大部分媒體檔案類型的一組有限詳細資料。 Windows 媒體格式 SDK 會公開大量詳細資料,但只公開 ASF 檔案。 因為所有檔案類型都應該盡可能驗證其格式代碼,因此最好使用 DirectShow 來探索或驗證基本格式程式碼,並使用 Windows 媒體格式 SDK 來探索 ASF 檔案所需的任何其他中繼資料。 DirectShow 也可以用來探索非 ASF 檔案的基本中繼資料。

以下是使用延伸模組對應和 DirectShow 探索檔案格式的其中一種方式。

首先,比較副檔名與已知副檔名的清單。 請務必讓您的比較不區分大小寫。 如果未對應延伸模組,請將格式設定為 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以取得資料流程數目。
      • 如果只有一個資料流程且它是音訊,則檔案類型會WMDM_FORMATCODE_UNDEFINEDAUDIO
      • 如果只有一個資料流程,而且是影片,則檔案類型會WMDM_FORMATCODE_UNDEFINEDVIDEO
      • 如果只有一個資料流程,而且它是視訊,且位元速率為零,則檔案類型會WMDM_FORMATCODE_WINDOWSIMAGEFORMAT。

您也可以嘗試比對從get_StreamMediaType擷取的VIDEOINFOHEADERWAVEFORMATEX成員的音訊或視訊編解碼器。

下列 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;
}

將檔案寫入裝置