2023年11月27日发(作者:)

live555代码分析

Live555

Live555是⼀个跨平台的C++开源项⽬,为流媒体提供解决⽅案,实现了RTP/RTCP、RTSP、SIP等标准流媒体传输协议。

Live555实现了⾳视频数据的流化、接收和处理。⽀持包括MPEG、H.253+、DV、JPEG等视频编码格式、及多种⾳频编码。⽬

前,Live555已经被⽤于多款播放器的流媒体播放功能的实现,如VLC(VideoLan)、MPlayer。

该项⽬的源代码包括四个基本的库,各种测试代码以及LIVE555 Media Server。

四个基本的库分别是UsageEnvironment&TaskScheduler,groupsock,liveMedia,BasicUsageEnvironment。

1Live555 Streaming Media整体框架

(1) UsageEnvironment模块是对系统环境的抽象,包括 UsageEnvironment和TaskScheduler,⽤于事件的调度。

<1> UsageEnvironment主要⽤于消息的输⼊输出和⽤户交互功能。

<2> TaskScheduler实现事件的、事件处理函数的注册等,它通过维护⼀个异步读取源实现对诸如通信消息到达等事件的处理,通过使

⽤DelayQueue实现对其他注册函数的延时调度

程序设计者通过⾃定义该抽象了类UsageEnvironment和TaskScheduler类的⼦类,就可以在特定环境(如GUI环境)中运⾏,不需要进

⾏过多的修改。

(2) BasicUsageEnvironment模块是UsageEnvironment的⼀个控制台应⽤的实现。它针对控制台的输⼊输出和信号响应进⾏具体实

现,利⽤select 实现事件获取和处理

(3) GroupSock模块,对⽹络接⼝进⾏封装、⽤于实现的发送和接收。GroupSock主要被设计⽤以⽀持,但它也完全⽀持通信。

(4) LiveMedia模块是Live555中最重要的模块。该模块声明了⼀个Medium,其他所有类都派⽣⾃该类。

<1> RTSPClient:该类实现RTSP请求的发送和响应的解析,同时根据解析的结果创建对应的RTP会话。

<2> MediaSession:⽤于表⽰⼀个RTP会话,⼀个MediaSession可能包含

(5) Media Server 是⼀个纯粹的RTSP 服务器。⽀持多种格式的媒体⽂件:

l TS 流⽂件,扩展名ts。

l PS 流⽂件,扩展名mpg。

l MPEG-4视频基本流⽂件,扩展名m4e。

l MP3⽂件,扩展名mp3。

l WAV ⽂件(PCM),扩展名wav。

l AMR ⾳频⽂件,扩展名.amr。

l AAC ⽂件,ADTS 格式,扩展名aac。

1.1 OpenRTSP客户端流程

Ø MediaSession *pMediaSession = MediaSession::createNew(env,sdpDescription);

Ø bool hasSubSession = pMediaSession->hasSubsession();

Ø MediaSubsessionIterator *iter = //⼦会话迭代器

newMediaSubsessionIterator(*pMediaSession);

Ø MediaSubsession *pSubsession = iter->next();

Ø pSubsession->initiate();

Ø unsigned short num = pSubsession->clientPortNum(); //本地rtp端⼝

Ø 本体rtcp端⼝:num + 1

Ø //发送setup命令

<2>运⾏,弹出的dos框⾥⾯有地址,如下图

<3>客户端,dos下进⼊到ffplay所在⽂件夹下,然后输⼊如下命令

rtsp://10.120.2.18/<媒体⽂件名>

2 编译live555

2.1 ⽅法1

利⽤⽣成VS可⽤的makefile

1 修改win32config。打开livewin32config⽂件,修改如下

TOOLS32 = c:ProgramTOOLS32 = E:Program FilesMicrosoft

FilesDevStudioVcVisual Studio 10.0VC

LINK_OPTS_0

= $(linkdebug)LINK_OPTS_0 = $(linkdebug)

将TOOLS32修改为你的VS2010路径

编译器索要的LINK运⾏库不同,原本以为可以改为

,但没找着

2 新增Makefile设定。打开,修改如下

INCLUDES = -Iinclude -INCLUDES = -Iinclude -I../UsageEnvironment/include -

