diff --git a/trunk/src/app/srs_app_rtc_api.cpp b/trunk/src/app/srs_app_rtc_api.cpp index c690f597f..75bde95d5 100644 --- a/trunk/src/app/srs_app_rtc_api.cpp +++ b/trunk/src/app/srs_app_rtc_api.cpp @@ -136,10 +136,16 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe string eip = r->query_get("eip"); // For client to specifies whether encrypt by SRTP. string encrypt = r->query_get("encrypt"); + // If keep_sequence is off, for client to specifies the startup sequence. + string sequence_startup = r->query_get("sequence_startup"); + // If keep_sequence is on, for client to specifies the delta value for sequence. + string sequence_delta = r->query_get("sequence_delta"); + // Whether keep sequence, overwrite the config for debugging each session. + string sequence_keep = r->query_get("sequence_keep"); - srs_trace("RTC play %s, api=%s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, encrypt=%s", - streamurl.c_str(), api.c_str(), clientip.c_str(), app.c_str(), stream_name.c_str(), remote_sdp_str.length(), - eip.c_str(), encrypt.c_str()); + srs_trace("RTC play %s, api=%s, clientip=%s, app=%s, stream=%s, offer=%dB, eip=%s, encrypt=%s, sequence(startup=%s,delta=%s,keep=%s)", + streamurl.c_str(), api.c_str(), clientip.c_str(), app.c_str(), stream_name.c_str(), remote_sdp_str.length(), eip.c_str(), encrypt.c_str(), + sequence_startup.c_str(), sequence_delta.c_str(), sequence_keep.c_str()); // TODO: FIXME: It seems remote_sdp doesn't represents the full SDP information. SrsSdp remote_sdp; @@ -189,6 +195,11 @@ srs_error_t SrsGoApiRtcPlay::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMe session->set_encrypt(encrypt != "false"); } + // Set the optional parameters from client. + session->sequence_startup = sequence_startup; + session->sequence_delta = sequence_delta; + session->sequence_keep = sequence_keep; + ostringstream os; if ((err = local_sdp.encode(os)) != srs_success) { return srs_error_wrap(err, "encode sdp"); diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 6cae8ac59..ece2dccbc 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -496,6 +496,7 @@ SrsRtcPlayer::SrsRtcPlayer(SrsRtcSession* s, int parent_cid) audio_sequence = 0; video_sequence = 0; + sequence_delta = 0; mw_msgs = 0; realtime = true; @@ -532,8 +533,17 @@ srs_error_t SrsRtcPlayer::initialize(const uint32_t& vssrc, const uint32_t& assr // TODO: FIXME: Support reload. nack_enabled_ = _srs_config->get_rtc_nack_enabled(session_->req->vhost); keep_sequence_ = _srs_config->get_rtc_keep_sequence(session_->req->vhost); - srs_trace("RTC player video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), nack=%d, keep-seq=%d", - video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, nack_enabled_, keep_sequence_); + if (!session_->sequence_startup.empty()) { + audio_sequence = video_sequence = uint16_t(::atoi(session_->sequence_startup.c_str())); + } + if (!session_->sequence_delta.empty()) { + sequence_delta = uint16_t(::atoi(session_->sequence_delta.c_str())); + } + if (!session_->sequence_keep.empty()) { + keep_sequence_ = (session_->sequence_keep == "true"); + } + srs_trace("RTC player video(ssrc=%d, pt=%d), audio(ssrc=%d, pt=%d), nack=%d, keep-seq=%d, sequence(audio=%u,video=%u,delta=%u)", + video_ssrc, video_payload_type, audio_ssrc, audio_payload_type, nack_enabled_, keep_sequence_, audio_sequence, video_sequence, sequence_delta); if (_srs_rtc_hijacker) { if ((err = _srs_rtc_hijacker->on_start_play(session_, this, session_->req)) != srs_success) { @@ -706,30 +716,36 @@ srs_error_t SrsRtcPlayer::send_packets(SrsRtcSource* source, const vectornb_bytes(); - // For audio, we transcoded AAC to opus in extra payloads. + uint16_t oseq = pkt->header.get_sequence(); if (pkt->is_audio()) { info.nn_audios++; if (!keep_sequence_) { - pkt->header.set_sequence(audio_sequence++); + // TODO: FIXME: Should keep the order by original sequence. + pkt->header.set_sequence(sequence_delta + audio_sequence++); + } else { + pkt->header.set_sequence(sequence_delta + oseq); } pkt->header.set_ssrc(audio_ssrc); pkt->header.set_payload_type(audio_payload_type); // TODO: FIXME: Padding audio to the max payload in RTP packets. + } else { + info.nn_videos++; - continue; + if (!keep_sequence_) { + // TODO: FIXME: Should keep the order by original sequence. + pkt->header.set_sequence(sequence_delta + video_sequence++); + } else { + pkt->header.set_sequence(sequence_delta + oseq); + } + pkt->header.set_ssrc(video_ssrc); + pkt->header.set_payload_type(video_payload_type); } - // For video, we should process all NALUs in samples. - info.nn_videos++; - - // For video, we should set the RTP packet informations about this consumer. - if (!keep_sequence_) { - pkt->header.set_sequence(video_sequence++); - } - pkt->header.set_ssrc(video_ssrc); - pkt->header.set_payload_type(video_payload_type); + // Detail log, should disable it in release version. + srs_info("RTC: Update PT=%u, SSRC=%#x, OSEQ=%u, SEQ=%u, Time=%u, %u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), + oseq, pkt->header.get_sequence(), pkt->header.get_timestamp(), pkt->nb_bytes()); } // By default, we send packets by sendmmsg. @@ -815,6 +831,10 @@ srs_error_t SrsRtcPlayer::do_send_packets(const std::vector& pkt // TODO: FIXME: Handle error. session_->sendonly_skt->sendto(iov->iov_base, iov->iov_len, 0); + + // Detail log, should disable it in release version. + srs_info("RTC: SEND PT=%u, SSRC=%#x, SEQ=%u, Time=%u, %u/%u bytes", pkt->header.get_payload_type(), pkt->header.get_ssrc(), + pkt->header.get_sequence(), pkt->header.get_timestamp(), pkt->nb_bytes(), iov->iov_len); } return err; diff --git a/trunk/src/app/srs_app_rtc_conn.hpp b/trunk/src/app/srs_app_rtc_conn.hpp index b4ebe2075..228dac6e7 100644 --- a/trunk/src/app/srs_app_rtc_conn.hpp +++ b/trunk/src/app/srs_app_rtc_conn.hpp @@ -206,6 +206,7 @@ private: SrsRtpRingBuffer* audio_queue_; SrsRtpRingBuffer* video_queue_; // Simulators. + uint16_t sequence_delta; int nn_simulate_nack_drop; private: // For merged-write messages. @@ -353,6 +354,11 @@ private: SrsRtcSource* source_; SrsSdp remote_sdp; SrsSdp local_sdp; +public: + // User debugging parameters, overwrite config. + std::string sequence_startup; + std::string sequence_delta; + std::string sequence_keep; private: bool blackhole; sockaddr_in* blackhole_addr;