一個基於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(constuint8_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的代碼已經添加完畢。
上一篇 回目錄
一個基於JRTPLIB的輕量級RTSP客戶端(myRTSPClient)——實現篇:(九)以g711-mulaw為例添加新的編碼格式解析支持