史萊姆論壇

返回   史萊姆論壇 > 教學文件資料庫 > 作業系統操作技術文件
忘記密碼?
論壇說明

歡迎您來到『史萊姆論壇』 ^___^

您目前正以訪客的身份瀏覽本論壇,訪客所擁有的權限將受到限制,您可以瀏覽本論壇大部份的版區與文章,但您將無法參與任何討論或是使用私人訊息與其他會員交流。若您希望擁有完整的使用權限,請註冊成為我們的一份子,註冊的程序十分簡單、快速,而且最重要的是--註冊是完全免費的!

請點擊這裡:『註冊成為我們的一份子!』

Google 提供的廣告


 
 
主題工具 顯示模式
舊 2004-02-23, 10:04 PM   #1
psac
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設 如何讓Windows Media Player播放你的自訂媒體檔案類型 

正文
有時候,我們會產生自訂的媒體文件(不同於標準的AVI、MPEG等文件格式)。為了回放這些特殊格式的文件,於是,我們不得不再寫一個播放器。那麼,有沒有一種辦法,讓Windows Media Player能夠認識我們的文件,進而讓它像播放其他標準文件一樣播放我們的文件呢?答案是肯定的。

Windows Media Player是關於DirectShow架構來播放媒體文件的。我們只要從DirectShow方面入手,就一定能夠解決問題。首先,我們來看看一般的播放文件的處理程序。大家知道,使用DirectShow播放媒體文件,肯定要新增一個Filter Graph。給定了一個文件路徑,首先是要找到一個合適的Source Filter,即得到它的CLSID。一般只需使用IGraphBuilder::RenderFile或者IGraphBuilder::AddSourceFilter就能做到。那麼,Filter Graph Manager(以下簡稱為FGM)的實現細節是怎麼樣的呢?瞭解這些,對我們解決問題有著決定性的作用。

首先要分析一下文件路徑,因為它可能包含有傳輸協定(譬如http、htp等)。FGM認為冒號前面的即為傳輸協定名。例如文件路徑為「 myprotocol://myfile.ext」,則myprotocol即為傳輸協定名。於是,FGM到註冊表的如下位置去找這個傳輸協定:
HKEY_CLASSES_ROOT
<protocol>
Source Filter = <Source filter CLSID>
Extensions
<.ext1> = <Source filter CLSID>
<.ext2> = <Source filter CLSID>
如果找到了這個傳輸協定,並且存在Extensions子鍵,FGM再到Extensions子鍵中進行文件副檔名的匹配。如果匹配成功,FGM就用這個找到的GUID字串串作為Source Filter的CLSID;如果不成功,FGM就使用該傳輸協定子鍵下的Source Filter的值。如果myprotocol這個傳輸協定並沒有在註冊表中註冊,FGM就預設使用一個叫File Source (URL)的Filter。另外,有兩點注意:(1)為了區別傳輸協定和驅動器磁碟代號(如C:\myfile.ext),FGM不承認單字串的傳輸協定;(2)字串串「file:」或「 file://」不認為是傳輸協定。

如果文件路徑中不包含傳輸協定呢?FGM就分析文件的副檔名,即到註冊表的HKEY_CLASSES_ROOT\Media Type\Extensions下去匹配。相應的副檔名子鍵下指定了Source Filter的CLSID字串串,有的還有Media Type和Subtype指定Source Filter輸出Pin上使用的Media Type。但是,如果這種文件的副檔名在這裡也沒有註冊呢?FGM還有最後一招,就是通過文件的校驗字元(Check Bytes)去判斷。這些校驗字元在如下位置定義:
HKEY_CLASSES_ROOT\MediaType\{major type}\{subtype}
典型的如下:
{e436eb83-524f-11ce-9f53-0020af0ba770}
{7364696D-0000-0010-8000-00AA00389B71}
0 "0,4,,52494646,8,4,,524D4944"
1 "0,4,,4D546864"
Source Filter "{E436EBB5-524F-11CE-9F53-0020AF0BA770}"
開啟註冊表,我們可以看到MediaType有一個{e436eb83-524f-11ce-9f53-0020af0ba770}子鍵,即為MEDIATYPE_Stream,它下面又定義了一系列的Subtype,有{e436eb88-524f-11ce-9f53-0020af0ba770}(MEDIASUBTYPE_Avi)、{e436eb84-524f-11ce-9f53-0020af0ba770}(MEDIASUBTYPE_MPEG1System)等。在Subtype子鍵下,我們還可以看到一些子鍵,其中編號為0,1,2…的即是定義的校驗字元,Source Filter即為定義的相應的CLSID。校驗字元定義塊一般的格式為:offset,cb,mask,val,意思為在文件頭偏移offset字元處讀取cb個字元的資料,將其與mask做位與操作,結果等於val即表示匹配。如果定義的mask為空,可以不做位與操作;如果offset為負數,表示從文件尾開始計算偏移;如果一個子鍵有多個定義塊,則所有的定義塊都匹配才能算這個子鍵匹配;如果有多個子鍵用於校驗字元的定義,那麼任何一個匹配就表示Source Filter的匹配。如果註冊表中定義的所有校驗字元都不能匹配,FGM最後就只能預設新增一個叫File Source (Async.)的Filter,Media Type使用{MEDIATYPE_Stream, MEDIASUBTYPE_None}。

