Bug 1288904 - Clean up RID header extension support. r=jesup, r=drno, a=gchang
authorRandell Jesup <rjesup@jesup.org>
Fri, 23 Sep 2016 21:55:08 -0400
changeset 356102 2235c46ad1be7a13f7176b5573b743fb69a6be48
parent 356101 7f07acca81b92e382c90863c4c672f8feee86cf1
child 356103 bdff84e3875eef2c713550705ba0e629270e7a69
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, drno, gchang
bugs1288904
milestone51.0a2
Bug 1288904 - Clean up RID header extension support. r=jesup, r=drno, a=gchang
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
@@ -1369,16 +1374,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);
@@ -1521,16 +1530,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