Bug 1288904: Clean up RID header extension support r=jesup,drno
authorRandell Jesup <rjesup@jesup.org>
Fri, 23 Sep 2016 21:55:08 -0400
changeset 315237 27b9a320f8d7b7a573a847a9e9db3c657fa4ec88
parent 315236 5880da58e1447162590d06196a875bb373aafe0c
child 315238 b0be7d1b7a9acb28c6f2e4b0b580df805bbadb8b
push id32563
push userihsiao@mozilla.com
push dateMon, 26 Sep 2016 11:18:33 +0000
treeherderautoland@eb840c87b5fd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, drno
bugs1288904
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1288904: Clean up RID header extension support r=jesup,drno
media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
media/webrtc/signaling/src/media-conduit/MediaConduitInterface.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/jsep_session_unittest.cpp
media/webrtc/trunk/webrtc/config.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
media/webrtc/trunk/webrtc/video/call.cc
media/webrtc/trunk/webrtc/video/video_send_stream.cc
media/webrtc/trunk/webrtc/video_engine/vie_channel.cc
media/webrtc/trunk/webrtc/video_engine/vie_channel.h
media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc
media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc
--- a/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
+++ b/media/webrtc/signaling/src/jsep/JsepSessionImpl.cpp
@@ -2206,16 +2206,18 @@ JsepSessionImpl::SetupDefaultCodecs()
   // codecs.  Note: only uses the video codecs.
   red->UpdateRedundantEncodings(mSupportedCodecs.values);
 }
 
 void
 JsepSessionImpl::SetupDefaultRtpExtensions()
 {
   AddAudioRtpExtension("urn:ietf:params:rtp-hdrext:ssrc-audio-level");
+  AddAudioRtpExtension("urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
+  AddVideoRtpExtension("urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
 }
 
 void
 JsepSessionImpl::SetState(JsepSignalingState state)
 {
   if (state == mState)
     return;
 
--- a/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
+++ b/media/webrtc/signaling/src/media-conduit/MediaConduitInterface.h
@@ -347,16 +347,24 @@ public:
    * Set an external decoder
    * @param decoder
    * @result: on success, we will use the specified decoder
    */
   virtual MediaConduitErrorCode SetExternalRecvCodec(VideoCodecConfig* config,
                                                      VideoDecoder* decoder) = 0;
 
   /**
+   * Function to enable the RTP Stream ID (RID) extension
+   * @param enabled: enable extension
+   * @param id: id to be used for this rtp header extension
+   * NOTE: See VideoConduit for more information
+   */
+  virtual MediaConduitErrorCode EnableRTPStreamIdExtension(bool enabled, uint8_t id) = 0;
+
+  /**
    * These methods allow unit tests to double-check that the
    * max-fs and max-fr related settings are as expected.
    */
   virtual unsigned short SendingWidth() = 0;
 
   virtual unsigned short SendingHeight() = 0;
 
   virtual unsigned int SendingMaxFs() = 0;
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -90,16 +90,18 @@ WebrtcVideoConduit::WebrtcVideoConduit()
   mLastFramerateTenths(DEFAULT_VIDEO_MAX_FRAMERATE*10),
   mNumReceivingStreams(1),
   mVideoLatencyTestEnable(false),
   mVideoLatencyAvg(0),
   mMinBitrate(0),
   mStartBitrate(0),
   mMaxBitrate(0),
   mMinBitrateEstimate(0),
+  mRtpStreamIdEnabled(false),
+  mRtpStreamIdExtId(0),
   mCodecMode(webrtc::kRealtimeVideo)
 {}
 
 WebrtcVideoConduit::~WebrtcVideoConduit()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   CSFLogDebug(logTag,  "%s ", __FUNCTION__);
 
@@ -656,16 +658,19 @@ WebrtcVideoConduit::ConfigureSendMediaCo
     }
   }
 
   condError = StopTransmitting();
   if (condError != kMediaConduitNoError) {
     return condError;
   }
 
+  if (mRtpStreamIdEnabled) {
+    video_codec.ridId = mRtpStreamIdExtId;
+  }
   if (mExternalSendCodec &&
       codecConfig->mType == mExternalSendCodec->mType) {
     CSFLogError(logTag, "%s Configuring External H264 Send Codec", __FUNCTION__);
 
     // width/height will be overridden on the first frame
     video_codec.width = 320;
     video_codec.height = 240;
 #ifdef MOZ_WEBRTC_OMX
@@ -1355,16 +1360,20 @@ WebrtcVideoConduit::ReconfigureSendCodec
     CSFLogError(logTag, "%s: GetSendCodec failed, err %d", __FUNCTION__, err);
     return NS_ERROR_FAILURE;
   }
 
   CSFLogDebug(logTag,
               "%s: Requesting resolution change to %ux%u (from %ux%u)",
               __FUNCTION__, width, height, vie_codec.width, vie_codec.height);
 
+  if (mRtpStreamIdEnabled) {
+    vie_codec.ridId = mRtpStreamIdExtId;
+  }
+
   vie_codec.width = width;
   vie_codec.height = height;
   vie_codec.maxFramerate = mSendingFramerate;
   SelectBitrates(vie_codec.width, vie_codec.height, 0,
                  mLastFramerateTenths,
                  vie_codec.minBitrate,
                  vie_codec.startBitrate,
                  vie_codec.maxBitrate);
@@ -1507,16 +1516,23 @@ WebrtcVideoConduit::SetExternalRecvCodec
     mExternalRecvCodecHandle = decoder;
     mExternalRecvCodec = new VideoCodecConfig(*config);
     return kMediaConduitNoError;
   }
   return kMediaConduitInvalidReceiveCodec;
 }
 
 MediaConduitErrorCode
