Expose RtpCodecParameters to VoiceMediaInfo stats.

Payload type -> RtpCodecParameters maps added for sender and receiver.
This is a follow-up to https://codereview.webrtc.org/2484193002/ which
did the same thing for VideoMediaInfo. This information will be used to
produce RTCCodecStats[1].

Voice[Sender/Receiver]Info is updated with current codec payload type
for every stream which can be used to look up the codec in
VoiceMediaInfo.

[1] https://w3c.github.io/webrtc-stats/#codec-dict*

BUG=chromium:659117

Review-Url: https://codereview.webrtc.org/2503383002
Cr-Commit-Position: refs/heads/master@{#15144}
diff --git a/webrtc/api/call/audio_receive_stream.h b/webrtc/api/call/audio_receive_stream.h
index ec80a9e..2fd6760 100644
--- a/webrtc/api/call/audio_receive_stream.h
+++ b/webrtc/api/call/audio_receive_stream.h
@@ -16,6 +16,7 @@
 #include <string>
 #include <vector>
 
+#include "webrtc/base/optional.h"
 #include "webrtc/base/scoped_ref_ptr.h"
 #include "webrtc/modules/audio_coding/codecs/audio_decoder_factory.h"
 #include "webrtc/common_types.h"
@@ -40,6 +41,7 @@
     uint32_t packets_lost = 0;
     float fraction_lost = 0.0f;
     std::string codec_name;
+    rtc::Optional<int> codec_payload_type;
     uint32_t ext_seqnum = 0;
     uint32_t jitter_ms = 0;
     uint32_t jitter_buffer_ms = 0;
diff --git a/webrtc/api/call/audio_send_stream.cc b/webrtc/api/call/audio_send_stream.cc
index 3ce35e7..b619007 100644
--- a/webrtc/api/call/audio_send_stream.cc
+++ b/webrtc/api/call/audio_send_stream.cc
@@ -30,6 +30,7 @@
 namespace webrtc {
 
 AudioSendStream::Stats::Stats() = default;
+AudioSendStream::Stats::~Stats() = default;
 
 AudioSendStream::Config::Config(Transport* send_transport)
     : send_transport(send_transport) {}
diff --git a/webrtc/api/call/audio_send_stream.h b/webrtc/api/call/audio_send_stream.h
index aab625e..b4ba615 100644
--- a/webrtc/api/call/audio_send_stream.h
+++ b/webrtc/api/call/audio_send_stream.h
@@ -15,6 +15,7 @@
 #include <string>
 #include <vector>
 
+#include "webrtc/base/optional.h"
 #include "webrtc/config.h"
 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
 #include "webrtc/transport.h"
@@ -31,6 +32,7 @@
  public:
   struct Stats {
     Stats();
+    ~Stats();
 
     // TODO(solenberg): Harmonize naming and defaults with receive stream stats.
     uint32_t local_ssrc = 0;
@@ -39,6 +41,7 @@
     int32_t packets_lost = -1;
     float fraction_lost = -1.0f;
     std::string codec_name;
+    rtc::Optional<int> codec_payload_type;
     int32_t ext_seqnum = -1;
     int32_t jitter_ms = -1;
     int64_t rtt_ms = -1;
diff --git a/webrtc/audio/audio_receive_stream.cc b/webrtc/audio/audio_receive_stream.cc
index 0d75307..5a8efc2 100644
--- a/webrtc/audio/audio_receive_stream.cc
+++ b/webrtc/audio/audio_receive_stream.cc
@@ -184,6 +184,7 @@
   stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
   if (codec_inst.pltype != -1) {
     stats.codec_name = codec_inst.plname;
+    stats.codec_payload_type = rtc::Optional<int>(codec_inst.pltype);
   }
   stats.ext_seqnum = call_stats.extendedMax;
   if (codec_inst.plfreq / 1000 > 0) {
diff --git a/webrtc/audio/audio_send_stream.cc b/webrtc/audio/audio_send_stream.cc
index 8c03dba..b031762 100644
--- a/webrtc/audio/audio_send_stream.cc
+++ b/webrtc/audio/audio_send_stream.cc
@@ -170,6 +170,7 @@
   if (codec->GetSendCodec(config_.voe_channel_id, codec_inst) != -1) {
     RTC_DCHECK_NE(codec_inst.pltype, -1);
     stats.codec_name = codec_inst.plname;
+    stats.codec_payload_type = rtc::Optional<int>(codec_inst.pltype);
 
     // Get data from the last remote RTCP report.
     for (const auto& block : channel_proxy_->GetRemoteRTCPReportBlocks()) {
diff --git a/webrtc/media/base/mediachannel.h b/webrtc/media/base/mediachannel.h
index 80b9d4d..d4d339e 100644
--- a/webrtc/media/base/mediachannel.h
+++ b/webrtc/media/base/mediachannel.h
@@ -553,6 +553,7 @@
   float fraction_lost;
   int64_t rtt_ms;
   std::string codec_name;
+  rtc::Optional<int> codec_payload_type;
   std::vector<SsrcSenderInfo> local_stats;
   std::vector<SsrcReceiverInfo> remote_stats;
 };
@@ -598,6 +599,7 @@
   int packets_lost;
   float fraction_lost;
   std::string codec_name;
+  rtc::Optional<int> codec_payload_type;
   std::vector<SsrcReceiverInfo> local_stats;
   std::vector<SsrcSenderInfo> remote_stats;
 };
@@ -698,9 +700,6 @@
   std::vector<SsrcGroup> ssrc_groups;
   // TODO(hbos): Move this to |VideoMediaInfo::send_codecs|?
   std::string encoder_implementation_name;
-  // TODO(hbos): Move this to |MediaSenderInfo| when supported by
-  // |VoiceSenderInfo| as well (which also extends that class).
-  rtc::Optional<uint32_t> codec_payload_type;
   int packets_cached;
   int firs_rcvd;
   int plis_rcvd;
@@ -746,9 +745,6 @@
   std::vector<SsrcGroup> ssrc_groups;
   // TODO(hbos): Move this to |VideoMediaInfo::receive_codecs|?
   std::string decoder_implementation_name;
-  // TODO(hbos): Move this to |MediaReceiverInfo| when supported by
-  // |VoiceReceiverInfo| as well (which also extends that class).
-  rtc::Optional<uint32_t> codec_payload_type;
   int packets_concealed;
   int firs_sent;
   int plis_sent;
@@ -831,9 +827,13 @@
   void Clear() {
     senders.clear();
     receivers.clear();
+    send_codecs.clear();
+    receive_codecs.clear();
   }
   std::vector<VoiceSenderInfo> senders;
   std::vector<VoiceReceiverInfo> receivers;
+  RtpCodecParametersMap send_codecs;
+  RtpCodecParametersMap receive_codecs;
 };
 
 struct VideoMediaInfo {
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
index c43dff8..5238348 100644
--- a/webrtc/media/engine/webrtcvideoengine2.cc
+++ b/webrtc/media/engine/webrtcvideoengine2.cc
@@ -2025,8 +2025,8 @@
 
   if (parameters_.codec_settings) {
     info.codec_name = parameters_.codec_settings->codec.name;
-    info.codec_payload_type = rtc::Optional<uint32_t>(
-        static_cast<uint32_t>(parameters_.codec_settings->codec.id));
+    info.codec_payload_type = rtc::Optional<int>(
+        parameters_.codec_settings->codec.id);
   }
 
   if (stream_ == NULL)
@@ -2436,8 +2436,8 @@
   webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
   info.decoder_implementation_name = stats.decoder_implementation_name;
   if (stats.current_payload_type != -1) {
-    info.codec_payload_type = rtc::Optional<uint32_t>(
-        static_cast<uint32_t>(stats.current_payload_type));
+    info.codec_payload_type = rtc::Optional<int>(
+        stats.current_payload_type);
   }
   info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes +
                     stats.rtp_stats.transmitted.header_bytes +
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index 937078c..57921ac 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -2526,7 +2526,7 @@
   RTC_DCHECK(info);
 
   // Get SSRC and stats for each sender.
-  RTC_DCHECK(info->senders.size() == 0);
+  RTC_DCHECK_EQ(info->senders.size(), 0U);
   for (const auto& stream : send_streams_) {
     webrtc::AudioSendStream::Stats stats = stream.second->GetStats();
     VoiceSenderInfo sinfo;
@@ -2536,6 +2536,7 @@
     sinfo.packets_lost = stats.packets_lost;
     sinfo.fraction_lost = stats.fraction_lost;
     sinfo.codec_name = stats.codec_name;
+    sinfo.codec_payload_type = stats.codec_payload_type;
     sinfo.ext_seqnum = stats.ext_seqnum;
     sinfo.jitter_ms = stats.jitter_ms;
     sinfo.rtt_ms = stats.rtt_ms;
@@ -2551,7 +2552,7 @@
   }
 
   // Get SSRC and stats for each receiver.
-  RTC_DCHECK(info->receivers.size() == 0);
+  RTC_DCHECK_EQ(info->receivers.size(), 0U);
   for (const auto& stream : recv_streams_) {
     webrtc::AudioReceiveStream::Stats stats = stream.second->GetStats();
     VoiceReceiverInfo rinfo;
@@ -2561,6 +2562,7 @@
     rinfo.packets_lost = stats.packets_lost;
     rinfo.fraction_lost = stats.fraction_lost;
     rinfo.codec_name = stats.codec_name;
+    rinfo.codec_payload_type = stats.codec_payload_type;
     rinfo.ext_seqnum = stats.ext_seqnum;
     rinfo.jitter_ms = stats.jitter_ms;
     rinfo.jitter_buffer_ms = stats.jitter_buffer_ms;
@@ -2584,6 +2586,18 @@
     info->receivers.push_back(rinfo);
   }
 
+  // Get codec info
+  for (const AudioCodec& codec : send_codecs_) {
+    webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
+    info->send_codecs.insert(
+        std::make_pair(codec_params.payload_type, std::move(codec_params)));
+  }
+  for (const AudioCodec& codec : recv_codecs_) {
+    webrtc::RtpCodecParameters codec_params = codec.ToCodecParameters();
+    info->receive_codecs.insert(
+        std::make_pair(codec_params.payload_type, std::move(codec_params)));
+  }
+
   return true;
 }
 
diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
index 3b4670e..e4e4cf1 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -446,6 +446,7 @@
     stats.packets_lost = 9012;
     stats.fraction_lost = 34.56f;
     stats.codec_name = "codec_name_send";
+    stats.codec_payload_type = rtc::Optional<int>(42);
     stats.ext_seqnum = 789;
     stats.jitter_ms = 12;
     stats.rtt_ms = 345;
@@ -473,6 +474,7 @@
     EXPECT_EQ(info.packets_lost, stats.packets_lost);
     EXPECT_EQ(info.fraction_lost, stats.fraction_lost);
     EXPECT_EQ(info.codec_name, stats.codec_name);
+    EXPECT_EQ(info.codec_payload_type, stats.codec_payload_type);
     EXPECT_EQ(info.ext_seqnum, stats.ext_seqnum);
     EXPECT_EQ(info.jitter_ms, stats.jitter_ms);
     EXPECT_EQ(info.rtt_ms, stats.rtt_ms);
@@ -496,6 +498,7 @@
     stats.packets_lost = 101;
     stats.fraction_lost = 23.45f;
     stats.codec_name = "codec_name_recv";
+    stats.codec_payload_type = rtc::Optional<int>(42);
     stats.ext_seqnum = 678;
     stats.jitter_ms = 901;
     stats.jitter_buffer_ms = 234;
@@ -530,6 +533,7 @@
     EXPECT_EQ(info.packets_lost, stats.packets_lost);
     EXPECT_EQ(info.fraction_lost, stats.fraction_lost);
     EXPECT_EQ(info.codec_name, stats.codec_name);
+    EXPECT_EQ(info.codec_payload_type, stats.codec_payload_type);
     EXPECT_EQ(info.ext_seqnum, stats.ext_seqnum);
     EXPECT_EQ(info.jitter_ms, stats.jitter_ms);
     EXPECT_EQ(info.jitter_buffer_ms, stats.jitter_buffer_ms);
@@ -552,6 +556,20 @@
     EXPECT_EQ(info.decoding_muted_output, stats.decoding_muted_output);
     EXPECT_EQ(info.capture_start_ntp_time_ms, stats.capture_start_ntp_time_ms);
   }
+  void VerifyVoiceSendRecvCodecs(const cricket::VoiceMediaInfo& info) const {
+    EXPECT_EQ(send_parameters_.codecs.size(), info.send_codecs.size());
+    for (const cricket::AudioCodec& codec : send_parameters_.codecs) {
+      ASSERT_EQ(info.send_codecs.count(codec.id), 1U);
+      EXPECT_EQ(info.send_codecs.find(codec.id)->second,
+                codec.ToCodecParameters());
+    }
+    EXPECT_EQ(recv_parameters_.codecs.size(), info.receive_codecs.size());
+    for (const cricket::AudioCodec& codec : recv_parameters_.codecs) {
+      ASSERT_EQ(info.receive_codecs.count(codec.id), 1U);
+      EXPECT_EQ(info.receive_codecs.find(codec.id)->second,
+                codec.ToCodecParameters());
+    }
+  }
 
  protected:
   StrictMock<webrtc::test::MockAudioDeviceModule> adm_;
@@ -2275,6 +2293,7 @@
     for (const auto& sender : info.senders) {
       VerifyVoiceSenderInfo(sender, false);
     }
+    VerifyVoiceSendRecvCodecs(info);
 
     // We have added one receive stream. We should see empty stats.
     EXPECT_EQ(info.receivers.size(), 1u);
@@ -2300,6 +2319,7 @@
     EXPECT_EQ(static_cast<size_t>(arraysize(kSsrcs4)), info.senders.size());
     EXPECT_EQ(1u, info.receivers.size());
     VerifyVoiceReceiverInfo(info.receivers[0]);
+    VerifyVoiceSendRecvCodecs(info);
   }
 }
 
@@ -2483,6 +2503,7 @@
     SetSend(true);
     EXPECT_EQ(true, channel_->GetStats(&info));
     VerifyVoiceSenderInfo(info.senders[0], true);
+    VerifyVoiceSendRecvCodecs(info);
   }
 
   // Remove the kSsrc2 stream. No receiver stats.
@@ -2504,6 +2525,7 @@
     EXPECT_EQ(1u, info.senders.size());
     EXPECT_EQ(1u, info.receivers.size());
     VerifyVoiceReceiverInfo(info.receivers[0]);
+    VerifyVoiceSendRecvCodecs(info);
   }
 }