--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -85,19 +85,19 @@ WebrtcVideoConduit::WebrtcVideoConduit()
mSendingHeight(0),
mReceivingWidth(640),
mReceivingHeight(480),
mSendingFramerate(DEFAULT_VIDEO_MAX_FRAMERATE),
mLastFramerateTenths(DEFAULT_VIDEO_MAX_FRAMERATE*10),
mNumReceivingStreams(1),
mVideoLatencyTestEnable(false),
mVideoLatencyAvg(0),
- mMinBitrate(200),
- mStartBitrate(300),
- mMaxBitrate(2000),
+ mMinBitrate(0),
+ mStartBitrate(0),
+ mMaxBitrate(0),
mCodecMode(webrtc::kRealtimeVideo)
{}
WebrtcVideoConduit::~WebrtcVideoConduit()
{
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
CSFLogDebug(logTag, "%s ", __FUNCTION__);
@@ -281,16 +281,25 @@ WebrtcVideoConduit::InitMain()
(void) NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.start_bitrate", &temp)));
if (temp >= 0) {
mStartBitrate = temp;
}
(void) NS_WARN_IF(NS_FAILED(branch->GetIntPref("media.peerconnection.video.max_bitrate", &temp)));
if (temp >= 0) {
mMaxBitrate = temp;
}
+ if (mMinBitrate != 0 && mMinBitrate < webrtc::kViEMinCodecBitrate) {
+ mMinBitrate = webrtc::kViEMinCodecBitrate;
+ }
+ if (mStartBitrate < mMinBitrate) {
+ mStartBitrate = mMinBitrate;
+ }
+ if (mStartBitrate > mMaxBitrate) {
+ mStartBitrate = mMaxBitrate;
+ }
bool use_loadmanager = false;
(void) NS_WARN_IF(NS_FAILED(branch->GetBoolPref("media.navigator.load_adapt", &use_loadmanager)));
if (use_loadmanager) {
mLoadManager = LoadManagerBuild();
}
}
}
@@ -956,73 +965,87 @@ WebrtcVideoConduit::ConfigureRecvMediaCo
mPtrRTP->SetRembStatus(mChannel, false, true);
DumpCodecDB();
return kMediaConduitNoError;
}
struct ResolutionAndBitrateLimits {
uint32_t resolution_in_mb;
uint16_t min_bitrate;
+ uint16_t start_bitrate;
uint16_t max_bitrate;
};
#define MB_OF(w,h) ((unsigned int)((((w)>>4))*((unsigned int)((h)>>4))))
// For now, try to set the max rates well above the knee in the curve.
// Chosen somewhat arbitrarily; it's hard to find good data oriented for
// realtime interactive/talking-head recording. These rates assume
// 30fps.
// XXX Populate this based on a pref (which we should consider sorting because
// people won't assume they need to).
static ResolutionAndBitrateLimits kResolutionAndBitrateLimits[] = {
- {MB_OF(1920, 1200), 1500, 10000}, // >HD (3K, 4K, etc)
- {MB_OF(1280, 720), 1200, 5000}, // HD ~1080-1200
- {MB_OF(800, 480), 600, 2500}, // HD ~720
- {std::max(MB_OF(400, 240), MB_OF(352, 288)), 200, 1300}, // VGA, WVGA
- {MB_OF(176, 144), 100, 500}, // WQVGA, CIF
- {0 , 40, 250} // QCIF and below
+ {MB_OF(1920, 1200), 1500, 2000, 10000}, // >HD (3K, 4K, etc)
+ {MB_OF(1280, 720), 1200, 1500, 5000}, // HD ~1080-1200
+ {MB_OF(800, 480), 600, 800, 2500}, // HD ~720
+ {std::max(MB_OF(400, 240), MB_OF(352, 288)), 200, 300, 1300}, // VGA, WVGA
+ {MB_OF(176, 144), 100, 150, 500}, // WQVGA, CIF
+ {0 , 40, 80, 250} // QCIF and below
};
-static void
-SelectBandwidth(webrtc::VideoCodec& vie_codec,
- unsigned short width,
- unsigned short height,
- mozilla::Atomic<int32_t, mozilla::Relaxed>& aLastFramerateTenths)
+void
+WebrtcVideoConduit::SelectBandwidth(webrtc::VideoCodec& vie_codec,
+ unsigned short width,
+ unsigned short height,
+ mozilla::Atomic<int32_t, mozilla::Relaxed>& aLastFramerateTenths)
{
// max bandwidth should be proportional (not linearly!) to resolution, and
// proportional (perhaps linearly, or close) to current frame rate.
unsigned int fs, mb_width, mb_height;
mb_width = (width + 15) >> 4;
mb_height = (height + 15) >> 4;
fs = mb_width * mb_height;
for (ResolutionAndBitrateLimits resAndLimits : kResolutionAndBitrateLimits) {
if (fs > resAndLimits.resolution_in_mb) {
vie_codec.minBitrate = resAndLimits.min_bitrate;
+ vie_codec.startBitrate = resAndLimits.start_bitrate;
vie_codec.maxBitrate = resAndLimits.max_bitrate;
break;
}
}
// mLastFramerateTenths is an atomic, and scaled by *10
double framerate = std::min((aLastFramerateTenths/10.),60.0);
MOZ_ASSERT(framerate > 0);
// Now linear reduction/increase based on fps (max 60fps i.e. doubling)
if (framerate >= 10) {
vie_codec.minBitrate = vie_codec.minBitrate * (framerate/30);
+ vie_codec.startBitrate = vie_codec.startBitrate * (framerate/30);
vie_codec.maxBitrate = vie_codec.maxBitrate * (framerate/30);
} else {
// At low framerates, don't reduce bandwidth as much - cut slope to 1/2.
// Mostly this would be ultra-low-light situations/mobile or screensharing.
vie_codec.minBitrate = vie_codec.minBitrate * ((10-(framerate/2))/30);
+ vie_codec.startBitrate = vie_codec.startBitrate * ((10-(framerate/2))/30);
vie_codec.maxBitrate = vie_codec.maxBitrate * ((10-(framerate/2))/30);
}
+ if (mMinBitrate && mMinBitrate > vie_codec.minBitrate) {
+ vie_codec.minBitrate = mMinBitrate;
+ }
+ if (mStartBitrate && mStartBitrate > vie_codec.startBitrate) {
+ vie_codec.startBitrate = mStartBitrate;
+ }
+ if (mMaxBitrate && mMaxBitrate > vie_codec.maxBitrate) {
+ vie_codec.maxBitrate = mMaxBitrate;
+ }
+
// If we try to set a minimum bitrate that is too low, ViE will reject it.
vie_codec.minBitrate = std::max((unsigned int) webrtc::kViEMinCodecBitrate,
vie_codec.minBitrate);
}
static void ConstrainPreservingAspectRatioExact(uint32_t max_fs,
unsigned short* width,
unsigned short* height)
@@ -1776,19 +1799,22 @@ WebrtcVideoConduit::CodecConfigToWebRTCC
// width/height will be overridden on the first frame; they must be 'sane' for
// SetSendCodec()
if (codecInfo->mEncodingConstraints.maxFps > 0) {
cinst.maxFramerate = codecInfo->mEncodingConstraints.maxFps;
} else {
cinst.maxFramerate = DEFAULT_VIDEO_MAX_FRAMERATE;
}
- cinst.minBitrate = mMinBitrate;
- cinst.startBitrate = mStartBitrate;
- cinst.maxBitrate = mMaxBitrate;
+ // Defaults if rates aren't forced by pref. Typically defaults are
+ // overridden on the first video frame.
+ cinst.minBitrate = mMinBitrate ? mMinBitrate : 200;
+ cinst.startBitrate = mStartBitrate ? mStartBitrate : 300;
+ cinst.targetBitrate = cinst.startBitrate;
+ cinst.maxBitrate = mMaxBitrate ? mMaxBitrate : 2000;
if (cinst.codecType == webrtc::kVideoCodecH264)
{
#ifdef MOZ_WEBRTC_OMX
cinst.resolution_divisor = 16;
#endif
// cinst.codecSpecific.H264.profile = ?
cinst.codecSpecific.H264.profile_byte = codecInfo->mProfile;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -379,40 +379,37 @@ pref("media.peerconnection.video.enabled
pref("media.navigator.video.max_fs", 1200); // 640x480 == 1200mb
pref("media.navigator.video.max_fr", 30);
pref("media.navigator.video.h264.level", 12); // 0x42E00C - level 1.2
pref("media.navigator.video.h264.max_br", 700); // 8x10
pref("media.navigator.video.h264.max_mbps", 11880); // CIF@30fps
pref("media.peerconnection.video.h264_enabled", false);
pref("media.peerconnection.video.vp9_enabled", false);
pref("media.getusermedia.aec", 4);
-// Gonk typically captures at QVGA, and so min resolution is QQVGA or
-// 160x120; 100Kbps is plenty for that.
-pref("media.peerconnection.video.min_bitrate", 100);
-pref("media.peerconnection.video.start_bitrate", 220);
-pref("media.peerconnection.video.max_bitrate", 1000);
#else
pref("media.navigator.video.default_width",0); // adaptive default
pref("media.navigator.video.default_height",0); // adaptive default
pref("media.peerconnection.enabled", true);
pref("media.peerconnection.video.enabled", true);
pref("media.navigator.video.max_fs", 12288); // Enough for 2048x1536
pref("media.navigator.video.max_fr", 60);
pref("media.navigator.video.h264.level", 31); // 0x42E01f - level 3.1
pref("media.navigator.video.h264.max_br", 0);
pref("media.navigator.video.h264.max_mbps", 0);
pref("media.peerconnection.video.h264_enabled", false);
pref("media.getusermedia.aec", 1);
pref("media.getusermedia.browser.enabled", true);
+#endif
+// Gonk typically captures at QVGA, and so min resolution is QQVGA or
+// 160x120; 100Kbps is plenty for that.
// Desktop is typically VGA capture or more; and qm_select will not drop resolution
// below 1/2 in each dimension (or so), so QVGA (320x200) is the lowest here usually.
-pref("media.peerconnection.video.min_bitrate", 200);
-pref("media.peerconnection.video.start_bitrate", 300);
-pref("media.peerconnection.video.max_bitrate", 2000);
-#endif
+pref("media.peerconnection.video.min_bitrate", 0);
+pref("media.peerconnection.video.start_bitrate", 0);
+pref("media.peerconnection.video.max_bitrate", 0);
pref("media.navigator.audio.fake_frequency", 1000);
pref("media.navigator.permission.disabled", false);
pref("media.peerconnection.simulcast", true);
pref("media.peerconnection.default_iceservers", "[]");
pref("media.peerconnection.ice.loopback", false); // Set only for testing in offline environments.
pref("media.peerconnection.ice.tcp", false);
pref("media.peerconnection.ice.tcp_so_sock_count", 0); // Disable SO gathering
pref("media.peerconnection.ice.link_local", false); // Set only for testing IPV6 in networks that don't assign IPV6 addresses