vlc 代码学习.docx

上传人:b****5 文档编号:8368532 上传时间:2023-01-30 格式:DOCX 页数:11 大小:23.62KB
下载 相关 举报
vlc 代码学习.docx_第1页
第1页 / 共11页
vlc 代码学习.docx_第2页
第2页 / 共11页
vlc 代码学习.docx_第3页
第3页 / 共11页
vlc 代码学习.docx_第4页
第4页 / 共11页
vlc 代码学习.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

vlc 代码学习.docx

《vlc 代码学习.docx》由会员分享,可在线阅读,更多相关《vlc 代码学习.docx(11页珍藏版)》请在冰豆网上搜索。

vlc 代码学习.docx

vlc代码学习

【转】vlc代码学习

第一部分变量及宏定义

1.消息映射宏

vlc_module_begin();

…………………..

vlc_module_end();

2.结构中包含函数

structinput_thread_t

{

VLC_COMMON_MEMBERS

/*Threadproperties*/

vlc_bool_tb_eof;

vlc_bool_tb_out_pace_control;

/*Accessmodule*/

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.宏与换行符妙用

#defineVLC_COMMON_MEMBERS/**\nameVLC_COMMON_MEMBERS*thesemembersarecommonforallvlcobjects*//**@{*/inti_object_id;int

i_object_type;char*psz_object_type;char*psz_object_name;/**Justaremindersothatpeopledon'tcastgarbage*/int

be_sure_to_add_VLC_COMMON_MEMBERS_to_struct;/**@}*/

#defineVLC_OBJECT(x)\

((vlc_object_t*)(x))+

0*(x)-be_sure_to_add_VLC_COMMON_MEMBERS_to_struct

structvlc_object_t

{

VLC_COMMON_MEMBERS

};//定义一个结构来使用宏定义的公共成员

4.定义导出函数

#ifndef__PLUGIN__

#defineVLC_EXPORT(type,name,args)typenameargs

#else

#defineVLC_EXPORT(type,name,args)struct_u_n_u_s_e_d_

externmodule_symbols_t*p_symbols;

#endif

5.定义回调函数

typedefint(*vlc_callback_t)(vlc_object_t*,/*variable'sobject*/

charconst*,/*variablename*/

vlc_value_t,/*oldvalue*/

vlc_value_t,/*newvalue*/

void*);/*callbackdata*/

6.函数作为参数的定义方式

IntFun(intn,int(*pf)(int,int),char*pstr)

{intj=10;

pf(n,j);

}

7.回调函数的声明

必须声明为global,或者static

Intvlc_callback_t(int,int)

{。

}

8.回调函数的使用

Fun(0,vlc_callback_t,”test”);

9.函数表达式

#defineinput_BuffersInit(a)__input_BuffersInit(VLC_OBJECT(a))

void*__input_BuffersInit(vlc_object_t*);

#definemodule_Need(a,b,c,d)__module_Need(VLC_OBJECT(a),b,c,d)

VLC_EXPORT(module_t*,__module_Need,(vlc_object_t*,constchar*,constchar*,vlc_bool_t));

10.定义函数

/*Dynamicarrayhandling:

reallocarray,movedata,incrementposition*/

#defineINSERT_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;

}

returns;//注解:

s-p_sys改变了

}

第二部分程序框架实现

1.播放列表文件src/playlist/playlist.c的线程

playlist_t*__playlist_Create(vlc_object_t*p_parent)函数中创建的线程,线程函数为

staticvoidRunThread(playlist_t*p_playlist)

线程思路分析:

在RunThread里面执行循环,如果没有任务执行,则适当的延迟,如果接到p_playlist-i_status!

=PLAYLIST_STOPPED的条件,则调用PlayItem(

p_playlist)函数,在PlayItem(p_playlist)函数中从新创建输入线程。

通过voidplaylist_Command(playlist_t*p_playlist,playlist_command_ti_command,inti_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)函数中创建的线程,线程函数为

staticintRunThread(input_thread_t*p_input)

线程思路分析:

