添加对g711A/U rtsp支持相关文件,api添加windows静态库编译选项,g711 RTMP支持尚未修改

This commit is contained in:
baiyfcu
2020-04-08 15:42:52 +08:00
parent fb77293648
commit 340629cdc6
15 changed files with 761 additions and 40 deletions

View File

@@ -13,8 +13,10 @@
#include "H264Rtmp.h"
#include "H265Rtmp.h"
#include "AACRtmp.h"
#include "G711Rtmp.h"
#include "H264Rtp.h"
#include "AACRtp.h"
#include "G711Rtp.h"
#include "H265Rtp.h"
#include "Common/Parser.h"
@@ -45,6 +47,14 @@ Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
return std::make_shared<AACTrack>(aac_cfg);
}
if (strcasecmp(track->_codec.data(), "PCMA") == 0) {
return std::make_shared<G711Track>(CodecG711A);
}
if (strcasecmp(track->_codec.data(), "PCMU") == 0) {
return std::make_shared<G711Track>(CodecG711U);
}
if (strcasecmp(track->_codec.data(), "h264") == 0) {
//a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA==
auto map = Parser::parseArgs(FindField(track->_fmtp.data()," ", nullptr),";","=");
@@ -90,6 +100,12 @@ Track::Ptr Factory::getTrackByCodecId(CodecId codecId) {
case CodecAAC:{
return std::make_shared<AACTrack>();
}
case CodecG711A: {
return std::make_shared<G711Track>(CodecG711A);
}
case CodecG711U: {
return std::make_shared<G711Track>(CodecG711U);
}
default:
WarnL << "暂不支持该CodecId:" << codecId;
return nullptr;
@@ -125,6 +141,9 @@ RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
return std::make_shared<H265RtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
case CodecAAC:
return std::make_shared<AACRtpEncoder>(ssrc,mtu,sample_rate,pt,interleaved);
case CodecG711A:
case CodecG711U:
return std::make_shared<G711RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
default:
WarnL << "暂不支持该CodecId:" << codec_id;
return nullptr;
@@ -139,6 +158,9 @@ RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
return std::make_shared<H265RtpDecoder>();
case CodecAAC:
return std::make_shared<AACRtpDecoder>(track->clone());
case CodecG711A:
case CodecG711U:
return std::make_shared<G711RtpDecoder>(track->clone());
default:
WarnL << "暂不支持该CodecId:" << track->getCodecName();
return nullptr;
@@ -198,6 +220,9 @@ RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) {
return std::make_shared<AACRtmpEncoder>(track);
case CodecH265:
return std::make_shared<H265RtmpEncoder>(track);
case CodecG711A:
case CodecG711U:
return std::make_shared<G711RtmpEncoder>(track);
default:
WarnL << "暂不支持该CodecId:" << track->getCodecName();
return nullptr;
@@ -209,6 +234,8 @@ AMFValue Factory::getAmfByCodecId(CodecId codecId) {
case CodecAAC: return AMFValue("mp4a");
case CodecH264: return AMFValue("avc1");
case CodecH265: return AMFValue(FLV_CODEC_H265);
case CodecG711A: return AMFValue(7);
case CodecG711U: return AMFValue(8);
default: return AMFValue(AMF_NULL);
}
}

View File

@@ -26,6 +26,8 @@ typedef enum {
CodecH264 = 0,
CodecH265,
CodecAAC,
CodecG711A,
CodecG711U,
CodecMax = 0x7FFF
} CodecId;

26
src/Extension/G711.cpp Normal file
View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include "G711.h"
namespace mediakit{
Sdp::Ptr G711Track::getSdp() {
if(!ready()){
WarnL << "AAC Track未准备好";
return nullptr;
}
return std::make_shared<G711Sdp>(getCodecId(), getAudioSampleRate(), getCodecId() == CodecG711A ? 8 : 0, getAudioSampleBit());
}
}//namespace mediakit

248
src/Extension/G711.h Normal file
View File

@@ -0,0 +1,248 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_G711_H
#define ZLMEDIAKIT_G711_H
#include "Frame.h"
#include "Track.h"
namespace mediakit{
class G711Frame;
unsigned const samplingFrequencyTableG711[16] = { 96000, 88200,
64000, 48000,
44100, 32000,
24000, 22050,
16000, 12000,
11025, 8000,
7350, 0, 0, 0 };
void makeAdtsHeader(const string &strAudioCfg,G711Frame &adts);
void writeAdtsHeader(const G711Frame &adts, uint8_t *pcAdts) ;
string makeG711AdtsConfig(const uint8_t *pcAdts);
void getAACInfo(const G711Frame &adts,int &iSampleRate,int &iChannel);
/**
* aac帧包含adts头
*/
class G711Frame : public Frame {
public:
typedef std::shared_ptr<G711Frame> Ptr;
char *data() const override{
return (char *)buffer;
}
uint32_t size() const override {
return frameLength;
}
uint32_t dts() const override {
return timeStamp;
}
uint32_t prefixSize() const override{
return iPrefixSize;
}
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return CodecAAC;
}
bool keyFrame() const override {
return false;
}
bool configFrame() const override{
return false;
}
public:
unsigned int frameLength; // 一个帧的长度包括 raw data block
unsigned char buffer[2 * 1024 + 7];
uint32_t timeStamp;
uint32_t iPrefixSize = 0;
} ;
class G711FrameNoCacheAble : public FrameNoCacheAble {
public:
typedef std::shared_ptr<G711FrameNoCacheAble> Ptr;
G711FrameNoCacheAble(CodecId codecId, char *ptr,uint32_t size,uint32_t dts,int prefixeSize = 7){
_codecId = codecId;
_ptr = ptr;
_size = size;
_dts = dts;
_prefixSize = prefixeSize;
}
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return _codecId;
}
bool keyFrame() const override {
return false;
}
bool configFrame() const override{
return false;
}
private:
CodecId _codecId;
} ;
/**
* g711音频通道
*/
class G711Track : public AudioTrack{
public:
typedef std::shared_ptr<G711Track> Ptr;
/**
* 延后获取adts头信息
* 在随后的inputFrame中获取adts头信息
*/
G711Track(){}
/**
* G711A G711U
*/
G711Track(CodecId codecId, int sampleBit = 16, int sampleRate = 8000){
_codecid = codecId;
_sampleBit = sampleBit;
_sampleRate = sampleRate;
onReady();
}
/**
* 返回编码类型
* @return
*/
CodecId getCodecId() const override{
return _codecid;
}
/**
* 在获取aac_cfg前是无效的Track
* @return
*/
bool ready() override {
return true;
}
/**
* 返回音频采样率
* @return
*/
int getAudioSampleRate() const override{
return _sampleRate;
}
/**
* 返回音频采样位数一般为16或8
* @return
*/
int getAudioSampleBit() const override{
return _sampleBit;
}
/**
* 返回音频通道数
* @return
*/
int getAudioChannel() const override{
return _channel;
}
/**
* 输入数据帧,并获取aac_cfg
* @param frame 数据帧
*/
void inputFrame(const Frame::Ptr &frame) override{
AudioTrack::inputFrame(frame);
}
private:
/**
*
*/
void onReady(){
/*
if(_cfg.size() < 2){
return;
}
G711Frame aacFrame;
makeAdtsHeader(_cfg,aacFrame);
getAACInfo(aacFrame,_sampleRate,_channel);*/
}
Track::Ptr clone() override {
return std::make_shared<std::remove_reference<decltype(*this)>::type >(*this);
}
//生成sdp
Sdp::Ptr getSdp() override ;
private:
string _cfg;
CodecId _codecid = CodecG711A;
int _sampleRate = 8000;
int _sampleBit = 16;
int _channel = 1;
};
/**
* aac类型SDP
*/
class G711Sdp : public Sdp {
public:
/**
*
* @param aac_codecId G711A G711U
* @param sample_rate 音频采样率
* @param playload_type rtp playload type 默认0为G711U 8为G711A
* @param bitrate 比特率
*/
G711Sdp(CodecId codecId,
int sample_rate,
int playload_type = 0,
int bitrate = 128) : Sdp(sample_rate,playload_type), _codecId(codecId){
_printer << "m=audio 0 RTP/AVP " << playload_type << "\r\n";
//_printer << "b=AS:" << bitrate << "\r\n";
_printer << "a=rtpmap:" << playload_type << (codecId == CodecG711A ? " PCMA/" : " PCMU/") << sample_rate << "\r\n";
_printer << "a=control:trackID=" << getTrackType() << "\r\n";
}
string getSdp() const override {
return _printer;
}
TrackType getTrackType() const override {
return TrackAudio;
}
CodecId getCodecId() const override {
return _codecId;
}
private:
_StrPrinter _printer;
CodecId _codecId = CodecG711A;
};
}//namespace mediakit
#endif //ZLMEDIAKIT_AAC_H

