1. 程式人生 > >VLC學習文件(載)

VLC學習文件(載)

一 videolan-howto-en-html

該文件完全描述了VideoLAN "流"的解決方法.

VideoLAN 專案包括兩個軟體.

1) VLC:以前是視訊流接收的客戶端,但是現在也可以作為服務端工作.

2) VLS:視訊服務端,能傳送 MPEG-1, MPEG-2 and MPEG-4 files, DVDs, digital satellite channels, digital terrestial television channels and live videos on the network in unicast or multicast.

1.VLC 在REDHAT 下的安裝

從下面的連結中下載 vlc的包和包所需要的庫,把他們都放在同一個目錄.

http://www.videolan.org/vlc/download-redhat.html

原始碼安裝:

原始碼安裝需要的庫如下:

libdvbpsi (compulsory) ,

mpeg2dec (compulsory) ,

libdvdcss if you want to be able to read encrypted DVDs ,

libdvdplay if you want to have DVD menu navigation ,

a52dec if you want to be able to decode the AC3 (i.e. A52) sound format often used in DVDs ,

ffmpeg, libmad, faad2 if you want to read MPEG 4 / DivX files ,

libogg & libvorbis if you want to read Ogg Vorbis files .

2.VLC在命令列下接收流

Receive an unicast stream

% vlc -vvv udp:

Receive a multicast stream

% vlc -vvv udp:@239.255.12.42

where 239.255.12.42 is the multicast IP address you want to join.

Receive an HTTP/FTP/MMS stream

Use one of the following command lines:

% vlc -vvv http://example/stream.xyz

where http://example/stream.xyz is the HTTP address of the stream;

% vlc -vvv ftp://example/stream.xyz

where ftp://example/stream.xyz is the FTP address of the stream;

% vlc -vvv ms://viptvr.yacast.fr/encoderfranceinfo

where mms://viptvr.yacast.fr/encoderfranceinfo is the MMS address of the stream.

Receive a RTP stream available through RTSP

% vlc -vvv rtsp://www.hardradio.com/tonbeme.mov

where rtsp://www.hardradio.com/tonbeme.mov is the address of the stream.

Receive a stream described by an SDP file

% vlc -vvv http://server.example.org/stream.sdp

3.VLC在命令列下發送流

% vlc -vvv video1.xyz --sout udp:192.168.0.42 --ttl 12

where:

*video1.xyz is the file you want to stream,

*192.168.0.42 is either:

o the IP address of the machine you want to unicast to;

o or the DNS name the machine you want to unicast to;

o or a multicast IP address.

*12 is the value of the TTL (Time To Live) of your IP packets (which means that the stream will be able to cross 11 routers).

If you want to stream the file continuously, add the --loop option.

4.VLC 高階應用(VLC's stream output (transcoding, multiple streaming, etc...))

語法: Please refer to the" command line interface" chapter of the "VLC user guide "to learn the syntax of VLC's stream output.

例子:

----編碼方面的例子

Transcode the input stream and send it to a multicast IP address with the associated SAP announce:

% vlc -vvv input_stream --sout '#transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}:

standard{access=udp,mux=ts,url=239.255.12.42,sap,name="TestStream"}'

Display the input stream, transcode it and send it to a multicast IP address with the associated SAP announce:

% vlc -vvv input_stream --sout '#duplicate{dst=display,dst=

"transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}:

standard{access=udp,mux=ts,url=239.255.12.42,sap,name="TestStream"}"}'

Transcode the input stream, display the transcoded stream and send it to a multicast IP address with the associated SAP announce:

% vlc -vvv input_stream --sout '#transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}:

duplicate{dst=display,dst=standard{access=udp,mux=ts,url=239.255.12.42,sap,name="TestStream"}}'

--多種流的例子

Send a stream to a multicast IP address and a unicast IP address:

% vlc -vvv input_stream --sout '#duplicate{dst=

standard{access=udp,mux=ts,url=239.255.12.42,sap,name="TestStream"},

dst=standard{access=udp,mux=ts,url=192.168.1.2}}'

Display the stream and send it to two unicast IP addresses:

% vlc -vvv input_stream --sout '#duplicate{dst=display,dst=

standard{access=udp,mux=ts,url=192.168.1.12},

dst=standard{access=udp,mux=ts,url=192.168.1.42}}'

Send parts of a multiple program input stream:

% vlc -vvv multiple_program_input_stream

--sout '#duplicate{dst=standard{access=udp,mux=ts,url=239.255.12.42},select="program=12345",

