mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 863306: Propagate RTCP_MUX Status to pipeline via VCM. r=abr
This commit is contained in:
parent
5a2c890c2d
commit
21880a4f7a
@ -1405,12 +1405,14 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id,
|
||||
return VCM_ERROR;
|
||||
}
|
||||
|
||||
mozilla::RefPtr<TransportFlow> rtcp_flow =
|
||||
vcmCreateTransportFlow(pc.impl(), level, true,
|
||||
fingerprint_alg, fingerprint);
|
||||
if (!rtcp_flow) {
|
||||
CSFLogError( logTag, "Could not create RTCP flow");
|
||||
return VCM_ERROR;
|
||||
mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
|
||||
if(!attrs->rtcp_mux) {
|
||||
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true,
|
||||
fingerprint_alg, fingerprint);
|
||||
if (!rtcp_flow) {
|
||||
CSFLogError( logTag, "Could not create RTCP flow");
|
||||
return VCM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (CC_IS_AUDIO(mcap_id)) {
|
||||
@ -2046,12 +2048,14 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id,
|
||||
CSFLogError( logTag, "Could not create RTP flow");
|
||||
return VCM_ERROR;
|
||||
}
|
||||
mozilla::RefPtr<TransportFlow> rtcp_flow =
|
||||
vcmCreateTransportFlow(pc.impl(), level, true,
|
||||
fingerprint_alg, fingerprint);
|
||||
if (!rtcp_flow) {
|
||||
mozilla::RefPtr<TransportFlow> rtcp_flow = nullptr;
|
||||
if(!attrs->rtcp_mux) {
|
||||
rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true,
|
||||
fingerprint_alg, fingerprint);
|
||||
if (!rtcp_flow) {
|
||||
CSFLogError( logTag, "Could not create RTCP flow");
|
||||
return VCM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (CC_IS_AUDIO(mcap_id)) {
|
||||
|
@ -122,6 +122,10 @@ class MediaPipeline : public sigslot::has_slots<> {
|
||||
|
||||
virtual Direction direction() const { return direction_; }
|
||||
|
||||
bool IsDoingRtcpMux() const {
|
||||
return (rtp_transport_ == rtcp_transport_);
|
||||
}
|
||||
|
||||
int rtp_packets_sent() const { return rtp_packets_sent_; }
|
||||
int rtcp_packets_sent() const { return rtcp_packets_sent_; }
|
||||
int rtp_packets_received() const { return rtp_packets_received_; }
|
||||
|
@ -443,6 +443,20 @@ PeerConnectionMedia::IceStreamReady(NrIceMediaStream *aStream)
|
||||
CSFLogDebug(logTag, "%s: %s", __FUNCTION__, aStream->name().c_str());
|
||||
}
|
||||
|
||||
// This method exists for the unittests.
|
||||
// It allows visibility into the pipelines and flows.
|
||||
// It returns NULL if no pipeline exists for this track number.
|
||||
mozilla::RefPtr<mozilla::MediaPipeline>
|
||||
SourceStreamInfo::GetPipeline(int aTrack) {
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> >::iterator it =
|
||||
mPipelines.find(aTrack);
|
||||
|
||||
if (it == mPipelines.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void
|
||||
LocalSourceStreamInfo::StorePipeline(int aTrack,
|
||||
|
@ -162,17 +162,42 @@ class Fake_VideoGenerator {
|
||||
#endif
|
||||
|
||||
|
||||
// TODO(ekr@rtfm.com): Refactor {Local,Remote}SourceStreamInfo
|
||||
// bug 837539.
|
||||
class LocalSourceStreamInfo {
|
||||
class SourceStreamInfo {
|
||||
public:
|
||||
typedef mozilla::DOMMediaStream DOMMediaStream;
|
||||
|
||||
LocalSourceStreamInfo(DOMMediaStream* aMediaStream, PeerConnectionMedia *aParent)
|
||||
: mMediaStream(aMediaStream), mParent(aParent) {
|
||||
MOZ_ASSERT(aMediaStream);
|
||||
SourceStreamInfo(DOMMediaStream* aMediaStream,
|
||||
PeerConnectionMedia *aParent)
|
||||
: mMediaStream(aMediaStream),
|
||||
mParent(aParent) {
|
||||
MOZ_ASSERT(mMediaStream);
|
||||
}
|
||||
|
||||
SourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
|
||||
PeerConnectionMedia *aParent)
|
||||
: mMediaStream(aMediaStream),
|
||||
mParent(aParent) {
|
||||
MOZ_ASSERT(mMediaStream);
|
||||
}
|
||||
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> GetPipeline(int aTrack);
|
||||
|
||||
protected:
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> > mPipelines;
|
||||
nsRefPtr<DOMMediaStream> mMediaStream;
|
||||
PeerConnectionMedia *mParent;
|
||||
};
|
||||
|
||||
// TODO(ekr@rtfm.com): Refactor {Local,Remote}SourceStreamInfo
|
||||
// bug 837539.
|
||||
class LocalSourceStreamInfo : public SourceStreamInfo {
|
||||
public:
|
||||
typedef mozilla::DOMMediaStream DOMMediaStream;
|
||||
|
||||
LocalSourceStreamInfo(DOMMediaStream *aMediaStream,
|
||||
PeerConnectionMedia *aParent)
|
||||
: SourceStreamInfo(aMediaStream, aParent) {}
|
||||
|
||||
~LocalSourceStreamInfo() {
|
||||
mMediaStream = NULL;
|
||||
}
|
||||
@ -191,25 +216,18 @@ public:
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LocalSourceStreamInfo)
|
||||
private:
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> > mPipelines;
|
||||
nsRefPtr<DOMMediaStream> mMediaStream;
|
||||
nsTArray<mozilla::TrackID> mAudioTracks;
|
||||
nsTArray<mozilla::TrackID> mVideoTracks;
|
||||
PeerConnectionMedia *mParent;
|
||||
};
|
||||
|
||||
class RemoteSourceStreamInfo {
|
||||
class RemoteSourceStreamInfo : public SourceStreamInfo {
|
||||
public:
|
||||
typedef mozilla::DOMMediaStream DOMMediaStream;
|
||||
|
||||
RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
|
||||
PeerConnectionMedia *aParent)
|
||||
: mTrackTypeHints(0),
|
||||
mMediaStream(aMediaStream),
|
||||
mPipelines(),
|
||||
mParent(aParent) {
|
||||
MOZ_ASSERT(mMediaStream);
|
||||
}
|
||||
RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
|
||||
PeerConnectionMedia *aParent)
|
||||
: SourceStreamInfo(aMediaStream, aParent),
|
||||
mTrackTypeHints(0) {}
|
||||
|
||||
DOMMediaStream* GetMediaStream() {
|
||||
return mMediaStream;
|
||||
@ -225,10 +243,7 @@ RemoteSourceStreamInfo(already_AddRefed<DOMMediaStream> aMediaStream,
|
||||
public:
|
||||
DOMMediaStream::TrackTypeHints mTrackTypeHints;
|
||||
private:
|
||||
nsRefPtr<DOMMediaStream> mMediaStream;
|
||||
std::map<int, mozilla::RefPtr<mozilla::MediaPipeline> > mPipelines;
|
||||
std::map<int, bool> mTypes;
|
||||
PeerConnectionMedia *mParent;
|
||||
};
|
||||
|
||||
class PeerConnectionMedia : public sigslot::has_slots<> {
|
||||
|
@ -4734,12 +4734,14 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
|
||||
/*
|
||||
* Negotiate rtcp-mux
|
||||
*/
|
||||
if(SDP_MEDIA_APPLICATION != media_type) {
|
||||
sdp_res = sdp_attr_get_rtcp_mux_attribute(sdp_p->dest_sdp, i,
|
||||
0, SDP_ATTR_RTCP_MUX,
|
||||
1, &rtcp_mux);
|
||||
|
||||
sdp_res = sdp_attr_get_rtcp_mux_attribute (sdp_p->dest_sdp, i,
|
||||
0, SDP_ATTR_RTCP_MUX, 1, &rtcp_mux);
|
||||
|
||||
if (SDP_SUCCESS == sdp_res) {
|
||||
media->rtcp_mux = TRUE;
|
||||
if (SDP_SUCCESS == sdp_res) {
|
||||
media->rtcp_mux = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!unsupported_line) {
|
||||
@ -4753,8 +4755,10 @@ gsmsdp_negotiate_media_lines (fsm_fcb_t *fcb_p, cc_sdp_t *sdp_p, boolean initial
|
||||
sdp_p->src_sdp, media->candidatesp[j]);
|
||||
}
|
||||
|
||||
/* Set RTCPMux if we have it turned on in our config
|
||||
and the other side requests it */
|
||||
config_get_value(CFGID_RTCPMUX, &rtcpmux, sizeof(rtcpmux));
|
||||
if (rtcpmux) {
|
||||
if (rtcpmux && media->rtcp_mux) {
|
||||
gsmsdp_set_rtcp_mux_attribute (SDP_ATTR_RTCP_MUX, media->level,
|
||||
sdp_p->src_sdp, TRUE);
|
||||
}
|
||||
@ -5275,7 +5279,7 @@ gsmsdp_add_media_line (fsmdef_dcb_t *dcb_p, const cc_media_cap_t *media_cap,
|
||||
}
|
||||
|
||||
config_get_value(CFGID_RTCPMUX, &rtcpmux, sizeof(rtcpmux));
|
||||
if (rtcpmux) {
|
||||
if (SDP_MEDIA_APPLICATION != media_cap->type && rtcpmux) {
|
||||
gsmsdp_set_rtcp_mux_attribute (SDP_ATTR_RTCP_MUX, level, dcb_p->sdp->src_sdp, TRUE);
|
||||
}
|
||||
|
||||
|
@ -984,6 +984,7 @@ lsm_rx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
||||
media->src_port = open_rcv.port;
|
||||
}
|
||||
|
||||
attrs.rtcp_mux = media->rtcp_mux;
|
||||
if ( media->cap_index == CC_VIDEO_1 ) {
|
||||
attrs.video.opaque = media->video;
|
||||
} else {
|
||||
@ -1220,6 +1221,8 @@ lsm_tx_start (lsm_lcb_t *lcb, const char *fname, fsmdef_media_t *media)
|
||||
media->xmit_chan = TRUE;
|
||||
|
||||
attrs.mute = FALSE;
|
||||
|
||||
attrs.rtcp_mux = media->rtcp_mux;
|
||||
if ( CC_IS_VIDEO(media->cap_index)) {
|
||||
attrs.video.opaque = media->video;
|
||||
if (lcb->vid_mute) {
|
||||
|
@ -179,7 +179,7 @@ static const int gDscpCallControl = 1;
|
||||
static const int gSpeakerEnabled = 1;
|
||||
static const char gExternalNumberMask[] = "";
|
||||
static const char gVersion[] = "0.1";
|
||||
static const boolean gRTCPMUX = FALSE;
|
||||
static const boolean gRTCPMUX = TRUE;
|
||||
static boolean gRTPSAVPF = TRUE; /* TRUE = RTP/SAVPF , FALSE = RTP/SAVP */
|
||||
static const boolean gMAXAVBITRATE = FALSE; /* Following six are OPUS fmtp options */
|
||||
static const boolean gMAXCODEDAUDIOBW = FALSE;
|
||||
|
@ -331,6 +331,7 @@ typedef struct vcm_audioAttrs_t_ {
|
||||
typedef struct vcm_attrs_t_ {
|
||||
cc_boolean mute;
|
||||
cc_boolean is_video;
|
||||
cc_boolean rtcp_mux;
|
||||
vcm_audioAttrs_t audio; /**< audio line attribs */
|
||||
vcm_videoAttrs_t video; /**< Video Atrribs */
|
||||
} vcm_mediaAttrs_t;
|
||||
|
@ -137,6 +137,15 @@ enum offerAnswerFlags
|
||||
ANSWER_AV = ANSWER_AUDIO | ANSWER_VIDEO
|
||||
};
|
||||
|
||||
enum mediaPipelineFlags
|
||||
{
|
||||
PIPELINE_LOCAL = (1<<0),
|
||||
PIPELINE_RTCP_MUX = (1<<1),
|
||||
PIPELINE_SEND = (1<<2),
|
||||
PIPELINE_VIDEO = (1<<3)
|
||||
};
|
||||
|
||||
|
||||
static bool SetupGlobalThread() {
|
||||
if (!gThread) {
|
||||
nsIThread *thread;
|
||||
@ -455,7 +464,14 @@ class ParsedSDP {
|
||||
Parse();
|
||||
}
|
||||
|
||||
void DeleteLine(std::string objType)
|
||||
{
|
||||
ReplaceLine(objType, "");
|
||||
}
|
||||
|
||||
// Replaces the first instance of objType in the SDP with
|
||||
// a new string.
|
||||
// If content is an empty string then the line will be removed
|
||||
void ReplaceLine(std::string objType, std::string content)
|
||||
{
|
||||
std::multimap<std::string, SdpLine>::iterator it;
|
||||
@ -464,6 +480,9 @@ class ParsedSDP {
|
||||
SdpLine sdp_line_pair = (*it).second;
|
||||
int line_no = sdp_line_pair.first;
|
||||
sdp_map_.erase(it);
|
||||
if(content.empty()) {
|
||||
return;
|
||||
}
|
||||
std::string value = content.substr(objType.length());
|
||||
sdp_map_.insert(std::pair<std::string, SdpLine>(objType,
|
||||
std::make_pair(line_no,value)));
|
||||
@ -752,7 +771,7 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
DONT_CHECK_VIDEO|
|
||||
DONT_CHECK_DATA,
|
||||
sipcc::PeerConnectionImpl::SignalingState endState =
|
||||
sipcc::PeerConnectionImpl::kSignalingHaveRemoteOffer) {
|
||||
sipcc::PeerConnectionImpl::kSignalingHaveRemoteOffer) {
|
||||
|
||||
uint32_t aHintContents = 0;
|
||||
if (offerAnswerFlags & ANSWER_AUDIO) {
|
||||
@ -935,6 +954,42 @@ void CreateAnswer(sipcc::MediaConstraints& constraints, std::string offer,
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> GetMediaPipeline(
|
||||
bool local, int stream, int track) {
|
||||
sipcc::SourceStreamInfo *streamInfo;
|
||||
|
||||
if (local) {
|
||||
streamInfo = pc->media()->GetLocalStream(stream);
|
||||
} else {
|
||||
streamInfo = pc->media()->GetRemoteStream(stream);
|
||||
}
|
||||
|
||||
if (!streamInfo) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return streamInfo->GetPipeline(track);
|
||||
}
|
||||
|
||||
|
||||
void CheckMediaPipeline(int stream, int track, uint32_t flags) {
|
||||
mozilla::RefPtr<mozilla::MediaPipeline> pipeline =
|
||||
GetMediaPipeline((flags & PIPELINE_LOCAL), stream, track);
|
||||
ASSERT_TRUE(pipeline);
|
||||
ASSERT_EQ(pipeline->IsDoingRtcpMux(), !!(flags & PIPELINE_RTCP_MUX));
|
||||
// We cannot yet test send/recv with video.
|
||||
if (!(flags & PIPELINE_VIDEO)) {
|
||||
if (flags & PIPELINE_SEND) {
|
||||
ASSERT_GE(pipeline->rtp_packets_sent(), 40);
|
||||
ASSERT_GE(pipeline->rtcp_packets_received(), 1);
|
||||
} else {
|
||||
ASSERT_GE(pipeline->rtp_packets_received(), 40);
|
||||
ASSERT_GE(pipeline->rtcp_packets_sent(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
mozilla::RefPtr<sipcc::PeerConnectionImpl> pc;
|
||||
nsRefPtr<TestObserver> pObserver;
|
||||
@ -1624,6 +1679,15 @@ TEST_F(SignalingTest, FullCall)
|
||||
//ASSERT_GE(a2_.GetPacketsSent(0), 40);
|
||||
//ASSERT_GE(a1_.GetPacketsReceived(0), 40);
|
||||
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
|
||||
|
||||
// Check the low-level media pipeline
|
||||
// for RTP and RTCP flows
|
||||
// The first Local pipeline gets stored at 0
|
||||
a1_.CheckMediaPipeline(0, 0,
|
||||
PIPELINE_LOCAL | PIPELINE_RTCP_MUX | PIPELINE_SEND);
|
||||
|
||||
// The first Remote pipeline gets stored at 1
|
||||
a2_.CheckMediaPipeline(0, 1, PIPELINE_RTCP_MUX);
|
||||
}
|
||||
|
||||
TEST_F(SignalingTest, FullCallAudioOnly)
|
||||
@ -2284,11 +2348,99 @@ TEST_F(SignalingTest, missingUfrag)
|
||||
a1_.CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
|
||||
a1_.SetLocal(TestObserver::OFFER, offer, true);
|
||||
// We now detect the missing ICE parameters at SetRemoteDescription
|
||||
a2_.SetRemote(TestObserver::OFFER, offer, true,
|
||||
a2_.SetRemote(TestObserver::OFFER, offer, true,
|
||||
sipcc::PeerConnectionImpl::kSignalingStable);
|
||||
ASSERT_TRUE(a2_.pObserver->state == TestObserver::stateError);
|
||||
}
|
||||
|
||||
TEST_F(SignalingTest, AudioOnlyCalleeNoRtcpMux)
|
||||
{
|
||||
sipcc::MediaConstraints constraints;
|
||||
|
||||
a1_.CreateOffer(constraints, OFFER_AUDIO, SHOULD_SENDRECV_AUDIO);
|
||||
a1_.SetLocal(TestObserver::OFFER, a1_.offer(), false);
|
||||
ParsedSDP sdpWrapper(a1_.offer());
|
||||
sdpWrapper.DeleteLine("a=rtcp-mux");
|
||||
std::cout << "Modified SDP " << std::endl
|
||||
<< indent(sdpWrapper.getSdp()) << std::endl;
|
||||
a2_.SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
|
||||
a2_.CreateAnswer(constraints, sdpWrapper.getSdp(),
|
||||
OFFER_AUDIO | ANSWER_AUDIO);
|
||||
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
|
||||
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
|
||||
|
||||
// Answer should not have a=rtcp-mux
|
||||
ASSERT_EQ(a2_.getLocalDescription().find("\r\na=rtcp-mux"),
|
||||
std::string::npos);
|
||||
|
||||
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
|
||||
|
||||
PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
|
||||
|
||||
a1_.CloseSendStreams();
|
||||
a2_.CloseReceiveStreams();
|
||||
|
||||
ASSERT_GE(a1_.GetPacketsSent(0), 40);
|
||||
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
|
||||
|
||||
// Check the low-level media pipeline
|
||||
// for RTP and RTCP flows
|
||||
// The first Local pipeline gets stored at 0
|
||||
a1_.CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND);
|
||||
|
||||
// The first Remote pipeline gets stored at 1
|
||||
a2_.CheckMediaPipeline(0, 1, 0);
|
||||
}
|
||||
|
||||
TEST_F(SignalingTest, FullCallAudioNoMuxVideoMux)
|
||||
{
|
||||
sipcc::MediaConstraints constraints;
|
||||
|
||||
a1_.CreateOffer(constraints, OFFER_AV, SHOULD_SENDRECV_AV);
|
||||
a1_.SetLocal(TestObserver::OFFER, a1_.offer(), false);
|
||||
ParsedSDP sdpWrapper(a1_.offer());
|
||||
sdpWrapper.DeleteLine("a=rtcp-mux");
|
||||
std::cout << "Modified SDP " << std::endl
|
||||
<< indent(sdpWrapper.getSdp()) << std::endl;
|
||||
a2_.SetRemote(TestObserver::OFFER, sdpWrapper.getSdp(), false);
|
||||
a2_.CreateAnswer(constraints, sdpWrapper.getSdp(), OFFER_AV | ANSWER_AV);
|
||||
a2_.SetLocal(TestObserver::ANSWER, a2_.answer(), false);
|
||||
a1_.SetRemote(TestObserver::ANSWER, a2_.answer(), false);
|
||||
|
||||
// Answer should have only one a=rtcp-mux line
|
||||
size_t match = a2_.getLocalDescription().find("\r\na=rtcp-mux");
|
||||
ASSERT_NE(match, std::string::npos);
|
||||
match = a2_.getLocalDescription().find("\r\na=rtcp-mux", match + 1);
|
||||
ASSERT_EQ(match, std::string::npos);
|
||||
|
||||
ASSERT_TRUE_WAIT(a1_.IceCompleted() == true, kDefaultTimeout);
|
||||
ASSERT_TRUE_WAIT(a2_.IceCompleted() == true, kDefaultTimeout);
|
||||
|
||||
PR_Sleep(kDefaultTimeout * 2); // Wait for some data to get written
|
||||
|
||||
a1_.CloseSendStreams();
|
||||
a2_.CloseReceiveStreams();
|
||||
|
||||
ASSERT_GE(a1_.GetPacketsSent(0), 40);
|
||||
ASSERT_GE(a2_.GetPacketsReceived(0), 40);
|
||||
|
||||
// Check the low-level media pipeline
|
||||
// for RTP and RTCP flows
|
||||
// The first Local pipeline gets stored at 0
|
||||
a1_.CheckMediaPipeline(0, 0, PIPELINE_LOCAL | PIPELINE_SEND);
|
||||
|
||||
// Now check video mux.
|
||||
a1_.CheckMediaPipeline(0, 1,
|
||||
PIPELINE_LOCAL | PIPELINE_RTCP_MUX | PIPELINE_SEND | PIPELINE_VIDEO);
|
||||
|
||||
// The first Remote pipeline gets stored at 1
|
||||
a2_.CheckMediaPipeline(0, 1, 0);
|
||||
|
||||
// Now check video mux.
|
||||
a2_.CheckMediaPipeline(0, 2, PIPELINE_RTCP_MUX | PIPELINE_VIDEO);
|
||||
}
|
||||
|
||||
} // End namespace test.
|
||||
|
||||
bool is_color_terminal(const char *terminal) {
|
||||
|
Loading…
Reference in New Issue
Block a user