初步整理Rtp打包解包

This commit is contained in:
xiongziliang 2018-10-18 23:48:00 +08:00
parent 4b87ec36c6
commit 8ed205878f
19 changed files with 521 additions and 89 deletions

View File

@ -128,8 +128,8 @@ void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,boo
inputAAC(pcData+7,iDataLen-7,uiStamp,pcData); inputAAC(pcData+7,iDataLen-7,uiStamp,pcData);
} else if(m_pAdtsHeader){ } else if(m_pAdtsHeader){
m_pAdtsHeader->aac_frame_length = iDataLen; m_pAdtsHeader->aac_frame_length = iDataLen;
writeAdtsHeader(*m_pAdtsHeader,m_pAdtsHeader->data); writeAdtsHeader(*m_pAdtsHeader,(uint8_t *)m_pAdtsHeader->buffer);
inputAAC(pcData,iDataLen,uiStamp,(const char *)m_pAdtsHeader->data); inputAAC(pcData,iDataLen,uiStamp,(const char *)m_pAdtsHeader->buffer);
} }
} }
void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader){ 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) { void DevChannel::initAudio(const AudioInfo& info) {
m_audio.reset(new AudioInfo(info)); m_audio.reset(new AudioInfo(info));
m_pAdtsHeader.reset((AdtsFrame *)malloc(sizeof(AdtsFrame) - sizeof(AdtsFrame::data) + 7),[](AdtsFrame *ptr){ m_pAdtsHeader = std::make_shared<AdtsFrame>();
free(ptr);
});
m_pAdtsHeader->syncword = 0x0FFF; m_pAdtsHeader->syncword = 0x0FFF;
m_pAdtsHeader->id = 0; m_pAdtsHeader->id = 0;

View File

@ -89,7 +89,7 @@ void PlayerProxy::play(const char* strUrl) {
return; return;
} }
if(strongSelf->m_pChn){ 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){ if(!strongSelf->m_haveAudio){
strongSelf->makeMuteAudio(data.timeStamp); strongSelf->makeMuteAudio(data.timeStamp);
} }
@ -103,7 +103,7 @@ void PlayerProxy::play(const char* strUrl) {
return; return;
} }
if(strongSelf->m_pChn){ 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{ }else{
strongSelf->initMedia(); strongSelf->initMedia();
} }

View File

