Add audio_level member to RtpSource and set it from RtpReceiverImpl::IncomingRtpPacket.

BUG=webrtc:7987

Review-Url: https://codereview.webrtc.org/3000713002
Cr-Original-Commit-Position: refs/heads/master@{#19503}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 2b706343de6f79839f46d12008ec3c8062bb94bc
diff --git a/api/rtpreceiverinterface.h b/api/rtpreceiverinterface.h
index ce4abeb..3119fb7 100644
--- a/api/rtpreceiverinterface.h
+++ b/api/rtpreceiverinterface.h
@@ -39,6 +39,15 @@
         source_id_(source_id),
         source_type_(source_type) {}
 
+  RtpSource(int64_t timestamp_ms,
+            uint32_t source_id,
+            RtpSourceType source_type,
+            uint8_t audio_level)
+      : timestamp_ms_(timestamp_ms),
+        source_id_(source_id),
+        source_type_(source_type),
+        audio_level_(audio_level) {}
+
   int64_t timestamp_ms() const { return timestamp_ms_; }
   void update_timestamp_ms(int64_t timestamp_ms) {
     RTC_DCHECK_LE(timestamp_ms_, timestamp_ms);
@@ -51,19 +60,21 @@
   // The source can be either a contributing source or a synchronization source.
   RtpSourceType source_type() const { return source_type_; }
 
-  // This isn't implemented yet and will always return an empty Optional.
-  // TODO(zhihuang): Implement this to return real audio level.
-  rtc::Optional<int8_t> audio_level() const { return rtc::Optional<int8_t>(); }
+  rtc::Optional<uint8_t> audio_level() const { return audio_level_; }
+  void set_audio_level(const rtc::Optional<uint8_t>& level) {
+    audio_level_ = level;
+  }
 
   bool operator==(const RtpSource& o) const {
     return timestamp_ms_ == o.timestamp_ms() && source_id_ == o.source_id() &&
-           source_type_ == o.source_type();
+           source_type_ == o.source_type() && audio_level_ == o.audio_level_;
   }
 
  private:
   int64_t timestamp_ms_;
   uint32_t source_id_;
   RtpSourceType source_type_;
+  rtc::Optional<uint8_t> audio_level_;
 };
 
 class RtpReceiverObserverInterface {
diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/modules/rtp_rtcp/source/rtp_receiver_impl.cc
index 20f5746..ed0383f 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_impl.cc
@@ -163,7 +163,11 @@
   webrtc_rtp_header.header = rtp_header;
   CheckCSRC(webrtc_rtp_header);
 
-  UpdateSources();
+  auto audio_level =
+      rtp_header.extension.hasAudioLevel
+          ? rtc::Optional<uint8_t>(rtp_header.extension.audioLevel)
+          : rtc::Optional<uint8_t>();
+  UpdateSources(audio_level);
 
   size_t payload_data_length = payload_length - rtp_header.paddingLength;
 
@@ -500,7 +504,8 @@
   }
 }
 
-void RtpReceiverImpl::UpdateSources() {
+void RtpReceiverImpl::UpdateSources(
+    const rtc::Optional<uint8_t>& ssrc_audio_level) {
   rtc::CritScope lock(&critical_section_rtp_receiver_);
   int64_t now_ms = clock_->TimeInMilliseconds();
 
@@ -527,6 +532,8 @@
     ssrc_sources_.rbegin()->update_timestamp_ms(now_ms);
   }
 
+  ssrc_sources_.back().set_audio_level(ssrc_audio_level);
+
   RemoveOutdatedSources(now_ms);
 }
 
diff --git a/modules/rtp_rtcp/source/rtp_receiver_impl.h b/modules/rtp_rtcp/source/rtp_receiver_impl.h
index b64683a..6d38cf7 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_impl.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_impl.h
@@ -79,7 +79,7 @@
                               bool* is_red,
                               PayloadUnion* payload);
 
-  void UpdateSources();
+  void UpdateSources(const rtc::Optional<uint8_t>& ssrc_audio_level);
   void RemoveOutdatedSources(int64_t now_ms);
 
   Clock* clock_;
