Bug 1091242 - Part 6: Wiring the new JSEP handler code in. See https://github.com/unicorn-wg/gecko-dev/tree/multistream_rebase for more history. r=jesup, r=smaug

This commit is contained in:
Byron Campen [:bwc] 2014-11-19 16:16:29 -08:00
parent 43300ec021
commit 3af28ea884
73 changed files with 3433 additions and 7026 deletions

View File

@ -507,7 +507,7 @@ class Automation(object):
env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1'
# Set WebRTC logging in case it is not set yet
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')
env.setdefault('R_LOG_LEVEL', '6')
env.setdefault('R_LOG_DESTINATION', 'stderr')
env.setdefault('R_LOG_VERBOSE', '1')

View File

@ -410,7 +410,7 @@ def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=N
env.setdefault('MOZ_DISABLE_NONLOCAL_CONNECTIONS', '1')
# Set WebRTC logging in case it is not set yet
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5')
env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5')
env.setdefault('R_LOG_LEVEL', '6')
env.setdefault('R_LOG_DESTINATION', 'stderr')
env.setdefault('R_LOG_VERBOSE', '1')

View File

@ -862,7 +862,7 @@ DOMInterfaces = {
},
'PeerConnectionImpl': {
'nativeType': 'sipcc::PeerConnectionImpl',
'nativeType': 'mozilla::PeerConnectionImpl',
'headerFile': 'PeerConnectionImpl.h',
'wrapperCache': False
},

View File

@ -25,7 +25,7 @@ const PC_STATIC_CONTRACT = "@mozilla.org/dom/peerconnectionstatic;1";
const PC_SENDER_CONTRACT = "@mozilla.org/dom/rtpsender;1";
const PC_RECEIVER_CONTRACT = "@mozilla.org/dom/rtpreceiver;1";
const PC_CID = Components.ID("{00e0e20d-1494-4776-8e0e-0f0acbea3c79}");
const PC_CID = Components.ID("{bdc2e533-b308-4708-ac8e-a8bfade6d851}");
const PC_OBS_CID = Components.ID("{d1748d4c-7f6a-4dc5-add6-d55b7678537e}");
const PC_ICE_CID = Components.ID("{02b9970c-433d-4cc2-923d-f7028ac66073}");
const PC_SESSION_CID = Components.ID("{1775081b-b62d-4954-8ffe-a067bbf508a7}");
@ -849,7 +849,7 @@ RTCPeerConnection.prototype = {
this._impl.addIceCandidate(cand.candidate, cand.sdpMid || "",
(cand.sdpMLineIndex === null) ? 0 :
cand.sdpMLineIndex + 1);
cand.sdpMLineIndex);
},
addStream: function(stream) {
@ -1122,7 +1122,7 @@ PeerConnectionObserver.prototype = {
const reasonName = [
"",
"InternalError",
"InternalError",
"InvalidCandidateError",
"InvalidParameter",
"InvalidStateError",
"InvalidSessionDescriptionError",
@ -1221,7 +1221,7 @@ PeerConnectionObserver.prototype = {
{
candidate: candidate,
sdpMid: mid,
sdpMLineIndex: level - 1
sdpMLineIndex: level
}
));
}

View File

@ -1,4 +1,4 @@
component {00e0e20d-1494-4776-8e0e-0f0acbea3c79} PeerConnection.js
component {bdc2e533-b308-4708-ac8e-a8bfade6d851} PeerConnection.js
component {d1748d4c-7f6a-4dc5-add6-d55b7678537e} PeerConnection.js
component {02b9970c-433d-4cc2-923d-f7028ac66073} PeerConnection.js
component {1775081b-b62d-4954-8ffe-a067bbf508a7} PeerConnection.js
@ -9,7 +9,7 @@ component {0fb47c47-a205-4583-a9fc-cbadf8c95880} PeerConnection.js
component {4fff5d46-d827-4cd4-a970-8fd53977440e} PeerConnection.js
component {d974b814-8fde-411c-8c45-b86791b81030} PeerConnection.js
contract @mozilla.org/dom/peerconnection;1 {00e0e20d-1494-4776-8e0e-0f0acbea3c79}
contract @mozilla.org/dom/peerconnection;1 {bdc2e533-b308-4708-ac8e-a8bfade6d851}
contract @mozilla.org/dom/peerconnectionobserver;1 {d1748d4c-7f6a-4dc5-add6-d55b7678537e}
contract @mozilla.org/dom/rtcicecandidate;1 {02b9970c-433d-4cc2-923d-f7028ac66073}
contract @mozilla.org/dom/rtcsessiondescription;1 {1775081b-b62d-4954-8ffe-a067bbf508a7}

View File

@ -59,6 +59,7 @@ interface IPeerConnection : nsISupports
/* Constants for 'name' in error callbacks */
const unsigned long kNoError = 0; // Test driver only
const unsigned long kInvalidCandidate = 2;
const unsigned long kInvalidMediastreamTrack = 3;
const unsigned long kInvalidState = 4;
const unsigned long kInvalidSessionDescription = 5;

View File

@ -21,9 +21,9 @@ NS_DEFINE_NAMED_CID(NS_STUN_UDP_SOCKET_FILTER_HANDLER_CID)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsStunUDPSocketFilterHandler)
namespace sipcc
namespace mozilla
{
// Factory defined in sipcc::, defines sipcc::PeerConnectionImplConstructor
// Factory defined in mozilla::, defines mozilla::PeerConnectionImplConstructor
NS_GENERIC_FACTORY_CONSTRUCTOR(PeerConnectionImpl)
}
@ -31,7 +31,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(PeerConnectionImpl)
NS_DEFINE_NAMED_CID(PEERCONNECTION_CID);
static const mozilla::Module::CIDEntry kCIDs[] = {
{ &kPEERCONNECTION_CID, false, nullptr, sipcc::PeerConnectionImplConstructor },
{ &kPEERCONNECTION_CID, false, nullptr, mozilla::PeerConnectionImplConstructor },
{ &kNS_STUN_UDP_SOCKET_FILTER_HANDLER_CID, false, nullptr, nsStunUDPSocketFilterHandlerConstructor },
{ nullptr }
};

View File

@ -67,6 +67,7 @@ interface PeerConnectionImpl {
boolean pluginCrash(unsigned long long pluginId, DOMString name, DOMString pluginDumpID);
/* Attributes */
[Constant]
readonly attribute DOMString fingerprint;
readonly attribute DOMString localDescription;
readonly attribute DOMString remoteDescription;
@ -74,7 +75,6 @@ interface PeerConnectionImpl {
readonly attribute PCImplIceConnectionState iceConnectionState;
readonly attribute PCImplIceGatheringState iceGatheringState;
readonly attribute PCImplSignalingState signalingState;
readonly attribute PCImplSipccState sipccState;
attribute DOMString id;
attribute DOMString peerIdentity;

View File

@ -17,8 +17,6 @@
namespace mozilla {
MOZ_MTLOG_MODULE("mtransport")
DtlsIdentity::~DtlsIdentity() {
// XXX: make cert_ a smart pointer to avoid this, after we figure
// out the linking problem.
@ -27,7 +25,6 @@ DtlsIdentity::~DtlsIdentity() {
}
const std::string DtlsIdentity::DEFAULT_HASH_ALGORITHM = "sha-256";
const size_t DtlsIdentity::HASH_ALGORITHM_MAX_LENGTH = 64;
TemporaryRef<DtlsIdentity> DtlsIdentity::Generate() {
@ -210,89 +207,4 @@ nsresult DtlsIdentity::ComputeFingerprint(const CERTCertificate *cert,
return NS_OK;
}
// Format the fingerprint in RFC 4572 Section 5 attribute format, including both
// the hash name and the fingerprint, colons and all.
// returns an empty string if there is a problem
std::string DtlsIdentity::GetFormattedFingerprint(const std::string &algorithm) {
unsigned char digest[HASH_ALGORITHM_MAX_LENGTH];
size_t digest_length;
nsresult res = this->ComputeFingerprint(algorithm,
digest,
sizeof(digest),
&digest_length);
if (NS_FAILED(res)) {
MOZ_MTLOG(ML_ERROR, "Unable to compute " << algorithm
<< " hash for identity: nsresult = 0x"
<< std::hex << std::uppercase
<< static_cast<uint32_t>(res)
<< std::nouppercase << std::dec);
return "";
}
return algorithm + " " + this->FormatFingerprint(digest, digest_length);
}
std::string DtlsIdentity::FormatFingerprint(const unsigned char *digest,
std::size_t size) {
std::string str("");
char group[3];
for (std::size_t i=0; i < size; i++) {
PR_snprintf(group, sizeof(group), "%.2X", digest[i]);
if (i != 0) {
str += ":";
}
str += group;
}
MOZ_ASSERT(str.size() == (size * 3 - 1)); // Check result length
return str;
}
// Parse a fingerprint in RFC 4572 format.
// Note that this tolerates some badly formatted data, in particular:
// (a) arbitrary runs of colons
// (b) colons at the beginning or end.
nsresult DtlsIdentity::ParseFingerprint(const std::string fp,
unsigned char *digest,
size_t size,
size_t *length) {
size_t offset = 0;
bool top_half = true;
uint8_t val = 0;
for (size_t i=0; i<fp.length(); i++) {
if (offset >= size) {
// Note: no known way for offset to get > size
MOZ_MTLOG(ML_ERROR, "Fingerprint too long for buffer");
return NS_ERROR_INVALID_ARG;
}
if (top_half && (fp[i] == ':')) {
continue;
} else if ((fp[i] >= '0') && (fp[i] <= '9')) {
val |= fp[i] - '0';
} else if ((fp[i] >= 'A') && (fp[i] <= 'F')) {
val |= fp[i] - 'A' + 10;
} else {
MOZ_MTLOG(ML_ERROR, "Invalid fingerprint value " << fp[i]);
return NS_ERROR_ILLEGAL_VALUE;
}
if (top_half) {
val <<= 4;
top_half = false;
} else {
digest[offset++] = val;
top_half = true;
val = 0;
}
}
*length = offset;
return NS_OK;
}
} // close namespace

View File

@ -33,8 +33,6 @@ class DtlsIdentity {
CERTCertificate *cert() { return cert_; }
SECKEYPrivateKey *privkey() { return privkey_; }
std::string GetFormattedFingerprint(const std::string &algorithm = DEFAULT_HASH_ALGORITHM);
nsresult ComputeFingerprint(const std::string algorithm,
unsigned char *digest,
std::size_t size,
@ -45,24 +43,18 @@ class DtlsIdentity {
unsigned char *digest,
std::size_t size,
std::size_t *digest_length);
static nsresult ParseFingerprint(const std::string fp,
unsigned char *digest,
size_t size, size_t *length);
static const std::string DEFAULT_HASH_ALGORITHM;
enum {
HASH_ALGORITHM_MAX_LENGTH = 64
};
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DtlsIdentity)
private:
private:
DtlsIdentity(SECKEYPrivateKey *privkey, CERTCertificate *cert)
: privkey_(privkey), cert_(cert) {}
DISALLOW_COPY_ASSIGN(DtlsIdentity);
static const std::string DEFAULT_HASH_ALGORITHM;
static const size_t HASH_ALGORITHM_MAX_LENGTH;
std::string FormatFingerprint(const unsigned char *digest,
std::size_t size);
ScopedSECKEYPrivateKey privkey_;
CERTCertificate *cert_; // TODO: Using a smart pointer here causes link
// errors.

View File

@ -40,7 +40,6 @@
// PR_LOGGING is off --> make no-op MTLOG macros
#define MOZ_MTLOG_MODULE(n)
#define MOZ_MTLOG(level, b)
#endif // defined(PR_LOGGING)
#endif // logging_h__

View File

@ -533,11 +533,21 @@ NrIceCtx::CreateStream(const std::string& name, int components) {
RefPtr<NrIceMediaStream> stream =
NrIceMediaStream::Create(this, name, components);
streams_.push_back(stream);
if (stream) {
streams_.push_back(stream);
}
return stream;
}
std::string NrIceCtx::ufrag() const {
return ctx_->ufrag;
}
std::string NrIceCtx::pwd() const {
return ctx_->pwd;
}
void NrIceCtx::destroy_peer_ctx() {
nr_ice_peer_ctx_destroy(&peer_);
}

View File

@ -207,9 +207,20 @@ class NrIceCtx {
RefPtr<NrIceMediaStream> CreateStream(const std::string& name,
int components);
RefPtr<NrIceMediaStream> GetStream(size_t index) {
if (index < streams_.size()) {
return streams_[index];
}
return nullptr;
}
// The name of the ctx
const std::string& name() const { return name_; }
// Get ufrag and password.
std::string ufrag() const;
std::string pwd() const;
// Current state
ConnectionState connection_state() const {
return connection_state_;

View File

@ -338,6 +338,27 @@ nsresult NrIceMediaStream::GetCandidatePairs(std::vector<NrIceCandidatePair>*
return NS_OK;
}
nsresult NrIceMediaStream::GetDefaultCandidate(
NrIceCandidate* candidate) const {
nr_ice_candidate *cand;
int r = nr_ice_media_stream_get_default_candidate(stream_, 1, &cand);
if (r) {
MOZ_MTLOG(ML_ERROR, "Couldn't get default ICE candidate for '"
<< name_ << "'");
return NS_ERROR_FAILURE;
}
if (!ToNrIceCandidate(*cand, candidate)) {
MOZ_MTLOG(ML_ERROR, "Failed to convert default ICE candidate for '"
<< name_ << "'");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
std::vector<std::string> NrIceMediaStream::GetCandidates() const {
char **attrs = 0;
int attrct;

View File

@ -136,6 +136,10 @@ class NrIceMediaStream {
// queue, in priority order. |out_pairs| is cleared before being filled.
nsresult GetCandidatePairs(std::vector<NrIceCandidatePair>* out_pairs) const;
// TODO(bug 1096795): This needs to take a component number, so we can get
// default candidates for rtcp.
nsresult GetDefaultCandidate(NrIceCandidate* candidate) const;
// Parse remote attributes
nsresult ParseAttributes(std::vector<std::string>& candidates);
@ -151,7 +155,7 @@ class NrIceMediaStream {
NrIceCandidate** local, NrIceCandidate** remote);
// The number of components
int components() const { return components_; }
size_t components() const { return components_; }
// The underlying nICEr stream
nr_ice_media_stream *stream() { return stream_; }
@ -188,7 +192,7 @@ class NrIceMediaStream {
private:
NrIceMediaStream(NrIceCtx *ctx, const std::string& name,
int components) :
size_t components) :
state_(ICE_CONNECTING),
ctx_(ctx),
name_(name),
@ -203,7 +207,7 @@ class NrIceMediaStream {
State state_;
NrIceCtx *ctx_;
const std::string name_;
const int components_;
const size_t components_;
nr_ice_media_stream *stream_;
uint16_t level_;
};

View File

@ -545,7 +545,7 @@ class IceTestPeer : public sigslot::has_slots<> {
void DumpAndCheckActiveCandidates_s() {
std::cerr << "Active candidates:" << std::endl;
for (size_t i=0; i < streams_.size(); ++i) {
for (int j=0; j < streams_[i]->components(); ++j) {
for (size_t j=0; j < streams_[i]->components(); ++j) {
std::cerr << "Stream " << i << " component " << j+1 << std::endl;
NrIceCandidate *local;

View File

@ -607,7 +607,8 @@ class TransportTestPeer : public sigslot::has_slots<> {
connect(this, &TransportTestPeer::GotCandidate);
// Create the transport layer
ice_ = new TransportLayerIce(name, ice_ctx_, stream, 1);
ice_ = new TransportLayerIce(name);
ice_->SetParameters(ice_ctx_, stream, 1);
// Assemble the stack
nsAutoPtr<std::queue<mozilla::TransportLayer *> > layers(

View File

@ -463,7 +463,9 @@ int nr_ice_candidate_initialize(nr_ice_candidate *cand, NR_async_cb ready_cb, vo
if(r=nr_socket_getaddr(cand->isock->sock,&cand->addr))
ABORT(r);
cand->osock=cand->isock->sock;
cand->state=NR_ICE_CAND_STATE_INITIALIZED;
// This is actually ready, but we set this anyway to prevent it from
// being paired twice.
cand->state=NR_ICE_CAND_STATE_INITIALIZING;
// Post this so that it doesn't happen in-line
cand->ready_cb = ready_cb;
cand->ready_cb_arg = cb_arg;

View File

@ -793,10 +793,11 @@ int nr_ice_component_pair_candidate(nr_ice_peer_ctx *pctx, nr_ice_component *pco
trickle candidates).
*/
if (pair_all_remote || (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_UNPAIRED)) {
/* If we are pairing our own trickle candidates, the remote candidate should
all be paired */
if (pair_all_remote)
assert (pcand->state == NR_ICE_CAND_PEER_CANDIDATE_PAIRED);
if (pair_all_remote) {
/* When a remote candidate arrives after the start of checking, but
* before the gathering of local candidates, it can be in UNPAIRED */
pcand->state = NR_ICE_CAND_PEER_CANDIDATE_PAIRED;
}
nr_ice_compute_codeword(pcand->label,strlen(pcand->label),codeword);
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND(%s): Pairing with peer candidate %s", pctx->label, codeword, pcand->label);
@ -1101,10 +1102,12 @@ int nr_ice_component_insert_pair(nr_ice_component *pcomp, nr_ice_cand_pair *pair
ABORT(r);
/* Make sure the check timer is running, if the stream was previously
* started. We will not start streams just because a pair was created. */
* started. We will not start streams just because a pair was created,
* unless it is the first pair to be created across all streams. */
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND-PAIR(%s): Ensure that check timer is running for new pair %s.",pair->remote->stream->pctx->label, pair->codeword, pair->as_string);
if(pair->remote->stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE){
if(pair->remote->stream->ice_state == NR_ICE_MEDIA_STREAM_CHECKS_ACTIVE ||
!pair->remote->stream->pctx->checks_started){
if(nr_ice_media_stream_start_checks(pair->remote->stream->pctx, pair->remote->stream)) {
r_log(LOG_ICE,LOG_WARNING,"ICE-PEER(%s)/CAND-PAIR(%s): Could not restart checks for new pair %s.",pair->remote->stream->pctx->label, pair->codeword, pair->as_string);
ABORT(R_INTERNAL);

View File

@ -455,6 +455,10 @@ void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
ctx->uninitialized_candidates--;
// Avoid the need for yet another initialization function
if (cand->state == NR_ICE_CAND_STATE_INITIALIZING && cand->type == HOST)
cand->state = NR_ICE_CAND_STATE_INITIALIZED;
if (cand->state == NR_ICE_CAND_STATE_INITIALIZED) {
int was_pruned = 0;
@ -468,7 +472,7 @@ void nr_ice_initialize_finished_cb(NR_SOCKET s, int h, void *cb_arg)
if (ctx->trickle_cb && !was_pruned) {
ctx->trickle_cb(ctx->trickle_cb_arg, ctx, cand->stream, cand->component_id, cand);
if (r=nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
if (nr_ice_ctx_pair_new_trickle_candidates(ctx, cand)) {
r_log(LOG_ICE,LOG_ERR, "ICE(%s): All could not pair new trickle candidate",ctx->label);
/* But continue */
}

View File

@ -137,6 +137,10 @@ nr_ice_peer_candidate_from_attribute(nr_ice_ctx *ctx,char *orig,nr_ice_media_str
cand->stream=stream;
skip_whitespace(&str);
/* Skip a= if present */
if (!strncmp(str, "a=", 2))
str += 2;
/* Candidate attr */
if (strncasecmp(str, "candidate:", 10))
ABORT(R_BAD_DATA);

View File

@ -171,7 +171,7 @@ static int nr_ice_peer_ctx_parse_stream_attributes_int(nr_ice_peer_ctx *pctx, nr
}
}
else {
r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) specified bogus attribute",pctx->ctx->label,pctx->label);
r_log(LOG_ICE,LOG_WARNING,"ICE(%s): peer (%s) specified bogus attribute: %s",pctx->ctx->label,pctx->label,attrs[i]);
}
}
@ -220,6 +220,9 @@ static int nr_ice_ctx_parse_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_stream
TAILQ_INSERT_TAIL(&comp->candidates,cand,entry_comp);
r_log(LOG_ICE,LOG_DEBUG,"ICE-PEER(%s)/CAND(%s): creating peer candidate",
pctx->label,cand->label);
_status=0;
abort:
if (_status) {
@ -291,25 +294,25 @@ int nr_ice_peer_ctx_parse_trickle_candidate(nr_ice_peer_ctx *pctx, nr_ice_media_
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to pair trickle ICE candidates",pctx->ctx->label,pctx->label,stream->label);
ABORT(r);
}
}
/* Start checks if this stream is not checking yet or if it has checked
all the available candidates but not had a completed check for all
components.
/* Start checks if this stream is not checking yet or if it has checked
all the available candidates but not had a completed check for all
components.
Note that this is not compliant with RFC 5245, but consistent with
the libjingle trickle ICE behavior. Note that we will not restart
checks if either (a) the stream has failed or (b) all components
have a successful pair because the switch statement above jumps
will in both states.
Note that this is not compliant with RFC 5245, but consistent with
the libjingle trickle ICE behavior. Note that we will not restart
checks if either (a) the stream has failed or (b) all components
have a successful pair because the switch statement above jumps
will in both states.
TODO(ekr@rtfm.com): restart checks.
TODO(ekr@rtfm.com): update when the trickle ICE RFC is published
*/
if (!pstream->timer) {
if(r=nr_ice_media_stream_start_checks(pctx, pstream)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to start checks",pctx->ctx->label,pctx->label,stream->label);
ABORT(r);
TODO(ekr@rtfm.com): restart checks.
TODO(ekr@rtfm.com): update when the trickle ICE RFC is published
*/
if (!pstream->timer) {
if(r=nr_ice_media_stream_start_checks(pctx, pstream)) {
r_log(LOG_ICE,LOG_ERR,"ICE(%s): peer (%s), stream(%s) failed to start checks",pctx->ctx->label,pctx->label,stream->label);
ABORT(r);
}
}
}

View File

@ -84,11 +84,25 @@ namespace mozilla {
MOZ_MTLOG_MODULE("mtransport")
TransportLayerIce::TransportLayerIce(const std::string& name,
RefPtr<NrIceCtx> ctx, RefPtr<NrIceMediaStream> stream,
int component)
: name_(name), ctx_(ctx), stream_(stream), component_(component) {
target_ = ctx->thread();
TransportLayerIce::TransportLayerIce(const std::string& name)
: name_(name), ctx_(nullptr), stream_(nullptr), component_(0) {}
TransportLayerIce::~TransportLayerIce() {
// No need to do anything here, since we use smart pointers
}
void TransportLayerIce::SetParameters(RefPtr<NrIceCtx> ctx,
RefPtr<NrIceMediaStream> stream,
int component) {
ctx_ = ctx;
stream_ = stream;
component_ = component;
PostSetup();
}
void TransportLayerIce::PostSetup() {
target_ = ctx_->thread();
stream_->SignalReady.connect(this, &TransportLayerIce::IceReady);
stream_->SignalFailed.connect(this, &TransportLayerIce::IceFailed);
@ -99,10 +113,6 @@ TransportLayerIce::TransportLayerIce(const std::string& name,
}
}
TransportLayerIce::~TransportLayerIce() {
// No need to do anything here, since we use smart pointers
}
TransportResult TransportLayerIce::SendPacket(const unsigned char *data,
size_t len) {
CheckThread();

View File

@ -31,12 +31,14 @@ namespace mozilla {
class TransportLayerIce : public TransportLayer {
public:
TransportLayerIce(const std::string& name,
RefPtr<NrIceCtx> ctx,
RefPtr<NrIceMediaStream> stream,
int component);
explicit TransportLayerIce(const std::string& name);
virtual ~TransportLayerIce();
void SetParameters(RefPtr<NrIceCtx> ctx,
RefPtr<NrIceMediaStream> stream,
int component);
// Transport layer overrides.
virtual TransportResult SendPacket(const unsigned char *data, size_t len);
@ -51,6 +53,7 @@ class TransportLayerIce : public TransportLayer {
private:
DISALLOW_COPY_ASSIGN(TransportLayerIce);
void PostSetup();
const std::string name_;
RefPtr<NrIceCtx> ctx_;

View File

@ -1,314 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include "ECC_Types.h"
#include "mozilla/RefPtr.h"
extern "C"
{
#include "ccapi_types.h"
#include "fsmdef_states.h"
}
#if defined(__cplusplus) && __cplusplus >= 201103L
typedef struct Timecard Timecard;
#else
#include "timecard.h"
#endif
namespace CSF
{
class ECC_API CC_Call
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_Call)
protected:
CC_Call () { }
virtual ~CC_Call () {}
public:
virtual void setRemoteWindow (VideoWindowHandle window) = 0;
virtual int setExternalRenderer(VideoFormat videoFormat, ExternalRendererHandle renderer) = 0;
virtual void sendIFrame () = 0;
virtual void getLocalSdp(std::string *sdp) const = 0;
virtual void getRemoteSdp(std::string *sdp) const = 0;
virtual fsmdef_states_t getFsmState () const = 0;
virtual std::string fsmStateToString (fsmdef_states_t state) const = 0;
virtual void getErrorString(std::string *error) const = 0;
virtual pc_error getError() const = 0;
virtual CC_CallInfoPtr getCallInfo () = 0;
virtual std::string toString() = 0;
/**
Originate call - API to go offhook and dial specified digits on a given call
@param [in] video_pref - video direction desired on call
@param [in] digits - digits to be dialed. can be empty then this API simply goes offhook
@return true or false.
*/
virtual bool originateCall (cc_sdp_direction_t video_pref, const std::string & digits) = 0;
/**
Use this function to answer an incoming call.
@param[in] video_pref - video direction desired on call
@return true or false.
*/
virtual bool answerCall (cc_sdp_direction_t video_pref) = 0;
/**
Use this function to put an active call on hold.
@param[in] reason - If the user chooses to put the call on hold then
CC_HOLD_REASON_NONE should be the value passed in here.
@return true or false. If it's not appropriate to put this call on
hold at the moment then this function will return false.
*/
virtual bool hold (cc_hold_reason_t reason) = 0;
/**
Use this function to resume a call that is currently on hold.
@param [in] video_pref - video direction desired on call
@return true or false
*/
virtual bool resume (cc_sdp_direction_t video_pref) = 0;
/**
Use this function to end an active call.
@return true or false
*/
virtual bool endCall() = 0;
/**
Send digits on the call - can be invoked either to dial additional digits or send DTMF
@param [in] digit - digit to be dialed
@return true or false
*/
virtual bool sendDigit (cc_digit_t digit) = 0;
/**
Send Backspace - Delete last digit dialed.
@return true or false
*/
virtual bool backspace() = 0;
/**
Redial
@param [in] video_pref - video direction desired on call
@return true or false
*/
virtual bool redial (cc_sdp_direction_t video_pref) = 0;
/**
Initiate Call Forward All
@return true or false
*/
virtual bool initiateCallForwardAll() = 0;
/**
end Consult leg - used to end consult leg when the user picks active calls list for xfer/conf
@return true or false
*/
virtual bool endConsultativeCall() = 0;
/**
Initiate a conference
@param [in] video_pref - video direction desired on consult call
@return true or false
*/
virtual bool conferenceStart (cc_sdp_direction_t video_pref) = 0;
/**
complete conference
@param [in] otherCall - CC_CallPtr of the other leg
@param [in] video_pref - video direction desired on consult call
@return true or false
*/
virtual bool conferenceComplete (CC_CallPtr otherLog, cc_sdp_direction_t video_pref) = 0;
/**
start transfer
@param [in] video_pref - video direction desired on consult call
@return true or false
*/
virtual bool transferStart (cc_sdp_direction_t video_pref) = 0;
/**
complete transfer
@param [in] otherLeg - CC_CallPtr of the other leg
@param [in] video_pref - video direction desired on consult call
@return true or false
*/
virtual bool transferComplete (CC_CallPtr otherLeg,
cc_sdp_direction_t video_pref) = 0;
/**
cancel conference or transfer
@return true or false
*/
virtual bool cancelTransferOrConferenceFeature() = 0;
/**
direct Transfer
@param [in] target - call handle for transfer target call
@return true or false
*/
virtual bool directTransfer (CC_CallPtr target) = 0;
/**
Join Across line
@param [in] target - join target
@return true or false
*/
virtual bool joinAcrossLine (CC_CallPtr target) = 0;
/**
BLF Call Pickup
@param [in] video_pref - video direction preference
@param [in] speed - speedDial Number
@return true or false
*/
virtual bool blfCallPickup (cc_sdp_direction_t video_pref, const std::string & speed) = 0;
/**
Select a call
@return true or false
*/
virtual bool select() = 0;
/**
Update Video Media Cap for the call
@param [in] video_pref - video direction desired on call
@return true or false
*/
virtual bool updateVideoMediaCap (cc_sdp_direction_t video_pref) = 0;
/**
send INFO method for the call
@param [in] handle - call handle
@param [in] infopackage - Info-Package header value
@param [in] infotype - Content-Type header val
@param [in] infobody - Body of the INFO message
@return true or false
*/
virtual bool sendInfo (const std::string & infopackage, const std::string & infotype, const std::string & infobody) = 0;
/**
API to mute audio
@return true if the operation succeeded
NOTE: The mute state is persisted within the stack and shall be remembered across hold/resume.
*/
virtual bool muteAudio(void) = 0;
/**
API to unmute audio
@return true if the operation succeeded
NOTE: The mute state is persisted within the stack and shall be remembered across hold/resume.
*/
virtual bool unmuteAudio(void) = 0;
/**
API to mute video
@return true if the operation succeeded
NOTE: The mute state is persisted within the stack and shall be remembered across hold/resume.
*/
virtual bool muteVideo(void) = 0;
/**
API to unmute video
@return true if the operation succeeded
NOTE: The mute state is persisted within the stack and shall be remembered across hold/resume.
*/
virtual bool unmuteVideo(void) = 0;
/**
API to set the call volume, acceptable values are 0 - 100
@return true if volume set successfully, false if value out of range or change failed
*/
virtual bool setVolume(int volume) = 0;
/**
Originate P2P call - API to go offhook and dial specified digits\user on a given call
@param [in] video_pref - video direction desired on call
@param [in] digits - digits to be dialed. can be empty then this API simply goes offhook
@param [in] ip address - the ip address of the peer to call
@return void
*/
virtual void originateP2PCall (cc_sdp_direction_t video_pref, const std::string & digits, const std::string & ip) = 0;
virtual pc_error createOffer (cc_media_options_t* options, Timecard *) = 0;
virtual pc_error createAnswer(Timecard *) = 0;
virtual pc_error setLocalDescription(cc_jsep_action_t action, const std::string & sdp, Timecard *) = 0;
virtual pc_error setRemoteDescription(cc_jsep_action_t action, const std::string & sdp, Timecard *) = 0;
virtual pc_error setPeerConnection(const std::string& handle) = 0;
virtual pc_error addStream(cc_media_stream_id_t stream_id,
cc_media_track_id_t track_id,
cc_media_type_t media_type) = 0;
virtual pc_error removeStream(cc_media_stream_id_t stream_id, cc_media_track_id_t track_id, cc_media_type_t media_type) = 0;
virtual const std::string& getPeerConnection() const = 0;
virtual pc_error addICECandidate(const std::string & candidate, const std::string & mid, unsigned short level, Timecard *) = 0;
virtual pc_error foundICECandidate(const std::string & candidate, const std::string & mid, unsigned short level, Timecard *) = 0;
};
}

View File

@ -1,339 +0,0 @@
/* 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/. */
#pragma once
#include <set>
extern "C"
{
#include "ccapi_types.h"
#include "fsmdef_states.h"
}
#include "CC_Common.h"
#include "CC_CallTypes.h"
#include "peer_connection_types.h"
#if defined(__cplusplus) && __cplusplus >= 201103L
typedef struct Timecard Timecard;
#else
#include "timecard.h"
#endif
namespace CSF
{
class ECC_API CC_CallInfo
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_CallInfo)
protected:
CC_CallInfo() { }
//Base class needs dtor to be declared as virtual
virtual ~CC_CallInfo() {};
public:
/**
Get the line object associated with this call.
@return CC_LinePtr - line ID
*/
virtual CC_LinePtr getline () = 0;
/**
get Call state
@param [in] handle - call info handle
@return call state
*/
virtual cc_call_state_t getCallState () = 0;
/**
get FSM state
@param [in] handle - call info handle
@return FSM state
*/
virtual fsmdef_states_t getFsmState () const = 0;
/**
print Call state
@param [in] handle - call info handle
@return call state as string
*/
virtual std::string callStateToString (cc_call_state_t state) = 0;
/**
print FSM state
@param [in] handle - call info handle
@return call state as string
*/
virtual std::string fsmStateToString (fsmdef_states_t state) const = 0;
/**
print Call event
@param [in] call event
@return call event as string
*/
virtual std::string callEventToString (ccapi_call_event_e callEvent) = 0;
/**
Get ringer state.
@return bool ringer state.
*/
virtual bool getRingerState() = 0;
/**
Get call attributes
@return cc_call_attr_t.
*/
virtual cc_call_attr_t getCallAttr() = 0;
/**
Get the call type
@return cc_call_type_t for this call. Supported values inlude:
CC_CALL_TYPE_INCOMING, CC_CALL_TYPE_OUTGOING and CC_CALL_TYPE_FORWARDED.
*/
virtual cc_call_type_t getCallType() = 0;
/**
Get called party name
@return called party name
*/
virtual std::string getCalledPartyName() = 0;
/**
Get called party number
@return called party number as a string.
*/
virtual std::string getCalledPartyNumber() = 0;
/**
Get calling party name
@return calling party name
*/
virtual std::string getCallingPartyName() = 0;
/**
Get calling party number
@return calling party number as a string
Note: this is a const reference to a string that's owned by the
*/
virtual std::string getCallingPartyNumber() = 0;
/**
Get alternate number
@return calling party number as a string.
*/
virtual std::string getAlternateNumber() = 0;
/**
This function is used to check if a given capability is supported
based on the information in this CC_CallInfo object.
@param [in] capability - the capability that is to be checked for availability.
@return boolean - returns true if the given capability is available, false otherwise.
*/
virtual bool hasCapability (CC_CallCapabilityEnum::CC_CallCapability capability) = 0;
/**
If you need the complete set of capabilities
@return cc_return_t - set of Call Capabilities.
*/
virtual std::set<CC_CallCapabilityEnum::CC_CallCapability> getCapabilitySet() = 0;
/**
get Original Called party name
@param [in] handle - call info handle
@return original called party name
*/
virtual std::string getOriginalCalledPartyName() = 0;
/**
get Original Called party number
@param [in] handle - call info handle
@return original called party number
*/
virtual std::string getOriginalCalledPartyNumber() = 0;
/**
get last redirecting party name
@param [in] handle - call info handle
@return last redirecting party name
*/
virtual std::string getLastRedirectingPartyName() = 0;
/**
get past redirecting party number
@param [in] handle - call info handle
@return last redirecting party number
*/
virtual std::string getLastRedirectingPartyNumber() = 0;
/**
get placed call party name
@param [in] handle - call info handle
@return placed party name
*/
virtual std::string getPlacedCallPartyName() = 0;
/**
get placed call party number
@param [in] handle - call info handle
@return placed party number
*/
virtual std::string getPlacedCallPartyNumber() = 0;
/**
get call instance number
@param [in] handle - call info handle
@return
*/
virtual cc_int32_t getCallInstance() = 0;
/**
get call status prompt
@param [in] handle - call info handle
@return call status
*/
virtual std::string getStatus() = 0;
/**
get call security // TODO XLS has callagent security and endtoend security on call?
@param [in] handle - call info handle
@return call security status
*/
virtual cc_call_security_t getSecurity() = 0;
/**
get Call Selection Status
@param [in] handle - call info handle
@return bool - TRUE => selected
*/
virtual cc_int32_t getSelectionStatus() = 0;
/**
get GCID
@param [in] handle - call info handle
@return GCID
*/
virtual std::string getGCID() = 0;
/**
get ringer loop count
@param handle - call handle
@return once Vs continuous
*/
virtual bool getIsRingOnce() = 0;
/**
get ringer mode
@param handle - call handle
@return ringer mode
*/
virtual int getRingerMode() = 0;
/**
get onhook reason
@param [in] handle - call info handle
@return onhook reason
*/
virtual cc_int32_t getOnhookReason() = 0;
/**
is Conference Call?
@param [in] handle - call info handle
@return boolean - is Conference
*/
virtual bool getIsConference() = 0;
/**
getStream Statistics
@param [in] handle - call info handle
@param [in,out] stats - Array to get the stats
@param [in,out] count - in len of stats arraysize of stats / out stats copied
@return cc_return_t - CC_SUCCESS or CC_FAILURE
*/
virtual std::set<cc_int32_t> getStreamStatistics() = 0;
/**
Call selection status
@param [in] handle - call info handle
@return bool - selection status
*/
virtual bool isCallSelected() = 0;
/**
INFO Package for RECEIVED_INFO event
@param [in] handle - call info handle
@return string - Info package header
*/
virtual std::string getINFOPack() = 0;
/**
INFO type for RECEIVED_INFO event
@return string - content-type header
*/
virtual std::string getINFOType() = 0;
/**
INFO body for RECEIVED_INFO event
@return string - INFO body
*/
virtual std::string getINFOBody() = 0;
/**
Get the call log reference
//TODO NEED TO DO SOMETHING WRAP CALL LOG REF.
@return string - INFO body
NOTE: Memory associated with the call log is tied to the
this would be freed when the callinfo ref is freed.
*/
virtual cc_calllog_ref_t getCallLogRef() = 0;
/**
returns the negotiated video direction for this call
@return cc_sdp_direction_t - video direction
*/
virtual cc_sdp_direction_t getVideoDirection() = 0;
/**
Find out if this call is capable of querying the media state, which includes mute state and video direction
@return bool
*/
virtual bool isMediaStateAvailable() = 0;
/**
Get the audio mute state if available (check availability with isMediaStateAvailable())
@return bool - the current audio state of the call
*/
virtual bool isAudioMuted(void) = 0;
/**
Get the video mute state if available (check availability with isMediaStateAvailable())
@return bool - the current video state of the call
*/
virtual bool isVideoMuted(void) = 0;
/**
Get the current call volume level
@return int - the current call volume level, or -1 if it cannot be determined
*/
virtual int getVolume() = 0;
};
};

View File

@ -1,50 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include <vector>
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
class ECC_API CC_CallServerInfo
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_CallServerInfo)
protected:
//Base class needs dtor to be declared as virtual
virtual ~CC_CallServerInfo() { }
CC_CallServerInfo() { }
public:
/**
gets call server name
@returns name of the call server
*/
virtual std::string getCallServerName() = 0;
/**
gets call server mode
@returns - mode of the call server
*/
virtual cc_cucm_mode_t getCallServerMode() = 0;
/**
gets calls erver name
@returns status of the call server
*/
virtual cc_ccm_status_t getCallServerStatus() = 0;
};
};

View File

@ -1,50 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include <string>
#include <set>
namespace CSF
{
namespace CC_CallCapabilityEnum
{
typedef enum
{
canSetRemoteWindow,
canSetLocalWindow,
canSendIFrame,
canOriginateCall,
canAnswerCall,
canHold,
canResume,
canEndCall,
canSendDigit,
canBackspace,
canRedial,
canInitiateCallForwardAll,
canEndConsultativeCall,
canConferenceStart,
canConferenceComplete,
canTransferStart,
canTransferComplete,
canCancelTransferOrConferenceFeature,
canDirectTransfer,
canJoinAcrossLine,
canBlfCallPickup,
canSelect,
canUpdateVideoMediaCap,
canSendInfo,
canMuteAudio,
canUnmuteAudio,
canMuteVideo,
canUnmuteVideo,
canSetVolume
} CC_CallCapability;
std::string ECC_API toString(CC_CallCapability cap);
std::string ECC_API toString(std::set<CC_CallCapability>& caps);
};
};

View File

@ -1,34 +0,0 @@
/* 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/. */
#pragma once
#include "SharedPtr.h"
#ifndef ECC_API
#ifdef ECC_EXPORT
#define ECC_API _declspec(dllexport)
#elif ECC_IMPORT
#define ECC_API _declspec(dllimport)
#else
#define ECC_API
#endif
#endif
namespace CSF
{
DECLARE_NS_PTR(CallControlManager)
DECLARE_NS_PTR_VECTOR(PhoneDetails)
DECLARE_NS_PTR(CC_Service)
DECLARE_NS_PTR(VideoControl)
DECLARE_NS_PTR(AudioControl)
DECLARE_NS_PTR_VECTOR(CC_Device)
DECLARE_NS_PTR(CC_DeviceInfo)
DECLARE_NS_PTR(CC_CallServerInfo)
DECLARE_NS_PTR(CC_FeatureInfo)
DECLARE_NS_PTR_VECTOR(CC_Line)
DECLARE_NS_PTR(CC_LineInfo)
DECLARE_NS_PTR_VECTOR(CC_Call)
DECLARE_NS_PTR(CC_CallInfo)
}

View File

@ -1,50 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
class ECC_API CC_Device
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_Device)
protected:
CC_Device() {}
virtual ~CC_Device() {}
public:
virtual std::string toString() = 0;
virtual CC_DeviceInfoPtr getDeviceInfo () = 0;
/**
Create a call on the device. Line selection is on the first available line.
Lines that have their MNC reached will be skipped. If you have a specific line
you want to make a call on (assuming the device has more than available) then
you should use CC_Line::createCall() to do that.
@return CC_CallPtr - the created call object wrapped in a smart_ptr.
*/
virtual CC_CallPtr createCall() = 0;
virtual void enableVideo(bool enable) = 0;
virtual void enableCamera(bool enable) = 0;
virtual void setDigestNamePasswd (char *name, char *pw) = 0;
private:
// Cannot copy - clients should be passing the pointer not the object.
CC_Device& operator=(const CC_Device& rhs);
CC_Device(const CC_Device&);
};
}

View File

@ -1,136 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include <vector>
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
class ECC_API CC_DeviceInfo
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_DeviceInfo)
protected:
CC_DeviceInfo() { }
//Base class needs dtor to be declared as virtual
virtual ~CC_DeviceInfo() {};
public:
/**
gets the device name
@returns - the device name as an std::string
*/
virtual std::string getDeviceName() = 0;
/**
gets the service state
@param [in] handle - reference to device info
@returns cc_service_state_t - INS/OOS
*/
virtual cc_service_state_t getServiceState() = 0;
/**
gets the service cause
@param [in] handle - reference to device info
@returns cc_service_cause_t - reason for service state
*/
virtual cc_service_cause_t getServiceCause() = 0;
/**
gets vector of CC_CallPtr from this CC_DeviceInfo
@returns vector<CC_CallPtr> containing the CC_CallPtrs
*/
virtual std::vector<CC_CallPtr> getCalls () = 0;
/**
gets list of handles to calls on the device by state
@param [in] handle - reference to device info
@param [in] state - call state for which the calls are requested
@param [out] handles - array of call handle to be returned
@param [in,out] count number allocated in array/elements returned
@returns
*/
// void getCallsByState (cc_call_state_t state,
// cc_call_handle_t handles[], cc_uint16_t *count);
/**
gets vector of CC_LinePtr from this CC_DeviceInfo
@returns vector<CC_LinePtr> containing the CC_LinePtrs
*/
virtual std::vector<CC_LinePtr> getLines () = 0;
/**
gets vector of features on the device
@returns
*/
virtual std::vector<CC_FeatureInfoPtr> getFeatures () = 0;
/**
gets handles of call agent servers
@returns
*/
virtual std::vector<CC_CallServerInfoPtr> getCallServers () = 0;
/**
gets call server name
@param [in] handle - handle of call server
@returns name of the call server
NOTE: The memory for return string doesn't need to be freed it will be freed when the info reference is freed
*/
// cc_string_t getCallServerName (cc_callserver_ref_t handle);
/**
gets call server mode
@param [in] handle - handle of call server
@returns - mode of the call server
*/
// cc_cucm_mode_t getCallServerMode (cc_callserver_ref_t handle);
/**
gets calls erver name
@param [in] handle - handle of call server
@returns status of the call server
*/
// cc_ccm_status_t getCallServerStatus (cc_callserver_ref_t handle);
/**
get the NOTIFICATION PROMPT
@param [in] handle - reference to device info
@returns
*/
// cc_string_t getNotifyPrompt ();
/**
get the NOTIFICATION PROMPT PRIORITY
@param [in] handle - reference to device info
@returns
*/
// cc_uint32_t getNotifyPromptPriority ();
/**
get the NOTIFICATION PROMPT Progress
@param [in] handle - reference to device info
@returns
*/
// cc_uint32_t getNotifyPromptProgress ();
private:
// Cannot copy - clients should be passing the pointer not the object.
CC_DeviceInfo& operator=(const CC_DeviceInfo& rhs);
CC_DeviceInfo(const CC_DeviceInfo&);
};
};

View File

@ -1,76 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
class ECC_API CC_FeatureInfo
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_FeatureInfo)
protected:
CC_FeatureInfo() { }
//Base class needs dtor to be declared as virtual
virtual ~CC_FeatureInfo() {};
public:
/**
Get the physical button number on which this feature is configured
@return cc_int32_t - button assgn to the feature
*/
virtual cc_int32_t getButton() = 0;
/**
Get the featureID
@return cc_int32_t - button assgn to the feature
*/
virtual cc_int32_t getFeatureID() = 0;
/**
Get the feature Name
@return string - handle of the feature created
*/
virtual std::string getDisplayName() = 0;
/**
Get the speeddial Number
@return string - handle of the feature created
*/
virtual std::string getSpeedDialNumber() = 0;
/**
Get the contact
@return string - handle of the feature created
*/
virtual std::string getContact() = 0;
/**
Get the retrieval prefix
@return string - handle of the feature created
*/
virtual std::string getRetrievalPrefix() = 0;
/**
Get the feature option mask
@return cc_int32_t - button assgn to the feature
*/
virtual cc_int32_t getFeatureOptionMask() = 0;
};
};

View File

@ -1,32 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
class ECC_API CC_Line
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_Line)
protected:
CC_Line () { }
virtual ~CC_Line () {};
public:
virtual std::string toString() = 0;
virtual cc_lineid_t getID() = 0;
virtual CC_LineInfoPtr getLineInfo () = 0;
virtual CC_CallPtr createCall () = 0;
};
};

View File

@ -1,152 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include <bitset>
#include <set>
#include <vector>
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
class ECC_API CC_LineInfo
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_LineInfo)
protected:
CC_LineInfo() { }
//Base class needs dtor to be declared as virtual
virtual ~CC_LineInfo() {};
public:
/**
Get the line Name
@return string - line Name
*/
virtual std::string getName() = 0;
/**
Get the line DN Number
@return string - line DN
*/
virtual std::string getNumber() = 0;
/**
Get the physical button number on which this line is configured
@return cc_uint32_t - button number
*/
virtual cc_uint32_t getButton() = 0;
/**
Get the Line Type
@return cc_line_feature_t - line featureID ( Line )
*/
virtual cc_line_feature_t getLineType() = 0;
/**
@return bool - true if phone is currently registered with CM.
*/
virtual bool getRegState() = 0;
/**
Get the CFWDAll status for the line
@return bool - isForwarded
*/
virtual bool isCFWDActive() = 0;
/**
Get the CFWDAll destination
@return string - cfwd target
*/
virtual std::string getCFWDName() = 0;
/**
Get calls on line
@param [in] line - line
@return vector<CC_CallPtr>
*/
virtual std::vector<CC_CallPtr> getCalls (CC_LinePtr linePtr) = 0;
/**
Get calls on line by state
@param [in] line - line
@param [in] state - state
@return vector<CC_CallPtr>
*/
virtual std::vector<CC_CallPtr> getCallsByState (CC_LinePtr linePtr, cc_call_state_t state) = 0;
/**
Get the MWI Status
@return cc_uint32_t - MWI status (boolean 0 => no MWI)
*/
virtual bool getMWIStatus() = 0;
/**
Get the MWI Type
@return cc_uint32_t - MWI Type
*/
virtual cc_uint32_t getMWIType() = 0;
/**
Get the MWI new msg count
@return cc_uint32_t - MWI new msg count
*/
virtual cc_uint32_t getMWINewMsgCount() = 0;
/**
Get the MWI old msg count
@return cc_uint32_t - MWI old msg count
*/
virtual cc_uint32_t getMWIOldMsgCount() = 0;
/**
Get the MWI high priority new msg count
@return cc_uint32_t - MWI new msg count
*/
virtual cc_uint32_t getMWIPrioNewMsgCount() = 0;
/**
Get the MWI high priority old msg count
@return cc_uint32_t - MWI old msg count
*/
virtual cc_uint32_t getMWIPrioOldMsgCount() = 0;
/**
has capability - is the feature allowed
@param [in] capability - capability being queried to see if it's available
@return bool - is Allowed
*/
virtual bool hasCapability(ccapi_call_capability_e capability) = 0;
/**
get Allowed Feature set
@return cc_return_t - bitset of Line Capabilities.
*/
virtual std::bitset<CCAPI_CALL_CAP_MAX> getCapabilitySet() = 0;
};
};

View File

@ -1,28 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
extern "C"
{
#include "ccapi_types.h"
}
namespace CSF
{
/**
* These callbacks relate to the "core" Call Control API objects CC_Device, CC_Line and CC_Call.
*/
class ECC_API CC_Observer
{
public:
virtual void onDeviceEvent ( ccapi_device_event_e deviceEvent, CC_DevicePtr device, CC_DeviceInfoPtr info ) = 0;
virtual void onFeatureEvent ( ccapi_device_event_e deviceEvent, CC_DevicePtr device, CC_FeatureInfoPtr feature_info) = 0;
virtual void onLineEvent ( ccapi_line_event_e lineEvent, CC_LinePtr line, CC_LineInfoPtr info ) = 0;
virtual void onCallEvent ( ccapi_call_event_e callEvent, CC_CallPtr call, CC_CallInfoPtr infog ) = 0;
};
}

View File

@ -1,87 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include "CC_Observer.h"
#include <vector>
extern "C"
{
#include "ccapi_types.h"
#include "ccapi_service.h"
}
namespace CSF
{
class ECC_API CC_Service
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CC_Service)
protected:
CC_Service() {}
virtual ~CC_Service() {};
public:
/**
* Clients use CC_Observer to receive CCAPI events (Device, Line, Call) from the service.
*/
virtual void addCCObserver ( CC_Observer * observer ) = 0;
virtual void removeCCObserver ( CC_Observer * observer ) = 0;
/**
* Use init() immediately on creating the service, and destroy() when finished with it.
* password is required for Asterisk not CUCM.
* deviceName is required for CUCM not Asterisk.
*/
virtual bool init(const std::string& user, const std::string& password, const std::string& domain, const std::string& deviceName) = 0;
virtual void destroy() = 0;
/**
* TODO: Set config parameters prior to starting the service.
* Need to design a nice abstraction for this accommodating SIPCC and CTI.
*/
/**
* Use start() to attempt to register for a device and stop() to cancel a current
* registration (or registration attempt).
*/
virtual bool startService() = 0;
virtual void stop() = 0;
/**
* Check on the current status/health of the service.
*/
virtual bool isStarted() = 0;
/**
* Obtain the currently selected Device.
* If multiple devices are discoverable (i.e. in CTI), all known devices will appear
* in getDevices(), but only the ActiveDevice will be controllable at any given time.
*/
virtual CC_DevicePtr getActiveDevice() = 0;
virtual std::vector<CC_DevicePtr> getDevices() = 0;
/**
* Global settings for audio and video control. Return nullptr if Media control is not
* available in this implementation. Return nullptr in any case if media is not yet
* initialized.
* TODO: Assuming for now that media init aligns with init/destroy.
*/
virtual AudioControlPtr getAudioControl() = 0;
virtual VideoControlPtr getVideoControl() = 0;
virtual bool setLocalVoipPort(int port) = 0;
virtual bool setRemoteVoipPort(int port) = 0;
virtual bool setP2PMode(bool mode) = 0;
virtual bool setSDPMode(bool mode) = 0;
private:
CC_Service(const CC_Service& rhs);
CC_Service& operator=(const CC_Service& rhs);
};
}

View File

@ -1,36 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
namespace CSF
{
DECLARE_NS_PTR(AudioControl)
class ECC_API AudioControl
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AudioControl)
// device names are in UTF-8 encoding
virtual std::vector<std::string> getRecordingDevices() = 0;
virtual std::vector<std::string> getPlayoutDevices() = 0;
virtual std::string getRecordingDevice() = 0;
virtual std::string getPlayoutDevice() = 0;
virtual bool setRecordingDevice( const std::string& name ) = 0;
virtual bool setPlayoutDevice( const std::string& name ) = 0;
virtual bool setDefaultVolume( int ) = 0;
virtual int getDefaultVolume() = 0;
virtual bool setRingerVolume( int ) = 0;
virtual int getRingerVolume() = 0;
protected:
virtual ~AudioControl(){};
};
};

View File

@ -1,36 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include "ECC_Types.h"
#include <string>
#include <vector>
namespace CSF
{
DECLARE_NS_PTR(VideoControl)
class ECC_API VideoControl
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoControl)
virtual void setVideoMode( bool enable ) = 0;
// window type is platform-specific
virtual void setPreviewWindow( VideoWindowHandle window, int top, int left, int bottom, int right, RenderScaling style ) = 0;
virtual void showPreviewWindow( bool show ) = 0;
// device names are in UTF-8 encoding
virtual std::vector<std::string> getCaptureDevices() = 0;
virtual std::string getCaptureDevice() = 0;
virtual bool setCaptureDevice( const std::string& name ) = 0;
protected:
virtual ~VideoControl() {};
};
}; // namespace

View File

@ -1,130 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include "CC_Observer.h"
#include "ECC_Observer.h"
#include "ECC_Types.h"
#include <string>
#include <vector>
/**
* @mainpage Enhanced Call Control
*
* @section intro_sec Introduction
* This wraps and aggregates the SIPCC and CTI call control stacks, media stacks, and various additional
* components and glue necessary to start, configure and run them, and presents a high-level C++ API
* for connection, device selection and status, and call control.
*
* @section main_outline Outline
* @li The main entry point is CSF::CallControlManager, which is used to configure and start a
* call control stack.
* @li Configuration and events are raised to the CSF::ECC_Observer interface.
* @li Call Control is performed via CSF::CC_Device, CSF::CC_Line and CSF::CC_Call.
* @li Call Control events are raised to the CSF::CC_Observer interface.
* @li Audio/Video device selection and global media configuration is performed via CSF::AudioControl
* and CSF::VideoControl. Per-call media operations (mute, volume, etc) are integrated onto
* the CSF::CC_Call and CSF::CC_CallInfo interfaces.
*/
namespace CSF
{
DECLARE_NS_PTR(CallControlManager)
/**
* CallControlManager
*
* The class is partitioned into several blocks of functionality:
* - Create/Destroy - Initialisation and clean shutdown.
* Destroy is optional if the destructor is used properly.
* - Observer - Register for events when any state changes. Optional but strongly advised.
*
* Methods are generally synchronous (at present).
*/
class ECC_API CallControlManager
{
protected:
virtual ~CallControlManager();
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CallControlManager)
/**
* Use create() to create a CallControlManager instance.
*
* CallControlManager cleans up its resources in its destructor, implicitly disconnect()in if required.
* Use the destroy() method if you need to force a cleanup earlier. It is a bad idea to continue using
* CallControlManager or any of its related objects after destroy().
*/
static CallControlManagerPtr create();
virtual bool destroy() = 0;
/**
CC_Observer is for core call control events (on CC_Device, CC_Line and CC_Call).
ECC_Observer is for "value add" features of CallControlManager.
Client can add multiple observers if they have different Observer objects that handle
different event scenarios, but generally it's probably sufficient to only register one observer.
@param[in] observer - This is a pointer to a CC_Observer-derived class that the client
must instantiate to receive notifications on this client object.
*/
virtual void addCCObserver ( CC_Observer * observer ) = 0;
virtual void removeCCObserver ( CC_Observer * observer ) = 0;
virtual void addECCObserver ( ECC_Observer * observer ) = 0;
virtual void removeECCObserver ( ECC_Observer * observer ) = 0;
virtual void setMultiClusterMode(bool allowMultipleClusters) = 0;
virtual void setSIPCCLoggingMask(const cc_int32_t mask) = 0;
virtual void setAuthenticationString(const std::string &authString) = 0;
virtual void setSecureCachePath(const std::string &secureCachePath) = 0;
// Add local codecs
virtual void setAudioCodecs(int codecMask) = 0;
virtual void setVideoCodecs(int codecMask) = 0;
virtual bool registerUser(const std::string& deviceName, const std::string& user, const std::string& password, const std::string& domain) = 0;
virtual bool disconnect() = 0;
virtual std::string getPreferredDeviceName() = 0;
virtual std::string getPreferredLineDN() = 0;
virtual ConnectionStatusEnum::ConnectionStatus getConnectionStatus() = 0;
virtual std::string getCurrentServer() = 0;
/* P2P MODE */
virtual bool startP2PMode(const std::string& user) = 0;
/* SDP MODE */
virtual bool startSDPMode() = 0;
/**
* Obtain the device object, from which call control can be done.
* getAvailablePhoneDetails lists all known devices which the user is likely to be able to control.
*/
virtual CC_DevicePtr getActiveDevice() = 0;
virtual PhoneDetailsVtrPtr getAvailablePhoneDetails() = 0;
virtual PhoneDetailsPtr getAvailablePhoneDetails(const std::string& deviceName) = 0;
/**
* Obtain the audio/video object, from which video setup can be done.
* This relates to global tuning, device selection, preview window positioning, etc, not to
* per-call settings or control.
*
* These objects are unavailable except while in softphone mode.
*/
virtual VideoControlPtr getVideoControl() = 0;
virtual AudioControlPtr getAudioControl() = 0;
virtual bool setProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key, std::string& value) = 0;
virtual std::string getProperty(ConfigPropertyKeysEnum::ConfigPropertyKeys key) = 0;
protected:
CallControlManager() {}
private:
CallControlManager(const CallControlManager&);
CallControlManager& operator=(const CallControlManager&);
};
} //end namespace CSF

View File

@ -1,27 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
#include "ECC_Types.h"
namespace CSF
{
/**
* These callbacks relate to CallControlManager's "value add" features relating to authentication,
* configuration, setup, service health and management of SIP.
*
* They do not relate to call control - see also CC_Observer.
*/
class ECC_API ECC_Observer
{
public:
virtual void onAvailablePhoneEvent (AvailablePhoneEventType::AvailablePhoneEvent event,
const PhoneDetailsPtr availablePhoneDetails) = 0;
virtual void onAuthenticationStatusChange (AuthenticationStatusEnum::AuthenticationStatus) = 0;
virtual void onConnectionStatusChange(ConnectionStatusEnum::ConnectionStatus status) = 0;
};
}

View File

@ -1,152 +0,0 @@
/* 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/. */
#pragma once
#include "CC_Common.h"
/*
These #defines are for use with CallControlManager::createSoftphone(..., const cc_int32_t mask) parameter as follows:
CallControlManager::createSoftphone(..., GSM_DEBUG_BIT | FIM_DEBUG_BIT | LSM_DEBUG_BIT );
This turns on debugging for the three areas (and disables logging in all other areas) of pSIPCC logging specified.
*/
#define SIP_DEBUG_MSG_BIT (1 << 0) // Bit 0
#define SIP_DEBUG_STATE_BIT (1 << 1) // Bit 1
#define SIP_DEBUG_TASK_BIT (1 << 2) // Bit 2
#define SIP_DEBUG_REG_STATE_BIT (1 << 3) // Bit 3
#define GSM_DEBUG_BIT (1 << 4) // Bit 4
#define FIM_DEBUG_BIT (1 << 5) // Bit 5
#define LSM_DEBUG_BIT (1 << 6) // Bit 6
#define FSM_DEBUG_SM_BIT (1 << 7) // Bit 7
#define CSM_DEBUG_SM_BIT (1 << 8) // Bit 8
#define CC_DEBUG_BIT (1 << 9) // Bit 9
#define CC_DEBUG_MSG_BIT (1 << 10) // Bit 10
#define AUTH_DEBUG_BIT (1 << 11) // Bit 11
#define CONFIG_DEBUG_BIT (1 << 12) // Bit 12
#define DPINT_DEBUG_BIT (1 << 13) // Bit 13
#define KPML_DEBUG_BIT (1 << 15) // Bit 15
#define VCM_DEBUG_BIT (1 << 17) // Bit 17
#define CC_APP_DEBUG_BIT (1 << 18) // Bit 18
#define CC_LOG_DEBUG_BIT (1 << 19) // Bit 19
#define TNP_DEBUG_BIT (1 << 20) // Bit 20
namespace CSFUnified
{
DECLARE_PTR(DeviceInfo)
}
namespace CSF
{
namespace AuthenticationFailureCodeType
{
typedef enum {
eNoError,
eNoServersConfigured,
eNoCredentialsConfigured,
eCouldNotConnect,
eServerCertificateRejected,
eCredentialsRejected,
eResponseEmpty,
eResponseInvalid
} AuthenticationFailureCode;
std::string ECC_API toString(AuthenticationFailureCode value);
}
namespace AuthenticationStatusEnum
{
typedef enum {
eNotAuthenticated,
eInProgress,
eAuthenticated,
eFailed
} AuthenticationStatus;
std::string ECC_API toString(AuthenticationStatus value);
}
namespace DeviceRetrievalFailureCodeType
{
typedef enum {
eNoError,
eNoServersConfigured,
eNoDeviceNameConfigured,
eCouldNotConnect,
eFileNotFound,
eFileEmpty,
eFileInvalid
} DeviceRetrievalFailureCode;
std::string ECC_API toString(DeviceRetrievalFailureCode value);
}
namespace ConnectionStatusEnum
{
typedef enum {
eIdle,
eNone,
eFetchingDeviceConfig,
eRegistering,
eReady,
eConnectedButNoDeviceReady,
eRetrying,
eFailed
} ConnectionStatus;
std::string ECC_API toString(ConnectionStatus value);
}
namespace ServiceStateType {
typedef enum
{
eUnknown,
eInService,
eOutOfService
} ServiceState;
std::string ECC_API toString(ServiceState value);
}
namespace AvailablePhoneEventType
{
typedef enum {
eFound, // New Phone device discovered and added to the Available list.
eUpdated, // Change to an existing Phone details record in the Available list.
eLost // Phone device removed from the Available list.
} AvailablePhoneEvent;
std::string ECC_API toString(AvailablePhoneEvent value);
}
namespace ConfigPropertyKeysEnum
{
typedef enum {
eLocalVoipPort,
eRemoteVoipPort,
eVersion,
eTransport
} ConfigPropertyKeys;
}
typedef enum
{
VideoEnableMode_DISABLED,
VideoEnableMode_SENDONLY,
VideoEnableMode_RECVONLY,
VideoEnableMode_SENDRECV
} VideoEnableMode;
typedef enum // scaling from codec size to render window size
{
RenderScaling_NONE, // 1:1 actual pixels, crop and/or fill
RenderScaling_TO_FIT, // scale to fit, without preserving aspect ratio
RenderScaling_BORDER, // scale to fit, fill without cropping
RenderScaling_CROP // scale to fit, crop without filling
} RenderScaling;
typedef void *VideoWindowHandle;
typedef void* ExternalRendererHandle;
typedef unsigned int VideoFormat;
}

View File

@ -1,60 +0,0 @@
/* 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/. */
#pragma once
#include <string>
#include "CC_Common.h"
#include "ECC_Types.h"
namespace CSF
{
DECLARE_NS_PTR_VECTOR(PhoneDetails);
class ECC_API PhoneDetails
{
protected:
virtual ~PhoneDetails() {}
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PhoneDetails)
/**
* Get the device name (the CUCM device name) and the free text description.
*/
virtual std::string getName() const = 0;
virtual std::string getDescription() const = 0;
/**
* Get the model number (the internal CUCM number, not the number printed on the phone)
* and the corresponding description (which normally does include the number printed on the phone).
* Returns -1, "" if unknown
*/
virtual int getModel() const = 0;
virtual std::string getModelDescription() const = 0;
virtual bool isSoftPhone() = 0;
/**
* List the known directory numbers of lines associated with the device.
* Empty list if unknown.
*/
virtual std::vector<std::string> getLineDNs() const = 0;
/**
* Current status of the device, if known.
*/
virtual ServiceStateType::ServiceState getServiceState() const = 0;
/**
* TFTP config of device, and freshness of the config.
*/
virtual std::string getConfig() const = 0;
protected:
PhoneDetails() {}
private:
PhoneDetails(const PhoneDetails&);
PhoneDetails& operator=(const PhoneDetails&);
};
};

View File

@ -1,44 +0,0 @@
/* 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/. */
#pragma once
#include <vector>
#include "base/linked_ptr.h"
#include "nsAutoPtr.h"
#ifndef DECLARE_PTR
#define DECLARE_PTR(className)\
class className;\
typedef linked_ptr<className> className##Ptr;
#endif
#ifndef DECLARE_PTR_VECTOR
#define DECLARE_PTR_VECTOR(className)\
DECLARE_PTR(className)\
typedef std::vector<className##Ptr> className##Vtr;\
typedef linked_ptr<className##Vtr> className##Vtr##Ptr;
#endif
#ifndef NULL_PTR
#define NULL_PTR(className) linked_ptr<className>()
#endif
// NSPR Variations of the above, to help with migration
// from linked_ptr to nsRefPtr
#ifndef DECLARE_NS_PTR
#define DECLARE_NS_PTR(className)\
class className;\
typedef nsRefPtr<className> className##Ptr;
#endif
#ifndef DECLARE_NS_PTR_VECTOR
#define DECLARE_NS_PTR_VECTOR(className)\
DECLARE_NS_PTR(className)\
typedef std::vector<className##Ptr> className##Vtr;\
typedef linked_ptr<className##Vtr> className##Vtr##Ptr;
#endif

View File

@ -1,53 +0,0 @@
/* 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 T1_DEBUG_H
#define T1_DEBUG_H
#include "CC_Common.h"
extern "C"
{
#include <ccapi_service.h>
#include "ccapi_types.h"
ECC_API cc_string_t device_event_getname(ccapi_device_event_e);
ECC_API cc_string_t call_event_getname(ccapi_call_event_e);
ECC_API cc_string_t line_event_getname(ccapi_line_event_e);
ECC_API cc_string_t digit_getname(cc_digit_t);
ECC_API cc_string_t cucm_mode_getname(cc_cucm_mode_t);
ECC_API cc_string_t line_feature_getname(cc_line_feature_t);
ECC_API cc_string_t feature_option_mask_getname(cc_feature_option_mask_t);
ECC_API cc_string_t service_cause_getname(cc_service_cause_t);
ECC_API cc_string_t service_state_getname(cc_service_state_t);
ECC_API cc_string_t ccm_status_getname(cc_ccm_status_t);
ECC_API cc_string_t line_reg_state_getname(cc_line_reg_state_t);
ECC_API cc_string_t shutdown_reason_getname(cc_shutdown_reason_t);
ECC_API cc_string_t kpml_config_getname(cc_kpml_config_t);
ECC_API cc_string_t upgrade_getname(cc_upgrade_t);
ECC_API cc_string_t sdp_direction_getname(cc_sdp_direction_t);
ECC_API cc_string_t blf_state_getname(cc_blf_state_t);
ECC_API cc_string_t blf_feature_mask_getname(cc_blf_feature_mask_t);
ECC_API cc_string_t call_state_getname(cc_call_state_t);
ECC_API cc_string_t call_attr_getname(cc_call_attr_t);
ECC_API cc_string_t hold_reason_getname(cc_hold_reason_t);
ECC_API cc_string_t call_type_getname(cc_call_type_t);
ECC_API cc_string_t call_security_getname(cc_call_security_t);
ECC_API cc_string_t call_policy_getname(cc_call_policy_t);
ECC_API cc_string_t log_disposition_getname(cc_log_disposition_t);
ECC_API cc_string_t call_priority_getname(cc_call_priority_t);
ECC_API cc_string_t call_selection_getname(cc_call_selection_t);
ECC_API cc_string_t call_capability_getname(ccapi_call_capability_e);
ECC_API cc_string_t srv_ctrl_req_getname(cc_srv_ctrl_req_t);
ECC_API cc_string_t srv_ctrl_cmd_getname(cc_srv_ctrl_cmd_t);
ECC_API cc_string_t message_type_getname(cc_message_type_t);
ECC_API cc_string_t lamp_state_getname(cc_lamp_state_t);
ECC_API cc_string_t cause_getname(cc_cause_t);
ECC_API cc_string_t subscriptions_ext_getname(cc_subscriptions_ext_t);
ECC_API cc_string_t apply_config_result_getname(cc_apply_config_result_t);
}
#endif /* T1_DEBUG_H */

View File

@ -10,19 +10,9 @@
#include "base/basictypes.h"
#include <map>
#include "cpr_threads.h"
#include "prrwlock.h"
#include "prthread.h"
#include "nsThreadUtils.h"
#ifndef WIN32
#include <pthread.h>
#endif
#ifdef OS_MACOSX
#include <dlfcn.h>
#endif
#ifdef OS_LINUX
#include <sys/prctl.h>
#endif
static PRLogModuleInfo *gLogModuleInfo = nullptr;
@ -44,81 +34,6 @@ PRLogModuleInfo *GetWebRTCLogInfo()
return gWebRTCLogModuleInfo;
}
extern "C" {
void CSFLogRegisterThread(const cprThread_t thread);
void CSFLogUnregisterThread(const cprThread_t thread);
#ifndef WIN32
pthread_t cprGetThreadId(cprThread_t thread);
#endif
}
#ifdef WIN32
typedef unsigned int thread_key_t;
#else
typedef pthread_t thread_key_t;
#endif
static PRRWLock *maplock = PR_NewRWLock(0,"thread map");
typedef std::map<thread_key_t,const cpr_thread_t*> threadMap_t;
static threadMap_t threadMap;
void CSFLogRegisterThread(const cprThread_t thread) {
const cpr_thread_t *t = reinterpret_cast<cpr_thread_t *>(thread);
thread_key_t key;
#ifdef WIN32
key = t->threadId;
#else
key = cprGetThreadId(thread);
#endif
CSFLog(CSF_LOG_DEBUG, __FILE__, __LINE__, "log",
"Registering new thread with logging system: %s", t->name);
PR_RWLock_Wlock(maplock);
threadMap[key] = t;
PR_RWLock_Unlock(maplock);
}
void CSFLogUnregisterThread(const cprThread_t thread) {
const cpr_thread_t *t = reinterpret_cast<cpr_thread_t *>(thread);
thread_key_t key;
#ifdef WIN32
key = t->threadId;
#else
key = cprGetThreadId(thread);
#endif
CSFLog(CSF_LOG_DEBUG, __FILE__, __LINE__, "log",
"Unregistering thread from logging system: %s", t->name);
PR_RWLock_Wlock(maplock);
threadMap.erase(key);
PR_RWLock_Unlock(maplock);
}
const char *CSFCurrentThreadName() {
const char *name = nullptr;
#ifdef WIN32
thread_key_t key = GetCurrentThreadId();
#else
thread_key_t key = pthread_self();
#endif
PR_RWLock_Rlock(maplock);
threadMap_t::iterator i = threadMap.find(key);
if (i != threadMap.end()) {
name = i->second->name;
}
PR_RWLock_Unlock(maplock);
return name;
}
#ifdef OS_MACOSX
// pthread_getname_np isn't available on all versions of OS X, so
// we need to load it in dynamically and check for its presence
static int (*dynamic_pthread_getname_np)(pthread_t,char*,size_t);
bool init_pthread_getname() {
*reinterpret_cast<void**>(&dynamic_pthread_getname_np) =
dlsym(RTLD_DEFAULT, "pthread_getname_np");
return dynamic_pthread_getname_np;
}
static bool have_pthread_getname_np = init_pthread_getname();
#endif
void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine, const char* tag , const char* format, va_list args)
{
@ -151,40 +66,16 @@ void CSFLogV(CSFLogLevel priority, const char* sourceFile, int sourceLine, const
#define MAX_MESSAGE_LENGTH 1024
char message[MAX_MESSAGE_LENGTH];
char buffer[64] = "";
const char *threadName = CSFCurrentThreadName();
const char *threadName = NULL;
// Check if we're the main thread...
if (!threadName && NS_IsMainThread()) {
if (NS_IsMainThread()) {
threadName = "main";
}
// If null, the name wasn't set up by CPR -- try NSPR
if (!threadName) {
} else {
threadName = PR_GetThreadName(PR_GetCurrentThread());
}
// If not NSPR, it might be from some other imported library that uses
// one of the variety of non-portable means of naming threads.
#ifdef OS_LINUX
if (!threadName &&
!prctl(PR_GET_NAME,reinterpret_cast<uintptr_t>(buffer),0,0,0)) {
buffer[16]='\0';
if (buffer[0] != '\0') {
threadName = buffer;
}
}
#endif
#ifdef OS_MACOSX
if (!threadName && have_pthread_getname_np) {
dynamic_pthread_getname_np(pthread_self(), buffer, sizeof(buffer));
if (buffer[0] != '\0') {
threadName = buffer;
}
}
#endif
// If we can't find it anywhere, use a blank string
if (!threadName) {
threadName = "";

View File

@ -88,8 +88,9 @@ print_timecard(Timecard *tc)
}
}
printf("\nTimecard created %4lld.%6.6lld\n\n",
tc->start_time / PR_USEC_PER_SEC, tc->start_time % PR_USEC_PER_SEC);
printf("\nTimecard created %4ld.%6.6ld\n\n",
(long)(tc->start_time / PR_USEC_PER_SEC),
(long)(tc->start_time % PR_USEC_PER_SEC));
line_width = 1 + 11 + 11 + event_width + file_width + 6 +
function_width + (4 * 3);
@ -113,9 +114,9 @@ print_timecard(Timecard *tc)
} else {
delta = entry->timestamp - tc->start_time;
}
printf(" %4lld.%6.6lld | %4lld.%6.6lld | %-*s | %*s:%-5d | %-*s\n",
offset / PR_USEC_PER_SEC, offset % PR_USEC_PER_SEC,
delta / PR_USEC_PER_SEC, delta % PR_USEC_PER_SEC,
printf(" %4ld.%6.6ld | %4ld.%6.6ld | %-*s | %*s:%-5d | %-*s\n",
(long)(offset / PR_USEC_PER_SEC), (long)(offset % PR_USEC_PER_SEC),
(long)(delta / PR_USEC_PER_SEC), (long)(delta % PR_USEC_PER_SEC),
(int)event_width, entry->event,
(int)file_width, entry->file, entry->line,
(int)function_width, entry->function);

View File

@ -861,6 +861,10 @@ WebrtcAudioConduit::CodecConfigToWebRTCCodec(const AudioCodecConfig* codecInfo,
cinst.rate = codecInfo->mRate;
cinst.pacsize = codecInfo->mPacSize;
cinst.plfreq = codecInfo->mFreq;
if (codecInfo->mName == "G722") {
// Compensate for G.722 spec error in RFC 1890
cinst.plfreq = 16000;
}
cinst.channels = codecInfo->mChannels;
return true;
}

View File

@ -7,7 +7,7 @@
#define CODEC_CONFIG_H_
#include <string>
#include "ccsdp_rtcp_fb.h"
#include <vector>
namespace mozilla {
@ -76,7 +76,11 @@ public:
*/
int mType; // payload type
std::string mName;
uint32_t mRtcpFbTypes;
std::vector<std::string> mAckFbTypes;
std::vector<std::string> mNackFbTypes;
std::vector<std::string> mCcmFbTypes;
unsigned int mMaxFrameSize;
unsigned int mMaxFrameRate;
unsigned int mMaxMBPS; // in macroblocks-per-second
@ -91,13 +95,11 @@ public:
VideoCodecConfig(int type,
std::string name,
int rtcpFbTypes,
unsigned int max_fs = 0,
unsigned int max_fr = 0,
const struct VideoCodecConfigH264 *h264 = nullptr) :
mType(type),
mName(name),
mRtcpFbTypes(rtcpFbTypes),
mMaxFrameSize(max_fs), // may be overridden
mMaxFrameRate(max_fr),
mMaxMBPS(0),
@ -121,19 +123,36 @@ public:
}
}
bool RtcpFbIsSet(sdp_rtcp_fb_nack_type_e type) const
// Nothing seems to use this right now. Do we intend to support this
// someday?
bool RtcpFbAckIsSet(const std::string& type) const
{
return mRtcpFbTypes & sdp_rtcp_fb_nack_to_bitmap(type);
for (auto i = mAckFbTypes.begin(); i != mAckFbTypes.end(); ++i) {
if (*i == type) {
return true;
}
}
return false;
}
bool RtcpFbIsSet(sdp_rtcp_fb_ack_type_e type) const
bool RtcpFbNackIsSet(const std::string& type) const
{
return mRtcpFbTypes & sdp_rtcp_fb_ack_to_bitmap(type);
for (auto i = mNackFbTypes.begin(); i != mNackFbTypes.end(); ++i) {
if (*i == type) {
return true;
}
}
return false;
}
bool RtcpFbIsSet(sdp_rtcp_fb_ccm_type_e type) const
bool RtcpFbCcmIsSet(const std::string& type) const
{
return mRtcpFbTypes & sdp_rtcp_fb_ccm_to_bitmap(type);
for (auto i = mCcmFbTypes.begin(); i != mCcmFbTypes.end(); ++i) {
if (*i == type) {
return true;
}
}
return false;
}
};
}