找好Source Filter之後,FGM在這個Filter上得到IFileSourceFilter接頭,通過其接頭方法IFileSourceFilter::Load載入將要播放的這個媒體文件(或者URL)。然後Render這個Source Filter的所有Output pin,完成Filter Graph的構造。

知道了以上原理後,我們就可以採取原則了。針對我們自訂的媒體文件,我們可以開發一個Pull模式的「Parser Filter」。這個Filter必須實現一個Pull模式的Input pin,Filter完成的主要功能還有:從File Source中讀取資料;分析資料,如果是音視瀕交互格式的,則要把它們分離,然後從不同的Output pin輸出;實現IMediaSeeking接頭;回應Quality Control消息等。另外,我們還要保證「Parser Filter」輸出的資料,系統中有相應的Decoder進行解碼(如果沒有,我們要寫自己的Decoder)。注意,註冊這個「Parser Filter」(以及相應的Decoder)時,要讓它(們)的Merit值大於MERIT_DO_NOT_USE。這種處理方法,我們不在註冊表中寫額外的信息。在文件回放時,FGM使用預設的File Source (Async.) Filter作為Source Filter,而後面接上我們的「Parser Filter」(以及相應的Decoder)。

另外一種解決方法,我們可以寫一個Push模式的Source Filter。這個Filter類可以從CSource類中繼承;Filter完成的功能包括:讀取文件內容,如果是音視瀕交互格式,則將它們分離後從不同的Output pin輸出,實現IFileSourceFilter接頭,實現IMediaSeeking接頭,回應Quality Control消息等。(如果我們的Source Filter輸出的資料不是裸資料,而系統中沒有對應的Decoder,那我們也必須自己寫相應的Decoder,類似於第一種處理方法。)這種情況下,要讓FGM自動找到我們的Source Filter,我們就必須在Filter註冊的時候向註冊表中寫入一些額外的信息:可以是註冊文件副檔名,也可以註冊這種文件的校驗字元。下面,筆者給出一種註冊文件副檔名的方法,程式碼參考如下(假設我們的自訂文件副檔名為「.avx」,Source Filter的CLSID為CLSID_MySourceFiler):
STDAPI DllRegisterServer()
{
// Register the ".avx" file extension
DWORD dwDisposition;
DWORD dwReserved = 0;
HKEY hTempKey = (HKEY)0;
TCHAR szKey[] = "Media Type\\Extensions\\.avx";
TCHAR sz類型[] = "Source Filter";
TCHAR szData[100];

WCHAR * pClsid = NULL;
StringFromCLSID(CLSID_MySourceFiler, &pClsid);
WideCharToMultiByte(CP_ACP, 0, pClsid, -1, szData, 100, NULL, NULL);
CoTaskMemFree(pClsid);

DWORD dwBufferLength = lstrlen(szData) * sizeof(TCHAR);
if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, dwReserved,
(太太TSTR)0, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, 0,
&hTempKey, &dwDisposition))
{

// dwBufferLength must include size of terminating nul
// character when using REG_SZ with RegSet類型Ex function
dwBufferLength += sizeof(TCHAR);
::RegSet類型Ex(hTempKey, (太太TSTR)sz類型, dwReserved, REG_SZ,
(太太BYTE)szData, dwBufferLength);
::RegCloseKey(hTempKey);
}

return AMovieDllRegisterServer2( TRUE );
}

STDAPI DllUnregisterServer()
{
// Remove ".avx" file extension registry
HKEY hKey = NULL;
DWORD dw = 0;
TCHAR szKey[] = "Media Type\\Extensions";
if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0L,
NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dw))
{
EliminateSubKey(hKey, ".avx");
::RegCloseKey(hKey);
}

return AMovieDllRegisterServer2( FALSE );
}








正文完
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次
 



發表規則
不可以發文
不可以回覆主題
不可以上傳附加檔案
不可以編輯您的文章

論壇啟用 BB 語法
論壇啟用 表情符號
論壇啟用 [IMG] 語法
論壇禁用 HTML 語法
Trackbacks are 禁用
Pingbacks are 禁用
Refbacks are 禁用

相似的主題
主題 主題作者 討論區 回覆 最後發表
DRM數字版權管Windows Media Rights Manager 1 簡介 psac 作業系統操作技術文件 0 2004-02-20 11:02 AM


所有時間均為台北時間。現在的時間是 07:03 PM


Powered by vBulletin® 版本 3.6.8
版權所有 ©2000 - 2024, Jelsoft Enterprises Ltd.


SEO by vBSEO 3.6.1