From 41509800bce952280ed2a93c08c6350a14a7b99b Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Thu, 28 May 2020 17:03:12 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E5=AF=B9=E6=97=A0metadata?= =?UTF-8?q?=E7=9A=84rtmp=E6=B5=81=E7=9A=84=E5=85=BC=E5=AE=B9=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/Factory.cpp | 18 ++++++++++++-- src/Extension/Factory.h | 3 ++- src/Rtmp/Rtmp.cpp | 19 +++++++++++++++ src/Rtmp/Rtmp.h | 3 ++- src/Rtmp/RtmpDemuxer.cpp | 34 ++++++++++++-------------- src/Rtmp/RtmpDemuxer.h | 2 +- src/Rtmp/RtmpMediaSourceImp.h | 22 +++++++++++++++-- src/Rtmp/RtmpMuxer.cpp | 46 +++-------------------------------- src/Rtmp/amf.cpp | 22 ++++++----------- src/Rtmp/amf.h | 6 ++--- 10 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/Extension/Factory.cpp b/src/Extension/Factory.cpp index b59e166f..276ce140 100644 --- a/src/Extension/Factory.cpp +++ b/src/Extension/Factory.cpp @@ -221,13 +221,27 @@ Track::Ptr Factory::getAudioTrackByAmf(const AMFValue& amf, int sample_rate, int 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()){ case CodecH264 : return std::make_shared(track); case CodecAAC : return std::make_shared(track); case CodecH265 : return std::make_shared(track); case CodecG711A : - case CodecG711U : return std::make_shared(track); + case CodecG711U : { + auto audio_track = dynamic_pointer_cast(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(track); + } default : WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr; } } diff --git a/src/Extension/Factory.h b/src/Extension/Factory.h index 6b678d34..74b70c58 100644 --- a/src/Extension/Factory.h +++ b/src/Extension/Factory.h @@ -59,8 +59,9 @@ public: /** * 根据Track获取Rtmp的编解码器 * @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描述 diff --git a/src/Rtmp/Rtmp.cpp b/src/Rtmp/Rtmp.cpp index 4749f3ea..db0078f4 100644 --- a/src/Rtmp/Rtmp.cpp +++ b/src/Rtmp/Rtmp.cpp @@ -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(dynamic_pointer_cast(track)); + } + break; + case TrackAudio: { + new_metadata = std::make_shared(dynamic_pointer_cast(track)); + } + break; + default: + return; + } + + new_metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value) { + metadata.set(key, value); + }); +} }//namespace mediakit \ No newline at end of file diff --git a/src/Rtmp/Rtmp.h b/src/Rtmp/Rtmp.h index 22f0775f..f9d3d8e6 100644 --- a/src/Rtmp/Rtmp.h +++ b/src/Rtmp/Rtmp.h @@ -220,6 +220,8 @@ public: const AMFValue &getMetadata() const{ return _metadata; } + + static void addTrack(AMFValue &metadata, const Track::Ptr &track); protected: AMFValue _metadata; }; @@ -261,7 +263,6 @@ private: CodecId _codecId; }; - class AudioMeta : public Metadata{ public: typedef std::shared_ptr Ptr; diff --git a/src/Rtmp/RtmpDemuxer.cpp b/src/Rtmp/RtmpDemuxer.cpp index 4848a960..6e38b0d7 100644 --- a/src/Rtmp/RtmpDemuxer.cpp +++ b/src/Rtmp/RtmpDemuxer.cpp @@ -13,60 +13,56 @@ namespace mediakit { -void RtmpDemuxer::loadMetaData(const AMFValue &val){ +bool RtmpDemuxer::loadMetaData(const AMFValue &val){ + bool ret = false; try { 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"){ + if (key == "audiosamplerate") { audiosamplerate = val.as_integer(); return; } - - if(key == "audiosamplesize"){ + if (key == "audiosamplesize") { audiosamplesize = val.as_integer(); return; } - - if(key == "stereo"){ + if (key == "stereo") { audiochannels = val.as_boolean() ? 2 : 1; return; } - - if(key == "videocodecid"){ + if (key == "videocodecid") { //找到视频 videocodecid = &val; return; } - - if(key == "audiocodecid"){ + if (key == "audiocodecid") { //找到音频 audiocodecid = &val; return; } }); - - if(videocodecid){ + if (videocodecid) { //有视频 + ret = true; makeVideoTrack(*videocodecid); } - - if(audiocodecid){ + if (audiocodecid) { //有音频 + ret = true; makeAudioTrack(*audiocodecid, audiosamplerate, audiochannels, audiosamplesize); } - }catch (std::exception &ex){ + } catch (std::exception &ex) { WarnL << ex.what(); } + return ret; } bool RtmpDemuxer::inputRtmp(const RtmpPacket::Ptr &pkt) { @@ -105,7 +101,7 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) { _videoTrack = dynamic_pointer_cast(Factory::getVideoTrackByAmf(videoCodec)); if (_videoTrack) { //生成rtmpCodec对象以便解码rtmp - _videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack); + _videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack, false); if (_videoRtmpDecoder) { //设置rtmp解码器代理,生成的frame写入该Track _videoRtmpDecoder->addDelegate(_videoTrack); @@ -123,7 +119,7 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int _audioTrack = dynamic_pointer_cast(Factory::getAudioTrackByAmf(audioCodec, sample_rate, channels, sample_bit)); if (_audioTrack) { //生成rtmpCodec对象以便解码rtmp - _audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack); + _audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack, false); if (_audioRtmpDecoder) { //设置rtmp解码器代理,生成的frame写入该Track _audioRtmpDecoder->addDelegate(_audioTrack); diff --git a/src/Rtmp/RtmpDemuxer.h b/src/Rtmp/RtmpDemuxer.h index fbff5d2e..7c6bdfa7 100644 --- a/src/Rtmp/RtmpDemuxer.h +++ b/src/Rtmp/RtmpDemuxer.h @@ -30,7 +30,7 @@ public: RtmpDemuxer() = default; virtual ~RtmpDemuxer() = default; - void loadMetaData(const AMFValue &metadata); + bool loadMetaData(const AMFValue &metadata); /** * 开始解复用 diff --git a/src/Rtmp/RtmpMediaSourceImp.h b/src/Rtmp/RtmpMediaSourceImp.h index e78f1286..4e8aae87 100644 --- a/src/Rtmp/RtmpMediaSourceImp.h +++ b/src/Rtmp/RtmpMediaSourceImp.h @@ -49,8 +49,13 @@ public: * 设置metadata */ void setMetaData(const AMFValue &metadata) override{ - _demuxer->loadMetaData(metadata); - RtmpMediaSource::setMetaData(metadata); + if(!_demuxer->loadMetaData(metadata)){ + //该metadata无效,需要重新生成 + _metadata = metadata; + _recreate_metadata = true; + }else{ + RtmpMediaSource::setMetaData(metadata); + } } /** @@ -138,6 +143,11 @@ public: _muxer->addTrack(track); track->addDelegate(_muxer); } + + if(_recreate_metadata){ + //需要重新生成metadata + Metadata::addTrack(_metadata,track); + } } /** @@ -146,11 +156,19 @@ public: void onAllTrackReady() override{ setTrackSource(_muxer); _all_track_ready = true; + + if(_recreate_metadata){ + //需要重新生成metadata + RtmpMediaSource::setMetaData(_metadata); + } } + private: RtmpDemuxer::Ptr _demuxer; MultiMediaSourceMuxer::Ptr _muxer; + AMFValue _metadata; bool _all_track_ready = false; + bool _recreate_metadata = false; }; } /* namespace mediakit */ diff --git a/src/Rtmp/RtmpMuxer.cpp b/src/Rtmp/RtmpMuxer.cpp index 2547642e..50686d01 100644 --- a/src/Rtmp/RtmpMuxer.cpp +++ b/src/Rtmp/RtmpMuxer.cpp @@ -23,47 +23,9 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) { } void RtmpMuxer::addTrack(const Track::Ptr &track) { - //根据track生产metadata - Metadata::Ptr metadata; - switch (track->getTrackType()){ - case TrackVideo:{ - metadata = std::make_shared(dynamic_pointer_cast(track)); - } - break; - case TrackAudio:{ - metadata = std::make_shared(dynamic_pointer_cast(track)); - } - break; - default: - return; - - } - - switch (track->getCodecId()){ - case CodecG711A: - case CodecG711U:{ - auto audio_track = dynamic_pointer_cast(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()]; //生成rtmp编码器,克隆该Track,防止循环引用 - encoder = Factory::getRtmpCodecByTrack(track->clone()); + encoder = Factory::getRtmpCodecByTrack(track->clone(), true); if (!encoder) { return; } @@ -71,10 +33,8 @@ void RtmpMuxer::addTrack(const Track::Ptr &track) { //设置rtmp输出环形缓存 encoder->setRtmpRing(_rtmpRing); - //添加其metadata - metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value){ - _metadata.set(key,value); - }); + //添加metadata + Metadata::addTrack(_metadata,track); } void RtmpMuxer::inputFrame(const Frame::Ptr &frame) { diff --git a/src/Rtmp/amf.cpp b/src/Rtmp/amf.cpp index c19136cb..ca4c8077 100644 --- a/src/Rtmp/amf.cpp +++ b/src/Rtmp/amf.cpp @@ -44,6 +44,7 @@ inline void AMFValue::destroy() { break; } } + inline void AMFValue::init() { switch (_type) { case AMF_OBJECT: @@ -60,14 +61,13 @@ inline void AMFValue::init() { default: break; } - } + AMFValue::AMFValue(AMFType type) : _type(type) { init(); } - AMFValue::~AMFValue() { destroy(); } @@ -78,7 +78,6 @@ AMFValue::AMFValue(const char *s) : *_value.string = s; } - AMFValue::AMFValue(const std::string &s) : _type(AMF_STRING) { init(); @@ -108,15 +107,7 @@ AMFValue::AMFValue(const AMFValue &from) : *this = from; } -AMFValue::AMFValue(AMFValue &&from) { - *this = std::forward(from); -} - -AMFValue& AMFValue::operator =(const AMFValue &from) { - return *this = const_cast(from); - -} -AMFValue& AMFValue::operator =(AMFValue &&from) { +AMFValue& AMFValue::operator = (const AMFValue &from) { destroy(); _type = from._type; init(); @@ -144,7 +135,6 @@ AMFValue& AMFValue::operator =(AMFValue &&from) { break; } return *this; - } void AMFValue::clear() { @@ -236,7 +226,6 @@ string AMFValue::to_string() const{ } } - const AMFValue& AMFValue::operator[](const char *str) const { if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) { throw std::runtime_error("AMF not a object"); @@ -338,6 +327,7 @@ AMFEncoder & AMFEncoder::operator <<(const char *s) { } return *this; } + AMFEncoder & AMFEncoder::operator <<(const std::string &s) { if (!s.empty()) { buf += char(AMF0_STRING); @@ -349,18 +339,22 @@ AMFEncoder & AMFEncoder::operator <<(const std::string &s) { } return *this; } + AMFEncoder & AMFEncoder::operator <<(std::nullptr_t) { buf += char(AMF0_NULL); return *this; } + AMFEncoder & AMFEncoder::write_undefined() { buf += char(AMF0_UNDEFINED); return *this; } + AMFEncoder & AMFEncoder::operator <<(const int n){ return (*this) << (double)n; } + AMFEncoder & AMFEncoder::operator <<(const double n) { buf += char(AMF0_NUMBER); uint64_t encoded = 0; diff --git a/src/Rtmp/amf.h b/src/Rtmp/amf.h index 830fbe28..9b29b11e 100644 --- a/src/Rtmp/amf.h +++ b/src/Rtmp/amf.h @@ -40,6 +40,7 @@ public: typedef std::map mapType; typedef std::vector arrayType; + ~AMFValue(); AMFValue(AMFType type = AMF_NULL); AMFValue(const char *s); AMFValue(const std::string &s); @@ -47,10 +48,7 @@ public: AMFValue(int i); AMFValue(bool b); AMFValue(const AMFValue &from); - AMFValue(AMFValue &&from); - AMFValue &operator =(const AMFValue &from); - AMFValue &operator =(AMFValue &&from); - ~AMFValue(); + AMFValue &operator = (const AMFValue &from); void clear(); AMFType type() const ;