From 8ed205878fe67c04541aefe49f35b8027d17e372 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Thu, 18 Oct 2018 23:48:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=95=B4=E7=90=86Rtp?= =?UTF-8?q?=E6=89=93=E5=8C=85=E8=A7=A3=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Device/Device.cpp | 8 +-- src/Device/PlayerProxy.cpp | 4 +- src/MediaFile/MediaReader.cpp | 10 +-- src/Player/Frame.cpp | 5 ++ src/Player/Frame.h | 83 +++++++++++++++++++++ src/Player/Player.h | 35 +-------- src/Player/PlayerBase.h | 12 +--- src/RTP/AACRtpEncoder.cpp | 104 +++++++++++++++++++++++++++ src/RTP/AACRtpEncoder.h | 41 +++++++++++ src/RTP/H264RtpEncoder.cpp | 92 ++++++++++++++++++++++++ src/RTP/H264RtpEncoder.h | 29 ++++++++ src/RTP/RtpCodec.cpp | 5 ++ src/RTP/RtpCodec.h | 112 +++++++++++++++++++++++++++++ src/Rtmp/FlvMuxer.cpp | 2 +- src/Rtmp/RtmpParser.cpp | 12 ++-- src/Rtmp/RtmpToRtspMediaSource.cpp | 8 +-- src/Rtsp/RtpParser.cpp | 34 ++++----- src/Rtsp/RtspSession.h | 2 +- src/Rtsp/RtspToRtmpMediaSource.cpp | 12 ++-- 19 files changed, 521 insertions(+), 89 deletions(-) create mode 100644 src/Player/Frame.cpp create mode 100644 src/Player/Frame.h create mode 100644 src/RTP/AACRtpEncoder.cpp create mode 100644 src/RTP/AACRtpEncoder.h create mode 100644 src/RTP/H264RtpEncoder.cpp create mode 100644 src/RTP/H264RtpEncoder.h create mode 100644 src/RTP/RtpCodec.cpp create mode 100644 src/RTP/RtpCodec.h diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp index 94771cfb..79b5da6f 100644 --- a/src/Device/Device.cpp +++ b/src/Device/Device.cpp @@ -128,8 +128,8 @@ void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,boo inputAAC(pcData+7,iDataLen-7,uiStamp,pcData); } else if(m_pAdtsHeader){ m_pAdtsHeader->aac_frame_length = iDataLen; - writeAdtsHeader(*m_pAdtsHeader,m_pAdtsHeader->data); - inputAAC(pcData,iDataLen,uiStamp,(const char *)m_pAdtsHeader->data); + writeAdtsHeader(*m_pAdtsHeader,(uint8_t *)m_pAdtsHeader->buffer); + inputAAC(pcData,iDataLen,uiStamp,(const char *)m_pAdtsHeader->buffer); } } void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader){ @@ -278,9 +278,7 @@ void DevChannel::initVideo(const VideoInfo& info) { void DevChannel::initAudio(const AudioInfo& info) { m_audio.reset(new AudioInfo(info)); - m_pAdtsHeader.reset((AdtsFrame *)malloc(sizeof(AdtsFrame) - sizeof(AdtsFrame::data) + 7),[](AdtsFrame *ptr){ - free(ptr); - }); + m_pAdtsHeader = std::make_shared(); m_pAdtsHeader->syncword = 0x0FFF; m_pAdtsHeader->id = 0; diff --git a/src/Device/PlayerProxy.cpp b/src/Device/PlayerProxy.cpp index 2cbb741d..6882cc79 100644 --- a/src/Device/PlayerProxy.cpp +++ b/src/Device/PlayerProxy.cpp @@ -89,7 +89,7 @@ void PlayerProxy::play(const char* strUrl) { return; } if(strongSelf->m_pChn){ - strongSelf->m_pChn->inputH264((char *)data.data.data(), data.data.size(), data.timeStamp); + strongSelf->m_pChn->inputH264((char *)data.data(), data.size(), data.timeStamp); if(!strongSelf->m_haveAudio){ strongSelf->makeMuteAudio(data.timeStamp); } @@ -103,7 +103,7 @@ void PlayerProxy::play(const char* strUrl) { return; } if(strongSelf->m_pChn){ - strongSelf->m_pChn->inputAAC((char *)data.data, data.aac_frame_length, data.timeStamp); + strongSelf->m_pChn->inputAAC((char *)data.data(), data.size(), data.timeStamp); }else{ strongSelf->initMedia(); } diff --git a/src/MediaFile/MediaReader.cpp b/src/MediaFile/MediaReader.cpp index d5d01ccb..90186200 100644 --- a/src/MediaFile/MediaReader.cpp +++ b/src/MediaFile/MediaReader.cpp @@ -109,7 +109,7 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri if(MP4GetTrackESConfiguration(m_hMP4File,m_audio_trId,&ppConfig,&pConfigSize)){ m_strAacCfg.assign((char *)ppConfig, pConfigSize); makeAdtsHeader(m_strAacCfg, m_adts); - writeAdtsHeader(m_adts,m_adts.data); + writeAdtsHeader(m_adts,m_adts.buffer); getAACInfo(m_adts, (int &)m_audio_sample_rate, (int &)m_audio_num_channels); MP4Free(ppConfig); } @@ -148,7 +148,7 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri } if (m_audio_trId != MP4_INVALID_TRACK_ID) { - m_pChn->inputAAC((char *)m_adts.data, 7, 0); + m_pChn->inputAAC((char *)m_adts.buffer, 7, 0); } if (m_video_trId != MP4_INVALID_TRACK_ID) { @@ -240,12 +240,12 @@ inline bool MediaReader::readAudioSample(int iTimeInc) { auto iNextSample = getAudioSampleId(iTimeInc); for (auto i = m_audio_current; i < iNextSample; i++) { uint32_t numBytes = m_audio_sample_max_size; - uint8_t *pBytes = m_adts.data + 7; + uint8_t *pBytes = m_adts.buffer + 7; if(MP4ReadSample(m_hMP4File, m_audio_trId, i + 1, &pBytes, &numBytes)){ if (!iTimeInc) { m_adts.aac_frame_length = 7 + numBytes; - writeAdtsHeader(m_adts, m_adts.data); - writeAAC(m_adts.data, m_adts.aac_frame_length, (double) m_audio_ms * i / m_audio_num_samples); + writeAdtsHeader(m_adts, m_adts.buffer); + writeAAC(m_adts.buffer, m_adts.aac_frame_length, (double) m_audio_ms * i / m_audio_num_samples); } }else{ ErrorL << "读取音频失败:" << i+ 1; diff --git a/src/Player/Frame.cpp b/src/Player/Frame.cpp new file mode 100644 index 00000000..d15dcfc2 --- /dev/null +++ b/src/Player/Frame.cpp @@ -0,0 +1,5 @@ +// +// Created by xzl on 2018/10/18. +// + +#include "Frame.h" diff --git a/src/Player/Frame.h b/src/Player/Frame.h new file mode 100644 index 00000000..4f2d3133 --- /dev/null +++ b/src/Player/Frame.h @@ -0,0 +1,83 @@ +// +// Created by xzl on 2018/10/18. +// + +#ifndef ZLMEDIAKIT_FRAME_H +#define ZLMEDIAKIT_FRAME_H + +#include "Network/Socket.h" + +using namespace ZL::Network; + +class Frame : public Buffer { +public: + typedef std::shared_ptr Ptr; + virtual ~Frame(){} + virtual uint32_t stamp() = 0; +}; + +class H264Frame : public Frame { +public: + typedef std::shared_ptr Ptr; + + char *data() const override{ + return (char *)buffer.data(); + } + uint32_t size() const override { + return buffer.size(); + } + uint32_t stamp() override { + return timeStamp; + } +public: + uint16_t sequence; + uint32_t timeStamp; + unsigned char type; + string buffer; +}; + + + +//ADTS 头中相对有用的信息 采样率、声道数、帧长度 +class AdtsFrame : public Frame { +public: + typedef std::shared_ptr Ptr; + + char *data() const override{ + return (char *)buffer; + } + uint32_t size() const override { + return aac_frame_length; + } + uint32_t stamp() override { + return timeStamp; + } +public: + unsigned int syncword; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 + unsigned int id; //1 bslbf MPEG 标示符, 设置为1 + unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ + unsigned int protection_absent; //1 bslbf 表示是否误码校验 + unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC + unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 + unsigned int private_bit; //1 bslbf + unsigned int channel_configuration; //3 uimsbf 表示声道数 + unsigned int original; //1 bslbf + unsigned int home; //1 bslbf + //下面的为改变的参数即每一帧都不同 + unsigned int copyright_identification_bit; //1 bslbf + unsigned int copyright_identification_start; //1 bslbf + unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block + unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 +//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. +//所以说number_of_raw_data_blocks_in_frame == 0 +//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) + unsigned int no_raw_data_blocks_in_frame; //2 uimsfb + unsigned char buffer[2 * 1024 + 7]; + uint16_t sequence; + uint32_t timeStamp; +} ; + + + + +#endif //ZLMEDIAKIT_FRAME_H diff --git a/src/Player/Player.h b/src/Player/Player.h index 97d0b83f..6808d117 100644 --- a/src/Player/Player.h +++ b/src/Player/Player.h @@ -28,41 +28,10 @@ #define SRC_PLAYER_PLAYER_H_ #include +#include "Frame.h" + using namespace std; -typedef struct { - uint16_t sequence; - uint32_t timeStamp; - unsigned char type; - string data; -} H264Frame; - -//ADTS 头中相对有用的信息 采样率、声道数、帧长度 -typedef struct { - unsigned int syncword; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 - unsigned int id; //1 bslbf MPEG 标示符, 设置为1 - unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ - unsigned int protection_absent; //1 bslbf 表示是否误码校验 - unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC - unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 - unsigned int private_bit; //1 bslbf - unsigned int channel_configuration; //3 uimsbf 表示声道数 - unsigned int original; //1 bslbf - unsigned int home; //1 bslbf - //下面的为改变的参数即每一帧都不同 - unsigned int copyright_identification_bit; //1 bslbf - unsigned int copyright_identification_start; //1 bslbf - unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block - unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 -//no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. -//所以说number_of_raw_data_blocks_in_frame == 0 -//表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) - unsigned int no_raw_data_blocks_in_frame; //2 uimsfb - unsigned char data[2 * 1024 + 7]; - uint16_t sequence; - uint32_t timeStamp; -} AdtsFrame; - unsigned const samplingFrequencyTable[16] = { 96000, 88200, 64000, 48000, 44100, 32000, diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 0c93c5ee..56fa5058 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -36,6 +36,7 @@ #include "Util/mini.h" #include "Common/MediaSource.h" #include "Util/RingBuffer.h" +#include "Frame.h" using namespace std; using namespace ZL::Util; @@ -45,17 +46,10 @@ using namespace ZL::Network; namespace ZL { namespace Player { -class TrackFrame : public Buffer { -public: - typedef std::shared_ptr Ptr; - virtual ~TrackFrame(){} - virtual uint32_t stamp() = 0; -}; - class TrackFormat { public: typedef std::shared_ptr Ptr; - typedef RingBuffer RingType; + typedef RingBuffer RingType; typedef RingType::RingReader::Ptr ReaderType; typedef enum { @@ -80,7 +74,7 @@ public: return _ring->attach(useBuffer); } - void writeFrame(const TrackFrame::Ptr &frame,bool keypos = true){ + void writeFrame(const Frame::Ptr &frame,bool keypos = true){ _ring->write(frame, keypos); } private: diff --git a/src/RTP/AACRtpEncoder.cpp b/src/RTP/AACRtpEncoder.cpp new file mode 100644 index 00000000..141962af --- /dev/null +++ b/src/RTP/AACRtpEncoder.cpp @@ -0,0 +1,104 @@ +// +// Created by xzl on 2018/10/18. +// + +#include "AACRtpEncoder.h" + +void AACRtpEncoder::inputFame(const Frame::Ptr &frame, bool key_pos) { + RtpCodec::inputFame(frame, key_pos); + + GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Config::Rtp::kCycleMS); + auto uiStamp = frame->stamp(); + auto pcData = frame->data(); + auto iLen = frame->size(); + + uiStamp %= cycleMS; + char *ptr = (char *) pcData; + int iSize = iLen; + while (iSize > 0 ) { + if (iSize <= m_ui32MtuSize - 20) { + m_aucSectionBuf[0] = 0; + m_aucSectionBuf[1] = 16; + m_aucSectionBuf[2] = iLen >> 5; + m_aucSectionBuf[3] = (iLen & 0x1F) << 3; + memcpy(m_aucSectionBuf + 4, ptr, iSize); + makeAACRtp(m_aucSectionBuf, iSize + 4, true, uiStamp); + break; + } + m_aucSectionBuf[0] = 0; + m_aucSectionBuf[1] = 16; + m_aucSectionBuf[2] = (iLen) >> 5; + m_aucSectionBuf[3] = (iLen & 0x1F) << 3; + memcpy(m_aucSectionBuf + 4, ptr, m_ui32MtuSize - 20); + makeAACRtp(m_aucSectionBuf, m_ui32MtuSize - 16, false, uiStamp); + ptr += (m_ui32MtuSize - 20); + iSize -= (m_ui32MtuSize - 20); + + } +} + +void AACRtpEncoder::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp) { + uint16_t u16RtpLen = uiLen + 12; + m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp; + uint32_t ts = htonl(m_ui32TimeStamp); + uint16_t sq = htons(m_ui16Sequence); + uint32_t sc = htonl(m_ui32Ssrc); + auto pRtppkt = obtainRtp(); + auto &rtppkt = *(pRtppkt.get()); + unsigned char *pucRtp = rtppkt.payload; + pucRtp[0] = '$'; + pucRtp[1] = m_ui8Interleaved; + pucRtp[2] = u16RtpLen >> 8; + pucRtp[3] = u16RtpLen & 0x00FF; + pucRtp[4] = 0x80; + pucRtp[5] = (bMark << 7) | m_ui8PlayloadType; + memcpy(&pucRtp[6], &sq, 2); + memcpy(&pucRtp[8], &ts, 4); + //ssrc + memcpy(&pucRtp[12], &sc, 4); + //playload + memcpy(&pucRtp[16], pData, uiLen); + + rtppkt.PT = m_ui8PlayloadType; + rtppkt.interleaved = m_ui8Interleaved; + rtppkt.mark = bMark; + rtppkt.length = uiLen + 16; + rtppkt.sequence = m_ui16Sequence; + rtppkt.timeStamp = m_ui32TimeStamp; + rtppkt.ssrc = m_ui32Ssrc; + rtppkt.type = TrackAudio; + rtppkt.offset = 16; + + RtpCodec::inputRtp(pRtppkt, false); + m_ui16Sequence++; +} + +///////////////////////////////////////////////////////////////////////////////////// + +void AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { + RtpCodec::inputRtp(rtp, key_pos); + + auto &rtppack = *rtp; + char *frame = (char *) rtppack.payload + rtppack.offset; + int length = rtppack.length - rtppack.offset; + + if (m_adts->aac_frame_length + length - 4 > sizeof(AdtsFrame::buffer)) { + m_adts->aac_frame_length = 7; + return ; + } + memcpy(m_adts->buffer + m_adts->aac_frame_length, frame + 4, length - 4); + m_adts->aac_frame_length += (length - 4); + if (rtppack.mark == true) { + m_adts->sequence = rtppack.sequence; + + //todo(xzl) 完成时间戳转换 +// m_adts->timeStamp = rtppack.timeStamp * (1000.0 / m_iSampleRate); + writeAdtsHeader(*m_adts, m_adts->buffer); + RtpCodec::inputFame(m_adts,false); + m_adts->aac_frame_length = 7; + } +} + +AACRtpDecoder::AACRtpDecoder() { + m_adts = std::make_shared(); +} diff --git a/src/RTP/AACRtpEncoder.h b/src/RTP/AACRtpEncoder.h new file mode 100644 index 00000000..de67be64 --- /dev/null +++ b/src/RTP/AACRtpEncoder.h @@ -0,0 +1,41 @@ +// +// Created by xzl on 2018/10/18. +// + +#ifndef ZLMEDIAKIT_AACRTPCODEC_H +#define ZLMEDIAKIT_AACRTPCODEC_H + + +#include "RtpCodec.h" + +class AACRtpEncoder : public RtpEncoder { +public: + AACRtpEncoder(uint32_t ui32Ssrc, + uint32_t ui32MtuSize , + uint32_t ui32SampleRate, + uint8_t ui8PlayloadType = 97, + uint8_t ui8Interleaved = TrackAudio * 2) : + RtpEncoder(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved) { + } + ~AACRtpEncoder(){} + + void inputFame(const Frame::Ptr &frame,bool key_pos) override; +private: + void makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); +private: + unsigned char m_aucSectionBuf[1600]; +}; + + +class AACRtpDecoder : public RtpCodec{ +public: + AACRtpDecoder(); + ~AACRtpDecoder(){} + + void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override ; +private: + AdtsFrame::Ptr m_adts; +}; + + +#endif //ZLMEDIAKIT_AACRTPCODEC_H diff --git a/src/RTP/H264RtpEncoder.cpp b/src/RTP/H264RtpEncoder.cpp new file mode 100644 index 00000000..139b2972 --- /dev/null +++ b/src/RTP/H264RtpEncoder.cpp @@ -0,0 +1,92 @@ +// +// Created by xzl on 2018/10/18. +// + +#include "H264RtpEncoder.h" + +void H264RtpEncoder::inputFame(const Frame::Ptr &frame, bool key_pos) { + RtpCodec::inputFame(frame, key_pos); + + GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Config::Rtp::kCycleMS); + auto uiStamp = frame->stamp(); + auto pcData = frame->data(); + auto iLen = frame->size(); + + uiStamp %= cycleMS; + int iSize = m_ui32MtuSize - 2; + if (iLen > iSize) { //超过MTU + const unsigned char s_e_r_Start = 0x80; + const unsigned char s_e_r_Mid = 0x00; + const unsigned char s_e_r_End = 0x40; + //获取帧头数据,1byte + unsigned char naluType = *((unsigned char *) pcData) & 0x1f; //获取NALU的5bit 帧类型 + + unsigned char nal_ref_idc = *((unsigned char *) pcData) & 0x60; //获取NALU的2bit 帧重要程度 00 可以丢 11不能丢 + //nal_ref_idc = 0x60; + //组装FU-A帧头数据 2byte + unsigned char f_nri_type = nal_ref_idc + 28;//F为0 1bit,nri上面获取到2bit,28为FU-A分片类型5bit + unsigned char s_e_r_type = naluType; + bool bFirst = true; + bool mark = false; + int nOffset = 1; + while (!mark) { + if (iLen < nOffset + iSize) { //是否拆分结束 + iSize = iLen - nOffset; + mark = true; + s_e_r_type = s_e_r_End + naluType; + } else { + if (bFirst == true) { + s_e_r_type = s_e_r_Start + naluType; + bFirst = false; + } else { + s_e_r_type = s_e_r_Mid + naluType; + } + } + memcpy(m_aucSectionBuf, &f_nri_type, 1); + memcpy(m_aucSectionBuf + 1, &s_e_r_type, 1); + memcpy(m_aucSectionBuf + 2, (unsigned char *) pcData + nOffset, iSize); + nOffset += iSize; + makeH264Rtp(m_aucSectionBuf, iSize + 2, mark, uiStamp); + } + } else { + makeH264Rtp(pcData, iLen, true, uiStamp); + } +} + +void H264RtpEncoder::makeH264Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) { + uint16_t ui16RtpLen = len + 12; + m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp; + uint32_t ts = htonl(m_ui32TimeStamp); + uint16_t sq = htons(m_ui16Sequence); + uint32_t sc = htonl(m_ui32Ssrc); + + auto pRtppkt = obtainRtp(); + auto &rtppkt = *(pRtppkt.get()); + unsigned char *pucRtp = rtppkt.payload; + pucRtp[0] = '$'; + pucRtp[1] = m_ui8Interleaved; + pucRtp[2] = ui16RtpLen >> 8; + pucRtp[3] = ui16RtpLen & 0x00FF; + pucRtp[4] = 0x80; + pucRtp[5] = (mark << 7) | m_ui8PlayloadType; + memcpy(&pucRtp[6], &sq, 2); + memcpy(&pucRtp[8], &ts, 4); + //ssrc + memcpy(&pucRtp[12], &sc, 4); + //playload + memcpy(&pucRtp[16], data, len); + + rtppkt.PT = m_ui8PlayloadType; + rtppkt.interleaved = m_ui8Interleaved; + rtppkt.mark = mark; + rtppkt.length = len + 16; + rtppkt.sequence = m_ui16Sequence; + rtppkt.timeStamp = m_ui32TimeStamp; + rtppkt.ssrc = m_ui32Ssrc; + rtppkt.type = TrackVideo; + rtppkt.offset = 16; + + uint8_t type = ((uint8_t *) (data))[0] & 0x1F; + RtpCodec::inputRtp(pRtppkt,type == 5); + m_ui16Sequence++; +} diff --git a/src/RTP/H264RtpEncoder.h b/src/RTP/H264RtpEncoder.h new file mode 100644 index 00000000..08c97546 --- /dev/null +++ b/src/RTP/H264RtpEncoder.h @@ -0,0 +1,29 @@ +// +// Created by xzl on 2018/10/18. +// + +#ifndef ZLMEDIAKIT_H264RTPCODEC_H +#define ZLMEDIAKIT_H264RTPCODEC_H + +#include "RtpCodec.h" + +class H264RtpEncoder : public RtpEncoder { +public: + H264RtpEncoder(uint32_t ui32Ssrc, + uint32_t ui32MtuSize = 1400, + uint32_t ui32SampleRate = 90000, + uint8_t ui8PlayloadType = 96, + uint8_t ui8Interleaved = TrackVideo * 2) : + RtpEncoder(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved) { + } + ~H264RtpEncoder(){} + + void inputFame(const Frame::Ptr &frame,bool key_pos) override; +private: + void makeH264Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); +private: + unsigned char m_aucSectionBuf[1600]; +}; + + +#endif //ZLMEDIAKIT_H264RTPCODEC_H diff --git a/src/RTP/RtpCodec.cpp b/src/RTP/RtpCodec.cpp new file mode 100644 index 00000000..c738454d --- /dev/null +++ b/src/RTP/RtpCodec.cpp @@ -0,0 +1,5 @@ +// +// Created by xzl on 2018/10/18. +// + +#include "RtpCodec.h" diff --git a/src/RTP/RtpCodec.h b/src/RTP/RtpCodec.h new file mode 100644 index 00000000..aadf9061 --- /dev/null +++ b/src/RTP/RtpCodec.h @@ -0,0 +1,112 @@ +// +// Created by xzl on 2018/10/18. +// + +#ifndef ZLMEDIAKIT_RTPCODEC_H +#define ZLMEDIAKIT_RTPCODEC_H + +#include +#include "Util/RingBuffer.h" +#include "Rtsp/Rtsp.h" +#include "Player/PlayerBase.h" + +using namespace std; +using namespace ZL::Util; +using namespace ZL::Player; + +class RtpCodec{ +public: + typedef std::shared_ptr Ptr; + typedef RingBuffer FrameRing; + typedef RingBuffer RtpRing; + + RtpCodec(){ + _frameRing = std::make_shared(); + _rtpRing = std::make_shared(); + } + virtual ~RtpCodec(){} + + FrameRing::Ptr &getFrameRing() { + return _frameRing; + } + RtpRing::Ptr &getRtpRing() { + return _rtpRing; + } + + virtual void inputFame(const Frame::Ptr &frame,bool key_pos){ + _frameRing->write(frame,key_pos); + } + virtual void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos){ + _rtpRing->write(rtp,key_pos); + } +private: + FrameRing::Ptr _frameRing; + RtpRing::Ptr _rtpRing; +}; + + +class RtpEncoder : public RtpCodec{ +public: + typedef std::shared_ptr Ptr; + + RtpEncoder(uint32_t ui32Ssrc, + uint32_t ui32MtuSize, + uint32_t ui32SampleRate, + uint8_t ui8PlayloadType, + uint8_t ui8Interleaved) { + m_ui32Ssrc = ui32Ssrc; + m_ui32SampleRate = ui32SampleRate; + m_ui32MtuSize = ui32MtuSize; + m_ui8PlayloadType = ui8PlayloadType; + m_ui8Interleaved = ui8Interleaved; + m_rtpPool.setSize(32); + } + + ~RtpEncoder(){} + + int getInterleaved() const { + return m_ui8Interleaved; + } + + int getPlayloadType() const { + return m_ui8PlayloadType; + } + + int getSampleRate() const { + return m_ui32SampleRate; + } + + uint32_t getSsrc() const { + return m_ui32Ssrc; + } + + uint16_t getSeqence() const { + return m_ui16Sequence; + } + uint32_t getTimestamp() const { + return m_ui32TimeStamp; + } + uint32_t getMtuSize() const { + return m_ui32MtuSize; + } +protected: + RtpPacket::Ptr obtainRtp(){ + return m_rtpPool.obtain(); + } +protected: + uint32_t m_ui32Ssrc; + uint32_t m_ui32SampleRate; + uint32_t m_ui32MtuSize; + uint8_t m_ui8PlayloadType; + uint8_t m_ui8Interleaved; + uint16_t m_ui16Sequence = 0; + uint32_t m_ui32TimeStamp = 0; + ResourcePool m_rtpPool; +}; + + + + + + +#endif //ZLMEDIAKIT_RTPCODEC_H diff --git a/src/Rtmp/FlvMuxer.cpp b/src/Rtmp/FlvMuxer.cpp index 08f67a88..c648ca16 100644 --- a/src/Rtmp/FlvMuxer.cpp +++ b/src/Rtmp/FlvMuxer.cpp @@ -106,7 +106,7 @@ public: BufferRtmp(const RtmpPacket::Ptr & pkt):_rtmp(pkt){} virtual ~BufferRtmp(){} - char *data() override { + char *data() const override { return (char *)_rtmp->strBuf.data(); } uint32_t size() const override { diff --git a/src/Rtmp/RtmpParser.cpp b/src/Rtmp/RtmpParser.cpp index ff0f5edd..8d8233b4 100644 --- a/src/Rtmp/RtmpParser.cpp +++ b/src/Rtmp/RtmpParser.cpp @@ -152,15 +152,15 @@ inline void RtmpParser::_onGetH264(const char* pcData, int iLen, uint32_t ui32Ti inline void RtmpParser::onGetH264(const char* pcData, int iLen, uint32_t ui32TimeStamp) { m_h264frame.type = pcData[0] & 0x1F; m_h264frame.timeStamp = ui32TimeStamp; - m_h264frame.data.assign("\x0\x0\x0\x1", 4); //添加264头 - m_h264frame.data.append(pcData, iLen); + m_h264frame.buffer.assign("\x0\x0\x0\x1", 4); //添加264头 + m_h264frame.buffer.append(pcData, iLen); { lock_guard lck(m_mtxCB); if (onVideo) { onVideo(m_h264frame); } } - m_h264frame.data.clear(); + m_h264frame.buffer.clear(); } inline bool RtmpParser::inputAudio(const RtmpPacket::Ptr &pkt) { @@ -180,15 +180,15 @@ inline bool RtmpParser::inputAudio(const RtmpPacket::Ptr &pkt) { return false; } inline void RtmpParser::onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp) { - if(iLen + 7 > sizeof(m_adts.data)){ + if(iLen + 7 > sizeof(m_adts.buffer)){ WarnL << "Illegal adts data, exceeding the length limit."; return; } //添加adts头 - memcpy(m_adts.data + 7, pcData, iLen); + memcpy(m_adts.buffer + 7, pcData, iLen); m_adts.aac_frame_length = 7 + iLen; m_adts.timeStamp = ui32TimeStamp; - writeAdtsHeader(m_adts, m_adts.data); + writeAdtsHeader(m_adts, m_adts.buffer); { lock_guard lck(m_mtxCB); if (onAudio) { diff --git a/src/Rtmp/RtmpToRtspMediaSource.cpp b/src/Rtmp/RtmpToRtspMediaSource.cpp index df331e38..071e8d4f 100644 --- a/src/Rtmp/RtmpToRtspMediaSource.cpp +++ b/src/Rtmp/RtmpToRtspMediaSource.cpp @@ -48,20 +48,20 @@ RtmpToRtspMediaSource::~RtmpToRtspMediaSource() {} void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) { if(m_pRecorder){ - m_pRecorder->inputH264((char *) frame.data.data(), frame.data.size(), frame.timeStamp, frame.type); + m_pRecorder->inputH264((char *) frame.data(), frame.size(), frame.timeStamp, frame.type); } if(m_pRtpMaker_h264){ - m_pRtpMaker_h264->makeRtp(frame.data.data() + 4, frame.data.size() - 4, frame.timeStamp); + m_pRtpMaker_h264->makeRtp(frame.data() + 4, frame.size() - 4, frame.timeStamp); } } inline void RtmpToRtspMediaSource::onGetAdts(const AdtsFrame &frame) { if(m_pRecorder){ - m_pRecorder->inputAAC((char *) frame.data, frame.aac_frame_length, frame.timeStamp); + m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp); } if (m_pRtpMaker_aac) { - m_pRtpMaker_aac->makeRtp((char *) frame.data + 7, frame.aac_frame_length - 7, frame.timeStamp); + m_pRtpMaker_aac->makeRtp((char *) frame.buffer + 7, frame.aac_frame_length - 7, frame.timeStamp); } } diff --git a/src/Rtsp/RtpParser.cpp b/src/Rtsp/RtpParser.cpp index e475d187..30f0a1c4 100644 --- a/src/Rtsp/RtpParser.cpp +++ b/src/Rtsp/RtpParser.cpp @@ -121,13 +121,13 @@ inline bool RtpParser::inputVideo(const RtpPacket& rtppack, //Type==8:PPS frame if (nal.type >= 0 && nal.type < 24) { //a full frame - m_h264frame.data.assign("\x0\x0\x0\x1", 4); - m_h264frame.data.append((char *)frame, length); + m_h264frame.buffer.assign("\x0\x0\x0\x1", 4); + m_h264frame.buffer.append((char *)frame, length); m_h264frame.type = nal.type; m_h264frame.timeStamp = rtppack.timeStamp / 90; m_h264frame.sequence = rtppack.sequence; _onGetH264(m_h264frame); - m_h264frame.data.clear(); + m_h264frame.buffer.clear(); return (m_h264frame.type == 7); } if (nal.type == 28) { @@ -137,9 +137,9 @@ inline bool RtpParser::inputVideo(const RtpPacket& rtppack, if (fu.S == 1) { //FU-A start char tmp = (nal.forbidden_zero_bit << 7 | nal.nal_ref_idc << 5 | fu.type); - m_h264frame.data.assign("\x0\x0\x0\x1", 4); - m_h264frame.data.push_back(tmp); - m_h264frame.data.append((char *)frame + 2, length - 2); + m_h264frame.buffer.assign("\x0\x0\x0\x1", 4); + m_h264frame.buffer.push_back(tmp); + m_h264frame.buffer.append((char *)frame + 2, length - 2); m_h264frame.type = fu.type; m_h264frame.timeStamp = rtppack.timeStamp / 90; m_h264frame.sequence = rtppack.sequence; @@ -147,21 +147,21 @@ inline bool RtpParser::inputVideo(const RtpPacket& rtppack, } if (rtppack.sequence != (uint16_t)(m_h264frame.sequence + 1)) { - m_h264frame.data.clear(); + m_h264frame.buffer.clear(); WarnL << "丢包,帧废弃:" << rtppack.sequence << "," << m_h264frame.sequence; return false; } m_h264frame.sequence = rtppack.sequence; if (fu.E == 1) { //FU-A end - m_h264frame.data.append((char *)frame + 2, length - 2); + m_h264frame.buffer.append((char *)frame + 2, length - 2); m_h264frame.timeStamp = rtppack.timeStamp / 90; _onGetH264(m_h264frame); - m_h264frame.data.clear(); + m_h264frame.buffer.clear(); return false; } //FU-A mid - m_h264frame.data.append((char *)frame + 2, length - 2); + m_h264frame.buffer.append((char *)frame + 2, length - 2); return false; } WarnL << nal.type << " " << rtppack.sequence; @@ -242,16 +242,16 @@ inline bool RtpParser::inputAudio(const RtpPacket& rtppack, char *frame = (char *) rtppack.payload + rtppack.offset; int length = rtppack.length - rtppack.offset; - if (m_adts.aac_frame_length + length - 4 > sizeof(AdtsFrame::data)) { + if (m_adts.aac_frame_length + length - 4 > sizeof(AdtsFrame::buffer)) { m_adts.aac_frame_length = 7; return false; } - memcpy(m_adts.data + m_adts.aac_frame_length, frame + 4, length - 4); + memcpy(m_adts.buffer + m_adts.aac_frame_length, frame + 4, length - 4); m_adts.aac_frame_length += (length - 4); if (rtppack.mark == true) { m_adts.sequence = rtppack.sequence; m_adts.timeStamp = rtppack.timeStamp * (1000.0 / m_iSampleRate); - writeAdtsHeader(m_adts, m_adts.data); + writeAdtsHeader(m_adts, m_adts.buffer); onGetAdts(m_adts); m_adts.aac_frame_length = 7; } @@ -264,18 +264,18 @@ inline void RtpParser::_onGetH264(H264Frame& frame) { H264Frame insertedFrame; insertedFrame.type = 7; //SPS insertedFrame.timeStamp = frame.timeStamp; - insertedFrame.data = m_strSPS; + insertedFrame.buffer = m_strSPS; onGetH264(insertedFrame); insertedFrame.type = 8; //PPS insertedFrame.timeStamp = frame.timeStamp; - insertedFrame.data = m_strPPS; + insertedFrame.buffer = m_strPPS; onGetH264(insertedFrame); onGetH264(frame); } break; case 7: {//SPS - m_strSPS = frame.data; + m_strSPS = frame.buffer; if(m_bParseSpsDelay && !m_strSPS.empty()){ m_bParseSpsDelay = false; getAVCInfo(m_strSPS, m_iVideoWidth, m_iVideoHeight, m_fVideoFps); @@ -283,7 +283,7 @@ inline void RtpParser::_onGetH264(H264Frame& frame) { } break; case 8://PPS - m_strPPS=frame.data; + m_strPPS=frame.buffer; break; case 1: //B or P diff --git a/src/Rtsp/RtspSession.h b/src/Rtsp/RtspSession.h index 8b08060a..1748d327 100644 --- a/src/Rtsp/RtspSession.h +++ b/src/Rtsp/RtspSession.h @@ -59,7 +59,7 @@ public: BufferRtp(const RtpPacket::Ptr & pkt,uint32_t offset = 0 ):_rtp(pkt),_offset(offset){} virtual ~BufferRtp(){} - char *data() override { + char *data() const override { return (char *)_rtp->payload + _offset; } uint32_t size() const override { diff --git a/src/Rtsp/RtspToRtmpMediaSource.cpp b/src/Rtsp/RtspToRtmpMediaSource.cpp index 3c255da7..810ab116 100644 --- a/src/Rtsp/RtspToRtmpMediaSource.cpp +++ b/src/Rtsp/RtspToRtmpMediaSource.cpp @@ -92,9 +92,9 @@ void RtspToRtmpMediaSource::makeVideoConfigPkt() { } void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) { if(m_pRecorder){ - m_pRecorder->inputH264((char *) frame.data.data(), frame.data.size(), frame.timeStamp, frame.type); + m_pRecorder->inputH264((char *) frame.data(), frame.size(), frame.timeStamp, frame.type); } - uint8_t nal_type = frame.data[4] & 0x1F; + uint8_t nal_type = frame.data()[4] & 0x1F; int8_t flags = 7; //h.264 bool is_config = false; switch (nal_type) { @@ -112,10 +112,10 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) { rtmpPkt->strBuf.push_back(flags); rtmpPkt->strBuf.push_back(!is_config); rtmpPkt->strBuf.append("\x0\x0\x0", 3); - uint32_t size = frame.data.size() - 4; + uint32_t size = frame.size() - 4; size = htonl(size); rtmpPkt->strBuf.append((char *) &size, 4); - rtmpPkt->strBuf.append(&frame.data[4], frame.data.size() - 4); + rtmpPkt->strBuf.append(&frame.data()[4], frame.size() - 4); rtmpPkt->bodySize = rtmpPkt->strBuf.size(); rtmpPkt->chunkId = CHUNK_VIDEO; @@ -126,7 +126,7 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) { } void RtspToRtmpMediaSource::onGetAdts(const AdtsFrame& frame) { if(m_pRecorder){ - m_pRecorder->inputAAC((char *) frame.data, frame.aac_frame_length, frame.timeStamp); + m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp); } RtmpPacket::Ptr rtmpPkt(new RtmpPacket); @@ -134,7 +134,7 @@ void RtspToRtmpMediaSource::onGetAdts(const AdtsFrame& frame) { uint8_t is_config = false; rtmpPkt->strBuf.push_back(m_ui8AudioFlags); rtmpPkt->strBuf.push_back(!is_config); - rtmpPkt->strBuf.append((char *) frame.data + 7, frame.aac_frame_length - 7); + rtmpPkt->strBuf.append((char *) frame.buffer + 7, frame.aac_frame_length - 7); rtmpPkt->bodySize = rtmpPkt->strBuf.size(); rtmpPkt->chunkId = CHUNK_AUDIO;