一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(九)以g711-mulaw为例添加新的编码格式解析支持
2018-04-18 22:27 Ansersion 阅读(1166) 评论(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的代码已经添加完毕。