程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> VLC 架構初步分析

VLC 架構初步分析

編輯:C++入門知識

VLC player的大架構不難理解,難理解的是它的對象meta系統的作用,類的繼承機制,類的層次關系,以及消息傳遞路線。

 

 Meta系統
VLC實現了對象的Meta系統,我初步認為其作用為:

•     輕松實現屬性永久化,與配置文件原生態結合。

•     動態屬性

•     很多流程或者說消息驅動機制由屬性的可觀查機制實現。

類(結構)的繼承
•     大部分類都是從vlc_object_t繼承的。

•     vlc_object_t實現了對象之間的父子關系(不同於繼承)。

•     繼承的形式並不是像真正的類那樣或者是把vlc_object_t變量放在結構的最開始,而是用了一個宏:VLC_COMMON_MEMBERS放在了類的最開始處。

•     每個插件實現的私有數據保存在插件的公開類的帶有“sys”或“priv”字串的類型的變量中。

類的層次關系
•     對外的最高類是libvlc_instance_t,外部接口要使用的主要參數是libvlc_instance_t對象,由libvlc_new()創建。

•     內部操作的主要對象是libvlc_int_t,但其實就是libvlc_priv_t ,但更其實libvlc_priv_t和libvlc_int_t和libvlc_instance_t跟本就是一個對象。只不過為了實現封裝性搞出這麼多花樣,還不如都放一塊然後用注釋說明呢。

•     libvlc_priv_t包含了很多一個instance中應包含的東西,比如播放列表,media_library,流媒體服務器對象,熱鍵映射動作列表,界面對象等。所以獲得了libvlc_int_t對象,就能獲得所有其它對象。

 

消息傳遞路線
•     meta的可觀查機制是消息驅動的基礎。

•     舉個例子,playlist_t對象會觀查input_thread_t對象。input_thread_t對象代表一個輸入流。當input_thread_t對像的一些動態屬性發生變化時,就會通知playlist_t,而如果界面偵聽了playlist_t,就可以在界面上表現出這些變化。反之,如果playlist_t要操作input_thread_t,也是通過設置input_thread_t的動態屬性的值來做的。

 

流程粗析
 

QT消息與meta通知的配合
•     界面的主要作用一是提供用戶控制libvlc核心對象的用戶接口,二是舉核心對象的狀態顯示給用戶看。

•     要通過界面控制核心對象,只要在界面插件內部能獲取到libvlc_int_t,就能獲取到任何其它對象,然後利用現有函數或直接操作它的動態屬性即可。

•     要將核心對象的狀態反映到界面上來,就需要界面插件觀查這些對象的相關動態屬性。比如input_thread_t集中地通過一個動態屬性向觀查者通知事件的發生,這個屬性叫做:”intf-event”.

•     input_event_type_e中定義了所有input所能發出的事件通知。

•     Qt界面插件用一個全局函數InputEvent()作為“intf-event”動態屬性的回調函數,以響應”intf-event”事件。

•     playlist對象管理input對象,因為每次播放playlist中的一個條目,都需要建立一個新的input對象。Qt界面插件用一個InputManager對象對應一個input對象,用一個MainInputManager對象對應一個(也是唯一的)playlist對象。

•     InputManager對象負責從input對象中接收事件,通過InputEvent()把”intf-event”轉換為QT事件,然後post給自己的customEvent()函數,在其中又轉換為signal發出。但這個類不負責操作input對象,應該是playlist對象負責了。

•     MainInputManager對象負責從playlist對象中接收事件,偵聽了playlist的多個屬性。在回調函數中把屬性變化轉換為QT事件,然後將事件郵寄給自己,在接收函數中把事件轉換為signal發出。同時,MainInputManager對象還負載操作playlist對象。

•     對鍵盤與響應函數的映射,在libvlc內部已做好了。調用者要做的就是把鍵值轉換為libvlc內部定義的鍵值,然後以libvlc_int_t對象的"key-pressed"屬性傳給libvlc內部。內部會調用此屬性的偵聽函數,對鍵盤事件做出正確的反映。

Qt界面插件解析
•     界面在libvlc初始化完成後調用libvlc_add_intf()時被添加。

•     在插件的Open()函數中創建和初始化私有數據:intf_sys_t。然後又創建了界面所在的線程。

•     界面線程中創建QApp實例,創建主界面窗口,進入消息循壞。

•     主窗口界面分為三部分:菜單欄,中心區,狀態欄,分別由VLCMenuBar::createMenuBar(),createMainWidget(),createStatusBar()三個函數創建。

•     中心區包含很多控件,有控制欄,輸入欄,高級控制欄,視頻顯示控件,背景控件,播放列表控件等。當然有些控件是互斥顯示的。

•     含有多個控件的控件,比如控制欄和輸入欄,高級控制欄等,它們內部的控件都是跟據配置文件中的條目依次創建的。配置文件中的每個控件都對應一個類型,這個類型直接指定了控件的功能。

•     所有包含多個控件的控件,都是從AbstractController派生,AbstractController中為了能對自己包含的所有控件的信號進行統一處理,以支持可編程性,使用了QSignalMapper。所有的控件都把自己的信號加入mapper中,將mapper的信號連接到ActionsManager對象,在ActionsManager的doAction()中處理所有的控件的信號。

關於如可實現同步播放的思路
•     擴展Qt界面插件

•     使用非阻塞式Qt socket:QTcpSocket。

•     Socket處於界面所在線程中。

•     創建主界面窗口後立即創建tcp socket

•     在界面收到用戶輸入信號或libvlc信號時,向另一個端發出命令包。

•     socket從另一端收到命令包後,跟據命令的內容,直接調用libvlc的相關函數。

 

如何向工程中添加新的界面
•     在src/modules/gui/qt4/dialogs下添加定義界面的頭文件和源碼文件。

•     修改src/modules/gui/qt4下的makefile.am文件。

•     向nodist_SOURCES_qt4增加項。

•     向SOURCES_qt4增加項。

•     向noinst_HEADERS增加項。

•     如果要鏈接新的QT庫,則修改src/configure.ac。比如增加鏈接QtNetwork庫,則找到行:PKG_CHECK_MODULES(QT4,[QtCore QtGui >= 4.6.0], [ 改為PKG_CHECK_MODULES(QT4, [QtCore QtGui QtNetwork >=4.6.0], [

•     執行autoreconf命令

•     ./configure

•     make

 

如何向工程中增加圖像資源
•     將圖像文件,比如a.png放到/modules/gui/qt4/pixmaps下。

•     在modules/gui/qt4/Modules.am中的DEPS_res區增加一項:pixmaps/a.png。

•     在modules/gui/qt4/Modules.am中的<qresource prefix="/">區增加一條:<filealias="a_icon">pixmaps/a.png</file>

•     autoreconf,configure

•     在源文件中這樣使用:QIcon(“:a_icon”);

•     make

 

 

      

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved