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/modules/video_coding/include/video_codec_interface.h" 16 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h" 17 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" 18 19 // This file implements logic to adapt the number of temporal layers based on 20 // input frame rate in order to avoid having the base layer being relaying at 21 // a below acceptable framerate. 22 namespace webrtc { 23 namespace { 24 enum { 25 kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 26 VP8_EFLAG_NO_REF_GF | 27 VP8_EFLAG_NO_REF_ARF, 28 29 kTemporalUpdateGolden = 30 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, 31 32 kTemporalUpdateGoldenWithoutDependency = 33 kTemporalUpdateGolden | VP8_EFLAG_NO_REF_GF, 34 35 kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, 36 37 kTemporalUpdateAltrefWithoutDependency = 38 kTemporalUpdateAltref | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF, 39 40 kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 41 VP8_EFLAG_NO_UPD_LAST | 42 VP8_EFLAG_NO_UPD_ENTROPY, 43 44 kTemporalUpdateNoneNoRefAltref = kTemporalUpdateNone | VP8_EFLAG_NO_REF_ARF, 45 46 kTemporalUpdateNoneNoRefGoldenRefAltRef = 47 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | 48 VP8_EFLAG_NO_UPD_LAST | 49 VP8_EFLAG_NO_UPD_ENTROPY, 50 51 kTemporalUpdateGoldenWithoutDependencyRefAltRef = 52 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, 53 54 kTemporalUpdateLastRefAltRef = 55 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, 56 57 kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, 58 59 kTemporalUpdateLastAndGoldenRefAltRef = 60 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, 61 62 kTemporalUpdateLastRefAll = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF, 63 }; 64 65 int CalculateNumberOfTemporalLayers(int current_temporal_layers, 66 int input_fps) { 67 if (input_fps >= 24) { 68 return 3; 69 } 70 if (input_fps >= 20 && current_temporal_layers >= 3) { 71 // Keep doing 3 temporal layers until we go below 20fps. 72 return 3; 73 } 74 if (input_fps >= 10) { 75 return 2; 76 } 77 if (input_fps > 8 && current_temporal_layers >= 2) { 78 // keep doing 2 temporal layers until we go below 8fps 79 return 2; 80 } 81 return 1; 82 } 83 84 class RealTimeTemporalLayers : public TemporalLayers { 85 public: 86 RealTimeTemporalLayers(int max_num_temporal_layers, 87 uint8_t initial_tl0_pic_idx) 88 : temporal_layers_(1), 89 max_temporal_layers_(max_num_temporal_layers), 90 tl0_pic_idx_(initial_tl0_pic_idx), 91 frame_counter_(static_cast<unsigned int>(-1)), 92 timestamp_(0), 93 last_base_layer_sync_(0), 94 layer_ids_length_(0), 95 layer_ids_(NULL), 96 encode_flags_length_(0), 97 encode_flags_(NULL) { 98 assert(max_temporal_layers_ >= 1); 99 assert(max_temporal_layers_ <= 3); 100 } 101 102 virtual ~RealTimeTemporalLayers() {} 103 104 virtual bool ConfigureBitrates(int bitrate_kbit, 105 int max_bitrate_kbit, 106 int framerate, 107 vpx_codec_enc_cfg_t* cfg) { 108 temporal_layers_ = 109 CalculateNumberOfTemporalLayers(temporal_layers_, framerate); 110 temporal_layers_ = std::min(temporal_layers_, max_temporal_layers_); 111 assert(temporal_layers_ >= 1 && temporal_layers_ <= 3); 112 113 cfg->ts_number_layers = temporal_layers_; 114 for (int tl = 0; tl < temporal_layers_; ++tl) { 115 cfg->ts_target_bitrate[tl] = 116 bitrate_kbit * kVp8LayerRateAlloction[temporal_layers_ - 1][tl]; 117 } 118 119 switch (temporal_layers_) { 120 case 1: { 121 static const unsigned int layer_ids[] = {0u}; 122 layer_ids_ = layer_ids; 123 layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids); 124 125 static const int encode_flags[] = {kTemporalUpdateLastRefAll}; 126 encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids); 127 encode_flags_ = encode_flags; 128 129 cfg->ts_rate_decimator[0] = 1; 130 cfg->ts_periodicity = layer_ids_length_; 131 } break; 132 133 case 2: { 134 static const unsigned int layer_ids[] = {0u, 1u}; 135 layer_ids_ = layer_ids; 136 layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids); 137 138 static const int encode_flags[] = { 139 kTemporalUpdateLastAndGoldenRefAltRef, 140 kTemporalUpdateGoldenWithoutDependencyRefAltRef, 141 kTemporalUpdateLastRefAltRef, 142 kTemporalUpdateGoldenRefAltRef, 143 kTemporalUpdateLastRefAltRef, 144 kTemporalUpdateGoldenRefAltRef, 145 kTemporalUpdateLastRefAltRef, 146 kTemporalUpdateNone}; 147 encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids); 148 encode_flags_ = encode_flags; 149 150 cfg->ts_rate_decimator[0] = 2; 151 cfg->ts_rate_decimator[1] = 1; 152 cfg->ts_periodicity = layer_ids_length_; 153 } break; 154 155 case 3: { 156 static const unsigned int layer_ids[] = {0u, 2u, 1u, 2u}; 157 layer_ids_ = layer_ids; 158 layer_ids_length_ = sizeof(layer_ids) / sizeof(*layer_ids); 159 160 static const int encode_flags[] = { 161 kTemporalUpdateLastAndGoldenRefAltRef, 162 kTemporalUpdateNoneNoRefGoldenRefAltRef, 163 kTemporalUpdateGoldenWithoutDependencyRefAltRef, 164 kTemporalUpdateNone, 165 kTemporalUpdateLastRefAltRef, 166 kTemporalUpdateNone, 167 kTemporalUpdateGoldenRefAltRef, 168 kTemporalUpdateNone}; 169 encode_flags_length_ = sizeof(encode_flags) / sizeof(*layer_ids); 170 encode_flags_ = encode_flags; 171 172 cfg->ts_rate_decimator[0] = 4; 173 cfg->ts_rate_decimator[1] = 2; 174 cfg->ts_rate_decimator[2] = 1; 175 cfg->ts_periodicity = layer_ids_length_; 176 } break; 177 178 default: 179 assert(false); 180 return false; 181 } 182 memcpy(cfg->ts_layer_id, layer_ids_, 183 sizeof(unsigned int) * layer_ids_length_); 184 return true; 185 } 186 187 virtual int EncodeFlags(uint32_t timestamp) { 188 frame_counter_++; 189 return CurrentEncodeFlags(); 190 } 191 192 int CurrentEncodeFlags() const { 193 assert(encode_flags_length_ > 0 && encode_flags_ != NULL); 194 int index = frame_counter_ % encode_flags_length_; 195 assert(index >= 0 && index < encode_flags_length_); 196 return encode_flags_[index]; 197 } 198 199 virtual int CurrentLayerId() const { 200 assert(layer_ids_length_ > 0 && layer_ids_ != NULL); 201 int index = frame_counter_ % layer_ids_length_; 202 assert(index >= 0 && index < layer_ids_length_); 203 return layer_ids_[index]; 204 } 205 206 virtual void PopulateCodecSpecific(bool base_layer_sync, 207 CodecSpecificInfoVP8* vp8_info, 208 uint32_t timestamp) { 209 assert(temporal_layers_ > 0); 210 211 if (temporal_layers_ == 1) { 212 vp8_info->temporalIdx = kNoTemporalIdx; 213 vp8_info->layerSync = false; 214 vp8_info->tl0PicIdx = kNoTl0PicIdx; 215 } else { 216 if (base_layer_sync) { 217 vp8_info->temporalIdx = 0; 218 vp8_info->layerSync = true; 219 } else { 220 vp8_info->temporalIdx = CurrentLayerId(); 221 int temporal_reference = CurrentEncodeFlags(); 222 223 if (temporal_reference == kTemporalUpdateAltrefWithoutDependency || 224 temporal_reference == kTemporalUpdateGoldenWithoutDependency || 225 temporal_reference == 226 kTemporalUpdateGoldenWithoutDependencyRefAltRef || 227 temporal_reference == kTemporalUpdateNoneNoRefGoldenRefAltRef || 228 (temporal_reference == kTemporalUpdateNone && 229 temporal_layers_ == 4)) { 230 vp8_info->layerSync = true; 231 } else { 232 vp8_info->layerSync = false; 233 } 234 } 235 if (last_base_layer_sync_ && vp8_info->temporalIdx != 0) { 236 // Regardless of pattern the frame after a base layer sync will always 237 // be a layer sync. 238 vp8_info->layerSync = true; 239 } 240 if (vp8_info->temporalIdx == 0 && timestamp != timestamp_) { 241 timestamp_ = timestamp; 242 tl0_pic_idx_++; 243 } 244 last_base_layer_sync_ = base_layer_sync; 245 vp8_info->tl0PicIdx = tl0_pic_idx_; 246 } 247 } 248 249 void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override {} 250 251 bool UpdateConfiguration(vpx_codec_enc_cfg_t* cfg) override { return false; } 252 253 private: 254 int temporal_layers_; 255 int max_temporal_layers_; 256 257 int tl0_pic_idx_; 258 unsigned int frame_counter_; 259 uint32_t timestamp_; 260 bool last_base_layer_sync_; 261 262 // Pattern of temporal layer ids. 263 int layer_ids_length_; 264 const unsigned int* layer_ids_; 265 266 // Pattern of encode flags. 267 int encode_flags_length_; 268 const int* encode_flags_; 269 }; 270 } // namespace 271 272 TemporalLayers* RealTimeTemporalLayersFactory::Create( 273 int max_temporal_layers, 274 uint8_t initial_tl0_pic_idx) const { 275 return new RealTimeTemporalLayers(max_temporal_layers, initial_tl0_pic_idx); 276 } 277 } // namespace webrtc 278