代码改变世界

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

2018-04-18 22:27  Ansersion  阅读(1157)  评论(0编辑  收藏  举报

一、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的代码已经添加完毕。

 

上一篇                 回目录                下一篇