Bug 1320101 - Differentiate between b=TIAS and simulcast stream max-br. r?jesup, r?bwc draft
authorAndreas Pehrson <pehrsons@gmail.com>
Thu, 01 Dec 2016 11:48:06 +0100
changeset 446642 dd84437b9c101f473d804e92b821d9f76161360a
parent 446641 48194d50f88c8645847245af97b71e819e6a9bdc
child 446643 591f2f2ec129adb8a172b86a2ca5e878d5ffae39
push id37837
push userbmo:pehrson@telenordigital.com
push dateThu, 01 Dec 2016 17:14:18 +0000
reviewersjesup, bwc
bugs1320101
milestone53.0a1
Bug 1320101 - Differentiate between b=TIAS and simulcast stream max-br. r?jesup, r?bwc MozReview-Commit-ID: HPnOvwtawwV
media/webrtc/signaling/src/jsep/JsepTrack.cpp
media/webrtc/signaling/src/jsep/JsepTrack.h
media/webrtc/signaling/src/jsep/JsepTrackEncoding.h
media/webrtc/signaling/src/media-conduit/CodecConfig.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.h
media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
media/webrtc/signaling/test/mediaconduit_unittests.cpp
--- a/media/webrtc/signaling/src/jsep/JsepTrack.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepTrack.cpp
@@ -256,16 +256,19 @@ JsepTrack::FindConstraints(const std::st
 }
 
 void
 JsepTrack::CreateEncodings(
     const SdpMediaSection& remote,
     const std::vector<JsepCodecDescription*>& negotiatedCodecs,
     JsepTrackNegotiatedDetails* negotiatedDetails)
 {
+  negotiatedDetails->mTias = remote.GetBandwidth("TIAS");
+  // TODO add support for b=AS if TIAS is not set (bug 976521)
+
   std::vector<SdpRidAttributeList::Rid> rids;
   GetRids(remote, sdp::kRecv, &rids); // Get rids we will send
   NegotiateRids(rids, &mJsEncodeConstraints);
   if (rids.empty()) {
     // Add dummy value with an empty id to make sure we get a single unicast
     // stream.
     rids.push_back(SdpRidAttributeList::Rid());
   }
@@ -289,18 +292,16 @@ JsepTrack::CreateEncodings(
     // If we end up supporting params for rid, we would handle that here.
 
     // Incorporate the corresponding JS encoding constraints, if they exist
     for (const JsConstraints& jsConstraints : mJsEncodeConstraints) {
       if (jsConstraints.rid == rids[i].id) {
         encoding->mConstraints = jsConstraints.constraints;
       }
     }
-
-    encoding->UpdateMaxBitrate(remote);
   }
 }
 
 std::vector<JsepCodecDescription*>
 JsepTrack::GetCodecClones() const
 {
   std::vector<JsepCodecDescription*> clones;
   for (const JsepCodecDescription* codec : mPrototypeCodecs.values) {
--- a/media/webrtc/signaling/src/jsep/JsepTrack.h
+++ b/media/webrtc/signaling/src/jsep/JsepTrack.h
@@ -23,16 +23,20 @@
 #include "signaling/src/sdp/SdpMediaSection.h"
 #include "signaling/src/common/PtrVector.h"
 
 namespace mozilla {
 
 class JsepTrackNegotiatedDetails
 {
 public:
+  JsepTrackNegotiatedDetails() :
+    mTias(0)
+  {}
+
   size_t
   GetEncodingCount() const
   {
     return mEncodings.values.size();
   }
 
   const JsepTrackEncoding&
   GetEncoding(size_t index) const
@@ -51,22 +55,28 @@ public:
     return nullptr;
   }
 
   std::vector<uint8_t> GetUniquePayloadTypes() const
   {
     return mUniquePayloadTypes;
   }
 
+  uint32_t GetTias() const
+  {
+    return mTias;
+  }
+
 private:
   friend class JsepTrack;
 
   std::map<std::string, SdpExtmapAttributeList::Extmap> mExtmap;
   std::vector<uint8_t> mUniquePayloadTypes;
   PtrVector<JsepTrackEncoding> mEncodings;
+  uint32_t mTias; // bits per second
 };
 
 class JsepTrack
 {
 public:
   JsepTrack(mozilla::SdpMediaSection::MediaType type,
             const std::string& streamid,
             const std::string& trackid,
--- a/media/webrtc/signaling/src/jsep/JsepTrackEncoding.h
+++ b/media/webrtc/signaling/src/jsep/JsepTrackEncoding.h
@@ -34,26 +34,16 @@ public:
     for (const JsepCodecDescription* codec : mCodecs.values) {
       if (codec->mDefaultPt == format) {
         return true;
       }
     }
     return false;
   }
 
-  void UpdateMaxBitrate(const SdpMediaSection& remote)
-  {
-    uint32_t tias = remote.GetBandwidth("TIAS");
-    // select minimum of the two which is not zero
-    mConstraints.maxBr = std::min(tias ? tias : mConstraints.maxBr,
-                                  mConstraints.maxBr ? mConstraints.maxBr :
-                                                       tias);
-    // TODO add support for b=AS if TIAS is not set (bug 976521)
-  }
-
   EncodingConstraints mConstraints;
   std::string mRid;
 
 private:
   PtrVector<JsepCodecDescription> mCodecs;
 };
 }
 
--- a/media/webrtc/signaling/src/media-conduit/CodecConfig.h
+++ b/media/webrtc/signaling/src/media-conduit/CodecConfig.h
@@ -85,37 +85,36 @@ public:
   std::vector<std::string> mAckFbTypes;
   std::vector<std::string> mNackFbTypes;
   std::vector<std::string> mCcmFbTypes;
   // Don't pass mOtherFbTypes from JsepVideoCodecDescription because we'd have
   // to drag SdpRtcpFbAttributeList::Feedback along too.
   bool mRembFbSet;
   bool mFECFbSet;
 
-  EncodingConstraints mEncodingConstraints;
+  uint32_t mTias;
   struct SimulcastEncoding {
     std::string rid;
     EncodingConstraints constraints;
   };
   std::vector<SimulcastEncoding> mSimulcastEncodings;
   std::string mSpropParameterSets;
   uint8_t mProfile;
   uint8_t mConstraints;
   uint8_t mLevel;
   uint8_t mPacketizationMode;
   // TODO: add external negotiated SPS/PPS
 
   VideoCodecConfig(int type,
                    std::string name,
-                   const EncodingConstraints& constraints,
                    const struct VideoCodecConfigH264 *h264 = nullptr) :
     mType(type),
     mName(name),
     mFECFbSet(false),
-    mEncodingConstraints(constraints),
+    mTias(0),
     mProfile(0x42),
     mConstraints(0xE0),
     mLevel(0x0C),
     mPacketizationMode(1)
   {
     if (h264) {
       mProfile = (h264->profile_level_id & 0x00FF0000) >> 16;
       mConstraints = (h264->profile_level_id & 0x0000FF00) >> 8;
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -700,17 +700,17 @@ WebrtcVideoConduit::ConfigureSendMediaCo
       video_codec.resolution_divisor = 1; // We could try using it to handle odd resolutions
     }
 #else
     video_codec.resolution_divisor = 1; // We could try using it to handle odd resolutions
 #endif
     video_codec.qpMax = 56;
     video_codec.numberOfSimulcastStreams = 1;
     video_codec.simulcastStream[0].jsScaleDownBy =
-        codecConfig->mEncodingConstraints.scaleDownBy;
+        codecConfig->mSimulcastEncodings[0].constraints.scaleDownBy;
     video_codec.mode = mCodecMode;
 
     codecFound = true;
   } else {
     // we should be good here to set the new codec.
     for(int idx=0; idx < mPtrViECodec->NumberOfCodecs(); idx++)
     {
       if(0 == mPtrViECodec->GetCodec(idx, video_codec))
@@ -1246,29 +1246,29 @@ WebrtcVideoConduit::SelectSendResolution
 {
   mCodecMutex.AssertCurrentThreadOwns();
   // XXX This will do bandwidth-resolution adaptation as well - bug 877954
 
   mLastWidth = width;
   mLastHeight = height;
   // Enforce constraints
   if (mCurSendCodecConfig) {
-    uint16_t max_width = mCurSendCodecConfig->mEncodingConstraints.maxWidth;
-    uint16_t max_height = mCurSendCodecConfig->mEncodingConstraints.maxHeight;
+    uint16_t max_width = mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxWidth;
+    uint16_t max_height = mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxHeight;
     if (max_width || max_height) {
       max_width = max_width ? max_width : UINT16_MAX;
       max_height = max_height ? max_height : UINT16_MAX;
       ConstrainPreservingAspectRatio(max_width, max_height, &width, &height);
     }
 
     // Limit resolution to max-fs while keeping same aspect ratio as the
     // incoming image.
-    if (mCurSendCodecConfig->mEncodingConstraints.maxFs)
+    if (mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFs)
     {
-      uint32_t max_fs = mCurSendCodecConfig->mEncodingConstraints.maxFs;
+      uint32_t max_fs = mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFs;
       unsigned int cur_fs, mb_width, mb_height, mb_max;
 
       // Could we make this simpler by picking the larger of width and height,
       // calculating a max for just that value based on the scale parameter,
       // and then let ConstrainPreservingAspectRatio do the rest?
       mb_width = (width + 15) >> 4;
       mb_height = (height + 15) >> 4;
 
@@ -1494,33 +1494,33 @@ WebrtcVideoConduit::ReconfigureSendCodec
 // Invoked under lock of mCodecMutex!
 unsigned int
 WebrtcVideoConduit::SelectSendFrameRate(unsigned int framerate) const
 {
   mCodecMutex.AssertCurrentThreadOwns();
   unsigned int new_framerate = framerate;
 
   // Limit frame rate based on max-mbps
-  if (mCurSendCodecConfig && mCurSendCodecConfig->mEncodingConstraints.maxMbps)
+  if (mCurSendCodecConfig && mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxMbps)
   {
     unsigned int cur_fs, mb_width, mb_height, max_fps;
 
     mb_width = (mSendingWidth + 15) >> 4;
     mb_height = (mSendingHeight + 15) >> 4;
 
     cur_fs = mb_width * mb_height;
     if (cur_fs > 0) { // in case no frames have been sent
-      max_fps = mCurSendCodecConfig->mEncodingConstraints.maxMbps/cur_fs;
+      max_fps = mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxMbps/cur_fs;
       if (max_fps < mSendingFramerate) {
         new_framerate = max_fps;
       }
 
-      if (mCurSendCodecConfig->mEncodingConstraints.maxFps != 0 &&
-          mCurSendCodecConfig->mEncodingConstraints.maxFps < mSendingFramerate) {
-        new_framerate = mCurSendCodecConfig->mEncodingConstraints.maxFps;
+      if (mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFps != 0 &&
+          mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFps < mSendingFramerate) {
+        new_framerate = mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFps;
       }
     }
   }
   return new_framerate;
 }
 
 MediaConduitErrorCode
 WebrtcVideoConduit::SetExternalSendCodec(VideoCodecConfig* config,
@@ -1958,42 +1958,42 @@ WebrtcVideoConduit::CodecConfigToWebRTCC
     PL_strncpyz(cinst.plName, "I420", sizeof(cinst.plName));
   } else {
     cinst.codecType = webrtc::kVideoCodecUnknown;
     PL_strncpyz(cinst.plName, "Unknown", sizeof(cinst.plName));
   }
 
   // width/height will be overridden on the first frame; they must be 'sane' for
   // SetSendCodec()
-  if (codecInfo->mEncodingConstraints.maxFps > 0) {
-    cinst.maxFramerate = codecInfo->mEncodingConstraints.maxFps;
+  if (codecInfo->mSimulcastEncodings[0].constraints.maxFps > 0) {
+    cinst.maxFramerate = codecInfo->mSimulcastEncodings[0].constraints.maxFps;
   } else {
     cinst.maxFramerate = DEFAULT_VIDEO_MAX_FRAMERATE;
   }
 
   // Defaults if rates aren't forced by pref.  Typically defaults are
   // overridden on the first video frame.
   cinst.minBitrate = mMinBitrate ? mMinBitrate : 200;
   cinst.startBitrate = mStartBitrate ? mStartBitrate : 300;
   cinst.targetBitrate = cinst.startBitrate;
-  cinst.maxBitrate = MinIgnoreZero(2000U, codecInfo->mEncodingConstraints.maxBr/1000);
+  cinst.maxBitrate = MinIgnoreZero(2000U, codecInfo->mTias/1000);
   // not mNegotiatedMaxBitrate! cinst.maxBitrate is the max for the codec, which will be overridden
   cinst.maxBitrate = MinIgnoreZero(cinst.maxBitrate, mPrefMaxBitrate);
 
   if (cinst.codecType == webrtc::kVideoCodecH264)
   {
 #ifdef MOZ_WEBRTC_OMX
     cinst.resolution_divisor = 16;
 #endif
     // cinst.codecSpecific.H264.profile = ?
     cinst.codecSpecific.H264.profile_byte = codecInfo->mProfile;
     cinst.codecSpecific.H264.constraints = codecInfo->mConstraints;
     cinst.codecSpecific.H264.level = codecInfo->mLevel;
     cinst.codecSpecific.H264.packetizationMode = codecInfo->mPacketizationMode;
-    if (codecInfo->mEncodingConstraints.maxMbps > 0) {
+    if (codecInfo->mSimulcastEncodings[0].constraints.maxMbps > 0) {
       // Not supported yet!
       CSFLogError(logTag,  "%s H.264 max_mbps not supported yet  ", __FUNCTION__);
     }
     // XXX parse the encoded SPS/PPS data
     // paranoia
     cinst.codecSpecific.H264.spsData = nullptr;
     cinst.codecSpecific.H264.spsLen = 0;
     cinst.codecSpecific.H264.ppsData = nullptr;
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -266,24 +266,24 @@ public:
   }
 
   unsigned short SendingHeight() override {
     return mSendingHeight;
   }
 
   unsigned int SendingMaxFs() override {
     if(mCurSendCodecConfig) {
-      return mCurSendCodecConfig->mEncodingConstraints.maxFs;
+      return mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFs;
     }
     return 0;
   }
 
   unsigned int SendingMaxFr() override {
     if(mCurSendCodecConfig) {
-      return mCurSendCodecConfig->mEncodingConstraints.maxFps;
+      return mCurSendCodecConfig->mSimulcastEncodings[0].constraints.maxFps;
     }
     return 0;
   }
 
   WebrtcVideoConduit();
   virtual ~WebrtcVideoConduit();
 
   MediaConduitErrorCode InitMain();
--- a/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
+++ b/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
@@ -138,18 +138,17 @@ JsepCodecDescToCodecConfig(const JsepCod
             spropSize);
     h264Config->sprop_parameter_sets[spropSize - 1] = '\0';
     h264Config->packetization_mode = desc.mPacketizationMode;
     h264Config->profile_level_id = desc.mProfileLevelId;
     h264Config->tias_bw = 0; // TODO. Issue 165.
   }
 
   VideoCodecConfig* configRaw;
-  configRaw = new VideoCodecConfig(
-      pt, desc.mName, desc.mConstraints, h264Config.get());
+  configRaw = new VideoCodecConfig(pt, desc.mName, h264Config.get());
 
   configRaw->mAckFbTypes = desc.mAckFbTypes;
   configRaw->mNackFbTypes = desc.mNackFbTypes;
   configRaw->mCcmFbTypes = desc.mCcmFbTypes;
   configRaw->mRembFbSet = desc.RtcpFbRembIsSet();
   configRaw->mFECFbSet = desc.mFECEnabled;
 
   *aConfig = configRaw;
@@ -162,25 +161,28 @@ NegotiatedDetailsToVideoCodecConfigs(con
 {
   std::vector<JsepCodecDescription*> codecs(GetCodecs(aDetails));
   for (const JsepCodecDescription* codec : codecs) {
     VideoCodecConfig* config;
     if (NS_FAILED(JsepCodecDescToCodecConfig(*codec, &config))) {
       return NS_ERROR_INVALID_ARG;
     }
 
+    config->mTias = aDetails.GetTias();
+
     for (size_t i = 0; i < aDetails.GetEncodingCount(); ++i) {
       const JsepTrackEncoding& jsepEncoding(aDetails.GetEncoding(i));
       if (jsepEncoding.HasFormat(codec->mDefaultPt)) {
         VideoCodecConfig::SimulcastEncoding encoding;
         encoding.rid = jsepEncoding.mRid;
         encoding.constraints = jsepEncoding.mConstraints;
         config->mSimulcastEncodings.push_back(encoding);
       }
     }
+
     aConfigs->values.push_back(config);
   }
 
   return NS_OK;
 }
 
 // Accessing the PCMedia should be safe here because we shouldn't
 // have enqueued this function unless it was still active and
--- a/media/webrtc/signaling/test/mediaconduit_unittests.cpp
+++ b/media/webrtc/signaling/test/mediaconduit_unittests.cpp
@@ -640,20 +640,19 @@ class TransportConduitTest : public ::te
     // attach the transport and renderer to video-conduit
     err = mVideoSession2->AttachRenderer(mVideoRenderer);
     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
     err = mVideoSession->SetTransmitterTransport(mVideoTransport);
     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
     err = mVideoSession2->SetReceiverTransport(mVideoTransport);
     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
 
-    mozilla::EncodingConstraints constraints;
     //configure send and recv codecs on theconduit
-    mozilla::VideoCodecConfig cinst1(120, "VP8", constraints);
-    mozilla::VideoCodecConfig cinst2(124, "I420", constraints);
+    mozilla::VideoCodecConfig cinst1(120, "VP8");
+    mozilla::VideoCodecConfig cinst2(124, "I420");
 
 
     std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
     rcvCodecList.push_back(&cinst1);
     rcvCodecList.push_back(&cinst2);
 
     err = mVideoSession->ConfigureSendMediaCodec(
         send_vp8 ? &cinst1 : &cinst2);
@@ -726,36 +725,35 @@ class TransportConduitTest : public ::te
 
     std::vector<mozilla::VideoCodecConfig* > rcvCodecList;
 
     //Same APIs
     cerr << "   *************************************************" << endl;
     cerr << "    1. Same Codec (VP8) Repeated Twice " << endl;
     cerr << "   *************************************************" << endl;
 
-    mozilla::EncodingConstraints constraints;
-    mozilla::VideoCodecConfig cinst1(120, "VP8", constraints);
-    mozilla::VideoCodecConfig cinst2(120, "VP8", constraints);
+    mozilla::VideoCodecConfig cinst1(120, "VP8");
+    mozilla::VideoCodecConfig cinst2(120, "VP8");
     rcvCodecList.push_back(&cinst1);
     rcvCodecList.push_back(&cinst2);
     err = videoSession->ConfigureRecvMediaCodecs(rcvCodecList);
     EXPECT_NE(err,mozilla::kMediaConduitNoError);
     rcvCodecList.pop_back();
     rcvCodecList.pop_back();
 
 
     PR_Sleep(PR_SecondsToInterval(2));
     cerr << "   *************************************************" << endl;
     cerr << "    2. Codec With Invalid Payload Names " << endl;
     cerr << "   *************************************************" << endl;
     cerr << "   Setting payload 1 with name: I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676" << endl;
     cerr << "   Setting payload 2 with name of zero length" << endl;
 
-    mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676", constraints);
-    mozilla::VideoCodecConfig cinst4(124, "", constraints);
+    mozilla::VideoCodecConfig cinst3(124, "I4201234tttttthhhyyyy89087987y76t567r7756765rr6u6676");
+    mozilla::VideoCodecConfig cinst4(124, "");
 
     rcvCodecList.push_back(&cinst3);
     rcvCodecList.push_back(&cinst4);
 
     err = videoSession->ConfigureRecvMediaCodecs(rcvCodecList);
     EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
     rcvCodecList.pop_back();
     rcvCodecList.pop_back();
@@ -829,20 +827,21 @@ class TransportConduitTest : public ::te
 
     // Get pointer to VideoSessionConduit.
     mozilla::SyncRunnable::DispatchToThread(gMainThread,
                                             WrapRunnableNMRet(&mVideoSession,
                                                 &mozilla::VideoSessionConduit::Create));
     if( !mVideoSession )
       ASSERT_NE(mVideoSession, (void*)nullptr);
 
-    mozilla::EncodingConstraints constraints;
-    constraints.maxFs = max_fs;
+    mozilla::VideoCodecConfig::SimulcastEncoding stream;
+    stream.constraints.maxFs = max_fs;
     // Configure send codecs on the conduit.
-    mozilla::VideoCodecConfig cinst1(120, "VP8", constraints);
+    mozilla::VideoCodecConfig cinst1(120, "VP8");
+    cinst1.mSimulcastEncodings.push_back(stream);
 
     err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
     err = mVideoSession->StartTransmitting();
     ASSERT_EQ(mozilla::kMediaConduitNoError, err);
 
     // Send one frame.
     MOZ_ASSERT(!(orig_width & 1));
@@ -969,18 +968,17 @@ class TransportConduitTest : public ::te
       }
     }
     cerr << endl;
  }
 
   void SetGmpCodecs() {
     mExternalEncoder = mozilla::GmpVideoCodec::CreateEncoder();
     mExternalDecoder = mozilla::GmpVideoCodec::CreateDecoder();
-    mozilla::EncodingConstraints constraints;
-    mozilla::VideoCodecConfig config(124, "H264", constraints);
+    mozilla::VideoCodecConfig config(124, "H264");
     mVideoSession->SetExternalSendCodec(&config, mExternalEncoder);
     mVideoSession2->SetExternalRecvCodec(&config, mExternalDecoder);
   }
 
  private:
   //Audio Conduit Test Objects
   RefPtr<mozilla::AudioSessionConduit> mAudioSession;
   RefPtr<mozilla::AudioSessionConduit> mAudioSession2;