Bug 1320101 - Support renegotiations with changes to TIAS and simulcast params. r?jesup, r?bwc
MozReview-Commit-ID: GNWRNnwX9pk
--- a/media/webrtc/signaling/src/common/EncodingConstraints.h
+++ b/media/webrtc/signaling/src/common/EncodingConstraints.h
@@ -37,16 +37,28 @@ public:
maxBr == constraints.maxBr &&
maxPps == constraints.maxPps &&
maxMbps == constraints.maxMbps &&
maxCpb == constraints.maxCpb &&
maxDpb == constraints.maxDpb &&
scaleDownBy == constraints.scaleDownBy;
}
+ /**
+ * This returns true if the constraints affecting resolution are equal.
+ */
+ bool ResolutionEquals(const EncodingConstraints& constraints) const
+ {
+ return
+ maxWidth == constraints.maxWidth &&
+ maxHeight == constraints.maxHeight &&
+ maxFs == constraints.maxFs &&
+ scaleDownBy == constraints.scaleDownBy;
+ }
+
uint32_t maxWidth;
uint32_t maxHeight;
uint32_t maxFps;
uint32_t maxFs;
uint32_t maxBr;
uint32_t maxPps;
uint32_t maxMbps; // macroblocks per second
uint32_t maxCpb; // coded picture buffer size
--- a/media/webrtc/signaling/src/media-conduit/CodecConfig.h
+++ b/media/webrtc/signaling/src/media-conduit/CodecConfig.h
@@ -122,16 +122,30 @@ public:
mProfile = (h264->profile_level_id & 0x00FF0000) >> 16;
mConstraints = (h264->profile_level_id & 0x0000FF00) >> 8;
mLevel = (h264->profile_level_id & 0x000000FF);
mPacketizationMode = h264->packetization_mode;
mSpropParameterSets = h264->sprop_parameter_sets;
}
}
+ bool ResolutionEquals(const VideoCodecConfig& aConfig) const
+ {
+ if (mSimulcastEncodings.size() != aConfig.mSimulcastEncodings.size()) {
+ return false;
+ }
+ for (size_t i = 0; i < mSimulcastEncodings.size(); ++i) {
+ if (!mSimulcastEncodings[i].constraints.ResolutionEquals(
+ aConfig.mSimulcastEncodings[i].constraints)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
// Nothing seems to use this right now. Do we intend to support this
// someday?
bool RtcpFbAckIsSet(const std::string& type) const
{
for (auto i = mAckFbTypes.begin(); i != mAckFbTypes.end(); ++i) {
if (*i == type) {
return true;
}
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -298,17 +298,16 @@ WebrtcVideoConduit::InitMain()
if (temp >= 0) {
mStartBitrate = temp;
}
}
if (!NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.max_bitrate", &temp))))
{
if (temp >= 0) {
mPrefMaxBitrate = temp;
- mNegotiatedMaxBitrate = temp; // simplifies logic in SelectBitrate (don't have to do two limit tests)
}
}
if (mMinBitrate != 0 && mMinBitrate < webrtc::kViEMinCodecBitrate) {
mMinBitrate = webrtc::kViEMinCodecBitrate;
}
if (mStartBitrate < mMinBitrate) {
mStartBitrate = mMinBitrate;
}
@@ -722,47 +721,84 @@ WebrtcVideoConduit::ConfigureSendMediaCo
// by GetCodec()
codecFound = true;
break;
}
}
}//for
}
- if(codecFound == false)
+ if(!codecFound)
{
CSFLogError(logTag, "%s Codec Mismatch ", __FUNCTION__);
return kMediaConduitInvalidSendCodec;
}
// So we can comply with b=TIAS/b=AS/maxbr=X when input resolution changes
mNegotiatedMaxBitrate = codecConfig->mTias / 1000;
// Note: only for overriding parameters from GetCodec()!
CodecConfigToWebRTCCodec(codecConfig, video_codec);
- if (mSendingWidth != 0) {
- // We're already in a call and are reconfiguring (perhaps due to
- // ReplaceTrack). Set to match the last frame we sent.
-
- // We could also set mLastWidth to 0, to force immediate reconfig -
- // more expensive, but perhaps less risk of missing something. Really
- // on ReplaceTrack we should just call ConfigureCodecMode(), and if the
- // mode changed, we re-configure.
- // Do this after CodecConfigToWebRTCCodec() to avoid messing up simulcast
- video_codec.width = mSendingWidth;
- video_codec.height = mSendingHeight;
- video_codec.maxFramerate = mSendingFramerate;
- } else {
- mSendingWidth = 0;
- mSendingHeight = 0;
- mSendingFramerate = video_codec.maxFramerate;
- }
video_codec.mode = mCodecMode;
+ if (mSendingWidth != 0) {
+ bool resolutionChanged;
+ {
+ MutexAutoLock lock(mCodecMutex);
+ resolutionChanged = !mCurSendCodecConfig->ResolutionEquals(*codecConfig);
+ }
+
+ if (resolutionChanged) {
+ // We're already in a call and due to renegotiation an encoder parameter
+ // that requires reconfiguration has changed. Resetting these members
+ // triggers reconfig on the next frame.
+ mLastWidth = 0;
+ mLastHeight = 0;
+ mSendingWidth = 0;
+ mSendingHeight = 0;
+ } else {
+ // We're already in a call but changes don't require a reconfiguration.
+ // We update the resolutions in the send codec to match the current
+ // settings.
+ webrtc::VideoCodec oldSendCodec;
+ if ((error = mPtrViECodec->GetSendCodec(mChannel, oldSendCodec)) != 0) {
+ CSFLogError(logTag, "%s: GetSendCodec failed, err %d", __FUNCTION__, error);
+ return kMediaConduitInvalidSendCodec;
+ }
+
+ if (video_codec.numberOfSimulcastStreams !=
+ oldSendCodec.numberOfSimulcastStreams) {
+ MOZ_ASSERT(false);
+ return kMediaConduitInvalidSendCodec;
+ }
+
+ video_codec.width = oldSendCodec.width;
+ video_codec.height = oldSendCodec.height;
+ SelectBitrates(video_codec.width, video_codec.height,
+ video_codec.maxBitrate,
+ mLastFramerateTenths,
+ video_codec.minBitrate,
+ video_codec.targetBitrate,
+ video_codec.maxBitrate);
+ for (size_t i = 0; i < video_codec.numberOfSimulcastStreams; ++i) {
+ webrtc::SimulcastStream& stream(video_codec.simulcastStream[i]);
+ stream.width = oldSendCodec.simulcastStream[i].width;
+ stream.height = oldSendCodec.simulcastStream[i].height;
+ SelectBitrates(stream.width,
+ stream.height,
+ MinIgnoreZero(stream.jsMaxBitrate, video_codec.maxBitrate),
+ mLastFramerateTenths,
+ stream.minBitrate,
+ stream.targetBitrate,
+ stream.maxBitrate);
+ }
+ }
+ }
+
if(mPtrViECodec->SetSendCodec(mChannel, video_codec) == -1)
{
error = mPtrViEBase->LastError();
if(error == kViECodecInvalidCodec)
{
CSFLogError(logTag, "%s Invalid Send Codec", __FUNCTION__);
return kMediaConduitInvalidSendCodec;
}