dst=standard{access=udp,mux=ts,url=239.255.12.43}, select="video,program=1234-2345"}'

This command sends the program of the input stream which id is 12345 to 239.255.12.42 and all video programs with id between 1234 and 2345 to 239.255.12.43.

Transcoding and multiple streaming

Transcode the input stream, display the transcoded stream and send it to a multicast IP address with the associated SAP announce and an unicast IP address:

% vlc -vvv input_stream --sout '#transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128,deinterlace}:

duplicate{dst=display,dst=standard{access=udp,mux=ts,url=239.255.12.42,sap,name="TestStream"},

dst=standard{access=udp,mux=ts,url=192.168.1.2}}'

Display the input stream, transcode it and send it to two unicast IP addresses:

% vlc -vvv input_stream --sout '#duplicate{dst=display,

dst="transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128}:

duplicate{dst=standard{access=udp,mux=ts,url=192.168.1.2},

dst=standard{access=udp,mux=ts,url=192.168.1.12}"}'

Send the input stream to a multicast IP address and the transcoded stream to another multicast IP address with the associated SAP announces:

% vlc -vvv input_stream --sout '#duplicate{dst=

standard{access=udp,mux=ts,url=239.255.1.2,sap,name="OriginalStream"},

dst="transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128}:

standard{access=udp,mux=ts,url=239.255.1.3,sap,name="TranscodedStream"}"}'

 二、二進位制包安裝及使用

1.在RH9上的安裝需要

     1).RH9的升級包.

     2).FC2的RPM包

    詳細說明清參見:http://www.videolan.org/vlc/download-redhat.html

    以上VLC 版本為:0.7.2

2.下載RH9的升級包

    http://download.videolan.org/pub/videolan/vlc/0.7.2/rpm/redhat/rh9/

3.下載FC2的RPM包

  http://download.videolan.org/pub/videolan/vlc/0.7.2/rpm/fedora/fc2/

   二進位制包為:  vlc-binary.tar.gz

4.將RH9的升級包和 vlc-binary.tar.gz放在同一個目錄.

   ~#tar -zxvf   vlc-binary.tar.gz

   ~#tar -zxvf   redhat9-updates.tar.gz

 5.安裝

   ~#rpm -Uv  vlc/* --force --nodeps

6.使用

    1) 在REDHAT->AUDIO AND VIDEO->VLAN MEDIA PLAYER 可以開啟

     2)或者在BASH 中開啟vlc,使用命令列選項直接啟動,參見videolan-how-to-en.

7.未測試出的功能

      在區域網內的同一網段內的兩臺PC上不能用MULTICAST 進行VIDEO

      傳輸.

三、 VLC及其他播放器

一.rm格式的播放器:

  下載地址:http://www.real.com/linux/?src=020923home_cn_cn

  安裝方式:~#./realplayer.bin

        開啟方式:

     命令列:~#realplay

                    GUI:redhat->audio and video->other app->realplayer  

二.mp3 播放器:xmms-1.2.8.tar.gz

      安裝方式:./configure & make &make install

三. 經驗:從原始碼編譯安裝Mplayer 1.0pre5

 來自:http://yangchengkai.blogchina.com/blog/refer.177855.html

  Mplayer/gmplayer是目前Linux下廣範使用的媒體播放器,一個字--強!但由於它一般以Tarball的格式釋出,安裝比較BT,許多朋友都在找rpm的版本,但來源不同的rpm版本往往無法自己定製許多特性,比如中文支援等,而且容易造成rpm包的依賴問題,所以有不少朋友最終對 Mplayer又愛又恨...-_-!!

其實自己編譯mplayer並不是什麼太難的事,只是過程比較麻煩,但基本還是遵循tarball的安裝步驟,有關這個的文章Sir裡已經有了不少,自己這篇就不打算往Sir裡貼了,且留在這裡和大家分享...:)

首先是下載最新的mplayer的tarball,即1.0pre5:

http://www4.mplayerhq.hu/homepage/design7/dload.html

接下來是下載解碼器包,一般只要下載Essential Codes就足夠了,要放rmvb需要reallib的解碼器,我一般用xine放rmvb:

http://www4.mplayerhq.hu/homepage/design7/codecs.html

還有mplayer的字型檔案:

http://www4.mplayerhq.hu/homepage/design7/dload.html

這裡大家不用到"其他字型"裡下載中文字型,待會可以用simsun.ttf替代.

當然,還要下載Skin檔案給gmplayer用:

http://ftp5.mplayerhq.hu/mplayer/Skin/

建議用default blue或者neutron,當然,你也可以下載其他的Skin.

我們先把下載的所有檔案cp到/opt/目錄下,然後開始具體安裝步驟.

1.首先安裝解碼器:

tar -jxvf essential-20040916.tar.bz2

tar -jxvf rp9codecs-20040626.tar.bz2

cp -rf rp9codecs-20040626/* essential-20040916/

mv essential-20040916 /usr/lib/codes

以上命令把解碼器包安裝到了/usr/lib/codes,其實就是把解壓後的目錄ren&mv了過去.

2.編譯安裝mplayer:

tar -jxvf MPlayer-1.0pre5.tar.bz2

cd MPlayer-1.0pre5

./configure --enable-gui --with-codecsdir=/usr/lib/codecs --with-win32libdir=/usr/lib/codecs --with-reallibdir=/usr/lib/codecs --language=zh_CN

以上幾個引數解釋一下:

--enable-gui:開啟圖形介面支援,就是gmplayer

--with-codecsdir=/usr/lib/codecs:指明解碼器的目錄

--with-win32libdir=/usr/lib/codecs:指明windows的媒體檔案解碼器目錄位置

--with-reallibdir=/usr/lib/codecs:指明real媒體檔案的解碼器目錄位置,要用gmplayer放rmvb必須指定這條.

--language=zh_CN:設定系統介面語言為中文

在configure之前可以執行./configure --help檢視支援的特性設定,可以根據自己需求選擇,以上只是最基本的啦.

make

make install

3.安裝字型檔案:

tar -jxvf font-arial-iso-8859-1.tar.bz2

mv font-arial-iso-8859-1/ /usr/local/share/mplayer/font/

cd /usr/local/share/mplayer/font/

如果你的系統用simsun美化過,則直接

ln -s ***/simsun.ttf subfont.ttf

注意,這裡的***是指simsun的具體位置,為了保險起見,建議在~/.mplayer/裡也做同樣的連結.

要是系統沒有美化過,試試

ln -s /usr/share/fonts/zh_CN/TrueType/gbsn001p.ttf subfont.ttf

這樣中文字幕就搞定了.

4.安裝Skin:

超級簡單,把skin包解壓後mv到/usr/local/share/mplayer/Skin就可以了,注意一定要有一個skin叫做default,不然gmplayer無法執行.

OK,目前為止所有工作結束,執行gmplayer/mplayer看看,Enjoy it!:)

PS:要是你用xine,在setup裡可以把codes的目錄指定同mplayer一樣,這樣可以節省點空間^_^

5.nvidia driver 驅動安裝:

   下載:http://www.nvidia.com/object/linux_display_ia32_1.0-4363.html

    安裝:

              進入LEVEL 2  ,init 2

   配置: 在/etc/X11/XF86config

           load 'nv'  改成 load 'nvidia'

           load 'dri' 改成 load 'GLcore'

 在文字模式下:

#vim /etc/X11/XF86Config

找到Driver "nv",改為“nvidia”

去除 Load "dri"

Load "GLcore"

儲存後退出,再進入X桌面

看到NVIDIA畫面就OK了

  四、在EMACS中使用GDB除錯

