diff options
author | sprang@webrtc.org <sprang@webrtc.org> | 2014-12-23 15:19:35 +0000 |
---|---|---|
committer | sprang@webrtc.org <sprang@webrtc.org> | 2014-12-23 15:19:35 +0000 |
commit | 46d4d29a751c559b6f01b311a1e4aa14a2586a46 (patch) | |
tree | 3f5a6291db71b49639e9aef9c308782e73125f46 /talk | |
parent | 1be0a78f45f04505b4b97f28cdb4c02282dd4da4 (diff) | |
download | webrtc-46d4d29a751c559b6f01b311a1e4aa14a2586a46.tar.gz |
Add field trial for screenshare bitrates when using temporal layers.
BUG=
R=pbos@webrtc.org, pthatcher@webrtc.org, stefan@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/31209004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@7976 4adac7df-926f-26a2-2b94-8c16560cd09d
Diffstat (limited to 'talk')
-rwxr-xr-x | talk/libjingle_tests.gyp | 1 | ||||
-rwxr-xr-x | talk/media/webrtc/simulcast.cc | 65 | ||||
-rwxr-xr-x | talk/media/webrtc/simulcast.h | 17 | ||||
-rw-r--r-- | talk/media/webrtc/simulcast_unittest.cc | 73 | ||||
-rw-r--r-- | talk/media/webrtc/webrtcvideoengine2.cc | 12 |
5 files changed, 159 insertions, 9 deletions
diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp index b59a7ef463..c8d78c20b4 100755 --- a/talk/libjingle_tests.gyp +++ b/talk/libjingle_tests.gyp @@ -110,6 +110,7 @@ 'media/devices/dummydevicemanager_unittest.cc', 'media/devices/filevideocapturer_unittest.cc', 'media/sctp/sctpdataengine_unittest.cc', + 'media/webrtc/simulcast_unittest.cc', 'media/webrtc/webrtcpassthroughrender_unittest.cc', 'media/webrtc/webrtcvideocapturer_unittest.cc', 'media/base/videoframe_unittest.h', diff --git a/talk/media/webrtc/simulcast.cc b/talk/media/webrtc/simulcast.cc index 289aacad05..68a9d60aa7 100755 --- a/talk/media/webrtc/simulcast.cc +++ b/talk/media/webrtc/simulcast.cc @@ -25,13 +25,15 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <stdio.h> + #include "talk/media/base/mediachannel.h" // For VideoOptions #include "talk/media/base/streamparams.h" #include "talk/media/webrtc/simulcast.h" #include "webrtc/base/common.h" #include "webrtc/base/logging.h" #include "webrtc/common_types.h" // For webrtc::VideoCodec - +#include "webrtc/system_wrappers/interface/field_trial.h" namespace cricket { struct SimulcastFormat { @@ -71,9 +73,6 @@ static const int kDefaultConferenceNumberOfTemporalLayers[webrtc::kMaxSimulcastStreams] = {3, 3, 3, 3}; -static const int kScreencastWithTemporalLayerTargetVideoBitrate = 100; -static const int kScreencastWithTemporalLayerMaxVideoBitrate = 1000; - void GetSimulcastSsrcs(const StreamParams& sp, std::vector<uint32>* ssrcs) { const SsrcGroup* sim_group = sp.get_ssrc_group(kSimSsrcGroupSemantics); if (sim_group) { @@ -414,10 +413,64 @@ void LogSimulcastSubstreams(const webrtc::VideoCodec& codec) { } } +static const int kScreenshareMinBitrateKbps = 50; +static const int kScreenshareMaxBitrateKbps = 6000; +static const int kScreenshareDefaultTl0BitrateKbps = 100; +static const int kScreenshareDefaultTl1BitrateKbps = 1000; + +static const char* kScreencastLayerFieldTrialName = + "WebRTC-ScreenshareLayerRates"; + +ScreenshareLayerConfig::ScreenshareLayerConfig(int tl0_bitrate, int tl1_bitrate) + : tl0_bitrate_kbps(tl0_bitrate), tl1_bitrate_kbps(tl1_bitrate) { +} + +ScreenshareLayerConfig ScreenshareLayerConfig::GetDefault() { + std::string group = + webrtc::field_trial::FindFullName(kScreencastLayerFieldTrialName); + + ScreenshareLayerConfig config(kScreenshareDefaultTl0BitrateKbps, + kScreenshareDefaultTl1BitrateKbps); + if (!group.empty() && !FromFieldTrialGroup(group, &config)) { + LOG(LS_WARNING) << "Unable to parse WebRTC-ScreenshareLayerRates" + " field trial group: '" << group << "'."; + } + return config; +} + +bool ScreenshareLayerConfig::FromFieldTrialGroup( + const std::string& group, + ScreenshareLayerConfig* config) { + // Parse field trial group name, containing bitrates for tl0 and tl1. + int tl0_bitrate; + int tl1_bitrate; + if (sscanf(group.c_str(), "%d-%d", &tl0_bitrate, &tl1_bitrate) != 2) { + return false; + } + + // Sanity check. + if (tl0_bitrate < kScreenshareMinBitrateKbps || + tl0_bitrate > kScreenshareMaxBitrateKbps || + tl1_bitrate < kScreenshareMinBitrateKbps || + tl1_bitrate > kScreenshareMaxBitrateKbps || tl0_bitrate > tl1_bitrate) { + return false; + } + + config->tl0_bitrate_kbps = tl0_bitrate; + config->tl1_bitrate_kbps = tl1_bitrate; + + return true; +} + void ConfigureConferenceModeScreencastCodec(webrtc::VideoCodec* codec) { codec->codecSpecific.VP8.numberOfTemporalLayers = 2; - codec->maxBitrate = kScreencastWithTemporalLayerMaxVideoBitrate; - codec->targetBitrate = kScreencastWithTemporalLayerTargetVideoBitrate; + ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); + + // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked + // on the VideoCodec struct as target and max bitrates, respectively. + // See eg. webrtc::VP8EncoderImpl::SetRates(). + codec->targetBitrate = config.tl0_bitrate_kbps; + codec->maxBitrate = config.tl1_bitrate_kbps; } } // namespace cricket diff --git a/talk/media/webrtc/simulcast.h b/talk/media/webrtc/simulcast.h index be8097369f..4a7eecaba4 100755 --- a/talk/media/webrtc/simulcast.h +++ b/talk/media/webrtc/simulcast.h @@ -47,6 +47,23 @@ enum SimulcastBitrateMode { SBM_COUNT }; +// Config for use with screen cast when temporal layers are enabled. +struct ScreenshareLayerConfig { + public: + ScreenshareLayerConfig(int tl0_bitrate, int tl1_bitrate); + + // Bitrates, for temporal layers 0 and 1. + int tl0_bitrate_kbps; + int tl1_bitrate_kbps; + + static ScreenshareLayerConfig GetDefault(); + + // Parse bitrate from group name on format "(tl0_bitrate)-(tl1_bitrate)", + // eg. "100-1000" for the default rates. + static bool FromFieldTrialGroup(const std::string& group, + ScreenshareLayerConfig* config); +}; + // TODO(pthatcher): Write unit tests just for these functions, // independent of WebrtcVideoEngine. diff --git a/talk/media/webrtc/simulcast_unittest.cc b/talk/media/webrtc/simulcast_unittest.cc new file mode 100644 index 0000000000..e6b97f7796 --- /dev/null +++ b/talk/media/webrtc/simulcast_unittest.cc @@ -0,0 +1,73 @@ +/* + * libjingle + * Copyright 2014 Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string> + +#include "talk/media/webrtc/simulcast.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cricket { + +class ScreenshareLayerConfigTest : public testing::Test, + protected ScreenshareLayerConfig { + public: + ScreenshareLayerConfigTest() : ScreenshareLayerConfig(0, 0) {} + + void ExpectParsingFails(const std::string& group) { + ScreenshareLayerConfig config(100, 1000); + EXPECT_FALSE(FromFieldTrialGroup(group, &config)); + } +}; + +TEST_F(ScreenshareLayerConfigTest, UsesDefaultBitrateConfigForDefaultGroup) { + ExpectParsingFails(""); +} + +TEST_F(ScreenshareLayerConfigTest, UsesDefaultConfigForInvalidBitrates) { + ExpectParsingFails("-"); + ExpectParsingFails("1-"); + ExpectParsingFails("-1"); + ExpectParsingFails("-12"); + ExpectParsingFails("12-"); + ExpectParsingFails("booh!"); + ExpectParsingFails("1-b"); + ExpectParsingFails("a-2"); + ExpectParsingFails("49-1000"); + ExpectParsingFails("50-6001"); + ExpectParsingFails("100-99"); + ExpectParsingFails("1002003004005006-99"); + ExpectParsingFails("99-1002003004005006"); +} + +TEST_F(ScreenshareLayerConfigTest, ParsesValidBitrateConfig) { + ScreenshareLayerConfig config(100, 1000); + EXPECT_TRUE(ScreenshareLayerConfig::FromFieldTrialGroup("101-1001", &config)); + EXPECT_EQ(101, config.tl0_bitrate_kbps); + EXPECT_EQ(1001, config.tl1_bitrate_kbps); +} + +} // namespace cricket diff --git a/talk/media/webrtc/webrtcvideoengine2.cc b/talk/media/webrtc/webrtcvideoengine2.cc index 0b72fdf0ee..09dd4e11b1 100644 --- a/talk/media/webrtc/webrtcvideoengine2.cc +++ b/talk/media/webrtc/webrtcvideoengine2.cc @@ -131,8 +131,6 @@ static const int kDefaultQpMax = 56; static const int kDefaultRtcpReceiverReportSsrc = 1; -static const int kConferenceModeTemporalLayerBitrateBps = 100000; - // External video encoders are given payloads 120-127. This also means that we // only support up to 8 external payload types. static const int kExternalVideoPayloadTypeBase = 120; @@ -1657,9 +1655,17 @@ WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( // Conference mode screencast uses 2 temporal layers split at 100kbit. if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) && dimensions.is_screencast && encoder_config.streams.size() == 1) { + ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); + + // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked + // on the VideoCodec struct as target and max bitrates, respectively. + // See eg. webrtc::VP8EncoderImpl::SetRates(). + encoder_config.streams[0].target_bitrate_bps = + config.tl0_bitrate_kbps * 1000; + encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000; encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( - kConferenceModeTemporalLayerBitrateBps); + config.tl0_bitrate_kbps * 1000); } return encoder_config; } |