Bug 1279049 - add sdp handling for audio FEC, r=jesup draft
authorMichael Froman <mfroman@mozilla.com>
Wed, 08 Jun 2016 16:24:23 -0500
changeset 377165 d55915e6c364f5bd9bd7ccbadade122e88dda15b
parent 376593 f8ad071a6e14331d73fa44c8d3108bc2b66b2174
child 523326 7a080bc207579df56ba40e5445ea36c1e6f2fca1
push id20766
push usermfroman@nostrum.com
push dateThu, 09 Jun 2016 19:39:09 +0000
reviewersjesup
bugs1279049
milestone50.0a1
Bug 1279049 - add sdp handling for audio FEC, r=jesup MozReview-Commit-ID: J0ax8TnR3p8
media/webrtc/signaling/src/jsep/JsepCodecDescription.h
media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
media/webrtc/signaling/src/sdp/SdpAttribute.h
media/webrtc/signaling/src/sdp/SipccSdpAttributeList.cpp
media/webrtc/signaling/test/sdp_unittests.cpp
modules/libpref/init/all.js
--- a/media/webrtc/signaling/src/jsep/JsepCodecDescription.h
+++ b/media/webrtc/signaling/src/jsep/JsepCodecDescription.h
@@ -167,31 +167,36 @@ class JsepAudioCodecDescription : public
           GetOpusParameters(mDefaultPt, msection));
       if (mMaxPlaybackRate) {
         opusParams.maxplaybackrate = mMaxPlaybackRate;
       }
       if (mChannels == 2 && !mForceMono) {
         // We prefer to receive stereo, if available.
         opusParams.stereo = 1;
       }