一 .EMACS 中除錯

  1、using the clipboard

                M-x  menu-bar-enable-clipboard

        (make cut,copy,pasty menu items,use the clipboard)

  2、using “wheel”mice

              M-x   mouse-wheel-mode

         (啟用中間的滾動鍵)

  3、退出出任何命令狀態

         C-g

  4、進入編譯模式

       M-x  compile 或者從選單-》TOOLS-》COMPILE

  5、用COMPILE 模式

       C-x  `       (搜尋出錯的原始碼行)

       <RET>    (游標定位在compile buffer 的出錯提示行上,按〈RET〉鍵,會跳到出錯的原始碼行)

      C-u C-x ` 在compile buffer 列出同樣的錯誤。

   6、用GREP 搜尋

       一、M-x grep    進入搜尋

              引數為 a grep-style regexp(using in single-quotes to quote the shell's special characters)follows bye file names;

       二、 C-x  `       (搜尋出錯的原始碼行 --grep  搜尋出來的同種錯誤)

         <RET>    (游標定位在grep  buffer 的出錯提示行上,按〈RET〉鍵,會跳到出錯的原始碼行)

二、GUD 除錯

   1、進入

        M-x gdb

   2、命令

        C-x <SPC>     在指標所在原始碼行上設定斷點

    說明 C-c 在GUD BUFFER,而C-x C-a 在gud buffer and source buffer 都行

    3、  C-c    C-l

            C-x C-a   C-l   到達最後一行

    4、C-c   C-s

          C-x C-a  C-s      gud-step

    5、C-c   C-n

          C-x C-a  C-n      gud-next

     6、C-c C-r

            C-x C-a  C-r  gud-cont  執行到下一個斷點

      7、C-c  C-d

            C-x C-a  C-d   gud-remove 刪除當前斷點

三、GDB 命令

    1、除錯命令

          step         next          continue          untile

     2、設定斷點

           break file.c:foo

           break  file.c:11

           break +12

           break -12        如果執行到某一行,+表示往前,-表示向後

          斷點資訊

             info breakpoint

             enable <breakpoint number>

             disable  <breakpoint number>

            斷點條件

              break <args> if <cond>

              condition <break number> <cond>

              delete  breakpoints <break number> 

             clear

    3、顯示原始碼

           list 使用同斷點

    4、檢視變數

          print /fmt  <expr>

     5、檢視記憶體

          x /<fmt>  <addr>

     6、切換目錄

             cd

     7、新增原始檔路徑

           dir <path>

     8、顯示

           如果有    char msg[25];

                           int *arr=(int *)mollac(len*sizeof(int));

            則    display msg

                    display *[email protected]

             或者  p msg

         9、跳轉執行

             jump linespec

             jump  <addr>

四、Makefile 檔案

//mt.h

#ifdef _cplusplus

extern "c" {

#endif

int add(int a,int b);

int substract(int num,int n,int *ret);

#ifdef _cplusplus

}

#endif

-----------------------------------------------

//math.c

#include"mt.h"

int add(int a,int b)

 {  return (a+b);}

int subtract(int num,int n,int *ret)

{*ret=num-n;

return *ret;

}

-----------------------------------------------

//msg.h

#ifdef _cplusplus

extern "c" {

#endif

void prnmsg(char *msg);

#ifdef _cplusplus

}

#endif

-----------------------------------------------

//msg.c

#include<stdio.h>

#include"msg.h"

void prnmsg(char * msg)

{  printf("%s\n",msg);}

-----------------------------------------------

//comm.h

#include"mt.h"

#include"msg.h"

-----------------------------------------------

//vlc.c

#include<stdlib.h>

#include<stdio.h>

#include"comm.h"

int main(int argc,char *argv[])

{

   int i,j,sum;

   int *p_iret;

  char  msg[256];

    printf("hellow,this is a test program\n");

    i=15;

    j=10;

    sum=add(i,j);

   sprintf(msg,"number=%d",sum);

    prnmsg(msg);

   subtract(i,j,p_iret);

   sprintf(msg,"substract=%d",*p_iret);

   prnmsg(msg);

   sprintf(msg,"this has modify=%d",*p_iret);

   prnmsg(msg);

   return 0;

}

-----------------------------------------------

//Makefile

vlc:vlc.o math.o msg.o

    gcc -g -o [email protected] vlc.o  math.o msg.o

math.o:math.c mt.h

    gcc -g -c -o [email protected] math.c

msg.o:msg.c msg.h

    gcc -g -c msg.c

vlc.o:vlc.c comm.h

    gcc -g -c  vlc.c

clean:

    rm -rvf msg.o math.o vlc.o vlc

vlc學習計劃(5)--VLC程式巨集及執行緒分析

第一部分             變數及巨集定義

1.訊息對映巨集

                       vlc_module_begin();

                           …………………..

vlc_module_end();

2.結構中包含函式

       struct input_thread_t

{

    VLC_COMMON_MEMBERS

    /* Thread properties */

    vlc_bool_t              b_eof;

    vlc_bool_t              b_out_pace_control;

    /* Access module */

    module_t *       p_access;

    ssize_t       (* pf_read ) ( input_thread_t *, byte_t *, size_t );

    int           (* pf_set_program )( input_thread_t *, pgrm_descriptor_t * );

    int           (* pf_set_area )( input_thread_t *, input_area_t * );

    void          (* pf_seek ) ( input_thread_t *, off_t );

}

3.巨集與換行符妙用

#define VLC_COMMON_MEMBERS                                                  \

/** \name VLC_COMMON_MEMBERS                                                \

 * these members are common for all vlc objects                             \

 */                                                                         \

/**@{*/                                                                     \

    int   i_object_id;                                                      \

    int   i_object_type;                                                    \

    char *psz_object_type;                                                  \

    char *psz_object_name;                                                  \

                                                                                               \

 /** Just a reminder so that people don't cast garbage */                \

    int be_sure_to_add_VLC_COMMON_MEMBERS_to_struct;                        \

/**@}*/                   

#define VLC_OBJECT( x ) \

((vlc_object_t *)(x))+

0*(x)->be_sure_to_add_VLC_COMMON_MEMBERS_to_struct

struct vlc_object_t

{

    VLC_COMMON_MEMBERS

};//定義一個結構來使用巨集定義的公共成員

4.定義匯出函式

#ifndef __PLUGIN__

#   define VLC_EXPORT( type, name, args ) type name args

#else

#   define VLC_EXPORT( type, name, args ) struct _u_n_u_s_e_d_

    extern module_symbols_t* p_symbols;

#endif

5.定義回撥函式

typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */

                                   char const *,            /* variable name */

                                   vlc_value_t,                 /* old value */

                                   vlc_value_t,                 /* new value */

                                   void * );                /* callback data */                                                

6.函式作為引數的定義方式

     Int Fun(int n,int (*pf)(int ,int),char *pstr)

{   int j =10;

pf(n,j);

}

7.回撥函式的宣告

必須宣告為global,或者static

Int   vlc_callback_t (int ,int)

{。。。。。。。。。。。}

8.回撥函式的使用

       Fun(0, vlc_callback_t,"test");

9.函式表示式

#define input_BuffersInit(a) __input_BuffersInit(VLC_OBJECT(a))

void * __input_BuffersInit( vlc_object_t * );

#define module_Need(a,b,c,d) __module_Need(VLC_OBJECT(a),b,c,d)

VLC_EXPORT( module_t *, __module_Need, ( vlc_object_t *, const char *, const char *, vlc_bool_t ) );

10.定義函式

   /* Dynamic array handling: realloc array, move data, increment position */

#define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \

    do                                                                        \

    {                                                                         \

        if( i_oldsize )                                                       \

        {                                                                     \

            (p_ar) = realloc( p_ar, ((i_oldsize) + 1) * sizeof( *(p_ar) ) );  \

        }                                                                     \

        else                                                                  \

        {                                                                     \

            (p_ar) = malloc( ((i_oldsize) + 1) * sizeof( *(p_ar) ) );         \

        }                                                                     \

        if( (i_oldsize) - (i_pos) )                                           \

        {                                                                     \

            memmove( (p_ar) + (i_pos) + 1,                                    \

                     (p_ar) + (i_pos),                                        \

                     ((i_oldsize) - (i_pos)) * sizeof( *(p_ar) ) );           \

        }                                                                     \

        (p_ar)[i_pos] = elem;                                                 \

        (i_oldsize)++;                                                        \

    }                                                                         \

    while( 0 )

應用為:

     INSERT_ELEM( p_new->p_libvlc->pp_objects,

                     p_new->p_libvlc->i_objects,

                     p_new->p_libvlc->i_objects,

                     p_new );

11.改變地址的方式傳遞其值

stream_t *input_StreamNew( input_thread_t *p_input )

{    stream_t *s = vlc_object_create( p_input, sizeof( stream_t ) );

    input_stream_sys_t *p_sys;

    if( s )

    {

        s->p_sys = malloc( sizeof( input_stream_sys_t ) );

        p_sys = (input_stream_sys_t*)s->p_sys;

        p_sys->p_input = p_input;

    }

return s;//註解:s->p_sys改變了

}

                            第二部分  程式框架實現

1. 播放列表檔案src/playlist/playlist.c的執行緒

playlist_t * __playlist_Create ( vlc_object_t *p_parent )函式中建立的執行緒,執行緒函式為

static void RunThread ( playlist_t *p_playlist )

   執行緒思路分析:

     在RunThread裡面執行迴圈,如果沒有任務執行,則適當的延遲,如果接到p_playlist->i_status != PLAYLIST_STOPPED的條件,則呼叫PlayItem( p_playlist )函式,在PlayItem( p_playlist )函式中從新建立輸入執行緒。

通過void playlist_Command( playlist_t * p_playlist, playlist_command_t i_command,int i_arg )接收來自GUI介面的各種命令,然後設定p_playlist->i_status的狀態,由該狀態改變該播放列表檔案主迴圈執行緒的執行。

2. 輸入檔案SRC/INPUT/INPUT.C的輸入執行緒

    input_thread_t *__input_CreateThread( vlc_object_t *p_parent,

                                      input_item_t *p_item )函式中建立的執行緒,執行緒函式為

static int RunThread( input_thread_t *p_input )

   執行緒思路分析:

由 input_thread_t結構的成員分析是接收檔案流還是網路流,如果是檔案流,則呼叫file module 的讀函式(pf_read)和開啟函式(--).如果是network 則開啟network   module 的開啟函式和讀函式(pf_read)。

    在 RunThread執行緒函式中接收資料和呼叫demux 或者decode etc處理。

一旦產生新的輸入,則在播放列表執行緒中會首先結束該輸入執行緒,然後從新建立新的輸入執行緒。

3. 視訊輸出檔案src/video_output/ video_output.c的執行緒

vout_thread_t * __vout_Create( vlc_object_t *p_parent,

                               unsigned int i_width, unsigned int i_height,

                               vlc_fourcc_t i_chroma, unsigned int i_aspect )函式中建立的執行緒,執行緒函式為

static void RunThread( vout_thread_t *p_vout)

執行緒思路分析:

     在RunThread裡面執行迴圈,任務是顯示視訊。

4. 在modules\gui\wxwindows\wxwindows.cpp中的GUI執行緒

 static void Run( intf_thread_t *p_intf ) 函式中建立的執行緒,執行緒函式為

             static void Init( intf_thread_t *p_intf )

執行緒思路分析:

     在Init( intf_thread_t *p_intf )裡面執行迴圈,建立新的GUI例項。Instance-》OnInit()(CreateDialogsProvider)-》DialogsProvider為執行的對話方塊。

     接收網路檔案的步驟

OnOpenNet( wxCommandEvent& event )開啟網路檔案的步驟。開啟OpenDialog對話方塊,點選Ok後呼叫OpenDialog::OnOk( wxCommandEvent& WXUNUSED(event) )函式,呼叫playlist_Command函式改變播放列表執行緒的狀態。

  啟用執行緒分析:

         在wxwindow.cpp中的訊息對映中 set_callbacks( OpenDialogs, Close ); 則設定了module_t->pf_activate= OpenDialogs函式,

        在module.c 的__module_Need( vlc_object_t *p_this, const char *psz_capability,

                          const char *psz_name, vlc_bool_t b_strict )

函式中用到了pf_activate啟用GUI對話方塊;

    在video_output.c 的static void RunThread( vout_thread_t *p_vout)執行緒中,也用到了pf_activate啟用GUI對話方塊;

5. 開始所有module 的精髓

         訊息對映巨集

                       vlc_module_begin();

                          set_callbacks( NetOpen, NULL );

vlc_module_end();

然後設定模組結構的成員函式為:

#define set_callbacks( activate, deactivate )                                 \

               p_submodule->pf_activate = activate;                                      \

                 p_submodule->pf_deactivate = deactivate

在__module_Need函式中啟動pf_activate  啟用相應的module。

1. 我的理解:

macro of message map

2./*********

*定義一個公共的結構

*並把啟用本模組的函式傳給該結構的函式成員

************************/

vlc_module_begin();

set_callbacks( NetOpen, NULL );

vlc_module_end();

設定模組結構的pf_activate成員函式為NetOpen:

#define set_callbacks( activate, deactivate ) \

p_submodule->pf_activate = activate; \

p_submodule->pf_deactivate = deactivate

所以當通過函式module_need啟用模組的時候,就是通過pf_activate來啟動模組的!

vlc_module_begin()起到了一個訊息傳遞的作用!

vlc學習計劃(6)--網路資料流接收處理過程分析

網路資料流接收處理分析

1、在input.c(src\input)檔案中的主執行緒迴圈

      Thread in charge of processing the network packets and demultiplexing

RunThread( input_thread_t *p_input )

{

          InitThread( p_input ) ;

…………………………………………………….

     input_SelectES( p_input, p_input->stream.p_newly_selected_es );

              …………………………………………………….

      /* Read and demultiplex some data. */

     i_count = p_input->pf_demux( p_input );

}

2、在下列函式中:

分離出access  , demux  , name字串 ;

根據分離出的access  字串通過module_Need函式找到acess 指標模組;

根據分離出的demux  字串通過module_Need函式找到demux  指標模組;

 static int InitThread( input_thread_t * p_input )

{

     msg_Dbg( p_input, "access `%s', demux `%s', name `%s'",

             p_input->psz_access, p_input->psz_demux, p_input->psz_name );

    /* Find and open appropriate access module */

    p_input->p_access = module_Need( p_input, "access",

                                     p_input->psz_access, VLC_TRUE );

 …………………………………………………….

  while( !input_FillBuffer( p_input ) )

  …………………………………………………….

    /* Find and open appropriate demux module */

    p_input->p_demux =

        module_Need( p_input, "demux",

                     (p_input->psz_demux && *p_input->psz_demux) ?

                     p_input->psz_demux : "$demux",

                     (p_input->psz_demux && *p_input->psz_demux) ?

                     VLC_TRUE : VLC_FALSE );

…………………………………………………….

}

3、在ps.c (module\demux\mpeg)檔案中

a.通過訊息對映巨集賦值啟動函式Activate;

b.通過函式Activate賦值p_input->pf_demux = Demux;

c. 通過函式module_Need( p_input, "mpeg-system", NULL, 0 ) 啟用p_input->p_demux_data->mpeg.pf_read_ps( p_input, &p_data )函式(pf_read_ps);

d.在InitThread函式中啟用;

        static int Activate( vlc_object_t * p_this )

{

      /* Set the demux function */

p_input->pf_demux = Demux;

p_input->p_private = (void*)&p_demux->mpeg;

    p_demux->p_module = module_Need( p_input, "mpeg-system", NULL, 0 );

}

4、在system.c (module\demux\mpeg)檔案中

         賦值解碼模組mpeg_demux_t的成員函式;

     static int Activate ( vlc_object_t *p_this )

{

    static mpeg_demux_t mpeg_demux =

                    { NULL, ReadPS, ParsePS, DemuxPS, ReadTS, DemuxTS };

    mpeg_demux.cur_scr_time = -1;

    memcpy( p_this->p_private, &mpeg_demux, sizeof( mpeg_demux ) );

    return VLC_SUCCESS;

}

並且申明函式static ssize_t ReadPS( input_thread_t * p_input, data_packet_t ** pp_data );

5、在ps.c (module\demux\mpeg)檔案中

Demux( input_thread_t * p_input )

{

i_result = p_input->p_demux_data->mpeg.pf_read_ps( p_input, &p_data );

      p_input->p_demux_data->mpeg.pf_demux_ps( p_input, p_data );

}

進行讀取資料和分離工作;

6、在system.c (module\demux\mpeg)檔案中

資料走向圖如下

ReadPS-> PEEK-> input_Peek(src\input\input_ext-plugins.c)-> input_FillBuffert 通過 i_ret = p_input->pf_read( p_input,

                              (byte_t *)p_buf + sizeof(data_buffer_t)

                               + i_remains,

                              p_input->i_bufsize );

input_thread_t結構的pf_read函式成員如果是為udp.c(modules\access)的RTPChoose函式

則在開啟access(UDP 模組)時通過module_need 啟用;

 啟用網路讀資料模組 RTPChoose(modules\access\ udp.c)->Read->net_Read(src\misc\net.c);

7、在input_programs.c(src\input)檔案中

         執行解碼器對ES流解碼

   int input_SelectES( input_thread_t * p_input, es_descriptor_t * p_es )

{

      p_es->p_dec = input_RunDecoder( p_input, p_es );

}

 input_SelectES(src\input\input_programs.c)->input_RunDecoder(src\input\input_dec.c)->DecoderThread->DecoderDecode ->vout_DisplayPicture

vlc學習計劃(7)--從接收到資料流到播放視訊的過程分析

從接收到資料流到播放視訊的過程分析

   從網路接收到流->對資料流進行視訊和音訊分離->對視訊用解碼器解碼->顯示解碼後的視訊流

    視訊顯示部分走勢線:分離->解碼->新的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.

Warning

If 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.

相關推薦

VLC學習

一 videolan-howto-en-html 該文件完全描述了VideoLAN "流"的解決方法. VideoLAN 專案包括兩個軟體. 1) VLC:以前是視訊流接收的客戶端,但是現在也可以作為服務端工作. 2) VLS:視訊服務端,能傳送 MPEG-1,

linux學習

很快就要去公司實習了,所以最近在惡補linux作業系統的東西。之前學校有專門的作業系統的課程,從作業系統的發展開始講起,然後講解作業系統的程序排程,記憶體管理,檔案系統等等知識。同時也有與之相匹配的作業系統課程設計實驗課,做了幾個小實驗。但現在好多linux的命令都忘光了,

Activiti學習之畫流程圖並部署流程

上一節我們把 Activiti 的基礎環境給搭建好了,接下來的話就要使用到 Activiti 進行開發功能。當然了,在開發 Activiti 的時候,需要 :        a)先畫好流程圖;        b)部署流程;   這一節的話,我們就來講解這兩個步驟:    

php檔知識點整理函數、方法、

進行 兩種 排序 嚴重 進入 接收 [1] pan $max 函數: 函數定義形式: function 函數名 (形參1,形參2,.... ){ } 函數參數:(2種) 形參: 1,形參一定是一個變量名! 2,該變量名只能是在該函數中有效的變量名; 3,而

《Linux學習並不難》Linux網絡配置3:/etc/hosts

Linux /etc/hosts 26.3 《Linux學習並不難》Linux網絡配置文件(3):/etc/hosts文件當計算機啟動時,在可以查詢DNS以前,計算機需要查詢一些主機名到IP地址的匹配。這些匹配信息存放在/etc/hosts文件中。在沒有域名服務器的情況下,系統上的所有網絡程序都通過

《Linux學習並不難》Linux網絡配置4:/etc/networks

Linux /etc/networks 26.4 《Linux學習並不難》Linux網絡配置文件(4):/etc/networks文件/etc/networks文件定義了網絡名和網絡地址之間的映射關系,下面是/etc/networks文件內容的示例。default 0.0.0.0 loopback

Tushare學習十 電影票房

import tushare  as ts 1.實時票房 ts.realtime_boxoffice() BoxOffice 實時票房(萬) Irank 排名 MovieName 影片名 boxPer 票房佔比 (%) movieD

Tushare學習六 新聞事件資料

import  tushare  as  ts 1.即時新聞 ts.get_latest_news()  ,預設是80條新聞 ts.get_latest_news(數字小於八十) ts.get_latest_news(top=10,show_conten

Tushare學習三 股票分類資料

import tushare as ts 1.行業分類 ts.get_industry_classified()   2.概念分類 ts.get_concept_classified()   3.地域分類 ts.get_area_classified()  

Tushare學習交易資料

1.獲取歷史資料  ts.get_hist_data('601998')    獲取601998的歷史資料 ts.get_hist_data('601998',start='2016-06-05',end='2016-07-06')  獲取指定時間內的歷史資料 &

Tushare學習一 交易資料

1.復權資料 ts.get_h_data('002337') #前復權 ts.get_h_data('002337', autype='hfq') #後復權 ts.get_h_data('002337', autype=None) #不復權 ts.get_h_dat

Tushare學習二投資參考資料

import tushare as ts 1.分配預案(每到季報、年報公佈的時段,就經常會有上市公司利潤分配預案發布,而一些高送轉高分紅的股票往往會成為市場炒作的熱點。及時獲取和統計高送轉預案的股票是參與熱點炒作的關鍵,TuShare提供了簡潔的介面,能返回股票的送轉和

機器學習 Python scikit-learn 中文3使用 scikit-learn 介紹機器學習

與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn 與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn Logo 首頁 安裝 文件 案例 Fork me on GitHub Previous scikit-learn

機器學習 Python scikit-learn 中文2教程目錄

與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn 與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn scikit-learn 教程 使用 scikit-learn 介紹機器學習 機器學習:問題設定 載入示例資

機器學習 Python scikit-learn 中文 1

與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn 與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn Logo 首頁 安裝 文件 案例 ‹› scikit-learn 在Python中進行機器學習 簡單且高效的

機器學習 Python scikit-learn 中文7模型選擇: 選擇合適的估計器及其引數

模型選擇: 選擇合適的估計器及其引數 與官方文件完美匹配的中文文件,請訪問 https://www.studyai.cn Score, 和 cross-validated scores 交叉驗證生成器 網格搜尋與交叉驗證估計器 網格搜尋 自帶交叉驗證的估計器 模型選擇: 選擇

[知了堂學習筆記]列印生成wordjq

利用瀏覽器對jq外掛的支援進行列印 Html中給一個列印按鈕,id為jqprint 將所要列印的內容放入div中,div的id為print 直接.jqprint()列印—-1和2的區別放入下

java刪除夾下面的所有

str try 一個 ... cmd 刪除一個文件 文件夾 style exec 原文地址:http://blog.csdn.net/smach1991710/article/details/9175757 刪除一個文件夾下面的所有文件,一種調用遞歸算法,一種調用windo

NFC技術:使用Android Beam技術傳輸

imp 圖片 .com fault gen catch ret generate puts 1 public class MainActivity extends ActionBarActivity implements 2 CreateBeamUr

Cocos2dx 遍歷 夾下所有的草稿

cmp add cto filename () lena tin s2d sdi 備份,怕忘了 static std::vector<string> getFilePathAtVec(string folderPath, int depth) {