Bug 1320101 - Support renegotiations with changes to TIAS and simulcast params. r=bwc,jesup
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 08 Dec 2016 10:11:18 -1000
changeset 325415 afdc890658747791601d65c77ed549d4607d0d77
parent 325414 337f8b56236774aea32593bba2c540df33cddd26
child 325416 abcb8d9139a2d3b0cee9084313ef58326409b349
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersbwc, jesup
bugs1320101
milestone53.0a1
Bug 1320101 - Support renegotiations with changes to TIAS and simulcast params. r=bwc,jesup MozReview-Commit-ID: GNWRNnwX9pk
media/webrtc/signaling/src/common/EncodingConstraints.h
media/webrtc/signaling/src/media-conduit/CodecConfig.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
--- 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;
     }