@ -109,7 +109,7 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri
if(MP4GetTrackESConfiguration(m_hMP4File,m_audio_trId,&ppConfig,&pConfigSize)){ if(MP4GetTrackESConfiguration(m_hMP4File,m_audio_trId,&ppConfig,&pConfigSize)){
m_strAacCfg.assign((char *)ppConfig, pConfigSize); m_strAacCfg.assign((char *)ppConfig, pConfigSize);
makeAdtsHeader(m_strAacCfg, m_adts); 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); getAACInfo(m_adts, (int &)m_audio_sample_rate, (int &)m_audio_num_channels);
MP4Free(ppConfig); MP4Free(ppConfig);
} }
@ -148,7 +148,7 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri
} }
if (m_audio_trId != MP4_INVALID_TRACK_ID) { 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) { if (m_video_trId != MP4_INVALID_TRACK_ID) {
@ -240,12 +240,12 @@ inline bool MediaReader::readAudioSample(int iTimeInc) {
auto iNextSample = getAudioSampleId(iTimeInc); auto iNextSample = getAudioSampleId(iTimeInc);
for (auto i = m_audio_current; i < iNextSample; i++) { for (auto i = m_audio_current; i < iNextSample; i++) {
uint32_t numBytes = m_audio_sample_max_size; 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(MP4ReadSample(m_hMP4File, m_audio_trId, i + 1, &pBytes, &numBytes)){
if (!iTimeInc) { if (!iTimeInc) {
m_adts.aac_frame_length = 7 + numBytes; m_adts.aac_frame_length = 7 + numBytes;
writeAdtsHeader(m_adts, m_adts.data); writeAdtsHeader(m_adts, m_adts.buffer);
writeAAC(m_adts.data, m_adts.aac_frame_length, (double) m_audio_ms * i / m_audio_num_samples); writeAAC(m_adts.buffer, m_adts.aac_frame_length, (double) m_audio_ms * i / m_audio_num_samples);
} }
}else{ }else{
ErrorL << "读取音频失败:" << i+ 1; ErrorL << "读取音频失败:" << i+ 1;

5
src/Player/Frame.cpp Normal file
View File

@ -0,0 +1,5 @@
//
// Created by xzl on 2018/10/18.
//
#include "Frame.h"

83
src/Player/Frame.h Normal file
View File

@ -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<Frame> Ptr;
virtual ~Frame(){}
virtual uint32_t stamp() = 0;
};
class H264Frame : public Frame {
public:
typedef std::shared_ptr<H264Frame> 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<AdtsFrame> 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

View File

@ -28,41 +28,10 @@
#define SRC_PLAYER_PLAYER_H_ #define SRC_PLAYER_PLAYER_H_
#include <string> #include <string>
#include "Frame.h"
using namespace std; 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, unsigned const samplingFrequencyTable[16] = { 96000, 88200,
64000, 48000, 64000, 48000,
44100, 32000, 44100, 32000,

View File

@ -36,6 +36,7 @@
#include "Util/mini.h" #include "Util/mini.h"
#include "Common/MediaSource.h" #include "Common/MediaSource.h"
#include "Util/RingBuffer.h" #include "Util/RingBuffer.h"
#include "Frame.h"
using namespace std; using namespace std;
using namespace ZL::Util; using namespace ZL::Util;
@ -45,17 +46,10 @@ using namespace ZL::Network;
namespace ZL { namespace ZL {
namespace Player { namespace Player {
class TrackFrame : public Buffer {
public:
typedef std::shared_ptr<TrackFrame> Ptr;
virtual ~TrackFrame(){}
virtual uint32_t stamp() = 0;
};
class TrackFormat { class TrackFormat {
public: public:
typedef std::shared_ptr<TrackFormat> Ptr; typedef std::shared_ptr<TrackFormat> Ptr;
typedef RingBuffer<TrackFrame::Ptr> RingType; typedef RingBuffer<Frame::Ptr> RingType;
typedef RingType::RingReader::Ptr ReaderType; typedef RingType::RingReader::Ptr ReaderType;
typedef enum { typedef enum {
@ -80,7 +74,7 @@ public:
return _ring->attach(useBuffer); 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); _ring->write(frame, keypos);
} }
private: private:

104
src/RTP/AACRtpEncoder.cpp Normal file
View File

@ -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<AdtsFrame>();
}

41
src/RTP/AACRtpEncoder.h Normal file
View File

@ -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

View File

@ -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++;
}

29
src/RTP/H264RtpEncoder.h Normal file
View File

@ -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

5
src/RTP/RtpCodec.cpp Normal file
View File

@ -0,0 +1,5 @@
//
// Created by xzl on 2018/10/18.
//
#include "RtpCodec.h"

112
src/RTP/RtpCodec.h Normal file
View File

@ -0,0 +1,112 @@
//
// Created by xzl on 2018/10/18.
//
#ifndef ZLMEDIAKIT_RTPCODEC_H
#define ZLMEDIAKIT_RTPCODEC_H
#include <memory>
#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<RtpCodec> Ptr;
typedef RingBuffer<Frame::Ptr> FrameRing;
typedef RingBuffer<RtpPacket::Ptr> RtpRing;
RtpCodec(){
_frameRing = std::make_shared<FrameRing>();
_rtpRing = std::make_shared<RtpRing>();
}
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<RtpEncoder> 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<RtpPacket> m_rtpPool;
};
#endif //ZLMEDIAKIT_RTPCODEC_H

View File

@ -106,7 +106,7 @@ public:
BufferRtmp(const RtmpPacket::Ptr & pkt):_rtmp(pkt){} BufferRtmp(const RtmpPacket::Ptr & pkt):_rtmp(pkt){}
virtual ~BufferRtmp(){} virtual ~BufferRtmp(){}
char *data() override { char *data() const override {
return (char *)_rtmp->strBuf.data(); return (char *)_rtmp->strBuf.data();
} }
uint32_t size() const override { uint32_t size() const override {

View File

@ -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) { inline void RtmpParser::onGetH264(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
m_h264frame.type = pcData[0] & 0x1F; m_h264frame.type = pcData[0] & 0x1F;
m_h264frame.timeStamp = ui32TimeStamp; m_h264frame.timeStamp = ui32TimeStamp;
m_h264frame.data.assign("\x0\x0\x0\x1", 4); //添加264头 m_h264frame.buffer.assign("\x0\x0\x0\x1", 4); //添加264头
m_h264frame.data.append(pcData, iLen); m_h264frame.buffer.append(pcData, iLen);
{ {
lock_guard<recursive_mutex> lck(m_mtxCB); lock_guard<recursive_mutex> lck(m_mtxCB);
if (onVideo) { if (onVideo) {
onVideo(m_h264frame); onVideo(m_h264frame);
} }
} }
m_h264frame.data.clear(); m_h264frame.buffer.clear();
} }
inline bool RtmpParser::inputAudio(const RtmpPacket::Ptr &pkt) { inline bool RtmpParser::inputAudio(const RtmpPacket::Ptr &pkt) {
@ -180,15 +180,15 @@ inline bool RtmpParser::inputAudio(const RtmpPacket::Ptr &pkt) {
return false; return false;
} }
inline void RtmpParser::onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp) { 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."; WarnL << "Illegal adts data, exceeding the length limit.";
return; return;
} }
//添加adts头 //添加adts头
memcpy(m_adts.data + 7, pcData, iLen); memcpy(m_adts.buffer + 7, pcData, iLen);
m_adts.aac_frame_length = 7 + iLen; m_adts.aac_frame_length = 7 + iLen;
m_adts.timeStamp = ui32TimeStamp; m_adts.timeStamp = ui32TimeStamp;
writeAdtsHeader(m_adts, m_adts.data); writeAdtsHeader(m_adts, m_adts.buffer);
{ {
lock_guard<recursive_mutex> lck(m_mtxCB); lock_guard<recursive_mutex> lck(m_mtxCB);
if (onAudio) { if (onAudio) {

View File

@ -48,20 +48,20 @@ RtmpToRtspMediaSource::~RtmpToRtspMediaSource() {}
void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) { void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) {
if(m_pRecorder){ 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){ 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) { inline void RtmpToRtspMediaSource::onGetAdts(const AdtsFrame &frame) {
if(m_pRecorder){ 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) { 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);
} }
} }

View File

@ -121,13 +121,13 @@ inline bool RtpParser::inputVideo(const RtpPacket& rtppack,
//Type==8:PPS frame //Type==8:PPS frame
if (nal.type >= 0 && nal.type < 24) { if (nal.type >= 0 && nal.type < 24) {
//a full frame //a full frame
m_h264frame.data.assign("\x0\x0\x0\x1", 4); m_h264frame.buffer.assign("\x0\x0\x0\x1", 4);
m_h264frame.data.append((char *)frame, length); m_h264frame.buffer.append((char *)frame, length);
m_h264frame.type = nal.type; m_h264frame.type = nal.type;
m_h264frame.timeStamp = rtppack.timeStamp / 90; m_h264frame.timeStamp = rtppack.timeStamp / 90;
m_h264frame.sequence = rtppack.sequence; m_h264frame.sequence = rtppack.sequence;
_onGetH264(m_h264frame); _onGetH264(m_h264frame);
m_h264frame.data.clear(); m_h264frame.buffer.clear();
return (m_h264frame.type == 7); return (m_h264frame.type == 7);
} }
if (nal.type == 28) { if (nal.type == 28) {
@ -137,9 +137,9 @@ inline bool RtpParser::inputVideo(const RtpPacket& rtppack,
if (fu.S == 1) { if (fu.S == 1) {
//FU-A start //FU-A start
char tmp = (nal.forbidden_zero_bit << 7 | nal.nal_ref_idc << 5 | fu.type); 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.buffer.assign("\x0\x0\x0\x1", 4);
m_h264frame.data.push_back(tmp); m_h264frame.buffer.push_back(tmp);
m_h264frame.data.append((char *)frame + 2, length - 2); m_h264frame.buffer.append((char *)frame + 2, length - 2);
m_h264frame.type = fu.type; m_h264frame.type = fu.type;
m_h264frame.timeStamp = rtppack.timeStamp / 90; m_h264frame.timeStamp = rtppack.timeStamp / 90;
m_h264frame.sequence = rtppack.sequence; 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)) { if (rtppack.sequence != (uint16_t)(m_h264frame.sequence + 1)) {
m_h264frame.data.clear(); m_h264frame.buffer.clear();
WarnL << "丢包,帧废弃:" << rtppack.sequence << "," << m_h264frame.sequence; WarnL << "丢包,帧废弃:" << rtppack.sequence << "," << m_h264frame.sequence;
return false; return false;
} }
m_h264frame.sequence = rtppack.sequence; m_h264frame.sequence = rtppack.sequence;
if (fu.E == 1) { if (fu.E == 1) {
//FU-A end //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; m_h264frame.timeStamp = rtppack.timeStamp / 90;
_onGetH264(m_h264frame); _onGetH264(m_h264frame);
m_h264frame.data.clear(); m_h264frame.buffer.clear();
return false; return false;
} }
//FU-A mid //FU-A mid
m_h264frame.data.append((char *)frame + 2, length - 2); m_h264frame.buffer.append((char *)frame + 2, length - 2);
return false; return false;
} }
WarnL << nal.type << " " << rtppack.sequence; WarnL << nal.type << " " << rtppack.sequence;
@ -242,16 +242,16 @@ inline bool RtpParser::inputAudio(const RtpPacket& rtppack,
char *frame = (char *) rtppack.payload + rtppack.offset; char *frame = (char *) rtppack.payload + rtppack.offset;
int length = rtppack.length - 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; m_adts.aac_frame_length = 7;
return false; 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); m_adts.aac_frame_length += (length - 4);
if (rtppack.mark == true) { if (rtppack.mark == true) {
m_adts.sequence = rtppack.sequence; m_adts.sequence = rtppack.sequence;
m_adts.timeStamp = rtppack.timeStamp * (1000.0 / m_iSampleRate); m_adts.timeStamp = rtppack.timeStamp * (1000.0 / m_iSampleRate);
writeAdtsHeader(m_adts, m_adts.data); writeAdtsHeader(m_adts, m_adts.buffer);
onGetAdts(m_adts); onGetAdts(m_adts);
m_adts.aac_frame_length = 7; m_adts.aac_frame_length = 7;
} }
@ -264,18 +264,18 @@ inline void RtpParser::_onGetH264(H264Frame& frame) {
H264Frame insertedFrame; H264Frame insertedFrame;
insertedFrame.type = 7; //SPS insertedFrame.type = 7; //SPS
insertedFrame.timeStamp = frame.timeStamp; insertedFrame.timeStamp = frame.timeStamp;
insertedFrame.data = m_strSPS; insertedFrame.buffer = m_strSPS;
onGetH264(insertedFrame); onGetH264(insertedFrame);
insertedFrame.type = 8; //PPS insertedFrame.type = 8; //PPS
insertedFrame.timeStamp = frame.timeStamp; insertedFrame.timeStamp = frame.timeStamp;
insertedFrame.data = m_strPPS; insertedFrame.buffer = m_strPPS;
onGetH264(insertedFrame); onGetH264(insertedFrame);
onGetH264(frame); onGetH264(frame);
} }
break; break;
case 7: {//SPS case 7: {//SPS
m_strSPS = frame.data; m_strSPS = frame.buffer;
if(m_bParseSpsDelay && !m_strSPS.empty()){ if(m_bParseSpsDelay && !m_strSPS.empty()){
m_bParseSpsDelay = false; m_bParseSpsDelay = false;
getAVCInfo(m_strSPS, m_iVideoWidth, m_iVideoHeight, m_fVideoFps); getAVCInfo(m_strSPS, m_iVideoWidth, m_iVideoHeight, m_fVideoFps);
@ -283,7 +283,7 @@ inline void RtpParser::_onGetH264(H264Frame& frame) {
} }
break; break;
case 8://PPS case 8://PPS
m_strPPS=frame.data; m_strPPS=frame.buffer;
break; break;
case 1: case 1:
//B or P //B or P

View File

@ -59,7 +59,7 @@ public:
BufferRtp(const RtpPacket::Ptr & pkt,uint32_t offset = 0 ):_rtp(pkt),_offset(offset){} BufferRtp(const RtpPacket::Ptr & pkt,uint32_t offset = 0 ):_rtp(pkt),_offset(offset){}
virtual ~BufferRtp(){} virtual ~BufferRtp(){}
char *data() override { char *data() const override {
return (char *)_rtp->payload + _offset; return (char *)_rtp->payload + _offset;
} }
uint32_t size() const override { uint32_t size() const override {

View File

@ -92,9 +92,9 @@ void RtspToRtmpMediaSource::makeVideoConfigPkt() {
} }
void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) { void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
if(m_pRecorder){ 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 int8_t flags = 7; //h.264
bool is_config = false; bool is_config = false;
switch (nal_type) { switch (nal_type) {
@ -112,10 +112,10 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
rtmpPkt->strBuf.push_back(flags); rtmpPkt->strBuf.push_back(flags);
rtmpPkt->strBuf.push_back(!is_config); rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append("\x0\x0\x0", 3); rtmpPkt->strBuf.append("\x0\x0\x0", 3);
uint32_t size = frame.data.size() - 4; uint32_t size = frame.size() - 4;
size = htonl(size); size = htonl(size);
rtmpPkt->strBuf.append((char *) &size, 4); 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->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_VIDEO; rtmpPkt->chunkId = CHUNK_VIDEO;
@ -126,7 +126,7 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
} }
void RtspToRtmpMediaSource::onGetAdts(const AdtsFrame& frame) { void RtspToRtmpMediaSource::onGetAdts(const AdtsFrame& frame) {
if(m_pRecorder){ 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); RtmpPacket::Ptr rtmpPkt(new RtmpPacket);
@ -134,7 +134,7 @@ void RtspToRtmpMediaSource::onGetAdts(const AdtsFrame& frame) {
uint8_t is_config = false; uint8_t is_config = false;
rtmpPkt->strBuf.push_back(m_ui8AudioFlags); rtmpPkt->strBuf.push_back(m_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config); 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->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_AUDIO; rtmpPkt->chunkId = CHUNK_AUDIO;