由input_thread_t结构的成员分析是接收文件流还是网络流,如果是文件流,则调用filemodule的读函数(pf_read)和打开函数(--).如果是network则打

开networkmodule的打开函数和读函数(pf_read)。

在RunThread线程函数中接收数据和调用demux或者decodeetc处理。

一旦产生新的输入,则在播放列表线程中会首先结束该输入线程,然后从新创建新的输入线程。

3.视频输出文件src/video_output/video_output.c的线程

vout_thread_t*__vout_Create(vlc_object_t*p_parent,

unsignedinti_width,unsignedinti_height,

vlc_fourcc_ti_chroma,unsignedinti_aspect)函数中创建的线程,线程函数为

staticvoidRunThread(vout_thread_t*p_vout)

线程思路分析:

在RunThread里面执行循环,任务是显示视频。

4.在modules\gui\wxwindows\wxwindows.cpp中的GUI线程

staticvoidRun(intf_thread_t*p_intf)函数中创建的线程,线程函数为

staticvoidInit(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,constchar*psz_capability,

constchar*psz_name,vlc_bool_tb_strict)

函数中用到了pf_activate激活GUI对话框;

在video_output.c的staticvoidRunThread(vout_thread_t*p_vout)线程中,也用到了pf_activate激活GUI对话框;

5.开始所有module的精髓

消息映射宏

vlc_module_begin();

set_callbacks(NetOpen,NULL);

vlc_module_end();

然后设置模块结构的成员函数为:

#defineset_callbacks(activate,deactivate)p_submodule-pf_activate=activate;p_submodule-pf_deactivate=deactivate

在__module_Need函数中启动pf_activate激活相应的module。

网络数据流接收处理分析

1、在input.c(src\input)文件中的主线程循环

Threadinchargeofprocessingthenetworkpacketsanddemultiplexing

RunThread(input_thread_t*p_input)

{

InitThread(p_input);

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

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

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

/*Readanddemultiplexsomedata.*/

i_count=p_input->pf_demux(p_input);

}

2、在下列函数中:

分离出access,demux,name字符串;

根据分离出的access字符串通过module_Need函数找到acess指针模块;

根据分离出的demux字符串通过module_Need函数找到demux指针模块;

staticintInitThread(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);

/*Findandopenappropriateaccessmodule*/

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

p_input->psz_access,VLC_TRUE);

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

while(!

input_FillBuffer(p_input))

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

/*Findandopenappropriatedemuxmodule*/

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函数中激活;

staticintActivate(vlc_object_t*p_this)

{

/*Setthedemuxfunction*/

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的成员函数;

staticintActivate(vlc_object_t*p_this)

{

staticmpeg_demux_tmpeg_demux=

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

mpeg_demux.cur_scr_time=-1;

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

returnVLC_SUCCESS;

}

并且申明函数staticssize_tReadPS(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流解码

intinput_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

 

从接收到数据流到播放视频的过程分析

  从网络接收到流->对数据流进行视频和音频分离->对视频用解码器解码->显示解码后的视频流

 

   视频显示部分走势线:

分离->解码->新的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/   VLCAPIdocumentation 或者VLCdeveloperdocumentation

 

Chapter5. Thevideooutputlayer

Datastructuresandmainloop

Importantdatastructuresaredefinedininclude/video.handinclude/video_output.h.Themaindatastructureispicture_t,whichdescribes

everythingavideodecoderthreadneeds.Pleaserefertothisfileformoreinformation.Typically,p_datawillbeapointertoYUVplanar

picture.

Notealsothesubpicture_tstructure.InfacttheVLCSPUdecoderonlyparsestheSPUheader,andconvertstheSPUgraphicaldatatoan

internalformatwhichcanberenderedmuchfaster.Soapartofthe"real"SPUdecoderliesinsrc/video_output/video_spu.c.

Thevout_thread_tstructureismuchmorecomplex,butyouneedn'tunderstandeverything.Basicallythevideooutputthreadmanagesaheapof

picturesandsubpictures(5bydefault).Everypicturehasastatus(displayed,destroyed,empty...)andeventuallyapresentationtime.The

mainjobofthevideooutputisan

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 建筑土木

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1