完善对无metadata的rtmp流的兼容性

This commit is contained in:
xiongziliang 2020-05-28 17:03:12 +08:00
parent e7f263b046
commit 41509800bc
10 changed files with 88 additions and 87 deletions

View File

@ -221,13 +221,27 @@ Track::Ptr Factory::getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int
return getTrackByCodecId(codecId, sample_rate, channels, sample_bit); return getTrackByCodecId(codecId, sample_rate, channels, sample_bit);
} }
RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) { RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode) {
switch (track->getCodecId()){ switch (track->getCodecId()){
case CodecH264 : return std::make_shared<H264RtmpEncoder>(track); case CodecH264 : return std::make_shared<H264RtmpEncoder>(track);
case CodecAAC : return std::make_shared<AACRtmpEncoder>(track); case CodecAAC : return std::make_shared<AACRtmpEncoder>(track);
case CodecH265 : return std::make_shared<H265RtmpEncoder>(track); case CodecH265 : return std::make_shared<H265RtmpEncoder>(track);
case CodecG711A : case CodecG711A :
case CodecG711U : return std::make_shared<G711RtmpEncoder>(track); case CodecG711U : {
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
if (is_encode && (audio_track->getAudioSampleRate() != 8000 ||
audio_track->getAudioChannel() != 1 ||
audio_track->getAudioSampleBit() != 16)) {
//rtmp对g711只支持8000/1/16规格但是ZLMediaKit可以解析其他规格的G711
WarnL << "RTMP只支持8000/1/16规格的G711,目前规格是:"
<< audio_track->getAudioSampleRate() << "/"
<< audio_track->getAudioChannel() << "/"
<< audio_track->getAudioSampleBit()
<< ",该音频已被忽略";
return nullptr;
}
return std::make_shared<G711RtmpEncoder>(track);
}
default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr; default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
} }
} }

View File

