зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1396922 - Implement |setCodecPreferences| in RTCRtpTransceiver;r=bwc,jib,webidl,smaug
Differential Revision: https://phabricator.services.mozilla.com/D207472
This commit is contained in:
Родитель
a0e0f8ed65
Коммит
9d0c8a3753
|
@ -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
|
||||
|
|
|
@ -899,6 +899,134 @@ void RTCRtpTransceiver::Stop(ErrorResult& aRv) {
|
|||
mPc->UpdateNegotiationNeeded();
|
||||
}
|
||||
|
||||
void RTCRtpTransceiver::SetCodecPreferences(
|
||||
const nsTArray<RTCRtpCodec>& aCodecs, ErrorResult& aRv) {
|
||||
nsTArray<RTCRtpCodec> 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<dom::RTCRtpCapabilities> 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<UniquePtr<JsepCodecDescription>> 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::pair<UniquePtr<JsepCodecDescription>, std::string>>
|
||||
defaultCodecsAndParams;
|
||||
for (auto& codec : defaultCodecs) {
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters> 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);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#define _TRANSCEIVERIMPL_H_
|
||||
|
||||
#include <string>
|
||||
#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<RTCRtpCodec>& aCodecs,
|
||||
ErrorResult& aRv);
|
||||
void SetDirectionInternal(RTCRtpTransceiverDirection aDirection);
|
||||
bool HasBeenUsedToSend() const { return mHasBeenUsedToSend; }
|
||||
|
||||
|
@ -189,6 +192,12 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache {
|
|||
Canonical<std::string>& CanonicalMid() { return mMid; }
|
||||
Canonical<std::string>& CanonicalSyncGroup() { return mSyncGroup; }
|
||||
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& GetPreferredCodecs() {
|
||||
return mPreferredCodecs;
|
||||
}
|
||||
|
||||
bool GetPreferredCodecsInUse() { return mPreferredCodecsInUse; }
|
||||
|
||||
private:
|
||||
virtual ~RTCRtpTransceiver();
|
||||
void InitAudio();
|
||||
|
@ -247,6 +256,14 @@ class RTCRtpTransceiver : public nsISupports, public nsWrapperCache {
|
|||
|
||||
Canonical<std::string> mMid;
|
||||
Canonical<std::string> mSyncGroup;
|
||||
|
||||
// Preferred codecs to be negotiated set by calling
|
||||
// setCodecPreferences.
|
||||
std::vector<UniquePtr<JsepCodecDescription>> 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
|
||||
|
|
|
@ -61,8 +61,10 @@ void JsepTrack::EnsureSsrcs(SsrcGenerator& ssrcGenerator, size_t aNumber) {
|
|||
}
|
||||
|
||||
void JsepTrack::PopulateCodecs(
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& prototype) {
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& 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<UniquePtr<JsepCodecDescription>> JsepTrack::NegotiateCodecs(
|
|||
std::vector<UniquePtr<JsepCodecDescription>> negotiatedPseudoCodecs;
|
||||
std::vector<UniquePtr<JsepCodecDescription>> newPrototypePseudoCodecs;
|
||||
|
||||
std::vector<std::string> 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<UniquePtr<JsepCodecDescription>> 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<JsepCodecDescription> 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.
|
||||
|
|
|
@ -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<UniquePtr<JsepCodecDescription>>& aPreferredCodecs,
|
||||
bool aUsePreferredCodecsOrder);
|
||||
|
||||
virtual void PopulateCodecs(
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& prototype);
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& prototype,
|
||||
bool aUsePreferredCodecsOrder = false);
|
||||
|
||||
template <class UnaryFunction>
|
||||
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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -36,8 +36,8 @@ interface RTCRtpTransceiver {
|
|||
|
||||
[Throws]
|
||||
undefined stop();
|
||||
// TODO: bug 1396922
|
||||
// undefined setCodecPreferences(sequence<RTCRtpCodecCapability> codecs);
|
||||
[Throws]
|
||||
undefined setCodecPreferences(sequence<RTCRtpCodec> codecs);
|
||||
|
||||
[ChromeOnly]
|
||||
undefined setDirectionInternal(RTCRtpTransceiverDirection direction);
|
||||
|
|
|
@ -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<const JsepAudioCodecDescription*>(
|
||||
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()
|
||||
|
|
|
@ -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<JsepAudioCodecDescription> 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<JsepVideoCodecDescription> 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<JsepVideoCodecDescription> 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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[RTCRtpTransceiver-setCodecPreferences.html]
|
||||
disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1396922
|
||||
|
|
@ -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<RTCRtpCodec>)]
|
||||
expected: FAIL
|
||||
|
||||
[RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "setCodecPreferences(sequence<RTCRtpCodec>)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[RTCRtpTransceiver interface: calling setCodecPreferences(sequence<RTCRtpCodec>) on new RTCPeerConnection().addTransceiver('audio') with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче