Revert "Move stats ID generation from SSRC to local ID"

This reverts commit e357a4dd4e3b015f8281813f246de793589bd537.

Reason for revert: Looks like it's breaking some downstream projects.

Original change's description:
> Move stats ID generation from SSRC to local ID
> 
> This generates stats IDs for Track stats (which
> represents stats on the attachment of a track to
> a PeerConnection) from being SSRC-based to being
> based on an ID that is allocated when connecting the
> track to the PC.
> 
> This is a prerequisite to generating stats before
> the PeerConnection is connected.
> 
> Bug: webrtc:8673
> Change-Id: I82f6e521646b0c92b3af4dffb2cdee75e6dc10d4
> Reviewed-on: https://webrtc-review.googlesource.com/38360
> Commit-Queue: Harald Alvestrand <hta@webrtc.org>
> Reviewed-by: Fredrik Solenberg <solenberg@webrtc.org>
> Reviewed-by: Henrik Boström <hbos@webrtc.org>
> Cr-Commit-Position: refs/heads/master@{#21582}

TBR=solenberg@webrtc.org,hbos@webrtc.org,hta@webrtc.org

Change-Id: I621c10236c02be01d82f4660168f0323b85e24af
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: webrtc:8673
Reviewed-on: https://webrtc-review.googlesource.com/38681
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#21586}
diff --git a/api/rtpreceiverinterface.h b/api/rtpreceiverinterface.h
index ac2e090..311971d 100644
--- a/api/rtpreceiverinterface.h
+++ b/api/rtpreceiverinterface.h
@@ -127,13 +127,6 @@
   virtual std::vector<RtpSource> GetSources() const {
     return std::vector<RtpSource>();
   }
-  // TODO(hta): Remove default implementation or move function to
-  // an internal interface. content::FakeRtpReceiver in Chromium needs this.
-
-  // Returns an ID that changes if the attached track changes, but
-  // otherwise remains constant. Used to generate IDs for stats.
-  // The special value zero means that no track is attached.
-  virtual int AttachmentId() const { return 0; }
 
  protected:
   virtual ~RtpReceiverInterface() {}
@@ -153,7 +146,6 @@
   PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
   PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*);
   PROXY_CONSTMETHOD0(std::vector<RtpSource>, GetSources);
-  PROXY_CONSTMETHOD0(int, AttachmentId);
   END_PROXY_MAP()
 
 }  // namespace webrtc
diff --git a/api/rtpsenderinterface.h b/api/rtpsenderinterface.h
index d253e89..a7fbbda 100644
--- a/api/rtpsenderinterface.h
+++ b/api/rtpsenderinterface.h
@@ -59,11 +59,6 @@
   // Returns null for a video sender.
   virtual rtc::scoped_refptr<DtmfSenderInterface> GetDtmfSender() const = 0;
 
-  // Returns an ID that changes every time SetTrack() is called, but
-  // otherwise remains constant. Used to generate IDs for stats.
-  // The special value zero means that no track is attached.
-  virtual int AttachmentId() const = 0;
-
  protected:
   virtual ~RtpSenderInterface() {}
 };
@@ -82,8 +77,7 @@
   PROXY_CONSTMETHOD0(RtpParameters, GetParameters);
   PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
   PROXY_CONSTMETHOD0(rtc::scoped_refptr<DtmfSenderInterface>, GetDtmfSender);
-  PROXY_CONSTMETHOD0(int, AttachmentId);
-  END_PROXY_MAP()
+END_PROXY_MAP()
 
 }  // namespace webrtc
 
diff --git a/api/test/mock_rtpreceiver.h b/api/test/mock_rtpreceiver.h
index 53c04b9..7097adc 100644
--- a/api/test/mock_rtpreceiver.h
+++ b/api/test/mock_rtpreceiver.h
@@ -29,7 +29,6 @@
   MOCK_METHOD1(SetParameters, bool(const RtpParameters&));
   MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*));
   MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
-  MOCK_CONST_METHOD0(AttachmentId, int());
 };
 
 }  // namespace webrtc
diff --git a/api/test/mock_rtpsender.h b/api/test/mock_rtpsender.h
index 35d048c..a89fa92 100644
--- a/api/test/mock_rtpsender.h
+++ b/api/test/mock_rtpsender.h
@@ -30,7 +30,6 @@
   MOCK_CONST_METHOD0(GetParameters, RtpParameters());
   MOCK_METHOD1(SetParameters, bool(const RtpParameters&));
   MOCK_CONST_METHOD0(GetDtmfSender, rtc::scoped_refptr<DtmfSenderInterface>());
-  MOCK_CONST_METHOD0(AttachmentId, int());
 };
 
 }  // namespace webrtc
diff --git a/pc/peerconnectioninterface_unittest.cc b/pc/peerconnectioninterface_unittest.cc
index a06ed50..bc6b5e5 100644
--- a/pc/peerconnectioninterface_unittest.cc
+++ b/pc/peerconnectioninterface_unittest.cc
@@ -1506,31 +1506,6 @@
   EXPECT_TRUE(DoGetStats(nullptr));
 }
 
-TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddTrack) {
-  CreatePeerConnectionWithoutDtls();
-  rtc::scoped_refptr<AudioTrackInterface> audio_track(
-      pc_factory_->CreateAudioTrack("audio_track", nullptr));
-  rtc::scoped_refptr<VideoTrackInterface> video_track(
-      pc_factory_->CreateVideoTrack(
-          "video_track", pc_factory_->CreateVideoSource(
-                             std::unique_ptr<cricket::VideoCapturer>(
-                                 new cricket::FakeVideoCapturer()))));
-  auto audio_sender = pc_->AddTrack(audio_track, std::vector<std::string>());
-  auto video_sender = pc_->AddTrack(video_track, std::vector<std::string>());
-  EXPECT_TRUE(audio_sender.ok());
-  EXPECT_TRUE(video_sender.ok());
-  EXPECT_NE(0, video_sender.value()->AttachmentId());
-  EXPECT_NE(0, audio_sender.value()->AttachmentId());
-}
-
-TEST_F(PeerConnectionInterfaceTest, AttachmentIdIsSetOnAddStream) {
-  CreatePeerConnectionWithoutDtls();
-  AddVideoStream(kStreamLabel1);
-  auto senders = pc_->GetSenders();
-  EXPECT_EQ(1u, senders.size());
-  EXPECT_NE(0, senders[0]->AttachmentId());
-}
-
 TEST_F(PeerConnectionInterfaceTest, CreateOfferReceiveAnswer) {
   InitiateCall();
   WaitAndVerifyOnAddStream(kStreamLabel1);
diff --git a/pc/rtcstatscollector.cc b/pc/rtcstatscollector.cc
index 0f4dc3d..e777a26 100644
--- a/pc/rtcstatscollector.cc
+++ b/pc/rtcstatscollector.cc
@@ -57,11 +57,8 @@
       info.remote_candidate.id();
 }
 
