VLC整理流程还是比较复杂的,不过这次我们追踪一下视频输出部分的流程,大概熟悉一下大概框架。
视频输出模块还是比较复杂的,但是功能基本做到了自制,虽说包含了大量的时间校准以及修正的问题,但是基本上逻辑比较清晰,只要搞明白了大概架构,
视频输出主要包括两部分,一部分是控制视频输出线程以及数据交换的结构体,一个是控制输出的结构体,为了实现不同业务逻辑,这两个结构体都加载了两个模块,
控制线程的街头日是vout_thread_t,包含的模块式vout window。对于Android系统,其实本质上就是拿到了Java层的Awindow.里面提供两套方案,分别是处理OpenGL的surface方案,以及通过Android原生的native直接拿到surface。这里的module业务比较简单,这里不在详细介绍,直接找到核心部分的vout_thread_t。主要初始化是通过VoutCreate来实现的,这里主要保存了五个变量,
window是提供渲染的画布,池是提供数据,比如直接渲染图片,则使用的picture_fifo_t *decoder_fifo;。把已经解码的数据,交给线程来渲染,control则是控制消息,thread是渲染线程,display是控制渲染模块的变量,这是后半部分的核心,
初始化代码就不在详细介绍,后半部分核心是初始化线程,通过init指令,初始化视频输出模块,核心是ThreadStart,进行的初始化,关键函数是vout_OpenWrapper以及vout_InitWrapper。
vout_OpenWrapper是记载vout display模块,来控制输出,vout_InitWrapper则初始化一些变量,比如池数据的大小等。
Android平台的视频数据流包的主要通路是:解码器向Vout模块申请bufferid,然后去填充,最终在特定时间点告诉解码器去释放资源。
具体代码如下:
p_pic = decoder_NewPicture(p_dec);
if (!p_pic) {
msg_Warn(p_dec, "NewPicture failed");
return p_sys->api.release_out(&p_sys->api, p_out->buf.i_index, false);
}
......
if (p_sys->api.b_direct_rendering)
{
p_pic->p_sys->hw.i_index = p_out->buf.i_index;
InsertInflightPicture(p_dec, p_pic->p_sys);
}
这一篇大概介绍了初始化流程,以及各个模块的顺序关系,后面我们直接追踪具体流程,参考一下OpenGL和Android native的区别。