@ -59,8 +59,9 @@ public:
/** /**
* Track获取Rtmp的编解码器 * Track获取Rtmp的编解码器
* @param track * @param track
* @param is_encode
*/ */
static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track); static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track, bool is_encode);
/** /**
* codecId获取rtmp的codec描述 * codecId获取rtmp的codec描述

View File

@ -100,4 +100,23 @@ uint8_t getAudioRtmpFlags(const Track::Ptr &track){
} }
void Metadata::addTrack(AMFValue &metadata, const Track::Ptr &track) {
Metadata::Ptr new_metadata;
switch (track->getTrackType()) {
case TrackVideo: {
new_metadata = std::make_shared<VideoMeta>(dynamic_pointer_cast<VideoTrack>(track));
}
break;
case TrackAudio: {
new_metadata = std::make_shared<AudioMeta>(dynamic_pointer_cast<AudioTrack>(track));
}
break;
default:
return;
}
new_metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value) {
metadata.set(key, value);
});
}
}//namespace mediakit }//namespace mediakit

View File

@ -220,6 +220,8 @@ public:
const AMFValue &getMetadata() const{ const AMFValue &getMetadata() const{
return _metadata; return _metadata;
} }
static void addTrack(AMFValue &metadata, const Track::Ptr &track);
protected: protected:
AMFValue _metadata; AMFValue _metadata;
}; };
@ -261,7 +263,6 @@ private:
CodecId _codecId; CodecId _codecId;
}; };
class AudioMeta : public Metadata{ class AudioMeta : public Metadata{
public: public:
typedef std::shared_ptr<AudioMeta> Ptr; typedef std::shared_ptr<AudioMeta> Ptr;

View File

@ -13,60 +13,56 @@
namespace mediakit { namespace mediakit {
void RtmpDemuxer::loadMetaData(const AMFValue &val){ bool RtmpDemuxer::loadMetaData(const AMFValue &val){
bool ret = false;
try { try {
int audiosamplerate = 0; int audiosamplerate = 0;
int audiochannels = 0; int audiochannels = 0;
int audiosamplesize = 0; int audiosamplesize = 0;
const AMFValue *audiocodecid = nullptr; const AMFValue *audiocodecid = nullptr;
const AMFValue *videocodecid = nullptr; const AMFValue *videocodecid = nullptr;
val.object_for_each([&](const string &key, const AMFValue &val) { val.object_for_each([&](const string &key, const AMFValue &val) {
if (key == "duration") { if (key == "duration") {
_fDuration = val.as_number(); _fDuration = val.as_number();
return; return;
} }
if (key == "audiosamplerate") {
if(key == "audiosamplerate"){
audiosamplerate = val.as_integer(); audiosamplerate = val.as_integer();
return; return;
} }
if (key == "audiosamplesize") {
if(key == "audiosamplesize"){
audiosamplesize = val.as_integer(); audiosamplesize = val.as_integer();
return; return;
} }
if (key == "stereo") {
if(key == "stereo"){
audiochannels = val.as_boolean() ? 2 : 1; audiochannels = val.as_boolean() ? 2 : 1;
return; return;
} }
if (key == "videocodecid") {
if(key == "videocodecid"){
//找到视频 //找到视频
videocodecid = &val; videocodecid = &val;
return; return;
} }
if (key == "audiocodecid") {
if(key == "audiocodecid"){
//找到音频 //找到音频
audiocodecid = &val; audiocodecid = &val;
return; return;
} }
}); });
if (videocodecid) {
if(videocodecid){
//有视频 //有视频
ret = true;
makeVideoTrack(*videocodecid); makeVideoTrack(*videocodecid);
} }
if (audiocodecid) {
if(audiocodecid){
//有音频 //有音频
ret = true;
makeAudioTrack(*audiocodecid, audiosamplerate, audiochannels, audiosamplesize); makeAudioTrack(*audiocodecid, audiosamplerate, audiochannels, audiosamplesize);
} }
}catch (std::exception &ex){ } catch (std::exception &ex) {
WarnL << ex.what(); WarnL << ex.what();
} }
return ret;
} }
bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) { bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) {
@ -105,7 +101,7 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
_videoTrack = dynamic_pointer_cast<VideoTrack>(Factory::getVideoTrackByAmf(videoCodec)); _videoTrack = dynamic_pointer_cast<VideoTrack>(Factory::getVideoTrackByAmf(videoCodec));
if (_videoTrack) { if (_videoTrack) {
//生成rtmpCodec对象以便解码rtmp //生成rtmpCodec对象以便解码rtmp
_videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack); _videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack, false);
if (_videoRtmpDecoder) { if (_videoRtmpDecoder) {
//设置rtmp解码器代理生成的frame写入该Track //设置rtmp解码器代理生成的frame写入该Track
_videoRtmpDecoder->addDelegate(_videoTrack); _videoRtmpDecoder->addDelegate(_videoTrack);
@ -123,7 +119,7 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int
_audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit)); _audioTrack = dynamic_pointer_cast<AudioTrack>(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit));
if (_audioTrack) { if (_audioTrack) {
//生成rtmpCodec对象以便解码rtmp //生成rtmpCodec对象以便解码rtmp
_audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack); _audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack, false);
if (_audioRtmpDecoder) { if (_audioRtmpDecoder) {
//设置rtmp解码器代理生成的frame写入该Track //设置rtmp解码器代理生成的frame写入该Track
_audioRtmpDecoder->addDelegate(_audioTrack); _audioRtmpDecoder->addDelegate(_audioTrack);

View File

@ -30,7 +30,7 @@ public:
RtmpDemuxer() = default; RtmpDemuxer() = default;
virtual ~RtmpDemuxer() = default; virtual ~RtmpDemuxer() = default;
void loadMetaData(const AMFValue &metadata); bool loadMetaData(const AMFValue &metadata);
/** /**
* *

View File

@ -49,9 +49,14 @@ public:
* metadata * metadata
*/ */
void setMetaData(const AMFValue &metadata) override{ void setMetaData(const AMFValue &metadata) override{
_demuxer->loadMetaData(metadata); if(!_demuxer->loadMetaData(metadata)){
//该metadata无效需要重新生成
_metadata = metadata;
_recreate_metadata = true;
}else{
RtmpMediaSource::setMetaData(metadata); RtmpMediaSource::setMetaData(metadata);
} }
}
/** /**
* rtmp并解析 * rtmp并解析
@ -138,6 +143,11 @@ public:
_muxer->addTrack(track); _muxer->addTrack(track);
track->addDelegate(_muxer); track->addDelegate(_muxer);
} }
if(_recreate_metadata){
//需要重新生成metadata
Metadata::addTrack(_metadata,track);
}
} }
/** /**
@ -146,11 +156,19 @@ public:
void onAllTrackReady() override{ void onAllTrackReady() override{
setTrackSource(_muxer); setTrackSource(_muxer);
_all_track_ready = true; _all_track_ready = true;
if(_recreate_metadata){
//需要重新生成metadata
RtmpMediaSource::setMetaData(_metadata);
} }
}
private: private:
RtmpDemuxer::Ptr _demuxer; RtmpDemuxer::Ptr _demuxer;
MultiMediaSourceMuxer::Ptr _muxer; MultiMediaSourceMuxer::Ptr _muxer;
AMFValue _metadata;
bool _all_track_ready = false; bool _all_track_ready = false;
bool _recreate_metadata = false;
}; };
} /* namespace mediakit */ } /* namespace mediakit */

