| Index: webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| diff --git a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| index 586a6491fa027642c95b46b1601ff429eda128d1..766e517484671a4e1cfa7ac0c7f9621a91f7ea6e 100644
|
| --- a/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| +++ b/webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc
|
| @@ -17,6 +17,7 @@
|
|
|
| #include "webrtc/base/checks.h"
|
| #include "webrtc/modules/video_coding/codecs/vp8/screenshare_layers.h"
|
| +#include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
|
| #include "webrtc/system_wrappers/include/clock.h"
|
|
|
| namespace {
|
| @@ -26,14 +27,6 @@ const unsigned int kDefaultMaxQp = 56;
|
| // Max qp for lowest spatial resolution when doing simulcast.
|
| const unsigned int kLowestResMaxQp = 45;
|
|
|
| -uint32_t SumStreamTargetBitrate(int streams, const webrtc::VideoCodec& codec) {
|
| - uint32_t bitrate_sum = 0;
|
| - for (int i = 0; i < streams; ++i) {
|
| - bitrate_sum += codec.simulcastStream[i].targetBitrate;
|
| - }
|
| - return bitrate_sum;
|
| -}
|
| -
|
| uint32_t SumStreamMaxBitrate(int streams, const webrtc::VideoCodec& codec) {
|
| uint32_t bitrate_sum = 0;
|
| for (int i = 0; i < streams; ++i) {
|
| @@ -92,13 +85,8 @@ int VerifyCodec(const webrtc::VideoCodec* inst) {
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| }
|
|
|
| -// TL1 FrameDropper's max time to drop frames.
|
| -const float kTl1MaxTimeToDropFrames = 20.0f;
|
| -
|
| struct ScreenshareTemporalLayersFactory : webrtc::TemporalLayersFactory {
|
| - ScreenshareTemporalLayersFactory()
|
| - : tl1_frame_dropper_(kTl1MaxTimeToDropFrames) {}
|
| -
|
| + ScreenshareTemporalLayersFactory() {}
|
| virtual ~ScreenshareTemporalLayersFactory() {}
|
|
|
| virtual webrtc::TemporalLayers* Create(int num_temporal_layers,
|
| @@ -106,9 +94,6 @@ struct ScreenshareTemporalLayersFactory : webrtc::TemporalLayersFactory {
|
| return new webrtc::ScreenshareLayers(num_temporal_layers, rand(),
|
| webrtc::Clock::GetRealTimeClock());
|
| }
|
| -
|
| - mutable webrtc::FrameDropper tl0_frame_dropper_;
|
| - mutable webrtc::FrameDropper tl1_frame_dropper_;
|
| };
|
|
|
| // An EncodedImageCallback implementation that forwards on calls to a
|
| @@ -139,9 +124,10 @@ namespace webrtc {
|
|
|
| SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory)
|
| : factory_(factory),
|
| - encoded_complete_callback_(NULL),
|
| + encoded_complete_callback_(nullptr),
|
| implementation_name_("SimulcastEncoderAdapter") {
|
| memset(&codec_, 0, sizeof(webrtc::VideoCodec));
|
| + rate_allocator_.reset(new SimulcastRateAllocator(codec_));
|
| }
|
|
|
| SimulcastEncoderAdapter::~SimulcastEncoderAdapter() {
|
| @@ -189,6 +175,9 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
|
| }
|
|
|
| codec_ = *inst;
|
| + rate_allocator_.reset(new SimulcastRateAllocator(codec_));
|
| + std::vector<uint32_t> start_bitrates =
|
| + rate_allocator_->GetAllocation(codec_.startBitrate);
|
|
|
| // Special mode when screensharing on a single stream.
|
| if (number_of_streams == 1 && inst->mode == kScreensharing) {
|
| @@ -200,15 +189,18 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
|
| // Create |number_of_streams| of encoder instances and init them.
|
| for (int i = 0; i < number_of_streams; ++i) {
|
| VideoCodec stream_codec;
|
| - bool send_stream = true;
|
| + uint32_t start_bitrate_kbps = start_bitrates[i];
|
| if (!doing_simulcast) {
|
| stream_codec = codec_;
|
| stream_codec.numberOfSimulcastStreams = 1;
|
| } else {
|
| + // Cap start bitrate to the min bitrate in order to avoid strange codec
|
| + // behavior. Since sending sending will be false, this should not matter.
|
| + start_bitrate_kbps =
|
| + std::max(codec_.simulcastStream[i].minBitrate, start_bitrate_kbps);
|
| bool highest_resolution_stream = (i == (number_of_streams - 1));
|
| - PopulateStreamCodec(&codec_, i, number_of_streams,
|
| - highest_resolution_stream, &stream_codec,
|
| - &send_stream);
|
| + PopulateStreamCodec(&codec_, i, start_bitrate_kbps,
|
| + highest_resolution_stream, &stream_codec);
|
| }
|
|
|
| // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl.
|
| @@ -225,7 +217,8 @@ int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
|
| EncodedImageCallback* callback = new AdapterEncodedImageCallback(this, i);
|
| encoder->RegisterEncodeCompleteCallback(callback);
|
| streaminfos_.push_back(StreamInfo(encoder, callback, stream_codec.width,
|
| - stream_codec.height, send_stream));
|
| + stream_codec.height,
|
| + start_bitrate_kbps > 0));
|
| if (i != 0)
|
| implementation_name += ", ";
|
| implementation_name += streaminfos_[i].encoder->ImplementationName();
|
| @@ -363,6 +356,8 @@ int SimulcastEncoderAdapter::SetRates(uint32_t new_bitrate_kbit,
|
| if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) {
|
| new_bitrate_kbit = codec_.maxBitrate;
|
| }
|
| +
|
| + std::vector<uint32_t> stream_bitrates;
|
| if (new_bitrate_kbit > 0) {
|
| // Make sure the bitrate fits the configured min bitrates. 0 is a special
|
| // value that means paused, though, so leave it alone.
|
| @@ -373,19 +368,20 @@ int SimulcastEncoderAdapter::SetRates(uint32_t new_bitrate_kbit,
|
| new_bitrate_kbit < codec_.simulcastStream[0].minBitrate) {
|
| new_bitrate_kbit = codec_.simulcastStream[0].minBitrate;
|
| }
|
| + stream_bitrates = rate_allocator_->GetAllocation(new_bitrate_kbit);
|
| }
|
| codec_.maxFramerate = new_framerate;
|
|
|
| - bool send_stream = true;
|
| - uint32_t stream_bitrate = 0;
|
| + // Disable any stream not in the current allocation.
|
| + stream_bitrates.resize(streaminfos_.size(), 0U);
|
| +
|
| for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
|
| - stream_bitrate = GetStreamBitrate(stream_idx, streaminfos_.size(),
|
| - new_bitrate_kbit, &send_stream);
|
| + uint32_t stream_bitrate_kbps = stream_bitrates[stream_idx];
|
| // Need a key frame if we have not sent this stream before.
|
| - if (send_stream && !streaminfos_[stream_idx].send_stream) {
|
| + if (stream_bitrate_kbps > 0 && !streaminfos_[stream_idx].send_stream) {
|
| streaminfos_[stream_idx].key_frame_request = true;
|
| }
|
| - streaminfos_[stream_idx].send_stream = send_stream;
|
| + streaminfos_[stream_idx].send_stream = stream_bitrate_kbps > 0;
|
|
|
| // TODO(holmer): This is a temporary hack for screensharing, where we
|
| // interpret the startBitrate as the encoder target bitrate. This is
|
| @@ -395,14 +391,15 @@ int SimulcastEncoderAdapter::SetRates(uint32_t new_bitrate_kbit,
|
| if (codec_.targetBitrate > 0 &&
|
| (codec_.codecSpecific.VP8.numberOfTemporalLayers == 2 ||
|
| codec_.simulcastStream[0].numberOfTemporalLayers == 2)) {
|
| - stream_bitrate = std::min(codec_.maxBitrate, stream_bitrate);
|
| + stream_bitrate_kbps = std::min(codec_.maxBitrate, stream_bitrate_kbps);
|
| // TODO(ronghuawu): Can't change max bitrate via the VideoEncoder
|
| // interface. And VP8EncoderImpl doesn't take negative framerate.
|
| - // max_bitrate = std::min(codec_.maxBitrate, stream_bitrate);
|
| + // max_bitrate = std::min(codec_.maxBitrate, stream_bitrate_kbps);
|
| // new_framerate = -1;
|
| }
|
|
|
| - streaminfos_[stream_idx].encoder->SetRates(stream_bitrate, new_framerate);
|
| + streaminfos_[stream_idx].encoder->SetRates(stream_bitrate_kbps,
|
| + new_framerate);
|
| }
|
|
|
| return WEBRTC_VIDEO_CODEC_OK;
|
| @@ -422,61 +419,12 @@ EncodedImageCallback::Result SimulcastEncoderAdapter::OnEncodedImage(
|
| encodedImage, &stream_codec_specific, fragmentation);
|
| }
|
|
|
| -uint32_t SimulcastEncoderAdapter::GetStreamBitrate(
|
| - int stream_idx,
|
| - size_t total_number_of_streams,
|
| - uint32_t new_bitrate_kbit,
|
| - bool* send_stream) const {
|
| - if (total_number_of_streams == 1) {
|
| - *send_stream = true;
|
| - return new_bitrate_kbit;
|
| - }
|
| -
|
| - // The bitrate needed to start sending this stream is given by the
|
| - // minimum bitrate allowed for encoding this stream, plus the sum target
|
| - // rates of all lower streams.
|
| - uint32_t sum_target_lower_streams =
|
| - SumStreamTargetBitrate(stream_idx, codec_);
|
| - uint32_t bitrate_to_send_this_layer =
|
| - codec_.simulcastStream[stream_idx].minBitrate + sum_target_lower_streams;
|
| - if (new_bitrate_kbit >= bitrate_to_send_this_layer) {
|
| - // We have enough bandwidth to send this stream.
|
| - *send_stream = true;
|
| - // Bitrate for this stream is the new bitrate (|new_bitrate_kbit|) minus the
|
| - // sum target rates of the lower streams, and capped to a maximum bitrate.
|
| - // The maximum cap depends on whether we send the next higher stream.
|
| - // If we will be sending the next higher stream, |max_rate| is given by
|
| - // current stream's |targetBitrate|, otherwise it's capped by |maxBitrate|.
|
| - if (stream_idx < codec_.numberOfSimulcastStreams - 1) {
|
| - unsigned int max_rate = codec_.simulcastStream[stream_idx].maxBitrate;
|
| - if (new_bitrate_kbit >=
|
| - SumStreamTargetBitrate(stream_idx + 1, codec_) +
|
| - codec_.simulcastStream[stream_idx + 1].minBitrate) {
|
| - max_rate = codec_.simulcastStream[stream_idx].targetBitrate;
|
| - }
|
| - return std::min(new_bitrate_kbit - sum_target_lower_streams, max_rate);
|
| - } else {
|
| - // For the highest stream (highest resolution), the |targetBitRate| and
|
| - // |maxBitrate| are not used. Any excess bitrate (above the targets of
|
| - // all lower streams) is given to this (highest resolution) stream.
|
| - return new_bitrate_kbit - sum_target_lower_streams;
|
| - }
|
| - } else {
|
| - // Not enough bitrate for this stream.
|
| - // Return our max bitrate of |stream_idx| - 1, but we don't send it. We need
|
| - // to keep this resolution coding in order for the multi-encoder to work.
|
| - *send_stream = false;
|
| - return codec_.simulcastStream[stream_idx - 1].maxBitrate;
|
| - }
|
| -}
|
| -
|
| void SimulcastEncoderAdapter::PopulateStreamCodec(
|
| const webrtc::VideoCodec* inst,
|
| int stream_index,
|
| - size_t total_number_of_streams,
|
| + uint32_t start_bitrate_kbps,
|
| bool highest_resolution_stream,
|
| - webrtc::VideoCodec* stream_codec,
|
| - bool* send_stream) {
|
| + webrtc::VideoCodec* stream_codec) {
|
| *stream_codec = *inst;
|
|
|
| // Stream specific settings.
|
| @@ -505,9 +453,7 @@ void SimulcastEncoderAdapter::PopulateStreamCodec(
|
| }
|
| // TODO(ronghuawu): what to do with targetBitrate.
|
|
|
| - int stream_bitrate = GetStreamBitrate(stream_index, total_number_of_streams,
|
| - inst->startBitrate, send_stream);
|
| - stream_codec->startBitrate = stream_bitrate;
|
| + stream_codec->startBitrate = start_bitrate_kbps;
|
| }
|
|
|
| bool SimulcastEncoderAdapter::Initialized() const {
|
|
|