完成AAC RTMP编解码类

This commit is contained in:
xiongziliang 2018-10-24 14:21:59 +08:00
parent 6c9d50b04b
commit f4bce611ef
10 changed files with 209 additions and 21 deletions

View File

@ -114,12 +114,12 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
m_adts->sequence = rtppack->sequence;
m_adts->timeStamp = rtppack->timeStamp * (1000.0 / m_sampleRate);
writeAdtsHeader(*m_adts, m_adts->buffer);
onGetAdts(m_adts);
onGetAAC(m_adts);
}
return false;
}
void AACRtpDecoder::onGetAdts(const AACFrame::Ptr &frame) {
void AACRtpDecoder::onGetAAC(const AACFrame::Ptr &frame) {
//写入环形缓存
RtpCodec::inputFrame(frame);
m_adts = obtainFrame();

View File

@ -35,7 +35,7 @@ public:
return CodecAAC;
}
private:
void onGetAdts(const AACFrame::Ptr &frame);
void onGetAAC(const AACFrame::Ptr &frame);
AACFrame::Ptr obtainFrame();
private:
AACFrame::Ptr m_adts;

View File

@ -55,7 +55,7 @@ void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) {
m_pRtpMaker_h264->makeRtp(frame.data() + 4, frame.size() - 4, frame.timeStamp);
}
}
inline void RtmpToRtspMediaSource::onGetAdts(const AACFrame &frame) {
inline void RtmpToRtspMediaSource::onGetAAC(const AACFrame &frame) {
if(m_pRecorder){
m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp);
}

View File

@ -69,7 +69,7 @@ public:
m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser,m_bEnableHls,m_bEnableMp4));
//todo(xzl) 修复此处
// m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAdts, this, placeholders::_1));
// m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
// m_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
} catch (exception &ex) {
WarnL << ex.what();
@ -96,7 +96,7 @@ private:
bool m_bEnableHls;
bool m_bEnableMp4;
void onGetH264(const H264Frame &frame);
void onGetAdts(const AACFrame &frame);
void onGetAAC(const AACFrame &frame);
void makeSDP();
};

View File

@ -0,0 +1,122 @@
//
// Created by xzl on 2018/10/24.
//
#include <Player/Player.h>
#include "AACRtmpCodec.h"
namespace ZL{
namespace Rtmp {
AACRtmpDecoder::AACRtmpDecoder() {
_adts = obtainFrame();
}
AACFrame::Ptr AACRtmpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
frame->aac_frame_length = 7;
frame->iPrefixSize = 7;
return frame;
}
bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool key_pos) {
RtmpCodec::inputRtmp(pkt, false);
if (pkt->isCfgFrame()) {
_aac_cfg = pkt->getAacCfg();
return false;
}
if (!_aac_cfg.empty()) {
onGetAAC(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp);
}
return false;
}
void AACRtmpDecoder::onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
if(iLen + 7 > sizeof(_adts->buffer)){
WarnL << "Illegal adts data, exceeding the length limit.";
return;
}
//写adts结构头
makeAdtsHeader(_aac_cfg,*_adts);
//拷贝aac负载
memcpy(_adts->buffer + 7, pcData, iLen);
_adts->aac_frame_length = 7 + iLen;
_adts->timeStamp = ui32TimeStamp;
//adts结构头转成头7个字节
writeAdtsHeader(*_adts, _adts->buffer);
//写入环形缓存
RtmpCodec::inputFrame(_adts);
_adts = obtainFrame();
}
/////////////////////////////////////////////////////////////////////////////////////
void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
RtmpCodec::inputFrame(frame);
if(frame->prefixSize() == 7 && _aac_cfg.empty()){
//包含adts头
_aac_cfg = makeAdtsConfig(reinterpret_cast<const uint8_t *>(frame->data()));
makeAudioConfigPkt();
}
}
void AACRtmpEncoder::makeAudioConfigPkt() {
makeAdtsHeader(_aac_cfg,*_adts);
int iSampleRate , iChannel , iSampleBit = 16;
getAACInfo(*_adts,iSampleRate,iChannel);
uint8_t flvStereoOrMono = (iChannel > 1);
uint8_t flvSampleRate;
switch (iSampleRate) {
case 48000:
case 44100:
flvSampleRate = 3;
break;
case 24000:
case 22050:
flvSampleRate = 2;
break;
case 12000:
case 11025:
flvSampleRate = 1;
break;
default:
flvSampleRate = 0;
break;
}
uint8_t flvSampleBit = iSampleBit == 16;
uint8_t flvAudioType = 10; //aac
uint8_t m_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
//////////header
uint8_t is_config = true;
rtmpPkt->strBuf.push_back(m_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append(_aac_cfg);
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_AUDIO;
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = 0;
rtmpPkt->typeId = MSG_AUDIO;
inputRtmp(rtmpPkt, true);
}
}//namespace Rtmp
}//namespace ZL

