原文地址:http://luzefengoo.blog.163.com/blog/static/1403593882012754481846/

第二部分 程序框架实现

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

vlc框架流程解析(转)的更多相关文章

  1. Session (简介、、相关方法、流程解析、登录验证)

    Session简介 Session的由来 Cookie虽然在一定程度上解决了"保持状态"的需求,但是由于Cookie本身最大支持4096字节,以及Cookie本身保存在客户端,可能 ...

  2. 同人逼死官方系列!基于sddc 协议的SDK框架 sddc_sdk_lib 解析

    基于sddc 协议的SDK框架 sddc_sdk_lib 解析 之前在移植 libsddc 库的时候感觉官方 demo 太低效了( ̄. ̄),复制粘贴代码好累,而且写出一个BUG,其他复制的代码整个就裂 ...

  3. Java开发学习(二十三)----SpringMVC入门案例、工作流程解析及设置bean加载控制

    一.SpringMVC概述 SpringMVC是隶属于Spring框架的一部分,主要是用来进行Web开发,是对Servlet进行了封装.SpringMVC是处于Web层的框架,所以其主要的作用就是用来 ...

  4. TCP/IP协议三次握手与四次握手流程解析

    原文链接地址:http://www.2cto.com/net/201310/251896.html TCP/IP协议三次握手与四次握手流程解析 TCP/IP协议的详细信息参看<TCP/IP协议详 ...

  5. SSL/TLS算法流程解析

    SSL/TLS 早已不是陌生的词汇,然而其原理及细则却不是太容易记住.本文将试图通过一些简单图示呈现其流程原理,希望读者有所收获. 一.相关版本 Version Source Description ...

  6. CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

    最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时 ...

  7. TCP/IP协议三次握手与四次握手流程解析(转载及总结)

    原文地址:http://www.2cto.com/net/201310/251896.html,转载请注明出处: TCP/IP协议三次握手与四次握手流程解析 一.TCP报文格式  TCP/IP协议的详 ...

  8. Django生命周期 URL ----> CBV 源码解析-------------- 及rest_framework APIView 源码流程解析

    一.一个请求来到Django 的生命周期   FBV 不讨论 CBV: 请求被代理转发到uwsgi: 开始Django的流程: 首先经过中间件process_request (session等) 然后 ...

  9. [MapReduce_3] MapReduce 程序运行流程解析

    0. 说明 Word Count 程序运行流程解析 &&  MapReduce 程序运行流程解析 1. Word Count 程序运行流程解析 2. MapReduce 程序运行流程图

随机推荐

  1. UVA-810 A Dicey Problem (BFS)

    题目大意:滚骰子游戏,骰子的上面的点数跟方格中的数相同时或格子中的数是-1时能把格子滚过去,找一条从起点滚到起点的路径. 题目大意:简单BFS,状态转移时细心一些即可. 代码如下; # include ...

  2. Page.TryUpdateModel 方法

    使用来自值提供程序的值更新指定的模型实例. 使用来自值提供程序的值更新指定的模型实例. 命名空间:   System.Web.UI程序集:  System.Web(System.Web.dll 中) ...

  3. 【hive】分组求排名

    分组求排名 相信好多使用Mysql的用户一定对分组求排名的需求感到发怵. 但是在hive或者oracle来说就能简单实现. 采用窗口函数:rank() over() / row_number() ov ...

  4. 仿智能社官网:原生JS实现简单又酷炫的3D立方体时钟

    先放一下我做的效果:https://linrunzheng.github.io/3Dclock/3Dclock/new.html 至于3D立方体怎么做这里就不在阐述了,可以看一下我之前的博客. 这里默 ...

  5. Mac Book Pro重新安装出错

    错误描述 未能创建用于apfs安装的预启动宗卷 解决 网上的经验: 返场重修 多试几次拼人品 多试了几次之后还是没用,选择U盘安装. 搞定! U盘安装教程

  6. spring-security-4 (5)spring security Java配置实现自定义表单认证与授权

    前面三篇讲解了spring security的搭建以及简单的表单认证与授权原理.本篇将实现我们自定义的表单登录与认证.  本篇不会再讲项目的搭建过程,因为跟第二节的搭建如出一辙.本篇也不会将项目中所有 ...

  7. [LOJ535]「LibreOJ Round #6」花火

    loj description 给你一个排列\(h_i\),你需要交换任意两个位置上的数使得交换后排列的逆序对数最少. \(n \le 3\times 10^5\) sol 首先可以发现,如果交换两个 ...

  8. 安装 nodejs,npm,pm2

    一:需要安装组件: nodejs,npm,pm2 安装epel 源: rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel ...

  9. vmware esxi 4.1单IP访问不同机器

    1 vmware ESXI先创建虚拟机ROS作为路由  ROS设置两张网卡 WAN网卡对应外网IP LAN网卡对应LAN IP 设置网卡名 int set 0 name=wai             ...

  10. HQL语句:三表查询(一对多,一对多)

    实体类:CrmDepartment package com.learning.crm.department.domain; import java.util.HashSet; import java. ...