Add streams() to RtpReceiverInterface and implementations.

This makes the receiver know about its associated set of streams, the
equivalent of the [[AssociatedRemoteMediaStreams]] slot in the spec,
https://w3c.github.io/webrtc-pc/#dfn-x%5B%5Bassociatedremotemediastreams%5D%5D

This does not change layers below peerconnection.cc. The streams are set
upon the receiver's construction and is not modified for the duration of
its lifetime.

When we support modifying the associated set of streams of a receiver
the receiver needs to know about it. The receiver's streams() should be
used in all places where a receiver's streams need to be known.

Bug: webrtc:8473
Change-Id: I31202973aed98e61fa9b6a78b52e815227b6c17d
Reviewed-on: https://webrtc-review.googlesource.com/22922
Reviewed-by: Peter Thatcher <pthatcher@webrtc.org>
Reviewed-by: Magnus Jedvert <magjed@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20825}
diff --git a/api/rtpreceiverinterface.h b/api/rtpreceiverinterface.h
index afb737b..311971d 100644
--- a/api/rtpreceiverinterface.h
+++ b/api/rtpreceiverinterface.h
@@ -94,6 +94,14 @@
 class RtpReceiverInterface : public rtc::RefCountInterface {
  public:
   virtual rtc::scoped_refptr<MediaStreamTrackInterface> track() const = 0;
+  // The list of streams that |track| is associated with. This is the same as
+  // the [[AssociatedRemoteMediaStreams]] internal slot in the spec.
+  // https://w3c.github.io/webrtc-pc/#dfn-x%5B%5Bassociatedremotemediastreams%5D%5D
+  // TODO(hbos): Make pure virtual as soon as Chromium's mock implements this.
+  virtual std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
+      const {
+    return std::vector<rtc::scoped_refptr<MediaStreamInterface>>();
+  }
 
   // Audio or video receiver?
   virtual cricket::MediaType media_type() const = 0;
@@ -130,6 +138,8 @@
 BEGIN_SIGNALING_PROXY_MAP(RtpReceiver)
   PROXY_SIGNALING_THREAD_DESTRUCTOR()
   PROXY_CONSTMETHOD0(rtc::scoped_refptr<MediaStreamTrackInterface>, track)
+  PROXY_CONSTMETHOD0(std::vector<rtc::scoped_refptr<MediaStreamInterface>>,
+                     streams)
   PROXY_CONSTMETHOD0(cricket::MediaType, media_type)
   PROXY_CONSTMETHOD0(std::string, id)
   PROXY_CONSTMETHOD0(RtpParameters, GetParameters);
diff --git a/ortc/ortcrtpreceiveradapter.cc b/ortc/ortcrtpreceiveradapter.cc
index b30f63c..ffa9387b 100644
--- a/ortc/ortcrtpreceiveradapter.cc
+++ b/ortc/ortcrtpreceiveradapter.cc
@@ -152,13 +152,14 @@
   switch (kind_) {
     case cricket::MEDIA_TYPE_AUDIO:
       internal_receiver_ =
-          new AudioRtpReceiver(rtc::CreateRandomUuid(), ssrc,
+          new AudioRtpReceiver(rtc::CreateRandomUuid(), {}, ssrc,
                                rtp_transport_controller_->voice_channel());
       break;
     case cricket::MEDIA_TYPE_VIDEO:
-      internal_receiver_ = new VideoRtpReceiver(
-          rtc::CreateRandomUuid(), rtp_transport_controller_->worker_thread(),
-          ssrc, rtp_transport_controller_->video_channel());
+      internal_receiver_ =
+          new VideoRtpReceiver(rtc::CreateRandomUuid(), {},
+                               rtp_transport_controller_->worker_thread(), ssrc,
+                               rtp_transport_controller_->video_channel());
       break;
     case cricket::MEDIA_TYPE_DATA:
       RTC_NOTREACHED();
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index e4864c9..b9091c7 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -2079,33 +2079,34 @@
 void PeerConnection::CreateAudioReceiver(
     MediaStreamInterface* stream,
     const RtpSenderInfo& remote_sender_info) {
+  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
+  streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
   rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
       receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
           signaling_thread(),
-          new AudioRtpReceiver(remote_sender_info.sender_id,
+          new AudioRtpReceiver(remote_sender_info.sender_id, streams,
                                remote_sender_info.first_ssrc, voice_channel()));
   stream->AddTrack(
       static_cast<AudioTrackInterface*>(receiver->internal()->track().get()));
   GetAudioTransceiver()->internal()->AddReceiver(receiver);
-  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
-  streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
-  observer_->OnAddTrack(receiver, streams);
+  observer_->OnAddTrack(receiver, std::move(streams));
 }
 
 void PeerConnection::CreateVideoReceiver(
     MediaStreamInterface* stream,
     const RtpSenderInfo& remote_sender_info) {
+  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
+  streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
   rtc::scoped_refptr<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
       receiver = RtpReceiverProxyWithInternal<RtpReceiverInternal>::Create(
           signaling_thread(),
-          new VideoRtpReceiver(remote_sender_info.sender_id, worker_thread(),
-                               remote_sender_info.first_ssrc, video_channel()));
+          new VideoRtpReceiver(remote_sender_info.sender_id, streams,
+                               worker_thread(), remote_sender_info.first_ssrc,
+                               video_channel()));
   stream->AddTrack(
       static_cast<VideoTrackInterface*>(receiver->internal()->track().get()));
   GetVideoTransceiver()->internal()->AddReceiver(receiver);
-  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams;
-  streams.push_back(rtc::scoped_refptr<MediaStreamInterface>(stream));
-  observer_->OnAddTrack(receiver, streams);
+  observer_->OnAddTrack(receiver, std::move(streams));
 }
 
 // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote
diff --git a/pc/peerconnection_rtp_unittest.cc b/pc/peerconnection_rtp_unittest.cc
index 0261b1a..860c6dc 100644
--- a/pc/peerconnection_rtp_unittest.cc
+++ b/pc/peerconnection_rtp_unittest.cc
@@ -72,10 +72,10 @@
   ASSERT_EQ(1u, callee->observer()->add_track_events_.size());
   // TODO(deadbeef): When no stream is handled correctly we would expect
   // |add_track_events_[0].streams| to be empty. https://crbug.com/webrtc/7933
-  ASSERT_EQ(1u, callee->observer()->add_track_events_[0].streams.size());
-  EXPECT_TRUE(
-      callee->observer()->add_track_events_[0].streams[0]->FindAudioTrack(
-          "audio_track"));
+  auto& add_track_event = callee->observer()->add_track_events_[0];
+  ASSERT_EQ(1u, add_track_event.streams.size());
+  EXPECT_TRUE(add_track_event.streams[0]->FindAudioTrack("audio_track"));
+  EXPECT_EQ(add_track_event.streams, add_track_event.receiver->streams());
 }
 
 TEST_F(PeerConnectionRtpTest, AddTrackWithStreamFiresOnAddTrack) {
@@ -89,12 +89,11 @@
   ASSERT_TRUE(callee->SetRemoteDescription(caller->CreateOfferAndSetAsLocal()));
 
   ASSERT_EQ(1u, callee->observer()->add_track_events_.size());
-  ASSERT_EQ(1u, callee->observer()->add_track_events_[0].streams.size());
-  EXPECT_EQ("audio_stream",
-            callee->observer()->add_track_events_[0].streams[0]->label());
-  EXPECT_TRUE(
-      callee->observer()->add_track_events_[0].streams[0]->FindAudioTrack(
-          "audio_track"));
+  auto& add_track_event = callee->observer()->add_track_events_[0];
+  ASSERT_EQ(1u, add_track_event.streams.size());
+  EXPECT_EQ("audio_stream", add_track_event.streams[0]->label());
+  EXPECT_TRUE(add_track_event.streams[0]->FindAudioTrack("audio_track"));
+  EXPECT_EQ(add_track_event.streams, add_track_event.receiver->streams());
 }
 
 TEST_F(PeerConnectionRtpTest, RemoveTrackWithoutStreamFiresOnRemoveTrack) {
diff --git a/pc/rtpreceiver.cc b/pc/rtpreceiver.cc
index 4d69aa2..da7e642 100644
--- a/pc/rtpreceiver.cc
+++ b/pc/rtpreceiver.cc
@@ -10,6 +10,7 @@
 
 #include "pc/rtpreceiver.h"
 
+#include <utility>
 #include <vector>
 
 #include "api/mediastreamtrackproxy.h"
@@ -20,9 +21,11 @@
 
 namespace webrtc {
 
-AudioRtpReceiver::AudioRtpReceiver(const std::string& track_id,
-                                   uint32_t ssrc,
-                                   cricket::VoiceChannel* channel)
+AudioRtpReceiver::AudioRtpReceiver(
+    const std::string& track_id,
+    std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
+    uint32_t ssrc,
+    cricket::VoiceChannel* channel)
     : id_(track_id),
       ssrc_(ssrc),
       channel_(channel),
@@ -30,6 +33,7 @@
           rtc::Thread::Current(),
           AudioTrack::Create(track_id,
                              RemoteAudioSource::Create(ssrc, channel)))),
+      streams_(std::move(streams)),
       cached_track_enabled_(track_->enabled()) {
   RTC_DCHECK(track_->GetSource()->remote());
   track_->RegisterObserver(this);
@@ -144,10 +148,12 @@
   received_first_packet_ = true;
 }
 
-VideoRtpReceiver::VideoRtpReceiver(const std::string& track_id,
-                                   rtc::Thread* worker_thread,
-                                   uint32_t ssrc,
-                                   cricket::VideoChannel* channel)
+VideoRtpReceiver::VideoRtpReceiver(
+    const std::string& track_id,
+    std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
+    rtc::Thread* worker_thread,
+    uint32_t ssrc,
+    cricket::VideoChannel* channel)
     : id_(track_id),
       ssrc_(ssrc),
       channel_(channel),
@@ -161,7 +167,8 @@
               VideoTrackSourceProxy::Create(rtc::Thread::Current(),
                                             worker_thread,
                                             source_),
-              worker_thread))) {
+              worker_thread))),
+      streams_(std::move(streams)) {
   source_->SetState(MediaSourceInterface::kLive);
   if (!channel_) {
     RTC_LOG(LS_ERROR)
diff --git a/pc/rtpreceiver.h b/pc/rtpreceiver.h
index d3f0f26..a1af13c 100644
--- a/pc/rtpreceiver.h
+++ b/pc/rtpreceiver.h
@@ -49,9 +49,11 @@
   // sees.
   // TODO(deadbeef): Use rtc::Optional, or have another constructor that
   // doesn't take an SSRC, and make this one DCHECK(ssrc != 0).
-  AudioRtpReceiver(const std::string& track_id,
-                   uint32_t ssrc,
-                   cricket::VoiceChannel* channel);
+  AudioRtpReceiver(
+      const std::string& track_id,
+      std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
+      uint32_t ssrc,
+      cricket::VoiceChannel* channel);
 
   virtual ~AudioRtpReceiver();
 
@@ -69,6 +71,10 @@
   rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
     return track_.get();
   }
+  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
+      const override {
+    return streams_;
+  }
 
   cricket::MediaType media_type() const override {
     return cricket::MEDIA_TYPE_AUDIO;
@@ -99,6 +105,7 @@
   const uint32_t ssrc_;
   cricket::VoiceChannel* channel_;
   const rtc::scoped_refptr<AudioTrackInterface> track_;
+  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
   bool cached_track_enabled_;
   double cached_volume_ = 1;
   bool stopped_ = false;
@@ -111,10 +118,12 @@
  public:
   // An SSRC of 0 will create a receiver that will match the first SSRC it
   // sees.
-  VideoRtpReceiver(const std::string& track_id,
-                   rtc::Thread* worker_thread,
-                   uint32_t ssrc,
-                   cricket::VideoChannel* channel);
+  VideoRtpReceiver(
+      const std::string& track_id,
+      std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams,
+      rtc::Thread* worker_thread,
+      uint32_t ssrc,
+      cricket::VideoChannel* channel);
 
   virtual ~VideoRtpReceiver();
 
@@ -126,6 +135,10 @@
   rtc::scoped_refptr<MediaStreamTrackInterface> track() const override {
     return track_.get();
   }
+  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams()
+      const override {
+    return streams_;
+  }
 
   cricket::MediaType media_type() const override {
     return cricket::MEDIA_TYPE_VIDEO;
@@ -160,6 +173,7 @@
   // the VideoRtpReceiver is stopped.
   rtc::scoped_refptr<VideoTrackSource> source_;
   rtc::scoped_refptr<VideoTrackInterface> track_;
+  std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams_;
   bool stopped_ = false;
   RtpReceiverObserverInterface* observer_ = nullptr;
   bool received_first_packet_ = false;
diff --git a/pc/rtpsenderreceiver_unittest.cc b/pc/rtpsenderreceiver_unittest.cc
index f5b06d1..03bb84b 100644
--- a/pc/rtpsenderreceiver_unittest.cc
+++ b/pc/rtpsenderreceiver_unittest.cc
@@ -165,16 +165,19 @@
     VerifyVideoChannelNoInput();
   }
 
-  void CreateAudioRtpReceiver() {
-    audio_rtp_receiver_ =
-        new AudioRtpReceiver(kAudioTrackId, kAudioSsrc, voice_channel_);
+  void CreateAudioRtpReceiver(
+      std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams = {}) {
+    audio_rtp_receiver_ = new AudioRtpReceiver(
+        kAudioTrackId, std::move(streams), kAudioSsrc, voice_channel_);
     audio_track_ = audio_rtp_receiver_->audio_track();
     VerifyVoiceChannelOutput();
   }
 
-  void CreateVideoRtpReceiver() {
+  void CreateVideoRtpReceiver(
+      std::vector<rtc::scoped_refptr<MediaStreamInterface>> streams = {}) {
     video_rtp_receiver_ = new VideoRtpReceiver(
-        kVideoTrackId, rtc::Thread::Current(), kVideoSsrc, video_channel_);
+        kVideoTrackId, std::move(streams), rtc::Thread::Current(), kVideoSsrc,
+        video_channel_);
     video_track_ = video_rtp_receiver_->video_track();
     VerifyVideoChannelOutput();
   }
@@ -292,6 +295,16 @@
   DestroyVideoRtpReceiver();
 }
 
+TEST_F(RtpSenderReceiverTest, AddAndDestroyAudioRtpReceiverWithStreams) {
+  CreateAudioRtpReceiver({local_stream_});
+  DestroyAudioRtpReceiver();
+}
+
+TEST_F(RtpSenderReceiverTest, AddAndDestroyVideoRtpReceiverWithStreams) {
+  CreateVideoRtpReceiver({local_stream_});
+  DestroyVideoRtpReceiver();
+}
+
 // Test that the AudioRtpSender applies options from the local audio source.
 TEST_F(RtpSenderReceiverTest, LocalAudioSourceOptionsApplied) {
   cricket::AudioOptions options;
diff --git a/sdk/android/src/jni/pc/mediastream_jni.cc b/sdk/android/src/jni/pc/mediastream_jni.cc
index a56802a..e9c7309 100644
--- a/sdk/android/src/jni/pc/mediastream_jni.cc
+++ b/sdk/android/src/jni/pc/mediastream_jni.cc
@@ -64,7 +64,7 @@
 }
 
 JNI_FUNCTION_DECLARATION(void, MediaStream_free, JNIEnv*, jclass, jlong j_p) {
-  CHECK_RELEASE(reinterpret_cast<MediaStreamInterface*>(j_p));
+  reinterpret_cast<MediaStreamInterface*>(j_p)->Release();
 }
 
 }  // namespace jni