Live555基础

Stella981
• 阅读 545

1 Live555组成

LIVE555下包含LiveMedia、UsageEnvironment、BasicUsageEnvironment、GroupSock库,MediaServer简单服务器程序以及其他多个测试demo。

LiveMedia库:包含一系列处理不同编码格式和封装格式的类。

基类是Medium。

UsageEnvironment库:环境类,用于错误信息的输出。

LIVE555中多数类中均包含此类对象指针。

其内部包含TaskSchedule抽象类的指针,该类用于任务调度,因此所有包含UsageEnvironment指针的类均可将自己加入到调度中。

BasicUsageEnvironment库:包含具体环境类和具体TaskScheduler类。

UsageEnvironment用于对错误信息的处理,BasicUsageEnvironment类用于以控制台方式输出错误信息。因此想要以其他方式输出错误信息的类,可以从UsageEnvironment派生。

BasicTaskSchedule类继承自TaskScheduler抽象类,用以定义具体的调度策略。

任何基于LIVE555的应用程序均需要定义自己的BasicEnvironment和TaskScheduler库。

如果创建窗口应用程序,在重定义TaskScheduler时,需要与图形环境自己的事件处理框架集成。

BasicTaskSheduler使用select模型实现事件的获取和处理。如果想使用更高效的IOCP模型,可以定义自己的BasicTaskScheduler类。BasicTaskScheduler内部有一个循环,循环读取队列中的消息并处理。整个基于BasicTaskScheduler的程序只有一个线程驱动。

GroupSock库:对各种socket操作的封装

用于收发数据,主要面向组播,但也可以进行单播的收发数据,仅支持UDP,不支持TCP。

MediaServer 服务器程序:

该程序使用BasicUsageEnvironment库实现,因此是一个控制台程序。任务调度类是BasicTaskScheduler类,因此使用Select模型且仅有一个线程在循环处理各种事件。后期如果有时间会实现基于IOCP的MediaServer服务器程序。

其他测试Demo

基于LIVE555实现的客户端程序,会在需要的时候介绍。

2 基本概念

2.1 Source、Sink、Filter

Source:表示数据的提供者。比如通过RTP读取数据,通过文件读取数据或者从内存读取数据,这些均可以作为Souce。

Sink:表示数据的流向、消费者。比如写文件、显示到屏幕等。

Filter:在数据流从Souce流到Sink的过程中可以设置Filter,用于过滤或做进一步加工。

在整个LiveMedia中,数据都是从Souce,经过一个或多个Filter,最终流向Sink。

在服务器中数据流是从文件或设备流向网络。

在客户端数据流是从网络流向文件或屏幕。

MediaSouce是所有Souce的基类,MediaSink是所有Sink的基类。

从类数量和代码规模可以看到,LiveMedia类是整个LIVE555的核心,其内部包含数十个操作具体编码和封装格式的类。LiveMedia定义的各种Souce均是从文件读取,如果想实现从设备获得实时流的传输,可以定义自己的Souce。

2.2 ClientSession

对于每一个连接到服务器的客户端,服务器会为其创建一个ClientSession对象,保存该客户端的socket、ip地址等。

同时在该客户端中定义了各种响应函数用以处理和回应客户端的各种请求。

新版(2014.7.4)的LIVE555增加了ClientConnection类。用于处理一些与正常播放无关的命令。如命令未找到、命令不支持或媒体文件未找到等。在ClientConnection处理DESCRIBE命令时会创建ClientSession对象,其他命令在ClientSession中处理。

2.3 MediaSession、MediaSubsession、Track

LIVE555使用MediaSession管理一个包含音视频的媒体文件,每个MediaSession使用文件名唯一标识。

使用SubSession管理MediaSession中的一个音频流或视频流。为行文方便我们称音频或视频均为一个媒体文件中的媒体流。因此一个MediaSession可以有多个MediaSubsession,一个管理音频流一个管理视频流。

在上一篇介绍RTSP协议时,客户端在给服务器发送DESCRIBE查询某个文件的SDP信息时,服务器会给客户端返回该媒体文件所包含的多个媒体流信息。并为每个媒体流分配一个TrackID。如视频流分配为Track1,音频流分配为Track2。此后客户端必须在URL指定要为那个Track发送SETUP命令。因此我们可以认为MediaSubsession代表Server端媒体文件的一个Track,也即对应一个媒体流。MediaSession代表Server端一个媒体文件。对于既包含音频又包含视频的媒体文件,MediaSession内包含两个MediaSubsession。

但MediaSession和MediaSubsession仅代表静态信息。若多个客户端请求同一个文件,服务器仅会创建一个MediaSession。各个客户端公用。为了区分各个MediaSession的状态又定义了StreamState类,用来管理每个媒体流的状态。在MediaSubsession中完成了Souce和Sink连接。Souce对指针象会被设置进sink。在Sink需要数据时,可以通过调用Souce的GetNextFrame来获得。

LIVE555中大量使用简单工厂模式,每个子类均有一个CreateNew静态成员。该子类的构造函数被设置为Protected,因此在外部不能直接通过new来构造。同时,每个类的构造函数的参数中均有一个指向UsageEnvironment的指针,从而可以输出错误信息 和 将自己加入调度。

2.4 HashTable

LIVE555内部实现了一个简单哈希表类BasicHashTable。在LIVE555中,有很多地方需要用到该哈希表类。如:媒体文件名与MediaSession的映射,SessionID与ClientSession的映射,UserName和Password的映射等。

2.5 SDP

SDP是Session Description Protocol的缩写。是一个用来描述多媒体会话的应用层协议,它是基于文本的,用于会话建立过程中的媒体类型和编码方案的协商等。客户端会通过DESCRIBE命令请求查询指定文件的媒体信息。

2.6 LIVE555中的关键继承层次(以对H.264码流的处理为例)

Live555基础 Live555基础 Live555基础

                          Source                                                                      Sink                                                                              SubSession

H264VideoStreamFramer是真正的Source,它用于从H.264文件中读取数据,并且组装成帧。在Sink调用GetNextFrame时将帧数据返回给Sink。

H264VideoRTPSink是真正的Sink,用于完成帧数据的发送。

SubSession用于完成Source和Sink的连接,同时用于管理每个媒体流。

对于H264码流,数据流的流动方向为:

    服务器端:H264VideoStreamFramer ->H264Or5Fragmenter (Filter)r->H264VideoRTPSink

    客户端    :H264RTPSouce ->Sink(不同客户端实现不同)

学习方法的注意:LIVE555类之间关系很是复杂,类之间犬牙交错的关系增大了学习LIVE555的难度,深入学习之前应先熟悉基本流程,对各类的大概功能有所了解,至于细节问题可暂时略过。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Wesley13 Wesley13
2年前
Java日期时间API系列31
  时间戳是指格林威治时间1970年01月01日00时00分00秒起至现在的总毫秒数,是所有时间的基础,其他时间可以通过时间戳转换得到。Java中本来已经有相关获取时间戳的方法,Java8后增加新的类Instant等专用于处理时间戳问题。 1获取时间戳的方法和性能对比1.1获取时间戳方法Java8以前
Stella981 Stella981
2年前
Django之Django模板
1、问:html页面从数据库中读出DateTimeField字段时,显示的时间格式和数据库中存放的格式不一致,比如数据库字段内容为2012082616:00:00,但是页面显示的却是Aug.26,2012,4p.m.答:为了页面和数据库中显示一致,需要在页面格式化时间,需要添加<td{{dayrecord.p\_time|date:
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
4个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这