diff --git a/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp b/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp index 96db9fc31243..c98057695138 100644 --- a/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp +++ b/dom/media/webrtc/jsapi/RTCRtpReceiver.cpp @@ -884,7 +884,13 @@ void RTCRtpReceiver::SyncFromJsep(const JsepTransceiver& aJsepTransceiver) { } } -void RTCRtpReceiver::SyncToJsep(JsepTransceiver& aJsepTransceiver) const {} +void RTCRtpReceiver::SyncToJsep(JsepTransceiver& aJsepTransceiver) const { + if (!mTransceiver->GetPreferredCodecs().empty()) { + aJsepTransceiver.mRecvTrack.PopulateCodecs( + mTransceiver->GetPreferredCodecs(), + mTransceiver->GetPreferredCodecsInUse()); + } +} void RTCRtpReceiver::UpdateStreams(StreamAssociationChanges* aChanges) { // We don't sort and use set_difference, because we need to report the diff --git a/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp b/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp index 6b7b456e46fa..1bf60a9adcaf 100644 --- a/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp +++ b/dom/media/webrtc/jsapi/RTCRtpTransceiver.cpp @@ -899,6 +899,134 @@ void RTCRtpTransceiver::Stop(ErrorResult& aRv) { mPc->UpdateNegotiationNeeded(); } +void RTCRtpTransceiver::SetCodecPreferences( + const nsTArray& aCodecs, ErrorResult& aRv) { + nsTArray aCodecsFiltered; + bool rtxPref = + Preferences::GetBool("media.peerconnection.video.use_rtx", false); + bool useRtx = false; + bool useableCodecs = false; + + // kind = transciever's kind. + nsAutoString kind; + GetKind(kind); + + if (!aCodecs.IsEmpty()) { + struct { + bool Equals(const RTCRtpCodec& aA, const RTCRtpCodec& aB) const { + return ((aA.mMimeType == aB.mMimeType) && + (aA.mClockRate == aB.mClockRate) && + (aA.mChannels == aB.mChannels) && + (aA.mSdpFmtpLine == aB.mSdpFmtpLine)); + } + } CodecComparator; + + // Remove any duplicate values in codecs, ensuring that the first occurrence + // of each value remains in place. + for (const auto& codec : aCodecs) { + if (!std::any_of(aCodecsFiltered.begin(), aCodecsFiltered.end(), + [&codec, CodecComparator](RTCRtpCodec& alreadyInserted) { + return CodecComparator.Equals(alreadyInserted, codec); + })) { + aCodecsFiltered.AppendElement(codec); + } + + // Ensure a usable codec was supplied and if RTX is still preferred. + if (!useableCodecs && !codec.mMimeType.EqualsLiteral("video/ulpfec") && + !codec.mMimeType.EqualsLiteral("video/red") && + !codec.mMimeType.EqualsLiteral("video/rtx")) { + useableCodecs = true; + } + if (codec.mMimeType.EqualsLiteral("video/rtx")) { + useRtx = rtxPref; + } + } + + // If codecs are not in the codecCapabilities of receiver capabilities + // throw InvalidModificationError + dom::Nullable codecCapabilities; + PeerConnectionImpl::GetCapabilities(kind, codecCapabilities, + sdp::Direction::kRecv); + + for (const auto& codec : aCodecsFiltered) { + if (!std::any_of(codecCapabilities.Value().mCodecs.begin(), + codecCapabilities.Value().mCodecs.end(), + [&codec, CodecComparator](RTCRtpCodec& recvCap) { + return CodecComparator.Equals(codec, recvCap); + })) { + aRv.ThrowInvalidModificationError( + nsPrintfCString("Codec %s not in capabilities", + NS_ConvertUTF16toUTF8(codec.mMimeType).get())); + return; + } + } + + // If only RTX, RED, or FEC codecs throw InvalidModificationError + if (!useableCodecs) { + aRv.ThrowInvalidModificationError("No useable codecs supplied"); + return; + } + } else { + useRtx = rtxPref; + } + + mPreferredCodecs.clear(); + std::vector> defaultCodecs; + + if (kind.EqualsLiteral("video")) { + PeerConnectionImpl::GetDefaultVideoCodecs(defaultCodecs, useRtx); + } else if (kind.EqualsLiteral("audio")) { + PeerConnectionImpl::GetDefaultAudioCodecs(defaultCodecs); + } + + if (!aCodecsFiltered.IsEmpty()) { + mPreferredCodecsInUse = true; + + std::vector, std::string>> + defaultCodecsAndParams; + for (auto& codec : defaultCodecs) { + UniquePtr params; + codec->ApplyConfigToFmtp(params); + std::ostringstream paramsString; + if (params != nullptr) { + params->Serialize(paramsString); + } + defaultCodecsAndParams.emplace_back(std::move(codec), paramsString.str()); + } + + // Take the array of RTCRtpCodec and convert it to a vector of + // JsepCodecDescription in order to pass to the receive track and populate + // codecs. + for (auto& inputCodec : aCodecsFiltered) { + auto mimeType = NS_ConvertUTF16toUTF8(inputCodec.mMimeType); + for (auto& [defaultCodec, precomputedParamsString] : + defaultCodecsAndParams) { + bool channelsMatch = + (!inputCodec.mChannels.WasPassed() && !defaultCodec->mChannels) || + (inputCodec.mChannels.WasPassed() && + (inputCodec.mChannels.Value() == defaultCodec->mChannels)); + bool sdpFmtpLinesMatch = + (precomputedParamsString.empty() && + !inputCodec.mSdpFmtpLine.WasPassed()) || + ((!precomputedParamsString.empty() && + inputCodec.mSdpFmtpLine.WasPassed()) && + NS_ConvertUTF16toUTF8(inputCodec.mSdpFmtpLine.Value()) + .EqualsASCII(precomputedParamsString.c_str())); + + if ((mimeType.Find(defaultCodec->mName) != kNotFound) && + (inputCodec.mClockRate == defaultCodec->mClock) && channelsMatch && + sdpFmtpLinesMatch) { + mPreferredCodecs.emplace_back(defaultCodec->Clone()); + break; + } + } + } + } else { + mPreferredCodecs.swap(defaultCodecs); + mPreferredCodecsInUse = false; + } +} + void RTCRtpTransceiver::StopTransceiving() { if (mStopping) { MOZ_ASSERT(false); diff --git a/dom/media/webrtc/jsapi/RTCRtpTransceiver.h b/dom/media/webrtc/jsapi/RTCRtpTransceiver.h index 4fa7ef157c4b..693832bee5c9 100644 --- a/dom/media/webrtc/jsapi/RTCRtpTransceiver.h +++ b/dom/media/webrtc/jsapi/RTCRtpTransceiver.h @@ -5,6 +5,7 @@ #define _TRANSCEIVERIMPL_H_ #include +#include "mozilla/dom/RTCRtpCapabilitiesBinding.h" #include "mozilla/StateMirroring.h" #include "mozilla/RefPtr.h" #include "nsCOMPtr.h" @@ -109,6 +110,8 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache { return mCurrentDirection; } void Stop(ErrorResult& aRv); + void SetCodecPreferences(const nsTArray& aCodecs, + ErrorResult& aRv); void SetDirectionInternal(RTCRtpTransceiverDirection aDirection); bool HasBeenUsedToSend() const { return mHasBeenUsedToSend; } @@ -189,6 +192,12 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache { Canonical& CanonicalMid() { return mMid; } Canonical& CanonicalSyncGroup() { return mSyncGroup; } + const std::vector>& GetPreferredCodecs() { + return mPreferredCodecs; + } + + bool GetPreferredCodecsInUse() { return mPreferredCodecsInUse; } + private: virtual ~RTCRtpTransceiver(); void InitAudio(); @@ -247,6 +256,14 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache { Canonical mMid; Canonical mSyncGroup; + + // Preferred codecs to be negotiated set by calling + // setCodecPreferences. + std::vector> mPreferredCodecs; + // Identifies if a preferred list and order of codecs is to be used. + // This is true if setCodecPreferences was called succesfully and passed + // codecs (not empty). + bool mPreferredCodecsInUse = false; }; } // namespace dom diff --git a/dom/media/webrtc/jsep/JsepTrack.cpp b/dom/media/webrtc/jsep/JsepTrack.cpp index 2498200ab269..1ca1e4c94ea6 100644 --- a/dom/media/webrtc/jsep/JsepTrack.cpp +++ b/dom/media/webrtc/jsep/JsepTrack.cpp @@ -61,8 +61,10 @@ void JsepTrack::EnsureSsrcs(SsrcGenerator& ssrcGenerator, size_t aNumber) { } void JsepTrack::PopulateCodecs( - const std::vector>& prototype) { + const std::vector>& prototype, + bool aUsePreferredCodecsOrder) { mPrototypeCodecs.clear(); + mUsePreferredCodecsOrder = aUsePreferredCodecsOrder; for (const auto& prototypeCodec : prototype) { if (prototypeCodec->Type() == mType) { mPrototypeCodecs.emplace_back(prototypeCodec->Clone()); @@ -485,8 +487,29 @@ std::vector> JsepTrack::NegotiateCodecs( std::vector> negotiatedPseudoCodecs; std::vector> newPrototypePseudoCodecs; + std::vector remoteFormats; + + // If setCodecPreferences has been used we need to ensure the order of codecs + // matches what was set. + if (mUsePreferredCodecsOrder) { + for (auto& codec : mPrototypeCodecs) { + if (!codec || !codec->mEnabled) { + continue; + } + for (const std::string& fmt : remote.GetFormats()) { + if (!codec->Matches(fmt, remote)) { + continue; + } + remoteFormats.push_back(fmt); + break; + } + } + } else { + remoteFormats = remote.GetFormats(); + } + // Outer loop establishes the remote side's preference - for (const std::string& fmt : remote.GetFormats()) { + for (const std::string& fmt : remoteFormats) { // Decide if we want to store this codec for logging. const auto* entry = remote.FindRtpmap(fmt); if (entry) { @@ -534,6 +557,35 @@ std::vector> JsepTrack::NegotiateCodecs( } } + // If we are the offerer we need to be prepared to receive all codecs we + // offered even codecs missing from the answer. To achieve this we add the + // remaining codecs from mPrototypeCodecs to the back of the negotiated + // Codecs/PseudoCodecs. + for (auto& codec : mPrototypeCodecs) { + bool codecEnabled = codec && codec->mEnabled; + bool addAllCodecs = + !remoteIsOffer && mDirection != sdp::kSend && remote.IsSending(); + // 0 is a valid PT but not a dynamic PT so we validate if we see 0 that it + // is for PCMU + bool validPT = codecEnabled && (codec->mDefaultPt.compare("0") != 0 || + (codec->mName.compare("PCMU") == 0)); + if (!codecEnabled || (!addAllCodecs || !validPT)) { + continue; + } + + UniquePtr clone(codec->Clone()); + // Moves the codec out of mPrototypeCodecs, leaving an empty + // UniquePtr, so we don't use it again. + if (codec->mName == "red" || codec->mName == "ulpfec" || + codec->mName == "rtx") { + newPrototypePseudoCodecs.emplace_back(std::move(codec)); + negotiatedPseudoCodecs.emplace_back(std::move(clone)); + } else { + newPrototypeCodecs.emplace_back(std::move(codec)); + negotiatedCodecs.emplace_back(std::move(clone)); + } + } + if (negotiatedCodecs.empty()) { // We don't have any real codecs. Clearing so we don't attempt to create a // connection signaling only RED and/or ULPFEC. diff --git a/dom/media/webrtc/jsep/JsepTrack.h b/dom/media/webrtc/jsep/JsepTrack.h index 74a0d2396cd5..6d6f83ac391a 100644 --- a/dom/media/webrtc/jsep/JsepTrack.h +++ b/dom/media/webrtc/jsep/JsepTrack.h @@ -136,6 +136,7 @@ class JsepTrack { mMaxEncodings = rhs.mMaxEncodings; mInHaveRemote = rhs.mInHaveRemote; mRtxIsAllowed = rhs.mRtxIsAllowed; + mUsePreferredCodecsOrder = rhs.mUsePreferredCodecsOrder; mFecCodec = rhs.mFecCodec; mAudioPreferredCodec = rhs.mAudioPreferredCodec; mVideoPreferredCodec = rhs.mVideoPreferredCodec; @@ -192,8 +193,13 @@ class JsepTrack { bool GetRemoteSetSendBit() const { return mRemoteSetSendBit; } bool GetReceptive() const { return mReceptive; } + void PopulatePreferredCodecs( + const std::vector>& aPreferredCodecs, + bool aUsePreferredCodecsOrder); + virtual void PopulateCodecs( - const std::vector>& prototype); + const std::vector>& prototype, + bool aUsePreferredCodecsOrder = false); template void ForEachCodec(UnaryFunction func) { @@ -312,6 +318,10 @@ class JsepTrack { // See Bug 1642419, this can be removed when all sites are working with RTX. bool mRtxIsAllowed = true; + // Used with setCodecPreferences to determine if an answer created should + // match the order of preferred codecs. + bool mUsePreferredCodecsOrder = false; + // Codec names for logging std::string mFecCodec; std::string mAudioPreferredCodec; diff --git a/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp b/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp index e863934ebc81..a1ddede4647c 100644 --- a/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp +++ b/dom/media/webrtc/libwebrtcglue/VideoConduit.cpp @@ -512,6 +512,7 @@ void WebrtcVideoConduit::OnControlConfigChange() { mRecvStreamConfig.rtp); MOZ_ASSERT(newRtp == mRecvStreamConfig.rtp); newRtp.rtx_associated_payload_types.clear(); + newRtp.rtx_ssrc = 0; newRtp.rtcp_mode = rtpRtcpConfig->GetRtcpMode(); newRtp.nack.rtp_history_ms = 0; newRtp.remb = false; @@ -675,6 +676,14 @@ void WebrtcVideoConduit::OnControlConfigChange() { (codecConfig != mControl.mConfiguredSendCodec || rtpRtcpConfig != mControl.mConfiguredSendRtpRtcpConfig)) { CSFLogDebug(LOGTAG, "Configuring codec %s", codecConfig->mName.c_str()); + + if (mControl.mConfiguredSendCodec.isSome() && + (mControl.mConfiguredSendCodec->mName != codecConfig->mName)) { + // This tends to happen if the codec is changed mid call. + // We need to delete the stream now, if we continue to setup the new + // codec before deleting the send stream libwebrtc will throw erros. + DeleteSendStream(); + } mControl.mConfiguredSendCodec = codecConfig; mControl.mConfiguredSendRtpRtcpConfig = rtpRtcpConfig; @@ -1054,7 +1063,9 @@ void WebrtcVideoConduit::SetRemoteSSRCConfig(uint32_t aSsrc, } mRecvSSRC = mRecvStreamConfig.rtp.remote_ssrc = aSsrc; - mRecvStreamConfig.rtp.rtx_ssrc = aRtxSsrc; + // If we have no associated PT then ensure we dont have an rtx_ssrc set. + mRecvStreamConfig.rtp.rtx_ssrc = + mRecvStreamConfig.rtp.rtx_associated_payload_types.empty() ? 0 : aRtxSsrc; } void WebrtcVideoConduit::SetRemoteSSRCAndRestartAsNeeded(uint32_t aSsrc, diff --git a/dom/webidl/RTCRtpTransceiver.webidl b/dom/webidl/RTCRtpTransceiver.webidl index d6dae19a1048..404aa5073040 100644 --- a/dom/webidl/RTCRtpTransceiver.webidl +++ b/dom/webidl/RTCRtpTransceiver.webidl @@ -36,8 +36,8 @@ interface RTCRtpTransceiver { [Throws] undefined stop(); - // TODO: bug 1396922 - // undefined setCodecPreferences(sequence codecs); + [Throws] + undefined setCodecPreferences(sequence codecs); [ChromeOnly] undefined setDirectionInternal(RTCRtpTransceiverDirection direction); diff --git a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp index 2e4faa3af440..30f1796e0a1f 100644 --- a/media/webrtc/signaling/gtest/jsep_session_unittest.cpp +++ b/media/webrtc/signaling/gtest/jsep_session_unittest.cpp @@ -2338,14 +2338,15 @@ TEST_P(JsepSessionTest, RenegotiationOffererDisablesTelephoneEvent) { const JsepTrackNegotiatedDetails* details = track.GetNegotiatedDetails(); ASSERT_EQ(1U, details->GetEncodingCount()); const JsepTrackEncoding& encoding = details->GetEncoding(0); - ASSERT_EQ(4U, encoding.GetCodecs().size()); + auto expectedSize = (track.GetDirection() != sdp::kSend) ? 5U : 4U; + ASSERT_EQ(expectedSize, encoding.GetCodecs().size()); ASSERT_TRUE(encoding.HasFormat("109")); // we can cast here because we've already checked for audio track const JsepAudioCodecDescription* audioCodec = static_cast( encoding.GetCodecs()[0].get()); ASSERT_TRUE(audioCodec); - ASSERT_FALSE(audioCodec->mDtmfEnabled); + ASSERT_EQ(track.GetDirection() != sdp::kSend, audioCodec->mDtmfEnabled); } } @@ -3756,7 +3757,7 @@ TEST_F(JsepSessionTest, ValidateAnsweredCodecParamsNoRed) { ->GetEncoding(0) .GetCodecs() .size()); - ASSERT_EQ(2U, offerTransceivers[1] + ASSERT_EQ(4U, offerTransceivers[1] .mRecvTrack.GetNegotiatedDetails() ->GetEncoding(0) .GetCodecs() diff --git a/media/webrtc/signaling/gtest/jsep_track_unittest.cpp b/media/webrtc/signaling/gtest/jsep_track_unittest.cpp index 24e39b6a24eb..b6fd1040da3b 100644 --- a/media/webrtc/signaling/gtest/jsep_track_unittest.cpp +++ b/media/webrtc/signaling/gtest/jsep_track_unittest.cpp @@ -166,11 +166,11 @@ class JsepTrackTest : public JsepTrackTestBase { } } - void OfferAnswer() { + void OfferAnswer(bool offerCodecsMatchAnswer = true) { CreateOffer(); CreateAnswer(); Negotiate(); - SanityCheck(); + SanityCheck(offerCodecsMatchAnswer); } // TODO: Look into writing a macro that wraps an ASSERT_ and returns false @@ -296,10 +296,13 @@ class JsepTrackTest : public JsepTrackTestBase { } void SanityCheckNegotiatedDetails(const JsepTrackNegotiatedDetails& a, - const JsepTrackNegotiatedDetails& b) const { + const JsepTrackNegotiatedDetails& b, + bool codecsMustMatch) const { ASSERT_EQ(a.GetEncodingCount(), b.GetEncodingCount()); - for (size_t i = 0; i < a.GetEncodingCount(); ++i) { - SanityCheckEncodings(a.GetEncoding(i), b.GetEncoding(i)); + if (codecsMustMatch) { + for (size_t i = 0; i < a.GetEncodingCount(); ++i) { + SanityCheckEncodings(a.GetEncoding(i), b.GetEncoding(i)); + } } ASSERT_EQ(a.GetUniqueReceivePayloadTypes().size(), @@ -310,7 +313,8 @@ class JsepTrackTest : public JsepTrackTestBase { } } - void SanityCheckTracks(const JsepTrack& a, const JsepTrack& b) const { + void SanityCheckTracks(const JsepTrack& a, const JsepTrack& b, + bool codecsMustMatch) const { if (!a.GetNegotiatedDetails()) { ASSERT_FALSE(!!b.GetNegotiatedDetails()); return; @@ -328,12 +332,12 @@ class JsepTrackTest : public JsepTrackTestBase { } SanityCheckNegotiatedDetails(*a.GetNegotiatedDetails(), - *b.GetNegotiatedDetails()); + *b.GetNegotiatedDetails(), codecsMustMatch); } - void SanityCheck() const { - SanityCheckTracks(mSendOff, mRecvAns); - SanityCheckTracks(mRecvOff, mSendAns); + void SanityCheck(bool offerCodecsMatchAnswer = true) const { + SanityCheckTracks(mSendOff, mRecvAns, true); + SanityCheckTracks(mRecvOff, mSendAns, offerCodecsMatchAnswer); } protected: @@ -450,7 +454,7 @@ TEST_F(JsepTrackTest, AudioNegotiationOffererDtmf) { InitTracks(SdpMediaSection::kAudio); InitSdp(SdpMediaSection::kAudio); - OfferAnswer(); + OfferAnswer(false); CheckOffEncodingCount(1); CheckAnsEncodingCount(1); @@ -466,7 +470,7 @@ TEST_F(JsepTrackTest, AudioNegotiationOffererDtmf) { UniquePtr track; ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2, 0))); ASSERT_EQ("109", track->mDefaultPt); - ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2, 0))); + ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 3, 0))); ASSERT_EQ("109", track->mDefaultPt); ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2, 0))); ASSERT_EQ("109", track->mDefaultPt); @@ -474,7 +478,7 @@ TEST_F(JsepTrackTest, AudioNegotiationOffererDtmf) { ASSERT_EQ("109", track->mDefaultPt); ASSERT_TRUE((track = GetAudioCodec(mSendOff, 2, 1))); ASSERT_EQ("9", track->mDefaultPt); - ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 2, 1))); + ASSERT_TRUE((track = GetAudioCodec(mRecvOff, 3, 1))); ASSERT_EQ("9", track->mDefaultPt); ASSERT_TRUE((track = GetAudioCodec(mSendAns, 2, 1))); ASSERT_EQ("9", track->mDefaultPt); @@ -750,7 +754,7 @@ TEST_F(JsepTrackTest, VideoNegotationOffererFEC) { InitTracks(SdpMediaSection::kVideo); InitSdp(SdpMediaSection::kVideo); - OfferAnswer(); + OfferAnswer(false); CheckOffEncodingCount(1); CheckAnsEncodingCount(1); @@ -763,7 +767,7 @@ TEST_F(JsepTrackTest, VideoNegotationOffererFEC) { UniquePtr track; ASSERT_TRUE((track = GetVideoCodec(mSendOff, 2, 0))); ASSERT_EQ("120", track->mDefaultPt); - ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 2, 0))); + ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 4, 0))); ASSERT_EQ("120", track->mDefaultPt); ASSERT_TRUE((track = GetVideoCodec(mSendAns, 2, 0))); ASSERT_EQ("120", track->mDefaultPt); @@ -771,7 +775,7 @@ TEST_F(JsepTrackTest, VideoNegotationOffererFEC) { ASSERT_EQ("120", track->mDefaultPt); ASSERT_TRUE((track = GetVideoCodec(mSendOff, 2, 1))); ASSERT_EQ("126", track->mDefaultPt); - ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 2, 1))); + ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 4, 1))); ASSERT_EQ("126", track->mDefaultPt); ASSERT_TRUE((track = GetVideoCodec(mSendAns, 2, 1))); ASSERT_EQ("126", track->mDefaultPt); @@ -880,7 +884,7 @@ TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECMismatch) { InitTracks(SdpMediaSection::kVideo); InitSdp(SdpMediaSection::kVideo); - OfferAnswer(); + OfferAnswer(false); CheckOffEncodingCount(1); CheckAnsEncodingCount(1); @@ -895,7 +899,7 @@ TEST_F(JsepTrackTest, VideoNegotationOffererAnswererFECMismatch) { UniquePtr track; ASSERT_TRUE((track = GetVideoCodec(mSendOff, 3))); ASSERT_EQ("120", track->mDefaultPt); - ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 3))); + ASSERT_TRUE((track = GetVideoCodec(mRecvOff, 4))); ASSERT_EQ("120", track->mDefaultPt); ASSERT_TRUE((track = GetVideoCodec(mSendAns, 3))); ASSERT_EQ("120", track->mDefaultPt); @@ -1488,7 +1492,7 @@ TEST_F(JsepTrackTest, RtcpFbWithPayloadTypeAsymmetry) { ASSERT_TRUE((codec = GetVideoCodec(mSendOff))); ASSERT_EQ("136", codec->mDefaultPt) << "Offerer should have seen answer asymmetry!"; - ASSERT_TRUE((codec = GetVideoCodec(mRecvOff))); + ASSERT_TRUE((codec = GetVideoCodec(mRecvOff, 2, 0))); ASSERT_EQ("126", codec->mDefaultPt); ASSERT_EQ(expectedAckFbTypes, codec->mAckFbTypes); ASSERT_EQ(expectedNackFbTypes, codec->mNackFbTypes); diff --git a/testing/web-platform/meta/mediacapture-record/passthrough/MediaRecorder-passthrough.https.html.ini b/testing/web-platform/meta/mediacapture-record/passthrough/MediaRecorder-passthrough.https.html.ini index 95361d896869..847c0f28df07 100644 --- a/testing/web-platform/meta/mediacapture-record/passthrough/MediaRecorder-passthrough.https.html.ini +++ b/testing/web-platform/meta/mediacapture-record/passthrough/MediaRecorder-passthrough.https.html.ini @@ -4,14 +4,5 @@ [PeerConnection passthrough MediaRecorder receives VP9 after onstart with a video stream.] expected: FAIL - [PeerConnection passthrough MediaRecorder receives VP8 after onstart with a audio/video stream.] - expected: FAIL - [PeerConnection passthrough MediaRecorder receives VP9 after onstart with a audio/video stream.] expected: FAIL - - [PeerConnection passthrough MediaRecorder receives VP8 after onstart with a video stream.] - expected: FAIL - - [PeerConnection passthrough MediaRecorder should be prepared to handle the codec switching from VP8 to VP9] - expected: FAIL diff --git a/testing/web-platform/meta/webrtc-extensions/RTCRtpParameters-codec.html.ini b/testing/web-platform/meta/webrtc-extensions/RTCRtpParameters-codec.html.ini index 13473feaa194..c0e7114beb3e 100644 --- a/testing/web-platform/meta/webrtc-extensions/RTCRtpParameters-codec.html.ini +++ b/testing/web-platform/meta/webrtc-extensions/RTCRtpParameters-codec.html.ini @@ -1,5 +1,5 @@ [RTCRtpParameters-codec.html] - expected: ERROR + expected: [OK,TIMEOUT] [Creating an audio sender with addTransceiver and codec should work] expected: FAIL @@ -48,8 +48,18 @@ [Creating a video sender with addTransceiver and non-existing codec type should throw OperationError] expected: FAIL - [Stats output-rtp should match the selected codec in simulcast usecase on a video sender] + [Stats output-rtp should match the selected codec in non-simulcast usecase on an audio sender] + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1894137 + expected: [FAIL, TIMEOUT] + + [Stats output-rtp should match the selected codec in non-simulcast usecase on a video sender] + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1894137 expected: FAIL + [Stats output-rtp should match the selected codec in simulcast usecase on a video sender] + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1894137 + expected: [TIMEOUT, FAIL] + [Stats output-rtp should match the selected mixed codecs in simulcast usecase on a video sender] - expected: FAIL + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1894137 + expected: [TIMEOUT, FAIL, NOTRUN] diff --git a/testing/web-platform/meta/webrtc/RTCRtpTransceiver-setCodecPreferences.html.ini b/testing/web-platform/meta/webrtc/RTCRtpTransceiver-setCodecPreferences.html.ini deleted file mode 100644 index d78f524c4bb6..000000000000 --- a/testing/web-platform/meta/webrtc/RTCRtpTransceiver-setCodecPreferences.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[RTCRtpTransceiver-setCodecPreferences.html] - disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1396922 - diff --git a/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini b/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini index 37d9821fde17..1c7febe128d5 100644 --- a/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini +++ b/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini @@ -232,12 +232,3 @@ [RTCRtpReceiver interface: new RTCPeerConnection().addTransceiver('audio').receiver must inherit property "jitterBufferTarget" with the proper type] expected: FAIL - - [RTCRtpTransceiver interface: operation setCodecPreferences(sequence)] - expected: FAIL - - [RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "setCodecPreferences(sequence)" with the proper type] - expected: FAIL - - [RTCRtpTransceiver interface: calling setCodecPreferences(sequence) on new RTCPeerConnection().addTransceiver('audio') with too few arguments must throw TypeError] - expected: FAIL diff --git a/testing/web-platform/meta/webrtc/protocol/rtp-demuxing.html.ini b/testing/web-platform/meta/webrtc/protocol/rtp-demuxing.html.ini index 186f43bc0063..524fdd7d1a2e 100644 --- a/testing/web-platform/meta/webrtc/protocol/rtp-demuxing.html.ini +++ b/testing/web-platform/meta/webrtc/protocol/rtp-demuxing.html.ini @@ -2,9 +2,8 @@ bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1818283 expected: [OK, TIMEOUT] [Can demux two video tracks with different payload types on a bundled connection] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1396922 - expected: FAIL - - [Can demux two video tracks with the same payload type on an unbundled connection] bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1818283 expected: [PASS, TIMEOUT] + [Can demux two video tracks with the same payload type on an unbundled connection] + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1818283 + expected: [PASS, TIMEOUT, NOTRUN] diff --git a/testing/web-platform/meta/webrtc/simulcast/h264.https.html.ini b/testing/web-platform/meta/webrtc/simulcast/h264.https.html.ini deleted file mode 100644 index b1c8f8de4593..000000000000 --- a/testing/web-platform/meta/webrtc/simulcast/h264.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[h264.https.html] - [H264 simulcast setup with two streams] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1396922 - expected: FAIL diff --git a/testing/web-platform/meta/webrtc/simulcast/vp8.https.html.ini b/testing/web-platform/meta/webrtc/simulcast/vp8.https.html.ini deleted file mode 100644 index 8b2d9e33dd95..000000000000 --- a/testing/web-platform/meta/webrtc/simulcast/vp8.https.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[vp8.https.html] - [VP8 simulcast setup with two streams] - bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1396922 - expected: FAIL diff --git a/testing/web-platform/meta/webrtc/simulcast/vp9-scalability-mode.https.html.ini b/testing/web-platform/meta/webrtc/simulcast/vp9-scalability-mode.https.html.ini index 28e7afe277d0..f051301f0740 100644 --- a/testing/web-platform/meta/webrtc/simulcast/vp9-scalability-mode.https.html.ini +++ b/testing/web-platform/meta/webrtc/simulcast/vp9-scalability-mode.https.html.ini @@ -1,3 +1,5 @@ [vp9-scalability-mode.https.html] + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1633876 + expected: [OK, TIMEOUT] [VP9 simulcast setup with two streams and L1T2 set] - expected: FAIL + expected: [PASS, TIMEOUT] diff --git a/testing/web-platform/meta/webrtc/simulcast/vp9.https.html.ini b/testing/web-platform/meta/webrtc/simulcast/vp9.https.html.ini index 348df638cfcb..934c75ae0feb 100644 --- a/testing/web-platform/meta/webrtc/simulcast/vp9.https.html.ini +++ b/testing/web-platform/meta/webrtc/simulcast/vp9.https.html.ini @@ -1,3 +1,5 @@ [vp9.https.html] + bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1633876 + expected: [OK, TIMEOUT] [VP9 simulcast setup with two streams] - expected: FAIL + expected: [PASS, TIMEOUT] diff --git a/testing/web-platform/tests/webrtc-extensions/RTCRtpParameters-codec.html b/testing/web-platform/tests/webrtc-extensions/RTCRtpParameters-codec.html index 5fc1401badf4..a93e028e6f6f 100644 --- a/testing/web-platform/tests/webrtc-extensions/RTCRtpParameters-codec.html +++ b/testing/web-platform/tests/webrtc-extensions/RTCRtpParameters-codec.html @@ -292,13 +292,13 @@ const opus = findFirstCodec('audio/opus'); const nonOpus = codecsNotMatching(opus.mimeType); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences(nonOpus); - }; const transceiver = pc1.addTransceiver('audio'); exchangeIceCandidates(pc1, pc2); - await exchangeOfferAnswer(pc1, pc2); + const negotiated = exchangeOfferAnswer(pc1, pc2); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences(nonOpus); + await negotiated; const sender = transceiver.sender; let param = sender.getParameters(); @@ -316,13 +316,13 @@ const vp8 = findFirstCodec('video/VP8'); const nonVP8 = codecsNotMatching(vp8.mimeType); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences(nonVP8); - }; const transceiver = pc1.addTransceiver('video'); exchangeIceCandidates(pc1, pc2); - await exchangeOfferAnswer(pc1, pc2); + const negotiated = exchangeOfferAnswer(pc1, pc2); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences(nonVP8); + await negotiated; const sender = transceiver.sender; let param = sender.getParameters(); @@ -340,14 +340,14 @@ const opus = findFirstCodec('audio/opus'); const nonOpus = codecsNotMatching(opus.mimeType); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences(nonOpus); - }; const transceiver = pc1.addTransceiver('audio'); exchangeIceCandidates(pc1, pc2); - await exchangeOfferAnswer(pc1, pc2); + const negotiated = exchangeOfferAnswer(pc1, pc2); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences(nonOpus); + await negotiated; const sender = transceiver.sender; let param = sender.getParameters(); @@ -365,13 +365,13 @@ const vp8 = findFirstCodec('video/VP8'); const nonVP8 = codecsNotMatching(vp8.mimeType); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences(nonVP8); - }; const transceiver = pc1.addTransceiver('video'); exchangeIceCandidates(pc1, pc2); - await exchangeOfferAnswer(pc1, pc2); + const negotiated = exchangeOfferAnswer(pc1, pc2); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences(nonVP8); + await negotiated; const sender = transceiver.sender; let param = sender.getParameters(); @@ -452,15 +452,16 @@ const opus = findFirstCodec('audio/opus'); const nonOpus = codecsNotMatching(opus.mimeType); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences(nonOpus.concat([opus])); - }; const transceiver = pc1.addTransceiver(stream.getTracks()[0]); const sender = transceiver.sender; exchangeIceCandidates(pc1, pc2); - await exchangeOfferAnswer(pc1, pc2); + const negotiated = exchangeOfferAnswer(pc1, pc2); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences(nonOpus.concat([opus])); + await negotiated; + let codecs = await codecsForSender(sender); assert_not_equals(codecs[0], opus.mimeType); @@ -490,15 +491,15 @@ const vp8 = findFirstCodec('video/VP8'); const nonVP8 = codecsNotMatching(vp8.mimeType); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences(nonVP8.concat([vp8])); - }; const transceiver = pc1.addTransceiver(stream.getTracks()[0]); const sender = transceiver.sender; exchangeIceCandidates(pc1, pc2); - await exchangeOfferAnswer(pc1, pc2); + const negotiated = exchangeOfferAnswer(pc1, pc2); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences(nonVP8.concat([vp8])); + await negotiated; let codecs = await codecsForSender(sender); assert_not_equals(codecs[0], vp8.mimeType); @@ -528,16 +529,17 @@ const vp8 = findFirstCodec('video/VP8'); const h264 = findFirstCodec('video/H264'); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences([h264, vp8]); - }; + const transceiver = pc1.addTransceiver(stream.getTracks()[0], { sendEncodings: [{rid: '0'}, {rid: '1'}, {rid: '2'}], }); const sender = transceiver.sender; exchangeIceCandidates(pc1, pc2); - await doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']); + const negotiated = doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences([h264, vp8]); + await negotiated; await waitForAllLayers(t, sender); @@ -573,9 +575,6 @@ const vp8 = findFirstCodec('video/VP8'); const h264 = findFirstCodec('video/H264'); - pc2.ontrack = e => { - e.transceiver.setCodecPreferences([h264, vp8]); - }; const transceiver = pc1.addTransceiver(stream.getTracks()[0], { sendEncodings: [{rid: '0'}, {rid: '1'}, {rid: '2'}], @@ -583,7 +582,11 @@ const sender = transceiver.sender; exchangeIceCandidates(pc1, pc2); - await doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']); + const negotiated = doOfferToSendSimulcastAndAnswer(pc1, pc2, ['0', '1', '2']); + const trackEvent = await new Promise(r => pc2.ontrack = r); + trackEvent.transceiver.setCodecPreferences([h264, vp8]); + await negotiated; + await waitForAllLayers(t, sender);