一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(九)以g711-mulaw为例添加新的编码格式解析支持

一、myRtspClient音频解析架构

AudioTypeBase是处理解析各种编码的音频数据的接口类。处理MPA数据的MPEG_Audio类和处理g711-mulaw的PCMU_Audio类均从AudioTypeBase继承而来。AudioTypeBase最重要的接口为CopyData,它的作用就是将RTP接收到的实时数据(data)存放到用户的缓存区(buf),每当接收到1包新的RTP数据时,该函数就会得到调用。

二、myRtspClient视频解析架构

NALUTypeBase是处理解析各种编码的视频数据的接口类。处理H264的FU-A数据的FU_A类和处理H265的FUs数据的FUs_H265类均从NALUTypeBase继承而来。NALUTypeBase最重要的接口为CopyData,它的作用就是将RTP接收到的实时数据(data)存放到用户的缓存区(buf),每当接收到1包新的RTP数据时,该函数就会得到调用。

三、以g711-mulaw为例添加新的编码格式

相较于myRtspClient-1.2.3,myRtspClient-1.2.4增加了对g711-mulaw的支持。除去Makefile和注释,新版本添加和修改的源码总共100行左右。接下来我们将分析这100行代码。(历史版本:https://github.com/Ansersion/myRtspClient/releases)

首先我们构建2个类:PCMUTypeBase和PCMU_Audio,前者继承AudioTypeBase,后者继承前者。现在我们最主要的任务就是实现PCMU_Audio::CopyData和PCMU_Audio::GetFlagOffset

 1 class PCMUTypeBase : public AudioTypeBase
 2 {
 3     public:
 4         PCMUTypeBase() {Name.assign("PCMUTypeBase");};
 5         virtual ~PCMUTypeBase() {};
 6
 7     public:
 8         virtual size_t CopyData(uint8_t * buf, uint8_t * data, size_t size) { return 0;};
 9         virtual int GetFlagOffset(const uint8_t * RTPPayload) { return -1; };
10
11     // protected:
12     //  std::string Name;
13 };
14
15
16 class PCMU_Audio : public PCMUTypeBase
17 {
18     public:
19         PCMU_Audio() { Name.assign("PCMU_Audio"); };
20         virtual ~PCMU_Audio() {};
21
22     public:
23         virtual size_t CopyData(uint8_t * buf, uint8_t * data, size_t size);
24         virtual int GetFlagOffset(const uint8_t * RTPPayload);
25 };

g711-mulaw的RTP格式很简单,除去RTP的报文头就是g711-mulaw的数据了,所以GetFlagOffset无需解析任何g711的头,直接返回0即可,CopyData也只要将RTP数据data直接复制到用户缓存buf中就行了。

 1 size_t PCMU_Audio::CopyData(uint8_t * buf, uint8_t * data, size_t size)
 2 {
 3     size_t CopySize = 0;
 4     int Offset = 0;
 5     uint8_t * DataPointer = data;
 6
 7     if(!buf || !data) return 0;
 8     Offset = GetFlagOffset(DataPointer);
 9
10     memcpy(buf+CopySize, data + Offset, size - Offset);
11     CopySize += size - Offset;
12
13     return CopySize;
14 }
15
16 int PCMU_Audio::GetFlagOffset(const uint8_t * rtp_payload)
17 {
18     return 0;
19 }

然后修改uint8_t * RtspClient::GetAudioData(MediaSession * media_session, uint8_t * buf, size_t * size, size_t max_size),注意以下代码红色字体部分。

 1 uint8_t * RtspClient::GetAudioData(MediaSession * media_session, uint8_t * buf, size_t * size, size_t max_size)
 2 {
 3     if(!media_session || !buf || !size) return NULL;
 4
 5     *size = 0;
 6
 7     size_t SizeTmp = 0;
 8     AudioTypeBase * AudioType;
 9
10     if(!media_session->GetMediaData(AudioBuffer.Buf, &SizeTmp)) return NULL;
11     if(0 == SizeTmp) {
12         cerr << "No RTP data" << endl;
13         return NULL;
14     }
15
16
17     MyRegex Regex;
18     if(Regex.Regex(media_session->EncodeType.c_str(), "PCMU", true)) {
19         AudioType = &PCMU_AudioObj;
20     } else {
21         AudioType = &MPEG_AudioObj;
22     }
23
24     if(SizeTmp > AudioBuffer.Size) {
25         cerr << "Error: RTP Packet too large(" << SizeTmp << " bytes > " << AudioBuffer.Size << "bytes)" << endl;
26         return NULL;
27     }
28
29     if(*size + SizeTmp > max_size) {
30         fprintf(stderr, "\033[31mWARNING: NALU truncated because larger than buffer: %u(NALU size) > %u(Buffer size)\033[0m\n", *size + SizeTmp, max_size);
31         return buf;
32     }
33
34     SizeTmp = AudioType->CopyData(buf + (*size), AudioBuffer.Buf, SizeTmp);
35     *size += SizeTmp;
36
37     return buf;
38 }

至此,支持g711-mulaw的代码已经添加完毕。

上一篇                 回目录

原文地址:https://www.cnblogs.com/ansersion/p/8870820.html

时间: 2024-10-28 06:48:36

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(九)以g711-mulaw为例添加新的编码格式解析支持的相关文章

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(五)用户接口层之提取媒体流数据

当RTSP客户端向RTSP服务端发送完PLAY命令后,RTSP服务端就会另外开启UDP端口(SDP协商定义的端口)发送RTP媒体流数据包.这些数据包之间会间隔一段时间(毫秒级)陆续被发送到RTSP客户端,此时RTSP客户端可以调用GetMediaData等接口获取媒体流数据. 一.uint8_t * RtspClient::GetMediaData(string media_type, uint8_t * buf, size_t * size, size_t max_size) 该函数的作用即获

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(一)概览

myRTSPClient主要可以分成3个部分: 1. RTSPClient用户接口层: 2. RTP 音视频传输解析层: 3. RTP传输层. "RTSPClient用户接口层": 包含所有myRTSPClient的外显特性,包括与RTSP服务器交互接口和音视频数据提取接口,直接供用户使用. "RTP音视频传输解析层": 用于区分不同音视频格式(H264,H265,MPA等等)RTP数据包,分离其中的音视频数据和格式数据."RTSPClient用户接口层&

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(二)用户接口层之RtspClient类及其构造函数

RtspClient类是myRTSPClient函数库所有特性集中实现的地方. 主要为用户提供: 1. RTSP协议通信接口函数,如DoOPTIONS(): 2. RTSP账号.密码设置函数,如SetUsername(): 3. 音视频码流接收函数,如GetVideoData(). 本篇主要介绍RtspClient的构造函数和析构函数. 一.RtspClient::RtspClient() 1 RtspClient::RtspClient(): 2 RtspURI(""), RtspC

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(三)用户接口层之RTSP命令

截至版本1.2.3,myRtspClient函数库共支持以下6个RTSP命令: (1)OPTIONS (2)DESCRIBE (3)SETUP (4)PLAY (5)PAUSE (6)TEARDOWN 对应的接口函数都以"Do"开头,如"DoOPTIONS".各个接口函数写法相似,大同小异,差异部分会在后续章节做说明,现以DoOPTIONS()和DoPLAY()举例. 一.ErrorType RtspClient::DoOPTIONS(string uri) 1 E

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(六)RTP音视频传输解析层之音视频数据传输格式

一.差异 本地音视频数据格式和用来传输的音视频数据格式存在些许差异,由于音视频数据流到达客户端时,需要考虑数据流的数据边界.分包.组包顺序等问题,所以传输中的音视频数据往往会多一些字节. 举个例子,有时候一个媒体分包数据量很大(比如H264的一个分包常常会有2-4K),而大多数网络的MTU(最大传输单元)基本都是1500字节. 如果频繁收发这么大的数据包,会额外增添路由器的负担,甚至会导致网络阻塞,不利于网络的稳定. 于是服务器就自行对H264进行了分包以适应MTU,每个分包的开始处往往会多出一

一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient):(二)示例

一.搭建RTSP服务器 要想测试RTSP客户端,没有服务端怎么行呢?然而,有时候条件有限,手头并没有独立的RTSP服务器拿来用,那么我们不妨自己撘一个. 以下有2种方便的做法可供选择: 第一种:使用vlc播放器(推荐做法) 这种方法最方便,而且任何视频格式的文件都可以拿来测试,具体做法网上有很多,以下提供一个链接以供参考. http://blog.csdn.net/beitiandijun/article/details/9232405 这种方法只有一个地方需要注意一下: 如果你想让你的vlc

一个基于Android系统的新闻客户端(一)

一.整体概述 在服务器端,通过对凤凰网的抓取存入数据库,客户端通过向服务器发送请求得到新闻. 服务端用WCF,宿主为window服务,客户端为Java写的安卓程序. 二.客户端 我在eclipse里新建了个Android项目,命名为MyNewClient,eclipse自动生成二个xml布局文件,如图: 其中,fragment_main.xml是新版的布局文件,暂时不会用,把它删掉. 新建xml文件,命名为activity_foot.xml,在这里我们要做app的底部,先上代码: <?xml v

RestExpress 一个基于Netty的轻量级Rest服务开发框架

RestExpress 原文的定义是这么说的: RestExpress is the easiest way to create RESTful web services in Java. An extremely Lightweight, Fast, REST Engine and API for Java. Supports JSON and XML serialization automagically as well as ISO 8601 date formats. A thin wr

基于XMPP的IOS聊天客户端程序(XMPP服务器架构)

最近看了关于XMPP的框架,以文本聊天为例,需要发送的消息为: <message type="chat" from="[email protected]" to="[email protected]">          <body>helloWord</body>      </message> 基中from是从哪个用户发送的消息,to是发给谁的消息,XMPP的用户都是以邮箱形式.body就是我们