View File

@ -0,0 +1,69 @@
//
// Created by xzl on 2018/10/24.
//
#ifndef ZLMEDIAKIT_AACRTMPCODEC_H
#define ZLMEDIAKIT_AACRTMPCODEC_H
#include "RtmpCodec.h"
namespace ZL{
namespace Rtmp {
/**
* aac Rtmp转adts类
*/
class AACRtmpDecoder : public RtmpCodec , public ResourcePoolHelper<AACFrame> {
public:
typedef std::shared_ptr<AACRtmpDecoder> Ptr;
AACRtmpDecoder();
~AACRtmpDecoder() {}
/**
* Rtmp并解码
* @param Rtmp Rtmp数据包
* @param key_pos false,
*/
bool inputRtmp(const RtmpPacket::Ptr &Rtmp, bool key_pos = false) override;
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return CodecAAC;
}
protected:
void onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp);
AACFrame::Ptr obtainFrame();
protected:
AACFrame::Ptr _adts;
string _aac_cfg;
};
/**
* aac adts转Rtmp类
*/
class AACRtmpEncoder : public AACRtmpDecoder , public ResourcePoolHelper<RtmpPacket> {
public:
typedef std::shared_ptr<AACRtmpEncoder> Ptr;
AACRtmpEncoder();
~AACRtmpEncoder() {}
/**
* aac dats头
* @param frame dats头的aac数据
*/
void inputFrame(const Frame::Ptr &frame) override;
private:
void makeAudioConfigPkt();
};
}//namespace Rtmp
}//namespace ZL
#endif //ZLMEDIAKIT_AACRTMPCODEC_H

View File

@ -26,12 +26,12 @@ bool H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) {
bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
if (pkt->isCfgFrame()) {
//缓存sps pps后续插入到I帧之前
m_strSPS = pkt->getH264SPS();
m_strPPS = pkt->getH264PPS();
m_sps = pkt->getH264SPS();
m_pps = pkt->getH264PPS();
return false;
}
if (m_strSPS.size()) {
if (m_sps.size()) {
uint32_t iTotalLen = pkt->strBuf.size();
uint32_t iOffset = 5;
while(iOffset + 4 < iTotalLen){
@ -54,8 +54,8 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t
switch (pcData[0] & 0x1F) {
case 5: {
//I frame
onGetH264(m_strSPS.data(), m_strSPS.length(), ui32TimeStamp);
onGetH264(m_strPPS.data(), m_strPPS.length(), ui32TimeStamp);
onGetH264(m_sps.data(), m_sps.length(), ui32TimeStamp);
onGetH264(m_pps.data(), m_pps.length(), ui32TimeStamp);
}
case 1: {
//I or P or B frame

View File

@ -34,15 +34,15 @@ public:
CodecId getCodecId() const override{
return CodecH264;
}
private:
protected:
bool decodeRtmp(const RtmpPacket::Ptr &Rtmp);
void onGetH264_l(const char *pcData, int iLen, uint32_t ui32TimeStamp);
void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
H264Frame::Ptr obtainFrame();
private:
protected:
H264Frame::Ptr m_h264frame;
string m_strSPS;
string m_strPPS;
string m_sps;
string m_pps;
};
/**
@ -62,9 +62,6 @@ public:
void inputFrame(const Frame::Ptr &frame) override;
private:
void makeVideoConfigPkt();
private:
string m_sps;
string m_pps;
};
#endif //ZLMEDIAKIT_H264RTMPCODEC_H

View File

@ -126,7 +126,7 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
rtmpPkt->typeId = MSG_VIDEO;
m_pRtmpSrc->onGetMedia(rtmpPkt);
}
void RtspToRtmpMediaSource::onGetAdts(const AACFrame& frame) {
void RtspToRtmpMediaSource::onGetAAC(const AACFrame& frame) {
if(m_pRecorder){
m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp);
}

View File

@ -55,7 +55,7 @@ public:
m_pParser.reset(new RtpParser(strSdp));
m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser,m_bEnableHls,m_bEnableMp4));
//todo(xzl) 修复此处
// m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAdts, this, placeholders::_1));
// m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
// m_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
makeMetaData();
} catch (exception &ex) {
@ -94,7 +94,7 @@ public:
protected:
void onGetH264(const H264Frame &frame);
void onGetAdts(const AACFrame &frame);
void onGetAAC(const AACFrame &frame);
private:
void makeVideoConfigPkt();
void makeAudioConfigPkt();