Backed out changeset c5334aea6433 (bug 786234)

This commit is contained in:
Adam Roach [:abr] 2014-02-24 12:29:10 -06:00
Родитель a231c2f65a
Коммит 34d7d2d699
9 изменённых файлов: 210 добавлений и 825 удалений

Просмотреть файл

@ -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