Bug 1524145: set Opus stereo on send stream with 2 channels. r=dminor a=lizzard
authorNils Ohlmeier [:drno] <drno@ohlmeier.org>
Fri, 01 Feb 2019 18:28:10 +0000
changeset 513015 8b1e6095f35500a4a5d7b9e20ce14e3014f4db17
parent 513014 3e57fe219beb57862951db5c6ab6f109b23db212
child 513016 9a31c95f8563687c2a90fe53e2cdc74adcbdd40c
push id10681
push userdluca@mozilla.com
push dateTue, 12 Feb 2019 11:10:25 +0000
treeherdermozilla-beta@8b1e6095f355 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdminor, lizzard
bugs1524145
milestone66.0
Bug 1524145: set Opus stereo on send stream with 2 channels. r=dminor a=lizzard Differential Revision: https://phabricator.services.mozilla.com/D18175
media/webrtc/signaling/gtest/audioconduit_unittests.cpp
media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
--- a/media/webrtc/signaling/gtest/audioconduit_unittests.cpp
+++ b/media/webrtc/signaling/gtest/audioconduit_unittests.cpp
@@ -84,16 +84,27 @@ class AudioConduitTest : public ::testin
 
 TEST_F(AudioConduitTest, TestConfigureSendMediaCodec) {
   MediaConduitErrorCode ec;
 
   // defaults
   AudioCodecConfig codecConfig(114, "opus", 48000, 2, false);
   ec = mAudioConduit->ConfigureSendMediaCodec(&codecConfig);
   ASSERT_EQ(ec, kMediaConduitNoError);
+  {
+    const webrtc::SdpAudioFormat& f =
+        mCall->mAudioSendConfig.send_codec_spec->format;
+    ASSERT_EQ(f.name, "opus");
+    ASSERT_EQ(f.clockrate_hz, 48000);
+    ASSERT_EQ(f.num_channels, 2UL);
+    ASSERT_NE(f.parameters.find("stereo"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("stereo"), "1");
+    ASSERT_EQ(f.parameters.find("maxplaybackrate"), f.parameters.end());
+    ASSERT_EQ(f.parameters.find("useinbandfec"), f.parameters.end());
+  }
 
   // null codec
   ec = mAudioConduit->ConfigureSendMediaCodec(nullptr);
   ASSERT_EQ(ec, kMediaConduitMalformedArgument);
 
   // empty codec name
   codecConfig = AudioCodecConfig(114, "", 48000, 2, false);
   ec = mAudioConduit->ConfigureSendMediaCodec(&codecConfig);
@@ -105,33 +116,96 @@ TEST_F(AudioConduitTest, TestConfigureSe
   memset(longName, 'A', longNameLength - 2);
   longName[longNameLength - 1] = 0;
   codecConfig = AudioCodecConfig(114, longName, 48000, 2, false);
   ec = mAudioConduit->ConfigureSendMediaCodec(&codecConfig);
   ASSERT_EQ(ec, kMediaConduitMalformedArgument);
   delete[] longName;
 }
 
+TEST_F(AudioConduitTest, TestConfigureSendOpusMono) {
+  MediaConduitErrorCode ec;
+
+  // opus mono
+  AudioCodecConfig codecConfig = AudioCodecConfig(114, "opus", 48000, 1, false);
+  ec = mAudioConduit->ConfigureSendMediaCodec(&codecConfig);
+  ASSERT_EQ(ec, kMediaConduitNoError);
+  {
+    const webrtc::SdpAudioFormat& f =
+        mCall->mAudioSendConfig.send_codec_spec->format;
+    ASSERT_EQ(f.name, "opus");
+    ASSERT_EQ(f.clockrate_hz, 48000);
+    ASSERT_EQ(f.num_channels, 1UL);
+    ASSERT_EQ(f.parameters.find("stereo"), f.parameters.end());
+    ASSERT_EQ(f.parameters.find("maxplaybackrate"), f.parameters.end());
+    ASSERT_EQ(f.parameters.find("useinbandfec"), f.parameters.end());
+  }
+}
+
+TEST_F(AudioConduitTest, TestConfigureSendOpusFEC) {
+  MediaConduitErrorCode ec;
+
+  // opus with inband Forward Error Correction
+  AudioCodecConfig codecConfig = AudioCodecConfig(114, "opus", 48000, 2, true);
+  ec = mAudioConduit->ConfigureSendMediaCodec(&codecConfig);
+  ASSERT_EQ(ec, kMediaConduitNoError);
+  {
+    const webrtc::SdpAudioFormat& f =
+        mCall->mAudioSendConfig.send_codec_spec->format;
+    ASSERT_EQ(f.name, "opus");
+    ASSERT_EQ(f.clockrate_hz, 48000);
+    ASSERT_EQ(f.num_channels, 2UL);
+    ASSERT_NE(f.parameters.find("stereo"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("stereo"), "1");
+    ASSERT_NE(f.parameters.find("useinbandfec"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("useinbandfec"), "1");
+    ASSERT_EQ(f.parameters.find("maxplaybackrate"), f.parameters.end());
+  }
+}
+
+TEST_F(AudioConduitTest, TestConfigureSendMaxPlaybackRate) {
+  MediaConduitErrorCode ec;
+
+  AudioCodecConfig codecConfig = AudioCodecConfig(114, "opus", 48000, 2, false);
+  codecConfig.mMaxPlaybackRate = 1234;
+  ec = mAudioConduit->ConfigureSendMediaCodec(&codecConfig);
+  ASSERT_EQ(ec, kMediaConduitNoError);
+  {
+    const webrtc::SdpAudioFormat& f =
+        mCall->mAudioSendConfig.send_codec_spec->format;
+    ASSERT_EQ(f.name, "opus");
+    ASSERT_EQ(f.clockrate_hz, 48000);
+    ASSERT_EQ(f.num_channels, 2UL);
+    ASSERT_NE(f.parameters.find("stereo"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("stereo"), "1");
+    ASSERT_EQ(f.parameters.find("useinbandfec"), f.parameters.end());
+    ASSERT_NE(f.parameters.find("maxplaybackrate"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("maxplaybackrate"), "1234");
+  }
+}
+
 TEST_F(AudioConduitTest, TestConfigureReceiveMediaCodecs) {
   MediaConduitErrorCode ec;
 
-  // just opus
+  // just default opus stereo
   std::vector<UniquePtr<mozilla::AudioCodecConfig>> codecs;
   codecs.emplace_back(new AudioCodecConfig(114, "opus", 48000, 2, false));
   ec = mAudioConduit->ConfigureRecvMediaCodecs(codecs);
   ASSERT_EQ(ec, kMediaConduitNoError);
   ASSERT_EQ(mCall->mAudioReceiveConfig.sync_group, "");
   ASSERT_EQ(mCall->mAudioReceiveConfig.decoder_map.size(), 1U);
   {
     const webrtc::SdpAudioFormat& f =
         mCall->mAudioReceiveConfig.decoder_map.at(114);
     ASSERT_EQ(f.name, "opus");
     ASSERT_EQ(f.clockrate_hz, 48000);
     ASSERT_EQ(f.num_channels, 2UL);
     ASSERT_EQ(f.parameters.at("stereo"), "1");
+    ASSERT_EQ(f.parameters.find("maxplaybackrate"), f.parameters.end());
+    ASSERT_EQ(f.parameters.find("useinbandfec"), f.parameters.end());
   }
 
   // multiple codecs
   codecs.clear();
   codecs.emplace_back(new AudioCodecConfig(9, "g722", 16000, 2, false));
   codecs.emplace_back(new AudioCodecConfig(114, "opus", 48000, 2, false));
   ec = mAudioConduit->ConfigureRecvMediaCodecs(codecs);
   ASSERT_EQ(ec, kMediaConduitNoError);
@@ -184,17 +258,63 @@ TEST_F(AudioConduitTest, TestConfigureRe
   memset(longName, 'A', longNameLength - 2);
   longName[longNameLength - 1] = 0;
   codecs.emplace_back(new AudioCodecConfig(100, longName, 48000, 42, false));
   ec = mAudioConduit->ConfigureRecvMediaCodecs(codecs);
   ASSERT_EQ(ec, kMediaConduitMalformedArgument);
   delete[] longName;
 }
 
-TEST_F(AudioConduitTest, TestConfigureMaxPlaybackRate) {
+TEST_F(AudioConduitTest, TestConfigureReceiveOpusMono) {
+  MediaConduitErrorCode ec;
+
+  // opus mono
+  std::vector<UniquePtr<mozilla::AudioCodecConfig>> codecs;
+  codecs.emplace_back(new AudioCodecConfig(114, "opus", 48000, 1, false));
+  ec = mAudioConduit->ConfigureRecvMediaCodecs(codecs);
+  ASSERT_EQ(ec, kMediaConduitNoError);
+  ASSERT_EQ(mCall->mAudioReceiveConfig.sync_group, "");
+  ASSERT_EQ(mCall->mAudioReceiveConfig.decoder_map.size(), 1U);
+  {
+    const webrtc::SdpAudioFormat& f =
+        mCall->mAudioReceiveConfig.decoder_map.at(114);
+    ASSERT_EQ(f.name, "opus");
+    ASSERT_EQ(f.clockrate_hz, 48000);
+    ASSERT_EQ(f.num_channels, 1UL);
+    ASSERT_EQ(f.parameters.find("stereo"), f.parameters.end());
+    ASSERT_EQ(f.parameters.find("maxplaybackrate"), f.parameters.end());
+    ASSERT_EQ(f.parameters.find("useinbandfec"), f.parameters.end());
+  }
+}
+
+TEST_F(AudioConduitTest, TestConfigureReceiveOpusFEC) {
+  MediaConduitErrorCode ec;
+
+  // opus with inband Forward Error Correction
+  std::vector<UniquePtr<mozilla::AudioCodecConfig>> codecs;
+  codecs.emplace_back(new AudioCodecConfig(114, "opus", 48000, 2, true));
+  ec = mAudioConduit->ConfigureRecvMediaCodecs(codecs);
+  ASSERT_EQ(ec, kMediaConduitNoError);
+  ASSERT_EQ(mCall->mAudioReceiveConfig.sync_group, "");
+  ASSERT_EQ(mCall->mAudioReceiveConfig.decoder_map.size(), 1U);
+  {
+    const webrtc::SdpAudioFormat& f =
+        mCall->mAudioReceiveConfig.decoder_map.at(114);
+    ASSERT_EQ(f.name, "opus");
+    ASSERT_EQ(f.clockrate_hz, 48000);
+    ASSERT_EQ(f.num_channels, 2UL);
+    ASSERT_NE(f.parameters.find("stereo"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("stereo"), "1");
+    ASSERT_NE(f.parameters.find("useinbandfec"), f.parameters.end());
+    ASSERT_EQ(f.parameters.at("useinbandfec"), "1");
+    ASSERT_EQ(f.parameters.find("maxplaybackrate"), f.parameters.end());
+  }
+}
+
+TEST_F(AudioConduitTest, TestConfigureReceiveMaxPlaybackRate) {
   MediaConduitErrorCode ec;
 
   std::vector<UniquePtr<mozilla::AudioCodecConfig>> codecs;
   codecs.emplace_back(new AudioCodecConfig(114, "opus", 48000, 2, false));
 
   codecs[0]->mMaxPlaybackRate = 0;
   ec = mAudioConduit->ConfigureRecvMediaCodecs(codecs);
   ASSERT_EQ(ec, kMediaConduitNoError);
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
@@ -407,18 +407,22 @@ MediaConduitErrorCode WebrtcAudioConduit
     // if the codec param is invalid or diplicate, return error
     if ((condError = ValidateCodecConfig(codec.get(), false)) !=
         kMediaConduitNoError) {
       return condError;
     }
 
     webrtc::SdpAudioFormat::Parameters parameters;
     if (codec->mName == "opus") {
-      parameters = {{"stereo", "1"}};
-
+      if (codec->mChannels == 2) {
+        parameters = {{"stereo", "1"}};
+      }
+      if (codec->mFECEnabled) {
+        parameters["useinbandfec"] = "1";
+      }
       if (codec->mMaxPlaybackRate) {
         std::ostringstream o;
         o << codec->mMaxPlaybackRate;
         parameters["maxplaybackrate"] = o.str();
       }
     }
 
     webrtc::SdpAudioFormat format(codec->mName, codec->mFreq, codec->mChannels,
@@ -848,24 +852,28 @@ bool WebrtcAudioConduit::SendRtcp(const 
  */
 
 bool WebrtcAudioConduit::CodecConfigToWebRTCCodec(
     const AudioCodecConfig* codecInfo,
     webrtc::AudioSendStream::Config& config) {
   config.encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
 
   webrtc::SdpAudioFormat::Parameters parameters;
-  if (codecInfo->mFECEnabled) {
-    parameters["useinbandfec"] = "1";
-  }
-
-  if (codecInfo->mName == "opus" && codecInfo->mMaxPlaybackRate) {
-    std::ostringstream o;
-    o << codecInfo->mMaxPlaybackRate;
-    parameters["maxplaybackrate"] = o.str();
+  if (codecInfo->mName == "opus") {
+    if (codecInfo->mChannels == 2) {
+      parameters["stereo"] = "1";
+    }
+    if (codecInfo->mFECEnabled) {
+      parameters["useinbandfec"] = "1";
+    }
+    if (codecInfo->mMaxPlaybackRate) {
+      std::ostringstream o;
+      o << codecInfo->mMaxPlaybackRate;
+      parameters["maxplaybackrate"] = o.str();
+    }
   }
 
   webrtc::SdpAudioFormat format(codecInfo->mName, codecInfo->mFreq,
                                 codecInfo->mChannels, parameters);
   webrtc::AudioSendStream::Config::SendCodecSpec spec(codecInfo->mType, format);
   config.send_codec_spec = spec;
 
   return true;