G711支持多种规格

This commit is contained in:
xiongziliang
2020-04-18 22:13:11 +08:00
parent 5c3418a412
commit bacf8f100b
17 changed files with 203 additions and 197 deletions

View File

@@ -36,11 +36,68 @@ AudioMeta::AudioMeta(const AudioTrack::Ptr &audio,int datarate){
_metadata.set("audiosamplesize", audio->getAudioSampleBit());
}
if(audio->getAudioChannel() > 0){
_metadata.set("audiochannels", audio->getAudioChannel());
_metadata.set("stereo", audio->getAudioChannel() > 1);
}
_codecId = audio->getCodecId();
_metadata.set("audiocodecid", Factory::getAmfByCodecId(_codecId));
}
uint8_t getAudioRtmpFlags(const Track::Ptr &track){
switch (track->getTrackType()){
case TrackAudio : {
auto audioTrack = dynamic_pointer_cast<AudioTrack>(track);
if (!audioTrack) {
WarnL << "获取AudioTrack失败";
return 0;
}
auto iSampleRate = audioTrack->getAudioSampleRate();
auto iChannel = audioTrack->getAudioChannel();
auto iSampleBit = audioTrack->getAudioSampleBit();
uint8_t flvAudioType ;
switch (track->getCodecId()){
case CodecG711A : flvAudioType = FLV_CODEC_G711A; break;
case CodecG711U : flvAudioType = FLV_CODEC_G711U; break;
case CodecAAC : {
flvAudioType = FLV_CODEC_AAC;
//aac不通过flags获取音频相关信息
iSampleRate = 44100;
iSampleBit = 16;
iChannel = 2;
break;
}
default: WarnL << "该编码格式不支持转换为RTMP: " << track->getCodecName(); return 0;
}
uint8_t flvSampleRate;
switch (iSampleRate) {
case 44100:
flvSampleRate = 3;
break;
case 22050:
flvSampleRate = 2;
break;
case 11025:
flvSampleRate = 1;
break;
case 16000: // nellymoser only
case 8000: // nellymoser only
case 5512: // not MP3
flvSampleRate = 0;
break;
default:
WarnL << "FLV does not support sample rate " << iSampleRate << " ,choose from (44100, 22050, 11025)";
return 0;
}
uint8_t flvStereoOrMono = (iChannel > 1);
uint8_t flvSampleBit = iSampleBit == 16;
return (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
}
default : return 0;
}
}
}//namespace mediakit

View File

@@ -161,27 +161,26 @@ public:
strBuf = std::move(that.strBuf);
}
bool isVideoKeyFrame() const {
return typeId == MSG_VIDEO && (uint8_t) strBuf[0] >> 4 == FLV_KEY_FRAME
&& (uint8_t) strBuf[1] == 1;
return typeId == MSG_VIDEO && (uint8_t) strBuf[0] >> 4 == FLV_KEY_FRAME && (uint8_t) strBuf[1] == 1;
}
bool isCfgFrame() const {
return (typeId == MSG_VIDEO || typeId == MSG_AUDIO)
&& (uint8_t) strBuf[1] == 0;
switch (typeId){
case MSG_VIDEO : return strBuf[1] == 0;
case MSG_AUDIO : {
switch (getMediaType()){
case FLV_CODEC_AAC : return strBuf[1] == 0;
default : return false;
}
}
default : return false;
}
}
int getMediaType() const {
switch (typeId) {
case MSG_VIDEO: {
return (uint8_t) strBuf[0] & 0x0F;
}
break;
case MSG_AUDIO: {
return (uint8_t) strBuf[0] >> 4;
}
break;
default:
break;
case MSG_VIDEO : return (uint8_t) strBuf[0] & 0x0F;
case MSG_AUDIO : return (uint8_t) strBuf[0] >> 4;
default : return 0;
}
return 0;
}
int getAudioSampleRate() const {
if (typeId != MSG_AUDIO) {
@@ -314,6 +313,8 @@ private:
CodecId _codecId;
};
//根据音频track获取flags
uint8_t getAudioRtmpFlags(const Track::Ptr &track);
}//namespace mediakit

View File

@@ -15,14 +15,55 @@ namespace mediakit {
void RtmpDemuxer::loadMetaData(const AMFValue &val){
try {
makeVideoTrack(val["videocodecid"]);
makeAudioTrack(val["audiocodecid"]);
int audiosamplerate = 0;
int audiochannels = 0;
int audiosamplesize = 0;
const AMFValue *audiocodecid = nullptr;
const AMFValue *videocodecid = nullptr;
val.object_for_each([&](const string &key, const AMFValue &val) {
if (key == "duration") {
_fDuration = val.as_number();
return;
}
if(key == "audiosamplerate"){
audiosamplerate = val.as_integer();
return;
}
if(key == "audiosamplesize"){
audiosamplesize = val.as_integer();
return;
}
if(key == "stereo"){
audiochannels = val.as_boolean() ? 2 : 1;
return;
}
if(key == "videocodecid"){
//找到视频
videocodecid = &val;
return;
}
if(key == "audiocodecid"){
//找到音频
audiocodecid = &val;
return;
}
});
if(videocodecid){
//有视频
makeVideoTrack(*videocodecid);
}
if(audiocodecid){
//有音频
makeAudioTrack(*audiocodecid, audiosamplerate, audiochannels, audiosamplesize);
}
}catch (std::exception &ex){
WarnL << ex.what();
}
@@ -46,7 +87,7 @@ bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
if(!_tryedGetAudioTrack) {
_tryedGetAudioTrack = true;
auto codec = AMFValue(pkt->getMediaType());
makeAudioTrack(codec);
makeAudioTrack(codec, pkt->getAudioSampleRate(), pkt->getAudioChannel(), pkt->getAudioSampleBit());
}
if(_audioRtmpDecoder){
_audioRtmpDecoder->inputRtmp(pkt, false);
@@ -69,6 +110,7 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
//设置rtmp解码器代理生成的frame写入该Track
_videoRtmpDecoder->addDelegate(_videoTrack);
onAddTrack(_videoTrack);
_tryedGetVideoTrack = true;
} else {
//找不到相应的rtmp解码器该track无效
_videoTrack.reset();
@@ -76,9 +118,9 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
}
}
void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec) {
void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int channels, int sample_bit) {
//生成Track对象
_audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec));
_audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit));
if (_audioTrack) {
//生成rtmpCodec对象以便解码rtmp
_audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack);
@@ -86,6 +128,7 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec) {
//设置rtmp解码器代理生成的frame写入该Track
_audioRtmpDecoder->addDelegate(_audioTrack);
onAddTrack(_audioTrack);
_tryedGetAudioTrack = true;
} else {
//找不到相应的rtmp解码器该track无效
_audioTrack.reset();

View File

@@ -40,7 +40,7 @@ public:
bool inputRtmp(const RtmpPacket::Ptr &pkt);
private:
void makeVideoTrack(const AMFValue &val);
void makeAudioTrack(const AMFValue &val);
void makeAudioTrack(const AMFValue &val, int sample_rate, int channels, int sample_bit);
private:
bool _tryedGetVideoTrack = false;
bool _tryedGetAudioTrack = false;

View File

@@ -193,7 +193,6 @@ void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) {
throw std::runtime_error(StrPrinter << "Stop publishing" << endl);
}
void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr &src){
bool authSuccess = err.empty();
bool ok = (src.operator bool() && authSuccess);