前面大致的了解了 vlc 解碼器開發的過程以及 vlc-h265 插件開發的實例,于是開始嘗試開發一個支持 avs2 標準的 vlc 播放器
- 拓展閱讀:播放器插件實現系列 —— vlc
- 拓展閱讀:Hacker Guide/How To Write a Module
- 擴展閱讀:VLC Developers site
- 需要資源:vlc Github倉庫地址
1 內部模塊注冊
1.1 注冊聲明
vlc 的模塊注冊是一套標準的流程,我們的類型應當選擇解碼器 “Decoder”,在我們的核心 .c 文件中添加:
vlc_module_begin ()
set_category( CAT_VIDEO )
set_description( N_("avs2 Decoder library") )
set_capability( "decoder", 100 )
set_callbacks( Open, Close )
vlc_module_end ()
ps :這里的 N_() 是用于創建一個可以被 gettext 輕松轉換的字符串(語種之類的)的形式
- set_category::標明這個模塊起作用的地方(video)
- set_description:模塊的描述,添加成功后可以在 ./vlc --list 中顯示
- set_capability:功能與評分,這里下面會細講
- set_callbacks:調用模塊時的入口與出口(開關函數)
1.2 功能與評分
set_capability 函數是一開始困惑了我挺久的一個函數,因為我一直不知道后面這個 score 到底要怎么算...
第一個參數很好理解,我們作為一個解碼器功能自然是 "decoder" ,而第二個參數需要的是一個 score,不同的模塊可以選擇不同的 socre(對沒錯,是自己選的),主要功能就是當 vlc 需要一個功能的時候(比如解碼),他會大喊一聲:“解碼器!”,然后所有解碼器們就開始排隊,排隊的依據就是他們的 score ,高個在前,然后由 vlc 給出對應的格式詢問。
這個過程中排隊主要的意義就是優先選擇更愿意接受某種格式的模塊,比如同樣支持 .bin 格式的兩個模塊,一個 score=100 ,一個 score=50 ,最后的結果就是選擇前一個。
當然這里面就有了一個特例—— score=0,在這種情況下這個模塊只有被用戶或 vlc 明確指定的情況下才會被加載,否則不參與前面的排隊。
2 定義自己的模塊主體
注冊之后主要實現解碼器的邏輯與功能,這部分 emmm..... 沒法記,主要就是定義一個自己的數據結構體(上下文之類的),然后實現 Open、Close函數以及我們的 DecoderBlock,完成內部的調用或者其他邏輯。具體實現參照可以參考最開始的第一個拓展閱讀。
3 模塊正式注冊
模塊的正式注冊就是在 vlc 的模塊列表里正式添加我們的模塊,必須修改的文件一個是 vlc/configure.ac 一個是 vlc/modules/codec/Makefile.am (我們的核心代碼與這個 Makefile.am 應該在同一目錄下)。
3.1 configure.ac
這個文件主要是在 autoconf 中設置 vlc ,我們在里面加入一段我們自己的配置:
dnl
dnl AVS2 decoder module
dnl
AC_ARG_ENABLE(avs2,
[ --enable-avs2 AVS2 support (default disabled)])
AS_IF([test "${enable_avs2}" != "no"], [
AC_CHECK_HEADERS(cavs2dec.h, [
VLC_ADD_PLUGIN([avs2])
])
])
這里面 dnl 就是注釋的意思,AC_ARG_ENABLE 是在編譯過程中是否編譯該模塊的選擇,如果進行編譯,則檢查頭文件:cavs2dec.h,頭文件存在則執行 VLC_ADD_PLUGIN([avs2]) ,不存在則--(沒寫,需要的話可以寫在第三個參數上)。
3.2 Makefile.am
這個文件是在 make 過程中的模塊加載,我們也添加一下:
### AVS2 Decoder Module ###
libavs2dec_plugin_la_SOURCES = codec/cavs2dec.c
libavs2dec_plugin_la_CPPFLAGS = $(AM_CPPFLAGS)
libavs2dec_plugin_la_CFLAGS = $(AM_CFLAGS)
libavs2dec_plugin_la_LDFLAGS = $(AM_LDFLAGS)
libavs2dec_plugin_la_LIBADD = $(LIBM) -lpthread -lcavs2dec
codec_LTLIBRARIES += libavs2dec_plugin.la
我們編譯最終生成的的插件文件名字叫做 libavs2dec_plugin.la ,一定要注意上面的配置語句要和我們最終的名稱匹配。SOURCE 是我們剛剛編寫的核心代碼,CFLAGS、CPPFLAGS、LDFLAGS 使我們在編譯過程中需要的頭文件和優化項(沒啥特殊需求就和其他模塊一樣),LIBADD 使我們額外需要添加的編譯依賴,這里我們需要 m、pthread 以及暫時在本地 install 過的 cavs2dec 。
4 編譯與查詢
編譯進新模塊和查詢的指令:
./bootstrap
./configure --enable-avs2
make
./vlc -vvv --color --list | grep avs
一定要運行一下 ./bootstrap ,因為我們更改了 configure.ac ,這里面主要是執行了一些 autoconf 命令。
順利運行后我們找到了我們剛剛加入的模塊:
...
avs2dec avs2 Decoder library
...
5 加入我們的解碼器(TS)
5.1 ts.c
/* check only MPEG2, H.264, AVS2 and VC-1 */
if( p_es->fmt.i_codec != VLC_CODEC_MPGV &&
p_es->fmt.i_codec != VLC_CODEC_H264 &&
p_es->fmt.i_codec != VLC_CODEC_AVS2 &&
p_es->fmt.i_codec != VLC_CODEC_VC1 )
continue;
5.1 ts_psi.c
p_regs[] = {
{ "AC-3", AUDIO_ES, VLC_CODEC_A52 },
{ "EAC3", AUDIO_ES, VLC_CODEC_EAC3 },
// ……
{ "avs2", VIDEO_ES, VLC_CODEC_AVS2 },
{ "", UNKNOWN_ES, 0 }
switch( i_stream_type )
{
case 0x01: /* MPEG-1 video */
es_format_Change( fmt, VIDEO_ES, VLC_CODEC_MPGV );
fmt->i_original_fourcc = VLC_CODEC_MP1V;
break;
case 0x02: /* MPEG-2 video */
// ……
case 0x42: /* CAVS (Chinese AVS) */
es_format_Change( fmt, VIDEO_ES, VLC_CODEC_CAVS );
break;
case 0x43: /* AVS2 (Chinese AVS2) */
case 0xd2:
es_format_Change( fmt, VIDEO_ES, VLC_CODEC_AVS2 );
break;
5.3 fourcc
#define VLC_CODEC_AVS2 VLC_FOURCC('A','V','S','2')
B(VLC_CODEC_CAVS, "Chinese AVS"),
A("CAVS"),
6 小插曲—— vlc 界面問題
git clone 了 vlc 的 master (v4.0.0)之后編譯運行 ./vlc 不顯示界面,只能在命令行界面下運行。
仔細看了一下編譯結束后的輸出信息發現有特別多需要的包并沒有被安裝(開始時是跟著編譯缺包的信息裝的),后來在師兄提醒下用了 apt-get build-dep vlc 命令輕松地安上了很多需要的依賴,當然有時候會提醒未指定 deb-src 的問題,需要把 /etc/apt/sources.list 里面必要的語句解除注釋。
再次編譯后輸出:
libvlc configuration
--------------------
version : 4.0.0-dev
system : linux
architecture : x86_64 mmx sse sse2
optimizations : yes
vlc aliases : cvlc rvlc
在 vlc 的 Makefile.am 里可以找到
cvlc: make-alias Makefile
$(AM_V_GEN)$(MKALIAS) dummy
rvlc: make-alias Makefile
$(AM_V_GEN)$(MKALIAS) rc
svlc: make-alias Makefile
$(AM_V_GEN)$(MKALIAS) skins2
qvlc: make-alias Makefile
$(AM_V_GEN)$(MKALIAS) qt
nvlc: make-alias Makefile
$(AM_V_GEN)$(MKALIAS) ncurses
也就是說我們用于顯示界面的很重要的 qvlc 沒有被編譯進來。
于是在安裝完 QT5 后進行編譯時候使用命令
./configure --enable-qt
出現了一個錯誤
# include QPNI_HEADER 不存在這個文件或目錄
這個錯誤大概是 wayland 與 xwindow 的原因導致頭文件生成出現了問題,于是最終編譯命令就變成了
./configure --enable-debug --enable-qt --disable-wayland --enable-avs2
最后終于成功啦~
附成果截圖: