程式者的胡言亂語
ffqlay at SourceForge.net
我在SourceForge.net上建立了一個叫做ffqlay的專案,並且把ffqlay目前的一些產出都放上去了。你可以從這邊進到這個專案。除了之前提供下載的檔案外,我把製作出來的Win32
DLLs檔案也放上去了,如果你只是個單純的Windows應用程式開發者,不想自己build出這些檔案,它們可以提供一些偷懶的空間。
我使用的ffmpeg原始檔,是取自 “Unofficial FFmpeg Win32 Builds” 中的r13981(這個站不知怎麼了,現在連不上),gcc使用的則是 ”TDM Experimental GCC/MinGW32 Builds”
上的GCC
variables. Libavcodec has been miscompiled and may be very slow or crash. This
is not a bug in libavcodec, but in the compiler. Do not report crashes to
FFmpeg developers.” 的警告訊息)。此外,SDL用的是SDL-1.2.13。
單純的把這些dll檔案和ffqlayDemo的執行檔放在一塊便能夠使其執行。
在這個ffqlay-
int FFQLAY_get_volume(void)
int FFQLAY_set_volume(int
volume)
這兩個用以取得音量以及設定音量的函式。它們並不會改變實際硬體的音量,它們只是單純的利用SDL中的函式,調整audio
sample,藉以控制ffqlay所輸出的音量罷了。
日後若有什麼問題,就直接利用SourceForge的相關機制來討論囉。
文件也會整理出來。:p
Posted at 10:35下午 八月 27, 2008 by Chien-Hsing Wang in General | 迴響[1]
ffqlay API說明
ffqlay以C函式的方式提供一組API,為多媒體檔案的撥放提供支援,在本文中則說明這組API中的函式,以及其作用。
首先是FFQLAY_start(),其原型宣告為:
int FFQLAY_start(int argc, char
**argv, HWND hwndParent, int width, int height);
FFQLAY_start的用途在於啟始多媒體檔案的撥放動作。引數argc以及argv是原ffplay程式中main()自命令引接收的引數,ffplay的使用者可以透過命令列引數設定ffplay選項。在這個最初始的版本中,為了簡化起見,先不更動控制ffplay引數的方式,因此保有原有int argc, char **argv的型式,在日後的階段,將會設計API來支援選項的設定。最簡單的情況,你只需要指定argc為2,而argv[0]為任意名稱,argv[1]為欲撥放的檔案路徑即可。
如果你希望ffqlay的撥放畫面被放置到某視窗下,也就是說讓該視窗成為ffqlay撥放畫面的父視窗時,你可以指定hwndParent為該父視窗的window handle。倘若你沒有這樣的需求,將它指定為NULL即可。
此外,你可以透過width及height引數指定所欲撥放視窗的寬及高,在撥放時會依據你所指定的寬高來呈現影像。
FFQLAY_start在執行之後,會啟動一個執行緒來執行其內部的event_loop(),也就是ffplay原先用來處理各種撥放事件的函式(不過這個函式已經被ffqlay大幅的縮減,日後說明ffqlay的修改時會再說明),因此它並不會遲滯呼叫者所在的執行緒,在啟動撥放動作之後,FFQLAY_start便會返回。
那麼,應用程式要如何知道ffqlay已經撥放完畢呢?讓我們來看看下一個函式:
int
FFQLAY_get_play_state(void);
它有可能回傳(參見ffqlay.h)以下的回傳值:
FFQLAY_PLAY_STATE_PLAYING(1):撥放中
FFQLAY_PLAY_STATE_PAUSED(2):暫停
FFQLAY_PLAY_STATE_ABORT(3):放棄
FFQLAY_PLAY_STATE_STOPPED(4):停止
應用程式可以透過呼叫FFQLAY_get_play_state()來取得目前的狀態。目前ffqlay尚不支援事件的主動通知,所以應用程式無法透過設置callback函式之類的方式來接收撥放狀態的改變。
接著,正如撥放狀態中所展示的,你可以在你的應用程式中暫停或停止撥放的動作,只需分別呼叫:
int FFQLAY_pause(void);
int FFQLAY_stop(void);
你可以透過
double
FFQLAY_get_duration(void);
來取得檔案的撥放長度,回傳的double值其單位為秒。
你可以透過
double
FFQLAY_get_position(void);
來取得檔案目前已撥放的進度,回傳的double值單位同樣是秒。
另一方面,呼叫
int FFQLAY_set_position(double
position);
可以設定撥放位置,單位同樣是秒,這個函式可用來實作撥放時的seek功能。
最後,如果你在撥放的過程中想要變更撥放視窗的大小尺寸,可以使用
int FFQLAY_resize(int width,
int height);
分別傳入欲變更的寬及高,即可達成你的目的。
目前提供的函式就是這麼簡單。在ffqlayDemo專案中展示了如何利用這少數幾個函式即可完成一個典型的多媒體檔案撥放器(當然,GUI極其原始)。
另外,ffqlayDemo中的FFQlay.cs展示了如何在C#中使用ffqlay。它利用System.Runtime.InteropServices中的DllImport,能輕易的在managed的.Net程式中使用unmanaged的Windows DLL函式。所有ffqlay中的C函式,在FFQlay這個C#類別中都有相對應的函式。對於C#程式員來說,如果你不熟悉DllImport,你會發現FFQLAY_start的宣告方式有點意思:
public static extern int
FFQLAY_start(int argc, [MarshalAs(UnmanagedType.LPArray,
ArraySubType=UnmanagedType.LPStr)] IntPtr[] argv, IntPtr hwndParent, int width,
int height);
public static void
FFQLAY_start(string fileName, IntPtr hwndParent, int width, int height)
{
IntPtr[] argv = new IntPtr[2];
argv[0] =
Marshal.StringToHGlobalAnsi("ffqlay.exe");
argv[1] = Marshal.StringToHGlobalAnsi(fileName);
FFQLAY_start(2, argv, hwndParent, width, height);
Marshal.FreeHGlobal(argv[0]);
Marshal.FreeHGlobal(argv[1]);
}
它展示了如何建立char **argv以傳入C函式,並且處理字元集的問題。我對.Net並不熟悉,這是我目前所能找到的最好方法。:)
以上,簡單的說明ffqlay所提供的撥放API。
Posted at 11:09下午 八月 22, 2008 by Chien-Hsing Wang in General | 迴響[0]
工作以外的程式設計
在我們當中的許多程式員,最初踏入程式設計的領域,是基於對程式設計的喜愛。程式設計是一項十分能產生樂趣的活動,有著讓人無法自拔的魔力。我還記得就讀高中的時候,在某次月考前的前夕,好不容易把隔天要應考的科目準備完畢,趕緊衝到電腦前面打開電腦,開始寫起程式來。即便夜已深,且隔天仍有重要的考試,但仍舊像著迷一般的鑽進程式碼構築出來的虛擬世界裡,樂此不疲。程式設計彷彿成了治療考試壓力的最佳良方。
細究起自己之所以喜歡上設計程式,最大的原因應該是透過程式設計所展現出來的創造的力量。透過程式設計達成的創造是一種很特別的型式,因為它完全是虛擬的。我們所寫下的程式碼,雖然沒有物理的存在,但是卻又能夠讓程式的使用者,產生真實的體驗及感受。我相信許多程式員都和我一樣,初入門程式設計的技巧之後,最想做的事情就是撰寫電腦遊戲。背後的主要原因當然不是因為自己想玩自己撰寫出來的遊戲,而是為了要體驗身為造物者的那種感覺。做為電腦遊戲的創造者,你創造出遊戲中的每一項事物,舉凡角色扮演遊戲中的一草一木,射擊遊戲中每一關的大頭目,甚至是俄羅斯方塊中的方塊造型,完全都操控在你的意念之下。透過程式設計的活動,你賦予這一切生命,並使其活躍,在你的遊戲裡,你就是上帝。電腦遊戲的程式設計,無疑的是這種虛擬形式的最佳詮釋。
對我來說,透過撰寫程式所產生的虛擬玩意,能夠進入別人的生活,對別人的生活產生某種真實的影響,就是撰寫程式所能獲得的最大樂趣。
每個喜歡程式設計的人,不盡然都是為著相同的理由喜歡上這個活動。但是,仔細回想,在學習程式設計的那段時日裡,我們心中充滿著對程式設計的熱情,支持我們投入大量的時間,一點一滴的積累程式設計的經驗及技巧。即使程式設計不是我們的工作,我們也把它當做興趣一樣的在經營,即使佔去許多生活的時間,也不覺辛苦。
有一天我們踏入了職場,或許成了所謂的「程式設計師」或「軟體工程師」。程式設計也從業餘的興趣成了專職的工作。我們也許會發現,自己昔日愛上程式設計的那個原因,在專業的軟體分工體系下,早已消失殆盡。在專業的軟體分工體系下,每個人各盡其職,扮演各自的角色。或許是產品經理決定產品的規格及長相,架構師決定整體的架構,系統設計者,設計系統中的類別介面及互動的方式,程式撰寫者,則依據設計進行實作。在這樣的工作模式下,許多程式設計者所追尋的元素都已不復存在。有些程式設計者喜歡的是天馬行空的自由,有些程式設計者和我一樣喜歡的是創造的感覺,但很可惜的,在常見的開發工作中,我們並不容易從中獲取,程式設計者不再能夠自己決定自己想做什麼,我們或許失去了某種型式的自由,也失去了某些創造的感覺。這或者就是一種興趣被工業化後的結果吧。
也許你發現了,或者沒有發現,自己對程式設計的那份熱情日益消退,因為它成了工作的一部份。一方面因為工作帶來的壓力,一方面也因為自己在工作無法取得自己想要的元素。於是,漸漸的,程式設計成了負擔,你猛然發現它再也不是治療壓力的良方,反而成了製造壓力的來源。你開始不喜歡在下班時間撰寫程式,甚至希望撰寫程式的時間愈短愈好。支持你繼續撰寫程式的動力,不再是熱情,也不再是能夠享樂於其中,而是經濟的來源或是在職場中的職務升遷。
我想,這應該是一名程式設計者所會遭遇到的嚴重困境之一了。
程式設計這一項活動,需要以熱情加以灌溉才容易有所成長及茁壯。倘若程式設計這門學問有個終極的道,那麼我相信,你必須投入非常多的時間,才能在通往這個道的路上往前邁一小步。你得投入許多的時間,經歷許許多多看似平凡無奇的事情及經驗,才能有所領悟。或許程式設計領域真有天才,但我寧可相信許多在這個領域中出類拔萃有所成就的人,其成就來自於其熱情而非天份。只有對程式設計懷著高度熱情的人,才能以熱情驅動自己投入更勝於常人的時間及心力。這些時間,不論是用於技巧的反覆鑽研,或是錯誤的嘗試,最後都轉化成為在這門學問上不斷精進的養份來源。
對程式設計喪失熱情,對一名程式設計者能造成極大的傷害,其原因便在於此。當你的熱情消退,便不再願意投入更多的時間,間接的切斷精進養份的供給。或許你就只能在原地踏步,反覆做著自己已經熟悉的事情,但卻是更難再上層樓。即使從現實的角度來看,你的薪資也難以隨著能力的提昇而調漲,職場中向上的動力也有所不足。
我也曾身陷在這樣的泥淖困境中,或許也是在自己程式設計的生涯中的一大低潮。有一天,我突然發現自己其實是失去了熱情,失去了當初那種想要創造一些東西,接著改變許多人生活的動力,因為現實生活中的許多工作,早就壓的自己喘不過氣來。
要拯救自己脫離泥淖,就得找回自己消逝的熱情,要找回消逝的熱情,並不是讓自己遠離撰寫程式的圈子、減少程式設計的工作量,而是重新歸位到自己對程式設計熱情的發源地。我開始在工作之外開發一些小東西,這些小東西規模都不大,但做的都是源自於自己的想法。自己從頭到尾包辦了所有的工作,沒有專業的分工,自己既是產品經理,也是系統設計者,同時撰寫程式碼以及測試。每個不同的想法都會需要一些不同的新技術,在開發的過程中,有機會接觸到這些新的技巧。而更重要的是,這像極了最初開始學習撰寫程式時的模式。自己想到什麼就寫些什麼,既沒有規格也沒有必須完成的期限(所以也沒有壓力)。有趣的小東西可以發送給朋友甚至是公開給大眾試用。這個過程與其說是在開發,不如說是在玩樂,我可以盡情的操弄我自己隨心所創造出來的玩意兒。慢慢的,我覺得彷彿又拾回昔日從程式設計中所獲得的樂趣。我也同時發現,重新燃情的熱情,也從工作外感染回工作內,沖淡許多因為工作壓力所帶來的一些不愉快的情緒。甚至,我發現即使是因為工作的關係而撰寫程式碼,自己也能樂在其中,沉浸滿足於那種解決問題的成就感。寫程式的時間變得更多,但人卻更快樂了。
工作難免為了五斗米折腰的壓力所迫,必須做些自己或許不甚願意做的事情。但是,我們最初之所以想成為一名程式設計者,多半都是基於自己對程式設計的喜愛。千萬別讓工作磨損了這份熱愛,仔細回想自己喜歡程式設計的初衷,在工作以外,選擇一個沒有壓力的方式,重新體驗多年前讓你沉迷的那種感覺,你不但能重新找回對程式設計的熱情,也會重新發現自己工作中能讓自己快樂的地方。Blogged with Flock
Posted at 10:53下午 八月 20, 2008 by Chien-Hsing Wang in General | 迴響[2]
ffqlay – 基於ffmpeg、用於Windows的視訊音訊撥放程式庫
倘若要在Windows平台上開發視訊或音訊的應用程式,大多開發者的選擇都應該會是DirectShow。DirectShow是微軟官方針對此種應用所制定的一套架構。倘若從架構的角度來看,我個人認為它是一套不錯的架構,而且相當的元件化,透過標準化的filter介面,應用程式可以彈性的進行組裝,並且變化出自己所需要的撥放方式。 不過,在處理多媒體的撥放時,除了一個好的撥放架構外,我們還會需要各式各樣的codec,以供所需的視訊、音訊編解碼之用(當然,你還會需要muxer以及demuxer)。這個部份對於在Windows上的開發者來說是個不小的問題。Windows作業系統有內建少數幾種視訊及音訊格式的codec,例如WMV、WMA,但是倘若你的需求超出這內建的codec範圍,例如H.264,那麼除了購買codec開發商所開發的codec,尋求開放原始碼的codec就成了絕大多數開發者會採取的選擇 -
事實上,自行開發codec並不在應用程式開發者的責任範圍內,codec的開發已經是一份相當專業的工作,甚至許多公司的主要產品就是codec。
在開放原始碼的codec中,ffmpeg中所含的codecs無疑的是最受歡迎的其中之一組。ffmpeg本身主要的作用在於影音檔案的轉換,不過其中所含的各種video、audio的codecs,其類型之多十分少見。同時,投入ffmpeg的開發力量也很強大,codec的增加和改善都有讓人滿意的狀態。許多線上影音的分享網站,背後都採用ffmpeg做為轉換的工具。從之前的兩篇部落格文「包裝ffmpeg中的codecs成為DirectShow中的transform filter」以及「包裝ffmpeg中的MP3 codecs成為DirectShow中的MP3 Decoder」,就可以看的出來,我試著想要善用ffmpeg中的資源,以融入DirectShow架構的企圖中。
有一陣子,我想要包裝ffmpeg中的codecs,成為一個通用的decoder。也就是說,將ffmpeg中的codecs包裝成為單一filter,將它放到DirectShow中,便可以解所有ffmpeg所支援的codec。在現有的開放原始碼的專案中,ffdshow便是和我想做的事情一樣的產物。ffdshow中含有兩個通用性質的video decoder以及audio decoder,分別用來解各種格式的video及audio資訊,而且它們都是DirectShow架構下的filter。ffdshow提供的是一體適用的decoder,因此使用ffdshow的應用程式,因為codec而產生的困擾就會小的多了。儘管ffdshow十分強大,但是很可惜的,它的版權是GPL,是許多情況下我個人比較不偏好的一種。 礙於這一陣子的忙碌,基於LGPL的ffmpeg來打造通用性質decoder的這件工作,始終一直沒有時間著手。之後發生了一些事情,讓我生起來了想要放棄DirectShow架構來進行撥放的念頭。我想到,ffmpeg專案中有一個ffplay程式,是個基於 SDL(Simple DirectMedia Library)的撥放程式,它可以撥放ffmpeg中libavcodec這個程式庫中所含codec之格式的檔案。於是,我將這個想法轉變成為直接基於ffplay來做為撥放架構的基礎,如此一來,便能在不倚賴DirectShow的情況下,直接撥放ffmpeg所支援的所有類型檔案。這個部落格有幾篇文提到了「開放原始碼的回收與再利用」的想法,而這一次的想法與做法,也完全不脫這樣子的思維方式。
如果我們需要一張椅子,我們可能會先找到「一張既有的木頭茶几,然後將這張茶几重新修整,並且添加新的材料,而成為一張具有新面貌的椅子」。何況,ffplay本身就是一張十分符合我需求的椅子了,不過少了扶手罷了。所以,我要做的只是為它加上扶手。 我需要的不是一個像ffplay這樣子可獨立執行的程式,我需要的其實是一個程式庫,提供一組API,使得我可以輕易的利用這組API,為我的應用程式加上撥放的功能。所以我花了些許的時間,對ffplay做極小幅度的修改(事實上,我甚至沒有閱讀ffplay絕大多數的程式碼),將其中的功能包裝成為一組API。我把這程式庫版本的ffplay稱為ffqlay(把”p”左右反轉成為”q”,希望這樣子沒有違反開放原始碼社群的什麼慣例)。修改後的ffqlay,自然也是LGPL。 利用Mingw32可以編譯ffmpeg整個專案以及ffqlay。我為ffqlay撰寫了一個ffqlayDemo的專案,藉以示範說明ffqlay中的API。ffqlayDemo是C#撰寫的,透過它你可以明白應用程式的開發者可以如何輕易的以十分簡短的程式碼,便能達成撥放的種種功能。 以下,便是ffqlayDemo撥放一個VOB檔案的畫面,事實上,它可以撥放任何你所build出來ffmpeg中所支援的格式,所以我把之前下載的 FLV Player都砍掉了。即使拿來撥放不含video stream的MP3音樂檔案,也完全沒有問題。