View File

@@ -0,0 +1,68 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include "G711Rtmp.h"
namespace mediakit{
G711RtmpDecoder::G711RtmpDecoder() {
_adts = obtainFrame();
}
G711Frame::Ptr G711RtmpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<G711Frame>::obtainObj();
frame->frameLength = 0;
frame->iPrefixSize = 0;
return frame;
}
bool G711RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool key_pos) {
onGetG711(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp);
return false;
}
void G711RtmpDecoder::onGetG711(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
if(iLen + 7 > sizeof(_adts->buffer)){
WarnL << "Illegal adts data, exceeding the length limit.";
return;
}
//拷贝aac负载
memcpy(_adts->buffer, pcData, iLen);
_adts->frameLength = iLen;
_adts->timeStamp = ui32TimeStamp;
//写入环形缓存
RtmpCodec::inputFrame(_adts);
_adts = obtainFrame();
}
/////////////////////////////////////////////////////////////////////////////////////
G711RtmpEncoder::G711RtmpEncoder(const Track::Ptr &track) {
_track = dynamic_pointer_cast<G711Track>(track);
}
void G711RtmpEncoder::inputFrame(const Frame::Ptr& frame) {
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
rtmpPkt->strBuf.clear();
rtmpPkt->strBuf.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_AUDIO;
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = frame->dts();
rtmpPkt->typeId = MSG_AUDIO;
RtmpCodec::inputRtmp(rtmpPkt, false);
}
}//namespace mediakit