+      opusParams.useInBandFec = mFECEnabled ? 1 : 0;
       msection.SetFmtp(SdpFmtpAttributeList::Fmtp(mDefaultPt, opusParams));
     }
   }
 
   bool
   Negotiate(const std::string& pt,
             const SdpMediaSection& remoteMsection) override
   {
     JsepCodecDescription::Negotiate(pt, remoteMsection);
     if (mName == "opus" && mDirection == sdp::kSend) {
       SdpFmtpAttributeList::OpusParameters opusParams(
           GetOpusParameters(mDefaultPt, remoteMsection));
 
       mMaxPlaybackRate = opusParams.maxplaybackrate;
       mForceMono = !opusParams.stereo;
+      // draft-ietf-rtcweb-fec-03.txt section 4.2 says support for FEC
+      // at the received side is declarative and can be negotiated
+      // separately for either media direction.
+      mFECEnabled = opusParams.useInBandFec;
     }
 
     return true;
   }
 
   uint32_t mPacketSize;
   uint32_t mBitrate;
   uint32_t mMaxPlaybackRate;
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -870,17 +870,18 @@ class ConfigureCodec {
       mH264Enabled(false),
       mVP9Enabled(false),
       mH264Level(13), // minimum suggested for WebRTC spec
       mH264MaxBr(0), // Unlimited
       mH264MaxMbps(0), // Unlimited
       mVP8MaxFs(0),
       mVP8MaxFr(0),
       mUseTmmbr(false),
-      mUseRemb(false)
+      mUseRemb(false),
+      mUseAudioFec(false)
     {
 #ifdef MOZ_WEBRTC_OMX
       // Check to see if what HW codecs are available (not in use) at this moment.
       // Note that streaming video decode can reserve a decoder
 
       // XXX See bug 1018791 Implement W3 codec reservation policy
       // Note that currently, OMXCodecReservation needs to be held by an sp<> because it puts
       // 'this' into an sp<EventListener> to talk to the resource reservation code
@@ -939,23 +940,31 @@ class ConfigureCodec {
         mVP8MaxFr = 60; // We must specify something other than 0
       }
 
       // TMMBR is enabled from a pref in about:config
       branch->GetBoolPref("media.navigator.video.use_tmmbr", &mUseTmmbr);
 
       // REMB is enabled by default, but can be disabled from about:config
       branch->GetBoolPref("media.navigator.video.use_remb", &mUseRemb);
+
+      branch->GetBoolPref("media.navigator.audio.use_fec", &mUseAudioFec);
     }
 
     void operator()(JsepCodecDescription* codec) const
     {
       switch (codec->mType) {
         case SdpMediaSection::kAudio:
-          // Nothing to configure here, for now.
+          {
+            JsepAudioCodecDescription& audioCodec =
+              static_cast<JsepAudioCodecDescription&>(*codec);
+            if (audioCodec.mName == "opus") {
+              audioCodec.mFECEnabled = mUseAudioFec;
+            }
+          }
           break;
         case SdpMediaSection::kVideo:
           {
             JsepVideoCodecDescription& videoCodec =
               static_cast<JsepVideoCodecDescription&>(*codec);
 
             if (videoCodec.mName == "H264") {
               // Override level
@@ -1010,16 +1019,17 @@ class ConfigureCodec {
     bool mVP9Enabled;
     int32_t mH264Level;
     int32_t mH264MaxBr;
     int32_t mH264MaxMbps;
     int32_t mVP8MaxFs;
     int32_t mVP8MaxFr;
     bool mUseTmmbr;
     bool mUseRemb;
+    bool mUseAudioFec;
 };
 
 nsresult
 PeerConnectionImpl::ConfigureJsepSessionCodecs() {
   nsresult res;
   nsCOMPtr<nsIPrefService> prefs =
     do_GetService("@mozilla.org/preferences-service;1", &res);
 
--- a/media/webrtc/signaling/src/sdp/SdpAttribute.h
+++ b/media/webrtc/signaling/src/sdp/SdpAttribute.h
@@ -1238,38 +1238,42 @@ public:
     unsigned int max_fs;
     unsigned int max_fr;
   };
 
   class OpusParameters : public Parameters
   {
   public:
     enum { kDefaultMaxPlaybackRate = 48000,
-           kDefaultStereo = 0 };
+           kDefaultStereo = 0,
+           kDefaultUseInBandFec = 0 };
     OpusParameters() :
       Parameters(SdpRtpmapAttributeList::kOpus),
       maxplaybackrate(kDefaultMaxPlaybackRate),
-      stereo(kDefaultStereo)
+      stereo(kDefaultStereo),
+      useInBandFec(kDefaultUseInBandFec)
     {}
 
     Parameters*
     Clone() const override
     {
       return new OpusParameters(*this);
     }
 
     void
     Serialize(std::ostream& os) const override
     {
-      os << "maxplaybackrate=" << maxplaybackrate << ";"
-         << "stereo=" << stereo;
+      os << "maxplaybackrate=" << maxplaybackrate
+         << ";stereo=" << stereo
+         << ";useinbandfec=" << useInBandFec;
     }
 
     unsigned int maxplaybackrate;
     unsigned int stereo;
+    unsigned int useInBandFec;
   };
 
   class Fmtp
   {
   public:
     Fmtp(const std::string& aFormat, UniquePtr<Parameters> aParameters)
         : format(aFormat),
           parameters(Move(aParameters))
--- a/media/webrtc/signaling/src/sdp/SipccSdpAttributeList.cpp
+++ b/media/webrtc/signaling/src/sdp/SipccSdpAttributeList.cpp
@@ -721,16 +721,17 @@ SipccSdpAttributeList::LoadFmtp(sdp_t* s
 
         parameters.reset(vp8Parameters);
       } break;
       case RTP_OPUS: {
         SdpFmtpAttributeList::OpusParameters* opusParameters(
             new SdpFmtpAttributeList::OpusParameters);
         opusParameters->maxplaybackrate = fmtp->maxplaybackrate;
         opusParameters->stereo = fmtp->stereo;
+        opusParameters->useInBandFec = fmtp->useinbandfec;
         parameters.reset(opusParameters);
       } break;
       default: {
       }
     }
 
     fmtps->PushEntry(osPayloadType.str(), Move(parameters));
   }
--- a/media/webrtc/signaling/test/sdp_unittests.cpp
+++ b/media/webrtc/signaling/test/sdp_unittests.cpp
@@ -1556,17 +1556,17 @@ const std::string kH264AudioVideoOffer =
 "a=mid:first" CRLF
 "a=rtpmap:109 opus/48000/2" CRLF
 "a=ptime:20" CRLF
 "a=maxptime:20" CRLF
 "a=rtpmap:9 G722/8000" CRLF
 "a=rtpmap:0 PCMU/8000" CRLF
 "a=rtpmap:8 PCMA/8000" CRLF
 "a=rtpmap:101 telephone-event/8000" CRLF
-"a=fmtp:109 maxplaybackrate=32000;stereo=1" CRLF
+"a=fmtp:109 maxplaybackrate=32000;stereo=1;useinbandfec=1" CRLF
 "a=ice-ufrag:00000000" CRLF
 "a=ice-pwd:0000000000000000000000000000000" CRLF
 "a=sendonly" CRLF
 "a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level" CRLF
 "a=setup:actpass" CRLF
 "a=rtcp-mux" CRLF
 "a=msid:stream track" CRLF
 "a=candidate:0 1 UDP 2130379007 10.0.0.36 62453 typ host" CRLF
@@ -1618,16 +1618,17 @@ TEST_P(NewSdpTest, CheckFormatParameters
   ASSERT_EQ(1U, audio_format_params.size());
   ASSERT_EQ("109", audio_format_params[0].format);
   ASSERT_TRUE(!!audio_format_params[0].parameters);
   const SdpFmtpAttributeList::OpusParameters* opus_parameters =
     static_cast<SdpFmtpAttributeList::OpusParameters*>(
         audio_format_params[0].parameters.get());
   ASSERT_EQ(32000U, opus_parameters->maxplaybackrate);
   ASSERT_EQ(1U, opus_parameters->stereo);
+  ASSERT_EQ(1U, opus_parameters->useInBandFec);
 
   ASSERT_TRUE(mSdp->GetMediaSection(1).GetAttributeList().HasAttribute(
       SdpAttribute::kFmtpAttribute));
   auto video_format_params =
       mSdp->GetMediaSection(1).GetAttributeList().GetFmtp().mFmtps;
   ASSERT_EQ(3U, video_format_params.size());
   ASSERT_EQ("97", video_format_params[0].format);
   ASSERT_TRUE(!!video_format_params[0].parameters);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -394,17 +394,17 @@ pref("media.navigator.load_adapt", true)
 pref("media.navigator.load_adapt.measure_interval",1000);
 pref("media.navigator.load_adapt.avg_seconds",3);
 pref("media.navigator.load_adapt.high_load","0.90");
 pref("media.navigator.load_adapt.low_load","0.40");
 pref("media.navigator.video.default_fps",30);
 pref("media.navigator.video.default_minfps",10);
 pref("media.navigator.video.use_remb", true);
 pref("media.navigator.video.use_tmmbr", true);
-
+pref("media.navigator.audio.use_fec", true);
 
 pref("media.webrtc.debug.trace_mask", 0);
 pref("media.webrtc.debug.multi_log", false);
 pref("media.webrtc.debug.aec_log_dir", "");
 pref("media.webrtc.debug.log_file", "");
 pref("media.webrtc.debug.aec_dump_max_size", 4194304); // 4MB
 
 #ifdef MOZ_WIDGET_GONK