如何判別是否為 DRM 的 ASF 檔案?

如何判別一個 ASF 檔案是否為 DRM 的 ASF 檔案?
詳情資料可以參考微軟提供的 Specification: Advanced Systems Format (ASF) Specification
大致上很簡單,一個 ASF 檔案主要有三個部分: Header Object, Data Object, Index Object.
而每個部分又各由不同的 Object 所組成.
要分辨是否為 DRM,主要是在 Header Object 裡面找尋是否有 Content Encryption Object.
那麼要怎麼找尋呢?? OK, 每個 Object 的最前面有唯一的 GUID,你可以依據 GUID 來找到.
而這些,你都可以在 Specification 的後面幾張找到 ( 或者你可以搜尋 ASF GUIDs ).
至此,寫起來並不太困難.程式碼如下:

typedef unsigned long UINT32;
typedef unsigned short UINT16;
typedef unsigned char UINT8;
typedef int BOOL;
enum BOOLEAN
{
FALSE = 0,
TRUE
};
typedef struct GUID_s
{
UINT32 id1;
UINT16 id2;
UINT16 id3;
UINT16 id4;
UINT8 id5[6];
}GUID;
//Content Encryption Object
GUID ASF_Content_Encryption_Object_guid =
{
0x2211b3fb,
0xbd23,
0x11d2,
0xb7b4,
{
0x00, 0xa0, 0xc9, 0x55, 0xfc, 0x6e
}
};
/*
typedef struct ContentEncryptionObject_s
{
GUID objectID;
UINT32 objectSize; // objectSize should be QWORD, 8 bytes, but CCS has not this type.
UINT32 objectSize1;
UINT32 secretDataLength;
BYTE* secretData; // according secretDataLength
UINT32 protectionTypeLength;
char* protectionType;
UINT32 keyIDLength;
char* keyID;
UINT32 licenseURLLength;
char* licenseURL;
}ContentEncryptionObject_t;
*/
//extern CF_FILE* filePtrR;
typedef FILE CF_FILE;
CF_FILE* filePtrR;
long
FILEr_ftell()
{
return ftell( filePtrR );
}
int
FILEr_fseek( long filepos, int whence)
{
return fseek( filePtrR, filepos, whence );
}
long
FILEr_fread( UINT8* ptr, long length )
{
return fread( ptr, 1, length, filePtrR );
}
char* SDRAM_HOLE = NULL;
BOOL
isASFDRM( )
{
long filePos;
char* spaceForParsing = (char*)( SDRAM_HOLE + 0x800000 ); // use the space after 8 MB, prevent conflict
int GUIDLen = sizeof( GUID );
int iter, len = 0;
BOOL bFound = FALSE, bResult = FALSE;
UINT32 headerObjectSize = 0;
UINT32 secretDataLength=0;
UINT32 protectionTypeLength=0;
char* protectionType=NULL;
long readLen=0;
char* encryptionPos = NULL;
// save file position
filePos = FILEr_ftell();
// seek to the start position
FILEr_fseek( 16, 0); //SEEK_SET
FILEr_fread( (UINT8*)&headerObjectSize, 4 ); // we should read 8 here, but ….
// read all header object
// then search the specified GUID, use pattern compare
FILEr_fseek( 0, 0 ); // SEEK_SET
readLen = FILEr_fread( spaceForParsing, headerObjectSize );
len = headerObjectSize – GUIDLen;
// searching.
for( iter = 0; iter objectID
encryptionPos = spaceForParsing + iter;
// ( encryptionPos + GUIDLen ) ==> objectSize
// ( encryptionPos + GUIDLen + 8 ) ==> secretDataLength
secretDataLength = (UINT32) *( encryptionPos + GUIDLen + 8 );
// ( spaceForParsing + iter + GUIDLen + 8 + 4 ) ==> secretData
// ( spaceForParsing + iter + GUIDLen + 12 + secretDataLength ) ==> protectionTypeLength;
protectionTypeLength = (UINT32) *(encryptionPos + GUIDLen + 12 + secretDataLength );
protectionType = (char*) (encryptionPos + GUIDLen + 12 + secretDataLength + 4 );
if( strncmp( protectionType, “DRM”, 3 ) == 0 )
bResult = TRUE;
OnFinally:
// restore file position
FILEr_fseek( filePos, 0); //SEEK_SET
// return result.
return bResult;
}
int main(int argc, char* argv[])
{
SDRAM_HOLE = (char*) malloc( 0x800000 * 2 );
filePtrR = fopen( “00 Cannot Play.wma”, “rb” );
if( isASFDRM() )
printf(“is a drm file.\n”);
else
printf(“not a drm file.\n”);
fclose( filePtrR );
return 0;
}

ok, 程式裡面你會發現一些奇怪的地方,是的,因為我需要在 embedded 環境下運作,所以為了符合環境,所以做了一些調整,不過你還是可以在 Visual C++ 上來運行這段代碼.
看不順眼的,就自己調整吧…
這份 specification 其實斷斷續續看一陣子了,都沒怎麼專心看,不過昨天看的時候,突然開竅了,於是就把這麼一段代碼搞定了.
真神奇啊….

來到崑山

昨天晚上來到公司在崑山的廠區,即將在這裡呆三個星期….(希望是只有三個星期…)
剛來的第一個印象,就是…..我又收假了嗎??
感覺上跟以前在鳳山步校當兵的時候一樣,廠區大大的,也是切割成一塊一塊的~~
真的是太像了.
大致上該帶的東西都帶了,唯一的誤算是天氣,有些涼,沒想像中那麼的熱.
看來得每天洗冷水澡,增強抵抗力了.

不知所云

數週前….
小E:”啊~~整個改成這樣子以後,這邊可能會有問題….”
小E:”嗯…..怎麼辦…先記起來好了….到時候再說…”
今天…
H哥:”喔~~這邊沒辦法試播放影片!!小E,該怎麼辦??”
小E:”我知道這邊,我想一下…”
H哥:”這邊當初沒想到,這不能怪你…”
小E:”我想可以這樣子作…”
H哥:”我想也是這樣子…”
不知道為什麼….
小E:”我早就知道了…”
H哥:(驚愕貌…)”你早就知道了?!”
小E:”我的意思是…”
(一陣混亂….)
事後…
小E, 你在講什麼啊?!
就裝傻說不知道就好啦…

跳槽到 CentOS 3.4

昨天把家裡的 server 從原來的WBEL 改為 CentOS 了.
跳槽的原因….嗯….沒什麼特別的,只因為 CentOS 的 mailing list 比較活躍,更新速度感覺上也比較快.
步驟也是簡單到不行….CentOS 官方網站上有提供FAQ.
照步驟作,網路夠快,裝的套件也不多的話,很快就裝完了…
下次的目標是從 3.4 升級到 4, 不過看起來有蠻多困難的. 畢竟 kernel 換到 2.6 ,處理 hardware 的方式也變了挺多的, 找了一下,大部分都建議燒成光碟片,以光碟開機來作昇級.
再找時間試試看吧.

Upgrade to MediaWiki 1.4.4

鬼混了很久,終於把家裡的 wiki 升級到 1.4.4 了.
升級方法還挺簡單的.
1. 備份你的 LocalSettings.php / AdminSettings.php
2. 把下載來的 MediaWiki 1.4.4 tarball 解壓以後整個蓋過去.
3. 切到 maintenance 目錄下, 執行 php update.php
4. 收工.
真的很簡單吧….
下個目標是把 VFP Wiki 升級到 1.4.4 …

從拍戲看 XP

出自:藍藍的 movie blog – 拍戲沒劇本
轉貼一部分…

首先,他說:「我是編劇出身的,當然知道劇本的重要,但是我更清楚,真正的電影不是在紙上完成的,所有的劇本只是個藍圖,在拍攝的過程裡一定會有改動。」
其次,王家衛強調:「電影上有些東西是無法用文字說明白的,例如一種表情,怎麼用文字說它呢?有時候就是一個特寫,比千言萬語更重要,男女主角為什麼會相愛,只要鏡頭讓你感到他們會相愛,那就對了。電影就是要讓你看見,讓你相信。」
第三點呢,王家衛的說法是:「在拍攝《手》的過程裡,我先拿「薄暮的舞女」原著小說給鞏俐看,告訴她簡單的故事大概,告訴她我打算怎麼拍,然後我就儲一路寫劇本,開工前就交給演員,有時候會再改,會再修。對演員來說最困難的是她可能無法知道每一場戲之間的相互關係,她不能控制故事的流程,只能一場接一場地演。」

看完這篇文章,發現這些導演幹的就是 XP (Extreme Programming) 呀~~
先捉出一個大方向,每天早上決定接下來要作的東西,晚上驗收.
很像,不是嗎??