зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset c5334aea6433 (bug 786234)
This commit is contained in:
Родитель
a231c2f65a
Коммит
34d7d2d699
|
@ -199,17 +199,6 @@ TransportResult TransportFlow::SendPacket(const unsigned char *data,
|
|||
return top() ? top()->SendPacket(data, len) : TE_ERROR;
|
||||
}
|
||||
|
||||
bool TransportFlow::Contains(TransportLayer *layer) const {
|
||||
if (layers_) {
|
||||
for (auto l = layers_->begin(); l != layers_->end(); ++l) {
|
||||
if (*l == layer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TransportFlow::EnsureSameThread(TransportLayer *layer) {
|
||||
// Enforce that if any of the layers have a thread binding,
|
||||
// they all have the same binding.
|
||||
|
|
|
@ -96,8 +96,6 @@ class TransportFlow : public sigslot::has_slots<> {
|
|||
sigslot::signal3<TransportFlow*, const unsigned char *, size_t>
|
||||
SignalPacketReceived;
|
||||
|
||||
bool Contains(TransportLayer *layer) const;
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TransportFlow)
|
||||
|
||||
private:
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "MediaConduitErrors.h"
|
||||
#include "MediaConduitInterface.h"
|
||||
#include "MediaPipeline.h"
|
||||
#include "MediaPipelineFilter.h"
|
||||
#include "VcmSIPCCBinding.h"
|
||||
#include "csf_common.h"
|
||||
#include "PeerConnectionImpl.h"
|
||||
|
@ -1502,12 +1501,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
|||
const char *fingerprint,
|
||||
vcm_mediaAttrs_t *attrs)
|
||||
{
|
||||
CSFLogDebug( logTag, "%s(%s) track = %d, stream = %d, level = %d",
|
||||
__FUNCTION__,
|
||||
peerconnection,
|
||||
pc_track_id,
|
||||
pc_stream_id,
|
||||
level);
|
||||
CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection);
|
||||
|
||||
// Find the PC.
|
||||
sipcc::PeerConnectionWrapper pc(peerconnection);
|
||||
|
@ -1543,7 +1537,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
|||
}
|
||||
|
||||
mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
|
||||
if (!attrs->rtcp_mux) {
|
||||
if(!attrs->rtcp_mux) {
|
||||
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type,
|
||||
fingerprint_alg, fingerprint);
|
||||
if (!rtcp_flow) {
|
||||
|
@ -1552,60 +1546,6 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
|||
}
|
||||
}
|
||||
|
||||
// If we're offering bundle, a given MediaPipeline could receive traffic on
|
||||
// two different network flows depending on whether the answerer accepts,
|
||||
// before any answer comes in. We need to be prepared for both cases.
|
||||
nsAutoPtr<mozilla::MediaPipelineFilter> filter;
|
||||
RefPtr<TransportFlow> bundle_rtp_flow;
|
||||
RefPtr<TransportFlow> bundle_rtcp_flow;
|
||||
if (attrs->bundle_level) {
|
||||
filter = new MediaPipelineFilter;
|
||||
// Record our correlator, if present in our offer.
|
||||
filter->SetCorrelator(attrs->bundle_stream_correlator);
|
||||
|
||||
// Record our own ssrcs (these are _not_ those of the remote end; that
|
||||
// is handled in vcmTxStart)
|
||||
for (int s = 0; s < attrs->num_ssrcs; ++s) {
|
||||
filter->AddLocalSSRC(attrs->ssrcs[s]);
|
||||
}
|
||||
|
||||
// Record the unique payload types
|
||||
for (int p = 0; p < attrs->num_unique_payload_types; ++p) {
|
||||
filter->AddUniquePT(attrs->unique_payload_types[p]);
|
||||
}
|
||||
|
||||
// Do not pass additional TransportFlows if the pipeline will use the same
|
||||
// flow regardless of whether bundle happens or not.
|
||||
if (attrs->bundle_level != (unsigned int)level) {
|
||||
// This might end up creating it, or might reuse it.
|
||||
mozilla::RefPtr<TransportFlow> bundle_rtp_flow =
|
||||
vcmCreateTransportFlow(pc.impl(),
|
||||
attrs->bundle_level,
|
||||
false,
|
||||
setup_type,
|
||||
fingerprint_alg,
|
||||
fingerprint);
|
||||
|
||||
if (!bundle_rtp_flow) {
|
||||
CSFLogError( logTag, "Could not create bundle RTP flow");
|
||||
return VCM_ERROR;
|
||||
}
|
||||
|
||||
if (!attrs->rtcp_mux) {
|
||||
bundle_rtcp_flow = vcmCreateTransportFlow(pc.impl(),
|
||||
attrs->bundle_level,
|
||||
true,
|
||||
setup_type,
|
||||
fingerprint_alg,
|
||||
fingerprint);
|
||||
if (!bundle_rtcp_flow) {
|
||||
CSFLogError( logTag, "Could not create bundle RTCP flow");
|
||||
return VCM_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CC_IS_AUDIO(mcap_id)) {
|
||||
std::vector<mozilla::AudioCodecConfig *> configs;
|
||||
|
||||
|
@ -1640,6 +1580,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
|||
if (conduit->ConfigureRecvMediaCodecs(configs))
|
||||
return VCM_ERROR;
|
||||
|
||||
|
||||
// Now we have all the pieces, create the pipeline
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
|
||||
new mozilla::MediaPipelineReceiveAudio(
|
||||
|
@ -1649,12 +1590,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
|||
stream->GetMediaStream()->GetStream(),
|
||||
pc_track_id,
|
||||
level,
|
||||
conduit,
|
||||
rtp_flow,
|
||||
rtcp_flow,
|
||||
bundle_rtp_flow,
|
||||
bundle_rtcp_flow,
|
||||
filter);
|
||||
conduit, rtp_flow, rtcp_flow);
|
||||
|
||||
nsresult res = pipeline->Init();
|
||||
if (NS_FAILED(res)) {
|
||||
|
@ -1706,12 +1642,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
|||
stream->GetMediaStream()->GetStream(),
|
||||
pc_track_id,
|
||||
level,
|
||||
conduit,
|
||||
rtp_flow,
|
||||
rtcp_flow,
|
||||
bundle_rtp_flow,
|
||||
bundle_rtcp_flow,
|
||||
filter);
|
||||
conduit, rtp_flow, rtcp_flow);
|
||||
|
||||
nsresult res = pipeline->Init();
|
||||
if (NS_FAILED(res)) {
|
||||
|
@ -2251,12 +2182,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
|||
const char *fingerprint,
|
||||
vcm_mediaAttrs_t *attrs)
|
||||
{
|
||||
CSFLogDebug( logTag, "%s(%s) track = %d, stream = %d, level = %d",
|
||||
__FUNCTION__,
|
||||
peerconnection,
|
||||
pc_track_id,
|
||||
pc_stream_id,
|
||||
level);
|
||||
CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection);
|
||||
|
||||
// Find the PC and get the stream
|
||||
sipcc::PeerConnectionWrapper pc(peerconnection);
|
||||
|
@ -2282,22 +2208,6 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
|||
}
|
||||
}
|
||||
|
||||
// This tells the receive MediaPipeline (if there is one) whether we are
|
||||
// doing bundle, and if so, updates the filter. This does not affect the
|
||||
// transmit MediaPipeline (created above) at all.
|
||||
if (attrs->bundle_level) {
|
||||
nsAutoPtr<mozilla::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);
|
||||
}
|
||||
|
||||
|
||||
if (CC_IS_AUDIO(mcap_id)) {
|
||||
mozilla::AudioCodecConfig *config_raw;
|
||||
config_raw = new mozilla::AudioCodecConfig(
|
||||
|
|
|
@ -42,9 +42,6 @@
|
|||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
#include "webrtc/modules/interface/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
|
@ -78,35 +75,41 @@ nsresult MediaPipeline::Init_s() {
|
|||
conduit_->AttachTransport(transport_);
|
||||
|
||||
nsresult res;
|
||||
MOZ_ASSERT(rtp_.transport_);
|
||||
MOZ_ASSERT(rtcp_.transport_);
|
||||
res = ConnectTransport_s(rtp_);
|
||||
if (NS_FAILED(res)) {
|
||||
return res;
|
||||
}
|
||||
MOZ_ASSERT(rtp_transport_);
|
||||
// Look to see if the transport is ready
|
||||
rtp_transport_->SignalStateChange.connect(this,
|
||||
&MediaPipeline::StateChange);
|
||||
|
||||
if (rtcp_.transport_ != rtp_.transport_) {
|
||||
res = ConnectTransport_s(rtcp_);
|
||||
if (rtp_transport_->state() == TransportLayer::TS_OPEN) {
|
||||
res = TransportReady_s(rtp_transport_);
|
||||
if (NS_FAILED(res)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res="
|
||||
<< static_cast<uint32_t>(res) << " in " << __FUNCTION__);
|
||||
return res;
|
||||
}
|
||||
} else if (rtp_transport_->state() == TransportLayer::TS_ERROR) {
|
||||
MOZ_MTLOG(ML_ERROR, "RTP transport is already in error state");
|
||||
TransportFailed_s(rtp_transport_);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (possible_bundle_rtp_) {
|
||||
MOZ_ASSERT(possible_bundle_rtcp_);
|
||||
MOZ_ASSERT(possible_bundle_rtp_->transport_);
|
||||
MOZ_ASSERT(possible_bundle_rtcp_->transport_);
|
||||
// If rtcp_transport_ is the same as rtp_transport_ then we are muxing.
|
||||
// Otherwise, set it up separately.
|
||||
if (rtcp_transport_ != rtp_transport_) {
|
||||
rtcp_transport_->SignalStateChange.connect(this,
|
||||
&MediaPipeline::StateChange);
|
||||
|
||||
res = ConnectTransport_s(*possible_bundle_rtp_);
|
||||
if (NS_FAILED(res)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (possible_bundle_rtcp_->transport_ != possible_bundle_rtp_->transport_) {
|
||||
res = ConnectTransport_s(*possible_bundle_rtcp_);
|
||||
if (rtcp_transport_->state() == TransportLayer::TS_OPEN) {
|
||||
res = TransportReady_s(rtcp_transport_);
|
||||
if (NS_FAILED(res)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res="
|
||||
<< static_cast<uint32_t>(res) << " in " << __FUNCTION__);
|
||||
return res;
|
||||
}
|
||||
} else if (rtcp_transport_->state() == TransportLayer::TS_ERROR) {
|
||||
MOZ_MTLOG(ML_ERROR, "RTCP transport is already in error state");
|
||||
TransportFailed_s(rtcp_transport_);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -123,72 +126,55 @@ void MediaPipeline::ShutdownTransport_s() {
|
|||
|
||||
disconnect_all();
|
||||
transport_->Detach();
|
||||
rtp_.transport_ = nullptr;
|
||||
rtcp_.transport_ = nullptr;
|
||||
possible_bundle_rtp_ = nullptr;
|
||||
possible_bundle_rtcp_ = nullptr;
|
||||
rtp_transport_ = nullptr;
|
||||
rtcp_transport_ = nullptr;
|
||||
}
|
||||
|
||||
void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) {
|
||||
TransportInfo* info = GetTransportInfo_s(flow);
|
||||
MOZ_ASSERT(info);
|
||||
// If rtcp_transport_ is the same as rtp_transport_ then we are muxing.
|
||||
// So the only flow should be the RTP flow.
|
||||
if (rtcp_transport_ == rtp_transport_) {
|
||||
MOZ_ASSERT(flow == rtp_transport_);
|
||||
}
|
||||
|
||||
if (state == TransportLayer::TS_OPEN) {
|
||||
MOZ_MTLOG(ML_INFO, "Flow is ready");
|
||||
TransportReady_s(*info);
|
||||
TransportReady_s(flow);
|
||||
} else if (state == TransportLayer::TS_CLOSED ||
|
||||
state == TransportLayer::TS_ERROR) {
|
||||
TransportFailed_s(*info);
|
||||
TransportFailed_s(flow);
|
||||
}
|
||||
}
|
||||
|
||||
static bool MakeRtpTypeToStringArray(const char** array) {
|
||||
static const char* RTP_str = "RTP";
|
||||
static const char* RTCP_str = "RTCP";
|
||||
static const char* MUX_str = "RTP/RTCP mux";
|
||||
array[MediaPipeline::RTP] = RTP_str;
|
||||
array[MediaPipeline::RTCP] = RTCP_str;
|
||||
array[MediaPipeline::MUX] = MUX_str;
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* ToString(MediaPipeline::RtpType type) {
|
||||
static const char* array[(int)MediaPipeline::MAX_RTP_TYPE] = {nullptr};
|
||||
// Dummy variable to cause init to happen only on first call
|
||||
static bool dummy = MakeRtpTypeToStringArray(array);
|
||||
(void)dummy;
|
||||
return array[type];
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::TransportReady_s(TransportInfo &info) {
|
||||
nsresult MediaPipeline::TransportReady_s(TransportFlow *flow) {
|
||||
MOZ_ASSERT(!description_.empty());
|
||||
bool rtcp = !(flow == rtp_transport_);
|
||||
State *state = rtcp ? &rtcp_state_ : &rtp_state_;
|
||||
|
||||
// TODO(ekr@rtfm.com): implement some kind of notification on
|
||||
// failure. bug 852665.
|
||||
if (info.state_ != MP_CONNECTING) {
|
||||
if (*state != MP_CONNECTING) {
|
||||
MOZ_MTLOG(ML_ERROR, "Transport ready for flow in wrong state:" <<
|
||||
description_ << ": " << ToString(info.type_));
|
||||
description_ << ": " << (rtcp ? "rtcp" : "rtp"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult res;
|
||||
|
||||
MOZ_MTLOG(ML_INFO, "Transport ready for pipeline " <<
|
||||
static_cast<void *>(this) << " flow " << description_ << ": " <<
|
||||
ToString(info.type_));
|
||||
|
||||
// TODO(bcampen@mozilla.com): Should we disconnect from the flow on failure?
|
||||
nsresult res;
|
||||
(rtcp ? "rtcp" : "rtp"));
|
||||
|
||||
// Now instantiate the SRTP objects
|
||||
TransportLayerDtls *dtls = static_cast<TransportLayerDtls *>(
|
||||
info.transport_->GetLayer(TransportLayerDtls::ID()));
|
||||
flow->GetLayer(TransportLayerDtls::ID()));
|
||||
MOZ_ASSERT(dtls); // DTLS is mandatory
|
||||
|
||||
uint16_t cipher_suite;
|
||||
res = dtls->GetSrtpCipher(&cipher_suite);
|
||||
if (NS_FAILED(res)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to negotiate DTLS-SRTP. This is an error");
|
||||
info.state_ = MP_CLOSED;
|
||||
UpdateRtcpMuxState(info);
|
||||
*state = MP_CLOSED;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -198,8 +184,7 @@ nsresult MediaPipeline::TransportReady_s(TransportInfo &info) {
|
|||
srtp_block, sizeof(srtp_block));
|
||||
if (NS_FAILED(res)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Failed to compute DTLS-SRTP keys. This is an error");
|
||||
info.state_ = MP_CLOSED;
|
||||
UpdateRtcpMuxState(info);
|
||||
*state = MP_CLOSED;
|
||||
MOZ_CRASH(); // TODO: Remove once we have enough field experience to
|
||||
// know it doesn't happen. bug 798797. Note that the
|
||||
// code after this never executes.
|
||||
|
@ -233,63 +218,88 @@ nsresult MediaPipeline::TransportReady_s(TransportInfo &info) {
|
|||
read_key = client_write_key;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!info.send_srtp_ && !info.recv_srtp_);
|
||||
info.send_srtp_ = SrtpFlow::Create(cipher_suite, false, write_key,
|
||||
SRTP_TOTAL_KEY_LENGTH);
|
||||
info.recv_srtp_ = SrtpFlow::Create(cipher_suite, true, read_key,
|
||||
SRTP_TOTAL_KEY_LENGTH);
|
||||
if (!info.send_srtp_ || !info.recv_srtp_) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow for "
|
||||
<< ToString(info.type_));
|
||||
info.state_ = MP_CLOSED;
|
||||
UpdateRtcpMuxState(info);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (!rtcp) {
|
||||
// RTP side
|
||||
MOZ_ASSERT(!rtp_send_srtp_ && !rtp_recv_srtp_);
|
||||
rtp_send_srtp_ = SrtpFlow::Create(cipher_suite, false,
|
||||
write_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
rtp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true,
|
||||
read_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
if (!rtp_send_srtp_ || !rtp_recv_srtp_) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow for RTCP");
|
||||
*state = MP_CLOSED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (direction_ == RECEIVE) {
|
||||
// The TRANSMIT pipeline does not process _any_ RTCP. This is the RECEIVE
|
||||
// pipeline's job, even for receiver reports.
|
||||
MOZ_MTLOG(ML_INFO, "Listening for " << ToString(info.type_)
|
||||
<< " packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
// Start listening
|
||||
// If rtcp_transport_ is the same as rtp_transport_ then we are muxing
|
||||
if (rtcp_transport_ == rtp_transport_) {
|
||||
MOZ_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_);
|
||||
rtcp_send_srtp_ = rtp_send_srtp_;
|
||||
rtcp_recv_srtp_ = rtp_recv_srtp_;
|
||||
|
||||
switch (info.type_) {
|
||||
case RTP:
|
||||
dtls->downward()->SignalPacketReceived.connect(
|
||||
this,
|
||||
&MediaPipeline::RtpPacketReceived);
|
||||
break;
|
||||
case RTCP:
|
||||
dtls->downward()->SignalPacketReceived.connect(
|
||||
this,
|
||||
&MediaPipeline::RtcpPacketReceived);
|
||||
break;
|
||||
case MUX:
|
||||
dtls->downward()->SignalPacketReceived.connect(
|
||||
this,
|
||||
&MediaPipeline::PacketReceived);
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
MOZ_MTLOG(ML_INFO, "Listening for packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
|
||||
dtls->downward()->SignalPacketReceived.connect(this,
|
||||
&MediaPipeline::
|
||||
PacketReceived);
|
||||
rtcp_state_ = MP_OPEN;
|
||||
} else {
|
||||
MOZ_MTLOG(ML_INFO, "Listening for RTP packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
|
||||
dtls->downward()->SignalPacketReceived.connect(this,
|
||||
&MediaPipeline::
|
||||
RtpPacketReceived);
|
||||
}
|
||||
}
|
||||
else {
|
||||
MOZ_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_);
|
||||
rtcp_send_srtp_ = SrtpFlow::Create(cipher_suite, false,
|
||||
write_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
rtcp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true,
|
||||
read_key, SRTP_TOTAL_KEY_LENGTH);
|
||||
if (!rtcp_send_srtp_ || !rtcp_recv_srtp_) {
|
||||
MOZ_MTLOG(ML_ERROR, "Couldn't create SRTCP flow for RTCP");
|
||||
*state = MP_CLOSED;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
info.state_ = MP_OPEN;
|
||||
UpdateRtcpMuxState(info);
|
||||
MOZ_MTLOG(ML_DEBUG, "Listening for RTCP packets received on " <<
|
||||
static_cast<void *>(dtls->downward()));
|
||||
|
||||
// Start listening
|
||||
dtls->downward()->SignalPacketReceived.connect(this,
|
||||
&MediaPipeline::
|
||||
RtcpPacketReceived);
|
||||
}
|
||||
|
||||
*state = MP_OPEN;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::TransportFailed_s(TransportInfo &info) {
|
||||
nsresult MediaPipeline::TransportFailed_s(TransportFlow *flow) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
bool rtcp = !(flow == rtp_transport_);
|
||||
|
||||
info.state_ = MP_CLOSED;
|
||||
UpdateRtcpMuxState(info);
|
||||
State *state = rtcp ? &rtcp_state_ : &rtp_state_;
|
||||
|
||||
MOZ_MTLOG(ML_INFO, "Transport closed for flow " << ToString(info.type_));
|
||||
*state = MP_CLOSED;
|
||||
|
||||
// If rtcp_transport_ is the same as rtp_transport_ then we are muxing
|
||||
if(rtcp_transport_ == rtp_transport_) {
|
||||
MOZ_ASSERT(state != &rtcp_state_);
|
||||
rtcp_state_ = MP_CLOSED;
|
||||
}
|
||||
|
||||
|
||||
MOZ_MTLOG(ML_INFO, "Transport closed for flow " << (rtcp ? "rtcp" : "rtp"));
|
||||
|
||||
NS_WARNING(
|
||||
"MediaPipeline Transport failed. This is not properly cleaned up yet");
|
||||
|
||||
|
||||
// TODO(ekr@rtfm.com): SECURITY: Figure out how to clean up if the
|
||||
// connection was good and now it is bad.
|
||||
// TODO(ekr@rtfm.com): Report up so that the PC knows we
|
||||
|
@ -298,24 +308,6 @@ nsresult MediaPipeline::TransportFailed_s(TransportInfo &info) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void MediaPipeline::UpdateRtcpMuxState(TransportInfo &info) {
|
||||
if (info.type_ == MUX) {
|
||||
if (info.transport_ == rtcp_.transport_) {
|
||||
rtcp_.state_ = info.state_;
|
||||
if (!rtcp_.send_srtp_) {
|
||||
rtcp_.send_srtp_ = info.send_srtp_;
|
||||
rtcp_.recv_srtp_ = info.recv_srtp_;
|
||||
}
|
||||
} else if (possible_bundle_rtcp_ &&
|
||||
info.transport_ == possible_bundle_rtcp_->transport_) {
|
||||
possible_bundle_rtcp_->state_ = info.state_;
|
||||
if (!possible_bundle_rtcp_->send_srtp_) {
|
||||
possible_bundle_rtcp_->send_srtp_ = info.send_srtp_;
|
||||
possible_bundle_rtcp_->recv_srtp_ = info.recv_srtp_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::SendPacket(TransportFlow *flow, const void *data,
|
||||
int len) {
|
||||
|
@ -348,7 +340,7 @@ void MediaPipeline::increment_rtp_packets_sent(int32_t bytes) {
|
|||
if (!(rtp_packets_sent_ % 100)) {
|
||||
MOZ_MTLOG(ML_INFO, "RTP sent packet count for " << description_
|
||||
<< " Pipeline " << static_cast<void *>(this)
|
||||
<< " Flow : " << static_cast<void *>(rtp_.transport_)
|
||||
<< " Flow : " << static_cast<void *>(rtp_transport_)
|
||||
<< ": " << rtp_packets_sent_
|
||||
<< " (" << rtp_bytes_sent_ << " bytes)");
|
||||
}
|
||||
|
@ -359,7 +351,7 @@ void MediaPipeline::increment_rtcp_packets_sent() {
|
|||
if (!(rtcp_packets_sent_ % 100)) {
|
||||
MOZ_MTLOG(ML_INFO, "RTCP sent packet count for " << description_
|
||||
<< " Pipeline " << static_cast<void *>(this)
|
||||
<< " Flow : " << static_cast<void *>(rtcp_.transport_)
|
||||
<< " Flow : " << static_cast<void *>(rtcp_transport_)
|
||||
<< ": " << rtcp_packets_sent_);
|
||||
}
|
||||
}
|
||||
|
@ -370,7 +362,7 @@ void MediaPipeline::increment_rtp_packets_received(int32_t bytes) {
|
|||
if (!(rtp_packets_received_ % 100)) {
|
||||
MOZ_MTLOG(ML_INFO, "RTP received packet count for " << description_
|
||||
<< " Pipeline " << static_cast<void *>(this)
|
||||
<< " Flow : " << static_cast<void *>(rtp_.transport_)
|
||||
<< " Flow : " << static_cast<void *>(rtp_transport_)
|
||||
<< ": " << rtp_packets_received_
|
||||
<< " (" << rtp_bytes_received_ << " bytes)");
|
||||
}
|
||||
|
@ -381,7 +373,7 @@ void MediaPipeline::increment_rtcp_packets_received() {
|
|||
if (!(rtcp_packets_received_ % 100)) {
|
||||
MOZ_MTLOG(ML_INFO, "RTCP received packet count for " << description_
|
||||
<< " Pipeline " << static_cast<void *>(this)
|
||||
<< " Flow : " << static_cast<void *>(rtcp_.transport_)
|
||||
<< " Flow : " << static_cast<void *>(rtcp_transport_)
|
||||
<< ": " << rtcp_packets_received_);
|
||||
}
|
||||
}
|
||||
|
@ -399,84 +391,34 @@ void MediaPipeline::RtpPacketReceived(TransportLayer *layer,
|
|||
return;
|
||||
}
|
||||
|
||||
TransportInfo* info = &rtp_;
|
||||
|
||||
if (possible_bundle_rtp_ &&
|
||||
possible_bundle_rtp_->transport_->Contains(layer)) {
|
||||
// Received this on our possible bundle transport. Override info.
|
||||
info = possible_bundle_rtp_;
|
||||
}
|
||||
|
||||
// TODO(bcampen@mozilla.com): Can either of these actually happen? If not,
|
||||
// the info variable can be removed, and this function gets simpler.
|
||||
if (info->state_ != MP_OPEN) {
|
||||
if (rtp_state_ != MP_OPEN) {
|
||||
MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; pipeline not open");
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->transport_->state() != TransportLayer::TS_OPEN) {
|
||||
if (rtp_transport_->state() != TransportLayer::TS_OPEN) {
|
||||
MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; transport not open");
|
||||
return;
|
||||
}
|
||||
|
||||
// This should never happen.
|
||||
MOZ_ASSERT(info->recv_srtp_);
|
||||
MOZ_ASSERT(rtp_recv_srtp_); // This should never happen
|
||||
|
||||
if (direction_ == TRANSMIT) {
|
||||
// Discard any media that is being transmitted to us
|
||||
// This will be unnecessary when we have SSRC filtering.
|
||||
return;
|
||||
}
|
||||
|
||||
if (possible_bundle_rtp_ && (info == &rtp_)) {
|
||||
// We were not sure we would be using rtp_ or possible_bundle_rtp_, but we
|
||||
// have just received traffic that clears this up.
|
||||
// Don't let our filter prevent us from noticing this, if the filter is
|
||||
// incomplete (ie; no SSRCs in remote SDP, or no remote SDP at all).
|
||||
SetUsingBundle_s(false);
|
||||
MOZ_MTLOG(ML_INFO, "Ruled out the possibility that we're receiving bundle "
|
||||
"for " << description_);
|
||||
// TODO(bcampen@mozilla.com): Might be nice to detect when every
|
||||
// MediaPipeline but the master has determined that it isn't doing bundle,
|
||||
// since that means the master isn't doing bundle either. We could maybe
|
||||
// do this by putting some refcounted dummy variable in the filters, and
|
||||
// checking the value of the refcount. It is not clear whether this is
|
||||
// going to be useful in practice.
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out everything but RTP/RTCP
|
||||
if (data[0] < 128 || data[0] > 191) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter_) {
|
||||
webrtc::RTPHeader header;
|
||||
if (!rtp_parser_->Parse(data, len, &header) ||
|
||||
!filter_->Filter(header)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (possible_bundle_rtp_) {
|
||||
// Just got traffic that passed our filter on the potential bundle
|
||||
// transport. Must be doing bundle.
|
||||
SetUsingBundle_s(true);
|
||||
MOZ_MTLOG(ML_INFO, "Confirmed the possibility that we're receiving bundle");
|
||||
}
|
||||
|
||||
// Everything is decided now; just use rtp_
|
||||
MOZ_ASSERT(!possible_bundle_rtp_);
|
||||
MOZ_ASSERT(!possible_bundle_rtcp_);
|
||||
// TODO(ekr@rtfm.com): filter for DTLS here and in RtcpPacketReceived
|
||||
// TODO(ekr@rtfm.com): filter on SSRC for bundle
|
||||
|
||||
// Make a copy rather than cast away constness
|
||||
ScopedDeletePtr<unsigned char> inner_data(
|
||||
new unsigned char[len]);
|
||||
memcpy(inner_data, data, len);
|
||||
int out_len = 0;
|
||||
nsresult res = rtp_.recv_srtp_->UnprotectRtp(inner_data,
|
||||
len, len, &out_len);
|
||||
nsresult res = rtp_recv_srtp_->UnprotectRtp(inner_data,
|
||||
len, len, &out_len);
|
||||
if (!NS_SUCCEEDED(res)) {
|
||||
char tmp[16];
|
||||
|
||||
|
@ -509,58 +451,25 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer,
|
|||
return;
|
||||
}
|
||||
|
||||
TransportInfo* info = &rtcp_;
|
||||
if (possible_bundle_rtcp_ &&
|
||||
possible_bundle_rtcp_->transport_->Contains(layer)) {
|
||||
info = possible_bundle_rtcp_;
|
||||
}
|
||||
|
||||
if (info->state_ != MP_OPEN) {
|
||||
if (rtcp_state_ != MP_OPEN) {
|
||||
MOZ_MTLOG(ML_DEBUG, "Discarding incoming packet; pipeline not open");
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->transport_->state() != TransportLayer::TS_OPEN) {
|
||||
if (rtcp_transport_->state() != TransportLayer::TS_OPEN) {
|
||||
MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; transport not open");
|
||||
return;
|
||||
}
|
||||
|
||||
if (possible_bundle_rtp_ && (info == &rtcp_)) {
|
||||
// We have offered bundle, and received our first packet on a non-bundle
|
||||
// address. We are definitely not using the bundle address.
|
||||
SetUsingBundle_s(false);
|
||||
}
|
||||
|
||||
if (!len) {
|
||||
if (direction_ == RECEIVE) {
|
||||
// Discard any RTCP that is being transmitted to us
|
||||
// This will be unnecessary when we have SSRC filtering.
|
||||
return;
|
||||
}
|
||||
|
||||
// Filter out everything but RTP/RTCP
|
||||
if (data[0] < 128 || data[0] > 191) {
|
||||
return;
|
||||
}
|
||||
|
||||
MediaPipelineFilter::Result filter_result = MediaPipelineFilter::PASS;
|
||||
if (filter_) {
|
||||
filter_result = filter_->FilterRTCP(data, len);
|
||||
if (filter_result == MediaPipelineFilter::FAIL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter_result == MediaPipelineFilter::PASS && possible_bundle_rtp_) {
|
||||
// Just got traffic that passed our filter on the potential bundle
|
||||
// transport. Must be doing bundle.
|
||||
SetUsingBundle_s(true);
|
||||
}
|
||||
|
||||
// We continue using info here, since it is possible that the filter did not
|
||||
// support the payload type (ie; returned MediaPipelineFilter::UNSUPPORTED).
|
||||
// In this case, we just let it pass, and hope the webrtc.org code does
|
||||
// something sane.
|
||||
increment_rtcp_packets_received();
|
||||
|
||||
MOZ_ASSERT(info->recv_srtp_); // This should never happen
|
||||
MOZ_ASSERT(rtcp_recv_srtp_); // This should never happen
|
||||
|
||||
// Make a copy rather than cast away constness
|
||||
ScopedDeletePtr<unsigned char> inner_data(
|
||||
|
@ -568,10 +477,7 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer,
|
|||
memcpy(inner_data, data, len);
|
||||
int out_len;
|
||||
|
||||
nsresult res = info->recv_srtp_->UnprotectRtcp(inner_data,
|
||||
len,
|
||||
len,
|
||||
&out_len);
|
||||
nsresult res = rtcp_recv_srtp_->UnprotectRtcp(inner_data, len, len, &out_len);
|
||||
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return;
|
||||
|
@ -657,14 +563,11 @@ nsresult MediaPipelineTransmit::Init() {
|
|||
return MediaPipeline::Init();
|
||||
}
|
||||
|
||||
nsresult MediaPipelineTransmit::TransportReady_s(TransportInfo &info) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
nsresult MediaPipelineTransmit::TransportReady_s(TransportFlow *flow) {
|
||||
// Call base ready function.
|
||||
MediaPipeline::TransportReady_s(info);
|
||||
MediaPipeline::TransportReady_s(flow);
|
||||
|
||||
// Should not be set for a transmitter
|
||||
MOZ_ASSERT(!possible_bundle_rtp_);
|
||||
if (&info == &rtp_) {
|
||||
if (flow == rtp_transport_) {
|
||||
// TODO(ekr@rtfm.com): Move onto MSG thread.
|
||||
listener_->SetActive(true);
|
||||
}
|
||||
|
@ -672,121 +575,6 @@ nsresult MediaPipelineTransmit::TransportReady_s(TransportInfo &info) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void MediaPipeline::DisconnectTransport_s(TransportInfo &info) {
|
||||
MOZ_ASSERT(info.transport_);
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
info.transport_->SignalStateChange.disconnect(this);
|
||||
// We do this even if we're a transmitter, since we are still possibly
|
||||
// registered to receive RTCP.
|
||||
TransportLayerDtls *dtls = static_cast<TransportLayerDtls *>(
|
||||
info.transport_->GetLayer(TransportLayerDtls::ID()));
|
||||
MOZ_ASSERT(dtls); // DTLS is mandatory
|
||||
MOZ_ASSERT(dtls->downward());
|
||||
dtls->downward()->SignalPacketReceived.disconnect(this);
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::ConnectTransport_s(TransportInfo &info) {
|
||||
MOZ_ASSERT(info.transport_);
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
|
||||
// Look to see if the transport is ready
|
||||
if (info.transport_->state() == TransportLayer::TS_OPEN) {
|
||||
nsresult res = TransportReady_s(info);
|
||||
if (NS_FAILED(res)) {
|
||||
MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res="
|
||||
<< static_cast<uint32_t>(res) << " in " << __FUNCTION__);
|
||||
return res;
|
||||
}
|
||||
} else if (info.transport_->state() == TransportLayer::TS_ERROR) {
|
||||
MOZ_MTLOG(ML_ERROR, ToString(info.type_)
|
||||
<< "transport is already in error state");
|
||||
TransportFailed_s(info);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
info.transport_->SignalStateChange.connect(this,
|
||||
&MediaPipeline::StateChange);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MediaPipeline::TransportInfo* MediaPipeline::GetTransportInfo_s(
|
||||
TransportFlow *flow) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
if (flow == rtp_.transport_) {
|
||||
return &rtp_;
|
||||
}
|
||||
|
||||
if (flow == rtcp_.transport_) {
|
||||
return &rtcp_;
|
||||
}
|
||||
|
||||
if (possible_bundle_rtp_) {
|
||||
if (flow == possible_bundle_rtp_->transport_) {
|
||||
return possible_bundle_rtp_;
|
||||
}
|
||||
|
||||
if (flow == possible_bundle_rtcp_->transport_) {
|
||||
return possible_bundle_rtcp_;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MediaPipeline::SetUsingBundle_s(bool decision) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
// Note: This can be called either because of events on the STS thread, or
|
||||
// by events on the main thread (ie; receiving a remote description). It is
|
||||
// best to be careful of races here, so don't assume that transports are open.
|
||||
if (!possible_bundle_rtp_) {
|
||||
if (!decision) {
|
||||
// This can happen on the master pipeline.
|
||||
filter_ = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (direction_ == RECEIVE) {
|
||||
if (decision) {
|
||||
MOZ_MTLOG(ML_INFO, "Non-master pipeline confirmed bundle for "
|
||||
<< description_);
|
||||
// We're doing bundle. Release the unused flows, and copy the ones we
|
||||
// are using into the less wishy-washy members.
|
||||
DisconnectTransport_s(rtp_);
|
||||
DisconnectTransport_s(rtcp_);
|
||||
rtp_ = *possible_bundle_rtp_;
|
||||
rtcp_ = *possible_bundle_rtcp_;
|
||||
} else {
|
||||
MOZ_MTLOG(ML_INFO, "Non-master pipeline confirmed no bundle for "
|
||||
<< description_);
|
||||
// We are not doing bundle
|
||||
DisconnectTransport_s(*possible_bundle_rtp_);
|
||||
DisconnectTransport_s(*possible_bundle_rtcp_);
|
||||
filter_ = nullptr;
|
||||
}
|
||||
|
||||
// We are no longer in an ambiguous state.
|
||||
possible_bundle_rtp_ = nullptr;
|
||||
possible_bundle_rtcp_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void MediaPipeline::UpdateFilterFromRemoteDescription_s(
|
||||
nsAutoPtr<MediaPipelineFilter> filter) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
// This is only supposed to relax the filter. Relaxing a missing filter is
|
||||
// not possible.
|
||||
MOZ_ASSERT(filter_);
|
||||
|
||||
if (!filter) {
|
||||
filter_ = nullptr;
|
||||
} else {
|
||||
filter_->IncorporateRemoteDescription(*filter);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtpPacket(
|
||||
const void *data, int len) {
|
||||
|
||||
|
@ -805,17 +593,16 @@ nsresult MediaPipeline::PipelineTransport::SendRtpPacket(
|
|||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtpPacket_s(
|
||||
nsAutoPtr<DataBuffer> data) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
if (!pipeline_)
|
||||
return NS_OK; // Detached
|
||||
|
||||
if (!pipeline_->rtp_.send_srtp_) {
|
||||
if (!pipeline_->rtp_send_srtp_) {
|
||||
MOZ_MTLOG(ML_DEBUG, "Couldn't write RTP packet; SRTP not set up yet");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pipeline_->rtp_.transport_);
|
||||
NS_ENSURE_TRUE(pipeline_->rtp_.transport_, NS_ERROR_NULL_POINTER);
|
||||
MOZ_ASSERT(pipeline_->rtp_transport_);
|
||||
NS_ENSURE_TRUE(pipeline_->rtp_transport_, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// libsrtp enciphers in place, so we need a new, big enough
|
||||
// buffer.
|
||||
|
@ -827,15 +614,15 @@ nsresult MediaPipeline::PipelineTransport::SendRtpPacket_s(
|
|||
memcpy(inner_data, data->data(), data->len());
|
||||
|
||||
int out_len;
|
||||
nsresult res = pipeline_->rtp_.send_srtp_->ProtectRtp(inner_data,
|
||||
data->len(),
|
||||
max_len,
|
||||
&out_len);
|
||||
nsresult res = pipeline_->rtp_send_srtp_->ProtectRtp(inner_data,
|
||||
data->len(),
|
||||
max_len,
|
||||
&out_len);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
pipeline_->increment_rtp_packets_sent(out_len);
|
||||
return pipeline_->SendPacket(pipeline_->rtp_.transport_, inner_data,
|
||||
return pipeline_->SendPacket(pipeline_->rtp_transport_, inner_data,
|
||||
out_len);
|
||||
}
|
||||
|
||||
|
@ -857,17 +644,16 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket(
|
|||
|
||||
nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s(
|
||||
nsAutoPtr<DataBuffer> data) {
|
||||
ASSERT_ON_THREAD(sts_thread_);
|
||||
if (!pipeline_)
|
||||
return NS_OK; // Detached
|
||||
|
||||
if (!pipeline_->rtcp_.send_srtp_) {
|
||||
if (!pipeline_->rtcp_send_srtp_) {
|
||||
MOZ_MTLOG(ML_DEBUG, "Couldn't write RTCP packet; SRTCP not set up yet");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(pipeline_->rtcp_.transport_);
|
||||
NS_ENSURE_TRUE(pipeline_->rtcp_.transport_, NS_ERROR_NULL_POINTER);
|
||||
MOZ_ASSERT(pipeline_->rtcp_transport_);
|
||||
NS_ENSURE_TRUE(pipeline_->rtcp_transport_, NS_ERROR_NULL_POINTER);
|
||||
|
||||
// libsrtp enciphers in place, so we need a new, big enough
|
||||
// buffer.
|
||||
|
@ -879,16 +665,15 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s(
|
|||
memcpy(inner_data, data->data(), data->len());
|
||||
|
||||
int out_len;
|
||||
nsresult res = pipeline_->rtcp_.send_srtp_->ProtectRtcp(inner_data,
|
||||
data->len(),
|
||||
max_len,
|
||||
&out_len);
|
||||
|
||||
nsresult res = pipeline_->rtcp_send_srtp_->ProtectRtcp(inner_data,
|
||||
data->len(),
|
||||
max_len,
|
||||
&out_len);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
|
||||
pipeline_->increment_rtcp_packets_sent();
|
||||
return pipeline_->SendPacket(pipeline_->rtcp_.transport_, inner_data,
|
||||
return pipeline_->SendPacket(pipeline_->rtcp_transport_, inner_data,
|
||||
out_len);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include "VideoUtils.h"
|
||||
#endif
|
||||
#include "MediaConduitInterface.h"
|
||||
#include "MediaPipelineFilter.h"
|
||||
#include "AudioSegment.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "SrtpFlow.h"
|
||||
|
@ -30,8 +29,6 @@
|
|||
#include "VideoSegment.h"
|
||||
#endif
|
||||
|
||||
#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// A class that represents the pipeline of audio and video
|
||||
|
@ -83,11 +80,16 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
track_id_(track_id),
|
||||
level_(level),
|
||||
conduit_(conduit),
|
||||
rtp_(rtp_transport, rtcp_transport ? RTP : MUX),
|
||||
rtcp_(rtcp_transport ? rtcp_transport : rtp_transport,
|
||||
rtcp_transport ? RTCP : MUX),
|
||||
rtp_transport_(rtp_transport),
|
||||
rtp_state_(MP_CONNECTING),
|
||||
rtcp_transport_(rtcp_transport),
|
||||
rtcp_state_(MP_CONNECTING),
|
||||
main_thread_(main_thread),
|
||||
sts_thread_(sts_thread),
|
||||
rtp_send_srtp_(),
|
||||
rtcp_send_srtp_(),
|
||||
rtp_recv_srtp_(),
|
||||
rtcp_recv_srtp_(),
|
||||
rtp_packets_sent_(0),
|
||||
rtcp_packets_sent_(0),
|
||||
rtp_packets_received_(0),
|
||||
|
@ -99,8 +101,11 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
// To indicate rtcp-mux rtcp_transport should be nullptr.
|
||||
// Therefore it's an error to send in the same flow for
|
||||
// both rtp and rtcp.
|
||||
MOZ_ASSERT(rtp_transport != rtcp_transport);
|
||||
MOZ_ASSERT(rtp_transport_ != rtcp_transport_);
|
||||
|
||||
if (!rtcp_transport_) {
|
||||
rtcp_transport_ = rtp_transport;
|
||||
}
|
||||
// PipelineTransport() will access this->sts_thread_; moved here for safety
|
||||
transport_ = new PipelineTransport(this);
|
||||
}
|
||||
|
@ -121,22 +126,12 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
|
||||
virtual nsresult Init();
|
||||
|
||||
// When we have offered bundle, the MediaPipelines are created in an
|
||||
// indeterminate state; we do not know whether the answerer will take us
|
||||
// up on our offer. In the meantime, we need to behave in a manner that
|
||||
// errs on the side of packet loss when it is unclear whether an arriving
|
||||
// packet is meant for us. We want to get out of this indeterminate state
|
||||
// ASAP, which is what this function can be used for.
|
||||
void SetUsingBundle_s(bool decision);
|
||||
void UpdateFilterFromRemoteDescription_s(
|
||||
nsAutoPtr<MediaPipelineFilter> filter);
|
||||
|
||||
virtual Direction direction() const { return direction_; }
|
||||
virtual TrackID trackid() const { return track_id_; }
|
||||
virtual int level() const { return level_; }
|
||||
|
||||
bool IsDoingRtcpMux() const {
|
||||
return (rtp_.type_ == MUX);
|
||||
return (rtp_transport_ == rtcp_transport_);
|
||||
}
|
||||
|
||||
int32_t rtp_packets_sent() const { return rtp_packets_sent_; }
|
||||
|
@ -151,13 +146,6 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
// Thread counting
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPipeline)
|
||||
|
||||
typedef enum {
|
||||
RTP,
|
||||
RTCP,
|
||||
MUX,
|
||||
MAX_RTP_TYPE
|
||||
} RtpType;
|
||||
|
||||
protected:
|
||||
virtual void DetachMediaStream() {}
|
||||
|
||||
|
@ -165,7 +153,7 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
class PipelineTransport : public TransportInterface {
|
||||
public:
|
||||
// Implement the TransportInterface functions
|
||||
explicit PipelineTransport(MediaPipeline *pipeline)
|
||||
PipelineTransport(MediaPipeline *pipeline)
|
||||
: pipeline_(pipeline),
|
||||
sts_thread_(pipeline->sts_thread_) {}
|
||||
|
||||
|
@ -184,40 +172,15 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
};
|
||||
friend class PipelineTransport;
|
||||
|
||||
class TransportInfo {
|
||||
public:
|
||||
TransportInfo(RefPtr<TransportFlow> flow, RtpType type) :
|
||||
transport_(flow),
|
||||
state_(MP_CONNECTING),
|
||||
type_(type) {
|
||||
MOZ_ASSERT(flow);
|
||||
}
|
||||
|
||||
RefPtr<TransportFlow> transport_;
|
||||
State state_;
|
||||
RefPtr<SrtpFlow> send_srtp_;
|
||||
RefPtr<SrtpFlow> recv_srtp_;
|
||||
RtpType type_;
|
||||
};
|
||||
|
||||
// The transport is down
|
||||
virtual nsresult TransportFailed_s(TransportInfo &info);
|
||||
// The transport is ready
|
||||
virtual nsresult TransportReady_s(TransportInfo &info);
|
||||
void UpdateRtcpMuxState(TransportInfo &info);
|
||||
|
||||
// Unhooks from signals
|
||||
void DisconnectTransport_s(TransportInfo &info);
|
||||
nsresult ConnectTransport_s(TransportInfo &info);
|
||||
|
||||
TransportInfo* GetTransportInfo_s(TransportFlow *flow);
|
||||
virtual nsresult TransportFailed_s(TransportFlow *flow); // The transport is down
|
||||
virtual nsresult TransportReady_s(TransportFlow *flow); // The transport is ready
|
||||
|
||||
void increment_rtp_packets_sent(int bytes);
|
||||
void increment_rtcp_packets_sent();
|
||||
void increment_rtp_packets_received(int bytes);
|
||||
void increment_rtcp_packets_received();
|
||||
|
||||
virtual nsresult SendPacket(TransportFlow *flow, const void *data, int len);
|
||||
virtual nsresult SendPacket(TransportFlow *flow, const void* data, int len);
|
||||
|
||||
// Process slots on transports
|
||||
void StateChange(TransportFlow *flow, TransportLayer::State);
|
||||
|
@ -239,18 +202,10 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
// thread. Read on STS thread.
|
||||
|
||||
// The transport objects. Read/written on STS thread.
|
||||
TransportInfo rtp_;
|
||||
TransportInfo rtcp_;
|
||||
// These are for bundle. We have a separate set because when we have offered
|
||||
// bundle, we do not know whether we will receive traffic on the transport
|
||||
// in this pipeline's m-line, or the transport in the "master" m-line for
|
||||
// the bundle. We need to be ready for either. Once this ambiguity is
|
||||
// resolved, the transport we know that we'll be using will be set in
|
||||
// rtp_transport_ and rtcp_transport_, and these will be unset.
|
||||
// TODO(bcampen@mozilla.com): I'm pretty sure this could be leveraged for
|
||||
// re-offer with a new address on an m-line too, with a little work.
|
||||
nsAutoPtr<TransportInfo> possible_bundle_rtp_;
|
||||
nsAutoPtr<TransportInfo> possible_bundle_rtcp_;
|
||||
RefPtr<TransportFlow> rtp_transport_;
|
||||
State rtp_state_;
|
||||
RefPtr<TransportFlow> rtcp_transport_;
|
||||
State rtcp_state_;
|
||||
|
||||
// Pointers to the threads we need. Initialized at creation
|
||||
// and used all over the place.
|
||||
|
@ -261,8 +216,15 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
// destroyed on the STS thread.
|
||||
RefPtr<PipelineTransport> transport_;
|
||||
|
||||
// Only safe to access from STS thread.
|
||||
// Build into TransportInfo?
|
||||
// Used only on STS thread.
|
||||
RefPtr<SrtpFlow> rtp_send_srtp_;
|
||||
RefPtr<SrtpFlow> rtcp_send_srtp_;
|
||||
RefPtr<SrtpFlow> rtp_recv_srtp_;
|
||||
RefPtr<SrtpFlow> rtcp_recv_srtp_;
|
||||
|
||||
// Written only on STS thread. May be read on other
|
||||
// threads but since there is no mutex, the values
|
||||
// will only be approximate.
|
||||
int32_t rtp_packets_sent_;
|
||||
int32_t rtcp_packets_sent_;
|
||||
int32_t rtp_packets_received_;
|
||||
|
@ -274,10 +236,6 @@ class MediaPipeline : public sigslot::has_slots<> {
|
|||
std::string pc_;
|
||||
std::string description_;
|
||||
|
||||
// Written on Init, all following accesses are on the STS thread.
|
||||
nsAutoPtr<MediaPipelineFilter> filter_;
|
||||
nsAutoPtr<webrtc::RtpHeaderParser> rtp_parser_;
|
||||
|
||||
private:
|
||||
nsresult Init_s();
|
||||
|
||||
|
@ -386,7 +344,7 @@ class MediaPipelineTransmit : public MediaPipeline {
|
|||
}
|
||||
|
||||
// Override MediaPipeline::TransportReady.
|
||||
virtual nsresult TransportReady_s(TransportInfo &info);
|
||||
virtual nsresult TransportReady_s(TransportFlow *flow);
|
||||
|
||||
// Separate class to allow ref counting
|
||||
class PipelineListener : public MediaStreamDirectListener {
|
||||
|
@ -487,26 +445,11 @@ class MediaPipelineReceive : public MediaPipeline {
|
|||
int level,
|
||||
RefPtr<MediaSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport,
|
||||
RefPtr<TransportFlow> bundle_rtp_transport,
|
||||
RefPtr<TransportFlow> bundle_rtcp_transport,
|
||||
nsAutoPtr<MediaPipelineFilter> filter) :
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipeline(pc, RECEIVE, main_thread, sts_thread,
|
||||
stream, track_id, level, conduit, rtp_transport,
|
||||
rtcp_transport),
|
||||
segments_added_(0) {
|
||||
filter_ = filter;
|
||||
rtp_parser_ = webrtc::RtpHeaderParser::Create();
|
||||
if (bundle_rtp_transport) {
|
||||
if (bundle_rtcp_transport) {
|
||||
MOZ_ASSERT(bundle_rtp_transport != bundle_rtcp_transport);
|
||||
possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, RTP);
|
||||
possible_bundle_rtcp_ = new TransportInfo(bundle_rtcp_transport, RTCP);
|
||||
} else {
|
||||
possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, MUX);
|
||||
possible_bundle_rtcp_ = new TransportInfo(bundle_rtp_transport, MUX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int segments_added() const { return segments_added_; }
|
||||
|
@ -530,14 +473,10 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive {
|
|||
int level,
|
||||
RefPtr<AudioSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport,
|
||||
RefPtr<TransportFlow> bundle_rtp_transport,
|
||||
RefPtr<TransportFlow> bundle_rtcp_transport,
|
||||
nsAutoPtr<MediaPipelineFilter> filter) :
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipelineReceive(pc, main_thread, sts_thread,
|
||||
stream, track_id, level, conduit, rtp_transport,
|
||||
rtcp_transport, bundle_rtp_transport,
|
||||
bundle_rtcp_transport, filter),
|
||||
rtcp_transport),
|
||||
listener_(new PipelineListener(stream->AsSourceStream(),
|
||||
track_id, conduit)) {
|
||||
}
|
||||
|
@ -597,14 +536,10 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive {
|
|||
int level,
|
||||
RefPtr<VideoSessionConduit> conduit,
|
||||
RefPtr<TransportFlow> rtp_transport,
|
||||
RefPtr<TransportFlow> rtcp_transport,
|
||||
RefPtr<TransportFlow> bundle_rtp_transport,
|
||||
RefPtr<TransportFlow> bundle_rtcp_transport,
|
||||
nsAutoPtr<MediaPipelineFilter> filter) :
|
||||
RefPtr<TransportFlow> rtcp_transport) :
|
||||
MediaPipelineReceive(pc, main_thread, sts_thread,
|
||||
stream, track_id, level, conduit, rtp_transport,
|
||||
rtcp_transport, bundle_rtp_transport,
|
||||
bundle_rtcp_transport, filter),
|
||||
rtcp_transport),
|
||||
renderer_(new PipelineRenderer(MOZ_THIS_IN_INITIALIZER_LIST())),
|
||||
listener_(new PipelineListener(stream->AsSourceStream(), track_id)) {
|
||||
}
|
||||
|
|
|
@ -1327,11 +1327,9 @@ PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector, bool internalStats) {
|
|||
if (temp.get()) {
|
||||
streams.push_back(temp);
|
||||
} else {
|
||||
CSFLogError(logTag, "Failed to get NrIceMediaStream for level %zu "
|
||||
CSFLogError(logTag, "Failed to get NrIceMediaStream for level %u "
|
||||
"in %s: %s",
|
||||
static_cast<size_t>(level),
|
||||
__FUNCTION__,
|
||||
mHandle.c_str());
|
||||
uint32_t(level), __FUNCTION__, mHandle.c_str());
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -396,40 +396,6 @@ PeerConnectionMedia::GetRemoteStream(int aIndex)
|
|||
return mRemoteSourceStreams[aIndex];
|
||||
}
|
||||
|
||||
bool
|
||||
PeerConnectionMedia::SetUsingBundle_m(int level, bool decision)
|
||||
{
|
||||
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|
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CSFLogWarn(logTag, "Could not locate level %d to set bundle flag to %s",
|
||||
static_cast<int>(level),
|
||||
decision ? "true" : "false");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PeerConnectionMedia::UpdateFilterFromRemoteDescription_m(
|
||||
int level,
|
||||
nsAutoPtr<mozilla::MediaPipelineFilter> filter)
|
||||
{
|
||||
ASSERT_ON_THREAD(mMainThread);
|
||||
for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) {
|
||||
if (mRemoteSourceStreams[i]->UpdateFilterFromRemoteDescription_m(level,
|
||||
filter)) {
|
||||
// Found the MediaPipeline for |level|
|
||||
return true;
|
||||
}
|
||||
}
|
||||
CSFLogWarn(logTag, "Could not locate level %d to update filter",
|
||||
static_cast<int>(level));
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PeerConnectionMedia::AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo,
|
||||
int *aIndex)
|
||||
|
@ -537,68 +503,5 @@ RemoteSourceStreamInfo::StorePipeline(int aTrack,
|
|||
mTypes[aTrack] = aIsVideo;
|
||||
}
|
||||
|
||||
RefPtr<MediaPipeline> RemoteSourceStreamInfo::GetPipelineByLevel_m(int level) {
|
||||
ASSERT_ON_THREAD(mParent->GetMainThread());
|
||||
for (auto p = mPipelines.begin(); p != mPipelines.end(); ++p) {
|
||||
if (p->second->level() == level) {
|
||||
return p->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool RemoteSourceStreamInfo::UpdateFilterFromRemoteDescription_m(
|
||||
int aLevel,
|
||||
nsAutoPtr<mozilla::MediaPipelineFilter> aFilter) {
|
||||
ASSERT_ON_THREAD(mParent->GetMainThread());
|
||||
|
||||
if (!mMediaStream) {
|
||||
// Guard against dispatching once we've started teardown, since we don't
|
||||
// want the RefPtr<MediaPipeline> being the last one standing on the call
|
||||
// to MediaPipeline::UpdateFilterFromRemoteDescription_s; it is not safe
|
||||
// to delete a MediaPipeline anywhere other than the main thread.
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<MediaPipeline> pipeline(GetPipelineByLevel_m(aLevel));
|
||||
|
||||
if (pipeline) {
|
||||
RUN_ON_THREAD(mParent->GetSTSThread(),
|
||||
WrapRunnable(
|
||||
pipeline,
|
||||
&MediaPipeline::UpdateFilterFromRemoteDescription_s,
|
||||
aFilter
|
||||
),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RemoteSourceStreamInfo::SetUsingBundle_m(int aLevel, bool decision) {
|
||||
ASSERT_ON_THREAD(mParent->GetMainThread());
|
||||
|
||||
if (!mMediaStream) {
|
||||
// Guard against dispatching once we've started teardown, since we don't
|
||||
// want the RefPtr<MediaPipeline> being the last one standing on the call
|
||||
// to MediaPipeline::SetUsingBundle_s; it is not safe
|
||||
// to delete a MediaPipeline anywhere other than the main thread.
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<MediaPipeline> pipeline(GetPipelineByLevel_m(aLevel));
|
||||
|
||||
if (pipeline) {
|
||||
RUN_ON_THREAD(mParent->GetSTSThread(),
|
||||
WrapRunnable(
|
||||
pipeline,
|
||||
&MediaPipeline::SetUsingBundle_s,
|
||||
decision
|
||||
),
|
||||
NS_DISPATCH_NORMAL);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace sipcc
|
||||
|
|
|
@ -244,11 +244,6 @@ class RemoteSourceStreamInfo : public SourceStreamInfo {
|
|||
void StorePipeline(int aTrack, bool aIsVideo,
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> aPipeline);
|
||||
|
||||
bool UpdateFilterFromRemoteDescription_m(
|
||||
int aLevel,
|
||||
nsAutoPtr<mozilla::MediaPipelineFilter> aFilter);
|
||||
bool SetUsingBundle_m(int aLevel, bool decision);
|
||||
|
||||
void DetachTransport_s();
|
||||
void DetachMedia_m();
|
||||
|
||||
|
@ -257,7 +252,6 @@ class RemoteSourceStreamInfo : public SourceStreamInfo {
|
|||
public:
|
||||
DOMMediaStream::TrackTypeHints mTrackTypeHints;
|
||||
private:
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> GetPipelineByLevel_m(int level);
|
||||
std::map<int, bool> mTypes;
|
||||
};
|
||||
|
||||
|
@ -302,11 +296,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> {
|
|||
}
|
||||
RemoteSourceStreamInfo* GetRemoteStream(int index);
|
||||
|
||||
bool SetUsingBundle_m(int level, bool decision);
|
||||
bool UpdateFilterFromRemoteDescription_m(
|
||||
int level,
|
||||
nsAutoPtr<mozilla::MediaPipelineFilter> filter);
|
||||
|
||||
// Add a remote stream. Returns the index in index
|
||||
nsresult AddRemoteStream(nsRefPtr<RemoteSourceStreamInfo> aInfo, int *aIndex);
|
||||
nsresult AddRemoteStreamHint(int aIndex, bool aIsVideo);
|
||||
|
|
|
@ -114,20 +114,10 @@ class TestAgent {
|
|||
audio_pipeline_() {
|
||||
}
|
||||
|
||||
void ConnectRtpSocket(PRFileDesc *fd, bool client) {
|
||||
ConnectSocket(&audio_rtp_transport_, fd, client);
|
||||
}
|
||||
|
||||
void ConnectRtcpSocket(PRFileDesc *fd, bool client) {
|
||||
ConnectSocket(&audio_rtcp_transport_, fd, client);
|
||||
}
|
||||
|
||||
void ConnectBundleSocket(PRFileDesc *fd, bool client) {
|
||||
ConnectSocket(&bundle_transport_, fd, client);
|
||||
}
|
||||
|
||||
void ConnectSocket(TransportInfo *transport, PRFileDesc *fd, bool client) {
|
||||
void ConnectSocket(PRFileDesc *fd, bool client, bool isRtcp) {
|
||||
nsresult res;
|
||||
TransportInfo *transport = isRtcp ?
|
||||
&audio_rtcp_transport_ : &audio_rtp_transport_;
|
||||
|
||||
transport->Init(client);
|
||||
|
||||
|
@ -160,7 +150,6 @@ class TestAgent {
|
|||
audio_->GetStream()->Stop();
|
||||
audio_rtp_transport_.Stop();
|
||||
audio_rtcp_transport_.Stop();
|
||||
bundle_transport_.Stop();
|
||||
if (audio_pipeline_)
|
||||
audio_pipeline_->ShutdownTransport_s();
|
||||
}
|
||||
|
@ -187,13 +176,10 @@ class TestAgent {
|
|||
mozilla::RefPtr<mozilla::MediaPipeline> audio_pipeline_;
|
||||
TransportInfo audio_rtp_transport_;
|
||||
TransportInfo audio_rtcp_transport_;
|
||||
TransportInfo bundle_transport_;
|
||||
};
|
||||
|
||||
class TestAgentSend : public TestAgent {
|
||||
public:
|
||||
TestAgentSend() : use_bundle_(false) {}
|
||||
|
||||
virtual void CreatePipelines_s(bool aIsRtcpMux) {
|
||||
audio_ = new Fake_DOMMediaStream(new Fake_AudioStreamSource());
|
||||
|
||||
|
@ -208,14 +194,6 @@ class TestAgentSend : public TestAgent {
|
|||
ASSERT_FALSE(audio_rtcp_transport_.flow_);
|
||||
}
|
||||
|
||||
RefPtr<TransportFlow> rtp(audio_rtp_transport_.flow_);
|
||||
RefPtr<TransportFlow> rtcp(audio_rtcp_transport_.flow_);
|
||||
|
||||
if (use_bundle_) {
|
||||
rtp = bundle_transport_.flow_;
|
||||
rtcp = nullptr;
|
||||
}
|
||||
|
||||
audio_pipeline_ = new mozilla::MediaPipelineTransmit(
|
||||
test_pc,
|
||||
nullptr,
|
||||
|
@ -224,8 +202,8 @@ class TestAgentSend : public TestAgent {
|
|||
1,
|
||||
1,
|
||||
audio_conduit_,
|
||||
rtp,
|
||||
rtcp);
|
||||
audio_rtp_transport_.flow_,
|
||||
audio_rtcp_transport_.flow_);
|
||||
|
||||
audio_pipeline_->Init();
|
||||
}
|
||||
|
@ -238,12 +216,7 @@ class TestAgentSend : public TestAgent {
|
|||
return audio_pipeline_->rtcp_packets_received();
|
||||
}
|
||||
|
||||
void SetUsingBundle(bool use_bundle) {
|
||||
use_bundle_ = use_bundle;
|
||||
}
|
||||
|
||||
private:
|
||||
bool use_bundle_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -273,24 +246,13 @@ class TestAgentReceive : public TestAgent {
|
|||
ASSERT_FALSE(audio_rtcp_transport_.flow_);
|
||||
}
|
||||
|
||||
// For now, assume bundle always uses rtcp mux
|
||||
RefPtr<TransportFlow> dummy;
|
||||
RefPtr<TransportFlow> bundle_transport;
|
||||
if (bundle_filter_) {
|
||||
bundle_transport = bundle_transport_.flow_;
|
||||
}
|
||||
|
||||
audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio(
|
||||
test_pc,
|
||||
nullptr,
|
||||
test_utils->sts_target(),
|
||||
audio_->GetStream(), 1, 1,
|
||||
static_cast<mozilla::AudioSessionConduit *>(audio_conduit_.get()),
|
||||
audio_rtp_transport_.flow_,
|
||||
audio_rtcp_transport_.flow_,
|
||||
bundle_transport,
|
||||
dummy,
|
||||
bundle_filter_);
|
||||
audio_rtp_transport_.flow_, audio_rtcp_transport_.flow_);
|
||||
|
||||
audio_pipeline_->Init();
|
||||
}
|
||||
|
@ -303,20 +265,7 @@ class TestAgentReceive : public TestAgent {
|
|||
return audio_pipeline_->rtcp_packets_sent();
|
||||
}
|
||||
|
||||
void SetBundleFilter(nsAutoPtr<MediaPipelineFilter> filter) {
|
||||
bundle_filter_ = filter;
|
||||
}
|
||||
|
||||
void SetUsingBundle_s(bool decision) {
|
||||
audio_pipeline_->SetUsingBundle_s(decision);
|
||||
}
|
||||
|
||||
void UpdateFilterFromRemoteDescription_s(
|
||||
nsAutoPtr<MediaPipelineFilter> filter) {
|
||||
audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter);
|
||||
}
|
||||
private:
|
||||
nsAutoPtr<MediaPipelineFilter> bundle_filter_;
|
||||
};
|
||||
|
||||
|
||||
|
@ -325,7 +274,6 @@ class MediaPipelineTest : public ::testing::Test {
|
|||
MediaPipelineTest() : p1_() {
|
||||
rtp_fds_[0] = rtp_fds_[1] = nullptr;
|
||||
rtcp_fds_[0] = rtcp_fds_[1] = nullptr;
|
||||
bundle_fds_[0] = bundle_fds_[1] = nullptr;
|
||||
}
|
||||
|
||||
// Setup transport.
|
||||
|
@ -337,12 +285,12 @@ class MediaPipelineTest : public ::testing::Test {
|
|||
// RTP, DTLS server
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p1_, &TestAgent::ConnectRtpSocket, rtp_fds_[0], false));
|
||||
WrapRunnable(&p1_, &TestAgent::ConnectSocket, rtp_fds_[0], false, false));
|
||||
|
||||
// RTP, DTLS client
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p2_, &TestAgent::ConnectRtpSocket, rtp_fds_[1], true));
|
||||
WrapRunnable(&p2_, &TestAgent::ConnectSocket, rtp_fds_[1], true, false));
|
||||
|
||||
// Create RTCP flows separately if we are not muxing them.
|
||||
if(!aIsRtcpMux) {
|
||||
|
@ -352,48 +300,17 @@ class MediaPipelineTest : public ::testing::Test {
|
|||
// RTCP, DTLS server
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p1_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[0], false));
|
||||
WrapRunnable(&p1_, &TestAgent::ConnectSocket, rtcp_fds_[0], false, true));
|
||||
|
||||
// RTCP, DTLS client
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p2_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[1], true));
|
||||
WrapRunnable(&p2_, &TestAgent::ConnectSocket, rtcp_fds_[1], true, true));
|
||||
}
|
||||
|
||||
status = PR_NewTCPSocketPair(bundle_fds_);
|
||||
// BUNDLE, DTLS server
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p1_,
|
||||
&TestAgent::ConnectBundleSocket,
|
||||
bundle_fds_[0],
|
||||
false));
|
||||
|
||||
// BUNDLE, DTLS client
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p2_,
|
||||
&TestAgent::ConnectBundleSocket,
|
||||
bundle_fds_[1],
|
||||
true));
|
||||
|
||||
}
|
||||
|
||||
// Verify RTP and RTCP
|
||||
void TestAudioSend(bool aIsRtcpMux,
|
||||
bool bundle = false,
|
||||
nsAutoPtr<MediaPipelineFilter> localFilter =
|
||||
nsAutoPtr<MediaPipelineFilter>(nullptr),
|
||||
nsAutoPtr<MediaPipelineFilter> remoteFilter =
|
||||
nsAutoPtr<MediaPipelineFilter>(nullptr)) {
|
||||
|
||||
// We do not support testing bundle without rtcp mux, since that doesn't
|
||||
// make any sense.
|
||||
ASSERT_FALSE(!aIsRtcpMux && bundle);
|
||||
|
||||
p1_.SetUsingBundle(bundle);
|
||||
p2_.SetBundleFilter(localFilter);
|
||||
|
||||
void TestAudioSend(bool aIsRtcpMux) {
|
||||
// Setup transport flows
|
||||
InitTransports(aIsRtcpMux);
|
||||
|
||||
|
@ -408,51 +325,22 @@ class MediaPipelineTest : public ::testing::Test {
|
|||
p2_.Start();
|
||||
p1_.Start();
|
||||
|
||||
// Simulate pre-answer traffic
|
||||
PR_Sleep(500);
|
||||
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle));
|
||||
|
||||
if (bundle) {
|
||||
if (!remoteFilter) {
|
||||
remoteFilter = new MediaPipelineFilter;
|
||||
}
|
||||
mozilla::SyncRunnable::DispatchToThread(
|
||||
test_utils->sts_target(),
|
||||
WrapRunnable(&p2_,
|
||||
&TestAgentReceive::UpdateFilterFromRemoteDescription_s,
|
||||
remoteFilter));
|
||||
}
|
||||
|
||||
|
||||
// wait for some RTP/RTCP tx and rx to happen
|
||||
PR_Sleep(10000);
|
||||
|
||||
if (bundle) {
|
||||
// Filter should have eaten everything, so no RTCP
|
||||
} else {
|
||||
ASSERT_GE(p1_.GetAudioRtpCount(), 40);
|
||||
ASSERT_GE(p1_.GetAudioRtpCount(), 40);
|
||||
// TODO: Fix to not fail or crash (Bug 947663)
|
||||
// ASSERT_GE(p2_.GetAudioRtpCount(), 40);
|
||||
ASSERT_GE(p2_.GetAudioRtcpCount(), 1);
|
||||
}
|
||||
ASSERT_GE(p1_.GetAudioRtcpCount(), 1);
|
||||
ASSERT_GE(p2_.GetAudioRtcpCount(), 1);
|
||||
|
||||
p1_.Stop();
|
||||
p2_.Stop();
|
||||
}
|
||||
|
||||
void TestAudioReceiverOffersBundle(bool bundle_accepted,
|
||||
nsAutoPtr<MediaPipelineFilter> localFilter,
|
||||
nsAutoPtr<MediaPipelineFilter> remoteFilter =
|
||||
nsAutoPtr<MediaPipelineFilter>(nullptr)) {
|
||||
TestAudioSend(true, bundle_accepted, localFilter, remoteFilter);
|
||||
}
|
||||
protected:
|
||||
PRFileDesc *rtp_fds_[2];
|
||||
PRFileDesc *rtcp_fds_[2];
|
||||
PRFileDesc *bundle_fds_[2];
|
||||
TestAgentSend p1_;
|
||||
TestAgentReceive p2_;
|
||||
};
|
||||
|
@ -825,7 +713,7 @@ TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) {
|
|||
|
||||
TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) {
|
||||
// If the remote SDP doesn't have SSRCs, right now this is a no-op and
|
||||
// there is no point of even incorporating a filter, but we make the
|
||||
// there is no point of even incorporating a filter, but we make the
|
||||
// behavior consistent to avoid confusion.
|
||||
MediaPipelineFilter filter;
|
||||
filter.SetCorrelator(7777);
|
||||
|
@ -848,16 +736,6 @@ TEST_F(MediaPipelineTest, TestAudioSendMux) {
|
|||
TestAudioSend(true);
|
||||
}
|
||||
|
||||
TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) {
|
||||
nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
|
||||
TestAudioReceiverOffersBundle(false, filter);
|
||||
}
|
||||
|
||||
TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) {
|
||||
nsAutoPtr<MediaPipelineFilter> filter(new MediaPipelineFilter);
|
||||
TestAudioReceiverOffersBundle(true, filter);
|
||||
}
|
||||
|
||||
} // end namespace
|
||||
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче