LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/video_coding/utility - simulcast_rate_allocator.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 78 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/video_coding/utility/simulcast_rate_allocator.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <memory>
      15             : #include <vector>
      16             : #include <utility>
      17             : 
      18             : #include "webrtc/base/checks.h"
      19             : 
      20             : namespace webrtc {
      21             : 
      22           0 : SimulcastRateAllocator::SimulcastRateAllocator(
      23             :     const VideoCodec& codec,
      24           0 :     std::unique_ptr<TemporalLayersFactory> tl_factory)
      25           0 :     : codec_(codec), tl_factory_(std::move(tl_factory)) {
      26           0 :   if (tl_factory_.get())
      27           0 :     tl_factory_->SetListener(this);
      28           0 : }
      29             : 
      30           0 : void SimulcastRateAllocator::OnTemporalLayersCreated(int simulcast_id,
      31             :                                                      TemporalLayers* layers) {
      32           0 :   RTC_DCHECK(temporal_layers_.find(simulcast_id) == temporal_layers_.end());
      33           0 :   temporal_layers_[simulcast_id] = layers;
      34           0 : }
      35             : 
      36           0 : BitrateAllocation SimulcastRateAllocator::GetAllocation(
      37             :     uint32_t total_bitrate_bps,
      38             :     uint32_t framerate) {
      39           0 :   uint32_t left_to_allocate = total_bitrate_bps;
      40           0 :   if (codec_.maxBitrate && codec_.maxBitrate * 1000 < left_to_allocate)
      41           0 :     left_to_allocate = codec_.maxBitrate * 1000;
      42             : 
      43           0 :   BitrateAllocation allocated_bitrates_bps;
      44           0 :   if (codec_.numberOfSimulcastStreams == 0) {
      45             :     // No simulcast, just set the target as this has been capped already.
      46           0 :     allocated_bitrates_bps.SetBitrate(
      47           0 :         0, 0, std::max(codec_.minBitrate * 1000, left_to_allocate));
      48             :   } else {
      49             :     // Always allocate enough bitrate for the minimum bitrate of the first
      50             :     // layer. Suspending below min bitrate is controlled outside the codec
      51             :     // implementation and is not overridden by this.
      52           0 :     left_to_allocate =
      53           0 :         std::max(codec_.simulcastStream[0].minBitrate * 1000, left_to_allocate);
      54             : 
      55             :     // Begin by allocating bitrate to simulcast streams, putting all bitrate in
      56             :     // temporal layer 0. We'll then distribute this bitrate, across potential
      57             :     // temporal layers, when stream allocation is done.
      58             : 
      59             :     // Allocate up to the target bitrate for each simulcast layer.
      60           0 :     size_t layer = 0;
      61           0 :     for (; layer < codec_.numberOfSimulcastStreams; ++layer) {
      62           0 :       const SimulcastStream& stream = codec_.simulcastStream[layer];
      63           0 :       if (left_to_allocate < stream.minBitrate * 1000)
      64           0 :         break;
      65             :       uint32_t allocation =
      66           0 :           std::min(left_to_allocate, stream.targetBitrate * 1000);
      67           0 :       allocated_bitrates_bps.SetBitrate(layer, 0, allocation);
      68           0 :       RTC_DCHECK_LE(allocation, left_to_allocate);
      69           0 :       left_to_allocate -= allocation;
      70             :     }
      71             : 
      72             :     // Next, try allocate remaining bitrate, up to max bitrate, in top stream.
      73             :     // TODO(sprang): Allocate up to max bitrate for all layers once we have a
      74             :     //               better idea of possible performance implications.
      75           0 :     if (left_to_allocate > 0) {
      76           0 :       size_t active_layer = layer - 1;
      77           0 :       const SimulcastStream& stream = codec_.simulcastStream[active_layer];
      78             :       uint32_t bitrate_bps =
      79           0 :           allocated_bitrates_bps.GetSpatialLayerSum(active_layer);
      80             :       uint32_t allocation =
      81           0 :           std::min(left_to_allocate, stream.maxBitrate * 1000 - bitrate_bps);
      82           0 :       bitrate_bps += allocation;
      83           0 :       RTC_DCHECK_LE(allocation, left_to_allocate);
      84           0 :       left_to_allocate -= allocation;
      85           0 :       allocated_bitrates_bps.SetBitrate(active_layer, 0, bitrate_bps);
      86             :     }
      87             :   }
      88             : 
      89             :   const int num_spatial_streams =
      90           0 :       std::max(1, static_cast<int>(codec_.numberOfSimulcastStreams));
      91             : 
      92             :   // Finally, distribute the bitrate for the simulcast streams across the
      93             :   // available temporal layers.
      94           0 :   for (int simulcast_id = 0; simulcast_id < num_spatial_streams;
      95             :        ++simulcast_id) {
      96           0 :     auto tl_it = temporal_layers_.find(simulcast_id);
      97           0 :     if (tl_it == temporal_layers_.end())
      98           0 :       continue;  // TODO(sprang): If > 1 SS, assume default TL alloc?
      99             : 
     100             :     uint32_t target_bitrate_kbps =
     101           0 :         allocated_bitrates_bps.GetBitrate(simulcast_id, 0) / 1000;
     102           0 :     const uint32_t expected_allocated_bitrate_kbps = target_bitrate_kbps;
     103           0 :     RTC_DCHECK_EQ(
     104             :         target_bitrate_kbps,
     105           0 :         allocated_bitrates_bps.GetSpatialLayerSum(simulcast_id) / 1000);
     106           0 :     const int num_temporal_streams = std::max<uint8_t>(
     107           0 :         1, codec_.numberOfSimulcastStreams == 0
     108           0 :                ? codec_.VP8().numberOfTemporalLayers
     109           0 :                : codec_.simulcastStream[simulcast_id].numberOfTemporalLayers);
     110             : 
     111             :     uint32_t max_bitrate_kbps;
     112             :     // Legacy temporal-layered only screenshare, or simulcast screenshare
     113             :     // with legacy mode for simulcast stream 0.
     114           0 :     if (codec_.mode == kScreensharing && codec_.targetBitrate > 0 &&
     115           0 :         ((num_spatial_streams == 1 && num_temporal_streams == 2) ||  // Legacy.
     116           0 :          (num_spatial_streams > 1 && simulcast_id == 0))) {  // Simulcast.
     117             :       // TODO(holmer): This is a "temporary" hack for screensharing, where we
     118             :       // interpret the startBitrate as the encoder target bitrate. This is
     119             :       // to allow for a different max bitrate, so if the codec can't meet
     120             :       // the target we still allow it to overshoot up to the max before dropping
     121             :       // frames. This hack should be improved.
     122           0 :       int tl0_bitrate = std::min(codec_.targetBitrate, target_bitrate_kbps);
     123           0 :       max_bitrate_kbps = std::min(codec_.maxBitrate, target_bitrate_kbps);
     124           0 :       target_bitrate_kbps = tl0_bitrate;
     125           0 :     } else if (num_spatial_streams == 1) {
     126           0 :       max_bitrate_kbps = codec_.maxBitrate;
     127             :     } else {
     128           0 :       max_bitrate_kbps = codec_.simulcastStream[simulcast_id].maxBitrate;
     129             :     }
     130             : 
     131           0 :     std::vector<uint32_t> tl_allocation = tl_it->second->OnRatesUpdated(
     132           0 :         target_bitrate_kbps, max_bitrate_kbps, framerate);
     133           0 :     RTC_DCHECK_GT(tl_allocation.size(), 0);
     134           0 :     RTC_DCHECK_LE(tl_allocation.size(), num_temporal_streams);
     135             : 
     136           0 :     uint64_t tl_allocation_sum_kbps = 0;
     137           0 :     for (size_t tl_index = 0; tl_index < tl_allocation.size(); ++tl_index) {
     138           0 :       uint32_t layer_rate_kbps = tl_allocation[tl_index];
     139           0 :       allocated_bitrates_bps.SetBitrate(simulcast_id, tl_index,
     140           0 :                                         layer_rate_kbps * 1000);
     141           0 :       tl_allocation_sum_kbps += layer_rate_kbps;
     142             :     }
     143           0 :     RTC_DCHECK_LE(tl_allocation_sum_kbps, expected_allocated_bitrate_kbps);
     144             :   }
     145             : 
     146           0 :   return allocated_bitrates_bps;
     147             : }
     148             : 
     149           0 : uint32_t SimulcastRateAllocator::GetPreferredBitrateBps(uint32_t framerate) {
     150             :   // Create a temporary instance without temporal layers, as they may be
     151             :   // stateful, and updating the bitrate to max here can cause side effects.
     152           0 :   SimulcastRateAllocator temp_allocator(codec_, nullptr);
     153             :   BitrateAllocation allocation =
     154           0 :       temp_allocator.GetAllocation(codec_.maxBitrate * 1000, framerate);
     155           0 :   return allocation.get_sum_bps();
     156             : }
     157             : 
     158           0 : const VideoCodec& webrtc::SimulcastRateAllocator::GetCodec() const {
     159           0 :   return codec_;
     160             : }
     161             : 
     162             : }  // namespace webrtc

Generated by: LCOV version 1.13