diff --git a/modules/rtp_rtcp/source/rtp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
index b0531c3..e20d2d5 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_receiver_unittest.cc
@@ -255,4 +255,88 @@
             csrc_sources.begin()->timestamp_ms());
 }
 
+// The audio level from the RTPHeader extension should be stored in the
+// RtpSource with the matching SSRC.
+TEST_F(RtpReceiverTest, GetSourcesContainsAudioLevelExtension) {
+  RTPHeader header;
+  int64_t time1_ms = fake_clock_.TimeInMilliseconds();
+  header.payloadType = kPcmuPayloadType;
+  header.ssrc = kSsrc1;
+  header.timestamp = rtp_timestamp(time1_ms);
+  header.extension.hasAudioLevel = true;
+  header.extension.audioLevel = 10;
+  PayloadUnion payload_specific = {AudioPayload()};
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+  auto sources = rtp_receiver_->GetSources();
+  EXPECT_THAT(sources, UnorderedElementsAre(RtpSource(
+                           time1_ms, kSsrc1, RtpSourceType::SSRC, 10)));
+
+  // Receive a packet from a different SSRC with a different level and check
+  // that they are both remembered.
+  fake_clock_.AdvanceTimeMilliseconds(1);
+  int64_t time2_ms = fake_clock_.TimeInMilliseconds();
+  header.ssrc = kSsrc2;
+  header.timestamp = rtp_timestamp(time2_ms);
+  header.extension.hasAudioLevel = true;
+  header.extension.audioLevel = 20;
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+  sources = rtp_receiver_->GetSources();
+  EXPECT_THAT(sources,
+              UnorderedElementsAre(
+                  RtpSource(time1_ms, kSsrc1, RtpSourceType::SSRC, 10),
+                  RtpSource(time2_ms, kSsrc2, RtpSourceType::SSRC, 20)));
+
+  // Receive a packet from the first SSRC again and check that the level is
+  // updated.
+  fake_clock_.AdvanceTimeMilliseconds(1);
+  int64_t time3_ms = fake_clock_.TimeInMilliseconds();
+  header.ssrc = kSsrc1;
+  header.timestamp = rtp_timestamp(time3_ms);
+  header.extension.hasAudioLevel = true;
+  header.extension.audioLevel = 30;
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+  sources = rtp_receiver_->GetSources();
+  EXPECT_THAT(sources,
+              UnorderedElementsAre(
+                  RtpSource(time3_ms, kSsrc1, RtpSourceType::SSRC, 30),
+                  RtpSource(time2_ms, kSsrc2, RtpSourceType::SSRC, 20)));
+}
+
+TEST_F(RtpReceiverTest,
+       MissingAudioLevelHeaderExtensionClearsRtpSourceAudioLevel) {
+  RTPHeader header;
+  int64_t time1_ms = fake_clock_.TimeInMilliseconds();
+  header.payloadType = kPcmuPayloadType;
+  header.ssrc = kSsrc1;
+  header.timestamp = rtp_timestamp(time1_ms);
+  header.extension.hasAudioLevel = true;
+  header.extension.audioLevel = 10;
+  PayloadUnion payload_specific = {AudioPayload()};
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+  auto sources = rtp_receiver_->GetSources();
+  EXPECT_THAT(sources, UnorderedElementsAre(RtpSource(
+                           time1_ms, kSsrc1, RtpSourceType::SSRC, 10)));
+
+  // Receive a second packet without the audio level header extension and check
+  // that the audio level is cleared.
+  fake_clock_.AdvanceTimeMilliseconds(1);
+  int64_t time2_ms = fake_clock_.TimeInMilliseconds();
+  header.timestamp = rtp_timestamp(time2_ms);
+  header.extension.hasAudioLevel = false;
+
+  EXPECT_TRUE(rtp_receiver_->IncomingRtpPacket(
+      header, kTestPayload, sizeof(kTestPayload), payload_specific, !kInOrder));
+  sources = rtp_receiver_->GetSources();
+  EXPECT_THAT(sources, UnorderedElementsAre(
+                           RtpSource(time2_ms, kSsrc1, RtpSourceType::SSRC)));
+}
+
 }  // namespace webrtc