在本論文中我們討論了從使用者開啟 VLC 的執行檔產生一個 GUI 介面到 VLC 開始 播放一個多媒體檔案整個的基本流程;以簡單的多媒體播放器架構為基礎,探討多媒體播
放器運作的機制。我們以模組化為主軸去討論 VLC 中許多函數的重要性,從尋找資源
存取、解多工器、解碼器等等模組的 module_Need()函數去介紹一個支援播放多格式的 多媒體播放器是如何由影音檔案資訊去找到適合的模組。
目前許多的播放器都具有支援播放多格式影音檔案以及強大的解碼的功能,所以播 放器會面臨到的問題是如何依據不同格式的影音檔案找到適合的解多工和解碼程序,其 中也包括如何建立解多工、解碼程序跟讀取、傳送資料這些系統程序的溝通機制。所以 播放器會將解多工和解碼程序以及讀取、傳送資料程序進行模組化,以解多工器模組來 說;因為其中定義了模組的特性和解多工函數的 callback functions 以及讀取、傳送資料的 系統模組,所以解多工器模組會呼叫讀取資料系統模組來取得影音的data stream 後進行 解多工程序,將data stream 分成 audio bitstream 或 video bitstream,然後再呼叫傳送資 料系統模組把audio bitstream 或 video bitstream 交給解碼器模組進行解碼程序;當然解多 工器模組中的模組特性和解多工函數的callback functions 會因為不同的影音檔案格式有 所不同,所以必須藉由一套完整模組搜尋的機制來決定。所以播放器可以藉由透過模組 搜尋機制所找到的模組與系統模組之間的溝通建立起完整的影音播放程序。
所以本論文藉由研究 VLC 的 source code 去了解一個多媒體播放器是如何播放一個 影音檔案;並如何藉由不同格式的檔案所提供的資訊去找到適合的解多工器、解碼器和輸 出等等模組,然後藉由這些程序來了解功能模組化與模組的搜尋機制之間的關係和重要 性,並以軟體工程方面來學習程式的技巧。
81
參考文獻
[1] VLC http://www.videolan.org/vlc/
[2] VLC user guide http://www.tldp.org/REF/VLC-User-Guide/
[3] VLC media player API Documentation
http://www.videolan.org/developers/vlc/doc/developer/html/manual.
html
[4] Videolan's Wiki http://wiki.videolan.org/VideoLAN
[5] ISO/IEC 13818-2 Generic coding of moving picture and associated audio information: Video
[6] 陳瑩甄,『串流伺服器資料解析及封包包裝』,國立交通大學,碩士論文,96
學年度。
[7] 郭明山,『播放器內解多工器與解碼器搜尋與比對』,國立交通大學,碩士論
文,97 學年度。
82
附錄 A
如果想要build vlc from source code on windows,大致上有下列三個的方法:
1. 使用 cygwin(在 windowns 下 compile,建議用此方法)。
2. 使用 MSYS+MINGW。
3. 使用 Microsoft Visual C++。
在這邊我們只介紹如何用cygwin 去 building soutce code of vlc。
編譯步驟:
1. 到
http://www.cygwin.com/ 下載 cygwin.exe,執行並安裝所有 packgae.
2. 到
http://www.videolan.org/ 下載 vlc source code,解壓縮至
C:\cygwin\home\kyo 目錄底下。3. 到
http://download.videolan.org/pub/testing/win32/ ,下載
contrib-20061202-win32-bin-gcc-3.4.5-only.tar.bz2 並解壓縮之後,將資料夾裡
CPPFLAGS="-I${CONTRIB_TREE}/include -I${CONTRIB_TREE}/include/ebml" \ LDFLAGS=-L${CONTRIB_TREE}/lib \
PKG_CONFIG_LIBDIR=${CONTRIB_TREE}/lib/pkgconfig \ CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin" \
./configure \
--host=i686-pc-mingw32 \
--enable-sdl --with-sdl-config-path=${CONTRIB_TREE}/bin --disable-gtk \
83 --enable-nls \
--enable-ffmpeg --with-ffmpeg-mp3lame --with-ffmpeg-faac \ --with-ffmpeg-zlib --enable-faad --enable-flac --enable-theora \ --with-wx-config-path=${CONTRIB_TREE}/bin \
--with-freetype-config-path=${CONTRIB_TREE}/bin \ --with-fribidi-config-path=${CONTRIB_TREE}/bin \
--enable-live555 --with-live555-tree=${CONTRIB_TREE}/live.com \ --enable-caca --with-caca-config-path=${CONTRIB_TREE}/bin \ --with-xml2-config-path=${CONTRIB_TREE}/bin \
--with-dvdnav-config-path=${CONTRIB_TREE}/bin \ --disable-cddax --disable-vcdx --enable-goom \ --enable-twolame --enable-dvdread \
10. *Creating self contained packages:(optional)
Once the compilation is done, you can either run VLC directly from the source tree or you can build self-contained VLC packages with the following "make"
commands:
84
make package-win32-base
(This will create a subdirectory named vlc-x.x.x with all the binaries "stripped"
without any debugging symbols).
make package-win32-zip
(Same as above but will package the directory in a zip file).
make package-win32
(Same as above but will also create an auto-installer package. You will need to have NSIS installed in its default location for this to work).
(註)*步驟 10 選擇性執行
11. cygwin 編譯 VLC 錯誤修正:
由於 cygwin 版本問題,如果依照前 10 步驟來建立 VLC 還會產生錯誤的話,
請依照下面cygwin 介面所提示的錯誤訊息加以修正。
問題 1:
gcc -mno-cygwin -Wsign-compare -Wall -mms-bitfields -pipe -o libaccess_output_dummy_plugin.dll -g
-shared -u _vlc_entry__0_8_6 -L/usr/win32/lib libaccess_output_dummy_plugin.a -L/usr/local/lib if gcc -mno-cygwin -DHAVE_CONFIG_H -I. -I. -I../.. -I/usr/win32/include
-I/usr/win32/include/ebm
l -D_OFF_T_ -D_off_t=long -DSYS_MINGW32 -I../../include `top_builddir="../.." ../../vlc-config --c
flags plugin access_output_file` -Wsign-compare -Wall -mms-bitfields -pipe -MT libaccess_output_f
ile_plugin_a-file.o -MD -MP -MF ".deps/libaccess_output_file_plugin_a-file.Tpo" -c -o libaccess_ou
tput_file_plugin_a-file.o `test -f 'file.c' || echo './'`file.c; \
85
then mv -f ".deps/libaccess_output_file_plugin_a-file.Tpo" ".deps/libaccess_output_file_pl ugin_a-file.Po"; else rm -f ".deps/libaccess_output_file_plugin_a-file.Tpo"; exit 1; fi
In file included from file.c:30:
/usr/lib/gcc/i686-pc-mingw32/3.4.4/../../../../i686-pc-mingw32/include/sys/stat.h:113: error: pars e error before "off_t"
/usr/lib/gcc/i686-pc-mingw32/3.4.4/../../../../i686-pc-mingw32/include/sys/stat.h:118: error: pars e error before '}' token
make[4]: *** [libaccess_output_file_plugin_a-file.o] 錯誤 1 make[4]: Leaving directory `/tmp/vlc-0.8.6i/modules/access_output'
if g++ -mno-cygwin -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/win32/include -I/usr/win32/include/ebml -
D_OFF_T_ -D_off_t=long -DSYS_MINGW32 -I../include `top_builddir=".." ../vlc-config --cxxflags acti
vex` -Wsign-compare -Wall -mms-bitfields -pipe -MT libaxvlc_a-main.o -MD -MP -MF
".deps/libaxvlc
_a-main.Tpo" -c -o libaxvlc_a-main.o `test -f 'main.cpp' || echo './'`main.cpp; \
86
then mv -f ".deps/libaxvlc_a-main.Tpo" ".deps/libaxvlc_a-main.Po"; else rm -f ".deps/libax vlc_a-main.Tpo"; exit 1; fi
In file included from /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:54, from /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/postypes.h:46,
make[3]: *** [libaxvlc_a-main.o] 錯誤 1
make[3]: Leaving directory `/tmp/vlc-0.8.6i/activex'
gcc -mno-cygwin -Wsign-compare -Wall -mms-bitfields -pipe -o libdtstofloat32_plugin.dll -g -shared
-u _vlc_entry__0_8_6 -L/usr/win32/lib libdtstofloat32_plugin.a -L/usr/local/lib -ldts_pic libdtstofloat32_plugin.a(libdtstofloat32_plugin_a-dtstofloat32.o): In function `Open':
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:219: undefined reference to `_dca_in
87
it'
libdtstofloat32_plugin.a(libdtstofloat32_plugin_a-dtstofloat32.o): In function `DoWork':
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:303: undefined reference to `_dca_sy ncinfo'
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:312: undefined reference to `_dca_fr ame'
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:331: undefined reference to `_dca_bl ocks_num'
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:335: undefined reference to `_dca_bl ock'
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:341: undefined reference to `_dca_sa mples'
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:331: undefined reference to `_dca_bl ocks_num'
libdtstofloat32_plugin.a(libdtstofloat32_plugin_a-dtstofloat32.o): In function `Destroy':
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:376: undefined reference to `_dca_fr ee'
libdtstofloat32_plugin.a(libdtstofloat32_plugin_a-dtstofloat32.o): In function `CloseFilter':
/tmp/vlc-0.8.6i/modules/audio_filter/converter/dtstofloat32.c:430: undefined reference to `_dca_fr ee'
collect2: ld returned 1 exit status
make[6]: *** [libdtstofloat32_plugin.dll] 錯誤 1
make[6]: Leaving directory `/tmp/vlc-0.8.6i/modules/audio_filter/converter'
88
修改 vlc-config 文件中
dtstofloat32)
ldflags="${ldflags} -ldts_pic"
修改成為 dtstofloat32)
ldflags="${ldflags} -ldts"
重新 make 問題 4:
gcc -mno-cygwin -Wsign-compare -Wall -mms-bitfields -pipe -o libflacdec_plugin.dll -g -shared -u _
vlc_entry__0_8_6 -L/usr/win32/lib libflacdec_plugin.a -L/usr/local/lib /usr/win32/lib/libFLAC.a - lm /usr/win32/lib/libogg.a
/usr/win32/lib/libFLAC.a(bitwriter.o):bitwriter.c:(.text+0x3fb): undefined reference to `_ntohl@4' /usr/win32/lib/libFLAC.a(bitwriter.o):bitwriter.c:(.text+0x488): undefined reference to `_ntohl@4' /usr/win32/lib/libFLAC.a(bitwriter.o):bitwriter.c:(.text+0x4e5): undefined reference to `_ntohl@4' /usr/win32/lib/libFLAC.a(bitwriter.o):bitwriter.c:(.text+0x57f): undefined reference to `_ntohl@4' /usr/win32/lib/libFLAC.a(bitwriter.o):bitwriter.c:(.text+0x5d5): undefined reference to `_ntohl@4' /usr/win32/lib/libFLAC.a(bitwriter.o):bitwriter.c:(.text+0x66f): more undefined references to `_nt
ohl@4' follow
collect2: ld returned 1 exit status
make[4]: *** [libflacdec_plugin.dll] 錯誤 1
make[4]: Leaving directory `/tmp/vlc-0.8.6i/modules/codec'
89
ldflags="${ldflags} -lFLAC -lws2_32"
重新 make
if g++ -mno-cygwin -DHAVE_CONFIG_H -I. -I. -I.. -I/usr/win32/include -I/usr/win32/include/ebml -
D_OFF_T_ -D_off_t=long -DSYS_MINGW32 -I../include `top_builddir=".." ../vlc-config --cxxflags acti
vex` -Wsign-compare -Wall -mms-bitfields -pipe -MT libaxvlc_a-main.o -MD -MP -MF
".deps/libaxvlc
_a-main.Tpo" -c -o libaxvlc_a-main.o `test -f 'main.cpp' || echo './'`main.cpp; \
then mv -f ".deps/libaxvlc_a-main.Tpo" ".deps/libaxvlc_a-main.Po"; else rm -f ".deps/libax vlc_a-main.Tpo"; exit 1; fi
In file included from /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/cwchar:54, from /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/postypes.h:46,
90
does not name a type
make[3]: *** [libaxvlc_a-main.o] 錯誤 1
make[3]: Leaving directory `/tmp/vlc-0.8.6i/activex' make[2]: *** [all] 錯誤 2
make[2]: Leaving directory `/tmp/vlc-0.8.6i/activex' make[1]: *** [all-recursive] 錯誤 1
make[1]: Leaving directory `/tmp/vlc-0.8.6i' make: *** [all] 錯誤 2
問題 5 解決方法:
/usr/i686-pc-mingw32/include/目錄下 在 wchar.h 的檔案起頭增加
#ifndef _OFF_T DEFINED typedef long off_t;
#define _OFF_T DEFINED
#endif
91
處理檔案類型:音頻交換格式(Audio Interchange File Format,AIFF) 設定解碼四字元: VLC_FOURCC( 't', 'w', 'o', 's' )
92
93
94
95
1.21 wav.c
處理檔案類型: WAV 檔案
設定解碼四字元: VLC_FOURCC('a','r','a','w') VLC_FOURCC('p','c','m',' ') VLC_FOURCC('a','f','l','t')
VLC_FOURCC( 'a', 'r', 'a', 'w' ):
VLC_FOURCC( 'a', 'f', 'l', 't' ):
VLC_FOURCC( 'u', 'l', 'a', 'w' ):
VLC_FOURCC( 'a', 'l', 'a', 'w' ):
VLC_FOURCC( 'm', 'l', 'a', 'w' ):
VLC_FOURCC( 'p', 'c', 'm', ' ' ):
VLC_FOURCC( 'm', 's', 0x00, 0x02 ):
VLC_FOURCC( 'm', 's', 0x00, 0x11 ) VLC_FOURCC( 'm', 's', 0x00, 0x61 ):
VLC_FOURCC( 'm', 's', 0x00, 0x62 ):
VLC_FOURCC( 'm', 'p', 'g', 'a' ):
VLC_FOURCC( 'a', '5', '2', ' ' ):
1.22 xa.c
處理檔案類型:XA 檔案
設定解碼四字元: VLC_FOURCC('X','A','J',0)