I../UsageEnvironment/includeDNO_STRSTREAM

3 建⽴makefile

⽅法:运⾏,⽣成VS能够编译的*.mak⽂件

nmake /B -

5 开始编译:(命令⾏下)执⾏

5 编译结果:

5-1 在对应的⽂件下,如下图

① ⽣成与cpp⽂件对应的obj⽂件(Object File中间代码⽂件,源⽂件complie⽣成,在linux下为o⽂件)

② ⽣成lib库: 、、、

说明:若要⽤VS2010对代码进⾏调试跟踪,那么编译时需要做相应修改,修改⽅法如下:

⽅法⼀:修改*.mak⽂件下的NODEBUG 。不带DEBUG,NODEBUG=1(默认);带DEBUG,DEBUG=1

⽅法⼆:在win32config加⼊⼀⾏ "NODEBUG=1" (不推荐)

2.2 ⽅法2Win7+VS2010⽅式)

如果需要⾃⼰调试修改源码,采⽤编译器的⽅式会更好些,这种⽅式也更利于源码分析,步骤如下:

0 综述:分别为每个库单独编译⽣成lib

..groupsockinclude

..liveMediainclude

..UsageEnvironmentinclude

3 添加⽂件。

for(char const*ptr = inputLine; *ptr != ‘0’; ++ptr)

{

if( *ptr== ‘r’ || *ptr == ‘n’ )

{ ++ptr;}

while(*ptr== ‘r’ || *ptr == ‘n’ )

{

++ptr;

}

nextLine =ptr; //即是下⼀⾏的开始

if(nextLine[0]== ‘0’)

{

p = * (phone number)

c = IN IP4 0.0.0.0 //连接信息

b =* (表⽰宽度信息,值为0或者bandwidth information)

t = * (time the session is active,有效时间)

r = * (zero or more repeat times)

a = control:*

a = range:clock= 20150120T180515Z – 20150405T151210Z

m = video 0 RTP/AVP 95 //视频

i = video media

a = rtpmap: 95 H264/90000

a = fmtp:95 profile-level-id = 4D0014; packetization-mode = 0

void* afterGettingClientData,

onCloseFunc* onCloseFunc,

void* onCloseClientData);

private:

Groupsock* fGS;

}

Boolean H254VideoRTPSource::processSpecialHeader(BufferedPacket*packet, unsigned& resultSpecialHeaderSize)

{

unsigned char* headerStart =packet->data;

unsigned frameSize, //数据帧的实际⼤⼩

unsigned numTruncatedBytes,

struct timeval presentationTime,

unsigned durationInMicroseseconds

);

Ø fSource是MediaSink 中的类型为FramedSource*的类成员。

3.3 数据流

数据经过多个Source到Sink。

Source1 -> Source2(a filter) -> … -> Sourcen(a filter) -> sink

从其他Source接收数据的Source也叫Filter。

5.1 rtsp client

5.1.1创建任务调度类TaskScheduler的对象

TaskScheduler* scheduler = BasicTaskScheduler::CreateNew();

ClassBasicTaskScheduler : public BasicTaskScheduler0

{

//创建对象,不能在外⾯通过构造函数创建对象

5.1.3创建RtspClient

class RTSPClient : public Medium

{

public:

static RTSPClient* createNew( UsageEnvironment& env,

char const* rtspUrl,

struct timeval tv_timeToDelay;

tv__sec= 秒;

tv__usec = 毫秒;

int selectResult = select(fMaxNumSocket,&readSet, &writeSet, &exceptionSet, & tv_timeToDelay);

selectResult = 0; 表⽰超时

selectResult < 0; 表⽰错误

MediaSubsessionIterator it = newMediaSubsessionIterator(mediaSession);

创建MediaSubsession

MediaSubsession* pMediaSubsession = it->next();

pMediaSubsession->initiate();

}

class DummySink : public MediaSink

{

private:

RTPSource* fRtpSource;

FramedSource* fReadSouce; //帧数据源,RTP拆包后的H254帧数据

历史录像回放:absStartTime 按照格式yyyyMMddTHHmmss填写值

实时预览:absStartTime值为NULL

5.1.8发送Teardown命令关闭视频

Ø MediaSubsessionIterator *it;

delete it;