From 6dd77923cae895608021a2accf3e050fe1aaf6da Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 19 Jul 2020 10:26:05 +0800 Subject: [PATCH] RTC: Fix rtmp to rtc bug --- trunk/src/app/srs_app_rtc_conn.cpp | 38 ++++++------ trunk/src/app/srs_app_rtc_source.cpp | 87 ++++++++++++++++++++++++++-- trunk/src/app/srs_app_rtc_source.hpp | 16 +++++ 3 files changed, 119 insertions(+), 22 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index b1e852c99..71cecd02d 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1554,8 +1554,6 @@ void SrsRtcPublishStream::update_send_report_time(uint32_t ssrc, const SrsNtp& n } } -uint32_t SrsRtcConnection::ssrc_num = 0; - SrsRtcConnection::SrsRtcConnection(SrsRtcServer* s) { req = NULL; @@ -2516,11 +2514,6 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S return srs_error_wrap(err, "fetch rtc source"); } - // TODO: FIXME: Avoid SSRC collision. - if (!ssrc_num) { - ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid(); - } - for (size_t i = 0; i < remote_sdp.media_descs_.size(); ++i) { const SrsMediaDesc& remote_media_desc = remote_sdp.media_descs_[i]; // Whether feature enabled in remote extmap. @@ -2536,12 +2529,17 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S } std::vector track_descs; + std::vector remote_rtcp_fb; if (remote_media_desc.is_audio()) { // TODO: check opus format specific param std::vector payloads = remote_media_desc.find_media_with_encoding_name("opus"); if (payloads.empty()) { return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found opus payload type"); } + + SrsMediaPayloadType payload = payloads.at(0); + remote_rtcp_fb = payload.rtcp_fb_; + track_descs = source->get_track_desc("audio", "opus"); } else if (remote_media_desc.is_video()) { // TODO: check opus format specific param @@ -2549,25 +2547,34 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S if (payloads.empty()) { return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found opus payload type"); } + + SrsMediaPayloadType payload = payloads.at(0); + remote_rtcp_fb = payload.rtcp_fb_; + track_descs = source->get_track_desc("video", "H264"); } for (int i = 0; i < track_descs.size(); ++i) { SrsRtcTrackDescription* track = track_descs[i]->copy(); + track->mid_ = remote_media_desc.mid_; uint32_t publish_ssrc = track->ssrc_; track->media_->rtcp_fbs_.clear(); - if (nack_enabled) { - track->media_->rtcp_fbs_.push_back("nack"); - track->media_->rtcp_fbs_.push_back("nack pli"); + track->extmaps_.clear(); + + for (int j = 0; j < (int)remote_rtcp_fb.size(); j++) { + if (nack_enabled) { + if (remote_rtcp_fb.at(j) == "nack" || remote_rtcp_fb.at(j) == "nack pli" || remote_rtcp_fb.at(j) == "transport-cc") { + track->media_->rtcp_fbs_.push_back(remote_rtcp_fb.at(j)); + } + } } - track->extmaps_.clear(); if (twcc_enabled && remote_twcc_id) { track->add_rtp_extension_desc(remote_twcc_id, kTWCCExt); } - track->ssrc_ = ++ssrc_num; + track->ssrc_ = SrsRtcSSRCGenerator::instance()->generate_ssrc(); // TODO: FIXME: set audio_payload rtcp_fbs_, // according by whether downlink is support transport algorithms. // TODO: FIXME: if we support downlink RTX, MUST assign rtx_ssrc_, rtx_pt, rtx_apt @@ -2603,11 +2610,6 @@ srs_error_t SrsRtcConnection::fetch_source_capability(SrsRequest* req, std::map< return srs_error_wrap(err, "fetch rtc source"); } - // TODO: FIXME: Avoid SSRC collision. - if (!ssrc_num) { - ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid(); - } - std::vector track_descs = source->get_track_desc("audio", "opus"); std::vector video_track_desc = source->get_track_desc("video", "H264"); @@ -2629,7 +2631,7 @@ srs_error_t SrsRtcConnection::fetch_source_capability(SrsRequest* req, std::map< track->add_rtp_extension_desc(local_twcc_id, kTWCCExt); } - track->ssrc_ = ++ssrc_num; + track->ssrc_ = SrsRtcSSRCGenerator::instance()->generate_ssrc(); // TODO: FIXME: set audio_payload rtcp_fbs_, // according by whether downlink is support transport algorithms. // TODO: FIXME: if we support downlink RTX, MUST assign rtx_ssrc_, rtx_pt, rtx_apt diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 31d4f6e65..73342d385 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -23,6 +23,8 @@ #include +#include + #include #include #include @@ -37,13 +39,18 @@ #include #include #include +#include #ifdef SRS_FFMPEG_FIT #include #endif -const int kChannel = 2; -const int kSamplerate = 48000; +const int kAudioPayloadType = 111; +const int kAudioChannel = 2; +const int kAudioSamplerate = 48000; + +const int kVideoPayloadType = 102; +const int kVideoSamplerate = 90000; // An AAC packet may be transcoded to many OPUS packets. const int kMaxOpusPackets = 8; @@ -284,6 +291,7 @@ SrsRtcStream::SrsRtcStream() { _can_publish = true; publish_stream_ = NULL; + stream_desc_ = NULL; req = NULL; #ifdef SRS_FFMPEG_FIT @@ -291,7 +299,6 @@ SrsRtcStream::SrsRtcStream() #else bridger_ = new SrsRtcDummyBridger(); #endif - stream_desc_ = NULL; } SrsRtcStream::~SrsRtcStream() @@ -498,7 +505,7 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcStream* source) req = NULL; source_ = source; format = new SrsRtmpFormat(); - codec = new SrsAudioRecode(kChannel, kSamplerate); + codec = new SrsAudioRecode(kAudioChannel, kAudioSamplerate); discard_aac = false; discard_bframe = false; merge_nalus = false; @@ -506,6 +513,39 @@ SrsRtcFromRtmpBridger::SrsRtcFromRtmpBridger(SrsRtcStream* source) audio_timestamp = 0; audio_sequence = 0; video_sequence = 0; + + SrsRtcStreamDescription* stream_desc = new SrsRtcStreamDescription(); + SrsAutoFree(SrsRtcStreamDescription, stream_desc); + + // audio track description + if (true) { + SrsRtcTrackDescription* audio_track_desc = new SrsRtcTrackDescription(); + audio_track_desc->type_ = "audio"; + audio_track_desc->id_ = "audio-" + srs_random_str(8); + + audio_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc(); + audio_track_desc->ssrc_ = audio_ssrc; + audio_track_desc->direction_ = "recvonly"; + + audio_track_desc->media_ = new SrsAudioPayload(kAudioPayloadType, "opus", kAudioSamplerate, kAudioChannel); + stream_desc->audio_track_desc_ = audio_track_desc->copy(); + } + + // video track description + if (true) { + SrsRtcTrackDescription* video_track_desc = new SrsRtcTrackDescription(); + video_track_desc->type_ = "video"; + video_track_desc->id_ = "video-" + srs_random_str(8); + + video_ssrc = SrsRtcSSRCGenerator::instance()->generate_ssrc(); + video_track_desc->ssrc_ = video_ssrc; + video_track_desc->direction_ = "recvonly"; + + video_track_desc->media_ = new SrsVideoPayload(kVideoPayloadType, "H264", kVideoSamplerate); + stream_desc->video_track_descs_.push_back(video_track_desc->copy()); + } + + source_->set_stream_desc(stream_desc); } SrsRtcFromRtmpBridger::~SrsRtcFromRtmpBridger() @@ -672,6 +712,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_opus(char* data, int size, SrsRtpPack srs_error_t err = srs_success; SrsRtpPacket2* pkt = new SrsRtpPacket2(); + pkt->header.set_payload_type(kAudioPayloadType); + pkt->header.set_ssrc(audio_ssrc); pkt->frame_type = SrsFrameTypeAudio; pkt->header.set_marker(true); pkt->header.set_sequence(audio_sequence++); @@ -813,6 +855,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_stap_a(SrsRtcStream* source, SrsShare } SrsRtpPacket2* pkt = new SrsRtpPacket2(); + pkt->header.set_payload_type(kVideoPayloadType); + pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; pkt->header.set_marker(false); pkt->header.set_sequence(video_sequence++); @@ -884,6 +928,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const if (nn_bytes < kRtpMaxPayloadSize) { // Package NALUs in a single RTP packet. SrsRtpPacket2* pkt = new SrsRtpPacket2(); + pkt->header.set_payload_type(kVideoPayloadType); + pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); @@ -914,6 +960,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_nalus(SrsSharedPtrMessage* msg, const } SrsRtpPacket2* pkt = new SrsRtpPacket2(); + pkt->header.set_payload_type(kVideoPayloadType); + pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); @@ -940,6 +988,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_single_nalu(SrsSharedPtrMessage* msg, srs_error_t err = srs_success; SrsRtpPacket2* pkt = new SrsRtpPacket2(); + pkt->header.set_payload_type(kVideoPayloadType); + pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); @@ -970,6 +1020,8 @@ srs_error_t SrsRtcFromRtmpBridger::package_fu_a(SrsSharedPtrMessage* msg, SrsSam int packet_size = srs_min(nb_left, fu_payload_size); SrsRtpPacket2* pkt = new SrsRtpPacket2(); + pkt->header.set_payload_type(kVideoPayloadType); + pkt->header.set_ssrc(video_ssrc); pkt->frame_type = SrsFrameTypeVideo; pkt->header.set_sequence(video_sequence++); pkt->header.set_timestamp(msg->timestamp * 90); @@ -1700,3 +1752,30 @@ srs_error_t SrsRtcVideoSendTrack::on_rtcp(SrsRtpPacket2* pkt) return err; } +SrsRtcSSRCGenerator* SrsRtcSSRCGenerator::_instance = NULL; + +SrsRtcSSRCGenerator::SrsRtcSSRCGenerator() +{ + ssrc_num = 0; +} + +SrsRtcSSRCGenerator::~SrsRtcSSRCGenerator() +{ +} + +SrsRtcSSRCGenerator* SrsRtcSSRCGenerator::instance() +{ + if (!_instance) { + _instance = new SrsRtcSSRCGenerator(); + } + return _instance; +} + +uint32_t SrsRtcSSRCGenerator::generate_ssrc() +{ + if (!ssrc_num) { + ssrc_num = ::getpid() * 10000 + ::getpid() * 100 + ::getpid(); + } + + return ++ssrc_num; +} diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index f23125a24..f950939e1 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -211,6 +211,8 @@ private: uint32_t audio_timestamp; uint16_t audio_sequence; uint16_t video_sequence; + uint32_t audio_ssrc; + uint32_t video_ssrc; public: SrsRtcFromRtmpBridger(SrsRtcStream* source); virtual ~SrsRtcFromRtmpBridger(); @@ -473,5 +475,19 @@ public: virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt); }; +class SrsRtcSSRCGenerator +{ +private: + static SrsRtcSSRCGenerator* _instance; +private: + uint32_t ssrc_num; +private: + SrsRtcSSRCGenerator(); + virtual ~SrsRtcSSRCGenerator(); +public: + static SrsRtcSSRCGenerator* instance(); + uint32_t generate_ssrc(); +}; + #endif