diff --git a/src/Player/Frame.h b/src/Player/Frame.h index 31eede5a..53afbb2c 100644 --- a/src/Player/Frame.h +++ b/src/Player/Frame.h @@ -162,7 +162,9 @@ public: * @param frame */ void inputFrame(const Frame::Ptr &frame) override{ - _frameRing->write(frame,frame->keyFrame()); + if(_frameRing){ + _frameRing->write(frame,frame->keyFrame()); + } } protected: RingType::Ptr _frameRing; diff --git a/src/Player/Track.h b/src/Player/Track.h index 23473a0b..231a663d 100644 --- a/src/Player/Track.h +++ b/src/Player/Track.h @@ -37,7 +37,7 @@ using namespace toolkit; namespace mediakit{ -class Track : public FrameRing , public CodecInfo{ +class Track : public FrameRingInterfaceDelegate , public CodecInfo{ public: typedef std::shared_ptr Ptr; Track(){} diff --git a/src/RtspMuxer/RtpCodec.h b/src/RtspMuxer/RtpCodec.h index 3f452a80..0239b44a 100644 --- a/src/RtspMuxer/RtpCodec.h +++ b/src/RtspMuxer/RtpCodec.h @@ -97,7 +97,9 @@ public: } bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ - _rtpRing->write(rtp,key_pos); + if(_rtpRing){ + _rtpRing->write(rtp,key_pos); + } return key_pos; } protected: diff --git a/src/RtspMuxer/RtspMuxer.cpp b/src/RtspMuxer/RtspMuxer.cpp index c5df3cda..a8031135 100644 --- a/src/RtspMuxer/RtspMuxer.cpp +++ b/src/RtspMuxer/RtspMuxer.cpp @@ -30,14 +30,72 @@ namespace mediakit { void RtspMuxer::addTrack(const Track::Ptr &track, uint32_t ssrc, int mtu) { - if (track->getCodecId() == CodecInvalid) { - addTrack(std::make_shared(), ssrc, mtu); - } else { + //记录该Track + auto codec_id = track->getCodecId(); + _track_map[codec_id] = track; + auto lam = [this,ssrc,mtu,track](){ Sdp::Ptr sdp = Factory::getSdpByTrack(track); - if (sdp) { - addTrack(sdp, ssrc, mtu); + if (!sdp) { + return; + } + auto encoder = sdp->createRtpEncoder(ssrc ? ssrc : ((uint64_t) sdp.get()) & 0xFFFFFFFF, mtu); + if (!encoder) { + return; + } + //设置Track的代理,这样输入frame至Track时,最终数据将输出到RtpEncoder中 + track->setDelegate(encoder); + //rtp编码器共用同一个环形缓存 + encoder->setRtpRing(_rtpRing); + }; + if(track->ready()){ + lam(); + }else{ + _trackReadyCallback[codec_id] = lam; + } +} + +string RtspMuxer::getSdp() { + if(!_trackReadyCallback.empty()){ + //尚未就绪 + return ""; + } + +// _StrPrinter printer; +// for (auto &pr : _sdp_map) { +// printer << pr.second->getSdp(); +// } +// return printer; +} + + +void RtspMuxer::inputFrame(const Frame::Ptr &frame) { + auto codec_id = frame->getCodecId(); + auto it = _track_map.find(codec_id); + if (it == _track_map.end()) { + return; + } + //Track是否准备好 + auto ready = it->second->ready(); + //inputFrame可能使Track变成就绪状态 + it->second->inputFrame(frame); + + if(!ready && it->second->ready()){ + //Track又未就绪状态装换成就绪状态,我们就生成sdp以及rtp编码器 + auto it_callback = _trackReadyCallback.find(codec_id); + if(it_callback != _trackReadyCallback.end()){ + it_callback->second(); + _trackReadyCallback.erase(it_callback); } } } +bool RtspMuxer::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { + _rtpRing->write(rtp,key_pos); + return true; +} + +RtpRingInterface::RingType::Ptr RtspMuxer::getRtpRing() const { + return _rtpRing; +} + } /* namespace mediakit */ \ No newline at end of file diff --git a/src/RtspMuxer/RtspMuxer.h b/src/RtspMuxer/RtspMuxer.h index 1c40fca1..1115013a 100644 --- a/src/RtspMuxer/RtspMuxer.h +++ b/src/RtspMuxer/RtspMuxer.h @@ -33,34 +33,16 @@ namespace mediakit{ /** * rtsp生成器 */ -class RtspMuxer : public FrameRingInterface , public RtpRingInterface{ +class RtspMuxer{ public: /** - * 构成函数 + * 构造函数 */ RtspMuxer(){ _rtpRing = std::make_shared(); - _frameRing = std::make_shared(); } virtual ~RtspMuxer(){} - /** - * 添加音视频或title 媒体 - * @param sdp 媒体描述对象 - * @param ssrc 媒体rtp ssrc - * @param mtu 媒体rtp mtu - */ - void addTrack(const Sdp::Ptr & sdp,uint32_t ssrc = 0,int mtu = 1400){ - if(ssrc == 0){ - ssrc = ((uint64_t) sdp.get()) & 0xFFFFFFFF; - } - sdp->createRtpEncoder(ssrc, mtu); - sdp->setFrameRing(_frameRing); - sdp->setRtpRing(_rtpRing); - _sdp_map[sdp->getTrackType()] = sdp; - } - - /** * 添加音视频或title 媒体 * @param track 媒体描述 @@ -73,82 +55,30 @@ public: * 获取完整的SDP字符串 * @return SDP字符串 */ - string getSdp() { - _StrPrinter printer; - for(auto &pr : _sdp_map){ - printer << pr.second->getSdp() ; - } - return printer; - } - + string getSdp() ; /** * 写入帧数据然后打包rtp * @param frame 帧数据 */ - void inputFrame(const Frame::Ptr &frame) override { - auto it = _sdp_map.find(frame->getTrackType()); - if(it == _sdp_map.end()){ - return ; - } - it->second->inputFrame(frame); - } + void inputFrame(const Frame::Ptr &frame) ; /** * 也可以在外部打包好rtp然后再写入 * @param rtp rtp包 * @param key_pos 是否为关键帧的第一个rtp包 */ - bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override { - auto it = _sdp_map.find(rtp->type); - if(it == _sdp_map.end()){ - return false; - } - return it->second->inputRtp(rtp,key_pos); - } + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true); /** * 获取rtp环形缓存 * @return */ - RtpRingInterface::RingType::Ptr getRtpRing() const override{ - return _rtpRing; - } - - /** - * 获取帧环形缓存 - * @return - */ - FrameRingInterface::RingType::Ptr getFrameRing() const override{ - return _frameRing; - } - - /** - * 设置帧环形缓存 - * @param ring - */ - void setFrameRing(const FrameRingInterface::RingType::Ptr &ring) override{ - _frameRing = ring; - for(auto &pr : _sdp_map){ - pr.second->setFrameRing(ring); - } - } - - - /** - * 设置rtp环形缓存 - * @param ring - */ - void setRtpRing(const RtpRingInterface::RingType::Ptr &ring) override{ - _rtpRing = ring; - for(auto &pr : _sdp_map){ - pr.second->setRtpRing(ring); - } - } + RtpRingInterface::RingType::Ptr getRtpRing() const; private: - map _sdp_map; + map _track_map; + map > _trackReadyCallback; RtpRingInterface::RingType::Ptr _rtpRing; - FrameRingInterface::RingType::Ptr _frameRing; }; diff --git a/src/RtspMuxer/RtspSdp.cpp b/src/RtspMuxer/RtspSdp.cpp index 4363ec1d..69160d27 100644 --- a/src/RtspMuxer/RtspSdp.cpp +++ b/src/RtspMuxer/RtspSdp.cpp @@ -28,13 +28,13 @@ namespace mediakit{ -void Sdp::createRtpEncoder(uint32_t ssrc, int mtu) { - _encoder = Factory::getRtpEncoderById(getCodecId(), - ssrc, - mtu, - _sample_rate, - _playload_type, - getTrackType() * 2); +RtpCodec::Ptr Sdp::createRtpEncoder(uint32_t ssrc, int mtu) { + return Factory::getRtpEncoderById(getCodecId(), + ssrc, + mtu, + _sample_rate, + _playload_type, + getTrackType() * 2); } } diff --git a/src/RtspMuxer/RtspSdp.h b/src/RtspMuxer/RtspSdp.h index 1af73c76..c7363272 100644 --- a/src/RtspMuxer/RtspSdp.h +++ b/src/RtspMuxer/RtspSdp.h @@ -36,7 +36,7 @@ namespace mediakit { /** * sdp基类 */ -class Sdp : public FrameRingInterface , public RtpRingInterface , public CodecInfo{ +class Sdp : public CodecInfo{ public: typedef std::shared_ptr Ptr; @@ -59,63 +59,14 @@ public: virtual string getSdp() const = 0; - /** - * 获取帧环形缓存 - * @return - */ - FrameRingInterface::RingType::Ptr getFrameRing() const override { - return _encoder->getFrameRing(); - } - - /** - * 获取rtp环形缓存 - * @return - */ - RtpRingInterface::RingType::Ptr getRtpRing() const override{ - return _encoder->getRtpRing(); - } - - /** - * 输入帧数据,驱动rtp打包 - * @param frame 帧数据 - */ - void inputFrame(const Frame::Ptr &frame) override{ - _encoder->inputFrame(frame); - } - - /** - * 也可以在外部打包rtp后直接输入rtp - * @param rtp rtp数据包 - * @param key_pos 是否为关键帧第一个rtp包 - */ - bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ - return _encoder->inputRtp(rtp,key_pos); - } - - /** - * 替换帧环形缓存,目的是多个rtp打包器共用一个环形缓存 - * @param ring - */ - void setFrameRing(const FrameRingInterface::RingType::Ptr &ring) override{ - _encoder->setFrameRing(ring); - } - - /** - * 替换帧环形缓存,目的是多个rtp打包器共用一个环形缓存 - * @param ring - */ - void setRtpRing(const RtpRingInterface::RingType::Ptr &ring) override{ - _encoder->setRtpRing(ring); - } - /** * 创建Rtp打包器 * @param ssrc 打包器ssrc,可以为0 * @param mtu mtu大小,一般小于1500字节,推荐1400 + * @return Rtp打包器 */ - virtual void createRtpEncoder(uint32_t ssrc, int mtu); + virtual RtpCodec::Ptr createRtpEncoder(uint32_t ssrc, int mtu); private: - RtpCodec::Ptr _encoder; uint8_t _playload_type; uint32_t _sample_rate; }; @@ -270,7 +221,7 @@ public: TrackType getTrackType() const override { return TrackAudio; - }; + } CodecId getCodecId() const override { return CodecAAC; }