我的整理:html
Vlc流播放流程web
vlc源碼目錄樹:shell
目錄名稱macos |
說明vim |
bindings服務器 |
Java, CIL 和Python綁定網絡 |
docsocket |
幫助文檔 (不是更新的)tcp |
extras編輯器 |
另敘。 |
include |
VLC 頭文件 |
libs |
SRTP庫和裝載庫 |
lxdialog |
製做 menuconfig的文件 |
m4 |
Automake和autoconf的宏文件 |
modules |
除了src目錄外最重要的目錄。參考「功能模塊目錄樹」一節 |
po |
i18n (語言翻譯)文件 |
projects |
創建在 libvlc的項目,如Mozilla插件,ActiveX 插件和MacOS X Framework |
share |
圖標,腳本等等 |
src |
除了功能模塊之外最重要的目錄。 |
test |
一些腳本或測試代碼 |
extras/analyser |
一些代碼風格編輯器 (vim,emacs)的宏和一些valgrindsuppressions |
extras/buildsystem |
可選的編譯系統 |
extras/contrib |
須要的庫文件 (包括Makefiles自動下載和編譯(或交叉編譯),補丁)。 |
extras/deprecated |
deprecated 文件 |
extras/misc |
未分類文件 |
extras/package |
用於軟件發佈的文件如ipkg,不一樣的 rpm 規範文件,win32和Mac OS X安裝文件。 |
目錄名稱 |
子目錄 |
說明 |
access |
|
經過網絡獲取視頻流的協議(http,ftp,fake,tcp,udp等),獲取物理媒體介質的媒體內容如cd,dvd。 |
|
cdda |
讀取CD音頻的輸入模塊 |
|
dshow |
DirectShow獲取插件,用於WINDOWS平臺下的編碼卡。 |
|
dvb |
使用V4L2API的輸入模塊,用於DVB-S/C/T媒體流。 |
|
mms |
基於TCP,UDP的MMS和HTTP獲取模塊 |
|
rtsp |
|
|
screen |
獲取屏幕圖像的輸入模塊。 |
|
vcd |
獲取VCD數據的輸入模塊。 |
|
vcdx |
獲取VCD輸入模塊,能夠導航,靜止 |
|
|
|
access-filter |
|
包含下面的濾波器:timeshift, record, dump |
|
|
|
access-output |
|
|
|
|
|
audio-filter |
|
各類音頻濾波器如解碼,均衡,轉換。 |
|
channel-mixer |
各類混合器,解碼器如 Dolby解碼器 |
|
converter |
定點或浮點音頻格式轉換如 AC/3,MPEG I-II 音頻層1,2, 3 解碼 |
|
resampler |
各類音頻重採樣模塊 |
|
|
|
audio-mixer |
|
混合器插件 |
|
|
|
audio-output |
|
音頻輸出插件如ALSA,OSS和 DirectX音頻 |
|
|
|
codec |
|
各類編解碼,特別是ffmpeg |
|
cmml |
持續媒體標記語言,腳本/超連接解釋器 |
|
dmo |
一個DirectMediaObject解碼器,利用DirectMedia對WMV3視頻解碼 |
|
ffmpeg |
ffmpeg 庫的視頻解碼器 |
|
spudec |
RLE DVD 小標題解碼 |
|
xvmc |
XVMC視頻輸出和解碼 |
|
|
|
control |
|
控制播放器的各類接口:手勢, 熱鍵,lirc,遠程控制和telnet |
|
http |
HTTP遠程控制 |
|
|
|
demux |
|
不一樣的解複用程序 |
|
asf |
ASF 解復器 |
|
avi |
AVI文件流解復器 |
|
mp4 |
MP4文件輸入模塊 |
|
mpeg |
|
|
playlist |
播放清單導入模塊 |
|
|
|
gui |
|
不一樣平臺的用戶界面和 ncurses接口 |
|
beos |
用於BeOS的音頻輸出,視頻輸出和用戶界面輸出。 |
|
macosx |
Mac OS X 視頻輸出和用戶界面模塊 |
|
pda |
iPaq用戶接口,使用Gtk2+widget集. |
|
qnx |
QNX RTOS 插件 |
|
qt4 |
使用Qt4庫交叉編譯的用戶界面模塊。該模塊是默認的界面庫 |
|
skins2 |
換夫模塊。 |
|
wince |
Pocket PC 接口 |
|
wxwidgets |
使用wxWindows庫跨平臺的接口。做爲默認的接口的VLC版本是0.86a. |
|
|
|
meta-engine |
|
|
|
|
|
misc |
|
|
|
dummy |
啞 (沒有GUI)音頻輸出,視頻輸出,用戶接口和輸入模塊。 |
|
memcpy |
內存快拷貝模塊 |
|
notify |
通知,使用libnotify |
|
playlist |
|
|
probe |
|
|
testsuite |
|
|
xml |
LibXML 和 xtagxml 解析 |
|
|
|
mux |
Various Muxers |
|
|
mpeg |
|
|
rtp |
|
packetizer |
|
打包模塊,用於H264/AVC和MPEG 4音視頻流。 |
|
|
|
services-discovery |
|
|
|
|
|
stream-out |
|
|
|
transrate |
|
|
|
|
video-chroma |
|
圖像格式轉換,如 YUV到 RGB |
|
|
|
video-filter |
|
各類視頻濾波模塊如Deinterlace,Transform, Wall, Crop, Panoramix 等等。 |
|
|
|
video-output |
|
|
|
directx |
WINDOWS視頻輸出模塊,使用Direct3D和Direct X API,OpenGL |
|
qte |
QT嵌入式視頻輸出模塊 |
|
x11 |
X11 API視頻輸出模塊 |
|
|
|
visualization |
|
多種可視化模塊,包括goom |
|
galaktos |
輸出到 OpenGL的可視化模塊 |
|
visual |
可視化系統 |
vlc核心的是libvlc,它提供界面,應用處理功能,全部的libvlc的源代碼都放在src目錄及其子目錄
./config/: 從命令行和配置文件中加載配置
./control/: 提供動做控制功能,如播放等操做
./extras/: 大可能是平臺的特殊代碼
./modules/: 模塊管理
./network/: 提供網絡接口(socket管理,網絡接口)
./osd/: 顯示屏幕上的操做
./test/: libvlc測試模塊
./text/: 字符集
./interface/: 提供代碼中能夠調用的接口,如按鍵後的硬件做出反應
./playlist/: 管理播放功能
./input/: 創建並讀取一個輸入流,而且分離其中的音頻和視頻,而後把分離好的音頻和視頻流發給解碼器
./audio_output/: 初始化音頻混合器,即設置正確的同步頻率,並對從解碼器傳來的音頻流從新取樣
./video_output/: 初始化視頻播放器,把從解碼器獲得視頻畫面轉化格式從yuv到rgb,而後播放
./stream_output/ 輸出音頻流和視頻流到網絡
./misc/: libvlc使用的其餘部分功能,如線程系統,消息隊列等.
1、首先介紹一下vlc啓動動態加載模塊的過程:
1. 最早程序段入口是文件Vlc.c(./bin/)中的main()函數完成的Functions(parse command line, start interface and spawn threads),在main中程序會調用libvlc_new函數(./lib/Core.c)接口,實現建立一個VLC運行實例libvlc_instance_t,該實例在程序運行過程當中惟一。
2. 在libvlc_new函數接口中,調用了libvlc_InternalInit()函數實現具體的初始化工做。
3. libvlc_InternalInit(./src/Libvlc.c) 函數中,首先經過system_Init()函數完成傳入參數對系統的相關初始化,接着經過module_InitBank ()(./src/modules/Bank.c)函數初始化module_bank結構體,並建立了main模塊,而後(不支持動態載入的時候則經過 module_LoadBuiltins載入靜態模塊)經過module_LoadPlugins(./src/modules/Bank.c)函數載入 動態模塊,經過 module_need(./src/modules/Modules.c)函數載入並激活memcpy模塊,經過playlist_Create(. /src/playlist/playlist.c)函數,建立了一個playlist播放管理的線程,其線程處理函數爲RunThread(./src /stream_out/sap.c),經過intf_Create(./src/interface/Interface.c)函數添加並激活 hotkeys模塊,最後根據系統設置定義了宏HAVE_X11_XLIB_H,所以還須要添加screensaver模塊。
4. 此時加載的模塊有main,hotkeys,screensaver,memcpy;多建立了一個線程,用於管理playlist,該線程無限循環,直到p_playlist->b_die狀態爲止。
5. 其次程序中建立VLM對象,該接口調用的是vlm_New(./src/input/Vlm.c)函數,實現VLM對象的建立,函數返回值是指向vlm_t的指針。
6. vlm_New 函數中,建立了一個vlm管理線程,線程處理函數爲Manage(./modueles/video_output/msw/Glwin32.c)。該函 數循環處理當前各類媒體(vod、 broadcast、schedule)的播放實例,控制其每一個播放細節(如:從一個input切換到下一個input;schedule週期循環調度 等)。與playlist線程不一樣的是,Manage主要針對播放實例的操做,而RunThread主要針對播放列表的管理,也就是說VLC管理是分級 的,播放列表級和播放列表中媒體播放實例級。
7. 其次程序載入播放節目單,該接口調用的是ExecuteLoad(./src/input/Vlmshell.c)函數,在該函數中,依次調用以下函數:stream_UrlNew、stream_Seek、stream_Read、Load。
8. 接着程序調用libvlc_vlm_play_media(./lib/Vlm.c)將節目流發佈出去,實質是調用 ExecuteCommand(./src/input/Vlmshell.c),完成對命令的執行,根據命令類型,由 ExecuteControl(./src/input/Vlmshell.c)函數處理。
9. 而後由vlm_ControlMediaInstanceStart(./src/input/Vlm.c)函數完成播放實例的初始化,並調用input_CreateAndStart(./src/input/input.c)函數,input_CreateAndStart實際調用的是input_Create和input_Start(./src/input/input.c),在input_Start函數中實際調用vlc_clone最終完成播放線程的,線程的處理函數爲 Run(./src/input/input.c)。
10. Run線程是整個VLC做爲流媒體服務器的核心。其主要分爲以下幾個步驟:Init、MainLoop和End。其中MainLoop是一個無限循環,是完成流媒體的整個發佈過程。
2、分別介紹獲取、轉化、播放
Rtsp協議獲取rtp數據包:
1. 調用用函數rtsp_connect(./modules/access/rtsp/Rtsp.c)向服務器發出rtsp請求,而後函數rtsp_get_answers將會處理rtsp服務器反饋回來的信息,若是創建成功,則進入下一步。
2. 而後進行創建rtsp交互,依次調用的函數 是:rtsp_request_optionsàrtsp_request_describeàrtsp_request_setupàrtsp_request_setparameteràrtsp_request_playàrtsp_request_tearoff, 完成創建交互和關閉交互。
3. 詳細的是在成功創建以後而後調用的是rtsp_read_data(./modules/access/rtsp/Rtsp.c)函數進行獲取不透明的rtp數據實際填充的rtsp_client_t結構體最終實現完成數據的獲取。
Rtp數據包的轉換:
1. 獲取rtp數據以後進行的轉換就是yuv格式到rgb格式,使用的文件是 i420_rgb.c(./modules/video_chroma/i420_rgb.c)來是完成視頻格式的轉換。
2. 首先要對rtp數據流進行解碼,調用的函數是Rtp.c(./modules/access/rtp/Rtp.c)對rtp數據流進行demux,實際首 先調用rtp_autodetect(./modules/access/rtp/Rtp.c)去探測rtp數據包,而後調用函數 codec_decode(./modules/access/rtp/Rtp.c)把rtp數據包發送到decoder線程進行解碼。
3. 在codec_decode函數中實際調用的接 口是es_out_Control(./include/Vlc_es_out.h)和es_out_Send(./include /Vlc_es_out.h)來完成傳送數據包到解碼器,而後進入Decode.c(./src/input /Decodec.c)DecodeCreate等函數接口進行流解碼。
rgb數據的播放:
1. 在進行圖像格式的轉換成rgb格式以後由vout_new_buffer(./src/input/Decodec.c)接口實現由解碼器送到顯示器模 塊,在顯示器經過vout_Request(./src/video_output/video_output.c)接口去獲取解碼以後的rgb格式的圖 片或者子圖片。
2. 在vout_Request(./src/video_output/video_output.c)接口中若是vout原來存在的話就會進行嘗試重使 用,經過spu_Attach(./src/video_output/vout_subpictures.c)函數接口進行流單元的附屬操做,完成再使 用vout。
3. 若是vout不存在的,則轉向VoutCreate(./src/video_output/video_output.c)函數接口進行建立vout, 在該函數接口調用spu_Create(./include/Vlc_spu.h)進行流單元的建立,最終完成vout的建立,並建立處理線程 Thread。
4. 處理線程Thread(./src/video_output/video_output.c)來實際調用ThreadDisplaySubpicture以及結合其餘控制函數接口來完成流的控制和播放。
參考資料:vlc官網:http://wiki.videolan.org/Developers_Corner
從接收到數據流到播放視頻的過程分析
從網絡接收到流->對數據流進行視頻和音頻分離->對視頻用解碼器解碼->顯示解碼後的視頻流
視頻顯示部分走勢線:分離->解碼->新的VOUT緩衝區->VOUT線程
Demux(modules\demux\mpeg\ps.c)->DemuxPs(modules\demux\mpeg\system.c)-> ParsePS->input_SelectES(src\input\input_programs.c)->input_RunDecoder(src\input\input_dec.c)->CreateDecoder->
vout_new_buffer->vout_Request(src\video_output\video_output.c)->vout_Create->RunThread->vout_RenderPicture(src\video_output\vout_pictures.c)->pf_display
注意:p_dec->pf_vout_buffer_new = vout_new_buffer的pf_vout_buffer_new在ffmpeg_NewPictBuf(modules\codec\ffmpeg\video.c)函數中激活
解碼部分走勢線:
Demux(modules\demux\mpeg\ps.c)->DemuxPs(modules\demux\mpeg\system.c)-> ParsePS->input_SelectES(src\input\input_programs.c)->input_RunDecoder(src\input\input_dec.c)->CreateDecoder->DecoderThread
注意:在解碼線程中對數據流(AUDIO 或者VIDEO)進行解碼
詳細資料 http://developers.videolan.org/vlc/ VLC API documentation 或者VLC developer documentation
Chapter 5. The video output layer Data structures and main loop
Important data structures are defined in include/video.h and include/video_output.h. The main data structure is picture_t, which describes everything a video decoder thread needs. Please refer to this file for more information. Typically, p_data will be a pointer to YUV planar picture.
Note also the subpicture_t structure. In fact the VLC SPU decoder only parses the SPU header, and converts the SPU graphical data to an internal format which can be rendered much faster. So a part of the "real" SPU decoder lies in src/video_output/video_spu.c.
The vout_thread_t structure is much more complex, but you needn't understand everything. Basically the video output thread manages a heap of pictures and subpictures (5 by default). Every picture has a status (displayed, destroyed, empty...) and eventually a presentation time. The main job of the video output is an infinite loop to : [this is subject to change in the near future]
Find the next picture to display in the heap.
Find the current subpicture to display.
Render the picture (if the video output plug-in doesn't support YUV overlay). Rendering will call an optimized YUV plug-in, which will also do the scaling, add subtitles and an optional picture information field.
Sleep until the specified date.
Display the picture (plug-in function). For outputs which display RGB data, it is often accomplished with a buffer switching. p_vout->p_buffer is an array of two buffers where the YUV transform takes place, and p_vout->i_buffer_index indicates the currently displayed buffer.
Manage events.
Methods used by video decoders
The video output exports a bunch of functions so that decoders can send their decoded data. The most important function is vout_CreatePicture which allocates the picture buffer to the size indicated by the video decoder. It then just needs to feed (void *) p_picture->p_data with the decoded data, and call vout_DisplayPicture and vout_DatePicture upon necessary.
picture_t * vout_CreatePicture ( vout_thread_t *p_vout, int i_type, int i_width, int i_height ) : Returns an allocated picture buffer. i_type will be for instance YUV_420_PICTURE, and i_width and i_height are in pixels.
WarningIf no picture is available in the heap, vout_CreatePicture will return NULL.
vout_LinkPicture ( vout_thread_t *p_vout, picture_t *p_pic ) : Increases the refcount of the picture, so that it doesn't get accidently freed while the decoder still needs it. For instance, an I or P picture can still be needed after displaying to decode interleaved B pictures.
vout_UnlinkPicture ( vout_thread_t *p_vout, picture_t *p_pic ) : Decreases the refcount of the picture. An unlink must be done for every link previously made.
vout_DatePicture ( vout_thread_t *p_vout, picture_t *p_pic ) : Gives the picture a presentation date. You can start working on a picture before knowing precisely at what time it will be displayed. For instance to date an I or P picture, you must wait until you have decoded all previous B pictures (which are indeed placed after - decoding order != presentation order).
vout_DisplayPicture ( vout_thread_t *p_vout, picture_t *p_pic ) : Tells the video output that a picture has been completely decoded and is ready to be rendered. It can be called before or after vout_DatePicture.
vout_DestroyPicture ( vout_thread_t *p_vout, picture_t *p_pic ) : Marks the picture as empty (useful in case of a stream parsing error).
subpicture_t * vout_CreateSubPicture ( vout_thread_t *p_vout, int i_channel, int i_type ) : Returns an allocated subpicture buffer. i_channel is the ID of the subpicture channel, i_type is DVD_SUBPICTURE or TEXT_SUBPICTURE, i_size is the length in bytes of the packet.
vout_DisplaySubPicture ( vout_thread_t *p_vout, subpicture_t *p_subpic ) : Tells the video output that a subpicture has been completely decoded. It obsoletes the previous subpicture.
vout_DestroySubPicture ( vout_thread_t *p_vout, subpicture_t *p_subpic ) : Marks the subpicture as empty.