Skip to content

Commit

Permalink
Fix #3167: WebRTC: Play stucked when republish. v4.0.260
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Sep 3, 2022
1 parent 4a225c5 commit 34196ea
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 4 deletions.
1 change: 1 addition & 0 deletions trunk/doc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions trunk/src/app/srs_app_rtc_conn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,12 @@ srs_error_t SrsRtcPlayStream::initialize(SrsRequest* req, std::map<uint32_t, Srs

void SrsRtcPlayStream::on_stream_change(SrsRtcSourceDescription* desc)
{
if (!desc) return;

// Refresh the relation for audio.
// TODO: FIMXE: Match by label?
if (desc && desc->audio_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;

Expand All @@ -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;
Expand All @@ -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<SrsRtcTrackDescription*>::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)
Expand Down
71 changes: 71 additions & 0 deletions trunk/src/app/srs_app_rtc_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2546,12 +2546,53 @@ srs_error_t SrsRtcVideoRecvTrack::check_send_nacks()
return err;
}

SrsRtcJitter::SrsRtcJitter(uint32_t base)
{
pkt_base_ = pkt_last_ = 0;
correct_last_ = correct_base_ = 0;
base_ = base;
init_ = false;
}

SrsRtcJitter::~SrsRtcJitter()
{
}

uint32_t SrsRtcJitter::correct(uint32_t ts)
{
if (!init_) {
init_ = true;
correct_base_ = base_;
srs_trace("RTC: Jitter init base=%u, ts=%u", 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;
init_ = false;
// 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 {
Expand All @@ -2566,6 +2607,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)
Expand Down Expand Up @@ -2616,6 +2658,23 @@ std::string SrsRtcSendTrack::get_track_id()
return track_desc_->id_;
}

void SrsRtcSendTrack::rebuild_packet(SrsRtpPacket* pkt)
{
// Rebuild the sequence number.
if (!init_) {
init_ = true;
// 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;
Expand Down Expand Up @@ -2693,10 +2752,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;
}

Expand Down Expand Up @@ -2737,10 +2802,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;
}

Expand Down
31 changes: 30 additions & 1 deletion trunk/src/app/srs_app_rtc_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -579,16 +579,43 @@ class SrsRtcVideoRecvTrack : public SrsRtcRecvTrack, public ISrsRtspPacketDecode
virtual srs_error_t check_send_nacks();
};

class SrsRtcJitter
{
private:
// The ts about packet.
uint32_t pkt_base_;
uint32_t pkt_last_;
// The ts after corrected.
uint32_t correct_base_;
uint32_t correct_last_;
// The base timestamp by config, start from it.
uint32_t base_;
// Whether initialized. Note that we should not use correct_base_(0) as init state, because it might flip back.
bool init_;
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:
// The owner connection for this track.
SrsRtcConnection* session_;
// NACK ARQ ring buffer.
SrsRtpRingBuffer* rtp_queue_;
protected:
// Current sequence number.
uint64_t seqno_;
// Whether initialized. Note that we should not use seqno_(0) as init state, because it might flip back.
bool init_;
// The jitter to correct ts.
SrsRtcJitter* jitter_;
private:
// By config, whether no copy.
bool nack_no_copy_;
Expand All @@ -605,6 +632,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.
Expand Down
2 changes: 1 addition & 1 deletion trunk/src/core/srs_core_version4.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@

#define VERSION_MAJOR 4
#define VERSION_MINOR 0
#define VERSION_REVISION 259
#define VERSION_REVISION 260

#endif
4 changes: 4 additions & 0 deletions trunk/src/kernel/srs_kernel_rtc_rtp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 34196ea

Please sign in to comment.