Bug 881935 - Part 2: Device configuration for max-fs and max-fr. r=derf
authorShian-Yow Wu <swu@mozilla.com>
Sun, 13 Oct 2013 09:44:50 +0800
changeset 164415 46d26336b01aae00cf6611246d0bf7040c8b1a04
parent 164414 8127c14d0bd5e8d016f3c49d7f58f90f20cda050
child 164416 3df544a5e7ce5e283373eb131ec71ebb7cf86108
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersderf
bugs881935
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 881935 - Part 2: Device configuration for max-fs and max-fr. r=derf
media/webrtc/signaling/src/media-conduit/CodecConfig.h
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
media/webrtc/signaling/src/media/VcmSIPCCBinding.h
media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.h
media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
media/webrtc/signaling/src/sipcc/include/vcm.h
modules/libpref/src/init/all.js
--- a/media/webrtc/signaling/src/media-conduit/CodecConfig.h
+++ b/media/webrtc/signaling/src/media-conduit/CodecConfig.h
@@ -52,22 +52,38 @@ struct VideoCodecConfig
 {
   /*
    * The data-types for these properties mimic the
    * corresponding webrtc::VideoCodec data-types.
    */
   int mType;
   std::string mName;
   uint32_t mRtcpFbTypes;
+  unsigned int mMaxFrameSize;
+  unsigned int mMaxFrameRate;
 
   VideoCodecConfig(int type,
                    std::string name,
                    int rtcpFbTypes): mType(type),
                                      mName(name),
-                                     mRtcpFbTypes(rtcpFbTypes)
+                                     mRtcpFbTypes(rtcpFbTypes),
+                                     mMaxFrameSize(0),
+                                     mMaxFrameRate(0)
+  {
+  }
+
+  VideoCodecConfig(int type,
+                   std::string name,
+                   int rtcpFbTypes,
+                   unsigned int max_fs,
+                   unsigned int max_fr): mType(type),
+                                         mName(name),
+                                         mRtcpFbTypes(rtcpFbTypes),
+                                         mMaxFrameSize(max_fs),
+                                         mMaxFrameRate(max_fr)
   {
   }
 
 
   bool RtcpFbIsSet(sdp_rtcp_fb_nack_type_e type) const
   {
     return mRtcpFbTypes & sdp_rtcp_fb_nack_to_bitmap(type);
   }
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -11,16 +11,19 @@
 #include "VideoConduit.h"
 #include "AudioConduit.h"
 #include "webrtc/video_engine/include/vie_errors.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidJNIWrapper.h"
 #endif
 
+#include <algorithm>
+#include <math.h>
+
 namespace mozilla {
 
 static const char* logTag ="WebrtcVideoSessionConduit";
 
 const unsigned int WebrtcVideoConduit::CODEC_PLNAME_SIZE = 32;
 
 //Factory Implementation
 mozilla::RefPtr<VideoSessionConduit> VideoSessionConduit::Create()
@@ -611,16 +614,81 @@ WebrtcVideoConduit::ConfigureRecvMediaCo
 // XXX we need to figure out how to feed back changes in preferred capture
 // resolution to the getUserMedia source
 bool
 WebrtcVideoConduit::SelectSendResolution(unsigned short width,
                                          unsigned short height)
 {
   // XXX This will do bandwidth-resolution adaptation as well - bug 877954
 
+  // Limit resolution to max-fs while keeping same aspect ratio as the
+  // incoming image.
+  if (mCurSendCodecConfig && mCurSendCodecConfig->mMaxFrameSize)
+  {
+    unsigned int cur_fs, max_width, max_height, mb_width, mb_height, mb_max;
+
+    mb_width = (width + 15) >> 4;
+    mb_height = (height + 15) >> 4;
+
+    cur_fs = mb_width * mb_height;
+
+    // Limit resolution to max_fs, but don't scale up.
+    if (cur_fs > mCurSendCodecConfig->mMaxFrameSize)
+    {
+      double scale_ratio;
+
+      scale_ratio = sqrt((double) mCurSendCodecConfig->mMaxFrameSize /
+                         (double) cur_fs);
+
+      mb_width = mb_width * scale_ratio;
+      mb_height = mb_height * scale_ratio;
+
+      // Adjust mb_width and mb_height if they were truncated to zero.
+      if (mb_width == 0) {
+        mb_width = 1;
+        mb_height = std::min(mb_height, mCurSendCodecConfig->mMaxFrameSize);
+      }
+      if (mb_height == 0) {
+        mb_height = 1;
+        mb_width = std::min(mb_width, mCurSendCodecConfig->mMaxFrameSize);
+      }
+    }
+
+    // Limit width/height seperately to limit effect of extreme aspect ratios.
+    mb_max = (unsigned) sqrt(8 * (double) mCurSendCodecConfig->mMaxFrameSize);
+
+    max_width = 16 * std::min(mb_width, mb_max);
+    max_height = 16 * std::min(mb_height, mb_max);
+
+    if (width * max_height > max_width * height)
+    {
+      if (width > max_width)
+      {
+        // Due to the value is truncated to integer here and forced to even
+        // value later, adding 1 to improve accuracy.
+        height = max_width * height / width + 1;
+        width = max_width;
+      }
+    }
+    else
+    {
+      if (height > max_height)
+      {
+        // Due to the value is truncated to integer here and forced to even
+        // value later, adding 1 to improve accuracy.
+        width = max_height * width / height + 1;
+        height = max_height;
+      }
+    }
+
+    // Favor even multiples of pixels for width and height.
+    width = std::max(width & ~1, 2);
+    height = std::max(height & ~1, 2);
+  }
+
   // Adapt to getUserMedia resolution changes
   // check if we need to reconfigure the sending resolution
   if (mSendingWidth != width || mSendingHeight != height)
   {
     // This will avoid us continually retrying this operation if it fails.
     // If the resolution changes, we'll try again.  In the meantime, we'll
     // keep using the old size in the encoder.
     mSendingWidth = width;
@@ -845,16 +913,20 @@ WebrtcVideoConduit::DeliverFrame(unsigne
  */
 
 void
 WebrtcVideoConduit::CodecConfigToWebRTCCodec(const VideoCodecConfig* codecInfo,
                                               webrtc::VideoCodec& cinst)
 {
   cinst.plType  = codecInfo->mType;
   // leave width/height alone; they'll be overridden on the first frame
+  if (codecInfo->mMaxFrameRate > 0)
+  {
+    cinst.maxFramerate = codecInfo->mMaxFrameRate;
+  }
   cinst.minBitrate = 200;
   cinst.startBitrate = 300;
   cinst.maxBitrate = 2000;
 }
 
 bool
 WebrtcVideoConduit::CopyCodecToDB(const VideoCodecConfig* codecInfo)
 {
@@ -887,18 +959,20 @@ bool
 WebrtcVideoConduit::CheckCodecsForMatch(const VideoCodecConfig* curCodecConfig,
                                         const VideoCodecConfig* codecInfo) const
 {
   if(!curCodecConfig)
   {
     return false;
   }
 
-  if(curCodecConfig->mType   == codecInfo->mType &&
-     curCodecConfig->mName.compare(codecInfo->mName) == 0)
+  if(curCodecConfig->mType  == codecInfo->mType &&
+     curCodecConfig->mName.compare(codecInfo->mName) == 0 &&
+     curCodecConfig->mMaxFrameSize == codecInfo->mMaxFrameSize &&
+     curCodecConfig->mMaxFrameRate == codecInfo->mMaxFrameRate)
   {
     return true;
   }
 
   return false;
 }
 
 /**
@@ -942,12 +1016,14 @@ WebrtcVideoConduit::ValidateCodecConfig(
 
 void
 WebrtcVideoConduit::DumpCodecDB() const
 {
   for(std::vector<VideoCodecConfig*>::size_type i=0;i<mRecvCodecList.size();i++)
   {
     CSFLogDebug(logTag,"Payload Name: %s", mRecvCodecList[i]->mName.c_str());
     CSFLogDebug(logTag,"Payload Type: %d", mRecvCodecList[i]->mType);
+    CSFLogDebug(logTag,"Payload Max Frame Size: %d", mRecvCodecList[i]->mMaxFrameSize);
+    CSFLogDebug(logTag,"Payload Max Frame Rate: %d", mRecvCodecList[i]->mMaxFrameRate);
   }
 }
 
 }// end namespace
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp
@@ -19,16 +19,20 @@
 #include "transportflow.h"
 #include "transportlayer.h"
 #include "transportlayerdtls.h"
 #include "transportlayerice.h"
 #include "runnable_utils.h"
 #include "cpr_stdlib.h"
 #include "cpr_string.h"
 #include "mozilla/SyncRunnable.h"
+#include "mozilla/Services.h"
+#include "nsServiceManagerUtils.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <ssl.h>
 #include <sslproto.h>
 #include <algorithm>
 
 extern "C" {
@@ -65,16 +69,17 @@ typedef enum {
 
 using namespace CSF;
 
 VcmSIPCCBinding * VcmSIPCCBinding::gSelf = NULL;
 int VcmSIPCCBinding::gAudioCodecMask = 0;
 int VcmSIPCCBinding::gVideoCodecMask = 0;
 nsIThread *VcmSIPCCBinding::gMainThread = NULL;
 nsIEventTarget *VcmSIPCCBinding::gSTSThread = NULL;
+nsCOMPtr<nsIPrefBranch> VcmSIPCCBinding::gBranch = NULL;
 
 static mozilla::RefPtr<TransportFlow> vcmCreateTransportFlow(
     sipcc::PeerConnectionImpl *pc,
     int level,
     bool rtcp,
     sdp_setup_type_e setup_type,
     const char *fingerprint_alg,
     const char *fingerprint);
@@ -97,16 +102,22 @@ static mozilla::RefPtr<TransportFlow> vc
     }         \
   } while(0)
 
 VcmSIPCCBinding::VcmSIPCCBinding ()
   : streamObserver(NULL)
 {
     delete gSelf;//delete is NULL safe, so I don't need to check if it's NULL
     gSelf = this;
+  nsresult rv;
+
+  nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
+  if (NS_SUCCEEDED(rv)) {
+    gBranch = do_QueryInterface(prefs);
+  }
 }
 
 class VcmIceOpaque : public NrIceOpaque {
  public:
   VcmIceOpaque(cc_streamid_t stream_id,
                cc_call_handle_t call_handle,
                uint16_t level) :
       stream_id_(stream_id),
@@ -128,16 +139,18 @@ VcmSIPCCBinding::~VcmSIPCCBinding ()
     // In case we're torn down while STS is still running,
     // we try to dispatch to STS to disconnect all of the
     // ICE signals. If STS is no longer running, this will
     // harmlessly fail.
     SyncRunnable::DispatchToThread(
       gSTSThread,
       WrapRunnable(this, &VcmSIPCCBinding::disconnect_all),
       true);
+
+  gBranch = NULL;
 }
 
 void VcmSIPCCBinding::CandidateReady(NrIceMediaStream* stream,
                                      const std::string& candidate)
 {
     // This is called on the STS thread
     NrIceOpaque *opaque = stream->opaque();
     MOZ_ASSERT(opaque);
@@ -230,16 +243,21 @@ nsIEventTarget* VcmSIPCCBinding::getSTST
 
 void VcmSIPCCBinding::connectCandidateSignal(
     NrIceMediaStream *stream)
 {
   stream->SignalCandidate.connect(gSelf,
                                   &VcmSIPCCBinding::CandidateReady);
 }
 
+nsCOMPtr<nsIPrefBranch> VcmSIPCCBinding::getPrefBranch()
+{
+  return gBranch;
+}
+
 /* static */
 AudioTermination * VcmSIPCCBinding::getAudioTermination()
 {
     // commenting as part of media provider removal
     return NULL;
 }
 
 /* static */
@@ -2244,17 +2262,19 @@ static int vcmTxStartICE_m(cc_mcapid_t m
     // Now we have all the pieces, create the pipeline
     stream->StorePipeline(pc_track_id, pipeline);
 
   } else if (CC_IS_VIDEO(mcap_id)) {
     mozilla::VideoCodecConfig *config_raw;
     config_raw = new mozilla::VideoCodecConfig(
       payload->remote_rtp_pt,
       ccsdpCodecName(payload->codec_type),
-      payload->video.rtcp_fb_types);
+      payload->video.rtcp_fb_types,
+      payload->video.max_fs,
+      payload->video.max_fr);
 
     // Take possession of this pointer
     mozilla::ScopedDeletePtr<mozilla::VideoCodecConfig> config(config_raw);
 
     // Instantiate an appropriate conduit
     mozilla::RefPtr<mozilla::VideoSessionConduit> conduit =
       mozilla::VideoSessionConduit::Create();
 
@@ -3048,8 +3068,52 @@ int vcmDisableRtcpComponent(const char *
   mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
       WrapRunnableNMRet(&vcmDisableRtcpComponent_m,
                         peerconnection,
                         level,
                         &ret));
   return ret;
 }
 
+static short vcmGetVideoMaxFs_m(uint16_t codec,
+                                int32_t *max_fs) {
+  nsCOMPtr<nsIPrefBranch> branch = VcmSIPCCBinding::getPrefBranch();
+  if (branch && NS_SUCCEEDED(branch->GetIntPref("media.navigator.video.max_fs",
+                                                max_fs))) {
+    return 0;
+  }
+  return VCM_ERROR;
+}
+
+short vcmGetVideoMaxFs(uint16_t codec,
+                       int32_t *max_fs) {
+  short ret;
+
+  mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
+      WrapRunnableNMRet(&vcmGetVideoMaxFs_m,
+                        codec,
+                        max_fs,
+                        &ret));
+  return ret;
+}
+
+static short vcmGetVideoMaxFr_m(uint16_t codec,
+                                int32_t *max_fr) {
+  nsCOMPtr<nsIPrefBranch> branch = VcmSIPCCBinding::getPrefBranch();
+  if (branch && NS_SUCCEEDED(branch->GetIntPref("media.navigator.video.max_fr",
+                                                max_fr))) {
+    return 0;
+  }
+  return VCM_ERROR;
+}
+
+short vcmGetVideoMaxFr(uint16_t codec,
+                       int32_t *max_fr) {
+  short ret;
+
+  mozilla::SyncRunnable::DispatchToThread(VcmSIPCCBinding::getMainThread(),
+      WrapRunnableNMRet(&vcmGetVideoMaxFr_m,
+                        codec,
+                        max_fr,
+                        &ret));
+  return ret;
+}
+
--- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
+++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.h
@@ -9,16 +9,17 @@ extern "C"
 {
 #include "ccapi_types.h"
 }
 
 #include "sigslot.h"
 
 class nsIThread;
 class nsIEventTarget;
+class nsIPrefBranch;
 
 namespace mozilla {
     class NrIceMediaStream;
 };
 
 namespace CSF
 {
     class AudioTermination;
@@ -64,25 +65,28 @@ namespace CSF
 	static void setMainThread(nsIThread *thread);
 	static nsIThread *getMainThread();
 	static nsIEventTarget *getSTSThread();
 
 	static void setSTSThread(nsIEventTarget *thread);
 
 	static void connectCandidateSignal(mozilla::NrIceMediaStream* stream);
 
+        static nsCOMPtr<nsIPrefBranch> getPrefBranch();
+
     private:
 	void CandidateReady(mozilla::NrIceMediaStream* stream,
 			    const std::string& candidate);
 
         static VcmSIPCCBinding * gSelf;
         StreamObserver* streamObserver;
         MediaProviderObserver *mediaProviderObserver;
         static int gAudioCodecMask;
         static int gVideoCodecMask;
 	static nsIThread *gMainThread;
 	static nsIEventTarget *gSTSThread;
+        static nsCOMPtr<nsIPrefBranch> gBranch;
     };
 }
 
 #endif
 
 
--- a/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
+++ b/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.c
@@ -566,16 +566,38 @@ sip_config_local_supported_codecs_get (r
                 count++;
             }
         }
         codec++;
     }
     return count;
 }
 