View File

@ -23,47 +23,9 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) {
} }
void RtmpMuxer::addTrack(const Track::Ptr &track) { void RtmpMuxer::addTrack(const Track::Ptr &track) {
//根据track生产metadata
Metadata::Ptr metadata;
switch (track->getTrackType()){
case TrackVideo:{
metadata = std::make_shared<VideoMeta>(dynamic_pointer_cast<VideoTrack>(track));
}
break;
case TrackAudio:{
metadata = std::make_shared<AudioMeta>(dynamic_pointer_cast<AudioTrack>(track));
}
break;
default:
return;
}
switch (track->getCodecId()){
case CodecG711A:
case CodecG711U:{
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
if(!audio_track){
return;
}
if (audio_track->getAudioSampleRate() != 8000 ||
audio_track->getAudioChannel() != 1 ||
audio_track->getAudioSampleBit() != 16) {
WarnL << "RTMP只支持8000/1/16规格的G711,目前规格是:"
<< audio_track->getAudioSampleRate() << "/"
<< audio_track->getAudioChannel() << "/"
<< audio_track->getAudioSampleBit()
<< ",该音频已被忽略";
return;
}
break;
}
default : break;
}
auto &encoder = _encoder[track->getTrackType()]; auto &encoder = _encoder[track->getTrackType()];
//生成rtmp编码器,克隆该Track防止循环引用 //生成rtmp编码器,克隆该Track防止循环引用
encoder = Factory::getRtmpCodecByTrack(track->clone()); encoder = Factory::getRtmpCodecByTrack(track->clone(), true);
if (!encoder) { if (!encoder) {
return; return;
} }
@ -71,10 +33,8 @@ void RtmpMuxer::addTrack(const Track::Ptr &track) {
//设置rtmp输出环形缓存 //设置rtmp输出环形缓存
encoder->setRtmpRing(_rtmpRing); encoder->setRtmpRing(_rtmpRing);
//添加其metadata //添加metadata
metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value){ Metadata::addTrack(_metadata,track);
_metadata.set(key,value);
});
} }
void RtmpMuxer::inputFrame(const Frame::Ptr &frame) { void RtmpMuxer::inputFrame(const Frame::Ptr &frame) {

View File

@ -44,6 +44,7 @@ inline void AMFValue::destroy() {
break; break;
} }
} }
inline void AMFValue::init() { inline void AMFValue::init() {
switch (_type) { switch (_type) {
case AMF_OBJECT: case AMF_OBJECT:
@ -60,14 +61,13 @@ inline void AMFValue::init() {
default: default:
break; break;
} }
} }
AMFValue::AMFValue(AMFType type) : AMFValue::AMFValue(AMFType type) :
_type(type) { _type(type) {
init(); init();
} }
AMFValue::~AMFValue() { AMFValue::~AMFValue() {
destroy(); destroy();
} }
@ -78,7 +78,6 @@ AMFValue::AMFValue(const char *s) :
*_value.string = s; *_value.string = s;
} }
AMFValue::AMFValue(const std::string &s) : AMFValue::AMFValue(const std::string &s) :
_type(AMF_STRING) { _type(AMF_STRING) {
init(); init();
@ -108,15 +107,7 @@ AMFValue::AMFValue(const AMFValue &from) :
*this = from; *this = from;
} }
AMFValue::AMFValue(AMFValue &&from) { AMFValue& AMFValue::operator = (const AMFValue &from) {
*this = std::forward<AMFValue>(from);
}
AMFValue& AMFValue::operator =(const AMFValue &from) {
return *this = const_cast<AMFValue &&>(from);
}
AMFValue& AMFValue::operator =(AMFValue &&from) {
destroy(); destroy();
_type = from._type; _type = from._type;
init(); init();
@ -144,7 +135,6 @@ AMFValue& AMFValue::operator =(AMFValue &&from) {
break; break;
} }
return *this; return *this;
} }
void AMFValue::clear() { void AMFValue::clear() {
@ -236,7 +226,6 @@ string AMFValue::to_string() const{
} }
} }
const AMFValue& AMFValue::operator[](const char *str) const { const AMFValue& AMFValue::operator[](const char *str) const {
if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) { if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
throw std::runtime_error("AMF not a object"); throw std::runtime_error("AMF not a object");
@ -338,6 +327,7 @@ AMFEncoder & AMFEncoder::operator <<(const char *s) {
} }
return *this; return *this;
} }
AMFEncoder & AMFEncoder::operator <<(const std::string &s) { AMFEncoder & AMFEncoder::operator <<(const std::string &s) {
if (!s.empty()) { if (!s.empty()) {
buf += char(AMF0_STRING); buf += char(AMF0_STRING);
@ -349,18 +339,22 @@ AMFEncoder & AMFEncoder::operator <<(const std::string &s) {
} }
return *this; return *this;
} }
AMFEncoder & AMFEncoder::operator <<(std::nullptr_t) { AMFEncoder & AMFEncoder::operator <<(std::nullptr_t) {
buf += char(AMF0_NULL); buf += char(AMF0_NULL);
return *this; return *this;
} }
AMFEncoder & AMFEncoder::write_undefined() { AMFEncoder & AMFEncoder::write_undefined() {
buf += char(AMF0_UNDEFINED); buf += char(AMF0_UNDEFINED);
return *this; return *this;
} }
AMFEncoder & AMFEncoder::operator <<(const int n){ AMFEncoder & AMFEncoder::operator <<(const int n){
return (*this) << (double)n; return (*this) << (double)n;
} }
AMFEncoder & AMFEncoder::operator <<(const double n) { AMFEncoder & AMFEncoder::operator <<(const double n) {
buf += char(AMF0_NUMBER); buf += char(AMF0_NUMBER);
uint64_t encoded = 0; uint64_t encoded = 0;

View File

@ -40,6 +40,7 @@ public:
typedef std::map<std::string, AMFValue> mapType; typedef std::map<std::string, AMFValue> mapType;
typedef std::vector<AMFValue> arrayType; typedef std::vector<AMFValue> arrayType;
~AMFValue();
AMFValue(AMFType type = AMF_NULL); AMFValue(AMFType type = AMF_NULL);
AMFValue(const char *s); AMFValue(const char *s);
AMFValue(const std::string &s); AMFValue(const std::string &s);
@ -47,10 +48,7 @@ public:
AMFValue(int i); AMFValue(int i);
AMFValue(bool b); AMFValue(bool b);
AMFValue(const AMFValue &from); AMFValue(const AMFValue &from);
AMFValue(AMFValue &&from); AMFValue &operator = (const AMFValue &from);
AMFValue &operator =(const AMFValue &from);
AMFValue &operator =(AMFValue &&from);
~AMFValue();
void clear(); void clear();
AMFType type() const ; AMFType type() const ;