diff --git a/src/Rtmp/RtmpMediaSource.h b/src/Rtmp/RtmpMediaSource.h index 03975fcc..f37918e3 100644 --- a/src/Rtmp/RtmpMediaSource.h +++ b/src/Rtmp/RtmpMediaSource.h @@ -100,9 +100,8 @@ public: * 设置metadata */ virtual void setMetaData(const AMFValue &metadata) { - lock_guard lock(_mtx); _metadata = metadata; - if(_ring){ + if (_ring) { regist(); } } @@ -121,19 +120,19 @@ public: * @param key 是否为关键帧 */ void onWrite(const RtmpPacket::Ptr &pkt, bool key = true) override { - lock_guard lock(_mtx); - if(pkt->type_id == MSG_VIDEO){ - //有视频,那么启用GOP缓存 - _have_video = true; + //保存当前时间戳 + switch (pkt->type_id) { + case MSG_VIDEO : _track_stamps[TrackVideo] = pkt->time_stamp, _have_video = true; break; + case MSG_AUDIO : _track_stamps[TrackAudio] = pkt->time_stamp; break; + default : break; } + if (pkt->isCfgFrame()) { + lock_guard lock(_mtx); _config_frame_map[pkt->type_id] = pkt; return; } - //保存当前时间戳 - _track_stamps_map[pkt->type_id] = pkt->time_stamp; - if (!_ring) { weak_ptr weakSelf = dynamic_pointer_cast(shared_from_this()); auto lam = [weakSelf](const EventPoller::Ptr &, int size, bool) { @@ -144,9 +143,8 @@ public: strongSelf->onReaderChanged(size); }; - //rtmp包缓存最大允许512个,如果是纯视频(25fps)大概为20秒数据 - //但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍 - //而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值 + //GOP默认缓冲512组RTMP包,每组RTMP包时间戳相同(如果开启合并写了,那么每组为合并写时间内的RTMP包), + //每次遇到关键帧第一个RTMP包,则会清空GOP缓存(因为有新的关键帧了,同样可以实现秒开) _ring = std::make_shared(_ring_size,std::move(lam)); onReaderChanged(0); @@ -161,19 +159,23 @@ public: * 获取当前时间戳 */ uint32_t getTimeStamp(TrackType trackType) override { - lock_guard lock(_mtx); - switch (trackType) { - case TrackVideo: - return _track_stamps_map[MSG_VIDEO]; - case TrackAudio: - return _track_stamps_map[MSG_AUDIO]; - default: - return MAX(_track_stamps_map[MSG_VIDEO], _track_stamps_map[MSG_AUDIO]); + assert(trackType >= TrackInvalid && trackType < TrackMax); + if (trackType != TrackInvalid) { + //获取某track的时间戳 + return _track_stamps[trackType]; } + + //获取所有track的最小时间戳 + uint32_t ret = UINT32_MAX; + for (auto &stamp : _track_stamps) { + if (stamp > 0 && stamp < ret) { + ret = stamp; + } + } + return ret; } private: - /** * 批量flush rtmp包时触发该函数 * @param rtmp_list rtmp包列表 @@ -194,12 +196,13 @@ private: } private: - int _ring_size; bool _have_video = false; - mutable recursive_mutex _mtx; + int _ring_size; + uint32_t _track_stamps[TrackMax] = {0}; AMFValue _metadata; RingType::Ptr _ring; - unordered_map _track_stamps_map; + + mutable recursive_mutex _mtx; unordered_map _config_frame_map; }; diff --git a/src/Rtsp/RtspMediaSource.h b/src/Rtsp/RtspMediaSource.h index 4e2657e0..4bf4ca28 100644 --- a/src/Rtsp/RtspMediaSource.h +++ b/src/Rtsp/RtspMediaSource.h @@ -83,7 +83,8 @@ public: * 获取相应轨道的ssrc */ virtual uint32_t getSsrc(TrackType trackType) { - auto track = _sdp_parser.getTrack(trackType); + assert(trackType >= 0 && trackType < TrackMax); + auto track = _tracks[trackType]; if (!track) { return 0; } @@ -94,7 +95,8 @@ public: * 获取相应轨道的seqence */ virtual uint16_t getSeqence(TrackType trackType) { - auto track = _sdp_parser.getTrack(trackType); + assert(trackType >= 0 && trackType < TrackMax); + auto track = _tracks[trackType]; if (!track) { return 0; } @@ -105,28 +107,33 @@ public: * 获取相应轨道的时间戳,单位毫秒 */ uint32_t getTimeStamp(TrackType trackType) override { - auto track = _sdp_parser.getTrack(trackType); - if (track) { - return track->_time_stamp; + assert(trackType >= TrackInvalid && trackType < TrackMax); + if (trackType != TrackInvalid) { + //获取某track的时间戳 + auto track = _tracks[trackType]; + if (track) { + return track->_time_stamp; + } } - auto tracks = _sdp_parser.getAvailableTrack(); - switch (tracks.size()) { - case 0: - return 0; - case 1: - return tracks[0]->_time_stamp; - default: - return MIN(tracks[0]->_time_stamp, tracks[1]->_time_stamp); + + //获取所有track的最小时间戳 + uint32_t ret = UINT32_MAX; + for (auto &track : _tracks) { + if (track && track->_time_stamp < ret) { + ret = track->_time_stamp; + } } + return ret; } /** * 更新时间戳 */ - void setTimeStamp(uint32_t uiStamp) override { - auto tracks = _sdp_parser.getAvailableTrack(); - for (auto &track : tracks) { - track->_time_stamp = uiStamp; + void setTimeStamp(uint32_t stamp) override { + for (auto &track : _tracks) { + if (track) { + track->_time_stamp = stamp; + } } } @@ -135,8 +142,10 @@ public: */ virtual void setSdp(const string &sdp) { _sdp = sdp; - _sdp_parser.load(sdp); - _have_video = (bool)_sdp_parser.getTrack(TrackVideo); + SdpParser sdp_parser(sdp); + _tracks[TrackVideo] = sdp_parser.getTrack(TrackVideo); + _tracks[TrackAudio] = sdp_parser.getTrack(TrackAudio); + _have_video = (bool) _tracks[TrackVideo]; if (_ring) { regist(); } @@ -148,7 +157,8 @@ public: * @param keyPos 该包是否为关键帧的第一个包 */ void onWrite(const RtpPacket::Ptr &rtp, bool keyPos) override { - auto track = _sdp_parser.getTrack(rtp->type); + assert(rtp->type >= 0 && rtp->type < TrackMax); + auto track = _tracks[rtp->type]; if (track) { track->_seq = rtp->sequence; track->_time_stamp = rtp->timeStamp; @@ -163,9 +173,8 @@ public: } strongSelf->onReaderChanged(size); }; - //rtp包缓存最大允许2048个,大概最多3MB数据 - //但是这个是GOP缓存的上限值,真实的GOP缓存大小等于两个I帧之间的包数的两倍 - //而且每次遇到I帧,则会清空GOP缓存,所以真实的GOP缓存远小于此值 + //GOP默认缓冲512组RTP包,每组RTP包时间戳相同(如果开启合并写了,那么每组为合并写时间内的RTP包), + //每次遇到关键帧第一个RTP包,则会清空GOP缓存(因为有新的关键帧了,同样可以实现秒开) _ring = std::make_shared(_ring_size, std::move(lam)); onReaderChanged(0); if (!_sdp.empty()) { @@ -176,7 +185,6 @@ public: } private: - /** * 批量flush rtp包时触发该函数 * @param rtp_list rtp包列表 @@ -195,12 +203,13 @@ private: onNoneReader(); } } + private: - int _ring_size; bool _have_video = false; - SdpParser _sdp_parser; + int _ring_size; string _sdp; RingType::Ptr _ring; + SdpTrack::Ptr _tracks[TrackMax]; }; } /* namespace mediakit */