程式的下載可先於以下網址下載,我希望可以長期持續維護,因此我會尋找一個更適合的方式來分享相關的資源。
ffqlay.c下載 ffqlayDemo下載想用使用上述的程式,你或許需要自行能夠編譯ffmpeg以及把ffqlay加至ffmpeg中編譯。我希望有空可以再解釋,不過如果有讀者遇上了麻煩,就要請你留言了,我會試著盡我可能的協助。
Posted at 10:46下午 八月 20, 2008 by Chien-Hsing Wang in General | 迴響[1]
Thinking in Java 第四版中文版譯序
距離Thinking in Java第二版中文版的問世已經是六年前的事了。在這六年間,Java本身,以及Java的應用環境也起了很大的變化。這麼多年來,Java的主要戰場從網頁上的applet小程式轉移到伺服器端,成了開發網站應用系統的主流語言,反倒是applet,已經變得乏人問津。除此之外,手機及行動裝置應用逐漸受到重視,基於Java的手機及行動裝置平台,更有成為主流的高度可能性。
除了整個應用的生態環境有了很大的變化之外,Java語言也發生了許多本質上的改變。尤其在Java SE5之後,吸收了許多來自Java的競爭對手.NET及C#的特性,更是將Java帶往另一個截然不同的里程碑。
在過去,Thinking in Java每一個新版本,都是跟隨著Java語言的改版而來的,第四版也不例外。第四版針對Java SE5/6的新特色,做了很大幅度的調整。尤其是泛型(generics)、標註(annotation)、列舉型別(enumerated types)、並行性(concurrency),都是Java SE5/6中重大的增進,也是第四版中的最大賣點。對於中文版的讀者來說,第三版中開始介紹的New I/O,其高效的表現也應該會吸引你的目光。因為Java變得更加完備,本書份量之重自然勝過第二版許多。
第二版是由我在侯捷大哥的指導下和他一同進行翻譯的工作,而第四版的中譯工作,則是由我和王舜正先生協力完成。由於第二版與第四版有著高度的同質性,因此在第四版的中文版本中,依舊承襲著源自於第二版中文版本的文字及血統。即使侯捷大哥未於此譯本掛名,但這份譯本仍然有著他過去卓越的貢獻。在此版本中若有缺失之處,即為我個人有待向侯捷大哥學習改進的空間。
本書內容繁重,因此特別商請數位朋友協助審閱,在此我要特別向他們致謝。洪孟琮、謝欣至、林育慧、以及Victor Chen,謝謝你們。尤其是育慧及Victor,在翻譯工作進行到後期,提供給我們諸多寶貴的修改意見。
在本書的中譯工作即將告尾聲的時候,我的兒子宥宥也出世了。我要感謝我的妻子Chloris包容我在許多工作忙碌的夜晚,有失照料她們的責任。
最後,我要感謝碁峰資訊的Novia小姐,妳無疑的是此一譯本最重要的推手。
Blogged with Flock
Posted at 10:18上午 八月 13, 2008 by Chien-Hsing Wang in General | 迴響[2]
星期三 八月 27, 2008
