Home | History | Annotate | Download | only in vp8
      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 "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h"
     11 
     12 #include <assert.h>
     13 #include <stdlib.h>
     14 #include <string.h>
     15 
     16 #include "webrtc/modules/interface/module_common_types.h"
     17 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
     18 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
     19 
     20 #include "vpx/vpx_encoder.h"
     21 #include "vpx/vp8cx.h"
     22 
     23 namespace webrtc {
     24 
     25 DefaultTemporalLayers::DefaultTemporalLayers(int numberOfTemporalLayers,
     26                                              uint8_t initial_tl0_pic_idx)
     27     : number_of_temporal_layers_(numberOfTemporalLayers),
     28       temporal_ids_length_(0),
     29       temporal_pattern_length_(0),
     30       tl0_pic_idx_(initial_tl0_pic_idx),
     31       pattern_idx_(255),
     32       timestamp_(0),
     33       last_base_layer_sync_(false) {
     34   assert(kMaxTemporalStreams >= numberOfTemporalLayers);
     35   memset(temporal_ids_, 0, sizeof(temporal_ids_));
     36   memset(temporal_pattern_, 0, sizeof(temporal_pattern_));
     37 }
     38 
     39 int DefaultTemporalLayers::CurrentLayerId() const {
     40   assert(temporal_ids_length_ > 0);
     41   int index = pattern_idx_ % temporal_ids_length_;
     42   assert(index >= 0);
     43   return temporal_ids_[index];
     44  }
     45 
     46 bool DefaultTemporalLayers::ConfigureBitrates(int bitrateKbit,
     47                                               int max_bitrate_kbit,
     48                                               int framerate,
     49                                               vpx_codec_enc_cfg_t* cfg) {
     50   switch (number_of_temporal_layers_) {
     51     case 0:
     52     case 1:
     53       temporal_ids_length_ = 1;
     54       temporal_ids_[0] = 0;
     55       cfg->ts_number_layers = number_of_temporal_layers_;
     56       cfg->ts_periodicity = temporal_ids_length_;
     57       cfg->ts_target_bitrate[0] = bitrateKbit;
     58       cfg->ts_rate_decimator[0] = 1;
     59       memcpy(cfg->ts_layer_id,
     60              temporal_ids_,
     61              sizeof(unsigned int) * temporal_ids_length_);
     62       temporal_pattern_length_ = 1;
     63       temporal_pattern_[0] = kTemporalUpdateLastRefAll;
     64       break;
     65     case 2:
     66       temporal_ids_length_ = 2;
     67       temporal_ids_[0] = 0;
     68       temporal_ids_[1] = 1;
     69       cfg->ts_number_layers = number_of_temporal_layers_;
     70       cfg->ts_periodicity = temporal_ids_length_;
     71       // Split stream 60% 40%.
     72       // Bitrate API for VP8 is the agregated bitrate for all lower layers.
     73       cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[1][0];
     74       cfg->ts_target_bitrate[1] = bitrateKbit;
     75       cfg->ts_rate_decimator[0] = 2;
     76       cfg->ts_rate_decimator[1] = 1;
     77       memcpy(cfg->ts_layer_id,
     78              temporal_ids_,
     79              sizeof(unsigned int) * temporal_ids_length_);
     80       temporal_pattern_length_ = 8;
     81       temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
     82       temporal_pattern_[1] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
     83       temporal_pattern_[2] = kTemporalUpdateLastRefAltRef;
     84       temporal_pattern_[3] = kTemporalUpdateGoldenRefAltRef;
     85       temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
     86       temporal_pattern_[5] = kTemporalUpdateGoldenRefAltRef;
     87       temporal_pattern_[6] = kTemporalUpdateLastRefAltRef;
     88       temporal_pattern_[7] = kTemporalUpdateNone;
     89       break;
     90     case 3:
     91       temporal_ids_length_ = 4;
     92       temporal_ids_[0] = 0;
     93       temporal_ids_[1] = 2;
     94       temporal_ids_[2] = 1;
     95       temporal_ids_[3] = 2;
     96       cfg->ts_number_layers = number_of_temporal_layers_;
     97       cfg->ts_periodicity = temporal_ids_length_;
     98       // Split stream 40% 20% 40%.
     99       // Bitrate API for VP8 is the agregated bitrate for all lower layers.
    100       cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[2][0];
    101       cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[2][1];
    102       cfg->ts_target_bitrate[2] = bitrateKbit;
    103       cfg->ts_rate_decimator[0] = 4;
    104       cfg->ts_rate_decimator[1] = 2;
    105       cfg->ts_rate_decimator[2] = 1;
    106       memcpy(cfg->ts_layer_id,
    107              temporal_ids_,
    108              sizeof(unsigned int) * temporal_ids_length_);
    109       temporal_pattern_length_ = 8;
    110       temporal_pattern_[0] = kTemporalUpdateLastAndGoldenRefAltRef;
    111       temporal_pattern_[1] = kTemporalUpdateNoneNoRefGoldenRefAltRef;
    112       temporal_pattern_[2] = kTemporalUpdateGoldenWithoutDependencyRefAltRef;
    113       temporal_pattern_[3] = kTemporalUpdateNone;
    114       temporal_pattern_[4] = kTemporalUpdateLastRefAltRef;
    115       temporal_pattern_[5] = kTemporalUpdateNone;
    116       temporal_pattern_[6] = kTemporalUpdateGoldenRefAltRef;
    117       temporal_pattern_[7] = kTemporalUpdateNone;
    118       break;
    119     case 4:
    120       temporal_ids_length_ = 8;
    121       temporal_ids_[0] = 0;
    122       temporal_ids_[1] = 3;
    123       temporal_ids_[2] = 2;
    124       temporal_ids_[3] = 3;
    125       temporal_ids_[4] = 1;
    126       temporal_ids_[5] = 3;
    127       temporal_ids_[6] = 2;
    128       temporal_ids_[7] = 3;
    129       // Split stream 25% 15% 20% 40%.
    130       // Bitrate API for VP8 is the agregated bitrate for all lower layers.
    131       cfg->ts_number_layers = 4;
    132       cfg->ts_periodicity = temporal_ids_length_;
    133       cfg->ts_target_bitrate[0] = bitrateKbit * kVp8LayerRateAlloction[3][0];
    134       cfg->ts_target_bitrate[1] = bitrateKbit * kVp8LayerRateAlloction[3][1];
    135       cfg->ts_target_bitrate[2] = bitrateKbit * kVp8LayerRateAlloction[3][2];
    136       cfg->ts_target_bitrate[3] = bitrateKbit;
    137       cfg->ts_rate_decimator[0] = 8;
    138       cfg->ts_rate_decimator[1] = 4;
    139       cfg->ts_rate_decimator[2] = 2;
    140       cfg->ts_rate_decimator[3] = 1;
    141       memcpy(cfg->ts_layer_id,
    142              temporal_ids_,
    143              sizeof(unsigned int) * temporal_ids_length_);
    144       temporal_pattern_length_ = 16;
    145       temporal_pattern_[0] = kTemporalUpdateLast;
    146       temporal_pattern_[1] = kTemporalUpdateNone;
    147       temporal_pattern_[2] = kTemporalUpdateAltrefWithoutDependency;
    148       temporal_pattern_[3] = kTemporalUpdateNone;
    149       temporal_pattern_[4] = kTemporalUpdateGoldenWithoutDependency;
    150       temporal_pattern_[5] = kTemporalUpdateNone;
    151       temporal_pattern_[6] = kTemporalUpdateAltref;
    152       temporal_pattern_[7] = kTemporalUpdateNone;
    153       temporal_pattern_[8] = kTemporalUpdateLast;
    154       temporal_pattern_[9] = kTemporalUpdateNone;
    155       temporal_pattern_[10] = kTemporalUpdateAltref;
    156       temporal_pattern_[11] = kTemporalUpdateNone;
    157       temporal_pattern_[12] = kTemporalUpdateGolden;
    158       temporal_pattern_[13] = kTemporalUpdateNone;
    159       temporal_pattern_[14] = kTemporalUpdateAltref;
    160       temporal_pattern_[15] = kTemporalUpdateNone;
    161       break;
    162     default:
    163       assert(false);
    164       return false;
    165   }
    166   return true;
    167 }
    168 
    169 int DefaultTemporalLayers::EncodeFlags(uint32_t timestamp) {
    170   assert(number_of_temporal_layers_ > 0);
    171   assert(kMaxTemporalPattern >= temporal_pattern_length_);
    172   assert(0 < temporal_pattern_length_);
    173   int flags = 0;
    174   int patternIdx = ++pattern_idx_ % temporal_pattern_length_;
    175   assert(kMaxTemporalPattern >= patternIdx);
    176   switch (temporal_pattern_[patternIdx]) {
    177     case kTemporalUpdateLast:
    178       flags |= VP8_EFLAG_NO_UPD_GF;
    179       flags |= VP8_EFLAG_NO_UPD_ARF;
    180       flags |= VP8_EFLAG_NO_REF_GF;
    181       flags |= VP8_EFLAG_NO_REF_ARF;
    182       break;
    183     case kTemporalUpdateGoldenWithoutDependency:
    184       flags |= VP8_EFLAG_NO_REF_GF;
    185       // Deliberately no break here.
    186     case kTemporalUpdateGolden:
    187       flags |= VP8_EFLAG_NO_REF_ARF;
    188       flags |= VP8_EFLAG_NO_UPD_ARF;
    189       flags |= VP8_EFLAG_NO_UPD_LAST;
    190       break;
    191     case kTemporalUpdateAltrefWithoutDependency:
    192       flags |= VP8_EFLAG_NO_REF_ARF;
    193       flags |= VP8_EFLAG_NO_REF_GF;
    194       // Deliberately no break here.
    195     case kTemporalUpdateAltref:
    196       flags |= VP8_EFLAG_NO_UPD_GF;
    197       flags |= VP8_EFLAG_NO_UPD_LAST;
    198       break;
    199     case kTemporalUpdateNoneNoRefAltref:
    200       flags |= VP8_EFLAG_NO_REF_ARF;
    201       // Deliberately no break here.
    202     case kTemporalUpdateNone:
    203       flags |= VP8_EFLAG_NO_UPD_GF;
    204       flags |= VP8_EFLAG_NO_UPD_ARF;
    205       flags |= VP8_EFLAG_NO_UPD_LAST;
    206       flags |= VP8_EFLAG_NO_UPD_ENTROPY;
    207       break;
    208     case kTemporalUpdateNoneNoRefGoldenRefAltRef:
    209       flags |= VP8_EFLAG_NO_REF_GF;
    210       flags |= VP8_EFLAG_NO_UPD_GF;
    211       flags |= VP8_EFLAG_NO_UPD_ARF;
    212       flags |= VP8_EFLAG_NO_UPD_LAST;
    213       flags |= VP8_EFLAG_NO_UPD_ENTROPY;
    214       break;
    215     case kTemporalUpdateGoldenWithoutDependencyRefAltRef:
    216       flags |= VP8_EFLAG_NO_REF_GF;
    217       flags |= VP8_EFLAG_NO_UPD_ARF;
    218       flags |= VP8_EFLAG_NO_UPD_LAST;
    219       break;
    220     case kTemporalUpdateLastRefAltRef:
    221       flags |= VP8_EFLAG_NO_UPD_GF;
    222       flags |= VP8_EFLAG_NO_UPD_ARF;
    223       flags |= VP8_EFLAG_NO_REF_GF;
    224       break;
    225     case kTemporalUpdateGoldenRefAltRef:
    226       flags |= VP8_EFLAG_NO_UPD_ARF;
    227       flags |= VP8_EFLAG_NO_UPD_LAST;
    228       break;
    229     case kTemporalUpdateLastAndGoldenRefAltRef:
    230       flags |= VP8_EFLAG_NO_UPD_ARF;
    231       flags |= VP8_EFLAG_NO_REF_GF;
    232       break;
    233     case kTemporalUpdateLastRefAll:
    234       flags |= VP8_EFLAG_NO_UPD_ARF;
    235       flags |= VP8_EFLAG_NO_UPD_GF;
    236       break;
    237   }
    238   return flags;
    239 }
    240 
    241 void DefaultTemporalLayers::PopulateCodecSpecific(
    242     bool base_layer_sync,
    243     CodecSpecificInfoVP8 *vp8_info,
    244     uint32_t timestamp) {
    245   assert(number_of_temporal_layers_ > 0);
    246   assert(0 < temporal_ids_length_);
    247 
    248   if (number_of_temporal_layers_ == 1) {
    249     vp8_info->temporalIdx = kNoTemporalIdx;
    250     vp8_info->layerSync = false;
    251     vp8_info->tl0PicIdx = kNoTl0PicIdx;
    252   } else {
    253     if (base_layer_sync) {
    254     vp8_info->temporalIdx = 0;
    255     vp8_info->layerSync = true;
    256     } else {
    257       vp8_info->temporalIdx = CurrentLayerId();
    258       TemporalReferences temporal_reference =
    259           temporal_pattern_[pattern_idx_ % temporal_pattern_length_];
    260 
    261       if (temporal_reference == kTemporalUpdateAltrefWithoutDependency ||
    262           temporal_reference == kTemporalUpdateGoldenWithoutDependency ||
    263           temporal_reference ==
    264               kTemporalUpdateGoldenWithoutDependencyRefAltRef ||
    265           temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef ||
    266           (temporal_reference == kTemporalUpdateNone &&
    267               number_of_temporal_layers_ == 4)) {
    268         vp8_info->layerSync = true;
    269       } else {
    270         vp8_info->layerSync = false;
    271       }
    272     }
    273     if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) {
    274       // Regardless of pattern the frame after a base layer sync will always
    275       // be a layer sync.
    276       vp8_info->layerSync = true;
    277     }
    278     if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) {
    279       timestamp_ = timestamp;
    280       tl0_pic_idx_++;
    281     }
    282     last_base_layer_sync_ = base_layer_sync;
    283     vp8_info->tl0PicIdx = tl0_pic_idx_;
    284   }
    285 }
    286 
    287 TemporalLayers* TemporalLayers::Factory::Create(
    288     int temporal_layers,
    289     uint8_t initial_tl0_pic_idx) const {
    290   return new DefaultTemporalLayers(temporal_layers, initial_tl0_pic_idx);
    291 }
    292 }  // namespace webrtc
    293