-std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-    bool is_local,
-    const char* kind,
-    const std::string& id,
-    int attachment_id) {
+std::string RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+    bool is_local, const char* kind, const std::string& id, uint32_t ssrc) {
   RTC_DCHECK(kind == MediaStreamTrackInterface::kAudioKind ||
              kind == MediaStreamTrackInterface::kVideoKind);
   std::ostringstream oss;
@@ -69,7 +66,7 @@
                    : "RTCMediaStreamTrack_remote_");
   oss << kind << "_";
   oss << id << "_";
-  oss << attachment_id;
+  oss << ssrc;
   return oss.str();
 }
 
@@ -378,14 +375,14 @@
 ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
     int64_t timestamp_us,
     const AudioTrackInterface& audio_track,
-    const cricket::VoiceSenderInfo& voice_sender_info,
-    int attachment_id) {
+    const cricket::VoiceSenderInfo& voice_sender_info) {
   std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
       new RTCMediaStreamTrackStats(
-          RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
+          RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
               true, MediaStreamTrackInterface::kAudioKind, audio_track.id(),
-              attachment_id),
-          timestamp_us, RTCMediaStreamTrackKind::kAudio));
+              voice_sender_info.ssrc()),
+          timestamp_us,
+          RTCMediaStreamTrackKind::kAudio));
   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
       audio_track, audio_track_stats.get());
   audio_track_stats->remote_source = false;
@@ -412,16 +409,14 @@
 ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
     int64_t timestamp_us,
     const AudioTrackInterface& audio_track,
-    const cricket::VoiceReceiverInfo& voice_receiver_info,
-    int attachment_id) {
-  // Since receiver tracks can't be reattached, we use the SSRC as
-  // an attachment identifier.
+    const cricket::VoiceReceiverInfo& voice_receiver_info) {
   std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats(
       new RTCMediaStreamTrackStats(
-          RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
+          RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
               false, MediaStreamTrackInterface::kAudioKind, audio_track.id(),
-              attachment_id),
-          timestamp_us, RTCMediaStreamTrackKind::kAudio));
+              voice_receiver_info.ssrc()),
+          timestamp_us,
+          RTCMediaStreamTrackKind::kAudio));
   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
       audio_track, audio_track_stats.get());
   audio_track_stats->remote_source = true;
@@ -448,14 +443,14 @@
 ProduceMediaStreamTrackStatsFromVideoSenderInfo(
     int64_t timestamp_us,
     const VideoTrackInterface& video_track,
-    const cricket::VideoSenderInfo& video_sender_info,
-    int attachment_id) {
+    const cricket::VideoSenderInfo& video_sender_info) {
   std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
       new RTCMediaStreamTrackStats(
-          RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
+          RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
               true, MediaStreamTrackInterface::kVideoKind, video_track.id(),
-              attachment_id),
-          timestamp_us, RTCMediaStreamTrackKind::kVideo));
+              video_sender_info.ssrc()),
+          timestamp_us,
+          RTCMediaStreamTrackKind::kVideo));
   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
       video_track, video_track_stats.get());
   video_track_stats->remote_source = false;
@@ -474,16 +469,14 @@
 ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
     int64_t timestamp_us,
     const VideoTrackInterface& video_track,
-    const cricket::VideoReceiverInfo& video_receiver_info,
-    int attachment_id) {
-  // Since receiver tracks can't be reattached, we use the SSRC as
-  // attachment ID.
+    const cricket::VideoReceiverInfo& video_receiver_info) {
   std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats(
       new RTCMediaStreamTrackStats(
-          RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
+          RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
               false, MediaStreamTrackInterface::kVideoKind, video_track.id(),
-              attachment_id),
-          timestamp_us, RTCMediaStreamTrackKind::kVideo));
+              video_receiver_info.ssrc()),
+          timestamp_us,
+          RTCMediaStreamTrackKind::kVideo));
   SetMediaStreamTrackStatsFromMediaStreamTrackInterface(
       video_track, video_track_stats.get());
   video_track_stats->remote_source = true;
@@ -533,8 +526,8 @@
       RTC_CHECK(voice_sender_info)
           << "No voice sender info for sender with ssrc " << sender->ssrc();
       std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats =
