287 lines
10 KiB
C++
287 lines
10 KiB
C++
/* 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/. */
|
|
#ifndef _TRANSCEIVERIMPL_H_
|
|
#define _TRANSCEIVERIMPL_H_
|
|
|
|
#include <string>
|
|
#include "mozilla/dom/RTCRtpCapabilitiesBinding.h"
|
|
#include "mozilla/StateMirroring.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsISerialEventTarget.h"
|
|
#include "nsTArray.h"
|
|
#include "mozilla/dom/MediaStreamTrack.h"
|
|
#include "ErrorList.h"
|
|
#include "jsep/JsepSession.h"
|
|
#include "transport/transportlayer.h" // For TransportLayer::State
|
|
#include "mozilla/dom/RTCRtpTransceiverBinding.h"
|
|
#include "RTCStatsReport.h"
|
|
|
|
class nsIPrincipal;
|
|
|
|
namespace mozilla {
|
|
class PeerIdentity;
|
|
class MediaSessionConduit;
|
|
class VideoSessionConduit;
|
|
class AudioSessionConduit;
|
|
struct AudioCodecConfig;
|
|
class VideoCodecConfig; // Why is this a class, but AudioCodecConfig a struct?
|
|
class MediaPipelineTransmit;
|
|
class MediaPipeline;
|
|
class MediaPipelineFilter;
|
|
class MediaTransportHandler;
|
|
class RTCStatsIdGenerator;
|
|
class WebrtcCallWrapper;
|
|
class JsepTrackNegotiatedDetails;
|
|
class PeerConnectionImpl;
|
|
enum class PrincipalPrivacy : uint8_t;
|
|
|
|
namespace dom {
|
|
class RTCDtlsTransport;
|
|
class RTCDTMFSender;
|
|
class RTCRtpTransceiver;
|
|
struct RTCRtpSourceEntry;
|
|
class RTCRtpReceiver;
|
|
class RTCRtpSender;
|
|
|
|
/**
|
|
* This is what ties all the various pieces that make up a transceiver
|
|
* together. This includes:
|
|
* MediaStreamTrack for rendering and capture
|
|
* MediaTransportHandler for RTP transmission/reception
|
|
* Audio/VideoConduit for feeding RTP/RTCP into webrtc.org for decoding, and
|
|
* feeding audio/video frames into webrtc.org for encoding into RTP/RTCP.
|
|
*/
|
|
class RTCRtpTransceiver : public nsISupports, public nsWrapperCache {
|
|
public:
|
|
/**
|
|
* |aSendTrack| might or might not be set.
|
|
*/
|
|
RTCRtpTransceiver(
|
|
nsPIDOMWindowInner* aWindow, bool aPrivacyNeeded, PeerConnectionImpl* aPc,
|
|
MediaTransportHandler* aTransportHandler, JsepSession* aJsepSession,
|
|
const std::string& aTransceiverId, bool aIsVideo,
|
|
nsISerialEventTarget* aStsThread, MediaStreamTrack* aSendTrack,
|
|
WebrtcCallWrapper* aCallWrapper, RTCStatsIdGenerator* aIdGenerator);
|
|
|
|
void Init(const RTCRtpTransceiverInit& aInit, ErrorResult& aRv);
|
|
|
|
bool IsValid() const { return !!mConduit; }
|
|
|
|
nsresult UpdateTransport();
|
|
|
|
nsresult UpdateConduit();
|
|
|
|
void UpdatePrincipalPrivacy(PrincipalPrivacy aPrivacy);
|
|
|
|
void ResetSync();
|
|
|
|
nsresult SyncWithMatchingVideoConduits(
|
|
nsTArray<RefPtr<RTCRtpTransceiver>>& transceivers);
|
|
|
|
void Close();
|
|
|
|
void BreakCycles();
|
|
void Unlink();
|
|
|
|
bool ConduitHasPluginID(uint64_t aPluginID);
|
|
|
|
// for webidl
|
|
JSObject* WrapObject(JSContext* aCx,
|
|
JS::Handle<JSObject*> aGivenProto) override;
|
|
nsPIDOMWindowInner* GetParentObject() const;
|
|
RTCRtpReceiver* Receiver() const { return mReceiver; }
|
|
RTCRtpSender* Sender() const { return mSender; }
|
|
RTCDtlsTransport* GetDtlsTransport() const { return mDtlsTransport; }
|
|
void GetKind(nsAString& aKind) const;
|
|
void GetMid(nsAString& aMid) const;
|
|
RTCRtpTransceiverDirection Direction() const {
|
|
if (mStopping) {
|
|
return RTCRtpTransceiverDirection::Stopped;
|
|
}
|
|
return mDirection;
|
|
}
|
|
void SetDirection(RTCRtpTransceiverDirection aDirection, ErrorResult& aRv);
|
|
Nullable<RTCRtpTransceiverDirection> GetCurrentDirection() {
|
|
if (mStopped) {
|
|
return RTCRtpTransceiverDirection::Stopped;
|
|
}
|
|
return mCurrentDirection;
|
|
}
|
|
void Stop(ErrorResult& aRv);
|
|
void SetCodecPreferences(const nsTArray<RTCRtpCodec>& aCodecs,
|
|
ErrorResult& aRv);
|
|
void SetDirectionInternal(RTCRtpTransceiverDirection aDirection);
|
|
bool HasBeenUsedToSend() const { return mHasBeenUsedToSend; }
|
|
|
|
bool CanSendDTMF() const;
|
|
bool Stopped() const { return mStopped; }
|
|
bool Stopping() const { return mStopping; }
|
|
void SyncToJsep(JsepSession& aSession) const;
|
|
void SyncFromJsep(const JsepSession& aSession);
|
|
std::string GetMidAscii() const;
|
|
|
|
void SetDtlsTransport(RTCDtlsTransport* aDtlsTransport);
|
|
void SaveStateForRollback();
|
|
void RollbackToStableDtlsTransport();
|
|
|
|
std::string GetTransportId() const {
|
|
return mJsepTransceiver.mTransport.mTransportId;
|
|
}
|
|
|
|
JsepTransceiver& GetJsepTransceiver() { return mJsepTransceiver; }
|
|
|
|
bool IsVideo() const;
|
|
|
|
bool IsSending() const;
|
|
|
|
bool IsReceiving() const;
|
|
|
|
bool ShouldRemove() const;
|
|
|
|
Maybe<const std::vector<UniquePtr<JsepCodecDescription>>&>
|
|
GetNegotiatedSendCodecs() const;
|
|
|
|
Maybe<const std::vector<UniquePtr<JsepCodecDescription>>&>
|
|
GetNegotiatedRecvCodecs() const;
|
|
|
|
struct PayloadTypes {
|
|
Maybe<int> mSendPayloadType;
|
|
Maybe<int> mRecvPayloadType;
|
|
};
|
|
using ActivePayloadTypesPromise = MozPromise<PayloadTypes, nsresult, true>;
|
|
RefPtr<ActivePayloadTypesPromise> GetActivePayloadTypes() const;
|
|
|
|
MediaSessionConduit* GetConduit() const { return mConduit; }
|
|
|
|
const std::string& GetJsepTransceiverId() const { return mTransceiverId; }
|
|
|
|
void SetRemovedFromPc() { mHandlingUnlink = true; }
|
|
|
|
// nsISupports
|
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
NS_DECL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(RTCRtpTransceiver)
|
|
|
|
static void NegotiatedDetailsToAudioCodecConfigs(
|
|
const JsepTrackNegotiatedDetails& aDetails,
|
|
std::vector<AudioCodecConfig>* aConfigs);
|
|
|
|
static void NegotiatedDetailsToVideoCodecConfigs(
|
|
const JsepTrackNegotiatedDetails& aDetails,
|
|
std::vector<VideoCodecConfig>* aConfigs);
|
|
|
|
static void ToDomRtpCodec(const JsepCodecDescription& aCodec,
|
|
RTCRtpCodec* aDomCodec);
|
|
|
|
static void ToDomRtpCodecParameters(
|
|
const JsepCodecDescription& aCodec,
|
|
RTCRtpCodecParameters* aDomCodecParameters);
|
|
|
|
static void ToDomRtpCodecRtx(const JsepVideoCodecDescription& aCodec,
|
|
RTCRtpCodec* aDomCodec);
|
|
|
|
static void ToDomRtpCodecParametersRtx(
|
|
const JsepVideoCodecDescription& aCodec,
|
|
RTCRtpCodecParameters* aDomCodecParameters);
|
|
|
|
/* Returns a promise that will contain the stats in aStats, along with the
|
|
* codec stats (which is a PC-wide thing) */
|
|
void ChainToDomPromiseWithCodecStats(nsTArray<RefPtr<RTCStatsPromise>> aStats,
|
|
const RefPtr<Promise>& aDomPromise);
|
|
|
|
/**
|
|
* Takes a set of codec stats (per-peerconnection) and a set of
|
|
* transceiver/transceiver-stats-promise tuples. Filters out all referenced
|
|
* codec stats based on the transceiver's transport and rtp stream stats.
|
|
* Finally returns the flattened stats containing the filtered codec stats and
|
|
* all given per-transceiver-stats.
|
|
*/
|
|
static RefPtr<RTCStatsPromise> ApplyCodecStats(
|
|
nsTArray<RTCCodecStats> aCodecStats,
|
|
nsTArray<std::tuple<RTCRtpTransceiver*,
|
|
RefPtr<RTCStatsPromise::AllPromiseType>>>
|
|
aTransceiverStatsPromises);
|
|
|
|
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();
|
|
void InitVideo(const TrackingId& aRecvTrackingId);
|
|
void InitConduitControl();
|
|
void StopImpl();
|
|
void StopTransceiving();
|
|
|
|
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
|
RefPtr<PeerConnectionImpl> mPc;
|
|
RefPtr<MediaTransportHandler> mTransportHandler;
|
|
const std::string mTransceiverId;
|
|
// Copy of latest from the JSEP engine.
|
|
JsepTransceiver mJsepTransceiver;
|
|
nsCOMPtr<nsISerialEventTarget> mStsThread;
|
|
// state for webrtc.org that is shared between all transceivers
|
|
RefPtr<WebrtcCallWrapper> mCallWrapper;
|
|
RefPtr<MediaStreamTrack> mSendTrack;
|
|
RefPtr<RTCStatsIdGenerator> mIdGenerator;
|
|
RefPtr<MediaSessionConduit> mConduit;
|
|
// The spec says both RTCRtpReceiver and RTCRtpSender have a slot for
|
|
// an RTCDtlsTransport. They are always the same, so we'll store it
|
|
// here.
|
|
RefPtr<RTCDtlsTransport> mDtlsTransport;
|
|
// The spec says both RTCRtpReceiver and RTCRtpSender have a slot for
|
|
// a last stable state RTCDtlsTransport. They are always the same, so
|
|
// we'll store it here.
|
|
RefPtr<RTCDtlsTransport> mLastStableDtlsTransport;
|
|
RefPtr<RTCRtpReceiver> mReceiver;
|
|
RefPtr<RTCRtpSender> mSender;
|
|
RTCRtpTransceiverDirection mDirection = RTCRtpTransceiverDirection::Sendrecv;
|
|
Nullable<RTCRtpTransceiverDirection> mCurrentDirection;
|
|
bool mStopped = false;
|
|
bool mStopping = false;
|
|
bool mShutdown = false;
|
|
bool mHasBeenUsedToSend = false;
|
|
PrincipalPrivacy mPrincipalPrivacy;
|
|
bool mShouldRemove = false;
|
|
bool mHasTransport = false;
|
|
bool mIsVideo;
|
|
// This is really nasty. Most of the time, PeerConnectionImpl needs to be in
|
|
// charge of unlinking each RTCRtpTransceiver, because it needs to perform
|
|
// stats queries on its way out, which requires all of the RTCRtpTransceivers
|
|
// (and their transitive dependencies) to stick around until those stats
|
|
// queries are finished. However, when an RTCRtpTransceiver is removed from
|
|
// the PeerConnectionImpl due to negotiation, the PeerConnectionImpl
|
|
// releases its reference, which means the PeerConnectionImpl cannot be in
|
|
// charge of the unlink anymore. We cannot do the unlink when this reference
|
|
// is released either, because RTCRtpTransceiver might have some work it needs
|
|
// to do first. Also, JS may be maintaining a reference to the
|
|
// RTCRtpTransceiver (or one of its dependencies), which means it must remain
|
|
// fully functional after it is removed (meaning it cannot release any of its
|
|
// dependencies, or vice versa).
|
|
bool mHandlingUnlink = false;
|
|
std::string mTransportId;
|
|
|
|
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
|
|
|
|
} // namespace mozilla
|
|
|
|
#endif // _TRANSCEIVERIMPL_H_
|