+WebrtcVideoConduit::EnableRTPStreamIdExtension(bool enabled, uint8_t id) {
+  mRtpStreamIdEnabled = enabled;
+  mRtpStreamIdExtId = id;
+  return kMediaConduitNoError;
+}
+
+MediaConduitErrorCode
 WebrtcVideoConduit::SendVideoFrame(unsigned char* video_frame,
                                    unsigned int video_frame_length,
                                    unsigned short width,
                                    unsigned short height,
                                    VideoType video_type,
                                    uint64_t capture_time)
 {
 
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -208,16 +208,20 @@ public:
 
   /**
    * Set an external decoder object |decoder| to the payload type |pltype|
    * for receiver side codec.
    */
   virtual MediaConduitErrorCode SetExternalRecvCodec(VideoCodecConfig* config,
                                                      VideoDecoder* decoder) override;
 
+  /**
+  * Enables use of Rtp Stream Id, and sets the extension ID.
+  */
+  virtual MediaConduitErrorCode EnableRTPStreamIdExtension(bool enabled, uint8_t id) override;
 
   /**
    * Webrtc transport implementation to send and receive RTP packet.
    * VideoConduit registers itself as ExternalTransport to the VideoEngine
    */
   virtual int SendPacket(int channel, const void *data, size_t len) override;
 
   /**
@@ -395,16 +399,19 @@ private:
   unsigned short mNumReceivingStreams;
   bool mVideoLatencyTestEnable;
   uint64_t mVideoLatencyAvg;
   uint32_t mMinBitrate;
   uint32_t mStartBitrate;
   uint32_t mMaxBitrate;
   uint32_t mMinBitrateEstimate;
 
+  bool mRtpStreamIdEnabled;
+  uint8_t mRtpStreamIdExtId;
+
   static const unsigned int sAlphaNum = 7;
   static const unsigned int sAlphaDen = 8;
   static const unsigned int sRoundingPadding = 1024;
 
   RefPtr<WebrtcAudioConduit> mSyncedTo;
 
   nsAutoPtr<VideoCodecConfig> mExternalSendCodec;
   nsAutoPtr<VideoCodecConfig> mExternalRecvCodec;
--- a/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
+++ b/media/webrtc/signaling/src/peerconnection/MediaPipelineFactory.cpp
@@ -858,18 +858,33 @@ MediaPipelineFactory::GetOrCreateVideoCo
     }
 
     // TODO(bug 1018791): This really should be checked sooner
     if (EnsureExternalCodec(*conduit, configs.values[0], true)) {
       MOZ_MTLOG(ML_ERROR, "External codec not available");
       return NS_ERROR_FAILURE;
     }
 
+
     auto error = conduit->ConfigureSendMediaCodec(configs.values[0]);
 
+    const SdpExtmapAttributeList::Extmap* rtpStreamIdExt =
+        aTrack.GetNegotiatedDetails()->GetExt(
+            "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id");
+
+    if (rtpStreamIdExt) {
+      MOZ_MTLOG(ML_DEBUG, "Calling EnableRTPSenderIdExtension");
+      error = conduit->EnableRTPStreamIdExtension(true, rtpStreamIdExt->entry);
+
+      if (error) {
+        MOZ_MTLOG(ML_ERROR, "EnableRTPSenderIdExtension failed: " << error);
+        return NS_ERROR_FAILURE;
+      }
+    }
+
     if (error) {
       MOZ_MTLOG(ML_ERROR, "ConfigureSendMediaCodec failed: " << error);
       return NS_ERROR_FAILURE;
     }
   }
 
   *aConduitp = conduit;
 
--- a/media/webrtc/signaling/test/jsep_session_unittest.cpp
+++ b/media/webrtc/signaling/test/jsep_session_unittest.cpp
@@ -3469,54 +3469,61 @@ TEST_F(JsepSessionTest, TestIceOptions)
   ASSERT_EQ("trickle", mSessionAns.GetIceOptions()[0]);
 }
 
 TEST_F(JsepSessionTest, TestExtmap)
 {
   AddTracks(mSessionOff, "audio");
   AddTracks(mSessionAns, "audio");
   // ssrc-audio-level will be extmap 1 for both
-  mSessionOff.AddAudioRtpExtension("foo"); // Default mapping of 2
-  mSessionOff.AddAudioRtpExtension("bar"); // Default mapping of 3
-  mSessionAns.AddAudioRtpExtension("bar"); // Default mapping of 2
+  // rtp-stream-id will be extmap 2 for both
+  mSessionOff.AddAudioRtpExtension("foo"); // Default mapping of 3
+  mSessionOff.AddAudioRtpExtension("bar"); // Default mapping of 4
+  mSessionAns.AddAudioRtpExtension("bar"); // Default mapping of 3
   std::string offer = CreateOffer();
   SetLocalOffer(offer, CHECK_SUCCESS);
   SetRemoteOffer(offer, CHECK_SUCCESS);
   std::string answer = CreateAnswer();
   SetLocalAnswer(answer, CHECK_SUCCESS);
   SetRemoteAnswer(answer, CHECK_SUCCESS);
 
   UniquePtr<Sdp> parsedOffer(Parse(offer));
   ASSERT_EQ(1U, parsedOffer->GetMediaSectionCount());
 
   auto& offerMediaAttrs = parsedOffer->GetMediaSection(0).GetAttributeList();
   ASSERT_TRUE(offerMediaAttrs.HasAttribute(SdpAttribute::kExtmapAttribute));
   auto& offerExtmap = offerMediaAttrs.GetExtmap().mExtmaps;
-  ASSERT_EQ(3U, offerExtmap.size());
+  ASSERT_EQ(4U, offerExtmap.size());
   ASSERT_EQ("urn:ietf:params:rtp-hdrext:ssrc-audio-level",
       offerExtmap[0].extensionname);
   ASSERT_EQ(1U, offerExtmap[0].entry);
-  ASSERT_EQ("foo", offerExtmap[1].extensionname);
+  ASSERT_EQ("urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id",
+      offerExtmap[1].extensionname);
   ASSERT_EQ(2U, offerExtmap[1].entry);
-  ASSERT_EQ("bar", offerExtmap[2].extensionname);
+  ASSERT_EQ("foo", offerExtmap[2].extensionname);
   ASSERT_EQ(3U, offerExtmap[2].entry);
+  ASSERT_EQ("bar", offerExtmap[3].extensionname);
+  ASSERT_EQ(4U, offerExtmap[3].entry);
 
   UniquePtr<Sdp> parsedAnswer(Parse(answer));
   ASSERT_EQ(1U, parsedAnswer->GetMediaSectionCount());
 
   auto& answerMediaAttrs = parsedAnswer->GetMediaSection(0).GetAttributeList();
   ASSERT_TRUE(answerMediaAttrs.HasAttribute(SdpAttribute::kExtmapAttribute));
   auto& answerExtmap = answerMediaAttrs.GetExtmap().mExtmaps;
-  ASSERT_EQ(2U, answerExtmap.size());
+  ASSERT_EQ(3U, answerExtmap.size());
   ASSERT_EQ("urn:ietf:params:rtp-hdrext:ssrc-audio-level",
       answerExtmap[0].extensionname);
   ASSERT_EQ(1U, answerExtmap[0].entry);
+  ASSERT_EQ("urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id",
+      answerExtmap[1].extensionname);
+  ASSERT_EQ(2U, answerExtmap[1].entry);
   // We ensure that the entry for "bar" matches what was in the offer
-  ASSERT_EQ("bar", answerExtmap[1].extensionname);
-  ASSERT_EQ(3U, answerExtmap[1].entry);
+  ASSERT_EQ("bar", answerExtmap[2].extensionname);
+  ASSERT_EQ(4U, answerExtmap[2].entry);
 }
 
 TEST_F(JsepSessionTest, TestRtcpFbStar)
 {
   AddTracks(mSessionOff, "video");
   AddTracks(mSessionAns, "video");
 
   std::string offer = CreateOffer();
--- a/media/webrtc/trunk/webrtc/config.h
+++ b/media/webrtc/trunk/webrtc/config.h
@@ -10,16 +10,17 @@
 
 // TODO(pbos): Move Config from common.h to here.
 
 #ifndef WEBRTC_CONFIG_H_
 #define WEBRTC_CONFIG_H_
 
 #include <string>
 #include <vector>
+#include <algorithm>
 
 #include "webrtc/common_types.h"
 #include "webrtc/typedefs.h"
 
 namespace webrtc {
 
 // Settings for NACK, see RFC 4585 for details.
 struct NackConfig {
@@ -47,16 +48,17 @@ struct FecConfig {
 struct RtpExtension {
   RtpExtension(const std::string& name, int id) : name(name), id(id) {}
   std::string ToString() const;
   static bool IsSupported(const std::string& name);
 
   static const char* kTOffset;
   static const char* kAbsSendTime;
   static const char* kVideoRotation;
+  static const char* kRtpStreamId;
   std::string name;
   int id;
 };
 
 struct VideoStream {
   VideoStream();
   ~VideoStream();
   std::string ToString() const;
@@ -66,16 +68,28 @@ struct VideoStream {
   int max_framerate;
 
   int min_bitrate_bps;
   int target_bitrate_bps;
   int max_bitrate_bps;
 
   int max_qp;
 
+  char rid[kRIDSize+1];
+
+  const std::string Rid() const {
+    return std::string(rid);
+  }
+
+  void SetRid(const std::string& aRid) {
+    static_assert(sizeof(rid) > kRIDSize,
+      "mRid must be large enought to hold a RID + null termination");
+    strncpy(&rid[0], aRid.c_str(), std::min((size_t)kRIDSize, aRid.length()));
+    rid[kRIDSize] = 0;
+  }
   // Bitrate thresholds for enabling additional temporal layers. Since these are
   // thresholds in between layers, we have one additional layer. One threshold
   // gives two temporal layers, one below the threshold and one above, two give
   // three, and so on.
   // The VideoEncoder may redistribute bitrates over the temporal layers so a
   // bitrate threshold of 100k and an estimate of 105k does not imply that we
   // get 100k in one temporal layer and 5k in the other, just that the bitrate
   // in the first temporal layer should not exceed 100k.
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h
@@ -76,17 +76,17 @@ enum StorageType {
 
 enum RTPExtensionType {
   kRtpExtensionNone,
   kRtpExtensionTransmissionTimeOffset,
   kRtpExtensionAudioLevel,
   kRtpExtensionAbsoluteSendTime,
   kRtpExtensionVideoRotation,
   kRtpExtensionTransportSequenceNumber,
-  kRtpExtensionRID,
+  kRtpExtensionRtpStreamId,
 };
 
 enum RTCPAppSubTypes
 {
     kAppSubtypeBwe     = 0x00
 };
 
 enum RTCPPacketType
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_header_extension.h
@@ -22,17 +22,17 @@ const uint16_t kRtpOneByteHeaderExtensio
 
 const size_t kRtpOneByteHeaderLength = 4;
 const size_t kTransmissionTimeOffsetLength = 4;
 const size_t kAudioLevelLength = 2;
 const size_t kAbsoluteSendTimeLength = 4;
 const size_t kVideoRotationLength = 2;
 const size_t kTransportSequenceNumberLength = 3;
 // kRIDLength is variable
-const size_t kRIDLength = 4; // max 1-byte header extension length
+const size_t kRtpStreamIdLength = 4; // max 1-byte header extension length
 
 struct HeaderExtension {
   HeaderExtension(RTPExtensionType extension_type)
       : type(extension_type), length(0), active(true) {
     Init();
   }
 
   HeaderExtension(RTPExtensionType extension_type, bool active)
@@ -55,18 +55,18 @@ struct HeaderExtension {
         length = kAbsoluteSendTimeLength;
         break;
       case kRtpExtensionVideoRotation:
         length = kVideoRotationLength;
         break;
       case kRtpExtensionTransportSequenceNumber:
         length = kTransportSequenceNumberLength;
         break;
-      case kRtpExtensionRID:
-        length = kRIDLength;
+      case kRtpExtensionRtpStreamId:
+        length = kRtpStreamIdLength;
         break;
       default:
         assert(false);
     }
   }
 
   const RTPExtensionType type;
   uint8_t length;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
@@ -1229,17 +1229,17 @@ uint16_t RTPSender::BuildRTPHeaderExtens
         block_length = BuildAbsoluteSendTimeExtension(extension_data);
         break;
       case kRtpExtensionVideoRotation:
         block_length = BuildVideoRotationExtension(extension_data);
         break;
       case kRtpExtensionTransportSequenceNumber:
         block_length = BuildTransportSequenceNumberExtension(extension_data);
         break;
-      case kRtpExtensionRID:
+      case kRtpExtensionRtpStreamId:
         block_length = BuildRIDExtension(extension_data);
         break;
       default:
         assert(false);
     }
     total_block_length += block_length;
     type = rtp_header_extension_map_.Next(type);
   }
@@ -1417,19 +1417,20 @@ uint8_t RTPSender::BuildRIDExtension(
   //   0                   1                   2
   //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   //  |  ID   | L=?   |UTF-8 RID value......          |...
   //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
   // Get id defined by user.
   uint8_t id;
-  if (rtp_header_extension_map_.GetId(kRtpExtensionRID,
+  if (!rid_ ||
+    rtp_header_extension_map_.GetId(kRtpExtensionRtpStreamId,
                                       &id) != 0) {
-    // Not registered.
+    // No RtpStreamId or not registered
     return 0;
   }
   size_t pos = 0;
   // RID value is not null-terminated in header, so no +1
   const uint8_t len = strlen(rid_);
   data_buffer[pos++] = (id << 4) + len;
   memcpy(data_buffer + pos, rid_, len);
   pos += len;
--- a/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
+++ b/media/webrtc/trunk/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
@@ -92,17 +92,17 @@ uint32_t GetCurrentRTP(Clock* clock, uin
   local_clock->CurrentNtp(secs, frac);
   if (use_global_clock) {
     delete local_clock;
   }
   return ConvertNTPTimeToRTP(secs, frac, freq);
 }
 
 uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, uint32_t NTPfrac, uint32_t freq) {
-  float ftemp = (float)NTPfrac / (float)NTP_FRAC; 
+  float ftemp = (float)NTPfrac / (float)NTP_FRAC;
   uint32_t tmp = (uint32_t)(ftemp * freq);
  return NTPsec * freq + tmp;
 }
 
 uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) {
   int freq = 1000;
   float ftemp = (float)NTPfrac / (float)NTP_FRAC;
   uint32_t tmp = (uint32_t)(ftemp * freq);
@@ -485,17 +485,17 @@ void RtpHeaderParser::ParseOneByteExtens
           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
           uint16_t sequence_number = ptr[0] << 8;
           sequence_number += ptr[1];
           header.extension.transportSequenceNumber = sequence_number;
           header.extension.hasTransportSequenceNumber = true;
           break;
         }
-        case kRtpExtensionRID: {
+        case kRtpExtensionRtpStreamId: {
           //   0                   1                   2
           //   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           //  |  ID   | L=?   |UTF-8 RID value......          |...
           //  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 
           // TODO(jesup) - avoid allocating on each packet - high watermark the RID buffer?
           char* ptrRID = new char[len+1];
--- a/media/webrtc/trunk/webrtc/video/call.cc
+++ b/media/webrtc/trunk/webrtc/video/call.cc
@@ -37,21 +37,24 @@
 #include "webrtc/video_engine/include/vie_network.h"
 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
 
 namespace webrtc {
 const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
 const char* RtpExtension::kAbsSendTime =
     "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
 const char* RtpExtension::kVideoRotation = "urn:3gpp:video-orientation";
+const char* RtpExtension::kRtpStreamId =
+  "urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id";
 
 bool RtpExtension::IsSupported(const std::string& name) {
   return name == webrtc::RtpExtension::kTOffset ||
          name == webrtc::RtpExtension::kAbsSendTime ||
-         name == webrtc::RtpExtension::kVideoRotation;
+         name == webrtc::RtpExtension::kVideoRotation ||
+         name == webrtc::RtpExtension::kRtpStreamId;
 }
 
 VideoEncoder* VideoEncoder::Create(VideoEncoder::EncoderType codec_type) {
   switch (codec_type) {
     case kVp8:
       return VP8Encoder::Create();
     case kVp9:
       return VP9Encoder::Create();
--- a/media/webrtc/trunk/webrtc/video/video_send_stream.cc
+++ b/media/webrtc/trunk/webrtc/video/video_send_stream.cc
@@ -135,16 +135,18 @@ VideoSendStream::VideoSendStream(
     DCHECK_GE(id, 1);
     DCHECK_LE(id, 14);
     if (extension == RtpExtension::kTOffset) {
       CHECK_EQ(0, rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id));
     } else if (extension == RtpExtension::kAbsSendTime) {
       CHECK_EQ(0, rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id));
     } else if (extension == RtpExtension::kVideoRotation) {
       CHECK_EQ(0, rtp_rtcp_->SetSendVideoRotationStatus(channel_, true, id));
+    } else if (extension == RtpExtension::kRtpStreamId) {
+      RTC_CHECK_EQ(0, vie_channel_->SetSendRtpStreamId(true,id));
     } else {
       RTC_NOTREACHED() << "Registering unsupported RTP extension.";
     }
   }
 
   rtp_rtcp_->SetRembStatus(channel_, true, false);
 
   // Enable NACK, FEC or both.
--- a/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel.cc
@@ -363,46 +363,67 @@ int32_t ViEChannel::SetSendCodec(const V
   // set explicitly.
   bool restart_rtp = false;
   bool router_was_active = send_payload_router_->active();
   send_payload_router_->set_active(false);
   send_payload_router_->SetSendingRtpModules(std::list<RtpRtcp*>());
   packet_router_->RemoveRtpModule(rtp_rtcp_.get());
   for (RtpRtcp* module : simulcast_rtp_rtcp_)
     packet_router_->RemoveRtpModule(module);
-  if (rtp_rtcp_->Sending() && new_stream) {
+  // Set the RtpSenderId
+  rid_extension_id_ = video_codec.ridId;
+
+  if (rtp_rtcp_->Sending()) {
     restart_rtp = true;
     rtp_rtcp_->SetSendingStatus(false);
     int i = 0;
     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
          it != simulcast_rtp_rtcp_.end(); ++it, ++i) {
       (*it)->SetSendingStatus(false);
       (*it)->SetSendingMediaStatus(false);
       if (video_codec.simulcastStream[i].rid[0] != 0) {
         (*it)->RegisterSendRtpHeaderExtension(
-          kRtpExtensionRID, video_codec.ridId);
+          kRtpExtensionRtpStreamId, video_codec.ridId);
         (*it)->SetRID(video_codec.simulcastStream[i].rid);
       } else {
         (*it)->DeregisterSendRtpHeaderExtension(
-          kRtpExtensionRID);
+          kRtpExtensionRtpStreamId);
       }
     }
   }
 
   bool fec_enabled = false;
   uint8_t payload_type_red;
   uint8_t payload_type_fec;
   rtp_rtcp_->GenericFECStatus(fec_enabled, payload_type_red, payload_type_fec);
 
   std::vector<RtpRtcp*> registered_modules;
   std::vector<RtpRtcp*> deregistered_modules;
   {
     CriticalSectionScoped cs(rtp_rtcp_cs_.get());
 
     if (video_codec.numberOfSimulcastStreams > 0) {
+
+      // Set RTP Stream ID of primary stream
+      if (rid_extension_id_ != kInvalidRtpExtensionId) {
+        // Deregister in case the extension was previously enabled.
+        rtp_rtcp_->DeregisterSendRtpHeaderExtension(
+            kRtpExtensionRtpStreamId);
+        if (rtp_rtcp_->RegisterSendRtpHeaderExtension(
+                kRtpExtensionRtpStreamId,
+                rid_extension_id_) != 0) {
+          LOG(LS_WARNING) << "Register RID extension failed";
+        } else {
+          rtp_rtcp_->SetRID(video_codec.simulcastStream[0].rid);
+        }
+      } else {
+        rtp_rtcp_->DeregisterSendRtpHeaderExtension(
+            kRtpExtensionRtpStreamId);
+      }
+
       // Set correct bitrate to base layer.
       // Create our simulcast RTP modules.
       int num_modules_to_add =
           video_codec.numberOfSimulcastStreams - simulcast_rtp_rtcp_.size() - 1;
       if (num_modules_to_add < 0) {
         num_modules_to_add = 0;
       }
 
@@ -511,25 +532,27 @@ int32_t ViEChannel::SetSendCodec(const V
           }
         } else {
           rtp_rtcp->DeregisterSendRtpHeaderExtension(
               kRtpExtensionVideoRotation);
         }
         if (rid_extension_id_ != kInvalidRtpExtensionId) {
           // Deregister in case the extension was previously enabled.
           rtp_rtcp->DeregisterSendRtpHeaderExtension(
-              kRtpExtensionRID);
+              kRtpExtensionRtpStreamId);
           if (rtp_rtcp->RegisterSendRtpHeaderExtension(
-                  kRtpExtensionRID,
+                  kRtpExtensionRtpStreamId,
                   rid_extension_id_) != 0) {
             LOG(LS_WARNING) << "Register RID extension failed";
+          } else {
+            (*it)->SetRID(video_codec.simulcastStream[idx].rid);
           }
         } else {
           rtp_rtcp->DeregisterSendRtpHeaderExtension(
-              kRtpExtensionRID);
+              kRtpExtensionRtpStreamId);
         }
         rtp_rtcp->RegisterRtcpStatisticsCallback(
             rtp_rtcp_->GetRtcpStatisticsCallback());
         rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(
             rtp_rtcp_->GetSendChannelRtpStatisticsCallback());
       }
       // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old
       // modules can be deleted after this step.
@@ -984,44 +1007,44 @@ int ViEChannel::SetSendVideoRotationStat
   }
   return error;
 }
 
 int ViEChannel::SetReceiveVideoRotationStatus(bool enable, int id) {
   return vie_receiver_.SetReceiveVideoRotationStatus(enable, id) ? 0 : -1;
 }
 
-int ViEChannel::SetSendRIDStatus(bool enable, int id, const char *rid) {
+int ViEChannel::SetSendRtpStreamId(bool enable, int id, const char* rid) {
   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
   int error = 0;
   if (enable) {
     // Enable the extension, but disable possible old id to avoid errors.
     rid_extension_id_ = id;
     rtp_rtcp_->DeregisterSendRtpHeaderExtension(
-        kRtpExtensionRID);
+        kRtpExtensionRtpStreamId);
     error = rtp_rtcp_->RegisterSendRtpHeaderExtension(
-        kRtpExtensionRID, id);
+        kRtpExtensionRtpStreamId, id);
     rtp_rtcp_->SetRID(rid);
     // NOTE: simulcast streams must be set via the SetSendCodec() API
   } else {
     // Disable the extension.
     rid_extension_id_ = kInvalidRtpExtensionId;
     rtp_rtcp_->DeregisterSendRtpHeaderExtension(
-        kRtpExtensionRID);
+        kRtpExtensionRtpStreamId);
     // This may be overkill...
     for (std::list<RtpRtcp*>::iterator it = simulcast_rtp_rtcp_.begin();
          it != simulcast_rtp_rtcp_.end(); it++) {
       (*it)->DeregisterSendRtpHeaderExtension(
-          kRtpExtensionRID);
+          kRtpExtensionRtpStreamId);
     }
   }
   return error;
 }
 
-int ViEChannel::SetReceiveRIDStatus(bool enable, int id) {
+int ViEChannel::SetReceiveRtpStreamId(bool enable, int id) {
   return vie_receiver_.SetReceiveRIDStatus(enable, id) ? 0 : -1;
 }
 
 void ViEChannel::SetRtcpXrRrtrStatus(bool enable) {
   CriticalSectionScoped cs(rtp_rtcp_cs_.get());
   rtp_rtcp_->SetRtcpXrRrtrStatus(enable);
 }
 
--- a/media/webrtc/trunk/webrtc/video_engine/vie_channel.h
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_channel.h
@@ -133,18 +133,18 @@ class ViEChannel
   void EnableRemb(bool enable);
   int SetSendTimestampOffsetStatus(bool enable, int id);
   int SetReceiveTimestampOffsetStatus(bool enable, int id);
   int SetSendAbsoluteSendTimeStatus(bool enable, int id);
   int SetReceiveAbsoluteSendTimeStatus(bool enable, int id);
   bool GetReceiveAbsoluteSendTimeStatus() const;
   int SetSendVideoRotationStatus(bool enable, int id);
   int SetReceiveVideoRotationStatus(bool enable, int id);
-  int SetSendRIDStatus(bool enable, int id, const char *rid);
-  int SetReceiveRIDStatus(bool enable, int id);
+  int SetSendRtpStreamId(bool enable, int id, const char* rid);
+  int SetReceiveRtpStreamId(bool enable, int id);
   void SetRtcpXrRrtrStatus(bool enable);
   void SetTransmissionSmoothingStatus(bool enable);
   void EnableTMMBR(bool enable);
   int32_t EnableKeyFrameRequestCallback(const bool enable);
 
   // Sets SSRC for outgoing stream.
   int32_t SetSSRC(const uint32_t SSRC,
                   const StreamType usage,
--- a/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_receiver.cc
@@ -209,26 +209,26 @@ bool ViEReceiver::SetReceiveVideoRotatio
     return rtp_header_parser_->DeregisterRtpHeaderExtension(
         kRtpExtensionVideoRotation);
   }
 }
 
 bool ViEReceiver::SetReceiveRIDStatus(bool enable, int id) {
   if (enable) {
     if (rtp_header_parser_->RegisterRtpHeaderExtension(
-            kRtpExtensionRID, id)) {
+            kRtpExtensionRtpStreamId, id)) {
       receiving_rid_enabled_ = true;
       return true;
     } else {
       return false;
     }
   } else {
     receiving_rid_enabled_ = false;
     return rtp_header_parser_->DeregisterRtpHeaderExtension(
-        kRtpExtensionRID);
+        kRtpExtensionRtpStreamId);
   }
 }
 
 int ViEReceiver::ReceivedRTPPacket(const void* rtp_packet,
                                    size_t rtp_packet_length,
                                    const PacketTime& packet_time) {
   return InsertRTPPacket(static_cast<const uint8_t*>(rtp_packet),
                          rtp_packet_length, packet_time);
--- a/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc
+++ b/media/webrtc/trunk/webrtc/video_engine/vie_rtp_rtcp_impl.cc
@@ -706,17 +706,17 @@ int ViERTP_RTCPImpl::SetSendRIDStatus(in
                  << " enable: " << (enable ? "on" : "off") << " id: " << id << " RID: " << rid;
 
   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
   ViEChannel* vie_channel = cs.Channel(video_channel);
   if (!vie_channel) {
     shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
     return -1;
   }
-  if (vie_channel->SetSendRIDStatus(enable, id, rid) != 0) {
+  if (vie_channel->SetSendRtpStreamId(enable, id, rid) != 0) {
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
   return 0;
 }
 
 int ViERTP_RTCPImpl::SetReceiveRIDStatus(int video_channel,
                                          bool enable,
@@ -724,17 +724,17 @@ int ViERTP_RTCPImpl::SetReceiveRIDStatus
   LOG_F(LS_INFO) << "channel: " << video_channel
                  << " enable: " << (enable ? "on" : "off") << " id: " << id;
   ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
   ViEChannel* vie_channel = cs.Channel(video_channel);
   if (!vie_channel) {
     shared_data_->SetLastError(kViERtpRtcpInvalidChannelId);
     return -1;
   }
-  if (vie_channel->SetReceiveRIDStatus(enable, id) != 0) {
+  if (vie_channel->SetReceiveRtpStreamId(enable, id) != 0) {
     shared_data_->SetLastError(kViERtpRtcpUnknownError);
     return -1;
   }
   return 0;
 }
 
 int ViERTP_RTCPImpl::SetRtcpXrRrtrStatus(int video_channel, bool enable) {
   LOG_F(LS_INFO) << "channel: " << video_channel