86
src/Extension/G711Rtmp.h Normal file
View File

@@ -0,0 +1,86 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_G711RTMPCODEC_H
#define ZLMEDIAKIT_G711RTMPCODEC_H
#include "Rtmp/RtmpCodec.h"
#include "Extension/Track.h"
#include "Extension/G711.h"
namespace mediakit{
/**
* G711 Rtmp转adts类
*/
class G711RtmpDecoder : public RtmpCodec , public ResourcePoolHelper<G711Frame> {
public:
typedef std::shared_ptr<G711RtmpDecoder> Ptr;
G711RtmpDecoder();
~G711RtmpDecoder() {}
/**
* 输入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;
}
void setCodecId(CodecId codecId)
{
_codecid = codecId;
}
CodecId getCodecId() const override{
return _codecid;
}
protected:
void onGetG711(const char* pcData, int iLen, uint32_t ui32TimeStamp);
G711Frame::Ptr obtainFrame();
protected:
G711Frame::Ptr _adts;
CodecId _codecid = CodecG711A;
};
/**
* aac adts转Rtmp类
*/
class G711RtmpEncoder : public G711RtmpDecoder , public ResourcePoolHelper<RtmpPacket> {
public:
typedef std::shared_ptr<G711RtmpEncoder> Ptr;
/**
* 构造函数track可以为空此时则在inputFrame时输入adts头
* 如果track不为空且包含adts头相关信息
* 那么inputFrame时可以不输入adts头
* @param track
*/
G711RtmpEncoder(const Track::Ptr &track);
~G711RtmpEncoder() {}
/**
* 输入aac 数据可以不带adts头
* @param frame aac数据
*/
void inputFrame(const Frame::Ptr &frame) override;
private:
G711Track::Ptr _track;
};
}//namespace mediakit
#endif //ZLMEDIAKIT_G711RTMPCODEC_H

101
src/Extension/G711Rtp.cpp Normal file
View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#include "G711Rtp.h"
namespace mediakit{
G711RtpEncoder::G711RtpEncoder(uint32_t ui32Ssrc,
uint32_t ui32MtuSize,
uint32_t ui32SampleRate,
uint8_t ui8PlayloadType,
uint8_t ui8Interleaved) :
RtpInfo(ui32Ssrc,
ui32MtuSize,
ui32SampleRate,
ui8PlayloadType,
ui8Interleaved){
}
void G711RtpEncoder::inputFrame(const Frame::Ptr &frame) {
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
auto uiStamp = frame->dts();
auto pcData = frame->data() + frame->prefixSize();
auto iLen = frame->size() - frame->prefixSize();
uiStamp %= cycleMS;
char *ptr = (char *) pcData;
int iSize = iLen;
while (iSize > 0) {
if (iSize <= _ui32MtuSize - 20) {
makeG711Rtp(ptr, iSize, true, uiStamp);
break;
}
makeG711Rtp(ptr, _ui32MtuSize - 20, false, uiStamp);
ptr += (_ui32MtuSize - 20);
iSize -= (_ui32MtuSize - 20);
}
}
void G711RtpEncoder::makeG711Rtp(const void *data, unsigned int len, bool mark, uint32_t uiStamp) {
RtpCodec::inputRtp(makeRtp(getTrackType(),data,len,mark,uiStamp), false);
}
/////////////////////////////////////////////////////////////////////////////////////
G711RtpDecoder::G711RtpDecoder(const Track::Ptr &track){
auto aacTrack = dynamic_pointer_cast<G711Track>(track);
_codecid = aacTrack->getCodecId();
if(!aacTrack || !aacTrack->ready()){
WarnL << "该g711 track无效!";
}else{
//_aac_cfg = aacTrack->getAacCfg();
}
_adts = obtainFrame();
}
G711RtpDecoder::G711RtpDecoder() {
_adts = obtainFrame();
}
G711Frame::Ptr G711RtpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<G711Frame>::obtainObj();
frame->frameLength = 0;
frame->iPrefixSize = 0;
return frame;
}
bool G711RtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
// 获取rtp数据长度
int length = rtppack->size() - rtppack->offset;
// 获取rtp数据
const uint8_t *rtp_packet_buf = (uint8_t *)rtppack->data() + rtppack->offset;
_adts->frameLength = length;
memcpy(_adts->buffer, rtp_packet_buf, length);
if (rtppack->mark == true) {
_adts->timeStamp = rtppack->timeStamp;
onGetG711(_adts);
}
return false;
}
void G711RtpDecoder::onGetG711(const G711Frame::Ptr &frame) {
//写入环形缓存
RtpCodec::inputFrame(frame);
_adts = obtainFrame();
}
}//namespace mediakit