-          ProduceMediaStreamTrackStatsFromVoiceSenderInfo(
-              timestamp_us, *track, *voice_sender_info, sender->AttachmentId());
+          ProduceMediaStreamTrackStatsFromVoiceSenderInfo(timestamp_us, *track,
+                                                          *voice_sender_info);
       report->AddStats(std::move(audio_track_stats));
     } else if (sender->media_type() == cricket::MEDIA_TYPE_VIDEO) {
       VideoTrackInterface* track =
@@ -546,8 +539,8 @@
       RTC_CHECK(video_sender_info)
           << "No video sender info for sender with ssrc " << sender->ssrc();
       std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats =
-          ProduceMediaStreamTrackStatsFromVideoSenderInfo(
-              timestamp_us, *track, *video_sender_info, sender->AttachmentId());
+          ProduceMediaStreamTrackStatsFromVideoSenderInfo(timestamp_us, *track,
+                                                          *video_sender_info);
       report->AddStats(std::move(video_track_stats));
     } else {
       RTC_NOTREACHED();
@@ -572,8 +565,7 @@
       }
       std::unique_ptr<RTCMediaStreamTrackStats> audio_track_stats =
           ProduceMediaStreamTrackStatsFromVoiceReceiverInfo(
-              timestamp_us, *track, *voice_receiver_info,
-              receiver->AttachmentId());
+              timestamp_us, *track, *voice_receiver_info);
       report->AddStats(std::move(audio_track_stats));
     } else if (receiver->media_type() == cricket::MEDIA_TYPE_VIDEO) {
       VideoTrackInterface* track =
@@ -585,8 +577,7 @@
       }
       std::unique_ptr<RTCMediaStreamTrackStats> video_track_stats =
           ProduceMediaStreamTrackStatsFromVideoReceiverInfo(
-              timestamp_us, *track, *video_receiver_info,
-              receiver->AttachmentId());
+              timestamp_us, *track, *video_receiver_info);
       report->AddStats(std::move(video_track_stats));
     } else {
       RTC_NOTREACHED();
@@ -617,37 +608,59 @@
     // TODO(hta): Revisit in conjunction with https://bugs.webrtc.org/8674
     if (is_local) {
       for (auto audio_track : stream->GetAudioTracks()) {
-        stream_stats->track_ids->push_back(
-            RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-                is_local, MediaStreamTrackInterface::kAudioKind,
-                audio_track->id(),
-                track_media_info_map.GetAttachmentIdByTrack(audio_track)
-                    .value()));
+        auto sender_infos =
+            track_media_info_map.GetVoiceSenderInfos(*audio_track);
+        // There is no map entry on unconnected tracks.
+        // https://bugs.webrtc.org/8673
+        if (!sender_infos)
+          continue;
+        for (const auto& sender_info : *sender_infos) {
+          // In the WebRTC implementation, SSRC 0 means unconnected,
+          // and should not occur in the map.
+          // https://bugs.webrtc.org/8694
+          RTC_DCHECK_NE(0, sender_info->ssrc());
+          stream_stats->track_ids->push_back(
+              RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                  is_local, MediaStreamTrackInterface::kAudioKind,
+                  audio_track->id(), sender_info->ssrc()));
+        }
       }
       for (auto video_track : stream->GetVideoTracks()) {
-        stream_stats->track_ids->push_back(
-            RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-                is_local, MediaStreamTrackInterface::kVideoKind,
-                video_track->id(),
-                track_media_info_map.GetAttachmentIdByTrack(video_track)
-                    .value()));
+        auto sender_infos =
+            track_media_info_map.GetVideoSenderInfos(*video_track);
+        // There is no map entry on unconnected tracks.
+        // https://bugs.webrtc.org/8673
+        if (!sender_infos)
+          continue;
+        for (const auto& sender_info : *sender_infos) {
+          // SSRC must not be zero. https://bugs.webrtc.org/8694
+          RTC_DCHECK_NE(0, sender_info->ssrc());
+          stream_stats->track_ids->push_back(
+              RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                  is_local, MediaStreamTrackInterface::kVideoKind,
+                  video_track->id(), sender_info->ssrc()));
+        }
       }
     } else {
       for (auto audio_track : stream->GetAudioTracks()) {
-        stream_stats->track_ids->push_back(
-            RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-                is_local, MediaStreamTrackInterface::kAudioKind,
-                audio_track->id(),
-                track_media_info_map.GetAttachmentIdByTrack(audio_track)
-                    .value()));
+        auto receiver_info =
+            track_media_info_map.GetVoiceReceiverInfo(*audio_track);
+        if (receiver_info) {
+          stream_stats->track_ids->push_back(
+              RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                  is_local, MediaStreamTrackInterface::kAudioKind,
+                  audio_track->id(), receiver_info->ssrc()));
+        }
       }
       for (auto video_track : stream->GetVideoTracks()) {
-        stream_stats->track_ids->push_back(
-            RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-                is_local, MediaStreamTrackInterface::kVideoKind,
-                video_track->id(),
-                track_media_info_map.GetAttachmentIdByTrack(video_track)
-                    .value()));
+        auto receiver_info =
+            track_media_info_map.GetVideoReceiverInfo(*video_track);
+        if (receiver_info) {
+          stream_stats->track_ids->push_back(
+              RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                  is_local, MediaStreamTrackInterface::kVideoKind,
+                  video_track->id(), receiver_info->ssrc()));
+        }
       }
     }
     report->AddStats(std::move(stream_stats));
@@ -1064,21 +1077,22 @@
       if (voice_receiver_info.ssrc() == 0)
         continue;
       std::unique_ptr<RTCInboundRTPStreamStats> inbound_audio(
-          new RTCInboundRTPStreamStats(RTCInboundRTPStreamStatsIDFromSSRC(
-                                           true, voice_receiver_info.ssrc()),
-                                       timestamp_us));
+          new RTCInboundRTPStreamStats(
+              RTCInboundRTPStreamStatsIDFromSSRC(
+                  true, voice_receiver_info.ssrc()),
+              timestamp_us));
       SetInboundRTPStreamStatsFromVoiceReceiverInfo(
           voice_receiver_info, inbound_audio.get());
-      // TODO(hta): This lookup should look for the sender, not the track.
       rtc::scoped_refptr<AudioTrackInterface> audio_track =
           track_media_info_map_->GetAudioTrack(voice_receiver_info);
       if (audio_track) {
         RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end());
-        inbound_audio
-            ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-            false, MediaStreamTrackInterface::kAudioKind,
-            track_to_id_.find(audio_track.get())->second,
-            track_media_info_map_->GetAttachmentIdByTrack(audio_track).value());
+        inbound_audio->track_id =
+            RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                false,
+                MediaStreamTrackInterface::kAudioKind,
+                track_to_id_.find(audio_track.get())->second,
+                voice_receiver_info.ssrc());
       }
       inbound_audio->transport_id = transport_id;
       report->AddStats(std::move(inbound_audio));
@@ -1101,11 +1115,12 @@
           track_media_info_map_->GetAudioTrack(voice_sender_info);
       if (audio_track) {
         RTC_DCHECK(track_to_id_.find(audio_track.get()) != track_to_id_.end());
-        outbound_audio
-            ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-            true, MediaStreamTrackInterface::kAudioKind,
-            track_to_id_.find(audio_track.get())->second,
-            track_media_info_map.GetAttachmentIdByTrack(audio_track).value());
+        outbound_audio->track_id =
+            RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                true,
+                MediaStreamTrackInterface::kAudioKind,
+                track_to_id_.find(audio_track.get())->second,
+                voice_sender_info.ssrc());
       }
       outbound_audio->transport_id = transport_id;
       report->AddStats(std::move(outbound_audio));
@@ -1136,11 +1151,12 @@
           track_media_info_map_->GetVideoTrack(video_receiver_info);
       if (video_track) {
         RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end());
-        inbound_video
-            ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-            false, MediaStreamTrackInterface::kVideoKind,
-            track_to_id_.find(video_track.get())->second,
-            track_media_info_map_->GetAttachmentIdByTrack(video_track).value());
+        inbound_video->track_id =
+            RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                false,
+                MediaStreamTrackInterface::kVideoKind,
+                track_to_id_.find(video_track.get())->second,
+                video_receiver_info.ssrc());
       }
       inbound_video->transport_id = transport_id;
       report->AddStats(std::move(inbound_video));
@@ -1153,20 +1169,22 @@
       if (video_sender_info.ssrc() == 0)
         continue;
       std::unique_ptr<RTCOutboundRTPStreamStats> outbound_video(
-          new RTCOutboundRTPStreamStats(RTCOutboundRTPStreamStatsIDFromSSRC(
-                                            false, video_sender_info.ssrc()),
-                                        timestamp_us));
+          new RTCOutboundRTPStreamStats(
+              RTCOutboundRTPStreamStatsIDFromSSRC(
+                  false, video_sender_info.ssrc()),
+              timestamp_us));
       SetOutboundRTPStreamStatsFromVideoSenderInfo(
           video_sender_info, outbound_video.get());
       rtc::scoped_refptr<VideoTrackInterface> video_track =
           track_media_info_map_->GetVideoTrack(video_sender_info);
       if (video_track) {
         RTC_DCHECK(track_to_id_.find(video_track.get()) != track_to_id_.end());
-        outbound_video
-            ->track_id = RTCMediaStreamTrackStatsIDFromTrackKindIDAndAttachment(
-            true, MediaStreamTrackInterface::kVideoKind,
-            track_to_id_.find(video_track.get())->second,
-            track_media_info_map_->GetAttachmentIdByTrack(video_track).value());
+        outbound_video->track_id =
+            RTCMediaStreamTrackStatsIDFromTrackKindIDAndSsrc(
+                true,
+                MediaStreamTrackInterface::kVideoKind,
+                track_to_id_.find(video_track.get())->second,
+                video_sender_info.ssrc());
       }
       outbound_video->transport_id = transport_id;
       report->AddStats(std::move(outbound_video));
@@ -1292,9 +1310,6 @@
 
 std::map<MediaStreamTrackInterface*, std::string>
 RTCStatsCollector::PrepareTrackToID_s() const {
-  // TODO(hta): Remove this method, and vector its callers via
-  // senders / receivers instead.
-  // It ignores tracks that are multiply connected to the PC.
   RTC_DCHECK(signaling_thread_->IsCurrent());
   std::map<MediaStreamTrackInterface*, std::string> track_to_id;
   for (auto sender : pc_->GetSenders()) {
diff --git a/pc/rtcstatscollector_unittest.cc b/pc/rtcstatscollector_unittest.cc
index 141a3cf..2149695 100644
--- a/pc/rtcstatscollector_unittest.cc
+++ b/pc/rtcstatscollector_unittest.cc
@@ -238,8 +238,7 @@
 
 rtc::scoped_refptr<MockRtpSender> CreateMockSender(
     const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
-    uint32_t ssrc,
-    int attachment_id) {
+    uint32_t ssrc) {
   rtc::scoped_refptr<MockRtpSender> sender(
       new rtc::RefCountedObject<MockRtpSender>());
   EXPECT_CALL(*sender, track()).WillRepeatedly(Return(track));
@@ -254,14 +253,12 @@
       params.encodings[0].ssrc = ssrc;
       return params;
     }));
-  EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(Return(attachment_id));
   return sender;
 }
 
 rtc::scoped_refptr<MockRtpReceiver> CreateMockReceiver(
     const rtc::scoped_refptr<MediaStreamTrackInterface>& track,
-    uint32_t ssrc,
-    int attachment_id) {
+    uint32_t ssrc) {
   rtc::scoped_refptr<MockRtpReceiver> receiver(
       new rtc::RefCountedObject<MockRtpReceiver>());
   EXPECT_CALL(*receiver, track()).WillRepeatedly(Return(track));
@@ -275,7 +272,6 @@
       params.encodings[0].ssrc = ssrc;
       return params;
     }));
-  EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(Return(attachment_id));
   return receiver;
 }
 
@@ -353,8 +349,7 @@
       }
     }
 
-    rtc::scoped_refptr<MockRtpSender> sender =
-        CreateMockSender(track, ssrc, 50);
+    rtc::scoped_refptr<MockRtpSender> sender = CreateMockSender(track, ssrc);
     EXPECT_CALL(pc_, GetSenders()).WillRepeatedly(Return(
         std::vector<rtc::scoped_refptr<RtpSenderInterface>>({
             rtc::scoped_refptr<RtpSenderInterface>(sender.get()) })));
@@ -384,7 +379,7 @@
     }
 
     rtc::scoped_refptr<MockRtpReceiver> receiver =
-        CreateMockReceiver(track, ssrc, 62);
+        CreateMockReceiver(track, ssrc);
     EXPECT_CALL(pc_, GetReceivers()).WillRepeatedly(Return(
         std::vector<rtc::scoped_refptr<RtpReceiverInterface>>({
             rtc::scoped_refptr<RtpReceiverInterface>(receiver.get()) })));
@@ -409,7 +404,6 @@
     rtp_senders_.clear();
     rtp_receivers_.clear();
     // Local audio tracks and voice sender infos
-    int attachment_id = 147;
     for (auto& pair : local_audio_track_info_pairs) {
       MediaStreamTrackInterface* local_audio_track = pair.first;
       const cricket::VoiceSenderInfo& voice_sender_info = pair.second;
@@ -417,14 +411,14 @@
                     MediaStreamTrackInterface::kAudioKind);
 
       voice_media_info_->senders.push_back(voice_sender_info);
-      rtc::scoped_refptr<MockRtpSender> rtp_sender = CreateMockSender(
-          rtc::scoped_refptr<MediaStreamTrackInterface>(local_audio_track),
-          voice_sender_info.local_stats[0].ssrc, attachment_id++);
+      rtc::scoped_refptr<MockRtpSender> rtp_sender =
+          CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface>(
+                               local_audio_track),
+                           voice_sender_info.local_stats[0].ssrc);
       rtp_senders_.push_back(rtc::scoped_refptr<RtpSenderInterface>(
           rtp_sender.get()));
     }
     // Remote audio tracks and voice receiver infos
-    attachment_id = 181;
     for (auto& pair : remote_audio_track_info_pairs) {
       MediaStreamTrackInterface* remote_audio_track = pair.first;
       const cricket::VoiceReceiverInfo& voice_receiver_info = pair.second;
@@ -432,14 +426,14 @@
                     MediaStreamTrackInterface::kAudioKind);
 
       voice_media_info_->receivers.push_back(voice_receiver_info);
-      rtc::scoped_refptr<MockRtpReceiver> rtp_receiver = CreateMockReceiver(
-          rtc::scoped_refptr<MediaStreamTrackInterface>(remote_audio_track),
-          voice_receiver_info.local_stats[0].ssrc, attachment_id++);
+      rtc::scoped_refptr<MockRtpReceiver> rtp_receiver =
+          CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface>(
+                               remote_audio_track),
+                             voice_receiver_info.local_stats[0].ssrc);
       rtp_receivers_.push_back(rtc::scoped_refptr<RtpReceiverInterface>(
           rtp_receiver.get()));
     }
     // Local video tracks and video sender infos
-    attachment_id = 151;
     for (auto& pair : local_video_track_info_pairs) {
       MediaStreamTrackInterface* local_video_track = pair.first;
       const cricket::VideoSenderInfo& video_sender_info = pair.second;
@@ -447,14 +441,14 @@
                     MediaStreamTrackInterface::kVideoKind);
 
       video_media_info_->senders.push_back(video_sender_info);
-      rtc::scoped_refptr<MockRtpSender> rtp_sender = CreateMockSender(
-          rtc::scoped_refptr<MediaStreamTrackInterface>(local_video_track),
-          video_sender_info.local_stats[0].ssrc, attachment_id++);
+      rtc::scoped_refptr<MockRtpSender> rtp_sender =
+          CreateMockSender(rtc::scoped_refptr<MediaStreamTrackInterface>(
+                               local_video_track),
+                           video_sender_info.local_stats[0].ssrc);
       rtp_senders_.push_back(rtc::scoped_refptr<RtpSenderInterface>(
           rtp_sender.get()));
     }
     // Remote video tracks and video receiver infos
-    attachment_id = 191;
     for (auto& pair : remote_video_track_info_pairs) {
       MediaStreamTrackInterface* remote_video_track = pair.first;
       const cricket::VideoReceiverInfo& video_receiver_info = pair.second;
@@ -462,9 +456,10 @@
                     MediaStreamTrackInterface::kVideoKind);
 
       video_media_info_->receivers.push_back(video_receiver_info);
-      rtc::scoped_refptr<MockRtpReceiver> rtp_receiver = CreateMockReceiver(
-          rtc::scoped_refptr<MediaStreamTrackInterface>(remote_video_track),
-          video_receiver_info.local_stats[0].ssrc, attachment_id++);
+      rtc::scoped_refptr<MockRtpReceiver> rtp_receiver =
+          CreateMockReceiver(rtc::scoped_refptr<MediaStreamTrackInterface>(
+                               remote_video_track),
+                             video_receiver_info.local_stats[0].ssrc);
       rtp_receivers_.push_back(rtc::scoped_refptr<RtpReceiverInterface>(
           rtp_receiver.get()));
     }
@@ -1529,6 +1524,15 @@
   voice_sender_info_ssrc1.apm_statistics.echo_return_loss = 42.0;
   voice_sender_info_ssrc1.apm_statistics.echo_return_loss_enhancement = 52.0;
 
+  // Uses default values, the corresponding stats object should contain
+  // undefined members.
+  cricket::VoiceSenderInfo voice_sender_info_ssrc2;
+  voice_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo());
+  voice_sender_info_ssrc2.local_stats[0].ssrc = 2;
+  voice_sender_info_ssrc2.audio_level = 0;
+  voice_sender_info_ssrc2.total_input_energy = 0.0;
+  voice_sender_info_ssrc2.total_input_duration = 0.0;
+
   // Remote audio track
   rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio_track =
       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "RemoteAudioTrackID",
@@ -1548,8 +1552,10 @@
   voice_receiver_info.jitter_buffer_delay_seconds = 3456;
 
   test_->CreateMockRtpSendersReceiversAndChannels(
-      {std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1)},
-      {std::make_pair(remote_audio_track.get(), voice_receiver_info)}, {}, {});
+      { std::make_pair(local_audio_track.get(), voice_sender_info_ssrc1),
+        std::make_pair(local_audio_track.get(), voice_sender_info_ssrc2) },
+      { std::make_pair(remote_audio_track.get(), voice_receiver_info) },
+      {}, {});
 
   rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
 
@@ -1557,7 +1563,8 @@
       "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us());
   expected_local_stream.stream_identifier = local_stream->label();
   expected_local_stream.track_ids = std::vector<std::string>(
-      {"RTCMediaStreamTrack_local_audio_LocalAudioTrackID_147"});
+      { "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1",
+        "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2" });
   ASSERT_TRUE(report->Get(expected_local_stream.id()));
   EXPECT_EQ(expected_local_stream,
             report->Get(expected_local_stream.id())->cast_to<
@@ -1566,17 +1573,15 @@
   RTCMediaStreamStats expected_remote_stream(
       "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us());
   expected_remote_stream.stream_identifier = remote_stream->label();
-  expected_remote_stream.track_ids = std::vector<std::string>(
-      {"RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_181"});
+  expected_remote_stream.track_ids = std::vector<std::string>({
+      "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3" });
   ASSERT_TRUE(report->Get(expected_remote_stream.id()));
   EXPECT_EQ(expected_remote_stream,
             report->Get(expected_remote_stream.id())->cast_to<
                 RTCMediaStreamStats>());
 
-  // TODO(hta): Remove hardcoded stats IDs from the tests
-  // We should verify that they link properly rather than hardcoding them.
   RTCMediaStreamTrackStats expected_local_audio_track_ssrc1(
-      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_147",
+      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1",
       report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
   expected_local_audio_track_ssrc1.track_identifier = local_audio_track->id();
   expected_local_audio_track_ssrc1.remote_source = false;
@@ -1592,8 +1597,25 @@
             report->Get(expected_local_audio_track_ssrc1.id())->cast_to<
                 RTCMediaStreamTrackStats>());
 
+  RTCMediaStreamTrackStats expected_local_audio_track_ssrc2(
+      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_2",
+      report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
+  expected_local_audio_track_ssrc2.track_identifier = local_audio_track->id();
+  expected_local_audio_track_ssrc2.remote_source = false;
+  expected_local_audio_track_ssrc2.ended = true;
+  expected_local_audio_track_ssrc2.detached = false;
+  expected_local_audio_track_ssrc2.audio_level = 0.0;
+  expected_local_audio_track_ssrc2.total_audio_energy = 0.0;
+  expected_local_audio_track_ssrc2.total_samples_duration = 0.0;
+  // Should be undefined: |expected_local_audio_track_ssrc2.echo_return_loss|
+  // and |expected_local_audio_track_ssrc2.echo_return_loss_enhancement|.
+  ASSERT_TRUE(report->Get(expected_local_audio_track_ssrc2.id()));
+  EXPECT_EQ(expected_local_audio_track_ssrc2,
+            report->Get(expected_local_audio_track_ssrc2.id())->cast_to<
+                RTCMediaStreamTrackStats>());
+
   RTCMediaStreamTrackStats expected_remote_audio_track(
-      "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_181",
+      "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_3",
       report->timestamp_us(), RTCMediaStreamTrackKind::kAudio);
   expected_remote_audio_track.track_identifier = remote_audio_track->id();
   expected_remote_audio_track.remote_source = true;
@@ -1644,6 +1666,13 @@
   video_sender_info_ssrc1.send_frame_height = 4321;
   video_sender_info_ssrc1.frames_encoded = 11;
 
+  cricket::VideoSenderInfo video_sender_info_ssrc2;
+  video_sender_info_ssrc2.local_stats.push_back(cricket::SsrcSenderInfo());
+  video_sender_info_ssrc2.local_stats[0].ssrc = 2;
+  video_sender_info_ssrc2.send_frame_width = 4321;
+  video_sender_info_ssrc2.send_frame_height = 1234;
+  video_sender_info_ssrc2.frames_encoded = 22;
+
   // Remote video track with values
   rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc3 =
       CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID3",
@@ -1660,19 +1689,39 @@
   video_receiver_info_ssrc3.frames_decoded = 995;
   video_receiver_info_ssrc3.frames_rendered = 990;
 
+  // Remote video track with undefined (default) values
+  rtc::scoped_refptr<MediaStreamTrackInterface> remote_video_track_ssrc4 =
+      CreateFakeTrack(cricket::MEDIA_TYPE_VIDEO, "RemoteVideoTrackID4",
+                      MediaStreamTrackInterface::kLive);
+  remote_stream->AddTrack(static_cast<VideoTrackInterface*>(
+      remote_video_track_ssrc4.get()));
+
+  cricket::VideoReceiverInfo video_receiver_info_ssrc4;
+  video_receiver_info_ssrc4.local_stats.push_back(cricket::SsrcReceiverInfo());
+  video_receiver_info_ssrc4.local_stats[0].ssrc = 4;
+  video_receiver_info_ssrc4.frame_width = 0;
+  video_receiver_info_ssrc4.frame_height = 0;
+  video_receiver_info_ssrc4.frames_received = 0;
+  video_receiver_info_ssrc4.frames_decoded = 0;
+  video_receiver_info_ssrc4.frames_rendered = 0;
+
   test_->CreateMockRtpSendersReceiversAndChannels(
       {}, {},
-      {std::make_pair(local_video_track.get(), video_sender_info_ssrc1)},
-      {std::make_pair(remote_video_track_ssrc3.get(),
-                      video_receiver_info_ssrc3)});
+      { std::make_pair(local_video_track.get(), video_sender_info_ssrc1),
+        std::make_pair(local_video_track.get(), video_sender_info_ssrc2) },
+      { std::make_pair(remote_video_track_ssrc3.get(),
+                       video_receiver_info_ssrc3),
+        std::make_pair(remote_video_track_ssrc4.get(),
+                       video_receiver_info_ssrc4) });
 
   rtc::scoped_refptr<const RTCStatsReport> report = GetStatsReport();
 
   RTCMediaStreamStats expected_local_stream(
       "RTCMediaStream_local_LocalStreamLabel", report->timestamp_us());
   expected_local_stream.stream_identifier = local_stream->label();
-  expected_local_stream.track_ids = std::vector<std::string>(
-      {"RTCMediaStreamTrack_local_video_LocalVideoTrackID_151"});
+  expected_local_stream.track_ids = std::vector<std::string>({
+      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1",
+      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2" });
   ASSERT_TRUE(report->Get(expected_local_stream.id()));
   EXPECT_EQ(expected_local_stream,
             report->Get(expected_local_stream.id())->cast_to<
@@ -1681,15 +1730,16 @@
   RTCMediaStreamStats expected_remote_stream(
       "RTCMediaStream_remote_RemoteStreamLabel", report->timestamp_us());
   expected_remote_stream.stream_identifier = remote_stream->label();
-  expected_remote_stream.track_ids = std::vector<std::string>(
-      {"RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_191"});
+  expected_remote_stream.track_ids = std::vector<std::string>({
+      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3",
+      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4" });
   ASSERT_TRUE(report->Get(expected_remote_stream.id()));
   EXPECT_EQ(expected_remote_stream,
             report->Get(expected_remote_stream.id())->cast_to<
                 RTCMediaStreamStats>());
 
   RTCMediaStreamTrackStats expected_local_video_track_ssrc1(
-      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_151",
+      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1",
       report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
   expected_local_video_track_ssrc1.track_identifier = local_video_track->id();
   expected_local_video_track_ssrc1.remote_source = false;
@@ -1703,8 +1753,23 @@
             report->Get(expected_local_video_track_ssrc1.id())->cast_to<
                 RTCMediaStreamTrackStats>());
 
+  RTCMediaStreamTrackStats expected_local_video_track_ssrc2(
+      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_2",
+      report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
+  expected_local_video_track_ssrc2.track_identifier = local_video_track->id();
+  expected_local_video_track_ssrc2.remote_source = false;
+  expected_local_video_track_ssrc2.ended = false;
+  expected_local_video_track_ssrc2.detached = false;
+  expected_local_video_track_ssrc2.frame_width = 4321;
+  expected_local_video_track_ssrc2.frame_height = 1234;
+  expected_local_video_track_ssrc2.frames_sent = 22;
+  ASSERT_TRUE(report->Get(expected_local_video_track_ssrc2.id()));
+  EXPECT_EQ(expected_local_video_track_ssrc2,
+            report->Get(expected_local_video_track_ssrc2.id())->cast_to<
+                RTCMediaStreamTrackStats>());
+
   RTCMediaStreamTrackStats expected_remote_video_track_ssrc3(
-      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_191",
+      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID3_3",
       report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
   expected_remote_video_track_ssrc3.track_identifier =
       remote_video_track_ssrc3->id();
@@ -1720,6 +1785,24 @@
   EXPECT_EQ(expected_remote_video_track_ssrc3,
             report->Get(expected_remote_video_track_ssrc3.id())->cast_to<
                 RTCMediaStreamTrackStats>());
+
+  RTCMediaStreamTrackStats expected_remote_video_track_ssrc4(
+      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID4_4",
+      report->timestamp_us(), RTCMediaStreamTrackKind::kVideo);
+  expected_remote_video_track_ssrc4.track_identifier =
+      remote_video_track_ssrc4->id();
+  expected_remote_video_track_ssrc4.remote_source = true;
+  expected_remote_video_track_ssrc4.ended = false;
+  expected_remote_video_track_ssrc4.detached = false;
+  expected_remote_video_track_ssrc4.frames_received = 0;
+  expected_remote_video_track_ssrc4.frames_decoded = 0;
+  expected_remote_video_track_ssrc4.frames_dropped = 0;
+  // Should be undefined: |expected_remote_video_track_ssrc4.frame_width| and
+  // |expected_remote_video_track_ssrc4.frame_height|.
+  ASSERT_TRUE(report->Get(expected_remote_video_track_ssrc4.id()));
+  EXPECT_EQ(expected_remote_video_track_ssrc4,
+            report->Get(expected_remote_video_track_ssrc4.id())->cast_to<
+                RTCMediaStreamTrackStats>());
 }
 
 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
@@ -1783,7 +1866,7 @@
   expected_audio.is_remote = false;
   expected_audio.media_type = "audio";
   expected_audio.track_id =
-      "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_62";
+      "RTCMediaStreamTrack_remote_audio_RemoteAudioTrackID_1";
   expected_audio.transport_id = "RTCTransport_TransportName_" +
       rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
   expected_audio.codec_id = "RTCCodec_InboundAudio_42";
@@ -1792,6 +1875,7 @@
   expected_audio.packets_lost = -1;
   expected_audio.jitter = 4.5;
   expected_audio.fraction_lost = 5.5;
+
   ASSERT_TRUE(report->Get(expected_audio.id()));
   EXPECT_EQ(
       report->Get(expected_audio.id())->cast_to<RTCInboundRTPStreamStats>(),
@@ -1865,7 +1949,7 @@
   expected_video.is_remote = false;
   expected_video.media_type = "video";
   expected_video.track_id =
-      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_62";
+      "RTCMediaStreamTrack_remote_video_RemoteVideoTrackID_1";
   expected_video.transport_id = "RTCTransport_TransportName_" +
       rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
   expected_video.codec_id = "RTCCodec_InboundVideo_42";
@@ -1959,7 +2043,7 @@
   expected_audio.is_remote = false;
   expected_audio.media_type = "audio";
   expected_audio.track_id =
-      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_50";
+      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1";
   expected_audio.transport_id = "RTCTransport_TransportName_" +
       rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
   expected_audio.codec_id = "RTCCodec_OutboundAudio_42";
@@ -2041,7 +2125,7 @@
   expected_video.is_remote = false;
   expected_video.media_type = "video";
   expected_video.track_id =
-      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_50";
+      "RTCMediaStreamTrack_local_video_LocalVideoTrackID_1";
   expected_video.transport_id = "RTCTransport_TransportName_" +
       rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
   expected_video.codec_id = "RTCCodec_OutboundVideo_42";
@@ -2297,7 +2381,7 @@
   expected_audio.is_remote = false;
   expected_audio.media_type = "audio";
   expected_audio.track_id =
-      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_50";
+      "RTCMediaStreamTrack_local_audio_LocalAudioTrackID_1";
   expected_audio.transport_id =
       "RTCTransport_TransportName_" +
       rtc::ToString<>(cricket::ICE_CANDIDATE_COMPONENT_RTP);
@@ -2326,7 +2410,7 @@
   rtc::scoped_refptr<MediaStreamTrackInterface> track =
       CreateFakeTrack(cricket::MEDIA_TYPE_AUDIO, "audioTrack",
                       MediaStreamTrackInterface::kLive);
-  rtc::scoped_refptr<MockRtpSender> sender = CreateMockSender(track, 0, 49);
+  rtc::scoped_refptr<MockRtpSender> sender = CreateMockSender(track, 0);
   EXPECT_CALL(test_->pc(), GetSenders())
       .WillRepeatedly(
           Return(std::vector<rtc::scoped_refptr<RtpSenderInterface>>(
diff --git a/pc/rtpreceiver.cc b/pc/rtpreceiver.cc
index e318c17..98c501c 100644
--- a/pc/rtpreceiver.cc
+++ b/pc/rtpreceiver.cc
@@ -21,17 +21,6 @@
 
 namespace webrtc {
 
-namespace {
-
-// This function is only expected to be called on the signalling thread.
-int GenerateUniqueId() {
-  static int g_unique_id = 0;
-
-  return ++g_unique_id;
-}
-
-}  // namespace
-
 AudioRtpReceiver::AudioRtpReceiver(
     rtc::Thread* worker_thread,
     const std::string& receiver_id,
@@ -46,8 +35,7 @@
           AudioTrack::Create(
               receiver_id,
               RemoteAudioSource::Create(worker_thread, media_channel, ssrc)))),
-      cached_track_enabled_(track_->enabled()),
-      attachment_id_(GenerateUniqueId()) {
+      cached_track_enabled_(track_->enabled()) {
   RTC_DCHECK(worker_thread_);
   RTC_DCHECK(track_->GetSource()->remote());
   track_->RegisterObserver(this);
@@ -219,8 +207,7 @@
               VideoTrackSourceProxy::Create(rtc::Thread::Current(),
                                             worker_thread,
                                             source_),
-              worker_thread))),
-      attachment_id_(GenerateUniqueId()) {
+              worker_thread))) {
   RTC_DCHECK(worker_thread_);
   SetStreams(streams);
   source_->SetState(MediaSourceInterface::kLive);
diff --git a/pc/rtpreceiver.h b/pc/rtpreceiver.h
index 82c3134..e3848a7 100644
--- a/pc/rtpreceiver.h
+++ b/pc/rtpreceiver.h
@@ -107,7 +107,6 @@
   void SetMediaChannel(cricket::VoiceMediaChannel* media_channel);
 
   std::vector<RtpSource> GetSources() const override;
-  int AttachmentId() const override { return attachment_id_; }
 
  private:
   void Reconfigure();
@@ -124,7 +123,6 @@
   bool stopped_ = false;
   RtpReceiverObserverInterface* observer_ = nullptr;
   bool received_first_packet_ = false;
-  int attachment_id_ = 0;
 };
 
 class VideoRtpReceiver : public rtc::RefCountedObject<RtpReceiverInternal> {
@@ -194,7 +192,6 @@
   bool stopped_ = false;
   RtpReceiverObserverInterface* observer_ = nullptr;
   bool received_first_packet_ = false;
-  int attachment_id_ = 0;
 };
 
 }  // namespace webrtc
diff --git a/pc/rtpsender.cc b/pc/rtpsender.cc
index cad86f2..91e84d7 100644
--- a/pc/rtpsender.cc
+++ b/pc/rtpsender.cc
@@ -20,17 +20,6 @@
 
 namespace webrtc {
 
-namespace {
-
-// This function is only expected to be called on the signalling thread.
-int GenerateUniqueId() {
-  static int g_unique_id = 0;
-
-  return ++g_unique_id;
-}
-
-}  // namespace
-
 LocalAudioSinkAdapter::LocalAudioSinkAdapter() : sink_(nullptr) {}
 
 LocalAudioSinkAdapter::~LocalAudioSinkAdapter() {
@@ -71,8 +60,7 @@
           rtc::Thread::Current(),
           DtmfSender::Create(track_, rtc::Thread::Current(), this))),
       cached_track_enabled_(track ? track->enabled() : false),
-      sink_adapter_(new LocalAudioSinkAdapter()),
-      attachment_id_(track ? GenerateUniqueId() : 0) {
+      sink_adapter_(new LocalAudioSinkAdapter()) {
   // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are
   // supported.
   RTC_DCHECK_EQ(stream_labels.size(), 1u);
@@ -177,7 +165,6 @@
   } else if (prev_can_send_track) {
     ClearAudioSend();
   }
-  attachment_id_ = GenerateUniqueId();
   return true;
 }
 
@@ -289,10 +276,9 @@
       stream_ids_(stream_labels),
       track_(track),
       cached_track_enabled_(track ? track->enabled() : false),
-      cached_track_content_hint_(track
-                                     ? track->content_hint()
-                                     : VideoTrackInterface::ContentHint::kNone),
-      attachment_id_(track ? GenerateUniqueId() : 0) {
+      cached_track_content_hint_(
+          track ? track->content_hint()
+                : VideoTrackInterface::ContentHint::kNone) {
   // TODO(bugs.webrtc.org/7932): Remove once zero or multiple streams are
   // supported.
   RTC_DCHECK_EQ(stream_labels.size(), 1u);
@@ -354,7 +340,6 @@
   } else if (prev_can_send_track) {
     ClearVideoSend();
   }
-  attachment_id_ = GenerateUniqueId();
   return true;
 }
 
diff --git a/pc/rtpsender.h b/pc/rtpsender.h
index eb09d0b..a0c759a 100644
--- a/pc/rtpsender.h
+++ b/pc/rtpsender.h
@@ -137,8 +137,6 @@
 
   void Stop() override;
 
-  int AttachmentId() const override { return attachment_id_; }
-
   // Does not take ownership.
   // Should call SetChannel(nullptr) before |channel| is destroyed.
   void SetChannel(cricket::VoiceChannel* channel) { channel_ = channel; }
@@ -170,7 +168,6 @@
   // Used to pass the data callback from the |track_| to the other end of
   // cricket::AudioSource.
   std::unique_ptr<LocalAudioSinkAdapter> sink_adapter_;
-  int attachment_id_ = 0;
 };
 
 class VideoRtpSender : public ObserverInterface,
@@ -223,7 +220,6 @@
   }
 
   void Stop() override;
-  int AttachmentId() const override { return attachment_id_; }
 
   // Does not take ownership.
   // Should call SetChannel(nullptr) before |channel| is destroyed.
@@ -248,7 +244,6 @@
   VideoTrackInterface::ContentHint cached_track_content_hint_ =
       VideoTrackInterface::ContentHint::kNone;
   bool stopped_ = false;
-  int attachment_id_ = 0;
 };
 
 }  // namespace webrtc
diff --git a/pc/trackmediainfomap.cc b/pc/trackmediainfomap.cc
index 36e4eb3..3fbe3fa 100644
--- a/pc/trackmediainfomap.cc
+++ b/pc/trackmediainfomap.cc
@@ -125,14 +125,6 @@
       &local_video_track_by_ssrc, &remote_audio_track_by_ssrc,
       &remote_video_track_by_ssrc, &unsignaled_audio_track,
       &unsignaled_video_track);
-
-  for (auto& sender : rtp_senders) {
-    attachment_id_by_track_[sender->track()] = sender->AttachmentId();
-  }
-  for (auto& receiver : rtp_receivers) {
-    attachment_id_by_track_[receiver->track()] = receiver->AttachmentId();
-  }
-
   if (voice_media_info_) {
     for (auto& sender_info : voice_media_info_->senders) {
       AudioTrackInterface* associated_track =
@@ -266,11 +258,4 @@
   return FindValueOrNull(video_track_by_receiver_info_, &video_receiver_info);
 }
 
-rtc::Optional<int> TrackMediaInfoMap::GetAttachmentIdByTrack(
-    const MediaStreamTrackInterface* track) const {
-  auto it = attachment_id_by_track_.find(track);
-  return it != attachment_id_by_track_.end() ? rtc::Optional<int>(it->second)
-                                             : rtc::nullopt;
-}
-
 }  // namespace webrtc
diff --git a/pc/trackmediainfomap.h b/pc/trackmediainfomap.h
index c427c47..fd9a98e 100644
--- a/pc/trackmediainfomap.h
+++ b/pc/trackmediainfomap.h
@@ -74,13 +74,6 @@
   rtc::scoped_refptr<VideoTrackInterface> GetVideoTrack(
       const cricket::VideoReceiverInfo& video_receiver_info) const;
 
-  // TODO(hta): Remove this function, and redesign the callers not to need it.
-  // It is not going to work if a track is attached multiple times, and
-  // it is not going to work if a received track is attached as a sending
-  // track (loopback).
-  rtc::Optional<int> GetAttachmentIdByTrack(
-      const MediaStreamTrackInterface* track) const;
-
  private:
   std::unique_ptr<cricket::VoiceMediaInfo> voice_media_info_;
   std::unique_ptr<cricket::VideoMediaInfo> video_media_info_;
@@ -109,12 +102,6 @@
   std::map<const cricket::VideoReceiverInfo*,
            rtc::scoped_refptr<VideoTrackInterface>>
       video_track_by_receiver_info_;
-  // Map of tracks to attachment IDs.
-  // Necessary because senders and receivers live on the signaling thread,
-  // but the attachment IDs are needed while building stats on the networking
-  // thread, so we can't look them up in the senders/receivers without
-  // thread jumping.
-  std::map<const MediaStreamTrackInterface*, int> attachment_id_by_track_;
   // These maps map SSRCs to the corresponding voice or video info objects.
   std::map<uint32_t, cricket::VoiceSenderInfo*> voice_info_by_sender_ssrc_;
   std::map<uint32_t, cricket::VoiceReceiverInfo*> voice_info_by_receiver_ssrc_;
diff --git a/pc/trackmediainfomap_unittest.cc b/pc/trackmediainfomap_unittest.cc
index 583aa89..c05abe1 100644
--- a/pc/trackmediainfomap_unittest.cc
+++ b/pc/trackmediainfomap_unittest.cc
@@ -60,7 +60,6 @@
       .WillRepeatedly(testing::Return(media_type));
   EXPECT_CALL(*sender, GetParameters())
       .WillRepeatedly(testing::Return(CreateRtpParametersWithSsrcs(ssrcs)));
-  EXPECT_CALL(*sender, AttachmentId()).WillRepeatedly(testing::Return(1));
   return sender;
 }
 
@@ -76,7 +75,6 @@
       .WillRepeatedly(testing::Return(media_type));
   EXPECT_CALL(*receiver, GetParameters())
       .WillRepeatedly(testing::Return(CreateRtpParametersWithSsrcs(ssrcs)));
-  EXPECT_CALL(*receiver, AttachmentId()).WillRepeatedly(testing::Return(1));
   return receiver;
 }
 
@@ -402,14 +400,6 @@
   EXPECT_FALSE(map_->GetVoiceSenderInfoBySsrc(1024));
 }
 
-TEST_F(TrackMediaInfoMapTest, GetAttachmentIdByTrack) {
-  AddRtpSenderWithSsrcs({1}, local_audio_track_);
-  CreateMap();
-  EXPECT_EQ(rtp_senders_[0]->AttachmentId(),
-            map_->GetAttachmentIdByTrack(local_audio_track_));
-  EXPECT_EQ(rtc::nullopt, map_->GetAttachmentIdByTrack(local_video_track_));
-}
-
 // Death tests.
 // Disabled on Android because death tests misbehave on Android, see
 // base/test/gtest_util.h.