+uint32_t
+config_get_video_max_fs(const rtp_ptype codec)
+{
+  uint32_t max_fs;
+
+  if(vcmGetVideoMaxFs(codec, (int32_t *) &max_fs) == 0) {
+    return max_fs;
+  }
+  return 0;
+}
+
+uint32_t
+config_get_video_max_fr(const rtp_ptype codec)
+{
+  uint32_t max_fr;
+
+  if(vcmGetVideoMaxFr(codec, (int32_t *) &max_fr) == 0) {
+    return max_fr;
+  }
+  return 0;
+}
+
 /*
  * sip_config_local_supported_codecs_get()
  *
  * Get the locally supported codec list.
  */
 uint16_t
 sip_config_video_supported_codecs_get (rtp_ptype aSupportedCodecs[],
                           uint16_t supportedCodecsLen, boolean isOffer)
--- a/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.h
+++ b/media/webrtc/signaling/src/sipcc/core/common/prot_configmgr.h
@@ -287,10 +287,12 @@ line_t sip_config_get_line_from_button(l
 boolean sip_config_check_line(line_t line);
 line_t sip_config_local_line_get(void);
 void sip_config_get_display_name(line_t line, char *buffer, int buffer_len);
 line_t sip_config_get_line_by_called_number(line_t start_line, const char *called_number);
 int sip_minimum_config_check(void);
 void config_set_codec_table(int codec_mask);
 int sip_config_get_keepalive_expires();
 rtp_ptype sip_config_preferred_codec(void);
+uint32_t config_get_video_max_fs(const rtp_ptype codec);
+uint32_t config_get_video_max_fr(const rtp_ptype codec);
 
 #endif /* PROT_CONFIGMGR_H_ */
--- a/media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
+++ b/media/webrtc/signaling/src/sipcc/core/gsm/gsm_sdp.c
@@ -1180,17 +1180,19 @@ gsmsdp_set_video_media_attributes (uint3
                                              RTPMAP_VIDEO_CLOCKRATE);
             break;
         case RTP_VP8:
             (void) sdp_attr_set_rtpmap_encname(sdp_p, level, 0, a_inst,
                                                SIPSDP_ATTR_ENCNAME_VP8);
             (void) sdp_attr_set_rtpmap_clockrate(sdp_p, level, 0, a_inst,
                                              RTPMAP_VIDEO_CLOCKRATE);
 
-            /* TODO: Get max_fs & max_fr from device configuration (Bug 881935) */
+            max_fs = config_get_video_max_fs((rtp_ptype) media_type);
+            max_fr = config_get_video_max_fr((rtp_ptype) media_type);
+
             if (max_fs || max_fr) {
                 if (sdp_add_new_attr(sdp_p, level, 0, SDP_ATTR_FMTP, &a_inst)
                     != SDP_SUCCESS) {
                     GSM_ERR_MSG("Failed to add attribute");
                     return;
                 }
 
                 (void) sdp_attr_set_fmtp_payload_type(sdp_p, level, 0, a_inst,
@@ -3436,33 +3438,29 @@ gsmsdp_negotiate_codec (fsmdef_dcb_t *dc
                             != NULL ) {
                         media->previous_sdp.profile_level =
                             media->profile_level;
                         sscanf(attr_label,"%x", &media->profile_level);
                     }
 
                     /* This should ultimately use RFC 6236 a=imageattr
                        if present */
-                    switch (codec) {
-                        case RTP_VP8:
-                            payload_info->video.width = 640;
-                            payload_info->video.height = 480;
-                        break;
-                        case RTP_I420:
-                            payload_info->video.width = 176;
-                            payload_info->video.height = 144;
-                        break;
-                        default:
-                            GSM_DEBUG(DEB_L_C_F_PREFIX"codec=%d not setting "
-                                "codec parameters (not implemented)\n",
-                                DEB_L_C_F_PREFIX_ARGS(GSM, dcb_p->line,
-                                dcb_p->call_id, fname), codec);
-                            payload_info->video.width = -1;
-                            payload_info->video.height = -1;
-                    }
+
+                    payload_info->video.width = 0;
+                    payload_info->video.height = 0;
+
+                    /* Set maximum frame size */
+                    payload_info->video.max_fs = 0;
+                    sdp_attr_get_fmtp_max_fs(sdp_p->dest_sdp, level, 0, 1,
+                                             &payload_info->video.max_fs);
+
+                    /* Set maximum frame rate */
+                    payload_info->video.max_fr = 0;
+                    sdp_attr_get_fmtp_max_fr(sdp_p->dest_sdp, level, 0, 1,
+                                             &payload_info->video.max_fr);
                 } /* end video */
 
                 GSM_DEBUG(DEB_L_C_F_PREFIX"codec= %d",
                       DEB_L_C_F_PREFIX_ARGS(GSM, dcb_p->line,
                                             dcb_p->call_id, fname), codec);
 
 
                 found_codec = TRUE;
--- a/media/webrtc/signaling/src/sipcc/include/vcm.h
+++ b/media/webrtc/signaling/src/sipcc/include/vcm.h
@@ -181,16 +181,18 @@ typedef struct
       int bitrate;     /* Wire bitrate of RTP packet payloads */
     } audio;
 
     struct
     {
       int width;
       int height;
       uint32_t rtcp_fb_types;
+      uint32_t max_fs; /* Max frame size */
+      uint32_t max_fr; /* Max frame rate */
     } video;
   };
 
   /* Codec-specific parameters */
   union
   {
     struct {
         uint16_t mode;
@@ -1042,16 +1044,20 @@ int vcmOnSdpParseError(const char *peerc
 /**
  * vcmDisableRtcpComponent
  *
  * If we are doing rtcp-mux we need to disable component number 2 in the ICE
  * layer.  Otherwise we will wait for it to connect when it is unused
  */
 int vcmDisableRtcpComponent(const char *peerconnection, int level);
 
+short vcmGetVideoMaxFs(uint16_t codec, int32_t *max_fs);
+
+short vcmGetVideoMaxFr(uint16_t codec, int32_t *max_fs);
+
 //Using C++ for gips. This is the end of extern "C" above.
 #ifdef __cplusplus
 }
 #endif
 
 
 
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -225,16 +225,18 @@ pref("media.gstreamer.enabled", true);
 pref("media.apple.mp3.enabled", true);
 #endif
 #ifdef MOZ_WEBRTC
 pref("media.navigator.enabled", true);
 pref("media.navigator.video.default_width",640);
 pref("media.navigator.video.default_height",480);
 pref("media.navigator.video.default_fps",30);
 pref("media.navigator.video.default_minfps",10);
+pref("media.navigator.video.max_fs", 0); // unrestricted
+pref("media.navigator.video.max_fr", 0); // unrestricted
 pref("media.peerconnection.enabled", true);
 pref("media.navigator.permission.disabled", false);
 pref("media.peerconnection.default_iceservers", "[{\"url\": \"stun:23.21.150.121\"}]");
 pref("media.peerconnection.trickle_ice", true);
 pref("media.peerconnection.use_document_iceservers", true);
 // These values (aec, agc, and noice) are from media/webrtc/trunk/webrtc/common_types.h
 // kXxxUnchanged = 0, kXxxDefault = 1, and higher values are specific to each 
 // setting (for Xxx = Ec, Agc, or Ns).  Defaults are all set to kXxxDefault here.