星期二, 5月 15, 2007

yamdi 的Windows porting

最近似乎找東西都還蠻順利的,一些以前找不到的資訊,最近都找到解答了。像是使用自由軟體來產生 Flash video (FLV) 的方式,最近也找到了,而且還是使用我個人偏好的 mencoder 來達成。這個等我下一篇 blog 再詳述。

yamdi 是 Yet Another MetaData Injector 的縮寫。這個軟體的作用主要是用來在使用某些軟體轉換出來的 Flash Video (FLV) 檔案中,插入一些缺乏的 metadata,使檔案可以在 flash video player 上快轉和倒帶等等。這個軟體本來是針對 Un*x 平台,使用 C 語言所寫的,原作者也還沒有放出可以在 Win32 上使用的版本。相同功能的自由軟體還有一個叫做 flvtool2 的軟體,不過是用 Ruby 寫的,而我不會 Ruby,也懶得為了跑一個 script 而去裝一套我可能不會再去用的直譯器。Win32 下倒是還有其他的 freeware 可以用,例如 flvmdi,但 flvmdi 不是自由軟體,事實上根據網頁的說明,甚至不算是 freeware。

昨晚發現了 yamdi 這個 C 語言的自由軟體實做,下載回來看,發現其實程式碼不長。雖然作者在網頁上只說了這個軟體能夠在 *BSD 和 Linux 上跑(作者在 FreeBSD、MacOS、以及 Ubuntu Linux 上試過),但沒有提到到底行不行在 Win32 的環境上編譯。看到這種小程式,當然就要實際拿到 MinGW 上試試看啦!使用 MinGW 也是我的個人偏好,雖然移植 Un*x 程式到 Win32 上用 Cygwin 會簡單很多,但畢竟有一種隔靴搔癢的感覺.....回歸正題,使用 MinGW 的 MSys 環境,呼叫 GCC 去編譯時,馬上就發現了為何不能在 Win32 上編譯的主要原因:該程式使用到了 mmap() 這個記憶體映射函式。yamdi 的作者會使用 mmap() 的理由其實很明顯,他覺得 flvtool2 是把整個 FLV 檔案載入到記憶體中處理,這樣對檔案很大時,就會很慢又吃光記憶體。不過問題出在 MinGW 並沒有實做 mmap() 這個函式,所以這個程式在沒有修改的狀況下,沒辦法在 MinGW 上編譯通過。除了 mmap() 這個主要的問題外,還有使用到了 bzero() 這個也是 MinGW 沒有定義的函式,以及存取到了 /dev/null 這個在 native Win32 下不存在的裝置檔案。

我對 Win32 API 可以說是個門外漢,事實上對於用 MinGW 寫純的 Win32 程式也只是略知一二而已,所以這種情況下,當然只好拜請古狗大神啦 XD bzero() 和/dev/null 的問題好解決,根據 bzero() 的 manpage,bzero() 做的事情就只是把某塊記憶體空間填滿 0,因此可以用 memset() 來取代。至於 /dev/null,根據在 DOS 時代的記憶,以及以前做過的試驗,在 Win32 下可以使用 "nul"這個特殊的虛擬檔案來取代。剩下最麻煩的是 mmap() 了。查了好幾下 Google,Win32 API 中,與 mmap() 類似的對應函式是 CreateFileMapping() 以及 MapViewOfFile() 這兩個函式的組合。根據從 Google 找到的一個 libgda 的 MinGW porting 的 patch,我依樣畫葫蘆的,很快的改好了第一個可以編譯的版本。不過很不幸的,事情沒有這麼簡單。這樣依樣畫葫蘆的結果是,CreateFileMapping() 每次都會失敗。翻了一堆 MSDN 的網頁,也看了幾個範例程式,本來以為問題只是單純的參數或者旗標設錯。呼叫 GetLastError() 取得錯誤代碼後,發現是 File handle 錯誤。這下頭大了,我完全是照著該 patch 的邏輯,把 fopen() 回傳的指標,使用 fileno() 轉換成 file descriptor 之後,再強制型別轉換成 HANDLE 類型,難道這樣做不行嗎?經過幾次使用 gdb 去看一些變數的內容後,我決定放棄這條途徑,改用 MSDN 裡面建議的 CreateFile() 這個 API 來開啟檔案,直接取得 CreateFileMapping() 能夠接受的 file handle,這樣總不會錯了吧?又經過一些修改,總算產生了一個可以運作的版本啦!

經過一連串的找找改改,程式是編出來了,但到底能不能正常運作呢?當然要實際測試一下才知道了。找了一個很短的影像檔,先用 mencoder 轉換成 FLV 格式,然後再用我編出來的 yamdi.exe 來插入 metadata,最後再用另一個 flash video 播放器的自由軟體 -- FlowPlayer 來測試,果然成功,可以正常快轉和倒帶等等。辛苦還是有代價的。確定成功之後,我做了個 patch,並貼上該計畫網頁的 patch 頁面去了。

好久沒有這樣改程式了,加上 Win32 API 我本來就不熟,看了一堆 MSDN 的網頁,頭好昏啊 :P

沒有留言: