From 8930dd099ebbe94e33aebe066192d49146ee8e47 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Tue, 23 Oct 2018 18:39:17 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90Rtp?= =?UTF-8?q?=E8=A7=A3=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Player/Frame.h | 9 +++-- src/Player/PlayerBase.h | 21 ++++------- src/Player/Track.h | 10 +++++- src/RTP/AACRtpCodec.cpp | 10 +++--- src/RTP/AACRtpCodec.h | 8 +++-- src/RTP/H264RtpCodec.cpp | 14 +++++--- src/RTP/H264RtpCodec.h | 7 ++-- src/RTP/RtpCodec.cpp | 24 +++++++++---- src/RTP/RtpCodec.h | 37 +++++++++++++++----- src/Rtmp/RtmpMediaSource.h | 2 +- src/Rtsp/RtpParser.cpp | 71 ++++++++++++++++++-------------------- src/Rtsp/RtpParser.h | 31 ++++++----------- src/Rtsp/RtspEncoder.h | 32 ++++++++--------- 13 files changed, 158 insertions(+), 118 deletions(-) diff --git a/src/Player/Frame.h b/src/Player/Frame.h index 76bd000c..b2474804 100644 --- a/src/Player/Frame.h +++ b/src/Player/Frame.h @@ -27,6 +27,8 @@ typedef enum { class CodecInfo { public: + typedef std::shared_ptr Ptr; + CodecInfo(){} virtual ~CodecInfo(){} @@ -63,6 +65,7 @@ public: class FrameRingInterface { public: typedef RingBuffer RingType; + typedef std::shared_ptr Ptr; FrameRingInterface(){} virtual ~FrameRingInterface(){} @@ -83,8 +86,9 @@ public: * 写入帧数据 * @param frame 帧 * @param key_pos 是否为关键帧 + * @return 是否为关键帧 */ - virtual void inputFrame(const Frame::Ptr &frame,bool key_pos) = 0; + virtual bool inputFrame(const Frame::Ptr &frame,bool key_pos) = 0; }; @@ -118,8 +122,9 @@ public: * @param frame * @param key_pos */ - void inputFrame(const Frame::Ptr &frame,bool key_pos) override{ + bool inputFrame(const Frame::Ptr &frame,bool key_pos) override{ _frameRing->write(frame,key_pos); + return key_pos; } protected: RingType::Ptr _frameRing; diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 158246ee..677d1706 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -87,8 +87,7 @@ public: virtual float getRtpLossRate(int trackType) const {return 0; } virtual float getDuration() const { return 0;} - virtual int getTrackCount() const { return 0;} - virtual Track::Ptr getTrack(int index) const {return nullptr;} + virtual vector getTracks() const { return vector();} protected: virtual void onShutdown(const SockException &ex) {} virtual void onPlayResult(const SockException &ex) {} @@ -146,18 +145,12 @@ public: m_pMediaSrc = src; } - virtual int getTrackCount() const override{ - if (m_parser) { - return m_parser->getTrackCount(); - } - return PlayerBase::getTrackCount(); - } - virtual Track::Ptr getTrack(int index) const override{ - if (m_parser) { - return m_parser->getTrack(index); - } - return PlayerBase::getTrack(index); - } + vector getTracks() const override{ + if (m_parser) { + return m_parser->getTracks(); + } + return PlayerBase::getTracks(); + } protected: void onShutdown(const SockException &ex) override { if (m_shutdownCB) { diff --git a/src/Player/Track.h b/src/Player/Track.h index 705e5efd..38308ce6 100644 --- a/src/Player/Track.h +++ b/src/Player/Track.h @@ -26,6 +26,8 @@ public: class VideoTrack : public Track { public: + typedef std::shared_ptr Ptr; + TrackType getTrackType() const override { return TrackVideo;}; /** @@ -49,6 +51,8 @@ public: class AudioTrack : public Track { public: + typedef std::shared_ptr Ptr; + TrackType getTrackType() const override { return TrackAudio;}; /** @@ -72,6 +76,7 @@ public: class H264Track : public VideoTrack{ public: + typedef std::shared_ptr Ptr; /** * 不指定sps pps构造h264类型的媒体 @@ -162,7 +167,7 @@ public: * @param frame 数据帧 * @param key_pos 是否为关键帧 */ - void inputFrame(const Frame::Ptr &frame,bool key_pos) override{ + bool inputFrame(const Frame::Ptr &frame,bool key_pos) override{ int type = (*((uint8_t *)frame->data() + frame->prefixSize())) & 0x1F; switch (type){ case 7:{ @@ -209,6 +214,7 @@ public: } break; } + return type == 5; } private: /** @@ -228,6 +234,8 @@ private: class AACTrack : public AudioTrack{ public: + typedef std::shared_ptr Ptr; + /** * 构造aac类型的媒体 * @param aac_cfg aac两个字节的配置信息 diff --git a/src/RTP/AACRtpCodec.cpp b/src/RTP/AACRtpCodec.cpp index 318f0479..23f9e90d 100644 --- a/src/RTP/AACRtpCodec.cpp +++ b/src/RTP/AACRtpCodec.cpp @@ -17,7 +17,7 @@ AACRtpEncoder::AACRtpEncoder(uint32_t ui32Ssrc, AACRtpDecoder(ui32SampleRate){ } -void AACRtpEncoder::inputFrame(const Frame::Ptr &frame, bool key_pos) { +bool AACRtpEncoder::inputFrame(const Frame::Ptr &frame, bool key_pos) { RtpCodec::inputFrame(frame, false); GET_CONFIG_AND_REGISTER(uint32_t, cycleMS, Config::Rtp::kCycleMS); @@ -46,8 +46,8 @@ void AACRtpEncoder::inputFrame(const Frame::Ptr &frame, bool key_pos) { makeAACRtp(m_aucSectionBuf, m_ui32MtuSize - 16, false, uiStamp); ptr += (m_ui32MtuSize - 20); iSize -= (m_ui32MtuSize - 20); - } + return false; } void AACRtpEncoder::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp) { @@ -100,24 +100,24 @@ AACFrame::Ptr AACRtpDecoder::obtainFrame() { return frame; } -void AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) { +bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) { RtpCodec::inputRtp(rtppack, false); int length = rtppack->length - rtppack->offset; if (m_adts->aac_frame_length + length - 4 > sizeof(AACFrame::buffer)) { m_adts->aac_frame_length = 7; WarnL << "aac负载数据太长"; - return; + return false; } memcpy(m_adts->buffer + m_adts->aac_frame_length, rtppack->payload + rtppack->offset + 4, length - 4); m_adts->aac_frame_length += (length - 4); if (rtppack->mark == true) { m_adts->sequence = rtppack->sequence; - //todo(xzl) 此处完成时间戳转换 m_adts->timeStamp = rtppack->timeStamp * (1000.0 / m_sampleRate); writeAdtsHeader(*m_adts, m_adts->buffer); onGetAdts(m_adts); } + return false; } void AACRtpDecoder::onGetAdts(const AACFrame::Ptr &frame) { diff --git a/src/RTP/AACRtpCodec.h b/src/RTP/AACRtpCodec.h index 2950fca5..6fb5ac66 100644 --- a/src/RTP/AACRtpCodec.h +++ b/src/RTP/AACRtpCodec.h @@ -12,6 +12,8 @@ */ class AACRtpDecoder : public RtpCodec { public: + typedef std::shared_ptr Ptr; + /** * @param ui32SampleRate 采样率,用于时间戳转换用 */ @@ -23,7 +25,7 @@ public: * @param rtp rtp数据包 * @param key_pos 此参数内部强制转换为false,请忽略之 */ - void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override; + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = false) override; TrackType getTrackType() const override{ return TrackAudio; @@ -47,6 +49,8 @@ private: */ class AACRtpEncoder : public AACRtpDecoder , public RtpInfo { public: + typedef std::shared_ptr Ptr; + /** * @param ui32Ssrc ssrc * @param ui32MtuSize mtu 大小 @@ -66,7 +70,7 @@ public: * @param frame 带dats头的aac数据 * @param key_pos 此参数内部强制转换为false,请忽略之 */ - void inputFrame(const Frame::Ptr &frame, bool key_pos = false) override; + bool inputFrame(const Frame::Ptr &frame, bool key_pos = false) override; private: void makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); private: diff --git a/src/RTP/H264RtpCodec.cpp b/src/RTP/H264RtpCodec.cpp index 94b7885b..695adde1 100644 --- a/src/RTP/H264RtpCodec.cpp +++ b/src/RTP/H264RtpCodec.cpp @@ -17,8 +17,10 @@ H264Frame::Ptr H264RtpDecoder::obtainFrame() { return frame; } -void H264RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { - RtpCodec::inputRtp(rtp, decodeRtp(rtp)); +bool H264RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) { + key_pos = decodeRtp(rtp); + RtpCodec::inputRtp(rtp, key_pos); + return key_pos; } bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) { @@ -116,12 +118,14 @@ H264RtpEncoder::H264RtpEncoder(uint32_t ui32Ssrc, ui8Interleaved) { } -void H264RtpEncoder::inputFrame(const Frame::Ptr &frame, bool key_pos) { +bool H264RtpEncoder::inputFrame(const Frame::Ptr &frame, bool key_pos) { + auto pcData = frame->data() + frame->prefixSize(); + + key_pos = (((uint8_t *) (pcData))[0] & 0x1F) == 5; RtpCodec::inputFrame(frame, key_pos); GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Config::Rtp::kCycleMS); auto uiStamp = frame->stamp(); - auto pcData = frame->data() + frame->prefixSize(); auto iLen = frame->size() - frame->prefixSize(); uiStamp %= cycleMS; @@ -163,6 +167,8 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame, bool key_pos) { } else { makeH264Rtp(pcData, iLen, true, uiStamp); } + + return key_pos; } void H264RtpEncoder::makeH264Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) { diff --git a/src/RTP/H264RtpCodec.h b/src/RTP/H264RtpCodec.h index 348a5ae9..fff3ce72 100644 --- a/src/RTP/H264RtpCodec.h +++ b/src/RTP/H264RtpCodec.h @@ -15,6 +15,8 @@ using namespace ZL::Util; */ class H264RtpDecoder : public RtpCodec { public: + typedef std::shared_ptr Ptr; + H264RtpDecoder(); ~H264RtpDecoder() {} @@ -23,7 +25,7 @@ public: * @param rtp rtp包 * @param key_pos 此参数忽略之 */ - void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override; TrackType getTrackType() const override{ return TrackVideo; @@ -46,6 +48,7 @@ private: */ class H264RtpEncoder : public H264RtpDecoder ,public RtpInfo{ public: + typedef std::shared_ptr Ptr; /** * @param ui32Ssrc ssrc @@ -66,7 +69,7 @@ public: * @param frame 帧数据,必须 * @param key_pos */ - void inputFrame(const Frame::Ptr &frame, bool key_pos) override; + bool inputFrame(const Frame::Ptr &frame, bool key_pos) override; private: void makeH264Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp); private: diff --git a/src/RTP/RtpCodec.cpp b/src/RTP/RtpCodec.cpp index 605098b6..996d889b 100644 --- a/src/RTP/RtpCodec.cpp +++ b/src/RTP/RtpCodec.cpp @@ -6,12 +6,12 @@ #include "AACRtpCodec.h" #include "H264RtpCodec.h" -RtpCodec::Ptr RtpCodec::getRtpCodecById(CodecId codecId, - uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PlayloadType, - uint8_t ui8Interleaved) { +RtpCodec::Ptr RtpCodec::getRtpEncoderById(CodecId codecId, + uint32_t ui32Ssrc, + uint32_t ui32MtuSize, + uint32_t ui32SampleRate, + uint8_t ui8PlayloadType, + uint8_t ui8Interleaved) { switch (codecId){ case CodecH264: return std::make_shared(ui32Ssrc,ui32MtuSize,ui32SampleRate,ui8PlayloadType,ui8Interleaved); @@ -21,3 +21,15 @@ RtpCodec::Ptr RtpCodec::getRtpCodecById(CodecId codecId, return nullptr; } } + +RtpCodec::Ptr RtpCodec::getRtpDecoderById(CodecId codecId, uint32_t ui32SampleRate) { + switch (codecId){ + case CodecH264: + return std::make_shared(); + case CodecAAC: + return std::make_shared(ui32SampleRate); + default: + return nullptr; + } +} + diff --git a/src/RTP/RtpCodec.h b/src/RTP/RtpCodec.h index 7ff7d1de..ebcfccd4 100644 --- a/src/RTP/RtpCodec.h +++ b/src/RTP/RtpCodec.h @@ -41,12 +41,30 @@ public: class RtpRingInterface { public: typedef RingBuffer RingType; + typedef std::shared_ptr Ptr; RtpRingInterface(){} virtual ~RtpRingInterface(){} + + /** + * 获取rtp环形缓存 + * @return + */ virtual RingType::Ptr getRtpRing() const = 0; + + /** + * 设置rtp环形缓存 + * @param ring + */ virtual void setRtpRing(const RingType::Ptr &ring) = 0; - virtual void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) = 0; + + /** + * 输入rtp包 + * @param rtp rtp包 + * @param key_pos 是否为关键帧第一个rtp包 + * @return 是否为关键帧第一个rtp包 + */ + virtual bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) = 0; }; class RtpRing : public RtpRingInterface { @@ -67,8 +85,9 @@ public: _rtpRing = ring; } - void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ _rtpRing->write(rtp,key_pos); + return key_pos; } protected: RingType::Ptr _rtpRing; @@ -143,12 +162,14 @@ public: RtpCodec(){} virtual ~RtpCodec(){} - static Ptr getRtpCodecById(CodecId codecId, - uint32_t ui32Ssrc, - uint32_t ui32MtuSize, - uint32_t ui32SampleRate, - uint8_t ui8PlayloadType, - uint8_t ui8Interleaved); + static Ptr getRtpEncoderById(CodecId codecId, + uint32_t ui32Ssrc, + uint32_t ui32MtuSize, + uint32_t ui32SampleRate, + uint8_t ui8PlayloadType, + uint8_t ui8Interleaved); + + static Ptr getRtpDecoderById(CodecId codecId,uint32_t ui32SampleRate); }; diff --git a/src/Rtmp/RtmpMediaSource.h b/src/Rtmp/RtmpMediaSource.h index 55e2e9b5..1372ff89 100644 --- a/src/Rtmp/RtmpMediaSource.h +++ b/src/Rtmp/RtmpMediaSource.h @@ -85,7 +85,7 @@ public: lock_guard lock(m_mtxMap); m_metadata = _metadata; RtmpParser parser(_metadata); - m_iCfgFrameSize = parser.getTrackCount(); + m_iCfgFrameSize = parser.getTracks().size(); if(ready()){ MediaSource::regist(); m_bRegisted = true; diff --git a/src/Rtsp/RtpParser.cpp b/src/Rtsp/RtpParser.cpp index cd387724..8e28e3b9 100644 --- a/src/Rtsp/RtpParser.cpp +++ b/src/Rtsp/RtpParser.cpp @@ -53,76 +53,73 @@ static int getTimeInSDP(const string &sdp) { RtpParser::RtpParser(const string& sdp) { RtspTrack tmp[2]; int cnt = parserSDP(sdp, tmp); - if (0 == cnt) { - throw std::runtime_error("parse sdp failed"); - } - for (int i = 0; i < cnt; i++) { switch (tmp[i].type) { case TrackVideo: { - try { - onGetVideoTrack(tmp[i]); - m_bHaveVideo = true; - m_mapTracks.emplace(tmp[i].PT, tmp[i]); - } catch (std::exception &ex) { - WarnL << ex.what(); - } + onGetVideoTrack(tmp[i]); } break; case TrackAudio: { - try { - onGetAudioTrack(tmp[i]); - m_bHaveAudio = true; - m_mapTracks.emplace(tmp[i].PT, tmp[i]); - } catch (std::exception &ex) { - WarnL << ex.what(); - } + onGetAudioTrack(tmp[i]); } break; default: break; } } - if (!m_bHaveVideo && !m_bHaveAudio) { - throw std::runtime_error("不支持该RTSP媒体格式"); - } m_fDuration = getTimeInSDP(sdp); } -RtpParser::~RtpParser() { -} bool RtpParser::inputRtp(const RtpPacket::Ptr & rtp) { - auto &track = m_mapTracks[rtp->PT]; - switch (track.type) { + switch (rtp->getTrackType()) { case TrackVideo: - if (m_bHaveVideo) { - return inputVideo(rtp, track); - } - return false; + return inputVideo(rtp); case TrackAudio: - if (m_bHaveAudio) { - return inputAudio(rtp, track); - } - return false; + return inputAudio(rtp); default: return false; } } -inline bool RtpParser::inputVideo(const RtpPacket::Ptr & rtp, const RtspTrack& track) { +inline bool RtpParser::inputVideo(const RtpPacket::Ptr &rtp) { + if(_videoRtpDecoder){ + return _videoRtpDecoder->inputRtp(rtp, true); + } + return false; +} +inline bool RtpParser::inputAudio(const RtpPacket::Ptr &rtp) { + if(_audioRtpDecoder){ + return _audioRtpDecoder->inputRtp(rtp, false); + } + return false; } inline void RtpParser::onGetAudioTrack(const RtspTrack& audio) { - + _audioTrack = dynamic_pointer_cast(Track::getTrackBySdp(audio.trackSdp)); + if(_audioTrack){ + _audioRtpDecoder = RtpCodec::getRtpDecoderById(_audioTrack->getCodecId(),_audioTrack->getAudioSampleRate()); + } } inline void RtpParser::onGetVideoTrack(const RtspTrack& video) { - + _videoTrack = dynamic_pointer_cast(Track::getTrackBySdp(video.trackSdp)); + if(_videoTrack){ + _videoRtpDecoder = RtpCodec::getRtpDecoderById(_videoTrack->getCodecId(),90000); + } } -inline bool RtpParser::inputAudio(const RtpPacket::Ptr &rtppack, const RtspTrack& track) { +vector RtpParser::getTracks() const { + vector ret; + if(_videoTrack){ + ret.emplace_back(_videoTrack); + } + if(_audioTrack){ + ret.emplace_back(_audioTrack); + } + return ret; } + } /* namespace Rtsp */ } /* namespace ZL */ diff --git a/src/Rtsp/RtpParser.h b/src/Rtsp/RtpParser.h index 73ebfb0b..9bbbcb28 100644 --- a/src/Rtsp/RtpParser.h +++ b/src/Rtsp/RtpParser.h @@ -45,7 +45,8 @@ class RtpParser : public PlayerBase{ public: typedef std::shared_ptr Ptr; RtpParser(const string &sdp); - virtual ~RtpParser(); + virtual ~RtpParser(){}; + //返回值:true 代表是i帧第一个rtp包 bool inputRtp(const RtpPacket::Ptr &rtp); @@ -54,32 +55,22 @@ public: } bool isInited() const override{ - if (m_bHaveAudio && !m_strAudioCfg.size()) { - return false; - } - if (m_bHaveVideo && !m_strSPS.size()) { - return false; - } return true; } -private: - std::unordered_map m_mapTracks; + vector getTracks() const override; +private: inline void onGetAudioTrack(const RtspTrack &audio); inline void onGetVideoTrack(const RtspTrack &video); - //返回值:true 代表是i帧第一个rtp包 - inline bool inputVideo(const RtpPacket::Ptr &rtp, const RtspTrack &track); - inline bool inputAudio(const RtpPacket::Ptr &rtp, const RtspTrack &track); - - string m_strSPS; - string m_strPPS; - string m_strAudioCfg; - bool m_bHaveAudio = false; - bool m_bHaveVideo= false; + inline bool inputVideo(const RtpPacket::Ptr &rtp); + inline bool inputAudio(const RtpPacket::Ptr &rtp); +private: float m_fDuration = 0; - - recursive_mutex m_mtxCB; + AudioTrack::Ptr _audioTrack; + VideoTrack::Ptr _videoTrack; + RtpCodec::Ptr _audioRtpDecoder; + RtpCodec::Ptr _videoRtpDecoder; }; } /* namespace Rtsp */ diff --git a/src/Rtsp/RtspEncoder.h b/src/Rtsp/RtspEncoder.h index 9d037302..abd9f3b0 100644 --- a/src/Rtsp/RtspEncoder.h +++ b/src/Rtsp/RtspEncoder.h @@ -73,8 +73,8 @@ public: * @param frame 帧数据 * @param key_pos 是否为关键帧 */ - void inputFrame(const Frame::Ptr &frame,bool key_pos) override{ - _encoder->inputFrame(frame,key_pos); + bool inputFrame(const Frame::Ptr &frame,bool key_pos) override{ + return _encoder->inputFrame(frame,key_pos); } /** @@ -82,8 +82,8 @@ public: * @param rtp rtp数据包 * @param key_pos 是否为关键帧第一个rtp包 */ - void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ - _encoder->inputRtp(rtp,key_pos); + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) override{ + return _encoder->inputRtp(rtp,key_pos); } /** @@ -108,12 +108,12 @@ public: * @param mtu mtu大小,一般小于1500字节,推荐1400 */ virtual void createRtpEncoder(uint32_t ssrc, int mtu) { - _encoder = RtpCodec::getRtpCodecById(getCodecId(), - ssrc, - mtu, - _sample_rate, - _playload_type, - getTrackType() * 2); + _encoder = RtpCodec::getRtpEncoderById(getCodecId(), + ssrc, + mtu, + _sample_rate, + _playload_type, + getTrackType() * 2); } private: RtpCodec::Ptr _encoder; @@ -315,12 +315,12 @@ public: * @param frame 帧数据 * @param key_pos 是否为关键帧 */ - void inputFrame(const Frame::Ptr &frame,bool key_pos = true) override { + bool inputFrame(const Frame::Ptr &frame,bool key_pos = true) override { auto it = _sdp_map.find(frame->getTrackType()); if(it == _sdp_map.end()){ - return ; + return false; } - it->second->inputFrame(frame,key_pos); + return it->second->inputFrame(frame,key_pos); } /** @@ -328,12 +328,12 @@ public: * @param rtp rtp包 * @param key_pos 是否为关键帧的第一个rtp包 */ - void inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override { + bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos = true) override { auto it = _sdp_map.find(rtp->getTrackType()); if(it == _sdp_map.end()){ - return ; + return false; } - it->second->inputRtp(rtp,key_pos); + return it->second->inputRtp(rtp,key_pos); } /**