84
src/Extension/G711Rtp.h Normal file
View File

@@ -0,0 +1,84 @@
/*
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
*
* This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
*
* Use of this source code is governed by MIT license that can be found in the
* LICENSE file in the root of the source tree. All contributing project authors
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ZLMEDIAKIT_G711RTPCODEC_H
#define ZLMEDIAKIT_G711RTPCODEC_H
#include "Rtsp/RtpCodec.h"
#include "Extension/G711.h"
namespace mediakit{
/**
* G711 rtp转adts类
*/
class G711RtpDecoder : public RtpCodec , public ResourcePoolHelper<G711Frame> {
public:
typedef std::shared_ptr<G711RtpDecoder> Ptr;
G711RtpDecoder(const Track::Ptr &track);
~G711RtpDecoder() {}
/**
* 输入rtp并解码
* @param rtp rtp数据包
* @param key_pos 此参数内部强制转换为false,请忽略之
*/
bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override;
TrackType getTrackType() const override{
return TrackAudio;
}
CodecId getCodecId() const override{
return _codecid;
}
protected:
G711RtpDecoder();
private:
void onGetG711(const G711Frame::Ptr &frame);
G711Frame::Ptr obtainFrame();
private:
G711Frame::Ptr _adts;
CodecId _codecid = CodecG711A;
};
/**
* g711 转rtp类
*/
class G711RtpEncoder : public G711RtpDecoder , public RtpInfo {
public:
typedef std::shared_ptr<G711RtpEncoder> Ptr;
/**
* @param ui32Ssrc ssrc
* @param ui32MtuSize mtu 大小
* @param ui32SampleRate 采样率
* @param ui8PlayloadType pt类型
* @param ui8Interleaved rtsp interleaved 值
*/
G711RtpEncoder(uint32_t ui32Ssrc,
uint32_t ui32MtuSize,
uint32_t ui32SampleRate,
uint8_t ui8PlayloadType = 0,
uint8_t ui8Interleaved = TrackAudio * 2);
~G711RtpEncoder() {}
/**
* @param frame g711数据
*/
void inputFrame(const Frame::Ptr &frame) override;
private:
void makeG711Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
private:
unsigned char _aucSectionBuf[1600];
};
}//namespace mediakit
#endif //ZLMEDIAKIT_G711RTPCODEC_H