mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-29 14:45:55 +08:00
初步整理Rtp打包解包
This commit is contained in:
parent
4b87ec36c6
commit
8ed205878f
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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
5
src/Player/Frame.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by xzl on 2018/10/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Frame.h"
|
83
src/Player/Frame.h
Normal file
83
src/Player/Frame.h
Normal 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
|
@ -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,
|
||||||
|
@ -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
104
src/RTP/AACRtpEncoder.cpp
Normal 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
41
src/RTP/AACRtpEncoder.h
Normal 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
|
92
src/RTP/H264RtpEncoder.cpp
Normal file
92
src/RTP/H264RtpEncoder.cpp
Normal 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
29
src/RTP/H264RtpEncoder.h
Normal 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
5
src/RTP/RtpCodec.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by xzl on 2018/10/18.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "RtpCodec.h"
|
112
src/RTP/RtpCodec.h
Normal file
112
src/RTP/RtpCodec.h
Normal 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
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user