diff --git a/src/Common/Factory.cpp b/src/Common/Factory.cpp index 7f0dc501..98a3e31f 100644 --- a/src/Common/Factory.cpp +++ b/src/Common/Factory.cpp @@ -196,18 +196,19 @@ RtpCodec::Ptr Factory::getRtpDecoderById(CodecId codecId, uint32_t ui32SampleRat } } -RtmpCodec::Ptr Factory::getRtmpCodecById(CodecId codecId) { - switch (codecId){ +RtmpCodec::Ptr Factory::getRtmpCodecByTrack(const Track::Ptr &track) { + switch (track->getCodecId()){ case CodecH264: - return std::make_shared(); + return std::make_shared(track); case CodecAAC: - return std::make_shared(); + return std::make_shared(track); default: - WarnL << "暂不支持该CodecId:" << codecId; + WarnL << "暂不支持该CodecId:" << track->getCodecId(); return nullptr; } } + }//namespace mediakit diff --git a/src/Common/Factory.h b/src/Common/Factory.h index 3f276b08..458a0572 100644 --- a/src/Common/Factory.h +++ b/src/Common/Factory.h @@ -106,11 +106,11 @@ public: static CodecId getCodecIdByAmf(const AMFValue &val); /** - * 根据CodecId获取Rtmp的编解码器 - * @param codecId CodecId + * 根据Track获取Rtmp的编解码器 + * @param track 媒体描述对象 * @return */ - static RtmpCodec::Ptr getRtmpCodecById(CodecId codecId); + static RtmpCodec::Ptr getRtmpCodecByTrack(const Track::Ptr &track); }; diff --git a/src/RtmpMuxer/AACRtmpCodec.cpp b/src/RtmpMuxer/AACRtmpCodec.cpp index 69a8090e..b650447d 100644 --- a/src/RtmpMuxer/AACRtmpCodec.cpp +++ b/src/RtmpMuxer/AACRtmpCodec.cpp @@ -75,12 +75,23 @@ void AACRtmpDecoder::onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeSta } ///////////////////////////////////////////////////////////////////////////////////// +AACRtmpEncoder::AACRtmpEncoder(const Track::Ptr &track) { + _track = dynamic_pointer_cast(track); +} + void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { RtmpCodec::inputFrame(frame); - if(frame->prefixSize() >= 7 && _aac_cfg.empty()){ - //包含adts头 - _aac_cfg = makeAdtsConfig(reinterpret_cast(frame->data())); - makeAudioConfigPkt(); + + if(_aac_cfg.empty()){ + if(frame->prefixSize() >= 7){ + //包含adts头,从adts头获取aac配置信息 + _aac_cfg = makeAdtsConfig(reinterpret_cast(frame->data())); + makeAudioConfigPkt(); + } else if(_track && _track->ready()){ + //从track中和获取aac配置信息 + _aac_cfg = _track->getAacCfg(); + makeAudioConfigPkt(); + } } if(!_aac_cfg.empty()){ @@ -149,6 +160,4 @@ void AACRtmpEncoder::makeAudioConfigPkt() { inputRtmp(rtmpPkt, false); } - - }//namespace mediakit \ No newline at end of file diff --git a/src/RtmpMuxer/AACRtmpCodec.h b/src/RtmpMuxer/AACRtmpCodec.h index ad41c04c..d1e0332d 100644 --- a/src/RtmpMuxer/AACRtmpCodec.h +++ b/src/RtmpMuxer/AACRtmpCodec.h @@ -28,6 +28,7 @@ #define ZLMEDIAKIT_AACRTMPCODEC_H #include "RtmpCodec.h" +#include "Player/Track.h" namespace mediakit{ /** @@ -71,18 +72,26 @@ class AACRtmpEncoder : public AACRtmpDecoder , public ResourcePoolHelper Ptr; - AACRtmpEncoder(){} + /** + * 构造函数,track可以为空,此时则在inputFrame时输入adts头 + * 如果track不为空且包含adts头相关信息, + * 那么inputFrame时可以不输入adts头 + * @param track + */ + AACRtmpEncoder(const Track::Ptr &track); ~AACRtmpEncoder() {} /** - * 输入aac 数据,必须带dats头 - * @param frame 带dats头的aac数据 + * 输入aac 数据,可以不带adts头 + * @param frame aac数据 */ void inputFrame(const Frame::Ptr &frame) override; private: void makeAudioConfigPkt(); +private: uint8_t _ui8AudioFlags; + AACTrack::Ptr _track; }; }//namespace mediakit diff --git a/src/RtmpMuxer/H264RtmpCodec.cpp b/src/RtmpMuxer/H264RtmpCodec.cpp index 6a384250..06ceee49 100644 --- a/src/RtmpMuxer/H264RtmpCodec.cpp +++ b/src/RtmpMuxer/H264RtmpCodec.cpp @@ -105,7 +105,8 @@ inline void H264RtmpDecoder::onGetH264(const char* pcData, int iLen, uint32_t ui //////////////////////////////////////////////////////////////////////// -H264RtmpEncoder::H264RtmpEncoder() { +H264RtmpEncoder::H264RtmpEncoder(const Track::Ptr &track) { + _track = dynamic_pointer_cast(track); } void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { @@ -115,6 +116,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { auto iLen = frame->size() - frame->prefixSize(); auto type = ((uint8_t*)pcData)[0] & 0x1F; + //尝试从frame中获取sps pps switch (type){ case 7:{ //sps @@ -136,6 +138,18 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) { } } break; + default: + break; + } + + //尝试从track中获取sps pps信息 + if((!_sps.empty() || !_pps.empty()) && _track && _track->ready()){ + _sps = _track->getSps(); + _pps = _track->getPps(); + makeVideoConfigPkt(); + } + + switch (type){ case 1: case 5:{ //I or P or B frame diff --git a/src/RtmpMuxer/H264RtmpCodec.h b/src/RtmpMuxer/H264RtmpCodec.h index bb4ecc45..b6c463d8 100644 --- a/src/RtmpMuxer/H264RtmpCodec.h +++ b/src/RtmpMuxer/H264RtmpCodec.h @@ -28,6 +28,7 @@ #define ZLMEDIAKIT_H264RTMPCODEC_H #include "RtmpCodec.h" +#include "Player/Track.h" #include "Util/ResourcePool.h" using namespace toolkit; @@ -74,16 +75,24 @@ class H264RtmpEncoder : public H264RtmpDecoder, public ResourcePoolHelper Ptr; - H264RtmpEncoder(); + /** + * 构造函数,track可以为空,此时则在inputFrame时输入sps pps + * 如果track不为空且包含sps pps信息, + * 那么inputFrame时可以不输入sps pps + * @param track + */ + H264RtmpEncoder(const Track::Ptr &track); ~H264RtmpEncoder() {} /** - * 输入264帧,需要指出的是,必须输入sps pps帧 + * 输入264帧,可以不带sps pps * @param frame 帧数据 */ void inputFrame(const Frame::Ptr &frame) override; private: void makeVideoConfigPkt(); +private: + H264Track::Ptr _track; }; }//namespace mediakit diff --git a/src/RtmpMuxer/RtmpDemuxer.cpp b/src/RtmpMuxer/RtmpDemuxer.cpp index b8974911..0d3d9b6a 100644 --- a/src/RtmpMuxer/RtmpDemuxer.cpp +++ b/src/RtmpMuxer/RtmpDemuxer.cpp @@ -81,7 +81,7 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) { _videoTrack = dynamic_pointer_cast(Factory::getTrackByAmf(videoCodec)); if (_videoTrack) { //生成rtmpCodec对象以便解码rtmp - _videoRtmpDecoder = Factory::getRtmpCodecById(_videoTrack->getCodecId()); + _videoRtmpDecoder = Factory::getRtmpCodecByTrack(_videoTrack); if (_videoRtmpDecoder) { //设置rtmp解码器代理,生成的frame写入该Track _videoRtmpDecoder->setDelegate(_videoTrack); @@ -97,7 +97,7 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec) { _audioTrack = dynamic_pointer_cast(Factory::getTrackByAmf(audioCodec)); if (_audioTrack) { //生成rtmpCodec对象以便解码rtmp - _audioRtmpDecoder = Factory::getRtmpCodecById(_audioTrack->getCodecId()); + _audioRtmpDecoder = Factory::getRtmpCodecByTrack(_audioTrack); if (_audioRtmpDecoder) { //设置rtmp解码器代理,生成的frame写入该Track _audioRtmpDecoder->setDelegate(_audioTrack);