探索檔案的格式
將檔案傳送到裝置之前,應用程式應該先判斷裝置是否支援該檔案格式。
探索檔案的格式可能十分複雜。 最簡單的方法是建立對應至特定WMDM_FORMATCODE列舉值的副檔名清單。 不過,此系統有一些問題:一種是單一格式可以有多個延伸模組 (,例如.jpg、.jpe 和 .jpeg,適用于 JPEG 映射) 。 此外,不同的程式也可以針對不同的格式使用相同的副檔名。
若要克服嚴格對應的限制,最好讓應用程式確認格式符合延伸模組。 DirectShow SDK 提供工具,可讓應用程式探索大部分媒體檔案類型的一組有限詳細資料。 Windows 媒體格式 SDK 會公開大量詳細資料,但只公開 ASF 檔案。 因為所有檔案類型都應該盡可能驗證其格式代碼,因此最好使用 DirectShow 來探索或驗證基本格式程式碼,並使用 Windows 媒體格式 SDK 來探索 ASF 檔案所需的任何其他中繼資料。 DirectShow 也可以用來探索非 ASF 檔案的基本中繼資料。
以下是使用延伸模組對應和 DirectShow 探索檔案格式的其中一種方式。
首先,比較副檔名與已知副檔名的清單。 請務必讓您的比較不區分大小寫。 如果未對應延伸模組,請將格式設定為 WMDM_FORMATCODE_UNDEFINED。
- 如果找不到格式代碼 (,或您想要確認檔案是媒體檔案) ,您可以執行下列步驟:
- 使用 CoCreateInstance (CLSID_MediaDet) 和擷取 IMediaDet 介面建立 DirectShow Media Detector 物件。
- 呼叫 IMediaDet::p ut_Filename來開啟檔案。 如果檔案受到保護,此呼叫將會失敗。
- 呼叫 IMediaDet::get_StreamMediaType,以取得預設資料流程的媒體類型,這會傳回 AM_MEDIA_TYPE。
- 呼叫 IMediaDet::get_OutputStreams以取得資料流程數目。
- 如果只有一個資料流程且它是音訊,則檔案類型會WMDM_FORMATCODE_UNDEFINEDAUDIO
- 如果只有一個資料流程,而且是影片,則檔案類型會WMDM_FORMATCODE_UNDEFINEDVIDEO
- 如果只有一個資料流程,而且它是視訊,且位元速率為零,則檔案類型會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;
}
相關主題