1. 程式人生 > >一個基於JRTPLIB的輕量級RTSP客戶端(myRTSPClient)——實現篇:(九)以g711-mulaw為例添加新的編碼格式解析支持

一個基於JRTPLIB的輕量級RTSP客戶端(myRTSPClient)——實現篇:(九)以g711-mulaw為例添加新的編碼格式解析支持

調用 pcm 2個 h265 pri 源碼 返回 .cn memcpy

一、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的代碼已經添加完畢。

上一篇 回目錄

一個基於JRTPLIB的輕量級RTSP客戶端(myRTSPClient)——實現篇:(九)以g711-mulaw為例添加新的編碼格式解析支持