VLC源码分析01

VLC是开源的并且相当受欢迎的媒体处理软件。我们可以认为VLC是一个完善的多媒体框架,就如同Windows上的DirectShow或Unix上的GStreamer。在必要时它可以动态的加载第三方插件进行媒体处理。因为VLC使用了大量的第三方库,自身的代码量也十分庞大,编译起来也相对比较麻烦,所以网上相关的文章也相对较少,我们将在以下的文章中对VLC做一次深入的剖析。关于VLC的编译请移步http://hongxchen.github.io/2014/07/19/vlc-compile-on-linux/

一. libVLCcore

libVLCcore是VLC的内核,主要代码在src目录中。LibVLCcore主要管理线程,编解码模块,时钟,播放列表和底层控制等。LibVLCcore通过上层的LibVLC模块对外部应用提供服务,也就是说所有底层模块内建于LibVLCcore模块,而外部应用内建于LibVLC模块。

  1. VLC 的流水线和模块化

    VLC媒体处理时,在每个阶段都通过加载相关的模块进行工作,每个模块将输入的数据做相应的处理,然后输出给后续的模块。

  2. 线程管理

    VLC严重依赖多线程,因为解码,输出等工作是同步进行的,否则将不能保证视频播放时每一帧都在准确的时间内播放。线程控制较进程控制要付在很多,但是多进程将导致更多的内存开销,而且进程间的通信也比较蛋疼。
    VLC使用POSIX threads,但是它对POSIX threads做了轻量级的封装。

    (1). 线程(vlc_thread_t)

    vlc_clone() 创建一个线程
    vlc_join() 等待线程结束并释放资源

    (2). 互斥量(vlc_mutex_t)

    vlc_mutex_init 创建一个非递归的互斥量
    vlc_mutex_init_recursive() 创建一个递归互斥量
    vlc_mutex_lock() 锁住互斥量
    vlc_mutex_trylock() 查看一个互斥量,如果没有被锁定则锁定该互斥量,否则返回错误
    vlc_mutex_unlock() 解锁互斥量
    vlc_mutex_destroy() 释放互斥量

    (3). 条件变量(vlc_cond_t)

    vlc_cond_init() 创建一个条件变量,超时使用单调时钟(即系统启动后的tick)
    vlc_cond_init_daytime() 创建一个条件变量,超时使用realtime clock,wall clock
    vlc_cond_signal() 发送信号给某个线程等待条件变量
    vlc_cond_broadcast() 发送信号给所有线程等待条件变量
    vlc_cond_wait() 等待条件变量被signaled
    vlc_cond_timedwait() 在超时时间内等待条件变量被signaled
    vlc_cond_destroy() 释放条件变量

    (4). 杂项(Misc)

    读写锁,自旋锁,线程特定变量等。

    (5). 原子变量

    原子变量可以在多个线程中进行操作。相关的操作查看include/vlc_atomic.h

  3. 同步

    VLC的一个重要特点是解码和播放是异步进行的,解码通过解码器线程进行,播放是在audio_output和video_output线程中进行。这也就导致了VLC的界面,输入,解码,输出工作复杂的通信结构。
    系统层将数据流呈现的时间戳和采样时间传递给解码器,输出层选择在适当的时间播放。时间mtime_t是有符号的64位整数,单位微妙。当前时间可以同过mdate()获取,使用mwait(mtime_t data)挂起某个线程,sleep使用msleep(mtime_t delay)。