Bug 1349233: allow SSRC changes in VideoConduits r=bwc

MozReview-Commit-ID: 6PNyjLyl9L0
This commit is contained in:
Randell Jesup 2017-03-28 10:43:10 -04:00
parent 12f7354feb
commit 80022975a2
2 changed files with 31 additions and 19 deletions

View File

@ -198,7 +198,7 @@ WebrtcVideoConduit::WebrtcVideoConduit(RefPtr<WebRtcCallWrapper> aCall)
, mCall(aCall) // refcounted store of the call object , mCall(aCall) // refcounted store of the call object
, mSendStreamConfig(this) // 'this' is stored but not dereferenced in the constructor. , mSendStreamConfig(this) // 'this' is stored but not dereferenced in the constructor.
, mRecvStreamConfig(this) // 'this' is stored but not dereferenced in the constructor. , mRecvStreamConfig(this) // 'this' is stored but not dereferenced in the constructor.
, mRecvSSRCSet(false) , mRecvSSRC(0)
, mRecvSSRCSetInProgress(false) , mRecvSSRCSetInProgress(false)
, mSendCodecPlugin(nullptr) , mSendCodecPlugin(nullptr)
, mRecvCodecPlugin(nullptr) , mRecvCodecPlugin(nullptr)
@ -699,7 +699,6 @@ WebrtcVideoConduit::SetRemoteSSRC(unsigned int ssrc)
if (!GetRemoteSSRC(&current_ssrc)) { if (!GetRemoteSSRC(&current_ssrc)) {
return false; return false;
} }
mRecvSSRCSet = true;
if (current_ssrc == ssrc) { if (current_ssrc == ssrc) {
return true; return true;
@ -1177,7 +1176,8 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
mRecvStreamConfig.rtp.fec.red_rtx_payload_type = -1; mRecvStreamConfig.rtp.fec.red_rtx_payload_type = -1;
} }
if (!mRecvSSRCSet) { // XXX ugh! same SSRC==0 problem that webrtc.org has
if (mRecvSSRC == 0) {
// Handle un-signalled SSRCs by creating a random one and then when it actually gets set, // Handle un-signalled SSRCs by creating a random one and then when it actually gets set,
// we'll destroy and recreate. Simpler than trying to unwind all the logic that assumes // we'll destroy and recreate. Simpler than trying to unwind all the logic that assumes
// the receive stream is created and started when we ConfigureRecvMediaCodecs() // the receive stream is created and started when we ConfigureRecvMediaCodecs()
@ -1191,6 +1191,9 @@ WebrtcVideoConduit::ConfigureRecvMediaCodecs(
mRecvStreamConfig.rtp.remote_ssrc = ssrc; mRecvStreamConfig.rtp.remote_ssrc = ssrc;
} }
// Either set via SetRemoteSSRC, or temp one we created.
mRecvSSRC = mRecvStreamConfig.rtp.remote_ssrc;
// 0 isn't allowed. Would be best to ask for a random SSRC from the // 0 isn't allowed. Would be best to ask for a random SSRC from the
// RTP code. Would need to call rtp_sender.cc -- GenerateNewSSRC(), // RTP code. Would need to call rtp_sender.cc -- GenerateNewSSRC(),
// which isn't exposed. It's called on collision, or when we decide to // which isn't exposed. It's called on collision, or when we decide to
@ -1805,10 +1808,15 @@ MediaConduitErrorCode
WebrtcVideoConduit::ReceivedRTPPacket(const void* data, int len, uint32_t ssrc) WebrtcVideoConduit::ReceivedRTPPacket(const void* data, int len, uint32_t ssrc)
{ {
bool queue = mRecvSSRCSetInProgress; bool queue = mRecvSSRCSetInProgress;
if (!mRecvSSRCSet && !mRecvSSRCSetInProgress) { if (mRecvSSRC != ssrc && !queue) {
// we "switch" here immediately, but buffer until the queue is released
mRecvSSRC = ssrc;
mRecvSSRCSetInProgress = true; mRecvSSRCSetInProgress = true;
queue = true; queue = true;
// Handle the ssrc-not-signaled case; lock onto first ssrc // any queued packets are from a previous switch that hasn't completed
// yet; drop them and only process the latest SSRC
mQueuedPackets.Clear();
// Handle the unknown ssrc (and ssrc-not-signaled case).
// We can't just do this here; it has to happen on MainThread :-( // We can't just do this here; it has to happen on MainThread :-(
// We also don't want to drop the packet, nor stall this thread, so we hold // We also don't want to drop the packet, nor stall this thread, so we hold
// the packet (and any following) for inserting once the SSRC is set. // the packet (and any following) for inserting once the SSRC is set.
@ -1828,19 +1836,23 @@ WebrtcVideoConduit::ReceivedRTPPacket(const void* data, int len, uint32_t ssrc)
WebrtcGmpPCHandleSetter setter(self->mPCHandle); WebrtcGmpPCHandleSetter setter(self->mPCHandle);
self->SetRemoteSSRC(ssrc); // this will likely re-create the VideoReceiveStream self->SetRemoteSSRC(ssrc); // this will likely re-create the VideoReceiveStream
// We want to unblock the queued packets on the original thread // We want to unblock the queued packets on the original thread
thread->Dispatch(media::NewRunnableFrom([self]() mutable { thread->Dispatch(media::NewRunnableFrom([self, ssrc]() mutable {
self->mRecvSSRCSetInProgress = false; if (ssrc == self->mRecvSSRC) {
// SSRC is set; insert queued packets // SSRC is set; insert queued packets
for (auto& packet : self->mQueuedPackets) { for (auto& packet : self->mQueuedPackets) {
CSFLogDebug(logTag, "%s: seq# %u, Len %d ", __FUNCTION__, CSFLogDebug(logTag, "%s: seq# %u, Len %d ", __FUNCTION__,
(uint16_t)ntohs(((uint16_t*) packet->mData)[1]), packet->mLen); (uint16_t)ntohs(((uint16_t*) packet->mData)[1]), packet->mLen);
if (self->DeliverPacket(packet->mData, packet->mLen) != kMediaConduitNoError) { if (self->DeliverPacket(packet->mData, packet->mLen) != kMediaConduitNoError) {
CSFLogError(logTag, "%s RTP Processing Failed", __FUNCTION__); CSFLogError(logTag, "%s RTP Processing Failed", __FUNCTION__);
// Keep delivering and then clear the queue // Keep delivering and then clear the queue
}
} }
self->mQueuedPackets.Clear();
// we don't leave inprogress until there are no changes in-flight
self->mRecvSSRCSetInProgress = false;
} }
self->mQueuedPackets.Clear(); // else this is an intermediate switch; another is in-flight
return NS_OK; return NS_OK;
}), NS_DISPATCH_NORMAL); }), NS_DISPATCH_NORMAL);

View File

@ -503,10 +503,10 @@ private:
webrtc::VideoCodecH264 mEncoderSpecificH264; webrtc::VideoCodecH264 mEncoderSpecificH264;
webrtc::VideoReceiveStream::Config mRecvStreamConfig; webrtc::VideoReceiveStream::Config mRecvStreamConfig;
// We can't create mRecvStream without knowing the remote SSRC
// Atomic since we key off this on packet insertion, which happens // accessed on creation, and when receiving packets
// on a different thread. uint32_t mRecvSSRC; // this can change during a stream!
Atomic<bool> mRecvSSRCSet;
// The runnable to set the SSRC is in-flight; queue packets until it's done. // The runnable to set the SSRC is in-flight; queue packets until it's done.
bool mRecvSSRCSetInProgress; bool mRecvSSRCSetInProgress;
struct QueuedPacket { struct QueuedPacket {