diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index bc379927b0..1cf15d4b3b 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -646,6 +646,8 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vectoris_audio()) { // TODO: FIXME: Any simple solution? SrsRtcAudioSendTrack* audio_track = audio_tracks_[pkt->header.get_ssrc()]; + // update pt with sdp payload type, for each player + pkt->header.set_payload_type(audio_track->get_track_media_pt()); if ((err = audio_track->on_rtp(pkt, info)) != srs_success) { return srs_error_wrap(err, "audio track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); } @@ -654,6 +656,8 @@ srs_error_t SrsRtcPlayStream::send_packets(SrsRtcStream* source, const vectorheader.get_ssrc()]; + // update pt with sdp payload type, for each player + pkt->header.set_payload_type(video_track->get_track_media_pt()); if ((err = video_track->on_rtp(pkt, info)) != srs_success) { return srs_error_wrap(err, "video track, SSRC=%u, SEQ=%u", pkt->header.get_ssrc(), pkt->header.get_sequence()); } @@ -1815,6 +1819,14 @@ srs_error_t SrsRtcConnection::add_player(SrsRequest* req, const SrsSdp& remote_s return srs_error_wrap(err, "create player"); } + // release resource + for (std::map::iterator iter = play_sub_relations.begin(); iter != play_sub_relations.end(); ++iter) + { + SrsRtcTrackDescription* track = iter->second; + srs_freep(track); + } + play_sub_relations.clear(); + return err; } @@ -2917,6 +2929,7 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S bool nack_enabled = _srs_config->get_rtc_nack_enabled(req->vhost); bool twcc_enabled = _srs_config->get_rtc_twcc_enabled(req->vhost); + bool has_42e01f = srs_sdp_has_h264_profile(remote_sdp, "42e01f"); SrsRtcStream* source = NULL; if ((err = _srs_rtc_sources->fetch_or_create(req, &source)) != srs_success) { @@ -2925,6 +2938,10 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S for (size_t i = 0; i < remote_sdp.media_descs_.size(); ++i) { const SrsMediaDesc& remote_media_desc = remote_sdp.media_descs_[i]; + + SrsRtcTrackDescription* track_desc = new SrsRtcTrackDescription(); + SrsAutoFree(SrsRtcTrackDescription, track_desc); + // Whether feature enabled in remote extmap. int remote_twcc_id = 0; if (true) { @@ -2938,34 +2955,65 @@ 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()) { + SrsRtcTrackDescription* source_track_desc = source->get_track_desc("audio", "opus").at(0); + track_desc->ssrc_ = source_track_desc->ssrc_; + // 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_; + for (std::vector::iterator iter = payloads.begin(); iter != payloads.end(); ++iter) { + // if the playload is opus, and the encoding_param_ is channel + SrsAudioPayload* audio_payload = new SrsAudioPayload(iter->payload_type_, iter->encoding_name_, iter->clock_rate_, ::atol(iter->encoding_param_.c_str())); + audio_payload->set_opus_param_desc(iter->format_specific_param_); + audio_payload->rtcp_fbs_ = iter->rtcp_fb_; - track_descs = source->get_track_desc("audio", "opus"); + track_desc->type_ = "audio"; + track_desc->set_codec_payload((SrsCodecPayload*)audio_payload); + // Only choose one match opus codec. + break; + } + track_descs.push_back(track_desc); } else if (remote_media_desc.is_video()) { - // TODO: check opus format specific param + SrsRtcTrackDescription* source_track_desc = source->get_track_desc("video", "H264").at(0); + track_desc->ssrc_ = source_track_desc->ssrc_; + + // TODO: check H264 format specific param std::vector payloads = remote_media_desc.find_media_with_encoding_name("H264"); if (payloads.empty()) { return srs_error_new(ERROR_RTC_SDP_EXCHANGE, "no valid found h264 payload type"); } - SrsMediaPayloadType payload = payloads.at(0); - remote_rtcp_fb = payload.rtcp_fb_; + for (std::vector::iterator iter = payloads.begin(); iter != payloads.end(); ++iter) { + H264SpecificParam h264_param; + if ((err = srs_parse_h264_fmtp(iter->format_specific_param_, h264_param)) != srs_success) { + srs_error_reset(err); continue; + } + + // If not exists 42e01f, we pick up any profile such as 42001f. + bool profile_matched = (!has_42e01f || h264_param.profile_level_id == "42e01f"); - track_descs = source->get_track_desc("video", "H264"); + // Try to pick the "best match" H.264 payload type. + if (h264_param.packetization_mode == "1" && h264_param.level_asymmerty_allow == "1" && profile_matched) { + SrsVideoPayload* video_payload = new SrsVideoPayload(iter->payload_type_, iter->encoding_name_, iter->clock_rate_); + video_payload->set_h264_param_desc(iter->format_specific_param_); + video_payload->rtcp_fbs_ = iter->rtcp_fb_; + + track_desc->type_ = "video"; + track_desc->set_codec_payload((SrsCodecPayload*)video_payload); + // Only choose first match H.264 payload type. + break; + } + } + track_descs.push_back(track_desc); } for (int i = 0; i < (int)track_descs.size(); ++i) { SrsRtcTrackDescription* track = track_descs[i]->copy(); - track->mid_ = remote_media_desc.mid_; + track->set_mid(remote_media_desc.mid_); uint32_t publish_ssrc = track->ssrc_; vector rtcp_fb; @@ -2984,8 +3032,6 @@ srs_error_t SrsRtcConnection::negotiate_play_capability(SrsRequest* req, const S } } - 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 6beb54efc2..93ec2e26e2 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -1248,7 +1248,7 @@ SrsMediaPayloadType SrsVideoPayload::generate_media_payload_type() std::ostringstream format_specific_param; if (!h264_param_.level_asymmerty_allow.empty()) { - format_specific_param << "level-asymmetry-allowed=" << h264_param_.level_asymmerty_allow; + format_specific_param << ";level-asymmetry-allowed=" << h264_param_.level_asymmerty_allow; } if (!h264_param_.packetization_mode.empty()) { format_specific_param << ";packetization-mode=" << h264_param_.packetization_mode; @@ -1258,6 +1258,7 @@ SrsMediaPayloadType SrsVideoPayload::generate_media_payload_type() } media_payload_type.format_specific_param_ = format_specific_param.str(); + media_payload_type.format_specific_param_ = media_payload_type.format_specific_param_.substr(1); return media_payload_type; } @@ -1345,8 +1346,14 @@ SrsMediaPayloadType SrsAudioPayload::generate_media_payload_type() media_payload_type.rtcp_fb_ = rtcp_fbs_; std::ostringstream format_specific_param; + if (opus_param_.stereo) { + format_specific_param << ";stereo=" << opus_param_.stereo; + } + if (opus_param_.maxplaybackrate) { + format_specific_param << ";maxplaybackrate=" << opus_param_.maxplaybackrate; + } if (opus_param_.minptime) { - format_specific_param << "minptime=" << opus_param_.minptime; + format_specific_param << ";minptime=" << opus_param_.minptime; } if (opus_param_.use_inband_fec) { format_specific_param << ";useinbandfec=1"; @@ -1355,6 +1362,7 @@ SrsMediaPayloadType SrsAudioPayload::generate_media_payload_type() format_specific_param << ";usedtx=1"; } media_payload_type.format_specific_param_ = format_specific_param.str(); + media_payload_type.format_specific_param_ = media_payload_type.format_specific_param_.substr(1); return media_payload_type; } @@ -1372,6 +1380,10 @@ srs_error_t SrsAudioPayload::set_opus_param_desc(std::string fmtp) opus_param_.use_inband_fec = (kv[1] == "1") ? true : false; } else if (kv[0] == "usedtx") { opus_param_.usedtx = (kv[1] == "1") ? true : false; + } else if (kv[0] == "stereo") { + opus_param_.stereo = (int)::atol(kv[1].c_str()); + } else if (kv[0] == "maxplaybackrate") { + opus_param_.maxplaybackrate = (int)::atol(kv[1].c_str()); } } else { return srs_error_new(ERROR_RTC_SDP_DECODE, "invalid opus param=%s", vec[i].c_str()); @@ -1731,6 +1743,11 @@ std::string SrsRtcRecvTrack::get_track_id() return track_desc_->id_; } +int SrsRtcSendTrack::get_track_media_pt() +{ + return track_desc_->media_->pt_; +} + srs_error_t SrsRtcRecvTrack::on_nack(SrsRtpPacket2* pkt) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index 7a2f126c59..fae2885afe 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -322,11 +322,15 @@ class SrsAudioPayload : public SrsCodecPayload { struct SrsOpusParameter { + int stereo; + int maxplaybackrate; int minptime; bool use_inband_fec; bool usedtx; SrsOpusParameter() { + stereo = 0; // 0:mono; 1:stereo + maxplaybackrate = 0; minptime = 0; use_inband_fec = false; usedtx = false; @@ -566,6 +570,7 @@ class SrsRtcSendTrack bool set_track_status(bool active); bool get_track_status(); std::string get_track_id(); + int get_track_media_pt(); public: virtual srs_error_t on_rtp(SrsRtpPacket2* pkt, SrsRtcPlayStreamStatistic& info) = 0; virtual srs_error_t on_rtcp(SrsRtpPacket2* pkt) = 0;