基于GStreamer的Smooth Streaming插件开发
请求信息;最后,接受服务器发送的Manifest响应报头信息,获取Manifest实体正文内容,并将其保存在buffer中。本文中的媒体服务器的地址为:http://192.168.160.179/h264/7.ism/manifest。
2.解析Manifest数据模块
该模块主要实现对下载后的Manifest数据进行解析,获得Fragment数据的相关信息,比如:Fragment数据的URL,Fragment数据的个数,Fragment数据的偏移时间等。
通过将下载的Manifest数据buffer写入文件中可知该视讯清单是按照XML格式来制作的,因此本文通过expat开发库封装在一个函数中来解析该XML文件。该函数如下所示:
int SMTH_parsemanifest(Manifest *m, char **str, count_t contentlen) 其中:传入参数为Manifest结构体,用来储存解析后的相关数据;传入参数str为下载的Manifest数据;传入参数contentlen为该Manifest数据的长度。
3.下载Fragment数据模块
从解析数据可以得到下载Fragment数据的URL地址构造格式为: 4.解析Fragment数据模块 从服务器中下载的Fragment数据都是经过服务器处理的,按按照以片段的BOX容器格式存储的,因此我们需要对该Fragment数据进行解析BOX容器并从中获得其sample帧数据信息相关信息。 本文设计了一个函数来对下载的Fragment数据进行解析,如下所示: error_t SMTH_parsefragment(Fragment *f, char **str) 其中:f为用来存储解析后数据的结构体;str为传入的Fragment数据。通 37 基于GStreamer的Smooth Streaming插件开发 过调用该函数后,可以解析出一个Fragment中每个sample的地址、大小和时间戳等信息。 4.5 基于GStreamer的Smooth Streaming协议的插件设计 本文是通过Smooth Streaming协议去实现边下载、边解析和边播放的点播或直播形式的流媒体开发,为了将其应用在linux操作系统中,本文在GStreamer多媒体框架下设计一个用于实现Smooth Streaming协议的插件。 根据实际的需要,本文设计的插件通过三大部分实现:环形缓存设计、source元件设计和sink元件设计。该插件的设计思想是:首先,通过source元件从服务器端下载Manifest数据,对其解析并获得下载Fragment数据的URL地址;然后,根据URL地址从服务器端下载对应的Fragment并将该数据存放在环形缓存中;接着,在sink元件中从环形缓存取出对应的Fragment数据,对其解析得到实际的sample数据;最后,根据音视频的压缩方式,为每个sample数据添加对应的帧头,并将其注入到底层avplayer接口中。具体的插件设计模块如图4-8所示: 图4-8 Smooth Streaming插件设计模块图 38 基于GStreamer的Smooth Streaming插件开发 4.5.1 Smooth Streaming协议的source元件设计 本文设计的source元件的主要功能是实现Fragment数据的下载,并将下载的数据传入到环形缓存中。根据GStreamer插件开发的结构,本文设计的source元件的函数执行流程如图4-9所示: 图4-9 source元件内部执行流程 1.manifest_init()。该函数的功能是在GStreamer启动时,将该插件注册到GStreamer动态插件库中。 2._do_init()。该函数是用来初始化插件的接口信息。 3.gst_manifest_base_init()。用来注册元件的一些细节到插件中,比如说pad模板和该插件的描述信息等。 4.gst_manifest_class_init()。该函数是用来初始化插件与外部通信的一些参数,比如说信号,URL等。 5.gst_manifest_init()。该函数主要用来初始化本插件内部定义的数据结构中的数据。 6.gst_manifest_set_property()。该函数用来获得外面管道对source元件属性的设置参数。本文将输入的URL通过管道传入到source元件中,然后设计 39 基于GStreamer的Smooth Streaming插件开发 一个函数static gboolean gst_manifest_set_location(),该函数将URL地址传入到source元件的内部数据结构中。 7.gst_manifest_start()。该函数中描述的为source元件实际的功能。本文将source作为下载服务器数据的插件,那么在该函数中就要实现下载数据。具体实现步骤按照smooth streaming协议设计如下图4-10所示: 图4-10 start函数实现功能流程图 Step1.设计gst_manifest_init_ring_buffer()函数初始化环形缓存; Step2.设计gst_manifest_parse_url()函数解析从外面传入的URL; Step3.设计gst_manifest_connect_to_server()函数将客户端与服务器端建立连接; Step4.设计gst_manifest_send_request()函数发送请求信息到服务器端; Step5.设计http_Recvcontent()函数接受服务器端的响应信息。 Step6.调用SMTH_parsemanifest()函数解析下载的Manifest数据并获得相关Fragment下载的URL; Step7.设计void *gst_fragment_download_data_thread()线程函数来下载Fragment数据,并将数据保存到环形缓存区中。 8.gst_manifest_create()。该函数是用来将储存在GStreamer中临时缓存 40 基于GStreamer的Smooth Streaming插件开发 中的数据传递到下一个插件。本文是通过环形缓存来作为source元件与sink元件内容的一个交互过程,因此该函数设置传入到下一个插件的buffer为空。 9.gst_manifest_get_property()。该函数是用来将source元件中的一些参数传出,以便其他参数调用。本文在该函数中将source元件初始化的环形缓存指针传出,以供后面的sink插件访问该环形缓存。 10.gst_manifest_stop()和gst_manifest_finalize()。当source元件执行结束时,调用这两个函数来停止source元件的运行并释放已分配的资源。例如,线程的结束、环形缓存的销毁以及source元件内部数据的释放等。 4.5.2 Smooth Streaming协议的sink元件设计 sink插件一般的功能是将管道中的上一个插件传来的数据输入到底层设备中。本文设计一个用来做流媒体数据处理的sink插件,该插件分为两个大的部分:解析部分和注入数据部分。解析部分是将从环形缓存中取出的Fragment数据解析得到其中的sample数据;而注入数据部分是将这些sample数据按照不同的格式加入对应的帧头注入到avplayer底层接口中。sink插件整体的工作流程如图4-11所示: 图4-11 sink元件内部流程 41