View File

@ -288,21 +288,21 @@ MediaConduitErrorCode WebrtcVideoConduit::Init(WebrtcVideoConduit *other)
if (branch)
{
int32_t temp;
NS_WARN_IF(NS_FAILED(branch->GetBoolPref("media.video.test_latency", &mVideoLatencyTestEnable)));
NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.min_bitrate", &temp)));
(void) NS_WARN_IF(NS_FAILED(branch->GetBoolPref("media.video.test_latency", &mVideoLatencyTestEnable)));
(void) NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.min_bitrate", &temp)));
if (temp >= 0) {
mMinBitrate = temp;
}
NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.start_bitrate", &temp)));
(void) NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.start_bitrate", &temp)));
if (temp >= 0) {
mStartBitrate = temp;
}
NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.max_bitrate", &temp)));
(void) NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.max_bitrate", &temp)));
if (temp >= 0) {
mMaxBitrate = temp;
}
bool use_loadmanager = false;
NS_WARN_IF(NS_FAILED(branch->GetBoolPref("media.navigator.load_adapt", &use_loadmanager)));
(void) NS_WARN_IF(NS_FAILED(branch->GetBoolPref("media.navigator.load_adapt", &use_loadmanager)));
if (use_loadmanager) {
mLoadManager = LoadManagerBuild();
}
@ -657,7 +657,7 @@ WebrtcVideoConduit::ConfigureSendMediaCodec(const VideoCodecConfig* codecConfig)
mSendingWidth = 0;
mSendingHeight = 0;
if(codecConfig->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC)) {
if(codecConfig->RtcpFbNackIsSet("")) {
CSFLogDebug(logTag, "Enabling NACK (send) for video stream\n");
if (mPtrRTP->SetNACKStatus(mChannel, true) != 0)
{
@ -740,17 +740,17 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
// Check for the keyframe request type: PLI is preferred
// over FIR, and FIR is preferred over none.
if (codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_NACK_PLI))
if (codecConfigList[i]->RtcpFbNackIsSet("pli"))
{
kf_request = webrtc::kViEKeyFrameRequestPliRtcp;
} else if(kf_request == webrtc::kViEKeyFrameRequestNone &&
codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_CCM_FIR))
codecConfigList[i]->RtcpFbCcmIsSet("fir"))
{
kf_request = webrtc::kViEKeyFrameRequestFirRtcp;
}
// Check whether NACK is requested
if(codecConfigList[i]->RtcpFbIsSet(SDP_RTCP_FB_NACK_BASIC))
if(codecConfigList[i]->RtcpFbNackIsSet(""))
{
use_nack_basic = true;
}
@ -1278,7 +1278,7 @@ WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
// hand or from a config fetched with GetConfig(); this modifies the config
// to match parameters from VideoCodecConfig
cinst.plType = codecInfo->mType;
if (codecInfo->mName == "H264_P0" || codecInfo->mName == "H264_P1") {
if (codecInfo->mName == "H264") {
cinst.codecType = webrtc::kVideoCodecH264;
PL_strncpyz(cinst.plName, "H264", sizeof(cinst.plName));
} else if (codecInfo->mName == "VP8") {

View File

@ -1,94 +0,0 @@
/* 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/. */
#include "CSFLog.h"
#include "CSFVideoControlWrapper.h"
static const char* logTag = "VcmSipccBinding";
namespace CSF {
void VideoControlWrapper::setVideoMode( bool enable )
{
if (_realVideoControl != nullptr)
{
_realVideoControl->setVideoMode(enable);
}
else
{
CSFLogWarn( logTag, "Attempt to setVideoMode to %s for expired video control",
enable ? "TRUE" : "FALSE");
}
}
void VideoControlWrapper::setPreviewWindow( VideoWindowHandle window, int top, int left, int bottom, int right, RenderScaling style )
{
if (_realVideoControl != nullptr)
{
_realVideoControl->setPreviewWindow(window, top, left, bottom, right, style);
}
else
{
CSFLogWarn( logTag, "Attempt to setPreviewWindow for expired video control");
}
}
void VideoControlWrapper::showPreviewWindow( bool show )
{
if (_realVideoControl != nullptr)
{
_realVideoControl->showPreviewWindow(show);
}
else
{
CSFLogWarn( logTag, "Attempt to showPreviewWindow( %s ) for expired video control",
show ? "TRUE" : "FALSE");
}
}
std::vector<std::string> VideoControlWrapper::getCaptureDevices()
{
if (_realVideoControl != nullptr)
{
return _realVideoControl->getCaptureDevices();
}
else
{
CSFLogWarn( logTag, "Attempt to getCaptureDevices for expired video control");
std::vector<std::string> vec;
return vec;
}
}
std::string VideoControlWrapper::getCaptureDevice()
{
if (_realVideoControl != nullptr)
{
return _realVideoControl->getCaptureDevice();
}
else
{
CSFLogWarn( logTag, "Attempt to getCaptureDevice for expired video control");
return "";
}
}
bool VideoControlWrapper::setCaptureDevice( const std::string& name )
{
if (_realVideoControl != nullptr)
{
return _realVideoControl->setCaptureDevice(name);
}
else
{
CSFLogWarn( logTag, "Attempt to setCaptureDevice to %s for expired video control",
name.c_str());
return false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,90 +0,0 @@
/* 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 _CSF_VCM_SIPCC_BINDING_H_
#define _CSF_VCM_SIPCC_BINDING_H_
extern "C"
{
#include "ccapi_types.h"
}
#include "mozIGeckoMediaPluginService.h"
class nsIThread;
class nsIEventTarget;
class nsIPrefBranch;
namespace mozilla {
class NrIceMediaStream;
};
namespace CSF
{
class AudioTermination;
class VideoTermination;
class AudioControl;
class VideoControl;
class MediaProvider;
class MediaProviderObserver;
class StreamObserver
{
public:
virtual void registerStream(cc_call_handle_t call, int streamId, bool isVideo) = 0;
virtual void deregisterStream(cc_call_handle_t call, int streamId) = 0;
virtual void dtmfBurst(int digit, int direction, int duration) = 0;
virtual void sendIFrame(cc_call_handle_t call) = 0;
};
class VcmSIPCCBinding
{
public:
VcmSIPCCBinding ();
virtual ~VcmSIPCCBinding();
// The getter is only for use by the vcm_* impl functions.
void setStreamObserver(StreamObserver*);
static StreamObserver* getStreamObserver();
static AudioTermination * getAudioTermination();
static VideoTermination * getVideoTermination();
static AudioControl * getAudioControl();
static VideoControl * getVideoControl();
void setMediaProviderObserver(MediaProviderObserver* obs);
static MediaProviderObserver * getMediaProviderObserver();
static void setAudioCodecs(int codecMask);
static void setVideoCodecs(int codecMask);
static int getAudioCodecs();
static int getVideoCodecs();
static int getVideoCodecsGmp();
static int getVideoCodecsHw();
static void setMainThread(nsIThread *thread);
static nsIThread *getMainThread();
static nsCOMPtr<nsIPrefBranch> getPrefBranch();
static int gVideoCodecGmpMask;
private:
nsCOMPtr<mozIGeckoMediaPluginService> mGMPService;
static VcmSIPCCBinding * gSelf;
StreamObserver* streamObserver;
MediaProviderObserver *mediaProviderObserver;
static bool gInitGmpCodecs;
static int gAudioCodecMask;
static int gVideoCodecMask;
static nsIThread *gMainThread;
static nsIEventTarget *gSTSThread;
static nsCOMPtr<nsIPrefBranch> gBranch;
};
}
#endif

View File

@ -1,35 +0,0 @@
/* 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 _Included_cip_sipcc_CodecMask
#define _Included_cip_sipcc_CodecMask
#ifdef __cplusplus
extern "C" {
#endif
#undef cip_sipcc_CodecMask_DSP_RESOURCE_G711
#define cip_sipcc_CodecMask_DSP_RESOURCE_G711 1L
#undef cip_sipcc_CodecMask_DSP_RESOURCE_G729A
#define cip_sipcc_CodecMask_DSP_RESOURCE_G729A 2L
#undef cip_sipcc_CodecMask_DSP_RESOURCE_G729B
#define cip_sipcc_CodecMask_DSP_RESOURCE_G729B 4L
#undef cip_sipcc_CodecMask_DSP_RESOURCE_LINEAR
#define cip_sipcc_CodecMask_DSP_RESOURCE_LINEAR 8L
#undef cip_sipcc_CodecMask_DSP_RESOURCE_G722
#define cip_sipcc_CodecMask_DSP_RESOURCE_G722 16L
#undef cip_sipcc_CodecMask_DSP_RESOURCE_iLBC
#define cip_sipcc_CodecMask_DSP_RESOURCE_iLBC 32L
#undef cip_sipcc_CodecMask_DSP_RESOURCE_iSAC
#define cip_sipcc_CodecMask_DSP_RESOURCE_iSAC 64L
#undef cip_sipcc_CodecMask_DSP_DECODEONLY
#define cip_sipcc_CodecMask_DSP_DECODEONLY 0L
#undef cip_sipcc_CodecMask_DSP_ENCODEONLY
#define cip_sipcc_CodecMask_DSP_ENCODEONLY 1L
#undef cip_sipcc_CodecMask_DSP_FULLDUPLEX
#define cip_sipcc_CodecMask_DSP_FULLDUPLEX 2L
#undef cip_sipcc_CodecMask_DSP_IGNORE
#define cip_sipcc_CodecMask_DSP_IGNORE 3L
#ifdef __cplusplus
}
#endif
#endif

View File

@ -366,7 +366,6 @@ public:
nsCOMPtr<nsIEventTarget> main_thread,
nsCOMPtr<nsIEventTarget> sts_thread,
DOMMediaStream *domstream,
int pipeline_index, // For PeerConnectionMedia/mPipelines
int level,
bool is_video,
RefPtr<MediaSessionConduit> conduit,
@ -377,7 +376,6 @@ public:
conduit, rtp_transport, rtcp_transport),
listener_(new PipelineListener(conduit)),
domstream_(domstream),
pipeline_index_(pipeline_index),
is_video_(is_video)
{}
@ -387,7 +385,6 @@ public:
virtual void AttachToTrack(TrackID track_id);
// Index used to refer to this before we know the TrackID
virtual TrackID pipeline_index() const { return pipeline_index_; }
// Note: unlike MediaPipeline::trackid(), this is threadsafe
// Not set until first media is received
virtual TrackID const trackid_locked() { return listener_->trackid(); }
@ -521,7 +518,6 @@ public:
private:
RefPtr<PipelineListener> listener_;
DOMMediaStream *domstream_;
int pipeline_index_; // for lookups in LocalSourceStreamInfo::mPipelines;
bool is_video_;
};

View File

@ -0,0 +1,703 @@
/* 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/. */
#include "logging.h"
#include "PeerConnectionImpl.h"
#include "PeerConnectionMedia.h"
#include "MediaPipelineFactory.h"
#include "transportflow.h"
#include "transportlayer.h"
#include "transportlayerdtls.h"
#include "transportlayerice.h"
#include "signaling/src/jsep/JsepTrack.h"
#include "signaling/src/jsep/JsepTransport.h"
#ifdef MOZILLA_INTERNAL_API
#include "nsIPrincipal.h"
#include "nsIDocument.h"
#include "mozilla/Preferences.h"
#endif
#include "GmpVideoCodec.h"
#ifdef MOZ_WEBRTC_OMX
#include "OMXVideoCodec.h"
#include "OMXCodecWrapper.h"
#endif
#include <stdlib.h>
namespace mozilla {
MOZ_MTLOG_MODULE("MediaPipelineFactory")
// Trivial wrapper class around a vector of ptrs.
template <class T> class PtrVector
{
public:
~PtrVector()
{
for (auto it = values.begin(); it != values.end(); ++it) {
delete *it;
}
}
std::vector<T*> values;
};
static nsresult
JsepCodecDescToCodecConfig(const JsepCodecDescription& aCodec,
AudioCodecConfig** aConfig)
{
MOZ_ASSERT(aCodec.mType == SdpMediaSection::kAudio);
if (aCodec.mType != SdpMediaSection::kAudio)
return NS_ERROR_INVALID_ARG;
const JsepAudioCodecDescription& desc =
static_cast<const JsepAudioCodecDescription&>(aCodec);
uint16_t pt;
if (!desc.GetPtAsInt(&pt)) {
MOZ_MTLOG(ML_ERROR, "Invalid payload type: " << desc.mDefaultPt);
return NS_ERROR_INVALID_ARG;
}
*aConfig = new AudioCodecConfig(pt,
desc.mName,
desc.mClock,
desc.mPacketSize,
desc.mChannels,
desc.mBitrate);
return NS_OK;
}
static nsresult
JsepCodecDescToCodecConfig(const JsepCodecDescription& aCodec,
VideoCodecConfig** aConfig)
{
MOZ_ASSERT(aCodec.mType == SdpMediaSection::kVideo);
if (aCodec.mType != SdpMediaSection::kVideo) {
MOZ_ASSERT(false, "JsepCodecDescription has wrong type");
return NS_ERROR_INVALID_ARG;
}
const JsepVideoCodecDescription& desc =
static_cast<const JsepVideoCodecDescription&>(aCodec);
uint16_t pt;
if (!desc.GetPtAsInt(&pt)) {
MOZ_MTLOG(ML_ERROR, "Invalid payload type: " << desc.mDefaultPt);
return NS_ERROR_INVALID_ARG;
}
ScopedDeletePtr<VideoCodecConfigH264> h264Config;
if (desc.mName == "H264") {
h264Config = new VideoCodecConfigH264;
size_t spropSize = sizeof(h264Config->sprop_parameter_sets);
strncpy(h264Config->sprop_parameter_sets,
desc.mSpropParameterSets.c_str(),
spropSize);
h264Config->sprop_parameter_sets[spropSize - 1] = '\0';
h264Config->packetization_mode = desc.mPacketizationMode;
h264Config->profile_level_id = desc.mProfileLevelId;
h264Config->max_mbps = desc.mMaxMbps;
h264Config->max_fs = desc.mMaxFs;
h264Config->max_cpb = desc.mMaxCpb;
h264Config->max_dpb = desc.mMaxDpb;
h264Config->max_br = desc.mMaxBr;
h264Config->tias_bw = 0; // TODO. Issue 165.
}
VideoCodecConfig* configRaw;
configRaw = new VideoCodecConfig(
pt, desc.mName, desc.mMaxFs, desc.mMaxFr, h264Config);
configRaw->mAckFbTypes = desc.mAckFbTypes;
configRaw->mNackFbTypes = desc.mNackFbTypes;
configRaw->mCcmFbTypes = desc.mCcmFbTypes;
*aConfig = configRaw;
return NS_OK;
}
// Accessing the PCMedia should be safe here because we shouldn't
// have enqueued this function unless it was still active and
// the ICE data is destroyed on the STS.
static void
FinalizeTransportFlow_s(RefPtr<PeerConnectionMedia> aPCMedia,
RefPtr<TransportFlow> aFlow, size_t aLevel,
bool aIsRtcp,
nsAutoPtr<PtrVector<TransportLayer> > aLayerList)
{
TransportLayerIce* ice =
static_cast<TransportLayerIce*>(aLayerList->values.front());
ice->SetParameters(
aPCMedia->ice_ctx(), aPCMedia->ice_media_stream(aLevel), aIsRtcp ? 2 : 1);
nsAutoPtr<std::queue<TransportLayer*> > layerQueue(
new std::queue<TransportLayer*>);
for (auto i = aLayerList->values.begin(); i != aLayerList->values.end();
++i) {
layerQueue->push(*i);
}
aLayerList->values.clear();
(void)aFlow->PushLayers(layerQueue); // TODO(bug 854518): Process errors.
}
nsresult
MediaPipelineFactory::CreateOrGetTransportFlow(
size_t aLevel,
bool aIsRtcp,
const JsepTransport& aTransport,
RefPtr<TransportFlow>* aFlowOutparam)
{
nsresult rv;
RefPtr<TransportFlow> flow;
flow = mPCMedia->GetTransportFlow(aLevel, aIsRtcp);
if (flow) {
*aFlowOutparam = flow;
return NS_OK;
}
std::ostringstream osId;
osId << mPC->GetHandle() << ":" << aLevel << ","
<< (aIsRtcp ? "rtcp" : "rtp");
flow = new TransportFlow(osId.str());
// The media streams are made on STS so we need to defer setup.
auto ice = MakeUnique<TransportLayerIce>(mPC->GetHandle());
auto dtls = MakeUnique<TransportLayerDtls>();
dtls->SetRole(aTransport.mDtls->GetRole() ==
JsepDtlsTransport::kJsepDtlsClient
? TransportLayerDtls::CLIENT
: TransportLayerDtls::SERVER);
RefPtr<DtlsIdentity> pcid = mPC->GetIdentity();
if (!pcid) {
MOZ_MTLOG(ML_ERROR, "Failed to get DTLS identity.");
return NS_ERROR_FAILURE;
}
dtls->SetIdentity(pcid);
const SdpFingerprintAttributeList& fingerprints =
aTransport.mDtls->GetFingerprints();
for (auto fp = fingerprints.mFingerprints.begin();
fp != fingerprints.mFingerprints.end();
++fp) {
std::ostringstream ss;
ss << fp->hashFunc;
rv = dtls->SetVerificationDigest(ss.str(), &fp->fingerprint[0],
fp->fingerprint.size());
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Could not set fingerprint");
return rv;
}
}
std::vector<uint16_t> srtpCiphers;
srtpCiphers.push_back(SRTP_AES128_CM_HMAC_SHA1_80);
srtpCiphers.push_back(SRTP_AES128_CM_HMAC_SHA1_32);
rv = dtls->SetSrtpCiphers(srtpCiphers);
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Couldn't set SRTP ciphers");
return rv;
}
nsAutoPtr<PtrVector<TransportLayer> > layers(new PtrVector<TransportLayer>);
layers->values.push_back(ice.release());
layers->values.push_back(dtls.release());
rv = mPCMedia->GetSTSThread()->Dispatch(
WrapRunnableNM(FinalizeTransportFlow_s, mPCMedia, flow, aLevel, aIsRtcp,
layers),
NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Failed to dispatch FinalizeTransportFlow_s");
return rv;
}
mPCMedia->AddTransportFlow(aLevel, aIsRtcp, flow);
*aFlowOutparam = flow;
return NS_OK;
}
nsresult
MediaPipelineFactory::CreateMediaPipeline(const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack)
{
MOZ_MTLOG(ML_DEBUG,
"Creating media pipeline"
<< " m-line index=" << aTrackPair.mLevel
<< " type=" << aTrack.GetMediaType()
<< " direction=" << aTrack.GetDirection());
MOZ_ASSERT(aTrackPair.mRtpTransport);
// First make sure the transport flow exists.
RefPtr<TransportFlow> rtpFlow;
nsresult rv = CreateOrGetTransportFlow(
aTrackPair.mLevel, false, *aTrackPair.mRtpTransport, &rtpFlow);
if (NS_FAILED(rv))
return rv;
MOZ_ASSERT(rtpFlow);
RefPtr<TransportFlow> rtcpFlow;
if (aTrackPair.mRtcpTransport) {
rv = CreateOrGetTransportFlow(
aTrackPair.mLevel, true, *aTrackPair.mRtcpTransport, &rtcpFlow);
if (NS_FAILED(rv))
return rv;
MOZ_ASSERT(rtcpFlow);
}
// TODO(bug 1016476): If bundle is in play, grab the TransportFlows for the
// bundle level too.
bool receiving =
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
RefPtr<MediaSessionConduit> conduit;
if (aTrack.GetMediaType() == SdpMediaSection::kAudio) {
rv = CreateAudioConduit(aTrackPair, aTrack, &conduit);
if (NS_FAILED(rv))
return rv;
} else if (aTrack.GetMediaType() == SdpMediaSection::kVideo) {
rv = CreateVideoConduit(aTrackPair, aTrack, &conduit);
if (NS_FAILED(rv))
return rv;
} else {
// We've created the TransportFlow, nothing else to do here.
return NS_OK;
}
if (receiving) {
rv = CreateMediaPipelineReceiving(rtpFlow, rtcpFlow, nullptr, nullptr,
aTrackPair, aTrack, conduit);
if (NS_FAILED(rv))
return rv;
} else {
rv = CreateMediaPipelineSending(rtpFlow, rtcpFlow, nullptr, nullptr,
aTrackPair, aTrack, conduit);
if (NS_FAILED(rv))
return rv;
}
return NS_OK;
}
nsresult
MediaPipelineFactory::CreateMediaPipelineReceiving(
RefPtr<TransportFlow> aRtpFlow,
RefPtr<TransportFlow> aRtcpFlow,
RefPtr<TransportFlow> aBundleRtpFlow,
RefPtr<TransportFlow> aBundleRtcpFlow,
const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
const RefPtr<MediaSessionConduit>& aConduit)
{
// Find the stream we need
nsRefPtr<RemoteSourceStreamInfo> stream =
mPCMedia->GetRemoteStreamById(aTrack.GetStreamId());
MOZ_ASSERT(stream);
if (!stream) {
// This should never happen
MOZ_ASSERT(false);
MOZ_MTLOG(ML_ERROR, "Stream not found: " << aTrack.GetStreamId());
return NS_ERROR_FAILURE;
}
RefPtr<MediaPipelineReceive> pipeline;
// TODO(bug 1016476): Need bundle filter.
nsAutoPtr<MediaPipelineFilter> filter(nullptr);
if (aTrack.GetMediaType() == SdpMediaSection::kAudio) {
pipeline = new MediaPipelineReceiveAudio(
mPC->GetHandle(),
mPC->GetMainThread().get(),
mPC->GetSTSThread(),
stream->GetMediaStream()->GetStream(),
// Use the level + 1 as the track id. 0 is forbidden
aTrackPair.mLevel + 1,
aTrackPair.mLevel,
static_cast<AudioSessionConduit*>(aConduit.get()), // Ugly downcast.
aRtpFlow,
aRtcpFlow,
aBundleRtpFlow,
aBundleRtcpFlow,
filter);
} else if (aTrack.GetMediaType() == SdpMediaSection::kVideo) {
pipeline = new MediaPipelineReceiveVideo(
mPC->GetHandle(),
mPC->GetMainThread().get(),
mPC->GetSTSThread(),
stream->GetMediaStream()->GetStream(),
// Use the level + 1 as the track id. 0 is forbidden
aTrackPair.mLevel + 1,
aTrackPair.mLevel,
static_cast<VideoSessionConduit*>(aConduit.get()), // Ugly downcast.
aRtpFlow,
aRtcpFlow,
aBundleRtpFlow,
aBundleRtcpFlow,
filter);
} else {
MOZ_ASSERT(false);
MOZ_MTLOG(ML_ERROR, "Invalid media type in CreateMediaPipelineReceiving");
return NS_ERROR_FAILURE;
}
nsresult rv = pipeline->Init();
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Couldn't initialize receiving pipeline");
return rv;
}
stream->StorePipeline(aTrackPair.mLevel, SdpMediaSection::kVideo, pipeline);
return NS_OK;
}
nsresult
MediaPipelineFactory::CreateMediaPipelineSending(
RefPtr<TransportFlow> aRtpFlow,
RefPtr<TransportFlow> aRtcpFlow,
RefPtr<TransportFlow> aBundleRtpFlow,
RefPtr<TransportFlow> aBundleRtcpFlow,
const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
const RefPtr<MediaSessionConduit>& aConduit)
{
nsresult rv;
nsRefPtr<LocalSourceStreamInfo> stream =
mPCMedia->GetLocalStreamById(aTrack.GetStreamId());
MOZ_ASSERT(stream);
if (!stream) {
// This should never happen
MOZ_MTLOG(ML_ERROR, "Stream not found: " << aTrack.GetStreamId());
return NS_ERROR_FAILURE;
}
// Now we have all the pieces, create the pipeline
RefPtr<MediaPipelineTransmit> pipeline = new MediaPipelineTransmit(
mPC->GetHandle(), mPC->GetMainThread().get(), mPC->GetSTSThread(),
stream->GetMediaStream(), aTrackPair.mLevel,
aTrack.GetMediaType() == SdpMediaSection::kVideo, aConduit, aRtpFlow,
aRtcpFlow);
#ifdef MOZILLA_INTERNAL_API
// implement checking for peerIdentity (where failure == black/silence)
nsIDocument* doc = mPC->GetWindow()->GetExtantDoc();
if (doc) {
pipeline->UpdateSinkIdentity_m(doc->NodePrincipal(),
mPC->GetPeerIdentity());
} else {
MOZ_MTLOG(ML_ERROR, "Cannot initialize pipeline without attached doc");
return NS_ERROR_FAILURE; // Don't remove this till we know it's safe.
}
#endif
rv = pipeline->Init();
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Couldn't initialize sending pipeline");
return rv;
}
// TODO(bug 1016476): Copied from vcmSIPCCBinding. Need to unifdef and port in.
#if 0
// This tells the receive MediaPipeline (if there is one) whether we are
// doing bundle, and if so, updates the filter. Once the filter is finalized,
// it is then copied to the transmit pipeline so it can filter RTCP.
if (attrs->bundle_level) {
nsAutoPtr<MediaPipelineFilter> filter (new MediaPipelineFilter);
for (int s = 0; s < attrs->num_ssrcs; ++s) {
filter->AddRemoteSSRC(attrs->ssrcs[s]);
}
pc.impl()->media()->SetUsingBundle_m(level, true);
pc.impl()->media()->UpdateFilterFromRemoteDescription_m(level, filter);
} else {
// This will also clear the filter.
pc.impl()->media()->SetUsingBundle_m(level, false);
}
#endif
stream->StorePipeline(aTrackPair.mLevel, pipeline);
return NS_OK;
}
nsresult
MediaPipelineFactory::CreateAudioConduit(const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
RefPtr<MediaSessionConduit>* aConduitp)
{
if (!aTrack.GetNegotiatedDetails()) {
MOZ_ASSERT(false, "Track is missing negotiated details");
return NS_ERROR_INVALID_ARG;
}
bool receiving =
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
RefPtr<MediaSessionConduit> otherConduit =
mPCMedia->GetConduit(aTrackPair.mLevel, !receiving);
MOZ_ASSERT_IF(otherConduit,
otherConduit->type() == MediaSessionConduit::AUDIO);
// The two sides of a send/receive pair of conduits each keep a raw pointer
// to the other, and are responsible for cleanly shutting down.
RefPtr<AudioSessionConduit> conduit = AudioSessionConduit::Create(
static_cast<AudioSessionConduit*>(otherConduit.get()));
if (!conduit) {
MOZ_MTLOG(ML_ERROR, "Could not create audio conduit");
return NS_ERROR_FAILURE;
}
mPCMedia->AddConduit(aTrackPair.mLevel, receiving, conduit);
size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount();
if (numCodecs == 0) {
MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs");
return NS_ERROR_FAILURE;
}
if (receiving) {
PtrVector<AudioCodecConfig> configs;
for (size_t i = 0; i < numCodecs; i++) {
const JsepCodecDescription* cdesc;
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(i, &cdesc);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
<< static_cast<uint32_t>(rv));
return rv;
}
AudioCodecConfig* configRaw;
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
if (NS_FAILED(rv))
return rv;
configs.values.push_back(configRaw);
}
auto error = conduit->ConfigureRecvMediaCodecs(configs.values);
if (error) {
MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error);
return NS_ERROR_FAILURE;
}
} else {
const JsepCodecDescription* cdesc;
// Best codec.
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(0, &cdesc);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
<< static_cast<uint32_t>(rv));
return rv;
}
AudioCodecConfig* configRaw;
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
if (NS_FAILED(rv))
return rv;
ScopedDeletePtr<AudioCodecConfig> config(configRaw);
auto error = conduit->ConfigureSendMediaCodec(config.get());
if (error) {
MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error);
return NS_ERROR_FAILURE;
}
const SdpExtmapAttributeList::Extmap* audioLevelExt =
aTrack.GetNegotiatedDetails()->GetExt(
"urn:ietf:params:rtp-hdrext:ssrc-audio-level");
if (audioLevelExt) {
MOZ_MTLOG(ML_DEBUG, "Calling EnableAudioLevelExtension");
error = conduit->EnableAudioLevelExtension(true, audioLevelExt->entry);
if (error) {
MOZ_MTLOG(ML_ERROR, "EnableAudioLevelExtension failed: " << error);
return NS_ERROR_FAILURE;
}
}
}
*aConduitp = conduit;
return NS_OK;
}
nsresult
MediaPipelineFactory::CreateVideoConduit(const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
RefPtr<MediaSessionConduit>* aConduitp)
{
if (!aTrack.GetNegotiatedDetails()) {
MOZ_ASSERT(false, "Track is missing negotiated details");
return NS_ERROR_INVALID_ARG;
}
bool receiving =
aTrack.GetDirection() == JsepTrack::Direction::kJsepTrackReceiving;
// Instantiate an appropriate conduit
RefPtr<MediaSessionConduit> peerConduit =
mPCMedia->GetConduit(aTrackPair.mLevel, !receiving);
MOZ_ASSERT_IF(peerConduit, peerConduit->type() == MediaSessionConduit::VIDEO);
// The two sides of a send/receive pair of conduits each keep a raw
// pointer to the other, and are responsible for cleanly shutting down.
RefPtr<VideoSessionConduit> conduit = VideoSessionConduit::Create(
static_cast<VideoSessionConduit*>(peerConduit.get()));
if (!conduit) {
MOZ_MTLOG(ML_ERROR, "Could not create video conduit");
return NS_ERROR_FAILURE;
}
mPCMedia->AddConduit(aTrackPair.mLevel, receiving, conduit);
size_t numCodecs = aTrack.GetNegotiatedDetails()->GetCodecCount();
if (numCodecs == 0) {
MOZ_MTLOG(ML_ERROR, "Can't set up a conduit with 0 codecs");
return NS_ERROR_FAILURE;
}
if (receiving) {
PtrVector<VideoCodecConfig> configs;
for (size_t i = 0; i < numCodecs; i++) {
const JsepCodecDescription* cdesc;
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(i, &cdesc);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
<< static_cast<uint32_t>(rv));
return rv;
}
VideoCodecConfig* configRaw;
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
if (NS_FAILED(rv))
return rv;
UniquePtr<VideoCodecConfig> config(configRaw);
if (EnsureExternalCodec(*conduit, config.get(), false)) {
continue;
}
configs.values.push_back(config.release());
}
auto error = conduit->ConfigureRecvMediaCodecs(configs.values);
if (error) {
MOZ_MTLOG(ML_ERROR, "ConfigureRecvMediaCodecs failed: " << error);
return NS_ERROR_FAILURE;
}
} else {
const JsepCodecDescription* cdesc;
// Best codec.
nsresult rv = aTrack.GetNegotiatedDetails()->GetCodec(0, &cdesc);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) {
MOZ_MTLOG(ML_ERROR, "Failed to get codec from jsep track, rv="
<< static_cast<uint32_t>(rv));
return rv;
}
VideoCodecConfig* configRaw;
rv = JsepCodecDescToCodecConfig(*cdesc, &configRaw);
if (NS_FAILED(rv))
return rv;
// Take possession of this pointer
ScopedDeletePtr<VideoCodecConfig> config(configRaw);
if (EnsureExternalCodec(*conduit, config, true)) {
MOZ_MTLOG(ML_ERROR, "External codec not available");
return NS_ERROR_FAILURE;
}
auto error = conduit->ConfigureSendMediaCodec(config);
if (error) {
MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error);
return NS_ERROR_FAILURE;
}
}
*aConduitp = conduit;
return NS_OK;
}
/*
* Add external H.264 video codec.
*/
MediaConduitErrorCode
MediaPipelineFactory::EnsureExternalCodec(VideoSessionConduit& aConduit,
VideoCodecConfig* aConfig,
bool aIsSend)
{
if (aConfig->mName == "VP8") {
return kMediaConduitNoError;
} else if (aConfig->mName == "H264") {
// Register H.264 codec.
if (aIsSend) {
VideoEncoder* encoder = nullptr;
#ifdef MOZ_WEBRTC_OMX
encoder =
OMXVideoCodec::CreateEncoder(OMXVideoCodec::CodecType::CODEC_H264);
#else
encoder = GmpVideoCodec::CreateEncoder();
#endif
if (encoder) {
return aConduit.SetExternalSendCodec(aConfig, encoder);
} else {
return kMediaConduitInvalidSendCodec;
}
} else {
VideoDecoder* decoder;
#ifdef MOZ_WEBRTC_OMX
decoder =
OMXVideoCodec::CreateDecoder(OMXVideoCodec::CodecType::CODEC_H264);
#else
decoder = GmpVideoCodec::CreateDecoder();
#endif
if (decoder) {
return aConduit.SetExternalRecvCodec(aConfig, decoder);
} else {
return kMediaConduitInvalidReceiveCodec;
}
}
NS_NOTREACHED("Shouldn't get here!");
} else {
MOZ_MTLOG(ML_ERROR,
"Invalid video codec configured: " << aConfig->mName.c_str());
return aIsSend ? kMediaConduitInvalidSendCodec
: kMediaConduitInvalidReceiveCodec;
}
NS_NOTREACHED("Shouldn't get here!");
}
} // namespace mozilla

View File

@ -0,0 +1,72 @@
/* 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 _MEDIAPIPELINEFACTORY_H_
#define _MEDIAPIPELINEFACTORY_H_
#include "MediaConduitInterface.h"
#include "PeerConnectionMedia.h"
#include "transportflow.h"
#include "signaling/src/jsep/JsepTrack.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtr.h"
namespace mozilla {
class MediaPipelineFactory
{
public:
explicit MediaPipelineFactory(PeerConnectionMedia* aPCMedia)
: mPCMedia(aPCMedia), mPC(aPCMedia->GetPC())
{
}
nsresult CreateMediaPipeline(const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack);
private:
nsresult CreateMediaPipelineReceiving(
RefPtr<TransportFlow> aRtpFlow,
RefPtr<TransportFlow> aRtcpFlow,
RefPtr<TransportFlow> aBundleRtpFlow,
RefPtr<TransportFlow> aBundleRtcpFlow,
const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
const RefPtr<MediaSessionConduit>& aConduit);
nsresult CreateMediaPipelineSending(
RefPtr<TransportFlow> aRtpFlow,
RefPtr<TransportFlow> aRtcpFlow,
RefPtr<TransportFlow> aBundleRtpFlow,
RefPtr<TransportFlow> aBundleRtcpFlow,
const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
const RefPtr<MediaSessionConduit>& aConduit);
nsresult CreateAudioConduit(const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
RefPtr<MediaSessionConduit>* aConduitp);
nsresult CreateVideoConduit(const JsepTrackPair& aTrackPair,
const JsepTrack& aTrack,
RefPtr<MediaSessionConduit>* aConduitp);
MediaConduitErrorCode EnsureExternalCodec(VideoSessionConduit& aConduit,
VideoCodecConfig* aConfig,
bool aIsSend);
nsresult CreateOrGetTransportFlow(size_t aLevel, bool aIsRtcp,
const JsepTransport& transport,
RefPtr<TransportFlow>* out);
private:
// Not owned, and assumed to exist as long as the factory.
// The factory is a transient object, so this is fairly easy.
PeerConnectionMedia* mPCMedia;
PeerConnectionImpl* mPC;
};
} // namespace mozilla
#endif

View File

@ -15,7 +15,7 @@
namespace mozilla {
namespace dom {
MediaStreamList::MediaStreamList(sipcc::PeerConnectionImpl* peerConnection,
MediaStreamList::MediaStreamList(PeerConnectionImpl* peerConnection,
StreamType type)
: mPeerConnection(peerConnection),
mType(type)
@ -83,11 +83,11 @@ MediaStreamList::IndexedGetter(uint32_t index, bool& found)
}
if (mType == Local) {
return GetStreamFromInfo(mPeerConnection->media()->
GetLocalStream(index), found);
GetLocalStreamByIndex(index), found);
}
return GetStreamFromInfo(mPeerConnection->media()->
GetRemoteStream(index), found);
GetRemoteStreamByIndex(index), found);
}
uint32_t

View File

@ -16,11 +16,8 @@
#include "DOMMediaStream.h"
#endif
namespace sipcc {
class PeerConnectionImpl;
} // namespace sipcc
namespace mozilla {
class PeerConnectionImpl;
namespace dom {
class MediaStreamList : public nsISupports,
@ -32,7 +29,7 @@ public:
Remote
};
MediaStreamList(sipcc::PeerConnectionImpl* peerConnection, StreamType type);
MediaStreamList(PeerConnectionImpl* peerConnection, StreamType type);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaStreamList)
@ -47,7 +44,7 @@ public:
private:
virtual ~MediaStreamList();
nsRefPtr<sipcc::PeerConnectionImpl> mPeerConnection;
nsRefPtr<PeerConnectionImpl> mPeerConnection;
StreamType mType;
};

View File

@ -5,20 +5,9 @@
#include "CSFLog.h"
#include "base/histogram.h"
#include "CallControlManager.h"
#include "CC_Device.h"
#include "CC_Call.h"
#include "CC_Observer.h"
#include "ccapi_call_info.h"
#include "CC_SIPCCCallInfo.h"
#include "ccapi_device_info.h"
#include "CC_SIPCCDeviceInfo.h"
#include "vcm.h"
#include "VcmSIPCCBinding.h"
#include "PeerConnectionImpl.h"
#include "PeerConnectionCtx.h"
#include "runnable_utils.h"
#include "debug-psipcc-types.h"
#include "prcvar.h"
#include "mozilla/Telemetry.h"
@ -42,56 +31,6 @@ namespace mozilla {
using namespace dom;
// Convert constraints to C structures
#ifdef MOZILLA_INTERNAL_API
static void
Apply(const Optional<bool> &aSrc, cc_boolean_option_t *aDst) {
if (aSrc.WasPassed()) {
aDst->was_passed = true;
aDst->value = aSrc.Value();
}
}
static void
Apply(const Optional<int32_t> &aSrc, cc_int32_option_t *aDst) {
if (aSrc.WasPassed()) {
aDst->was_passed = true;
aDst->value = aSrc.Value();
}
}
#endif
SipccOfferOptions::SipccOfferOptions() {
memset(&mOptions, 0, sizeof(mOptions));
}
SipccOfferOptions::SipccOfferOptions(
const RTCOfferOptions &aSrc) {
cc_media_options_t* c = &mOptions;
memset(c, 0, sizeof(*c));
#ifdef MOZILLA_INTERNAL_API
Apply(aSrc.mOfferToReceiveAudio, &c->offer_to_receive_audio);
Apply(aSrc.mOfferToReceiveVideo, &c->offer_to_receive_video);
if (!Preferences::GetBool("media.peerconnection.video.enabled", true)) {
c->offer_to_receive_video.was_passed = true;
c->offer_to_receive_video.value = false;
}
Apply(aSrc.mMozDontOfferDataChannel, &c->moz_dont_offer_datachannel);
Apply(aSrc.mMozBundleOnly, &c->moz_bundle_only);
#endif
}
cc_media_options_t*
SipccOfferOptions::build() const {
cc_media_options_t* cc = (cc_media_options_t*)
cpr_malloc(sizeof(cc_media_options_t));
if (cc) {
*cc = mOptions;
}
return cc;
}
class PeerConnectionCtxShutdown : public nsIObserver
{
public:
@ -121,7 +60,7 @@ public:
const char16_t* aData) {
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
CSFLogDebug(logTag, "Shutting down PeerConnectionCtx");
sipcc::PeerConnectionCtx::Destroy();
PeerConnectionCtx::Destroy();
nsCOMPtr<nsIObserverService> observerService =
services::GetObserverService();
@ -134,7 +73,7 @@ public:
// Make sure we're not deleted while still inside ::Observe()
nsRefPtr<PeerConnectionCtxShutdown> kungFuDeathGrip(this);
sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown = nullptr;
PeerConnectionCtx::gPeerConnectionCtxShutdown = nullptr;
}
return NS_OK;
}
@ -152,8 +91,7 @@ private:
NS_IMPL_ISUPPORTS(PeerConnectionCtxShutdown, nsIObserver);
}
using namespace mozilla;
namespace sipcc {
namespace mozilla {
PeerConnectionCtx* PeerConnectionCtx::gInstance;
nsIThread* PeerConnectionCtx::gMainThread;
@ -163,7 +101,6 @@ nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread,
nsIEventTarget* stsThread) {
if (!gMainThread) {
gMainThread = mainThread;
CSF::VcmSIPCCBinding::setMainThread(gMainThread);
} else {
MOZ_ASSERT(gMainThread == mainThread);
}
@ -183,9 +120,9 @@ nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread,
gInstance = ctx;
if (!sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown) {
sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown = new PeerConnectionCtxShutdown();
sipcc::PeerConnectionCtx::gPeerConnectionCtxShutdown->Init();
if (!PeerConnectionCtx::gPeerConnectionCtxShutdown) {
PeerConnectionCtx::gPeerConnectionCtxShutdown = new PeerConnectionCtxShutdown();
PeerConnectionCtx::gPeerConnectionCtxShutdown->Init();
}
}
@ -363,51 +300,6 @@ PeerConnectionCtx::EverySecondTelemetryCallback_m(nsITimer* timer, void *closure
nsresult PeerConnectionCtx::Initialize() {
initGMP();
mCCM = CSF::CallControlManager::create();
NS_ENSURE_TRUE(mCCM.get(), NS_ERROR_FAILURE);
// Add the local audio codecs
// FIX - Get this list from MediaEngine instead
int codecMask = 0;
codecMask |= VCM_CODEC_RESOURCE_G711;
codecMask |= VCM_CODEC_RESOURCE_OPUS;
//codecMask |= VCM_CODEC_RESOURCE_LINEAR;
codecMask |= VCM_CODEC_RESOURCE_G722;
//codecMask |= VCM_CODEC_RESOURCE_iLBC;
//codecMask |= VCM_CODEC_RESOURCE_iSAC;
mCCM->setAudioCodecs(codecMask);
//Add the local video codecs
// FIX - Get this list from MediaEngine instead
// Turning them all on for now
codecMask = 0;
// Only adding codecs supported
//codecMask |= VCM_CODEC_RESOURCE_H263;
#ifdef MOZILLA_INTERNAL_API
#ifdef MOZ_WEBRTC_OMX
if (Preferences::GetBool("media.peerconnection.video.h264_enabled")) {
codecMask |= VCM_CODEC_RESOURCE_H264;
}
#endif
#else
// Outside MOZILLA_INTERNAL_API ensures H.264 available in unit tests
codecMask |= VCM_CODEC_RESOURCE_H264;
#endif
codecMask |= VCM_CODEC_RESOURCE_VP8;
//codecMask |= VCM_CODEC_RESOURCE_I420;
mCCM->setVideoCodecs(codecMask);
mCCM->addCCObserver(this);
ChangeSipccState(dom::PCImplSipccState::Starting);
if (!mCCM->startSDPMode())
return NS_ERROR_FAILURE;
mDevice = mCCM->getActiveDevice();
NS_ENSURE_TRUE(mDevice.get(), NS_ERROR_FAILURE);
#ifdef MOZILLA_INTERNAL_API
mConnectionCounter = 0;
Telemetry::GetHistogramById(Telemetry::WEBRTC_CALL_COUNT)->Add(0);
@ -418,7 +310,8 @@ nsresult PeerConnectionCtx::Initialize() {
NS_ENSURE_SUCCESS(rv, rv);
mTelemetryTimer->InitWithFuncCallback(EverySecondTelemetryCallback_m, this, 1000,
nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP);
#endif
#endif // MOZILLA_INTERNAL_API
return NS_OK;
}
@ -464,9 +357,6 @@ nsresult PeerConnectionCtx::Cleanup() {
mQueuedJSEPOperations.Clear();
mGMPService = nullptr;
mCCM->destroy();
mCCM->removeCCObserver(this);
return NS_OK;
}
@ -480,10 +370,6 @@ PeerConnectionCtx::~PeerConnectionCtx() {
#endif
};
CSF::CC_CallPtr PeerConnectionCtx::createCall() {
return mDevice->createCall();
}
void PeerConnectionCtx::queueJSEPOperation(nsRefPtr<nsIRunnable> aOperation) {
mQueuedJSEPOperations.AppendElement(aOperation);
}
@ -496,35 +382,33 @@ void PeerConnectionCtx::onGMPReady() {
mQueuedJSEPOperations.Clear();
}
void PeerConnectionCtx::onDeviceEvent(ccapi_device_event_e aDeviceEvent,
CSF::CC_DevicePtr aDevice,
CSF::CC_DeviceInfoPtr aInfo ) {
cc_service_state_t state = aInfo->getServiceState();
// We are keeping this in a local var to avoid a data race
// with ChangeSipccState in the debug message and compound if below
dom::PCImplSipccState currentSipccState = mSipccState;
switch (aDeviceEvent) {
case CCAPI_DEVICE_EV_STATE:
CSFLogDebug(logTag, "%s - %d : %d", __FUNCTION__, state,
static_cast<uint32_t>(currentSipccState));
if (CC_STATE_INS == state) {
// SIPCC is up
if (dom::PCImplSipccState::Starting == currentSipccState ||
dom::PCImplSipccState::Idle == currentSipccState) {
ChangeSipccState(dom::PCImplSipccState::Started);
} else {
CSFLogError(logTag, "%s PeerConnection already started", __FUNCTION__);
}
} else {
NS_NOTREACHED("Unsupported Signaling State Transition");
}
break;
default:
CSFLogDebug(logTag, "%s: Ignoring event: %s\n",__FUNCTION__,
device_event_getname(aDeviceEvent));
bool PeerConnectionCtx::gmpHasH264() {
if (!mGMPService) {
return false;
}
// XXX I'd prefer if this was all known ahead of time...
nsTArray<nsCString> tags;
tags.AppendElement(NS_LITERAL_CSTRING("h264"));
bool has_gmp;
nsresult rv;
rv = mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING("encode-video"),
&tags,
&has_gmp);
if (NS_FAILED(rv) || !has_gmp) {
return false;
}
rv = mGMPService->HasPluginForAPI(NS_LITERAL_CSTRING("decode-video"),
&tags,
&has_gmp);
if (NS_FAILED(rv) || !has_gmp) {
return false;
}
return true;
}
} // namespace sipcc
} // namespace mozilla

View File

@ -8,17 +8,6 @@
#include <string>
#include "mozilla/Attributes.h"
#include "CallControlManager.h"
#include "CC_Device.h"
#include "CC_DeviceInfo.h"
#include "CC_Call.h"
#include "CC_CallInfo.h"
#include "CC_Line.h"
#include "CC_LineInfo.h"
#include "CC_Observer.h"
#include "CC_FeatureInfo.h"
#include "cpr_stdlib.h"
#include "StaticPtr.h"
#include "PeerConnectionImpl.h"
#include "mozIGeckoMediaPluginService.h"
@ -31,52 +20,17 @@ namespace dom {
class WebrtcGlobalInformation;
}
// Unit-test helper, because cc_media_options_t is hard to forward-declare
class SipccOfferOptions {
public:
SipccOfferOptions();
explicit SipccOfferOptions(const dom::RTCOfferOptions &aOther);
cc_media_options_t* build() const;
protected:
cc_media_options_t mOptions;
};
}
namespace sipcc {
class OnCallEventArgs {
public:
OnCallEventArgs(ccapi_call_event_e aCallEvent, CSF::CC_CallInfoPtr aInfo)
: mCallEvent(aCallEvent), mInfo(aInfo) {}
ccapi_call_event_e mCallEvent;
CSF::CC_CallInfoPtr mInfo;
};
// A class to hold some of the singleton objects we need:
// * The global PeerConnectionImpl table and its associated lock.
// * Currently SIPCC only allows a single stack instance to exist in a process
// at once. This class implements a singleton object that wraps that.
// * The observer class that demuxes events onto individual PCs.
class PeerConnectionCtx : public CSF::CC_Observer {
// * Stats report objects for PCs that are gone
// * GMP related state
class PeerConnectionCtx {
public:
static nsresult InitializeGlobal(nsIThread *mainThread, nsIEventTarget *stsThread);
static PeerConnectionCtx* GetInstance();
static bool isActive();
static void Destroy();
// Implementations of CC_Observer methods
virtual void onDeviceEvent(ccapi_device_event_e deviceEvent, CSF::CC_DevicePtr device, CSF::CC_DeviceInfoPtr info);
virtual void onFeatureEvent(ccapi_device_event_e deviceEvent, CSF::CC_DevicePtr device, CSF::CC_FeatureInfoPtr feature_info) {}
virtual void onLineEvent(ccapi_line_event_e lineEvent, CSF::CC_LinePtr line, CSF::CC_LineInfoPtr info) {}
virtual void onCallEvent(ccapi_call_event_e callEvent, CSF::CC_CallPtr call, CSF::CC_CallInfoPtr info) {}
// Create a SIPCC Call
CSF::CC_CallPtr createCall();
mozilla::dom::PCImplSipccState sipcc_state() { return mSipccState; }
bool isReady() {
// If mGMPService is not set, we aren't using GMP.
if (mGMPService) {
@ -88,6 +42,8 @@ class PeerConnectionCtx : public CSF::CC_Observer {
void queueJSEPOperation(nsRefPtr<nsIRunnable> aJSEPOperation);
void onGMPReady();
bool gmpHasH264();
// Make these classes friend so that they can access mPeerconnections.
friend class PeerConnectionImpl;
friend class PeerConnectionWrapper;
@ -104,8 +60,7 @@ class PeerConnectionCtx : public CSF::CC_Observer {
// We could make these available only via accessors but it's too much trouble.
std::map<const std::string, PeerConnectionImpl *> mPeerConnections;
PeerConnectionCtx() : mSipccState(mozilla::dom::PCImplSipccState::Idle),
mCCM(nullptr), mDevice(nullptr), mGMPReady(false) {}
PeerConnectionCtx() : mGMPReady(false) {}
// This is a singleton, so don't copy construct it, etc.
PeerConnectionCtx(const PeerConnectionCtx& other) MOZ_DELETE;
void operator=(const PeerConnectionCtx& other) MOZ_DELETE;
@ -114,10 +69,6 @@ class PeerConnectionCtx : public CSF::CC_Observer {
nsresult Initialize();
nsresult Cleanup();
void ChangeSipccState(mozilla::dom::PCImplSipccState aState) {
mSipccState = aState;
}
void initGMP();
static void
@ -136,11 +87,6 @@ public:
private:
#endif
// SIPCC objects
mozilla::dom::PCImplSipccState mSipccState; // TODO(ekr@rtfm.com): refactor this out? What does it do?
CSF::CallControlManagerPtr mCCM;
CSF::CC_DevicePtr mDevice;
// We cannot form offers/answers properly until the Gecko Media Plugin stuff
// has been initted, which is a complicated mess of thread dispatches,
// including sync dispatches to main. So, we need to be able to queue up
@ -156,6 +102,6 @@ public:
static mozilla::StaticRefPtr<mozilla::PeerConnectionCtxShutdown> gPeerConnectionCtxShutdown;
};
} // namespace sipcc
} // namespace mozilla
#endif

View File

@ -22,8 +22,13 @@
#include "nricemediastream.h"
#include "nsComponentManagerUtils.h"
#include "nsPIDOMWindow.h"
#include "nsIUUIDGenerator.h"
#include "nsIThread.h"
#include "signaling/src/jsep/JsepSession.h"
#include "signaling/src/jsep/JsepSessionImpl.h"
#include "signaling/src/sdp/SdpMediaSection.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/PeerConnectionImplEnumsBinding.h"
#include "StreamBuffer.h"
@ -88,7 +93,6 @@ class PeerConnectionObserver;
typedef NS_ConvertUTF8toUTF16 PCObserverString;
#endif
}
class SipccOfferOptions;
}
#if defined(__cplusplus) && __cplusplus >= 201103L
@ -110,7 +114,7 @@ already_AddRefed<resulttype> func (__VA_ARGS__, rv)
struct MediaStreamTable;
namespace sipcc {
namespace mozilla {
using mozilla::dom::PeerConnectionObserver;
using mozilla::dom::RTCConfiguration;
@ -130,6 +134,15 @@ class PeerConnectionWrapper;
class PeerConnectionMedia;
class RemoteSourceStreamInfo;
// Uuid Generator
class PCUuidGenerator : public mozilla::JsepUuidGenerator {
public:
virtual bool Generate(std::string* idp) MOZ_OVERRIDE;
private:
nsCOMPtr<nsIUUIDGenerator> mGenerator;
};
class IceConfiguration
{
public:
@ -226,6 +239,7 @@ public:
enum Error {
kNoError = 0,
kInvalidCandidate = 2,
kInvalidMediastreamTrack = 3,
kInvalidState = 4,
kInvalidSessionDescription = 5,
@ -247,7 +261,8 @@ public:
IceConfiguration *aDst);
already_AddRefed<DOMMediaStream> MakeMediaStream(uint32_t aHint);
nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo);
nsresult CreateRemoteSourceStreamInfo(nsRefPtr<RemoteSourceStreamInfo>* aInfo,
const std::string& aId);
// DataConnection observers
void NotifyDataChannel(already_AddRefed<mozilla::DataChannel> aChannel);
@ -272,6 +287,10 @@ public:
NrIceCtx::ConnectionState state);
void IceGatheringStateChange(NrIceCtx* ctx,
NrIceCtx::GatheringState state);
// TODO(bug 1096795): Need a |component| id here for rtcp.
void EndOfLocalCandidates(const std::string& defaultAddr,
uint16_t defaultPort,
uint16_t level);
void IceStreamReady(NrIceMediaStream *aStream);
static void ListenThread(void *aData);
@ -291,9 +310,6 @@ public:
// Get the DTLS identity (local side)
mozilla::RefPtr<DtlsIdentity> const GetIdentity() const;
std::string GetFingerprint() const;
std::string GetFingerprintAlgorithm() const;
std::string GetFingerprintHexValue() const;
// Create a fake media stream
nsresult CreateFakeMediaStream(uint32_t hint, mozilla::DOMMediaStream** retval);
@ -336,7 +352,8 @@ public:
rv = CreateAnswer();
}
NS_IMETHODIMP CreateOffer(const mozilla::SipccOfferOptions& aConstraints);
NS_IMETHODIMP CreateOffer(
const mozilla::JsepOfferOptions& aConstraints);
NS_IMETHODIMP SetLocalDescription (int32_t aAction, const char* aSDP);
@ -368,8 +385,6 @@ public:
NS_ConvertUTF16toUTF8(aMid).get(), aLevel);
}
void OnRemoteStreamAdded(const MediaStreamTable& aStream);
NS_IMETHODIMP CloseStreams();
void CloseStreams(ErrorResult &rv)
@ -477,15 +492,6 @@ public:
return state;
}
NS_IMETHODIMP SipccState(mozilla::dom::PCImplSipccState* aState);
mozilla::dom::PCImplSipccState SipccState()
{
mozilla::dom::PCImplSipccState state;
SipccState(&state);
return state;
}
NS_IMETHODIMP IceConnectionState(
mozilla::dom::PCImplIceConnectionState* aState);
@ -517,8 +523,7 @@ public:
const nsAString& aPluginName,
const nsAString& aPluginDumpID);
nsresult InitializeDataChannel(int track_id, uint16_t aLocalport,
uint16_t aRemoteport, uint16_t aNumstreams);
nsresult InitializeDataChannel();
NS_IMETHODIMP_TO_ERRORRESULT(ConnectDataConnection, ErrorResult &rv,
uint16_t aLocalport,
@ -560,16 +565,6 @@ public:
// is called to start the list over.
void ClearSdpParseErrorMessages();
void StartTrickle();
// Called by VcmSIPCCBinding::vcmRxAllocICE; this is how sipcc tells us about
// each m-line it has put in the sdp.
void OnNewMline(uint16_t level) {
if (level > mNumMlines) {
mNumMlines = level;
}
}
void OnAddIceCandidateError() {
++mAddCandidateErrorCount;
}
@ -580,7 +575,7 @@ public:
// Sets the RTC Signaling State
void SetSignalingState_m(mozilla::dom::PCImplSignalingState aSignalingState);
// Updates the RTC signaling state based on the sipcc state
// Updates the RTC signaling state based on the JsepSession state
void UpdateSignalingState();
bool IsClosed() const;
@ -613,6 +608,9 @@ private:
const IceConfiguration* aConfiguration,
const RTCConfiguration* aRTCConfiguration,
nsISupports* aThread);
nsresult CalculateFingerprint(const std::string& algorithm,
std::vector<uint8_t>& fingerprint) const;
nsresult ConfigureJsepSessionCodecs();
NS_IMETHODIMP EnsureDataConnection(uint16_t aNumstreams);
@ -646,11 +644,10 @@ private:
void SendLocalIceCandidateToContent(uint16_t level,
const std::string& mid,
const std::string& candidate);
void FoundIceCandidate(const std::string& candidate, uint16_t level);
NS_IMETHOD FingerprintSplitHelper(
std::string& fingerprint, size_t& spaceIdx) const;
nsresult GetDatachannelParameters(
const mozilla::JsepApplicationCodecDescription** codec,
uint16_t* level) const;
#ifdef MOZILLA_INTERNAL_API
static void GetStatsForPCObserver_s(
@ -676,8 +673,6 @@ private:
// any other attributes of this class.
Timecard *mTimeCard;
// The call
mozilla::ScopedDeletePtr<Internal> mInternal;
mozilla::dom::PCImplSignalingState mSignalingState;
// ICE State
@ -697,12 +692,6 @@ private:
// The SDP sent in from JS - here for debugging.
std::string mLocalRequestedSDP;
std::string mRemoteRequestedSDP;
// The SDP we are using.
std::string mLocalSDP;
std::string mRemoteSDP;
// Holding tank for trickle candidates that arrive before setLocal is done.
std::vector<std::pair<std::string, uint16_t>> mCandidateBuffer;
// DTLS fingerprint
std::string mFingerprint;
@ -740,6 +729,10 @@ private:
bool mAllowIceLoopback;
nsRefPtr<PeerConnectionMedia> mMedia;
// The JSEP negotiation session.
mozilla::UniquePtr<PCUuidGenerator> mUuidGen;
mozilla::UniquePtr<mozilla::JsepSession> mJsepSession;
#ifdef MOZILLA_INTERNAL_API
// Start time of ICE, used for telemetry
mozilla::TimeStamp mIceStartTime;
@ -756,10 +749,6 @@ private:
bool mHaveDataStream;
uint16_t mNumMlines;
// Holder for error messages from parsing SDP
std::vector<std::string> mSDPParseErrorMessages;
unsigned int mAddCandidateErrorCount;
bool mTrickle;
@ -783,7 +772,7 @@ class PeerConnectionWrapper
nsRefPtr<PeerConnectionImpl> impl_;
};
} // end sipcc namespace
} // end mozilla namespace
#undef NS_IMETHODIMP_TO_ERRORRESULT
#undef NS_IMETHODIMP_TO_ERRORRESULT_RETREF

View File

@ -1,21 +1,27 @@
/* 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/. */
#include <ostream>
#include <string>
#include <vector>
#include "CSFLog.h"
#include "nspr.h"
#include "cc_constants.h"
#include "nricectx.h"
#include "nricemediastream.h"
#include "MediaPipelineFactory.h"
#include "PeerConnectionImpl.h"
#include "PeerConnectionMedia.h"
#include "AudioConduit.h"
#include "VideoConduit.h"
#include "runnable_utils.h"
#include "transportlayerice.h"
#include "transportlayerdtls.h"
#include "signaling/src/jsep/JsepSession.h"
#include "signaling/src/jsep/JsepTransport.h"
#ifdef MOZILLA_INTERNAL_API
#include "MediaStreamList.h"
@ -24,10 +30,10 @@
#include "mozilla/dom/RTCStatsReportBinding.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
namespace sipcc {
namespace mozilla {
static const char* logTag = "PeerConnectionMedia";
static const mozilla::TrackID TRACK_AUDIO = 0;
@ -134,12 +140,12 @@ int LocalSourceStreamInfo::HasTrackType(DOMMediaStream* aStream, bool aIsVideo)
}
// XXX revisit once we support multiple tracks of a type - bug 1056650
nsresult LocalSourceStreamInfo::ReplaceTrack(int aIndex,
nsresult LocalSourceStreamInfo::ReplaceTrack(int aMLine,
DOMMediaStream* aNewStream,
TrackID aNewTrack)
{
// Note aIndex != aOldTrack!
mozilla::RefPtr<mozilla::MediaPipeline> pipeline = mPipelines[aIndex];
// Note aMLine != aOldTrack!
mozilla::RefPtr<mozilla::MediaPipeline> pipeline = mPipelines[aMLine];
MOZ_ASSERT(pipeline);
if (NS_SUCCEEDED(static_cast<mozilla::MediaPipelineTransmit*>(pipeline.get())->ReplaceTrack(aNewStream, aNewTrack))) {
return NS_OK;
@ -166,7 +172,7 @@ void RemoteSourceStreamInfo::DetachMedia_m()
// walk through all the MediaPipelines and call the shutdown
// media functions. Must be on the main thread.
for (std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
mPipelines.begin(); it != mPipelines.end();
mPipelines.begin(); it != mPipelines.end();
++it) {
it->second->ShutdownMedia_m();
}
@ -196,15 +202,13 @@ PeerConnectionImpl* PeerConnectionImpl::CreatePeerConnection()
PeerConnectionMedia::PeerConnectionMedia(PeerConnectionImpl *parent)
: mParent(parent),
mParentHandle(parent->GetHandle()),
mParentName(parent->GetName()),
mAllowIceLoopback(false),
mIceCtx(nullptr),
mDNSResolver(new mozilla::NrIceResolver()),
mUuidGen(MakeUnique<PCUuidGenerator>()),
mMainThread(mParent->GetMainThread()),
mSTSThread(mParent->GetSTSThread()) {
#ifdef MOZILLA_INTERNAL_API
mAllowIceLoopback = Preferences::GetBool(
"media.peerconnection.ice.loopback", false);
#endif
}
nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_servers,
@ -212,7 +216,7 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
{
// TODO(ekr@rtfm.com): need some way to set not offerer later
// Looks like a bug in the NrIceCtx API.
mIceCtx = NrIceCtx::Create("PC:" + mParent->GetName(),
mIceCtx = NrIceCtx::Create("PC:" + mParentName,
true, // Offerer
true, // Trickle
mAllowIceLoopback);
@ -254,59 +258,274 @@ nsresult PeerConnectionMedia::Init(const std::vector<NrIceStunServer>& stun_serv
this,
&PeerConnectionMedia::IceConnectionStateChange_s);
// Create three streams to start with.
// One each for audio, video and DataChannel
// TODO: this will be re-visited
RefPtr<NrIceMediaStream> audioStream =
mIceCtx->CreateStream((mParent->GetName()+": stream1/audio").c_str(), 2);
RefPtr<NrIceMediaStream> videoStream =
mIceCtx->CreateStream((mParent->GetName()+": stream2/video").c_str(), 2);
RefPtr<NrIceMediaStream> dcStream =
mIceCtx->CreateStream((mParent->GetName()+": stream3/data").c_str(), 2);
return NS_OK;
}
if (!audioStream) {
CSFLogError(logTag, "%s: audio stream is NULL", __FUNCTION__);
return NS_ERROR_FAILURE;
} else {
mIceStreams.push_back(audioStream);
void
PeerConnectionMedia::UpdateTransports(const mozilla::JsepSession& session) {
size_t numTransports = session.GetTransportCount();
for (size_t i = 0; i < numTransports; ++i) {
RefPtr<JsepTransport> transport;
nsresult rv = session.GetTransport(i, &transport);
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv))
break;
std::string ufrag;
std::string pwd;
std::vector<std::string> candidates;
bool hasAttrs = false;
if (transport->mIce) {
hasAttrs = true;
ufrag = transport->mIce->GetUfrag();
pwd = transport->mIce->GetPassword();
candidates = transport->mIce->GetCandidates();
}
// Update the transport.
// TODO(bug 1017888): don't repeat candidates on renegotiation. Perhaps
// suppress inside nICEr?
RUN_ON_THREAD(GetSTSThread(),
WrapRunnable(RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::UpdateIceMediaStream_s,
i,
transport->mComponents,
hasAttrs,
ufrag,
pwd,
candidates),
NS_DISPATCH_NORMAL);
}
if (!videoStream) {
CSFLogError(logTag, "%s: video stream is NULL", __FUNCTION__);
return NS_ERROR_FAILURE;
} else {
mIceStreams.push_back(videoStream);
}
if (!dcStream) {
CSFLogError(logTag, "%s: datachannel stream is NULL", __FUNCTION__);
return NS_ERROR_FAILURE;
} else {
mIceStreams.push_back(dcStream);
}
// TODO(bug 1017888): Need to deal properly with renegotatiation.
// For now just start gathering.
RUN_ON_THREAD(GetSTSThread(),
WrapRunnable(
RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::EnsureIceGathering_s),
NS_DISPATCH_NORMAL);
// TODO(ekr@rtfm.com): This is not connected to the PCCimpl.
// Will need to do that later.
for (std::size_t i=0; i<mIceStreams.size(); i++) {
mIceStreams[i]->SetLevel(i + 1);
mIceStreams[i]->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady);
mIceStreams[i]->SignalCandidate.connect(
this,
&PeerConnectionMedia::OnCandidateFound_s);
}
}
// TODO(ekr@rtfm.com): When we have a generic error reporting mechanism,
// figure out how to report that StartGathering failed. Bug 827982.
RUN_ON_THREAD(mIceCtx->thread(),
WrapRunnable(mIceCtx, &NrIceCtx::StartGathering), NS_DISPATCH_NORMAL);
nsresult PeerConnectionMedia::UpdateMediaPipelines(
const mozilla::JsepSession& session) {
size_t numPairs = session.GetNegotiatedTrackPairCount();
mozilla::MediaPipelineFactory factory(this);
const mozilla::JsepTrackPair* pair;
for (size_t i = 0; i < numPairs; ++i) {
nsresult rv = session.GetNegotiatedTrackPair(i, &pair);
if (NS_FAILED(rv)) {
MOZ_ASSERT(false);
return rv;
}
// TODO(bug 1099318): We are forced to do receive then transmit, because of
// a bug in the VideoConduit code. This will need to be fixed for
// renegotiation.
if (pair->mReceiving) {
rv = factory.CreateMediaPipeline(*pair, *pair->mReceiving);
if (NS_FAILED(rv)) {
CSFLogError(logTag, "Failed to create receiving pipeline, rv=%u",
static_cast<unsigned>(rv));
return rv;
}
}
if (pair->mSending) {
rv = factory.CreateMediaPipeline(*pair, *pair->mSending);
if (NS_FAILED(rv)) {
CSFLogError(logTag, "Failed to create sending pipeline, rv=%u",
static_cast<unsigned>(rv));
return rv;
}
}
}
return NS_OK;
}
void
PeerConnectionMedia::StartIceChecks(const mozilla::JsepSession& session) {
std::vector<size_t> numComponentsByLevel;
for (size_t i = 0; i < session.GetTransportCount(); ++i) {
RefPtr<JsepTransport> transport;
nsresult rv = session.GetTransport(i, &transport);
if (NS_FAILED(rv)) {
CSFLogError(logTag, "JsepSession::GetTransport() failed: %u",
static_cast<unsigned>(rv));
MOZ_ASSERT(false, "JsepSession::GetTransport() failed!");
break;
}
if (transport->mState == JsepTransport::kJsepTransportClosed) {
numComponentsByLevel.push_back(0);
} else {
numComponentsByLevel.push_back(transport->mComponents);
}
}
RUN_ON_THREAD(GetSTSThread(),
WrapRunnable(
RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::StartIceChecks_s,
session.IsIceControlling(),
session.RemoteIsIceLite(),
// Copy, just in case API changes to return a ref
std::vector<std::string>(session.GetIceOptions()),
numComponentsByLevel),
NS_DISPATCH_NORMAL);
}
void
PeerConnectionMedia::StartIceChecks_s(
bool aIsControlling,
bool aIsIceLite,
const std::vector<std::string>& aIceOptionsList,
const std::vector<size_t>& aComponentCountByLevel) {
CSFLogDebug(logTag, "Starting ICE Checking");
std::vector<std::string> attributes;
if (aIsIceLite) {
attributes.push_back("ice-lite");
}
if (!aIceOptionsList.empty()) {
attributes.push_back("ice-options:");
for (auto i = aIceOptionsList.begin(); i != aIceOptionsList.end(); ++i) {
attributes.back() += *i + ' ';
}
}
nsresult rv = mIceCtx->ParseGlobalAttributes(attributes);
if (NS_FAILED(rv)) {
CSFLogError(logTag, "%s: couldn't parse global parameters", __FUNCTION__ );
}
mIceCtx->SetControlling(aIsControlling ?
NrIceCtx::ICE_CONTROLLING :
NrIceCtx::ICE_CONTROLLED);
for (size_t i = 0; i < aComponentCountByLevel.size(); ++i) {
RefPtr<NrIceMediaStream> stream(mIceCtx->GetStream(i));
if (!stream) {
MOZ_ASSERT(false, "JsepSession has more streams than the ICE ctx");
break;
}
for (size_t c = aComponentCountByLevel[i]; c < stream->components(); ++c) {
// components are 1-indexed
stream->DisableComponent(c + 1);
}
}
mIceCtx->StartChecks();
}
void
PeerConnectionMedia::AddIceCandidate(const std::string& candidate,
const std::string& mid,
uint32_t aMLine) {
RUN_ON_THREAD(GetSTSThread(),
WrapRunnable(
RefPtr<PeerConnectionMedia>(this),
&PeerConnectionMedia::AddIceCandidate_s,
std::string(candidate), // Make copies.
std::string(mid),
aMLine),
NS_DISPATCH_NORMAL);
}
void
PeerConnectionMedia::AddIceCandidate_s(const std::string& aCandidate,
const std::string& aMid,
uint32_t aMLine) {
if (aMLine >= mIceStreams.size()) {
CSFLogError(logTag, "Couldn't process ICE candidate for bogus level %u",
aMLine);
return;
}
nsresult rv = mIceStreams[aMLine]->ParseTrickleCandidate(aCandidate);
if (NS_FAILED(rv)) {
CSFLogError(logTag, "Couldn't process ICE candidate at level %u",
aMLine);
return;
}
}
void
PeerConnectionMedia::EnsureIceGathering_s() {
if (mIceCtx->gathering_state() == NrIceCtx::ICE_CTX_GATHER_INIT) {
mIceCtx->StartGathering();
}
}
void
PeerConnectionMedia::UpdateIceMediaStream_s(size_t aMLine,
size_t aComponentCount,
bool aHasAttrs,
const std::string& aUfrag,
const std::string& aPassword,
const std::vector<std::string>&
aCandidateList) {
if (aMLine > mIceStreams.size()) {
CSFLogError(logTag, "Missing stream for previous m-line %u, this can "
"happen if we failed to create a stream earlier.",
static_cast<unsigned>(aMLine - 1));
return;
}
CSFLogDebug(logTag, "%s: Creating ICE media stream=%u components=%u",
mParentHandle.c_str(),
static_cast<unsigned>(aMLine),
static_cast<unsigned>(aComponentCount));
RefPtr<NrIceMediaStream> stream;
if (mIceStreams.size() == aMLine) {
std::ostringstream os;
os << mParentName << " level=" << aMLine;
stream = mIceCtx->CreateStream(os.str().c_str(), aComponentCount);
if (!stream) {
CSFLogError(logTag, "Failed to create ICE stream.");
return;
}
stream->SetLevel(aMLine);
stream->SignalReady.connect(this, &PeerConnectionMedia::IceStreamReady_s);
stream->SignalCandidate.connect(this,
&PeerConnectionMedia::OnCandidateFound_s);
mIceStreams.push_back(stream);
} else {
stream = mIceStreams[aMLine];
}
if (aHasAttrs) {
std::vector<std::string> attrs;
for (auto i = aCandidateList.begin(); i != aCandidateList.end(); ++i) {
attrs.push_back("candidate:" + *i);
}
attrs.push_back("ice-ufrag:" + aUfrag);
attrs.push_back("ice-pwd:" + aPassword);
nsresult rv = stream->ParseAttributes(attrs);
if (NS_FAILED(rv)) {
CSFLogError(logTag, "Couldn't parse ICE attributes, rv=%u",
static_cast<unsigned>(rv));
}
}
}
nsresult
PeerConnectionMedia::AddStream(DOMMediaStream* aMediaStream,
uint32_t hints,
uint32_t *stream_id)
std::string *stream_id)
{
ASSERT_ON_THREAD(mMainThread);
@ -345,14 +564,20 @@ PeerConnectionMedia::AddStream(DOMMediaStream* aMediaStream,
}
if (aMediaStream == lss->GetMediaStream()) {
localSourceStream = lss;
*stream_id = u;
*stream_id = lss->GetId();
break;
}
}
if (!localSourceStream) {
localSourceStream = new LocalSourceStreamInfo(aMediaStream, this);
std::string id;
if (!mUuidGen->Generate(&id)) {
CSFLogError(logTag, "Failed to generate UUID for stream");
return NS_ERROR_FAILURE;
}
localSourceStream = new LocalSourceStreamInfo(aMediaStream, this, id);
mLocalSourceStreams.AppendElement(localSourceStream);
*stream_id = mLocalSourceStreams.Length() - 1;
*stream_id = id;
}
if (hints & DOMMediaStream::HINT_CONTENTS_AUDIO) {
@ -465,7 +690,7 @@ PeerConnectionMedia::ShutdownMediaTransport_s()
}
LocalSourceStreamInfo*
PeerConnectionMedia::GetLocalStream(int aIndex)
PeerConnectionMedia::GetLocalStreamByIndex(int aIndex)
{
ASSERT_ON_THREAD(mMainThread);
if(aIndex < 0 || aIndex >= (int) mLocalSourceStreams.Length()) {
@ -476,30 +701,57 @@ PeerConnectionMedia::GetLocalStream(int aIndex)
return mLocalSourceStreams[aIndex];
}
RemoteSourceStreamInfo*
PeerConnectionMedia::GetRemoteStream(int aIndex)
LocalSourceStreamInfo*
PeerConnectionMedia::GetLocalStreamById(const std::string& id)
{
ASSERT_ON_THREAD(mMainThread);
if(aIndex < 0 || aIndex >= (int) mRemoteSourceStreams.Length()) {
return nullptr;
for (size_t i = 0; i < mLocalSourceStreams.Length(); ++i) {
if (id == mLocalSourceStreams[i]->GetId()) {
return mLocalSourceStreams[i];
}
}
MOZ_ASSERT(mRemoteSourceStreams[aIndex]);
return mRemoteSourceStreams[aIndex];
MOZ_ASSERT(false);
return nullptr;
}
bool
PeerConnectionMedia::SetUsingBundle_m(int level, bool decision)
RemoteSourceStreamInfo*
PeerConnectionMedia::GetRemoteStreamByIndex(size_t aIndex)
{
ASSERT_ON_THREAD(mMainThread);
MOZ_ASSERT(mRemoteSourceStreams.SafeElementAt(aIndex));
return mRemoteSourceStreams.SafeElementAt(aIndex);
}
RemoteSourceStreamInfo*
PeerConnectionMedia::GetRemoteStreamById(const std::string& id)
{
ASSERT_ON_THREAD(mMainThread);
for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) {
if (mRemoteSourceStreams[i]->SetUsingBundle_m(level, decision)) {
// Found the MediaPipeline for |level|
if (id == mRemoteSourceStreams[i]->GetId()) {
return mRemoteSourceStreams[i];
}
}
// This does not have a MOZ_ASSERT like GetLocalStreamById because in the
// case of local streams, the stream id and stream info are created
// simultaneously, whereas in the remote case the stream id exists first,
// meaning we have to be able to check.
return nullptr;
}
bool
PeerConnectionMedia::SetUsingBundle_m(int aMLine, bool decision)
{
ASSERT_ON_THREAD(mMainThread);
for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) {
if (mRemoteSourceStreams[i]->SetUsingBundle_m(aMLine, decision)) {
// Found the MediaPipeline for |aMLine|
return true;
}
}
CSFLogWarn(logTag, "Could not locate level %d to set bundle flag to %s",
static_cast<int>(level),
static_cast<int>(aMLine),
decision ? "true" : "false");
return false;
}
@ -524,19 +776,19 @@ UpdateFilterFromRemoteDescription_s(
bool
PeerConnectionMedia::UpdateFilterFromRemoteDescription_m(
int level,
int aMLine,
nsAutoPtr<mozilla::MediaPipelineFilter> filter)
{
ASSERT_ON_THREAD(mMainThread);
RefPtr<mozilla::MediaPipeline> receive;
for (size_t i = 0; !receive && i < mRemoteSourceStreams.Length(); ++i) {
receive = mRemoteSourceStreams[i]->GetPipelineByLevel_m(level);
receive = mRemoteSourceStreams[i]->GetPipelineByLevel_m(aMLine);
}
RefPtr<mozilla::MediaPipeline> transmit;
for (size_t i = 0; !transmit && i < mLocalSourceStreams.Length(); ++i) {
transmit = mLocalSourceStreams[i]->GetPipelineByLevel_m(level);
transmit = mLocalSourceStreams[i]->GetPipelineByLevel_m(aMLine);
}
if (receive && transmit) {
@ -555,19 +807,15 @@ PeerConnectionMedia::UpdateFilterFromRemoteDescription_m(
return true;
} else {
CSFLogWarn(logTag, "Could not locate level %d to update filter",
static_cast<int>(level));
static_cast<int>(aMLine));
}
return false;
}
nsresult
PeerConnectionMedia::AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo,
int *aIndex)
PeerConnectionMedia::AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo)
{
ASSERT_ON_THREAD(mMainThread);
MOZ_ASSERT(aIndex);
*aIndex = mRemoteSourceStreams.Length();
mRemoteSourceStreams.AppendElement(aInfo);
@ -600,6 +848,31 @@ PeerConnectionMedia::IceGatheringStateChange_s(NrIceCtx* ctx,
NrIceCtx::GatheringState state)
{
ASSERT_ON_THREAD(mSTSThread);
if (state == NrIceCtx::ICE_CTX_GATHER_COMPLETE) {
// Fire off EndOfLocalCandidates for each stream
for (size_t i = 0; ; ++i) {
RefPtr<NrIceMediaStream> stream(ctx->GetStream(i));
if (!stream) {
break;
}
NrIceCandidate candidate;
nsresult res = stream->GetDefaultCandidate(&candidate);
if (NS_SUCCEEDED(res)) {
EndOfLocalCandidates(candidate.cand_addr.host,
candidate.cand_addr.port,
i);
} else {
CSFLogError(logTag, "%s: GetDefaultCandidate failed for level %u, "
"res=%u",
__FUNCTION__,
static_cast<unsigned>(i),
static_cast<unsigned>(res));
}
}
}
// ShutdownMediaTransport_s has not run yet because it unhooks this function
// from its signal, which means that SelfDestruct_m has not been dispatched
// yet either, so this PCMedia will still be around when this dispatch reaches
@ -650,6 +923,18 @@ PeerConnectionMedia::OnCandidateFound_s(NrIceMediaStream *aStream,
NS_DISPATCH_NORMAL);
}
void
PeerConnectionMedia::EndOfLocalCandidates(const std::string& aDefaultAddr,
uint16_t aDefaultPort,
uint16_t aMLine) {
// We will still be around because we have not started teardown yet
GetMainThread()->Dispatch(
WrapRunnable(this,
&PeerConnectionMedia::EndOfLocalCandidates_m,
aDefaultAddr, aDefaultPort, aMLine),
NS_DISPATCH_NORMAL);
}
void
PeerConnectionMedia::IceGatheringStateChange_m(NrIceCtx* ctx,
NrIceCtx::GatheringState state)
@ -667,7 +952,7 @@ PeerConnectionMedia::IceConnectionStateChange_m(NrIceCtx* ctx,
}
void
PeerConnectionMedia::IceStreamReady(NrIceMediaStream *aStream)
PeerConnectionMedia::IceStreamReady_s(NrIceMediaStream *aStream)
{
MOZ_ASSERT(aStream);
@ -676,13 +961,18 @@ PeerConnectionMedia::IceStreamReady(NrIceMediaStream *aStream)
void
PeerConnectionMedia::OnCandidateFound_m(const std::string &candidate,
uint16_t level)
uint16_t aMLine)
{
ASSERT_ON_THREAD(mMainThread);
SignalCandidate(candidate, level);
SignalCandidate(candidate, aMLine);
}
void
PeerConnectionMedia::EndOfLocalCandidates_m(const std::string& aDefaultAddr,
uint16_t aDefaultPort,
uint16_t aMLine) {
SignalEndOfLocalCandidates(aDefaultAddr, aDefaultPort, aMLine);
}
void
PeerConnectionMedia::DtlsConnected_s(TransportLayer *dtlsLayer,
@ -841,29 +1131,29 @@ RemoteSourceStreamInfo::AnyCodecHasPluginID(uint64_t aPluginID)
void
LocalSourceStreamInfo::StorePipeline(
int aTrack, mozilla::RefPtr<mozilla::MediaPipelineTransmit> aPipeline)
int aMLine, mozilla::RefPtr<mozilla::MediaPipelineTransmit> aPipeline)
{
MOZ_ASSERT(mPipelines.find(aTrack) == mPipelines.end());
if (mPipelines.find(aTrack) != mPipelines.end()) {
MOZ_ASSERT(mPipelines.find(aMLine) == mPipelines.end());
if (mPipelines.find(aMLine) != mPipelines.end()) {
CSFLogError(logTag, "%s: Storing duplicate track", __FUNCTION__);
return;
}
//TODO: Revisit once we start supporting multiple streams or multiple tracks
// of same type bug 1056650
mPipelines[aTrack] = aPipeline;
mPipelines[aMLine] = aPipeline;
}
void
RemoteSourceStreamInfo::StorePipeline(
int aTrack, bool aIsVideo,
int aMLine, bool aIsVideo,
mozilla::RefPtr<mozilla::MediaPipelineReceive> aPipeline)
{
MOZ_ASSERT(mPipelines.find(aTrack) == mPipelines.end());
if (mPipelines.find(aTrack) != mPipelines.end()) {
CSFLogError(logTag, "%s: Request to store duplicate track %d", __FUNCTION__, aTrack);
MOZ_ASSERT(mPipelines.find(aMLine) == mPipelines.end());
if (mPipelines.find(aMLine) != mPipelines.end()) {
CSFLogError(logTag, "%s: Request to store duplicate track %d", __FUNCTION__, aMLine);
return;
}
CSFLogDebug(logTag, "%s track %d %s = %p", __FUNCTION__, aTrack, aIsVideo ? "video" : "audio",
CSFLogDebug(logTag, "%s track %d %s = %p", __FUNCTION__, aMLine, aIsVideo ? "video" : "audio",
aPipeline.get());
// See if we have both audio and video here, and if so cross the streams and sync them
// XXX Needs to be adjusted when we support multiple streams of the same type bug 1056650
@ -880,17 +1170,17 @@ RemoteSourceStreamInfo::StorePipeline(
mPipelines[it->first]->Conduit());
video_conduit->SyncTo(audio_conduit);
CSFLogDebug(logTag, "Syncing %p to %p, %d to %d", video_conduit, audio_conduit,
aTrack, it->first);
aMLine, it->first);
}
}
//TODO: Revisit once we start supporting multiple streams or multiple tracks
// of same type bug 1056650
mPipelines[aTrack] = aPipeline;
mPipelines[aMLine] = aPipeline;
//TODO: move to attribute on Pipeline
mTypes[aTrack] = aIsVideo;
mTypes[aMLine] = aIsVideo;
}
RefPtr<MediaPipeline> SourceStreamInfo::GetPipelineByLevel_m(int level) {
RefPtr<MediaPipeline> SourceStreamInfo::GetPipelineByLevel_m(int aMLine) {
ASSERT_ON_THREAD(mParent->GetMainThread());
// Refuse to hand out references if we're tearing down.
@ -900,7 +1190,7 @@ RefPtr<MediaPipeline> SourceStreamInfo::GetPipelineByLevel_m(int level) {
// standing)
if (mMediaStream) {
for (auto p = mPipelines.begin(); p != mPipelines.end(); ++p) {
if (p->second->level() == level) {
if (p->second->level() == aMLine) {
return p->second;
}
}
@ -909,11 +1199,11 @@ RefPtr<MediaPipeline> SourceStreamInfo::GetPipelineByLevel_m(int level) {
return nullptr;
}
bool RemoteSourceStreamInfo::SetUsingBundle_m(int aLevel, bool decision) {
bool RemoteSourceStreamInfo::SetUsingBundle_m(int aMLine, bool decision) {
ASSERT_ON_THREAD(mParent->GetMainThread());
// Avoid adding and dropping an extra ref
MediaPipeline *pipeline = GetPipelineByLevel_m(aLevel);
MediaPipeline *pipeline = GetPipelineByLevel_m(aMLine);
if (pipeline) {
RUN_ON_THREAD(mParent->GetSTSThread(),
@ -928,4 +1218,4 @@ bool RemoteSourceStreamInfo::SetUsingBundle_m(int aLevel, bool decision) {
return false;
}
} // namespace sipcc
} // namespace mozilla

View File

@ -22,6 +22,7 @@
#include "MediaSegment.h"
#endif
#include "signaling/src/jsep/JsepSession.h"
#include "AudioSegment.h"
#ifdef MOZILLA_INTERNAL_API
@ -36,6 +37,7 @@ class nsIPrincipal;
namespace mozilla {
class DataChannel;
class PeerIdentity;
class MediaPipelineFactory;
namespace dom {
struct RTCInboundRTPStreamStats;
struct RTCOutboundRTPStreamStats;
@ -47,16 +49,15 @@ struct RTCOutboundRTPStreamStats;
#include "nricemediastream.h"
#include "MediaPipeline.h"
namespace sipcc {
namespace mozilla {
class PeerConnectionImpl;
class PeerConnectionMedia;
class PCUuidGenerator;
/* Temporary for providing audio data */
class Fake_AudioGenerator {
public:
typedef mozilla::DOMMediaStream DOMMediaStream;
explicit Fake_AudioGenerator(DOMMediaStream* aStream) : mStream(aStream), mCount(0) {
mTimer = do_CreateInstance("@mozilla.org/timer;1");
MOZ_ASSERT(mTimer);
@ -96,7 +97,6 @@ class Fake_AudioGenerator {
#ifdef MOZILLA_INTERNAL_API
class Fake_VideoGenerator {
public:
typedef mozilla::DOMMediaStream DOMMediaStream;
typedef mozilla::gfx::IntSize IntSize;
explicit Fake_VideoGenerator(DOMMediaStream* aStream) {
@ -174,19 +174,21 @@ class Fake_VideoGenerator {
class SourceStreamInfo {
public:
typedef mozilla::DOMMediaStream DOMMediaStream;
SourceStreamInfo(DOMMediaStream* aMediaStream,
PeerConnectionMedia *aParent)
PeerConnectionMedia *aParent,
const std::string& aId)
: mMediaStream(aMediaStream),
mParent(aParent) {
mParent(aParent),
mId(aId) {
MOZ_ASSERT(mMediaStream);
}
SourceStreamInfo(already_AddRefed<DOMMediaStream>& aMediaStream,
PeerConnectionMedia *aParent)
PeerConnectionMedia *aParent,
const std::string& aId)
: mMediaStream(aMediaStream),
mParent(aParent) {
mParent(aParent),
mId(aId) {
MOZ_ASSERT(mMediaStream);
}
@ -198,12 +200,14 @@ public:
// It allows visibility into the pipelines and flows.
const std::map<mozilla::TrackID, mozilla::RefPtr<mozilla::MediaPipeline>>&
GetPipelines() const { return mPipelines; }
mozilla::RefPtr<mozilla::MediaPipeline> GetPipelineByLevel_m(int level);
mozilla::RefPtr<mozilla::MediaPipeline> GetPipelineByLevel_m(int aMLine);
const std::string& GetId() const { return mId; }
protected:
std::map<mozilla::TrackID, mozilla::RefPtr<mozilla::MediaPipeline>> mPipelines;
nsRefPtr<DOMMediaStream> mMediaStream;
PeerConnectionMedia *mParent;
const std::string mId;
};
// TODO(ekr@rtfm.com): Refactor {Local,Remote}SourceStreamInfo
@ -213,28 +217,28 @@ class LocalSourceStreamInfo : public SourceStreamInfo {
mMediaStream = nullptr;
}
public:
typedef mozilla::DOMMediaStream DOMMediaStream;
LocalSourceStreamInfo(DOMMediaStream *aMediaStream,
PeerConnectionMedia *aParent)
: SourceStreamInfo(aMediaStream, aParent) {}
PeerConnectionMedia *aParent,
const std::string& aId)
: SourceStreamInfo(aMediaStream, aParent, aId) {}
// Returns the mPipelines index for the track or -1.
#if 0
int HasTrack(DOMMediaStream* aStream, mozilla::TrackID aTrack);
int HasTrack(DOMMediaStream* aStream, mozilla::TrackID aMLine);
#endif
int HasTrackType(DOMMediaStream* aStream, bool aIsVideo);
// XXX NOTE: does not change mMediaStream, even if it replaces the last track
// in a LocalSourceStreamInfo. Revise when we have support for multiple tracks
// of a type.
// Note aIndex != aOldTrack! It's the result of HasTrackType()
nsresult ReplaceTrack(int aIndex, DOMMediaStream* aNewStream, mozilla::TrackID aNewTrack);
// Note aMLine != aOldTrack! It's the result of HasTrackType()
nsresult ReplaceTrack(int aMLine, DOMMediaStream* aNewStream, mozilla::TrackID aNewTrack);
void StorePipeline(int aTrack,
void StorePipeline(int aMLine,
mozilla::RefPtr<mozilla::MediaPipelineTransmit> aPipeline);
#ifdef MOZILLA_INTERNAL_API
void UpdateSinkIdentity_m(nsIPrincipal* aPrincipal, const PeerIdentity* aSinkIdentity);
void UpdateSinkIdentity_m(nsIPrincipal* aPrincipal,
const mozilla::PeerIdentity* aSinkIdentity);
#endif
void ExpectAudio(const mozilla::TrackID);
@ -257,17 +261,17 @@ private:
class RemoteSourceStreamInfo : public SourceStreamInfo {
~RemoteSourceStreamInfo() {}
public:
typedef mozilla::DOMMediaStream DOMMediaStream;
RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
PeerConnectionMedia *aParent)
: SourceStreamInfo(aMediaStream, aParent),
mTrackTypeHints(0) {}
PeerConnectionMedia *aParent,
const std::string& aId)
: SourceStreamInfo(aMediaStream, aParent, aId),
mTrackTypeHints(0) {
}
void StorePipeline(int aTrack, bool aIsVideo,
void StorePipeline(int aMLine, bool aIsVideo,
mozilla::RefPtr<mozilla::MediaPipelineReceive> aPipeline);
bool SetUsingBundle_m(int aLevel, bool decision);
bool SetUsingBundle_m(int aMLine, bool decision);
void DetachTransport_s();
void DetachMedia_m();
@ -292,6 +296,7 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
public:
explicit PeerConnectionMedia(PeerConnectionImpl *parent);
PeerConnectionImpl* GetPC() { return mParent; }
nsresult Init(const std::vector<mozilla::NrIceStunServer>& stun_servers,
const std::vector<mozilla::NrIceTurnServer>& turn_servers);
// WARNING: This destroys the object!
@ -315,9 +320,22 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
return mIceStreams.size();
}
// Create and modify transports in response to negotiation events.
void UpdateTransports(const mozilla::JsepSession& session);
// Start ICE checks.
void StartIceChecks(const mozilla::JsepSession& session);
// Process a trickle ICE candidate.
void AddIceCandidate(const std::string& candidate, const std::string& mid,
uint32_t aMLine);
// Handle complete media pipelines.
nsresult UpdateMediaPipelines(const mozilla::JsepSession& session);
// Add a stream (main thread only)
nsresult AddStream(DOMMediaStream* aMediaStream, uint32_t hints,
uint32_t *stream_id);
std::string* stream_id);
// Remove a stream (main thread only)
nsresult RemoveStream(DOMMediaStream* aMediaStream,
@ -329,29 +347,33 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
{
return mLocalSourceStreams.Length();
}
LocalSourceStreamInfo* GetLocalStream(int index);
LocalSourceStreamInfo* GetLocalStreamByIndex(int index);
LocalSourceStreamInfo* GetLocalStreamById(const std::string& id);
// Get a specific remote stream
uint32_t RemoteStreamsLength()
{
return mRemoteSourceStreams.Length();
}
RemoteSourceStreamInfo* GetRemoteStream(int index);
bool SetUsingBundle_m(int level, bool decision);
RemoteSourceStreamInfo* GetRemoteStreamByIndex(size_t index);
RemoteSourceStreamInfo* GetRemoteStreamById(const std::string& id);
bool SetUsingBundle_m(int aMLine, bool decision);
bool UpdateFilterFromRemoteDescription_m(
int level,
int aMLine,
nsAutoPtr<mozilla::MediaPipelineFilter> filter);
// Add a remote stream. Returns the index in index
nsresult AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo, int *aIndex);
// Add a remote stream.
nsresult AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo);
nsresult AddRemoteStreamHint(int aIndex, bool aIsVideo);
#ifdef MOZILLA_INTERNAL_API
// In cases where the peer isn't yet identified, we disable the pipeline (not
// the stream, that would potentially affect others), so that it sends
// black/silence. Once the peer is identified, re-enable those streams.
void UpdateSinkIdentity_m(nsIPrincipal* aPrincipal, const PeerIdentity* aSinkIdentity);
void UpdateSinkIdentity_m(nsIPrincipal* aPrincipal,
const mozilla::PeerIdentity* aSinkIdentity);
// this determines if any stream is peerIdentity constrained
bool AnyLocalStreamHasPeerIdentity() const;
// When we finally learn who is on the other end, we need to change the ownership
@ -408,7 +430,11 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
SignalIceGatheringStateChange;
sigslot::signal2<mozilla::NrIceCtx*, mozilla::NrIceCtx::ConnectionState>
SignalIceConnectionStateChange;
// This passes a candidate:... attribute and level
sigslot::signal2<const std::string&, uint16_t> SignalCandidate;
// This passes address, port, level of the default candidate.
sigslot::signal3<const std::string&, uint16_t, uint16_t>
SignalEndOfLocalCandidates;
private:
// Shutdown media transport. Must be called on STS thread.
@ -418,26 +444,50 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
// thread.
void SelfDestruct_m();
// Manage ICE transports.
void UpdateIceMediaStream_s(size_t aMLine, size_t aComponentCount,
bool aHasAttrs,
const std::string& aUfrag,
const std::string& aPassword,
const std::vector<std::string>& aCandidateList);
void EnsureIceGathering_s();
void StartIceChecks_s(bool aIsControlling,
bool aIsIceLite,
const std::vector<std::string>& aIceOptionsList,
const std::vector<size_t>& aComponentCountByLevel);
// Process a trickle ICE candidate.
void AddIceCandidate_s(const std::string& aCandidate, const std::string& aMid,
uint32_t aMLine);
// ICE events
void IceGatheringStateChange_s(mozilla::NrIceCtx* ctx,
mozilla::NrIceCtx::GatheringState state);
void IceConnectionStateChange_s(mozilla::NrIceCtx* ctx,
mozilla::NrIceCtx::ConnectionState state);
void IceStreamReady(mozilla::NrIceMediaStream *aStream);
void IceStreamReady_s(mozilla::NrIceMediaStream *aStream);
void OnCandidateFound_s(mozilla::NrIceMediaStream *aStream,
const std::string &candidate);
void EndOfLocalCandidates(const std::string& aDefaultAddr,
uint16_t aDefaultPort,
uint16_t aMLine);
void IceGatheringStateChange_m(mozilla::NrIceCtx* ctx,
mozilla::NrIceCtx::GatheringState state);
void IceConnectionStateChange_m(mozilla::NrIceCtx* ctx,
mozilla::NrIceCtx::ConnectionState state);
void OnCandidateFound_m(const std::string &candidate, uint16_t level);
void OnCandidateFound_m(const std::string &candidate, uint16_t aMLine);
void EndOfLocalCandidates_m(const std::string& aDefaultAddr,
uint16_t aDefaultPort,
uint16_t aMLine);
// The parent PC
PeerConnectionImpl *mParent;
// and a loose handle on it for event driven stuff
std::string mParentHandle;
std::string mParentName;
// A list of streams returned from GetUserMedia
// This is only accessed on the main thread (with one special exception)
@ -464,6 +514,9 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
// flows)
std::map<int, mozilla::RefPtr<mozilla::MediaSessionConduit> > mConduits;
// UUID Generator
mozilla::UniquePtr<PCUuidGenerator> mUuidGen;
// The main thread.
nsCOMPtr<nsIThread> mMainThread;
@ -473,5 +526,5 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(PeerConnectionMedia)
};
} // namespace sipcc
} // namespace mozilla
#endif

View File

@ -25,18 +25,15 @@
#include "PeerConnectionImpl.h"
#include "webrtc/system_wrappers/interface/trace.h"
using sipcc::PeerConnectionImpl;
using sipcc::PeerConnectionCtx;
using sipcc::RTCStatsQuery;
static const char* logTag = "WebrtcGlobalInformation";
namespace mozilla {
namespace dom {
typedef Vector<nsAutoPtr<RTCStatsQuery>> RTCStatsQueries;
static sipcc::PeerConnectionCtx* GetPeerConnectionCtx()
static PeerConnectionCtx* GetPeerConnectionCtx()
{
if(PeerConnectionCtx::isActive()) {
MOZ_ASSERT(PeerConnectionCtx::GetInstance());
@ -500,7 +497,7 @@ static void GetStatsForLongTermStorage_s(
}
void WebrtcGlobalInformation::StoreLongTermICEStatistics(
sipcc::PeerConnectionImpl& aPc) {
PeerConnectionImpl& aPc) {
Telemetry::Accumulate(Telemetry::WEBRTC_ICE_FINAL_CONNECTION_STATE,
static_cast<uint32_t>(aPc.IceConnectionState()));

View File

@ -8,11 +8,8 @@
#include "nsString.h"
#include "mozilla/dom/BindingDeclarations.h" // for Optional
namespace sipcc {
class PeerConnectionImpl;
}
namespace mozilla {
class PeerConnectionImpl;
class ErrorResult;
namespace dom {
@ -39,7 +36,7 @@ public:
static void SetAecDebug(const GlobalObject& aGlobal, bool aEnable);
static bool AecDebug(const GlobalObject& aGlobal);
static void StoreLongTermICEStatistics(sipcc::PeerConnectionImpl& aPc);
static void StoreLongTermICEStatistics(PeerConnectionImpl& aPc);
private:
WebrtcGlobalInformation() MOZ_DELETE;

View File

@ -22,7 +22,7 @@
#include "PeerConnectionImpl.h"
#include "nsWeakReference.h"
namespace sipcc {
namespace mozilla {
class PeerConnectionImpl;
}
@ -47,7 +47,7 @@ public:
stateError
};
AFakePCObserver(sipcc::PeerConnectionImpl *peerConnection,
AFakePCObserver(mozilla::PeerConnectionImpl *peerConnection,
const std::string &aName) :
state(stateNoResponse), addIceSuccessCount(0),
onAddStreamCalled(false),
@ -61,7 +61,7 @@ public:
ResponseState state;
std::string lastString;
sipcc::PeerConnectionImpl::Error lastStatusCode;
mozilla::PeerConnectionImpl::Error lastStatusCode;
mozilla::dom::PCObserverStateType lastStateType;
int addIceSuccessCount;
bool onAddStreamCalled;
@ -90,7 +90,7 @@ public:
virtual NS_IMETHODIMP OnIceCandidate(uint16_t level, const char *mid,
const char *candidate, ER&) = 0;
protected:
sipcc::PeerConnectionImpl *pc;
mozilla::PeerConnectionImpl *pc;
std::vector<mozilla::DOMMediaStream *> streams;
};
}

View File

@ -629,8 +629,8 @@ class TransportConduitTest : public ::testing::Test
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
//configure send and recv codecs on theconduit
mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
mozilla::VideoCodecConfig cinst2(124, "I420", 0);
mozilla::VideoCodecConfig cinst1(120, "VP8");
mozilla::VideoCodecConfig cinst2(124, "I420");
std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
@ -711,8 +711,8 @@ class TransportConduitTest : public ::testing::Test
cerr << " 1. Same Codec (VP8) Repeated Twice " << endl;
cerr << " *************************************************" << endl;
mozilla::VideoCodecConfig cinst1(120, "VP8", 0);
mozilla::VideoCodecConfig cinst2(120, "VP8", 0);
mozilla::VideoCodecConfig cinst1(120, "VP8");
mozilla::VideoCodecConfig cinst2(120, "VP8");
rcvCodecList.push_back(&cinst1);
rcvCodecList.push_back(&cinst2);
err = videoSession->ConfigureRecvMediaCodecs(rcvCodecList);
@ -728,8 +728,8 @@ class TransportConduitTest : public ::testing::Test
cerr << " Setting payload 1 with name: I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676" << endl;
cerr << " Setting payload 2 with name of zero length" << endl;
mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676", 0);
mozilla::VideoCodecConfig cinst4(124, "", 0);
mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676");
mozilla::VideoCodecConfig cinst4(124, "");
rcvCodecList.push_back(&cinst3);
rcvCodecList.push_back(&cinst4);
@ -812,7 +812,7 @@ class TransportConduitTest : public ::testing::Test
ASSERT_NE(mVideoSession, (void*)nullptr);
// Configure send codecs on the conduit.
mozilla::VideoCodecConfig cinst1(120, "VP8", 0, max_fs);
mozilla::VideoCodecConfig cinst1(120, "VP8", max_fs);
err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
@ -947,7 +947,7 @@ class TransportConduitTest : public ::testing::Test
void SetGmpCodecs() {
mExternalEncoder = mozilla::GmpVideoCodec::CreateEncoder();
mExternalDecoder = mozilla::GmpVideoCodec::CreateDecoder();
mozilla::VideoCodecConfig config(124, "H264", 0);
mozilla::VideoCodecConfig config(124, "H264");
mVideoSession->SetExternalSendCodec(&config, mExternalEncoder);
mVideoSession2->SetExternalRecvCodec(&config, mExternalDecoder);
}

View File

@ -271,7 +271,6 @@ class TestAgentSend : public TestAgent {
test_utils->sts_target(),
audio_,
1,
1,
false,
audio_conduit_,
rtp,

View File

@ -56,7 +56,7 @@ static bool SetupGlobalThread() {
return false;
gThread = thread;
sipcc::PeerConnectionCtx::InitializeGlobal(gThread,
PeerConnectionCtx::InitializeGlobal(gThread,
test_utils->sts_target());
}
return true;
@ -2444,7 +2444,7 @@ int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
sipcc::PeerConnectionCtx::Destroy();
PeerConnectionCtx::Destroy();
delete test_utils;
return result;

File diff suppressed because it is too large Load Diff

View File

@ -335,8 +335,8 @@ pref("media.navigator.video.default_width",0); // adaptive default
pref("media.navigator.video.default_height",0); // adaptive default
pref("media.peerconnection.enabled", true);
pref("media.peerconnection.video.enabled", true);
pref("media.navigator.video.max_fs", 0); // unrestricted
pref("media.navigator.video.max_fr", 0); // unrestricted
pref("media.navigator.video.max_fs", 12288); // Enough for 2048x1536
pref("media.navigator.video.max_fr", 60);
pref("media.navigator.video.h264.level", 31); // 0x42E01f - level 3.1
pref("media.navigator.video.h264.max_br", 0);
pref("media.navigator.video.h264.max_mbps", 0);
@ -359,6 +359,7 @@ pref("media.peerconnection.use_document_iceservers", true);
// Do not enable identity before fixing origin spoofing: see Bug 968335
pref("media.peerconnection.identity.enabled", false);
pref("media.peerconnection.identity.timeout", 10000);
pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments.
// These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
// kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each
// setting (for Xxx = Ec, Agc, or Ns). Defaults are all set to kXxxDefault here.

View File

@ -25,7 +25,7 @@ class DeviceRunner(BaseRunner):
'MOZ_CRASHREPORTER_NO_REPORT': '1',
'MOZ_CRASHREPORTER_SHUTDOWN': '1',
'MOZ_HIDE_RESULTS_TABLE': '1',
'NSPR_LOG_MODULES': 'signaling:5,mtransport:5,datachannel:5',
'NSPR_LOG_MODULES': 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5',
'R_LOG_LEVEL': '6',
'R_LOG_DESTINATION': 'stderr',
'R_LOG_VERBOSE': '1',