视频流解码播放之VLC

http://blog.csdn.net/xzdong/article/details/7657707

从已有流服务器上接收多媒体流,对码流解码、分析、播放。

站在巨人的肩膀上才能看的更远。对于这个问题,先参考已有的比较成熟的开源项目,从中找到研究的思路。VLC无疑是一个比较好的选择。VLC是一种跨平台的媒体播放器和流媒体服务器。

其实VLC开源项目本身就是基于其他的开源项目:FFMPEG,LIVE555.下面主要讲VLC作为多媒体播放器的使用。

引用地址:http://loosky.net/?p=1127

视频播放的基本原理
    几乎所有的视频播放器,如VLC、MPlayer、Xine,包括DirectShow,在播放视频的原理和架构上都是非常相似的,理解这个对理解VLC的源码会有事半功倍的效果。
    大致的来说,播放一个视频分为4个步骤:
    1. acess 访问,或者理解为接收、获取、得到
    2. demux 解复用,就是把通常合在一起的音频和视频分离(还有可能的字幕)  
    3. decode 解码,包括音频和视频的解码
    4. output 输出,也分为音频和视频的输出(aout和vout)


    拿播放一个UDP组播的MPEG TS流来说吧,access部分负责从网络接收组播流,放到VLC的内存缓冲区中,access模块关注IP协议,如是否IPv6、组播地址、组播协议、端口等信息;如果检测出来是RTP协议(RTP协议在UDP头部简单得加上了固定12个字节的信息),还要分析RTP头部信息。这部分可以参看VLC源码 /modules/access/udp.c。在同目录下还可以看到大量的access模块,如file、http、dvd、ftp、smb、tcp、dshow、mms、v4l…等等


    而demux部分首先要解析TS流的信息。TS格式是MPEG2协议的一部分,概括地说,TS通常是固定188字节的一个packet,一个TS流可以包含多个program(节目),一个program又可以包含多个视频、音频、和文字信息的ES流;每个ES流会有不同的PID标示。而又为了可以分析这些ES流,TS有一些固定的PID用来间隔发送program和es流信息的表格:PAT和PMT表。关于TS格式的详细信息可以去google一下。VLC专门做了一个独立的库libdvbpsi来解析和编码TS流,而调用它的代码可以参见VLC源码 /modules/demux/ts.c
   

其实之所以需要demux,是因为音视频在制作的时候实际上都是独立编码的,得到的是分开的数据,为了传输方便必须要用某种方式合起来,这就有了各种封装格式也就有了demux。demux分解出来的音频和视频流分别送往音频解码器和视频解码器。因为原始的音视频都是占用大量空间,而且冗余度较高的数据,通常在制作的时候就会进行某种压缩。这就是我们熟知的音视频编码格式,包括MPEG1(VCD)、MPEG2(DVD)、MPEG4、H.264、rmvb等等。音视频解码器的作用就是把这些压缩了的数据还原成原始的音视频数据。

VLC解码MPEG2使用了一个独立的库libmpeg2,调用它的源文件是 /modules/codec/libmpeg2.cVLC关于编解码的模块都放在/modules/codec目录下,其中包括著名的庞大的ffmpeg
    解码器,例如视频解码器输出的是一张一张的类似位图格式的图像,但是要让人从屏幕看得到,还需要一个视频输出的模块。当然可以像一个Win32窗口程序那样直接把图像画到窗口DC上——VLC的一个输出模块WinGDI就是这么干的,但是通常这太慢了,而且消耗大量的CPU。在Windows下比较好的办法是用DirectX的接口,会自动调用显卡的加速功能。


    这样的功能分解使得模块化更容易一点,每个模块住需要专注于自己的事;从整体来说功能强大而且灵活。
    但是事情总是不会那么简单。就拿access来说,媒体的访问是分层的,如RTSP就涉及到IPv4、TCP、UDP、RTCP、RTSP等多个层次的协议。有些视频格式包括了传输、封装格式和编辑码格式如MPEG系列,有些封装格式是独立的容器,但是很多人会误解它是编解码格式,如mkv、avi这些。
    音频和视频在demux之后就是独立的,但是需要有一套机制把它们同步起来。同时我们需要有一套机制来控制速度、暂停、停止、跳进,获取各种媒体信息,这些都是很复杂而又很重要的事情。
    另外也许需要在某个地方插入一些修改,来实现某种效果。如音频的EQ,视频的亮度调整之类的,VLC专门设计了access_filter、audio_filter和video_filter类型的模块来做这一类事情。
    VLC比较独特的地方是集成了原来的VLS的功能,这依赖于VLC中stream_output类型的模块,它们可以把正在播放的视频以某种方式重新转码和发送出去,如http、UDP、文件等等。
    MPlayer的结构与此是类似的,如/stream目录对应的是access的功能,/mpdemux对应的demux功能,/libmpcodecs是解码器,/libvo和/libao2分别是视频和音频的输出。
    DirectShow也是类似的,不过分类更多一些更复杂一点。DirectShow里面的模块叫做“filter”,filter之间通过”pin”来连接。

access的模块对应于DirectShow中的SourceFIlter,这一类Filter只有输出pin没有输入pin。demux模块对应于splitter filter,这种filter有一个输入pin,多个输出pin。解码模块是一类transform filter,有一个输入pin、一个输出pin,输出模块对应于readering filter,有一个输入pin,没有输出pin。当然transform filter不一定是解码器,也可能是某种其他的处理。
    另外给出一个VLC的API Document,参见:http://rogerfd.cn/doc/vlcapi.htm

LIVE555就目前了解是指在做有关流协议封装接口。它实现了对标准流媒体传输协议如RTP/RTCP、RTSP、SIP等的支持。Live555实现了对多种音视频编码格式的音视频数据的流化、接收和处理等支持。在VLAN中应该属于第一个部分:    1. acess 访问,或者理解为接收、获取、得到
FFMPGE是多媒体视频处理工具,有非常强大的功能包括视频采集功能、视频格式转换、视频抓图、给视频加水印等。

av_register_all();//初始化ffmpeg库,如果系统里面的ffmpeg没配置好这里会出错
av_open_input_file();
av_find_stream_info();//查找文件的流信息
dump_format();//dump只是个调试函数,输出文件的音、视频流的基本信息了,帧率、分辨率、音频采样等等
for(...);//遍历文件的各个流,找到第一个视频流,并记录该流的编码信息
sws_getContext();//根据编码信息设置渲染格式
avcodec_find_decoder();//在库里面查找支持该格式的解码器
avcodec_open();//打开解码器
pFrame=avcodec_alloc_frame();//分配一个帧指针,指向解码后的原始帧
pFrameRGB=avcodec_alloc_frame();//分配一个帧指针,指向存放转换成RGB后的帧
avpicture_fill(pFrameRGB);//将pFrameRGB和分配的内存经行绑定;http://bbs.chinavideo.org/viewthread.php?tid=5588
while true{
     av_read_frame();//读取一个帧(到最后帧则break)
     avcodec_decode_video();//解码该帧
     sws_scale();//把该帧转换(渲染)成RGB
     SaveFrame();//对前5帧保存成ppm图形文件(这个是自定义函数,非API)
     av_free_packet();//释放本次读取的帧内存
}
avcodec_close();
av_close_input_file()

关于渲染:可以简单理解为将着色,只不过比较复杂。此处着色即为将yuv数据变为RGB数据。

发布了196 篇原创文章 · 获赞 150 · 访问量 37万+

猜你喜欢

转载自blog.csdn.net/u014162133/article/details/103295488