diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 95683650c3b..f27de73d041 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 4.0 Changelog +* v4.0, 2022-09-03, For [#3167](https://github.com/ossrs/srs/issues/3167): WebRTC: Play stucked when republish. v4.0.260 * v4.0, 2022-09-02, For [#307](https://github.com/ossrs/srs/issues/307): WebRTC: Support use domain name as CANDIDATE. v4.0.259 * v4.0, 2022-08-29, Copy libxml2-dev for FFmpeg. v4.0.258 * v4.0, 2022-08-24, STAT: Support config server_id and generate one if empty. v4.0.257 diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 1fd57883854..7eed2754e18 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -510,10 +510,12 @@ srs_error_t SrsRtcPlayStream::initialize(SrsRequest* req, std::mapaudio_track_desc_ && audio_tracks_.size() == 1) { - if (! audio_tracks_.empty()) { + if (!audio_tracks_.empty()) { uint32_t ssrc = desc->audio_track_desc_->ssrc_; SrsRtcAudioSendTrack* track = audio_tracks_.begin()->second; @@ -525,7 +527,7 @@ void SrsRtcPlayStream::on_stream_change(SrsRtcSourceDescription* desc) // Refresh the relation for video. // TODO: FIMXE: Match by label? if (desc && desc->video_track_descs_.size() == 1) { - if (! video_tracks_.empty()) { + if (!video_tracks_.empty()) { SrsRtcTrackDescription* vdesc = desc->video_track_descs_.at(0); uint32_t ssrc = vdesc->ssrc_; SrsRtcVideoSendTrack* track = video_tracks_.begin()->second; @@ -534,6 +536,15 @@ void SrsRtcPlayStream::on_stream_change(SrsRtcSourceDescription* desc) video_tracks_.insert(make_pair(ssrc, track)); } } + + // Request keyframe(PLI) when stream changed. + if (desc->audio_track_desc_) { + pli_worker_->request_keyframe(desc->audio_track_desc_->ssrc_, cid_); + } + for (vector::iterator it = desc->video_track_descs_.begin(); it != desc->video_track_descs_.end(); ++it) { + SrsRtcTrackDescription* vdesc = *it; + pli_worker_->request_keyframe(vdesc->ssrc_, cid_); + } } srs_error_t SrsRtcPlayStream::on_reload_vhost_play(string vhost) diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index ea1082c3190..1f2136527d9 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -2546,12 +2546,47 @@ srs_error_t SrsRtcVideoRecvTrack::check_send_nacks() return err; } +SrsRtcJitter::SrsRtcJitter(uint32_t base) +{ + pkt_base_ = pkt_last_ = 0; + correct_last_ = 0; + correct_base_ = base; +} + +SrsRtcJitter::~SrsRtcJitter() +{ +} + +uint32_t SrsRtcJitter::correct(uint32_t ts) +{ + if (!correct_base_) correct_base_ = ts; + if (!pkt_base_) pkt_base_ = ts; + + if (pkt_last_) { + int32_t distance = srs_rtp_ts_distance(ts, pkt_last_); + static int32_t max_deviation = 90 * 3 * 1000; + if (distance > max_deviation || distance < -1 * max_deviation) { + srs_trace("RTC: Jitter rebase ts=%u, last=%u, distance=%d, pkt-base=%u/%u, correct-base=%u/%u", ts, pkt_last_, distance, pkt_base_, ts, correct_base_, correct_last_); + pkt_base_ = ts; + correct_base_ = correct_last_; + } + } + pkt_last_ = ts; + + correct_last_ = correct_base_ + ts - pkt_base_; + return correct_last_; +} + SrsRtcSendTrack::SrsRtcSendTrack(SrsRtcConnection* session, SrsRtcTrackDescription* track_desc, bool is_audio) { session_ = session; track_desc_ = track_desc->copy(); nack_no_copy_ = false; + seqno_ = 0; + // Make a different start of sequence number, for debugging. + jitter_ = new SrsRtcJitter(track_desc_->type_ == "audio" ? 10000 : 20000); + if (is_audio) { rtp_queue_ = new SrsRtpRingBuffer(100); } else { @@ -2566,6 +2601,7 @@ SrsRtcSendTrack::~SrsRtcSendTrack() srs_freep(rtp_queue_); srs_freep(track_desc_); srs_freep(nack_epp); + srs_freep(jitter_); } bool SrsRtcSendTrack::has_ssrc(uint32_t ssrc) @@ -2616,6 +2652,22 @@ std::string SrsRtcSendTrack::get_track_id() return track_desc_->id_; } +void SrsRtcSendTrack::rebuild_packet(SrsRtpPacket* pkt) +{ + // Rebuild the sequence number. + if (!seqno_) { + // Make a different start of sequence number, for debugging. + seqno_ = track_desc_->type_ == "audio" ? 1000 : 2000; + srs_trace("RTC: Seqno rebuild %s track=%s, ssrc=%d, seqno=%d to %d", track_desc_->type_.c_str(), track_desc_->id_.c_str(), + pkt->header.get_ssrc(), pkt->header.get_sequence(), seqno_); + } + pkt->header.set_sequence(seqno_++); + + // Rebuild the timestamp. + uint32_t ts = pkt->header.get_timestamp(); + pkt->header.set_timestamp(jitter_->correct(ts)); +} + srs_error_t SrsRtcSendTrack::on_nack(SrsRtpPacket** ppkt) { srs_error_t err = srs_success; @@ -2693,10 +2745,16 @@ srs_error_t SrsRtcAudioSendTrack::on_rtp(SrsRtpPacket* pkt) // TODO: FIXME: Should update PT for RTX. } + // Rebuild the sequence number and timestamp of packet, see https://github.com/ossrs/srs/issues/3167 + rebuild_packet(pkt); + if ((err = session_->do_send_packet(pkt)) != srs_success) { return srs_error_wrap(err, "raw send"); } + srs_info("RTC: Send audio ssrc=%d, seqno=%d, keyframe=%d, ts=%u", pkt->header.get_ssrc(), + pkt->header.get_sequence(), pkt->is_keyframe(), pkt->header.get_timestamp()); + return err; } @@ -2737,10 +2795,16 @@ srs_error_t SrsRtcVideoSendTrack::on_rtp(SrsRtpPacket* pkt) // TODO: FIXME: Should update PT for RTX. } + // Rebuild the sequence number and timestamp of packet, see https://github.com/ossrs/srs/issues/3167 + rebuild_packet(pkt); + if ((err = session_->do_send_packet(pkt)) != srs_success) { return srs_error_wrap(err, "raw send"); } + srs_info("RTC: Send video ssrc=%d, seqno=%d, keyframe=%d, ts=%u", pkt->header.get_ssrc(), + pkt->header.get_sequence(), pkt->is_keyframe(), pkt->header.get_timestamp()); + return err; } diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index c4095946dcb..2f4e9a63c34 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -579,9 +579,23 @@ class SrsRtcVideoRecvTrack : public SrsRtcRecvTrack, public ISrsRtspPacketDecode virtual srs_error_t check_send_nacks(); }; +class SrsRtcJitter +{ +private: + uint32_t pkt_base_; + uint32_t pkt_last_; + uint32_t correct_base_; + uint32_t correct_last_; +public: + SrsRtcJitter(uint32_t base); + virtual ~SrsRtcJitter(); +public: + uint32_t correct(uint32_t ts); +}; + class SrsRtcSendTrack { -protected: +public: // send track description SrsRtcTrackDescription* track_desc_; protected: @@ -589,6 +603,11 @@ class SrsRtcSendTrack SrsRtcConnection* session_; // NACK ARQ ring buffer. SrsRtpRingBuffer* rtp_queue_; +protected: + // Current sequence number. + uint64_t seqno_; + // The jitter to correct ts. + SrsRtcJitter* jitter_; private: // By config, whether no copy. bool nack_no_copy_; @@ -605,6 +624,8 @@ class SrsRtcSendTrack bool set_track_status(bool active); bool get_track_status(); std::string get_track_id(); +protected: + void rebuild_packet(SrsRtpPacket* pkt); public: // Note that we can set the pkt to NULL to avoid copy, for example, if the NACK cache the pkt and // set to NULL, nack nerver copy it but set the pkt to NULL. diff --git a/trunk/src/core/srs_core_version4.hpp b/trunk/src/core/srs_core_version4.hpp index f9a5e16efc0..1c33376453c 100644 --- a/trunk/src/core/srs_core_version4.hpp +++ b/trunk/src/core/srs_core_version4.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 4 #define VERSION_MINOR 0 -#define VERSION_REVISION 259 +#define VERSION_REVISION 260 #endif diff --git a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp index 47553105a70..31c1053c679 100644 --- a/trunk/src/kernel/srs_kernel_rtc_rtp.hpp +++ b/trunk/src/kernel/srs_kernel_rtc_rtp.hpp @@ -61,6 +61,10 @@ inline int16_t srs_rtp_seq_distance(const uint16_t& prev_value, const uint16_t& { return (int16_t)(value - prev_value); } +inline int32_t srs_rtp_ts_distance(const uint32_t& prev_value, const uint32_t& value) +{ + return (int32_t)(value - prev_value); +} // For map to compare the sequence of RTP. struct SrsSeqCompareLess {