mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1531460 - Implement getCapabilities.r=bwc,webrtc-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D173550
This commit is contained in:
parent
0593550e7a
commit
80516090ea
@ -475,6 +475,18 @@ nsresult PeerConnectionImpl::Initialize(PeerConnectionObserver& aObserver,
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<UniquePtr<JsepCodecDescription>> preferredCodecs;
|
||||
SetupPreferredCodecs(preferredCodecs);
|
||||
mJsepSession->SetDefaultCodecs(preferredCodecs);
|
||||
|
||||
std::vector<RtpExtensionHeader> preferredHeaders;
|
||||
SetupPreferredRtpExtensions(preferredHeaders);
|
||||
|
||||
for (const auto& header : preferredHeaders) {
|
||||
mJsepSession->AddRtpExtension(header.mMediaType, header.extensionname,
|
||||
header.direction);
|
||||
}
|
||||
|
||||
if (XRE_IsContentProcess()) {
|
||||
mStunAddrsRequest =
|
||||
new net::StunAddrsRequestChild(new StunAddrsHandler(this));
|
||||
@ -2257,6 +2269,184 @@ void PeerConnectionImpl::SendWarningToConsole(const nsCString& aWarning) {
|
||||
"WebRTC"_ns, mWindow->WindowID());
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetDefaultVideoCodecs(
|
||||
std::vector<UniquePtr<JsepCodecDescription>>& aSupportedCodecs,
|
||||
bool aUseRtx) {
|
||||
// Supported video codecs.
|
||||
// Note: order here implies priority for building offers!
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultVP8(aUseRtx));
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultVP9(aUseRtx));
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultH264_1(aUseRtx));
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultH264_0(aUseRtx));
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultUlpFec());
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepApplicationCodecDescription::CreateDefault());
|
||||
aSupportedCodecs.emplace_back(JsepVideoCodecDescription::CreateDefaultRed());
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetDefaultAudioCodecs(
|
||||
std::vector<UniquePtr<JsepCodecDescription>>& aSupportedCodecs) {
|
||||
aSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultOpus());
|
||||
aSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultG722());
|
||||
aSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultPCMU());
|
||||
aSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultPCMA());
|
||||
aSupportedCodecs.emplace_back(
|
||||
JsepAudioCodecDescription::CreateDefaultTelephoneEvent());
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetDefaultRtpExtensions(
|
||||
std::vector<RtpExtensionHeader>& aRtpExtensions) {
|
||||
RtpExtensionHeader audioLevel = {JsepMediaType::kAudio,
|
||||
SdpDirectionAttribute::Direction::kSendrecv,
|
||||
webrtc::RtpExtension::kAudioLevelUri};
|
||||
aRtpExtensions.push_back(audioLevel);
|
||||
|
||||
RtpExtensionHeader csrcAudioLevels = {
|
||||
JsepMediaType::kAudio, SdpDirectionAttribute::Direction::kRecvonly,
|
||||
webrtc::RtpExtension::kCsrcAudioLevelsUri};
|
||||
aRtpExtensions.push_back(csrcAudioLevels);
|
||||
|
||||
RtpExtensionHeader mid = {JsepMediaType::kAudioVideo,
|
||||
SdpDirectionAttribute::Direction::kSendrecv,
|
||||
webrtc::RtpExtension::kMidUri};
|
||||
aRtpExtensions.push_back(mid);
|
||||
|
||||
RtpExtensionHeader absSendTime = {JsepMediaType::kVideo,
|
||||
SdpDirectionAttribute::Direction::kSendrecv,
|
||||
webrtc::RtpExtension::kAbsSendTimeUri};
|
||||
aRtpExtensions.push_back(absSendTime);
|
||||
|
||||
RtpExtensionHeader timestampOffset = {
|
||||
JsepMediaType::kVideo, SdpDirectionAttribute::Direction::kSendrecv,
|
||||
webrtc::RtpExtension::kTimestampOffsetUri};
|
||||
aRtpExtensions.push_back(timestampOffset);
|
||||
|
||||
RtpExtensionHeader playoutDelay = {
|
||||
JsepMediaType::kVideo, SdpDirectionAttribute::Direction::kRecvonly,
|
||||
webrtc::RtpExtension::kPlayoutDelayUri};
|
||||
aRtpExtensions.push_back(playoutDelay);
|
||||
|
||||
RtpExtensionHeader transportSequenceNumber = {
|
||||
JsepMediaType::kVideo, SdpDirectionAttribute::Direction::kSendrecv,
|
||||
webrtc::RtpExtension::kTransportSequenceNumberUri};
|
||||
aRtpExtensions.push_back(transportSequenceNumber);
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::GetCapabilities(
|
||||
const nsAString& aKind, dom::Nullable<dom::RTCRtpCapabilities>& aResult,
|
||||
sdp::Direction aDirection) {
|
||||
std::vector<UniquePtr<JsepCodecDescription>> codecs;
|
||||
std::vector<RtpExtensionHeader> headers;
|
||||
auto mediaType = JsepMediaType::kNone;
|
||||
|
||||
if (aKind.EqualsASCII("video")) {
|
||||
GetDefaultVideoCodecs(codecs, true);
|
||||
mediaType = JsepMediaType::kVideo;
|
||||
} else if (aKind.EqualsASCII("audio")) {
|
||||
GetDefaultAudioCodecs(codecs);
|
||||
mediaType = JsepMediaType::kAudio;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
GetDefaultRtpExtensions(headers);
|
||||
|
||||
// Use the codecs for kind to fill out the RTCRtpCodecCapability
|
||||
for (const auto& codec : codecs) {
|
||||
// To avoid misleading information on codec capabilities skip those
|
||||
// not signaled for audio/video (webrtc-datachannel)
|
||||
// and any disabled by default (ulpfec and red).
|
||||
if (codec->mName == "webrtc-datachannel" || codec->mName == "ulpfec" ||
|
||||
codec->mName == "red") {
|
||||
continue;
|
||||
}
|
||||
|
||||
dom::RTCRtpCodecCapability capability;
|
||||
capability.mMimeType = aKind + NS_ConvertASCIItoUTF16("/" + codec->mName);
|
||||
capability.mClockRate = codec->mClock;
|
||||
|
||||
if (codec->mChannels) {
|
||||
capability.mChannels.Construct(codec->mChannels);
|
||||
}
|
||||
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters> params;
|
||||
codec->ApplyConfigToFmtp(params);
|
||||
|
||||
if (params != nullptr) {
|
||||
std::ostringstream paramsString;
|
||||
params->Serialize(paramsString);
|
||||
nsTString<char16_t> fmtp;
|
||||
fmtp.AssignASCII(paramsString.str());
|
||||
capability.mSdpFmtpLine.Construct(fmtp);
|
||||
}
|
||||
|
||||
if (!aResult.SetValue().mCodecs.AppendElement(capability, fallible)) {
|
||||
mozalloc_handle_oom(0);
|
||||
}
|
||||
}
|
||||
|
||||
// We need to manually add rtx for video.
|
||||
if (mediaType == JsepMediaType::kVideo) {
|
||||
dom::RTCRtpCodecCapability capability;
|
||||
capability.mMimeType = aKind + NS_ConvertASCIItoUTF16("/rtx");
|
||||
capability.mClockRate = 90000;
|
||||
if (!aResult.SetValue().mCodecs.AppendElement(capability, fallible)) {
|
||||
mozalloc_handle_oom(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Add headers that match the direction and media type requested.
|
||||
for (const auto& header : headers) {
|
||||
if ((header.direction & aDirection) && (header.mMediaType & mediaType)) {
|
||||
dom::RTCRtpHeaderExtensionCapability rtpHeader;
|
||||
rtpHeader.mUri.AssignASCII(header.extensionname);
|
||||
if (!aResult.SetValue().mHeaderExtensions.AppendElement(rtpHeader,
|
||||
fallible)) {
|
||||
mozalloc_handle_oom(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::SetupPreferredCodecs(
|
||||
std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs) {
|
||||
bool useRtx =
|
||||
Preferences::GetBool("media.peerconnection.video.use_rtx", false);
|
||||
|
||||
GetDefaultVideoCodecs(aPreferredCodecs, useRtx);
|
||||
GetDefaultAudioCodecs(aPreferredCodecs);
|
||||
|
||||
// With red update the redundant encodings list
|
||||
for (auto& videoCodec : aPreferredCodecs) {
|
||||
if (videoCodec->mName == "red") {
|
||||
JsepVideoCodecDescription& red =
|
||||
static_cast<JsepVideoCodecDescription&>(*videoCodec);
|
||||
red.UpdateRedundantEncodings(aPreferredCodecs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionImpl::SetupPreferredRtpExtensions(
|
||||
std::vector<RtpExtensionHeader>& aPreferredheaders) {
|
||||
GetDefaultRtpExtensions(aPreferredheaders);
|
||||
|
||||
if (!Preferences::GetBool("media.navigator.video.use_transport_cc", false)) {
|
||||
aPreferredheaders.erase(
|
||||
std::remove_if(
|
||||
aPreferredheaders.begin(), aPreferredheaders.end(),
|
||||
[&](const RtpExtensionHeader& header) {
|
||||
return header.extensionname ==
|
||||
webrtc::RtpExtension::kTransportSequenceNumberUri;
|
||||
}),
|
||||
aPreferredheaders.end());
|
||||
}
|
||||
}
|
||||
|
||||
nsresult PeerConnectionImpl::CalculateFingerprint(
|
||||
const std::string& algorithm, std::vector<uint8_t>* fingerprint) const {
|
||||
DtlsDigest digest(algorithm);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "jsapi/PacketDumper.h"
|
||||
#include "mozilla/dom/RTCPeerConnectionBinding.h" // mozPacketDumpType, maybe move?
|
||||
#include "mozilla/dom/PeerConnectionImplBinding.h" // ChainedOperation
|
||||
#include "mozilla/dom/RTCRtpCapabilitiesBinding.h"
|
||||
#include "mozilla/dom/RTCRtpTransceiverBinding.h"
|
||||
#include "mozilla/dom/RTCConfigurationBinding.h"
|
||||
#include "PrincipalChangeObserver.h"
|
||||
@ -179,6 +180,12 @@ class PeerConnectionImpl final
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(PeerConnectionImpl)
|
||||
|
||||
struct RtpExtensionHeader {
|
||||
JsepMediaType mMediaType;
|
||||
SdpDirectionAttribute::Direction direction;
|
||||
std::string extensionname;
|
||||
};
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
nsPIDOMWindowInner* GetParentObject() const;
|
||||
@ -552,6 +559,25 @@ class PeerConnectionImpl final
|
||||
|
||||
bool LongTermStatsIsDisabled() const { return mDisableLongTermStats; }
|
||||
|
||||
static void GetDefaultVideoCodecs(
|
||||
std::vector<UniquePtr<JsepCodecDescription>>& aSupportedCodecs,
|
||||
bool aUseRtx);
|
||||
|
||||
static void GetDefaultAudioCodecs(
|
||||
std::vector<UniquePtr<JsepCodecDescription>>& aSupportedCodecs);
|
||||
|
||||
static void GetDefaultRtpExtensions(
|
||||
std::vector<RtpExtensionHeader>& aRtpExtensions);
|
||||
|
||||
static void GetCapabilities(const nsAString& aKind,
|
||||
dom::Nullable<dom::RTCRtpCapabilities>& aResult,
|
||||
sdp::Direction aDirection);
|
||||
static void SetupPreferredCodecs(
|
||||
std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs);
|
||||
|
||||
static void SetupPreferredRtpExtensions(
|
||||
std::vector<RtpExtensionHeader>& aPreferredheaders);
|
||||
|
||||
private:
|
||||
virtual ~PeerConnectionImpl();
|
||||
PeerConnectionImpl(const PeerConnectionImpl& rhs);
|
||||
|
@ -3,6 +3,8 @@
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RTCRtpReceiver.h"
|
||||
#include "PeerConnectionImpl.h"
|
||||
#include "mozilla/dom/RTCRtpCapabilitiesBinding.h"
|
||||
#include "transport/logging.h"
|
||||
#include "mozilla/dom/MediaStreamTrack.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
@ -152,6 +154,12 @@ RTCDtlsTransport* RTCRtpReceiver::GetTransport() const {
|
||||
return mTransceiver->GetDtlsTransport();
|
||||
}
|
||||
|
||||
void RTCRtpReceiver::GetCapabilities(
|
||||
const GlobalObject&, const nsAString& aKind,
|
||||
Nullable<dom::RTCRtpCapabilities>& aResult) {
|
||||
PeerConnectionImpl::GetCapabilities(aKind, aResult, sdp::Direction::kRecv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> RTCRtpReceiver::GetStats(ErrorResult& aError) {
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
|
||||
RefPtr<Promise> promise = Promise::Create(global, aError);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "libwebrtcglue/MediaConduitInterface.h"
|
||||
#include "libwebrtcglue/RtpRtcpConfig.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/dom/RTCRtpCapabilitiesBinding.h"
|
||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
#include "PerformanceRecorder.h"
|
||||
#include "RTCStatsReport.h"
|
||||
@ -34,6 +35,7 @@ namespace dom {
|
||||
class MediaStreamTrack;
|
||||
class Promise;
|
||||
class RTCDtlsTransport;
|
||||
struct RTCRtpCapabilities;
|
||||
struct RTCRtpContributingSource;
|
||||
struct RTCRtpSynchronizationSource;
|
||||
class RTCRtpTransceiver;
|
||||
@ -59,6 +61,8 @@ class RTCRtpReceiver : public nsISupports,
|
||||
// webidl
|
||||
MediaStreamTrack* Track() const { return mTrack; }
|
||||
RTCDtlsTransport* GetTransport() const;
|
||||
static void GetCapabilities(const GlobalObject&, const nsAString& aKind,
|
||||
Nullable<dom::RTCRtpCapabilities>& aResult);
|
||||
already_AddRefed<Promise> GetStats(ErrorResult& aError);
|
||||
void GetContributingSources(
|
||||
nsTArray<dom::RTCRtpContributingSource>& aSources);
|
||||
|
@ -472,6 +472,11 @@ nsTArray<RefPtr<dom::RTCStatsPromise>> RTCRtpSender::GetStatsInternal(
|
||||
return promises;
|
||||
}
|
||||
|
||||
void RTCRtpSender::GetCapabilities(const GlobalObject&, const nsAString& aKind,
|
||||
Nullable<dom::RTCRtpCapabilities>& aResult) {
|
||||
PeerConnectionImpl::GetCapabilities(aKind, aResult, sdp::Direction::kSend);
|
||||
}
|
||||
|
||||
void RTCRtpSender::WarnAboutBadSetParameters(const nsCString& aError) {
|
||||
nsCString warning(
|
||||
"WARNING! Invalid setParameters call detected! The good news? Firefox "
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "libwebrtcglue/RtpRtcpConfig.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/dom/RTCStatsReportBinding.h"
|
||||
#include "mozilla/dom/RTCRtpCapabilitiesBinding.h"
|
||||
#include "mozilla/dom/RTCRtpParametersBinding.h"
|
||||
#include "RTCStatsReport.h"
|
||||
#include "jsep/JsepTrack.h"
|
||||
@ -34,6 +35,7 @@ class MediaStreamTrack;
|
||||
class Promise;
|
||||
class RTCDtlsTransport;
|
||||
class RTCDTMFSender;
|
||||
struct RTCRtpCapabilities;
|
||||
class RTCRtpTransceiver;
|
||||
|
||||
class RTCRtpSender : public nsISupports,
|
||||
@ -62,6 +64,8 @@ class RTCRtpSender : public nsISupports,
|
||||
already_AddRefed<Promise> ReplaceTrack(MediaStreamTrack* aWithTrack,
|
||||
ErrorResult& aError);
|
||||
already_AddRefed<Promise> GetStats(ErrorResult& aError);
|
||||
static void GetCapabilities(const GlobalObject&, const nsAString& kind,
|
||||
Nullable<dom::RTCRtpCapabilities>& result);
|
||||
already_AddRefed<Promise> SetParameters(
|
||||
const dom::RTCRtpSendParameters& aParameters, ErrorResult& aError);
|
||||
// Not a simple getter, so not const
|
||||
|
@ -112,6 +112,9 @@ class JsepCodecDescription {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void ApplyConfigToFmtp(
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters>& aFmtp) const = 0;
|
||||
|
||||
virtual void AddToMediaSection(SdpMediaSection& msection) const {
|
||||
if (mEnabled && msection.GetMediaType() == Type()) {
|
||||
if (mDirection == sdp::kRecv) {
|
||||
@ -268,27 +271,13 @@ class JsepAudioCodecDescription : public JsepCodecDescription {
|
||||
}
|
||||
|
||||
if (mName == "opus") {
|
||||
SdpFmtpAttributeList::OpusParameters opusParams(
|
||||
GetOpusParameters(mDefaultPt, msection));
|
||||
if (mMaxPlaybackRate) {
|
||||
opusParams.maxplaybackrate = mMaxPlaybackRate;
|
||||
}
|
||||
opusParams.maxAverageBitrate = mMaxAverageBitrate;
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters> opusParams =
|
||||
MakeUnique<SdpFmtpAttributeList::OpusParameters>(
|
||||
GetOpusParameters(mDefaultPt, msection));
|
||||
|
||||
if (mChannels == 2 &&
|
||||
!Preferences::GetBool("media.peerconnection.sdp.disable_stereo_fmtp",
|
||||
false) &&
|
||||
!mForceMono) {
|
||||
// We prefer to receive stereo, if available.
|
||||
opusParams.stereo = 1;
|
||||
}
|
||||
opusParams.useInBandFec = mFECEnabled ? 1 : 0;
|
||||
opusParams.useDTX = mDTXEnabled;
|
||||
opusParams.frameSizeMs = mFrameSizeMs;
|
||||
opusParams.minFrameSizeMs = mMinFrameSizeMs;
|
||||
opusParams.maxFrameSizeMs = mMaxFrameSizeMs;
|
||||
opusParams.useCbr = mCbrEnabled;
|
||||
msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, opusParams));
|
||||
ApplyConfigToFmtp(opusParams);
|
||||
|
||||
msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, *opusParams));
|
||||
} else if (mName == "telephone-event") {
|
||||
// add the default dtmf tones
|
||||
SdpFmtpAttributeList::TelephoneEventParameters teParams(
|
||||
@ -336,6 +325,41 @@ class JsepAudioCodecDescription : public JsepCodecDescription {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ApplyConfigToFmtp(
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters>& aFmtp) const override {
|
||||
if (mName == "opus") {
|
||||
SdpFmtpAttributeList::OpusParameters opusParams;
|
||||
if (aFmtp) {
|
||||
MOZ_RELEASE_ASSERT(aFmtp->codec_type == SdpRtpmapAttributeList::kOpus);
|
||||
opusParams =
|
||||
static_cast<const SdpFmtpAttributeList::OpusParameters&>(*aFmtp);
|
||||
opusParams.useInBandFec = mFECEnabled ? 1 : 0;
|
||||
} else {
|
||||
// If we weren't passed a fmtp to use then show we can do in band FEC
|
||||
// for getCapabilities queries.
|
||||
opusParams.useInBandFec = 1;
|
||||
}
|
||||
if (mMaxPlaybackRate) {
|
||||
opusParams.maxplaybackrate = mMaxPlaybackRate;
|
||||
}
|
||||
opusParams.maxAverageBitrate = mMaxAverageBitrate;
|
||||
|
||||
if (mChannels == 2 &&
|
||||
!Preferences::GetBool("media.peerconnection.sdp.disable_stereo_fmtp",
|
||||
false) &&
|
||||
!mForceMono) {
|
||||
// We prefer to receive stereo, if available.
|
||||
opusParams.stereo = 1;
|
||||
}
|
||||
opusParams.useDTX = mDTXEnabled;
|
||||
opusParams.frameSizeMs = mFrameSizeMs;
|
||||
opusParams.minFrameSizeMs = mMinFrameSizeMs;
|
||||
opusParams.maxFrameSizeMs = mMaxFrameSizeMs;
|
||||
opusParams.useCbr = mCbrEnabled;
|
||||
aFmtp.reset(opusParams.Clone());
|
||||
}
|
||||
};
|
||||
|
||||
uint32_t mMaxPlaybackRate;
|
||||
bool mForceMono;
|
||||
bool mFECEnabled;
|
||||
@ -433,6 +457,68 @@ class JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
);
|
||||
}
|
||||
|
||||
void ApplyConfigToFmtp(
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters>& aFmtp) const override {
|
||||
if (mName == "H264") {
|
||||
SdpFmtpAttributeList::H264Parameters h264Params;
|
||||
if (aFmtp) {
|
||||
MOZ_RELEASE_ASSERT(aFmtp->codec_type == SdpRtpmapAttributeList::kH264);
|
||||
h264Params =
|
||||
static_cast<const SdpFmtpAttributeList::H264Parameters&>(*aFmtp);
|
||||
}
|
||||
|
||||
if (mDirection == sdp::kSend) {
|
||||
if (!h264Params.level_asymmetry_allowed) {
|
||||
// First time the fmtp has been set; set just in case this is for a
|
||||
// sendonly m-line, since even though we aren't receiving the level
|
||||
// negotiation still needs to happen (sigh).
|
||||
h264Params.profile_level_id = mProfileLevelId;
|
||||
}
|
||||
} else {
|
||||
// Parameters that only apply to what we receive
|
||||
h264Params.max_mbps = mConstraints.maxMbps;
|
||||
h264Params.max_fs = mConstraints.maxFs;
|
||||
h264Params.max_cpb = mConstraints.maxCpb;
|
||||
h264Params.max_dpb = mConstraints.maxDpb;
|
||||
h264Params.max_br = mConstraints.maxBr;
|
||||
strncpy(h264Params.sprop_parameter_sets, mSpropParameterSets.c_str(),
|
||||
sizeof(h264Params.sprop_parameter_sets) - 1);
|
||||
h264Params.profile_level_id = mProfileLevelId;
|
||||
}
|
||||
|
||||
// Parameters that apply to both the send and recv directions
|
||||
h264Params.packetization_mode = mPacketizationMode;
|
||||
// Hard-coded, may need to change someday?
|
||||
h264Params.level_asymmetry_allowed = true;
|
||||
|
||||
// Parameters that apply to both the send and recv directions
|
||||
h264Params.packetization_mode = mPacketizationMode;
|
||||
// Hard-coded, may need to change someday?
|
||||
h264Params.level_asymmetry_allowed = true;
|
||||
aFmtp.reset(h264Params.Clone());
|
||||
} else if (mName == "VP8" || mName == "VP9") {
|
||||
SdpRtpmapAttributeList::CodecType type =
|
||||
mName == "VP8" ? SdpRtpmapAttributeList::CodecType::kVP8
|
||||
: SdpRtpmapAttributeList::CodecType::kVP9;
|
||||
auto vp8Params = SdpFmtpAttributeList::VP8Parameters(type);
|
||||
|
||||
if (aFmtp) {
|
||||
MOZ_RELEASE_ASSERT(aFmtp->codec_type == type);
|
||||
vp8Params =
|
||||
static_cast<const SdpFmtpAttributeList::VP8Parameters&>(*aFmtp);
|
||||
}
|
||||
// VP8 and VP9 share the same SDP parameters thus far
|
||||
vp8Params.max_fs = mConstraints.maxFs;
|
||||
if (mConstraints.maxFps.isSome()) {
|
||||
vp8Params.max_fr =
|
||||
static_cast<unsigned int>(std::round(*mConstraints.maxFps));
|
||||
} else {
|
||||
vp8Params.max_fr = 60;
|
||||
}
|
||||
aFmtp.reset(vp8Params.Clone());
|
||||
}
|
||||
}
|
||||
|
||||
virtual void EnableTmmbr() {
|
||||
// EnableTmmbr can be called multiple times due to multiple calls to
|
||||
// PeerConnectionImpl::ConfigureJsepSessionCodecs
|
||||
@ -492,34 +578,13 @@ class JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
|
||||
void AddFmtpsToMSection(SdpMediaSection& msection) const {
|
||||
if (mName == "H264") {
|
||||
SdpFmtpAttributeList::H264Parameters h264Params(
|
||||
GetH264Parameters(mDefaultPt, msection));
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters> h264Params =
|
||||
MakeUnique<SdpFmtpAttributeList::H264Parameters>(
|
||||
GetH264Parameters(mDefaultPt, msection));
|
||||
|
||||
if (mDirection == sdp::kSend) {
|
||||
if (!h264Params.level_asymmetry_allowed) {
|
||||
// First time the fmtp has been set; set just in case this is for a
|
||||
// sendonly m-line, since even though we aren't receiving the level
|
||||
// negotiation still needs to happen (sigh).
|
||||
h264Params.profile_level_id = mProfileLevelId;
|
||||
}
|
||||
} else {
|
||||
// Parameters that only apply to what we receive
|
||||
h264Params.max_mbps = mConstraints.maxMbps;
|
||||
h264Params.max_fs = mConstraints.maxFs;
|
||||
h264Params.max_cpb = mConstraints.maxCpb;
|
||||
h264Params.max_dpb = mConstraints.maxDpb;
|
||||
h264Params.max_br = mConstraints.maxBr;
|
||||
strncpy(h264Params.sprop_parameter_sets, mSpropParameterSets.c_str(),
|
||||
sizeof(h264Params.sprop_parameter_sets) - 1);
|
||||
h264Params.profile_level_id = mProfileLevelId;
|
||||
}
|
||||
ApplyConfigToFmtp(h264Params);
|
||||
|
||||
// Parameters that apply to both the send and recv directions
|
||||
h264Params.packetization_mode = mPacketizationMode;
|
||||
// Hard-coded, may need to change someday?
|
||||
h264Params.level_asymmetry_allowed = true;
|
||||
|
||||
msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, h264Params));
|
||||
msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, *h264Params));
|
||||
} else if (mName == "red" && !mRedundantEncodings.empty()) {
|
||||
SdpFmtpAttributeList::RedParameters redParams(
|
||||
GetRedParameters(mDefaultPt, msection));
|
||||
@ -528,17 +593,11 @@ class JsepVideoCodecDescription : public JsepCodecDescription {
|
||||
} else if (mName == "VP8" || mName == "VP9") {
|
||||
if (mDirection == sdp::kRecv) {
|
||||
// VP8 and VP9 share the same SDP parameters thus far
|
||||
SdpFmtpAttributeList::VP8Parameters vp8Params(
|
||||
GetVP8Parameters(mDefaultPt, msection));
|
||||
|
||||
vp8Params.max_fs = mConstraints.maxFs;
|
||||
if (mConstraints.maxFps.isSome()) {
|
||||
vp8Params.max_fr =
|
||||
static_cast<unsigned int>(std::round(*mConstraints.maxFps));
|
||||
} else {
|
||||
vp8Params.max_fr = 60;
|
||||
}
|
||||
msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, vp8Params));
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters> vp8Params =
|
||||
MakeUnique<SdpFmtpAttributeList::VP8Parameters>(
|
||||
GetVP8Parameters(mDefaultPt, msection));
|
||||
ApplyConfigToFmtp(vp8Params);
|
||||
msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, *vp8Params));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1122,6 +1181,9 @@ class JsepApplicationCodecDescription : public JsepCodecDescription {
|
||||
void EnsureNoDuplicatePayloadTypes(std::set<std::string>& aUsedPts) override {
|
||||
}
|
||||
|
||||
void ApplyConfigToFmtp(
|
||||
UniquePtr<SdpFmtpAttributeList::Parameters>& aFmtp) const override{};
|
||||
|
||||
uint16_t mLocalPort;
|
||||
uint32_t mLocalMaxMessageSize;
|
||||
uint16_t mRemotePort;
|
||||
|
@ -88,6 +88,9 @@ class JsepSession {
|
||||
virtual nsresult AddDtlsFingerprint(const std::string& algorithm,
|
||||
const std::vector<uint8_t>& value) = 0;
|
||||
|
||||
virtual nsresult AddRtpExtension(
|
||||
JsepMediaType mediaType, const std::string& extensionName,
|
||||
SdpDirectionAttribute::Direction direction) = 0;
|
||||
virtual nsresult AddAudioRtpExtension(
|
||||
const std::string& extensionName,
|
||||
SdpDirectionAttribute::Direction direction) = 0;
|
||||
@ -220,6 +223,9 @@ class JsepSession {
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetDefaultCodecs(
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs) = 0;
|
||||
|
||||
// See Bug 1642419, this can be removed when all sites are working with RTX.
|
||||
void SetRtxIsAllowed(bool aRtxIsAllowed) { mRtxIsAllowed = aRtxIsAllowed; }
|
||||
|
||||
|
@ -112,9 +112,6 @@ nsresult JsepSessionImpl::Init() {
|
||||
nsresult rv = SetupIds();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
SetupDefaultCodecs();
|
||||
SetupDefaultRtpExtensions();
|
||||
|
||||
mEncodeTrackId =
|
||||
Preferences::GetBool("media.peerconnection.sdp.encode_track_id", true);
|
||||
|
||||
@ -2155,39 +2152,13 @@ nsresult JsepSessionImpl::SetupIds() {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void JsepSessionImpl::SetupDefaultCodecs() {
|
||||
// Supported audio codecs.
|
||||
mSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultOpus());
|
||||
mSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultG722());
|
||||
mSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultPCMU());
|
||||
mSupportedCodecs.emplace_back(JsepAudioCodecDescription::CreateDefaultPCMA());
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepAudioCodecDescription::CreateDefaultTelephoneEvent());
|
||||
void JsepSessionImpl::SetDefaultCodecs(
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs) {
|
||||
mSupportedCodecs.clear();
|
||||
|
||||
bool useRtx =
|
||||
mRtxIsAllowed &&
|
||||
Preferences::GetBool("media.peerconnection.video.use_rtx", false);
|
||||
// Supported video codecs.
|
||||
// Note: order here implies priority for building offers!
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultVP8(useRtx));
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultVP9(useRtx));
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultH264_1(useRtx));
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultH264_0(useRtx));
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepVideoCodecDescription::CreateDefaultUlpFec());
|
||||
|
||||
mSupportedCodecs.emplace_back(
|
||||
JsepApplicationCodecDescription::CreateDefault());
|
||||
|
||||
auto red = JsepVideoCodecDescription::CreateDefaultRed();
|
||||
// Update the redundant encodings for the RED codec with the supported
|
||||
// codecs. Note: only uses the video codecs.
|
||||
red->UpdateRedundantEncodings(mSupportedCodecs);
|
||||
mSupportedCodecs.push_back(std::move(red));
|
||||
for (const auto& codec : aPreferredCodecs) {
|
||||
mSupportedCodecs.emplace_back(codec->Clone());
|
||||
}
|
||||
|
||||
// Filter out codecs using pref (case sensitive), useful for testing.
|
||||
nsCString filteredCodecsPref;
|
||||
@ -2208,25 +2179,6 @@ void JsepSessionImpl::SetupDefaultCodecs() {
|
||||
}
|
||||
}
|
||||
|
||||
void JsepSessionImpl::SetupDefaultRtpExtensions() {
|
||||
AddAudioRtpExtension(webrtc::RtpExtension::kAudioLevelUri,
|
||||
SdpDirectionAttribute::Direction::kSendrecv);
|
||||
AddAudioRtpExtension(webrtc::RtpExtension::kCsrcAudioLevelsUri,
|
||||
SdpDirectionAttribute::Direction::kRecvonly);
|
||||
AddAudioVideoRtpExtension(webrtc::RtpExtension::kMidUri,
|
||||
SdpDirectionAttribute::Direction::kSendrecv);
|
||||
AddVideoRtpExtension(webrtc::RtpExtension::kAbsSendTimeUri,
|
||||
SdpDirectionAttribute::Direction::kSendrecv);
|
||||
AddVideoRtpExtension(webrtc::RtpExtension::kTimestampOffsetUri,
|
||||
SdpDirectionAttribute::Direction::kSendrecv);
|
||||
AddVideoRtpExtension(webrtc::RtpExtension::kPlayoutDelayUri,
|
||||
SdpDirectionAttribute::Direction::kRecvonly);
|
||||
if (Preferences::GetBool("media.navigator.video.use_transport_cc", false)) {
|
||||
AddVideoRtpExtension(webrtc::RtpExtension::kTransportSequenceNumberUri,
|
||||
SdpDirectionAttribute::Direction::kSendrecv);
|
||||
}
|
||||
}
|
||||
|
||||
void JsepSessionImpl::SetState(JsepSignalingState state) {
|
||||
if (state == mState) return;
|
||||
|
||||
|
@ -85,9 +85,9 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
virtual nsresult AddDtlsFingerprint(
|
||||
const std::string& algorithm, const std::vector<uint8_t>& value) override;
|
||||
|
||||
nsresult AddRtpExtension(JsepMediaType mediaType,
|
||||
const std::string& extensionName,
|
||||
SdpDirectionAttribute::Direction direction);
|
||||
virtual nsresult AddRtpExtension(
|
||||
JsepMediaType mediaType, const std::string& extensionName,
|
||||
SdpDirectionAttribute::Direction direction) override;
|
||||
virtual nsresult AddAudioRtpExtension(
|
||||
const std::string& extensionName,
|
||||
SdpDirectionAttribute::Direction direction =
|
||||
@ -180,6 +180,10 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
|
||||
virtual bool CheckNegotiationNeeded() const override;
|
||||
|
||||
virtual void SetDefaultCodecs(
|
||||
const std::vector<UniquePtr<JsepCodecDescription>>& aPreferredCodecs)
|
||||
override;
|
||||
|
||||
private:
|
||||
// Non-const so it can set mLastError
|
||||
nsresult CreateGenericSDP(UniquePtr<Sdp>* sdp);
|
||||
@ -192,8 +196,6 @@ class JsepSessionImpl : public JsepSession, public JsepSessionCopyableStuff {
|
||||
SdpMediaSection* msection);
|
||||
uint16_t GetNeverUsedExtmapEntry();
|
||||
nsresult SetupIds();
|
||||
void SetupDefaultCodecs();
|
||||
void SetupDefaultRtpExtensions();
|
||||
void SetState(JsepSignalingState state);
|
||||
// Non-const so it can set mLastError
|
||||
nsresult ParseSdp(const std::string& sdp, UniquePtr<Sdp>* parsedp);
|
||||
|
27
dom/webidl/RTCRtpCapabilities.webidl
Normal file
27
dom/webidl/RTCRtpCapabilities.webidl
Normal file
@ -0,0 +1,27 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/webrtc-pc/#dom-rtcrtpcapabilities
|
||||
*/
|
||||
|
||||
dictionary RTCRtpCapabilities {
|
||||
required sequence<RTCRtpCodecCapability> codecs;
|
||||
required sequence<RTCRtpHeaderExtensionCapability> headerExtensions;
|
||||
};
|
||||
|
||||
dictionary RTCRtpCodecCapability : RTCRtpCodec {
|
||||
};
|
||||
|
||||
dictionary RTCRtpCodec {
|
||||
required DOMString mimeType;
|
||||
required unsigned long clockRate;
|
||||
unsigned short channels;
|
||||
DOMString sdpFmtpLine;
|
||||
};
|
||||
|
||||
dictionary RTCRtpHeaderExtensionCapability {
|
||||
required DOMString uri;
|
||||
};
|
@ -12,10 +12,11 @@
|
||||
interface RTCRtpReceiver {
|
||||
readonly attribute MediaStreamTrack track;
|
||||
readonly attribute RTCDtlsTransport? transport;
|
||||
[NewObject]
|
||||
Promise<RTCStatsReport> getStats();
|
||||
static RTCRtpCapabilities? getCapabilities(DOMString kind);
|
||||
sequence<RTCRtpContributingSource> getContributingSources();
|
||||
sequence<RTCRtpSynchronizationSource> getSynchronizationSources();
|
||||
[NewObject]
|
||||
Promise<RTCStatsReport> getStats();
|
||||
|
||||
// test-only: for testing getContributingSources
|
||||
[ChromeOnly]
|
||||
|
@ -12,6 +12,7 @@
|
||||
interface RTCRtpSender {
|
||||
readonly attribute MediaStreamTrack? track;
|
||||
readonly attribute RTCDtlsTransport? transport;
|
||||
static RTCRtpCapabilities? getCapabilities(DOMString kind);
|
||||
[NewObject]
|
||||
Promise<undefined> setParameters (RTCRtpSendParameters parameters);
|
||||
RTCRtpSendParameters getParameters();
|
||||
|
@ -1070,6 +1070,7 @@ if CONFIG["MOZ_WEBRTC"]:
|
||||
"RTCIdentityProvider.webidl",
|
||||
"RTCPeerConnection.webidl",
|
||||
"RTCPeerConnectionStatic.webidl",
|
||||
"RTCRtpCapabilities.webidl",
|
||||
"RTCRtpParameters.webidl",
|
||||
"RTCRtpReceiver.webidl",
|
||||
"RTCRtpSender.webidl",
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define GTEST_HAS_RTTI 0
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "PeerConnectionImpl.h"
|
||||
#include "sdp/SdpMediaSection.h"
|
||||
#include "sdp/SipccSdpParser.h"
|
||||
#include "jsep/JsepCodecDescription.h"
|
||||
@ -73,6 +74,21 @@ class JsepSessionTest : public JsepSessionTestBase,
|
||||
EXPECT_EQ(NS_OK, mSessionOff->Init());
|
||||
EXPECT_EQ(NS_OK, mSessionAns->Init());
|
||||
|
||||
std::vector<UniquePtr<JsepCodecDescription>> preferredCodecs;
|
||||
PeerConnectionImpl::SetupPreferredCodecs(preferredCodecs);
|
||||
mSessionOff->SetDefaultCodecs(preferredCodecs);
|
||||
mSessionAns->SetDefaultCodecs(preferredCodecs);
|
||||
|
||||
std::vector<PeerConnectionImpl::RtpExtensionHeader> preferredHeaders;
|
||||
PeerConnectionImpl::SetupPreferredRtpExtensions(preferredHeaders);
|
||||
|
||||
for (const auto& header : preferredHeaders) {
|
||||
mSessionOff->AddRtpExtension(header.mMediaType, header.extensionname,
|
||||
header.direction);
|
||||
mSessionAns->AddRtpExtension(header.mMediaType, header.extensionname,
|
||||
header.direction);
|
||||
}
|
||||
|
||||
mOffererTransport = MakeUnique<TransportData>();
|
||||
mAnswererTransport = MakeUnique<TransportData>();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user