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

          Line data    Source code
       1             : /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
       2             : *
       3             : *  Use of this source code is governed by a BSD-style license
       4             : *  that can be found in the LICENSE file in the root of the source
       5             : *  tree. An additional intellectual property rights grant can be found
       6             : *  in the file PATENTS.  All contributing project authors may
       7             : *  be found in the AUTHORS file in the root of the source tree.
       8             : */
       9             : 
      10             : #include <stdlib.h>
      11             : #include <algorithm>
      12             : 
      13             : #include "vpx/vpx_encoder.h"
      14             : #include "vpx/vp8cx.h"
      15             : #include "webrtc/base/checks.h"
      16             : #include "webrtc/base/optional.h"
      17             : #include "webrtc/modules/video_coding/include/video_codec_interface.h"
      18             : #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
      19             : #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
      20             : 
      21             : // This file implements logic to adapt the number of temporal layers based on
      22             : // input frame rate in order to avoid having the base layer being relaying at
      23             : // a below acceptable framerate.
      24             : namespace webrtc {
      25             : namespace {
      26             : enum {
      27             :   kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
      28             :                         VP8_EFLAG_NO_REF_GF |
      29             :                         VP8_EFLAG_NO_REF_ARF,
      30             : 
      31             :   kTemporalUpdateGolden =
      32             :       VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST,
      33             : 
      34             :   kTemporalUpdateGoldenWithoutDependency =
      35             :       kTemporalUpdateGolden | VP8_EFLAG_NO_REF_GF,
      36             : 
      37             :   kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST,
      38             : 
      39             :   kTemporalUpdateAltrefWithoutDependency =
      40             :       kTemporalUpdateAltref | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF,
      41             : 
      42             :   kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
      43             :                         VP8_EFLAG_NO_UPD_LAST |
      44             :                         VP8_EFLAG_NO_UPD_ENTROPY,
      45             : 
      46             :   kTemporalUpdateNoneNoRefAltref = kTemporalUpdateNone | VP8_EFLAG_NO_REF_ARF,
      47             : 
      48             :   kTemporalUpdateNoneNoRefGoldenRefAltRef =
      49             :       VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
      50             :       VP8_EFLAG_NO_UPD_LAST |
      51             :       VP8_EFLAG_NO_UPD_ENTROPY,
      52             : 
      53             :   kTemporalUpdateGoldenWithoutDependencyRefAltRef =
      54             :       VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST,
      55             : 
      56             :   kTemporalUpdateLastRefAltRef =
      57             :       VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF,
      58             : 
      59             :   kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST,
      60             : 
      61             :   kTemporalUpdateLastAndGoldenRefAltRef =
      62             :       VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF,
      63             : 
      64             :   kTemporalUpdateLastRefAll = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF,
      65             : };
      66             : 
      67           0 : int CalculateNumberOfTemporalLayers(int current_temporal_layers,
      68             :                                     int input_fps) {
      69           0 :   if (input_fps >= 24) {
      70           0 :     return 3;
      71             :   }
      72           0 :   if (input_fps >= 20 && current_temporal_layers >= 3) {
      73             :     // Keep doing 3 temporal layers until we go below 20fps.
      74           0 :     return 3;
      75             :   }
      76           0 :   if (input_fps >= 10) {
      77           0 :     return 2;
      78             :   }
      79           0 :   if (input_fps > 8 && current_temporal_layers >= 2) {
      80             :     // keep doing 2 temporal layers until we go below 8fps
      81           0 :     return 2;
      82             :   }
      83           0 :   return 1;
      84             : }
      85             : 
      86             : class RealTimeTemporalLayers : public TemporalLayers {
      87             :  public:
      88           0 :   RealTimeTemporalLayers(int max_num_temporal_layers,
      89             :                          uint8_t initial_tl0_pic_idx)
      90           0 :       : temporal_layers_(1),
      91             :         max_temporal_layers_(max_num_temporal_layers),
      92             :         tl0_pic_idx_(initial_tl0_pic_idx),
      93             :         frame_counter_(static_cast<unsigned int>(-1)),
      94             :         timestamp_(0),
      95             :         last_base_layer_sync_(0),
      96             :         layer_ids_length_(0),
      97             :         layer_ids_(nullptr),
      98             :         encode_flags_length_(0),
      99           0 :         encode_flags_(nullptr) {
     100           0 :     RTC_CHECK_GE(max_temporal_layers_, 1);
     101           0 :     RTC_CHECK_LE(max_temporal_layers_, 3);
     102           0 :   }
     103             : 
     104           0 :   virtual ~RealTimeTemporalLayers() {}
     105             : 
     106           0 :   std::vector<uint32_t> OnRatesUpdated(int bitrate_kbps,
     107             :                                        int max_bitrate_kbps,
     108             :                                        int framerate) override {
     109           0 :     temporal_layers_ =
     110           0 :         CalculateNumberOfTemporalLayers(temporal_layers_, framerate);
     111           0 :     temporal_layers_ = std::min(temporal_layers_, max_temporal_layers_);
     112           0 :     RTC_CHECK_GE(temporal_layers_, 1);
     113           0 :     RTC_CHECK_LE(temporal_layers_, 3);
     114             : 
     115           0 :     switch (temporal_layers_) {
     116             :       case 1: {
     117             :         static const unsigned int layer_ids[] = {0u};
     118           0 :         layer_ids_ = layer_ids;
     119           0 :         layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids);
     120             : 
     121             :         static const int encode_flags[] = {kTemporalUpdateLastRefAll};
     122           0 :         encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
     123           0 :         encode_flags_ = encode_flags;
     124           0 :       } break;
     125             : 
     126             :       case 2: {
     127             :         static const unsigned int layer_ids[] = {0u, 1u};
     128           0 :         layer_ids_ = layer_ids;
     129           0 :         layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids);
     130             : 
     131             :         static const int encode_flags[] = {
     132             :             kTemporalUpdateLastAndGoldenRefAltRef,
     133             :             kTemporalUpdateGoldenWithoutDependencyRefAltRef,
     134             :             kTemporalUpdateLastRefAltRef,
     135             :             kTemporalUpdateGoldenRefAltRef,
     136             :             kTemporalUpdateLastRefAltRef,
     137             :             kTemporalUpdateGoldenRefAltRef,
     138             :             kTemporalUpdateLastRefAltRef,
     139             :             kTemporalUpdateNone};
     140           0 :         encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
     141           0 :         encode_flags_ = encode_flags;
     142           0 :       } break;
     143             : 
     144             :       case 3: {
     145             :         static const unsigned int layer_ids[] = {0u, 2u, 1u, 2u};
     146           0 :         layer_ids_ = layer_ids;
     147           0 :         layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids);
     148             : 
     149             :         static const int encode_flags[] = {
     150             :             kTemporalUpdateLastAndGoldenRefAltRef,
     151             :             kTemporalUpdateNoneNoRefGoldenRefAltRef,
     152             :             kTemporalUpdateGoldenWithoutDependencyRefAltRef,
     153             :             kTemporalUpdateNone,
     154             :             kTemporalUpdateLastRefAltRef,
     155             :             kTemporalUpdateNone,
     156             :             kTemporalUpdateGoldenRefAltRef,
     157             :             kTemporalUpdateNone};
     158           0 :         encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids);
     159           0 :         encode_flags_ = encode_flags;
     160           0 :       } break;
     161             : 
     162             :       default:
     163           0 :         RTC_NOTREACHED();
     164           0 :         return std::vector<uint32_t>();
     165             :     }
     166             : 
     167           0 :     std::vector<uint32_t> bitrates;
     168           0 :     const int num_layers = std::max(1, temporal_layers_);
     169           0 :     for (int i = 0; i < num_layers; ++i) {
     170             :       float layer_bitrate =
     171           0 :           bitrate_kbps * kVp8LayerRateAlloction[num_layers - 1][i];
     172           0 :       bitrates.push_back(static_cast<uint32_t>(layer_bitrate + 0.5));
     173             :     }
     174           0 :     new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>(bitrates);
     175             : 
     176             :     // Allocation table is of aggregates, transform to individual rates.
     177           0 :     uint32_t sum = 0;
     178           0 :     for (int i = 0; i < num_layers; ++i) {
     179           0 :       uint32_t layer_bitrate = bitrates[i];
     180           0 :       RTC_DCHECK_LE(sum, bitrates[i]);
     181           0 :       bitrates[i] -= sum;
     182           0 :       sum = layer_bitrate;
     183             : 
     184           0 :       if (sum >= static_cast<uint32_t>(bitrate_kbps)) {
     185             :         // Sum adds up; any subsequent layers will be 0.
     186           0 :         bitrates.resize(i + 1);
     187           0 :         break;
     188             :       }
     189             :     }
     190             : 
     191           0 :     return bitrates;
     192             :   }
     193             : 
     194           0 :   bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override {
     195           0 :     if (!new_bitrates_kbps_)
     196           0 :       return false;
     197             : 
     198           0 :     cfg->ts_number_layers = temporal_layers_;
     199           0 :     for (int tl = 0; tl < temporal_layers_; ++tl) {
     200           0 :       cfg->ts_target_bitrate[tl] = (*new_bitrates_kbps_)[tl];
     201             :     }
     202           0 :     new_bitrates_kbps_ = rtc::Optional<std::vector<uint32_t>>();
     203             : 
     204           0 :     cfg->ts_periodicity = layer_ids_length_;
     205           0 :     int decimator = 1;
     206           0 :     for (int i = temporal_layers_ - 1; i >= 0; --i, decimator *= 2) {
     207           0 :       cfg->ts_rate_decimator[i] = decimator;
     208             :     }
     209             : 
     210           0 :     memcpy(cfg->ts_layer_id, layer_ids_,
     211           0 :            sizeof(unsigned int) * layer_ids_length_);
     212             : 
     213           0 :     return true;
     214             :   }
     215             : 
     216           0 :   int EncodeFlags(uint32_t timestamp) override {
     217           0 :     frame_counter_++;
     218           0 :     return CurrentEncodeFlags();
     219             :   }
     220             : 
     221           0 :   int CurrentEncodeFlags() const {
     222           0 :     assert(encode_flags_length_ > 0 && encode_flags_ != NULL);
     223           0 :     int index = frame_counter_ % encode_flags_length_;
     224           0 :     assert(index >= 0 && index < encode_flags_length_);
     225           0 :     return encode_flags_[index];
     226             :   }
     227             : 
     228           0 :   int CurrentLayerId() const override {
     229           0 :     assert(layer_ids_length_ > 0 && layer_ids_ != NULL);
     230           0 :     int index = frame_counter_ % layer_ids_length_;
     231           0 :     assert(index >= 0 && index < layer_ids_length_);
     232           0 :     return layer_ids_[index];
     233             :   }
     234             : 
     235           0 :   void PopulateCodecSpecific(bool base_layer_sync,
     236             :                              CodecSpecificInfoVP8* vp8_info,
     237             :                              uint32_t timestamp) override {
     238           0 :     assert(temporal_layers_ > 0);
     239             : 
     240           0 :     if (temporal_layers_ == 1) {
     241           0 :       vp8_info->temporalIdx = kNoTemporalIdx;
     242           0 :       vp8_info->layerSync = false;
     243           0 :       vp8_info->tl0PicIdx = kNoTl0PicIdx;
     244             :     } else {
     245           0 :       if (base_layer_sync) {
     246           0 :         vp8_info->temporalIdx = 0;
     247           0 :         vp8_info->layerSync = true;
     248             :       } else {
     249           0 :         vp8_info->temporalIdx = CurrentLayerId();
     250           0 :         int temporal_reference = CurrentEncodeFlags();
     251             : 
     252           0 :         if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
     253           0 :             temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
     254             :             temporal_reference ==
     255           0 :                 kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
     256           0 :             temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
     257           0 :             (temporal_reference == kTemporalUpdateNone &&
     258           0 :              temporal_layers_ == 4)) {
     259           0 :           vp8_info->layerSync = true;
     260             :         } else {
     261           0 :           vp8_info->layerSync = false;
     262             :         }
     263             :       }
     264           0 :       if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
     265             :         // Regardless of pattern the frame after a base layer sync will always
     266             :         // be a layer sync.
     267           0 :         vp8_info->layerSync = true;
     268             :       }
     269           0 :       if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
     270           0 :         timestamp_ = timestamp;
     271           0 :         tl0_pic_idx_++;
     272             :       }
     273           0 :       last_base_layer_sync_ = base_layer_sync;
     274           0 :       vp8_info->tl0PicIdx = tl0_pic_idx_;
     275             :     }
     276           0 :   }
     277             : 
     278           0 :   void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override {}
     279             : 
     280             :  private:
     281             :   int temporal_layers_;
     282             :   int max_temporal_layers_;
     283             : 
     284             :   int tl0_pic_idx_;
     285             :   unsigned int frame_counter_;
     286             :   uint32_t timestamp_;
     287             :   bool last_base_layer_sync_;
     288             : 
     289             :   // Pattern of temporal layer ids.
     290             :   int layer_ids_length_;
     291             :   const unsigned int* layer_ids_;
     292             : 
     293             :   // Pattern of encode flags.
     294             :   int encode_flags_length_;
     295             :   const int* encode_flags_;
     296             : 
     297             :   rtc::Optional<std::vector<uint32_t>> new_bitrates_kbps_;
     298             : };
     299             : }  // namespace
     300             : 
     301           0 : TemporalLayers* RealTimeTemporalLayersFactory::Create(
     302             :     int simulcast_id,
     303             :     int max_temporal_layers,
     304             :     uint8_t initial_tl0_pic_idx) const {
     305             :   TemporalLayers* tl =
     306           0 :       new RealTimeTemporalLayers(max_temporal_layers, initial_tl0_pic_idx);
     307           0 :   if (listener_)
     308           0 :     listener_->OnTemporalLayersCreated(simulcast_id, tl);
     309           0 :   return tl;
     310             : }
     311             : }  // namespace webrtc

Generated by: LCOV version 1.13