| Index: talk/media/webrtc/simulcast.cc
|
| diff --git a/talk/media/webrtc/simulcast.cc b/talk/media/webrtc/simulcast.cc
|
| index 3f0820fef9e570363725a87bf1246367ab100824..a837b7ccb72f305b11ad3465febedc49164f2127 100755
|
| --- a/talk/media/webrtc/simulcast.cc
|
| +++ b/talk/media/webrtc/simulcast.cc
|
| @@ -27,12 +27,10 @@
|
|
|
| #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 {
|
|
|
| @@ -44,26 +42,26 @@ struct SimulcastFormat {
|
| size_t max_layers;
|
| // The maximum bitrate for encoding stream at |widthxheight|, when we are
|
| // not sending the next higher spatial stream.
|
| - int max_bitrate_kbps[SBM_COUNT];
|
| + int max_bitrate_kbps;
|
| // The target bitrate for encoding stream at |widthxheight|, when this layer
|
| // is not the highest layer (i.e., when we are sending another higher spatial
|
| // stream).
|
| - int target_bitrate_kbps[SBM_COUNT];
|
| + int target_bitrate_kbps;
|
| // The minimum bitrate needed for encoding stream at |widthxheight|.
|
| - int min_bitrate_kbps[SBM_COUNT];
|
| + int min_bitrate_kbps;
|
| };
|
|
|
| // These tables describe from which resolution we can use how many
|
| // simulcast layers at what bitrates (maximum, target, and minimum).
|
| // Important!! Keep this table from high resolution to low resolution.
|
| const SimulcastFormat kSimulcastFormats[] = {
|
| - {1920, 1080, 3, {5000, 5000, 5000}, {4000, 4000, 4000}, {800, 800, 800}},
|
| - {1280, 720, 3, {1200, 1200, 2500}, {1200, 1200, 2500}, {500, 600, 600}},
|
| - {960, 540, 3, {900, 900, 900}, {900, 900, 900}, {350, 450, 450}},
|
| - {640, 360, 2, {500, 700, 700}, {500, 500, 500}, {100, 150, 150}},
|
| - {480, 270, 2, {350, 450, 450}, {350, 350, 350}, {100, 150, 150}},
|
| - {320, 180, 1, {100, 200, 200}, {100, 150, 150}, {30, 30, 30}},
|
| - {0, 0, 1, {100, 200, 200}, {100, 150, 150}, {30, 30, 30}}
|
| + {1920, 1080, 3, 5000, 4000, 800},
|
| + {1280, 720, 3, 2500, 2500, 600},
|
| + {960, 540, 3, 900, 900, 450},
|
| + {640, 360, 2, 700, 500, 150},
|
| + {480, 270, 2, 450, 350, 150},
|
| + {320, 180, 1, 200, 150, 30},
|
| + {0, 0, 1, 200, 150, 30}
|
| };
|
|
|
| // Multiway: Number of temporal layers for each simulcast stream, for maximum
|
| @@ -82,22 +80,6 @@ void GetSimulcastSsrcs(const StreamParams& sp, std::vector<uint32_t>* ssrcs) {
|
| }
|
| }
|
|
|
| -SimulcastBitrateMode GetSimulcastBitrateMode(
|
| - const VideoOptions& options) {
|
| - VideoOptions::HighestBitrate bitrate_mode;
|
| - if (options.video_highest_bitrate.Get(&bitrate_mode)) {
|
| - switch (bitrate_mode) {
|
| - case VideoOptions::HIGH:
|
| - return SBM_HIGH;
|
| - case VideoOptions::VERY_HIGH:
|
| - return SBM_VERY_HIGH;
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| - return SBM_NORMAL;
|
| -}
|
| -
|
| void MaybeExchangeWidthHeight(int* width, int* height) {
|
| // |kSimulcastFormats| assumes |width| >= |height|. If not, exchange them
|
| // before comparing.
|
| @@ -133,23 +115,6 @@ int FindSimulcastFormatIndex(int width, int height, size_t max_layers) {
|
| return -1;
|
| }
|
|
|
| -SimulcastBitrateMode FindSimulcastBitrateMode(
|
| - size_t max_layers,
|
| - int stream_idx,
|
| - SimulcastBitrateMode highest_enabled) {
|
| -
|
| - if (highest_enabled > SBM_NORMAL) {
|
| - // We want high or very high for all layers if enabled.
|
| - return highest_enabled;
|
| - }
|
| - if (kSimulcastFormats[stream_idx].max_layers == max_layers) {
|
| - // We want high for the top layer.
|
| - return SBM_HIGH;
|
| - }
|
| - // And normal for everything else.
|
| - return SBM_NORMAL;
|
| -}
|
| -
|
| // Simulcast stream width and height must both be dividable by
|
| // |2 ^ simulcast_layers - 1|.
|
| int NormalizeSimulcastSize(int size, size_t simulcast_layers) {
|
| @@ -168,44 +133,30 @@ size_t FindSimulcastMaxLayers(int width, int height) {
|
| // TODO(marpan): Investigate if we should return 0 instead of -1 in
|
| // FindSimulcast[Max/Target/Min]Bitrate functions below, since the
|
| // codec struct max/min/targeBitrates are unsigned.
|
| -int FindSimulcastMaxBitrateBps(int width,
|
| - int height,
|
| - size_t max_layers,
|
| - SimulcastBitrateMode highest_enabled) {
|
| +int FindSimulcastMaxBitrateBps(int width, int height, size_t max_layers) {
|
| const int format_index = FindSimulcastFormatIndex(width, height);
|
| if (format_index == -1) {
|
| return -1;
|
| }
|
| - const SimulcastBitrateMode bitrate_mode = FindSimulcastBitrateMode(
|
| - max_layers, format_index, highest_enabled);
|
| - return kSimulcastFormats[format_index].max_bitrate_kbps[bitrate_mode] * 1000;
|
| + return kSimulcastFormats[format_index].max_bitrate_kbps * 1000;
|
| }
|
|
|
| int FindSimulcastTargetBitrateBps(int width,
|
| int height,
|
| - size_t max_layers,
|
| - SimulcastBitrateMode highest_enabled) {
|
| + size_t max_layers) {
|
| const int format_index = FindSimulcastFormatIndex(width, height);
|
| if (format_index == -1) {
|
| return -1;
|
| }
|
| - const SimulcastBitrateMode bitrate_mode = FindSimulcastBitrateMode(
|
| - max_layers, format_index, highest_enabled);
|
| - return kSimulcastFormats[format_index].target_bitrate_kbps[bitrate_mode] *
|
| - 1000;
|
| + return kSimulcastFormats[format_index].target_bitrate_kbps * 1000;
|
| }
|
|
|
| -int FindSimulcastMinBitrateBps(int width,
|
| - int height,
|
| - size_t max_layers,
|
| - SimulcastBitrateMode highest_enabled) {
|
| +int FindSimulcastMinBitrateBps(int width, int height, size_t max_layers) {
|
| const int format_index = FindSimulcastFormatIndex(width, height);
|
| if (format_index == -1) {
|
| return -1;
|
| }
|
| - const SimulcastBitrateMode bitrate_mode = FindSimulcastBitrateMode(
|
| - max_layers, format_index, highest_enabled);
|
| - return kSimulcastFormats[format_index].min_bitrate_kbps[bitrate_mode] * 1000;
|
| + return kSimulcastFormats[format_index].min_bitrate_kbps * 1000;
|
| }
|
|
|
| bool SlotSimulcastMaxResolution(size_t max_layers, int* width, int* height) {
|
| @@ -233,7 +184,6 @@ int GetTotalMaxBitrateBps(const std::vector<webrtc::VideoStream>& streams) {
|
|
|
| std::vector<webrtc::VideoStream> GetSimulcastConfig(
|
| size_t max_streams,
|
| - SimulcastBitrateMode bitrate_mode,
|
| int width,
|
| int height,
|
| int max_bitrate_bps,
|
| @@ -265,12 +215,12 @@ std::vector<webrtc::VideoStream> GetSimulcastConfig(
|
| // TODO(pbos): Fill actual temporal-layer bitrate thresholds.
|
| streams[s].temporal_layer_thresholds_bps.resize(
|
| kDefaultConferenceNumberOfTemporalLayers[s] - 1);
|
| - streams[s].max_bitrate_bps = FindSimulcastMaxBitrateBps(
|
| - width, height, simulcast_layers, bitrate_mode);
|
| - streams[s].target_bitrate_bps = FindSimulcastTargetBitrateBps(
|
| - width, height, simulcast_layers, bitrate_mode);
|
| - streams[s].min_bitrate_bps = FindSimulcastMinBitrateBps(
|
| - width, height, simulcast_layers, bitrate_mode);
|
| + streams[s].max_bitrate_bps =
|
| + FindSimulcastMaxBitrateBps(width, height, simulcast_layers);
|
| + streams[s].target_bitrate_bps =
|
| + FindSimulcastTargetBitrateBps(width, height, simulcast_layers);
|
| + streams[s].min_bitrate_bps =
|
| + FindSimulcastMinBitrateBps(width, height, simulcast_layers);
|
| streams[s].max_qp = max_qp;
|
| streams[s].max_framerate = max_framerate;
|
| width /= 2;
|
| @@ -289,126 +239,6 @@ std::vector<webrtc::VideoStream> GetSimulcastConfig(
|
| return streams;
|
| }
|
|
|
| -bool ConfigureSimulcastCodec(
|
| - int number_ssrcs,
|
| - SimulcastBitrateMode bitrate_mode,
|
| - webrtc::VideoCodec* codec) {
|
| - std::vector<webrtc::VideoStream> streams =
|
| - GetSimulcastConfig(static_cast<size_t>(number_ssrcs),
|
| - bitrate_mode,
|
| - static_cast<int>(codec->width),
|
| - static_cast<int>(codec->height),
|
| - codec->maxBitrate * 1000,
|
| - codec->qpMax,
|
| - codec->maxFramerate);
|
| - // Add simulcast sub-streams from lower resolution to higher resolutions.
|
| - codec->numberOfSimulcastStreams = static_cast<unsigned int>(streams.size());
|
| - codec->width = static_cast<unsigned short>(streams.back().width);
|
| - codec->height = static_cast<unsigned short>(streams.back().height);
|
| - // When using simulcast, |codec->maxBitrate| is set to the sum of the max
|
| - // bitrates over all streams. For a given stream |s|, the max bitrate for that
|
| - // stream is set by |simulcastStream[s].targetBitrate|, if it is not the
|
| - // highest resolution stream, otherwise it is set by
|
| - // |simulcastStream[s].maxBitrate|.
|
| -
|
| - for (size_t s = 0; s < streams.size(); ++s) {
|
| - codec->simulcastStream[s].width =
|
| - static_cast<unsigned short>(streams[s].width);
|
| - codec->simulcastStream[s].height =
|
| - static_cast<unsigned short>(streams[s].height);
|
| - codec->simulcastStream[s].numberOfTemporalLayers =
|
| - static_cast<unsigned int>(
|
| - streams[s].temporal_layer_thresholds_bps.size() + 1);
|
| - codec->simulcastStream[s].minBitrate = streams[s].min_bitrate_bps / 1000;
|
| - codec->simulcastStream[s].targetBitrate =
|
| - streams[s].target_bitrate_bps / 1000;
|
| - codec->simulcastStream[s].maxBitrate = streams[s].max_bitrate_bps / 1000;
|
| - codec->simulcastStream[s].qpMax = streams[s].max_qp;
|
| - }
|
| -
|
| - codec->maxBitrate =
|
| - static_cast<unsigned int>(GetTotalMaxBitrateBps(streams) / 1000);
|
| -
|
| - codec->codecSpecific.VP8.numberOfTemporalLayers =
|
| - kDefaultConferenceNumberOfTemporalLayers[0];
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool ConfigureSimulcastCodec(
|
| - const StreamParams& sp,
|
| - const VideoOptions& options,
|
| - webrtc::VideoCodec* codec) {
|
| - std::vector<uint32_t> ssrcs;
|
| - GetSimulcastSsrcs(sp, &ssrcs);
|
| - SimulcastBitrateMode bitrate_mode = GetSimulcastBitrateMode(options);
|
| - return ConfigureSimulcastCodec(static_cast<int>(ssrcs.size()), bitrate_mode,
|
| - codec);
|
| -}
|
| -
|
| -void ConfigureSimulcastTemporalLayers(
|
| - int num_temporal_layers, webrtc::VideoCodec* codec) {
|
| - for (size_t i = 0; i < codec->numberOfSimulcastStreams; ++i) {
|
| - codec->simulcastStream[i].numberOfTemporalLayers = num_temporal_layers;
|
| - }
|
| -}
|
| -
|
| -void DisableSimulcastCodec(webrtc::VideoCodec* codec) {
|
| - // TODO(hellner): the proper solution is to uncomment the next code line
|
| - // and remove the lines following it in this condition. This is pending
|
| - // b/7012070 being fixed.
|
| - // codec->numberOfSimulcastStreams = 0;
|
| - // It is possible to set non simulcast without the above line. However,
|
| - // the max bitrate for every simulcast layer must be set to 0. Further,
|
| - // there is a sanity check making sure that the aspect ratio is the same
|
| - // for all simulcast layers. The for-loop makes sure that the sanity check
|
| - // does not fail.
|
| - if (codec->numberOfSimulcastStreams > 0) {
|
| - const int ratio = codec->width / codec->height;
|
| - for (int i = 0; i < codec->numberOfSimulcastStreams - 1; ++i) {
|
| - // Min/target bitrate has to be zero not to influence padding
|
| - // calculations in VideoEngine.
|
| - codec->simulcastStream[i].minBitrate = 0;
|
| - codec->simulcastStream[i].targetBitrate = 0;
|
| - codec->simulcastStream[i].maxBitrate = 0;
|
| - codec->simulcastStream[i].width =
|
| - codec->simulcastStream[i].height * ratio;
|
| - codec->simulcastStream[i].numberOfTemporalLayers = 1;
|
| - }
|
| - // The for loop above did not set the bitrate of the highest layer.
|
| - codec->simulcastStream[codec->numberOfSimulcastStreams - 1]
|
| - .minBitrate = 0;
|
| - codec->simulcastStream[codec->numberOfSimulcastStreams - 1]
|
| - .targetBitrate = 0;
|
| - codec->simulcastStream[codec->numberOfSimulcastStreams - 1].
|
| - maxBitrate = 0;
|
| - // The highest layer has to correspond to the non-simulcast resolution.
|
| - codec->simulcastStream[codec->numberOfSimulcastStreams - 1].
|
| - width = codec->width;
|
| - codec->simulcastStream[codec->numberOfSimulcastStreams - 1].
|
| - height = codec->height;
|
| - codec->simulcastStream[codec->numberOfSimulcastStreams - 1].
|
| - numberOfTemporalLayers = 1;
|
| - // TODO(hellner): the maxFramerate should also be set here according to
|
| - // the screencasts framerate. Doing so will break some
|
| - // unittests.
|
| - }
|
| -}
|
| -
|
| -void LogSimulcastSubstreams(const webrtc::VideoCodec& codec) {
|
| - for (size_t i = 0; i < codec.numberOfSimulcastStreams; ++i) {
|
| - LOG(LS_INFO) << "Simulcast substream " << i << ": "
|
| - << codec.simulcastStream[i].width << "x"
|
| - << codec.simulcastStream[i].height << "@"
|
| - << codec.simulcastStream[i].minBitrate << "-"
|
| - << codec.simulcastStream[i].maxBitrate << "kbps"
|
| - << " with "
|
| - << static_cast<int>(
|
| - codec.simulcastStream[i].numberOfTemporalLayers)
|
| - << " temporal layers";
|
| - }
|
| -}
|
| -
|
| static const int kScreenshareMinBitrateKbps = 50;
|
| static const int kScreenshareMaxBitrateKbps = 6000;
|
| static const int kScreenshareDefaultTl0BitrateKbps = 200;
|
| @@ -458,16 +288,4 @@ bool ScreenshareLayerConfig::FromFieldTrialGroup(
|
| return true;
|
| }
|
|
|
| -void ConfigureConferenceModeScreencastCodec(webrtc::VideoCodec* codec) {
|
| - codec->codecSpecific.VP8.numberOfTemporalLayers = 2;
|
| - codec->codecSpecific.VP8.automaticResizeOn = false;
|
| - 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
|
|
|