• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "modules/video_coding/codecs/vp8/default_temporal_layers.h"
11 
12 #include <stdlib.h>
13 
14 #include <algorithm>
15 #include <array>
16 #include <memory>
17 #include <set>
18 #include <utility>
19 #include <vector>
20 
21 #include "modules/video_coding/include/video_codec_interface.h"
22 #include "rtc_base/arraysize.h"
23 #include "rtc_base/checks.h"
24 #include "rtc_base/logging.h"
25 #include "system_wrappers/include/field_trial.h"
26 
27 namespace webrtc {
28 DefaultTemporalLayers::PendingFrame::PendingFrame() = default;
PendingFrame(bool expired,uint8_t updated_buffers_mask,const DependencyInfo & dependency_info)29 DefaultTemporalLayers::PendingFrame::PendingFrame(
30     bool expired,
31     uint8_t updated_buffers_mask,
32     const DependencyInfo& dependency_info)
33     : expired(expired),
34       updated_buffer_mask(updated_buffers_mask),
35       dependency_info(dependency_info) {}
36 
37 namespace {
38 using BufferFlags = Vp8FrameConfig::BufferFlags;
39 using FreezeEntropy = Vp8FrameConfig::FreezeEntropy;
40 using Vp8BufferReference = Vp8FrameConfig::Vp8BufferReference;
41 
42 constexpr BufferFlags kNone = BufferFlags::kNone;
43 constexpr BufferFlags kReference = BufferFlags::kReference;
44 constexpr BufferFlags kUpdate = BufferFlags::kUpdate;
45 constexpr BufferFlags kReferenceAndUpdate = BufferFlags::kReferenceAndUpdate;
46 constexpr FreezeEntropy kFreezeEntropy = FreezeEntropy::kFreezeEntropy;
47 
48 static constexpr uint8_t kUninitializedPatternIndex =
49     std::numeric_limits<uint8_t>::max();
50 static constexpr std::array<Vp8BufferReference, 3> kAllBuffers = {
51     {Vp8BufferReference::kLast, Vp8BufferReference::kGolden,
52      Vp8BufferReference::kAltref}};
53 
GetTemporalIds(size_t num_layers)54 std::vector<unsigned int> GetTemporalIds(size_t num_layers) {
55   switch (num_layers) {
56     case 1:
57       // Temporal layer structure (single layer):
58       // 0 0 0 0 ...
59       return {0};
60     case 2:
61       // Temporal layer structure:
62       //   1   1 ...
63       // 0   0   ...
64       return {0, 1};
65     case 3:
66       // Temporal layer structure:
67       //   2   2   2   2 ...
68       //     1       1   ...
69       // 0       0       ...
70       return {0, 2, 1, 2};
71     case 4:
72       // Temporal layer structure:
73       //   3   3   3   3   3   3   3   3 ...
74       //     2       2       2       2   ...
75       //         1               1       ...
76       // 0               0               ...
77       return {0, 3, 2, 3, 1, 3, 2, 3};
78     default:
79       RTC_NOTREACHED();
80       break;
81   }
82   RTC_NOTREACHED();
83   return {0};
84 }
85 
GetUpdatedBuffers(const Vp8FrameConfig & config)86 uint8_t GetUpdatedBuffers(const Vp8FrameConfig& config) {
87   uint8_t flags = 0;
88   if (config.last_buffer_flags & BufferFlags::kUpdate) {
89     flags |= static_cast<uint8_t>(Vp8BufferReference::kLast);
90   }
91   if (config.golden_buffer_flags & BufferFlags::kUpdate) {
92     flags |= static_cast<uint8_t>(Vp8BufferReference::kGolden);
93   }
94   if (config.arf_buffer_flags & BufferFlags::kUpdate) {
95     flags |= static_cast<uint8_t>(Vp8BufferReference::kAltref);
96   }
97   return flags;
98 }
99 }  // namespace
100 
101 std::vector<DefaultTemporalLayers::DependencyInfo>
GetDependencyInfo(size_t num_layers)102 DefaultTemporalLayers::GetDependencyInfo(size_t num_layers) {
103   // For indexing in the patterns described below (which temporal layers they
104   // belong to), see the diagram above.
105   // Layer sync is done similarly for all patterns (except single stream) and
106   // happens every 8 frames:
107   // TL1 layer syncs by periodically by only referencing TL0 ('last'), but still
108   // updating 'golden', so it can be used as a reference by future TL1 frames.
109   // TL2 layer syncs just before TL1 by only depending on TL0 (and not depending
110   // on TL1's buffer before TL1 has layer synced).
111   // TODO(pbos): Consider cyclically updating 'arf' (and 'golden' for 1TL) for
112   // the base layer in 1-3TL instead of 'last' periodically on long intervals,
113   // so that if scene changes occur (user walks between rooms or rotates webcam)
114   // the 'arf' (or 'golden' respectively) is not stuck on a no-longer relevant
115   // keyframe.
116 
117   switch (num_layers) {
118     case 1:
119       // Always reference and update the same buffer.
120       return {{"S", {kReferenceAndUpdate, kNone, kNone}}};
121     case 2:
122       // All layers can reference but not update the 'alt' buffer, this means
123       // that the 'alt' buffer reference is effectively the last keyframe.
124       // TL0 also references and updates the 'last' buffer.
125       // TL1 also references 'last' and references and updates 'golden'.
126       if (!field_trial::IsDisabled("WebRTC-UseShortVP8TL2Pattern")) {
127         // Shortened 4-frame pattern:
128         //   1---1   1---1 ...
129         //  /   /   /   /
130         // 0---0---0---0 ...
131         return {{"SS", {kReferenceAndUpdate, kNone, kNone}},
132                 {"-S", {kReference, kUpdate, kNone}},
133                 {"SR", {kReferenceAndUpdate, kNone, kNone}},
134                 {"-D", {kReference, kReference, kNone, kFreezeEntropy}}};
135       } else {
136         // "Default" 8-frame pattern:
137         //   1---1---1---1   1---1---1---1 ...
138         //  /   /   /   /   /   /   /   /
139         // 0---0---0---0---0---0---0---0 ...
140         return {{"SS", {kReferenceAndUpdate, kNone, kNone}},
141                 {"-S", {kReference, kUpdate, kNone}},
142                 {"SR", {kReferenceAndUpdate, kNone, kNone}},
143                 {"-R", {kReference, kReferenceAndUpdate, kNone}},
144                 {"SR", {kReferenceAndUpdate, kNone, kNone}},
145                 {"-R", {kReference, kReferenceAndUpdate, kNone}},
146                 {"SR", {kReferenceAndUpdate, kNone, kNone}},
147                 {"-D", {kReference, kReference, kNone, kFreezeEntropy}}};
148       }
149     case 3:
150       if (field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) {
151         // This field trial is intended to check if it is worth using a shorter
152         // temporal pattern, trading some coding efficiency for less risk of
153         // dropped frames.
154         // The coding efficiency will decrease somewhat since the higher layer
155         // state is more volatile, but it will be offset slightly by updating
156         // the altref buffer with TL2 frames, instead of just referencing lower
157         // layers.
158         // If a frame is dropped in a higher layer, the jitter
159         // buffer on the receive side won't be able to decode any higher layer
160         // frame until the next sync frame. So we expect a noticeable decrease
161         // in frame drops on links with high packet loss.
162 
163         // TL0 references and updates the 'last' buffer.
164         // TL1  references 'last' and references and updates 'golden'.
165         // TL2 references both 'last' & 'golden' and references and updates
166         // 'arf'.
167         //     2-------2       2-------2       2
168         //    /     __/       /     __/       /
169         //   /   __1         /   __1         /
170         //  /___/           /___/           /
171         // 0---------------0---------------0-----
172         // 0   1   2   3   4   5   6   7   8   9 ...
173         return {{"SSS", {kReferenceAndUpdate, kNone, kNone}},
174                 {"--S", {kReference, kNone, kUpdate}},
175                 {"-DR", {kReference, kUpdate, kNone}},
176                 {"--D", {kReference, kReference, kReference, kFreezeEntropy}}};
177       } else {
178         // All layers can reference but not update the 'alt' buffer, this means
179         // that the 'alt' buffer reference is effectively the last keyframe.
180         // TL0 also references and updates the 'last' buffer.
181         // TL1 also references 'last' and references and updates 'golden'.
182         // TL2 references both 'last' and 'golden' but updates no buffer.
183         //     2     __2  _____2     __2       2
184         //    /     /____/    /     /         /
185         //   /     1---------/-----1         /
186         //  /_____/         /_____/         /
187         // 0---------------0---------------0-----
188         // 0   1   2   3   4   5   6   7   8   9 ...
189         return {{"SSS", {kReferenceAndUpdate, kNone, kNone}},
190                 {"--D", {kReference, kNone, kNone, kFreezeEntropy}},
191                 {"-SS", {kReference, kUpdate, kNone}},
192                 {"--D", {kReference, kReference, kNone, kFreezeEntropy}},
193                 {"SRR", {kReferenceAndUpdate, kNone, kNone}},
194                 {"--D", {kReference, kReference, kNone, kFreezeEntropy}},
195                 {"-DS", {kReference, kReferenceAndUpdate, kNone}},
196                 {"--D", {kReference, kReference, kNone, kFreezeEntropy}}};
197       }
198     case 4:
199       // TL0 references and updates only the 'last' buffer.
200       // TL1 references 'last' and updates and references 'golden'.
201       // TL2 references 'last' and 'golden', and references and updates 'arf'.
202       // TL3 references all buffers but update none of them.
203       // TODO(philipel): Set decode target information for this structure.
204       return {{"----", {kReferenceAndUpdate, kNone, kNone}},
205               {"----", {kReference, kNone, kNone, kFreezeEntropy}},
206               {"----", {kReference, kNone, kUpdate}},
207               {"----", {kReference, kNone, kReference, kFreezeEntropy}},
208               {"----", {kReference, kUpdate, kNone}},
209               {"----", {kReference, kReference, kReference, kFreezeEntropy}},
210               {"----", {kReference, kReference, kReferenceAndUpdate}},
211               {"----", {kReference, kReference, kReference, kFreezeEntropy}},
212               {"----", {kReferenceAndUpdate, kNone, kNone}},
213               {"----", {kReference, kReference, kReference, kFreezeEntropy}},
214               {"----", {kReference, kReference, kReferenceAndUpdate}},
215               {"----", {kReference, kReference, kReference, kFreezeEntropy}},
216               {"----", {kReference, kReferenceAndUpdate, kNone}},
217               {"----", {kReference, kReference, kReference, kFreezeEntropy}},
218               {"----", {kReference, kReference, kReferenceAndUpdate}},
219               {"----", {kReference, kReference, kReference, kFreezeEntropy}}};
220     default:
221       RTC_NOTREACHED();
222       break;
223   }
224   RTC_NOTREACHED();
225   return {{"", {kNone, kNone, kNone}}};
226 }
227 
DefaultTemporalLayers(int number_of_temporal_layers)228 DefaultTemporalLayers::DefaultTemporalLayers(int number_of_temporal_layers)
229     : num_layers_(std::max(1, number_of_temporal_layers)),
230       temporal_ids_(GetTemporalIds(num_layers_)),
231       temporal_pattern_(GetDependencyInfo(num_layers_)),
232       pattern_idx_(kUninitializedPatternIndex) {
233   RTC_CHECK_GE(kMaxTemporalStreams, number_of_temporal_layers);
234   RTC_CHECK_GE(number_of_temporal_layers, 0);
235   RTC_CHECK_LE(number_of_temporal_layers, 4);
236   // pattern_idx_ wraps around temporal_pattern_.size, this is incorrect if
237   // temporal_ids_ are ever longer. If this is no longer correct it needs to
238   // wrap at max(temporal_ids_.size(), temporal_pattern_.size()).
239   RTC_DCHECK_LE(temporal_ids_.size(), temporal_pattern_.size());
240 
241 #if RTC_DCHECK_IS_ON
242   checker_ = TemporalLayersChecker::CreateTemporalLayersChecker(
243       Vp8TemporalLayersType::kFixedPattern, number_of_temporal_layers);
244 #endif
245 
246   // Always need to start with a keyframe, so pre-populate all frame counters.
247   for (Vp8BufferReference buffer : kAllBuffers) {
248     frames_since_buffer_refresh_[buffer] = 0;
249   }
250 
251   kf_buffers_ = {kAllBuffers.begin(), kAllBuffers.end()};
252   for (const DependencyInfo& info : temporal_pattern_) {
253     uint8_t updated_buffers = GetUpdatedBuffers(info.frame_config);
254 
255     for (Vp8BufferReference buffer : kAllBuffers) {
256       if (static_cast<uint8_t>(buffer) & updated_buffers)
257         kf_buffers_.erase(buffer);
258     }
259   }
260 }
261 
262 DefaultTemporalLayers::~DefaultTemporalLayers() = default;
263 
SetQpLimits(size_t stream_index,int min_qp,int max_qp)264 void DefaultTemporalLayers::SetQpLimits(size_t stream_index,
265                                         int min_qp,
266                                         int max_qp) {
267   RTC_DCHECK_LT(stream_index, StreamCount());
268   // Ignore.
269 }
270 
StreamCount() const271 size_t DefaultTemporalLayers::StreamCount() const {
272   return 1;
273 }
274 
SupportsEncoderFrameDropping(size_t stream_index) const275 bool DefaultTemporalLayers::SupportsEncoderFrameDropping(
276     size_t stream_index) const {
277   RTC_DCHECK_LT(stream_index, StreamCount());
278   // This class allows the encoder drop frames as it sees fit.
279   return true;
280 }
281 
OnRatesUpdated(size_t stream_index,const std::vector<uint32_t> & bitrates_bps,int framerate_fps)282 void DefaultTemporalLayers::OnRatesUpdated(
283     size_t stream_index,
284     const std::vector<uint32_t>& bitrates_bps,
285     int framerate_fps) {
286   RTC_DCHECK_LT(stream_index, StreamCount());
287   RTC_DCHECK_GT(bitrates_bps.size(), 0);
288   RTC_DCHECK_LE(bitrates_bps.size(), num_layers_);
289   // |bitrates_bps| uses individual rate per layer, but Vp8EncoderConfig wants
290   // the accumulated rate, so sum them up.
291   new_bitrates_bps_ = bitrates_bps;
292   new_bitrates_bps_->resize(num_layers_);
293   for (size_t i = 1; i < num_layers_; ++i) {
294     (*new_bitrates_bps_)[i] += (*new_bitrates_bps_)[i - 1];
295   }
296 }
297 
UpdateConfiguration(size_t stream_index)298 Vp8EncoderConfig DefaultTemporalLayers::UpdateConfiguration(
299     size_t stream_index) {
300   RTC_DCHECK_LT(stream_index, StreamCount());
301 
302   Vp8EncoderConfig config;
303 
304   if (!new_bitrates_bps_) {
305     return config;
306   }
307 
308   config.temporal_layer_config.emplace();
309   Vp8EncoderConfig::TemporalLayerConfig& ts_config =
310       config.temporal_layer_config.value();
311 
312   for (size_t i = 0; i < num_layers_; ++i) {
313     ts_config.ts_target_bitrate[i] = (*new_bitrates_bps_)[i] / 1000;
314     // ..., 4, 2, 1
315     ts_config.ts_rate_decimator[i] = 1 << (num_layers_ - i - 1);
316   }
317 
318   ts_config.ts_number_layers = num_layers_;
319   ts_config.ts_periodicity = temporal_ids_.size();
320   std::copy(temporal_ids_.begin(), temporal_ids_.end(),
321             ts_config.ts_layer_id.begin());
322 
323   new_bitrates_bps_.reset();
324 
325   return config;
326 }
327 
IsSyncFrame(const Vp8FrameConfig & config) const328 bool DefaultTemporalLayers::IsSyncFrame(const Vp8FrameConfig& config) const {
329   // Since we always assign TL0 to 'last' in these patterns, we can infer layer
330   // sync by checking if temporal id > 0 and we only reference TL0 or buffers
331   // containing the last key-frame.
332   if (config.packetizer_temporal_idx == 0) {
333     // TL0 frames are per definition not sync frames.
334     return false;
335   }
336 
337   if ((config.last_buffer_flags & BufferFlags::kReference) == 0) {
338     // Sync frames must reference TL0.
339     return false;
340   }
341 
342   if ((config.golden_buffer_flags & BufferFlags::kReference) &&
343       kf_buffers_.find(Vp8BufferReference::kGolden) == kf_buffers_.end()) {
344     // Referencing a golden frame that contains a non-(base layer|key frame).
345     return false;
346   }
347   if ((config.arf_buffer_flags & BufferFlags::kReference) &&
348       kf_buffers_.find(Vp8BufferReference::kAltref) == kf_buffers_.end()) {
349     // Referencing an altref frame that contains a non-(base layer|key frame).
350     return false;
351   }
352 
353   return true;
354 }
355 
NextFrameConfig(size_t stream_index,uint32_t timestamp)356 Vp8FrameConfig DefaultTemporalLayers::NextFrameConfig(size_t stream_index,
357                                                       uint32_t timestamp) {
358   RTC_DCHECK_LT(stream_index, StreamCount());
359   RTC_DCHECK_GT(num_layers_, 0);
360   RTC_DCHECK_GT(temporal_pattern_.size(), 0);
361 
362   RTC_DCHECK_GT(kUninitializedPatternIndex, temporal_pattern_.size());
363   const bool first_frame = (pattern_idx_ == kUninitializedPatternIndex);
364 
365   pattern_idx_ = (pattern_idx_ + 1) % temporal_pattern_.size();
366   DependencyInfo dependency_info = temporal_pattern_[pattern_idx_];
367   Vp8FrameConfig& tl_config = dependency_info.frame_config;
368   tl_config.encoder_layer_id = tl_config.packetizer_temporal_idx =
369       temporal_ids_[pattern_idx_ % temporal_ids_.size()];
370 
371   if (pattern_idx_ == 0) {
372     // Start of new pattern iteration, set up clear state by invalidating any
373     // pending frames, so that we don't make an invalid reference to a buffer
374     // containing data from a previous iteration.
375     for (auto& it : pending_frames_) {
376       it.second.expired = true;
377     }
378   }
379 
380   if (first_frame) {
381     tl_config = Vp8FrameConfig::GetIntraFrameConfig();
382   } else {
383     // Last is always ok to reference as it contains the base layer. For other
384     // buffers though, we need to check if the buffer has actually been
385     // refreshed this cycle of the temporal pattern. If the encoder dropped
386     // a frame, it might not have.
387     ValidateReferences(&tl_config.golden_buffer_flags,
388                        Vp8BufferReference::kGolden);
389     ValidateReferences(&tl_config.arf_buffer_flags,
390                        Vp8BufferReference::kAltref);
391     // Update search order to let the encoder know which buffers contains the
392     // most recent data.
393     UpdateSearchOrder(&tl_config);
394     // Figure out if this a sync frame (non-base-layer frame with only
395     // base-layer references).
396     tl_config.layer_sync = IsSyncFrame(tl_config);
397 
398     // Increment frame age, this needs to be in sync with |pattern_idx_|,
399     // so must update it here. Resetting age to 0 must be done when encoding is
400     // complete though, and so in the case of pipelining encoder it might lag.
401     // To prevent this data spill over into the next iteration,
402     // the |pedning_frames_| map is reset in loops. If delay is constant,
403     // the relative age should still be OK for the search order.
404     for (Vp8BufferReference buffer : kAllBuffers) {
405       ++frames_since_buffer_refresh_[buffer];
406     }
407   }
408 
409   // Add frame to set of pending frames, awaiting completion.
410   pending_frames_[timestamp] =
411       PendingFrame{false, GetUpdatedBuffers(tl_config), dependency_info};
412 
413 #if RTC_DCHECK_IS_ON
414   // Checker does not yet support encoder frame dropping, so validate flags
415   // here before they can be dropped.
416   // TODO(sprang): Update checker to support dropping.
417   RTC_DCHECK(checker_->CheckTemporalConfig(first_frame, tl_config));
418 #endif
419 
420   return tl_config;
421 }
422 
ValidateReferences(BufferFlags * flags,Vp8BufferReference ref) const423 void DefaultTemporalLayers::ValidateReferences(BufferFlags* flags,
424                                                Vp8BufferReference ref) const {
425   // Check if the buffer specified by |ref| is actually referenced, and if so
426   // if it also a dynamically updating one (buffers always just containing
427   // keyframes are always safe to reference).
428   if ((*flags & BufferFlags::kReference) &&
429       kf_buffers_.find(ref) == kf_buffers_.end()) {
430     auto it = frames_since_buffer_refresh_.find(ref);
431     if (it == frames_since_buffer_refresh_.end() ||
432         it->second >= pattern_idx_) {
433       // No valid buffer state, or buffer contains frame that is older than the
434       // current pattern. This reference is not valid, so remove it.
435       *flags = static_cast<BufferFlags>(*flags & ~BufferFlags::kReference);
436     }
437   }
438 }
439 
UpdateSearchOrder(Vp8FrameConfig * config)440 void DefaultTemporalLayers::UpdateSearchOrder(Vp8FrameConfig* config) {
441   // Figure out which of the buffers we can reference, and order them so that
442   // the most recently refreshed is first. Otherwise prioritize last first,
443   // golden second, and altref third.
444   using BufferRefAge = std::pair<Vp8BufferReference, size_t>;
445   std::vector<BufferRefAge> eligible_buffers;
446   if (config->last_buffer_flags & BufferFlags::kReference) {
447     eligible_buffers.emplace_back(
448         Vp8BufferReference::kLast,
449         frames_since_buffer_refresh_[Vp8BufferReference::kLast]);
450   }
451   if (config->golden_buffer_flags & BufferFlags::kReference) {
452     eligible_buffers.emplace_back(
453         Vp8BufferReference::kGolden,
454         frames_since_buffer_refresh_[Vp8BufferReference::kGolden]);
455   }
456   if (config->arf_buffer_flags & BufferFlags::kReference) {
457     eligible_buffers.emplace_back(
458         Vp8BufferReference::kAltref,
459         frames_since_buffer_refresh_[Vp8BufferReference::kAltref]);
460   }
461 
462   std::sort(eligible_buffers.begin(), eligible_buffers.end(),
463             [](const BufferRefAge& lhs, const BufferRefAge& rhs) {
464               if (lhs.second != rhs.second) {
465                 // Lower count has highest precedence.
466                 return lhs.second < rhs.second;
467               }
468               return lhs.first < rhs.first;
469             });
470 
471   // Populate the search order fields where possible.
472   if (!eligible_buffers.empty()) {
473     config->first_reference = eligible_buffers.front().first;
474     if (eligible_buffers.size() > 1)
475       config->second_reference = eligible_buffers[1].first;
476   }
477 }
478 
OnEncodeDone(size_t stream_index,uint32_t rtp_timestamp,size_t size_bytes,bool is_keyframe,int qp,CodecSpecificInfo * info)479 void DefaultTemporalLayers::OnEncodeDone(size_t stream_index,
480                                          uint32_t rtp_timestamp,
481                                          size_t size_bytes,
482                                          bool is_keyframe,
483                                          int qp,
484                                          CodecSpecificInfo* info) {
485   RTC_DCHECK_LT(stream_index, StreamCount());
486   RTC_DCHECK_GT(num_layers_, 0);
487 
488   if (size_bytes == 0) {
489     RTC_LOG(LS_WARNING) << "Empty frame; treating as dropped.";
490     OnFrameDropped(stream_index, rtp_timestamp);
491     return;
492   }
493 
494   auto pending_frame = pending_frames_.find(rtp_timestamp);
495   RTC_DCHECK(pending_frame != pending_frames_.end());
496 
497   PendingFrame& frame = pending_frame->second;
498   const Vp8FrameConfig& frame_config = frame.dependency_info.frame_config;
499 #if RTC_DCHECK_IS_ON
500   if (is_keyframe) {
501     // Signal key-frame so checker resets state.
502     RTC_DCHECK(checker_->CheckTemporalConfig(true, frame_config));
503   }
504 #endif
505 
506   CodecSpecificInfoVP8& vp8_info = info->codecSpecific.VP8;
507   if (num_layers_ == 1) {
508     vp8_info.temporalIdx = kNoTemporalIdx;
509     vp8_info.layerSync = false;
510   } else {
511     if (is_keyframe) {
512       // Restart the temporal pattern on keyframes.
513       pattern_idx_ = 0;
514       vp8_info.temporalIdx = 0;
515       vp8_info.layerSync = true;  // Keyframes are always sync frames.
516 
517       for (Vp8BufferReference buffer : kAllBuffers) {
518         if (kf_buffers_.find(buffer) != kf_buffers_.end()) {
519           // Update frame count of all kf-only buffers, regardless of state of
520           // |pending_frames_|.
521           frames_since_buffer_refresh_[buffer] = 0;
522         } else {
523           // Key-frames update all buffers, this should be reflected when
524           // updating state in FrameEncoded().
525           frame.updated_buffer_mask |= static_cast<uint8_t>(buffer);
526         }
527       }
528     } else {
529       // Delta frame, update codec specifics with temporal id and sync flag.
530       vp8_info.temporalIdx = frame_config.packetizer_temporal_idx;
531       vp8_info.layerSync = frame_config.layer_sync;
532     }
533   }
534 
535   vp8_info.useExplicitDependencies = true;
536   RTC_DCHECK_EQ(vp8_info.referencedBuffersCount, 0u);
537   RTC_DCHECK_EQ(vp8_info.updatedBuffersCount, 0u);
538 
539   GenericFrameInfo& generic_frame_info = info->generic_frame_info.emplace();
540 
541   for (int i = 0; i < static_cast<int>(Vp8FrameConfig::Buffer::kCount); ++i) {
542     bool references = false;
543     bool updates = is_keyframe;
544 
545     if (!is_keyframe &&
546         frame_config.References(static_cast<Vp8FrameConfig::Buffer>(i))) {
547       RTC_DCHECK_LT(vp8_info.referencedBuffersCount,
548                     arraysize(CodecSpecificInfoVP8::referencedBuffers));
549       references = true;
550       vp8_info.referencedBuffers[vp8_info.referencedBuffersCount++] = i;
551     }
552 
553     if (is_keyframe ||
554         frame_config.Updates(static_cast<Vp8FrameConfig::Buffer>(i))) {
555       RTC_DCHECK_LT(vp8_info.updatedBuffersCount,
556                     arraysize(CodecSpecificInfoVP8::updatedBuffers));
557       updates = true;
558       vp8_info.updatedBuffers[vp8_info.updatedBuffersCount++] = i;
559     }
560 
561     if (references || updates)
562       generic_frame_info.encoder_buffers.emplace_back(i, references, updates);
563   }
564 
565   // The templates are always present on keyframes, and then refered to by
566   // subsequent frames.
567   if (is_keyframe) {
568     info->template_structure = GetTemplateStructure(num_layers_);
569     generic_frame_info.decode_target_indications =
570         temporal_pattern_.front().decode_target_indications;
571     generic_frame_info.temporal_id = 0;
572   } else {
573     generic_frame_info.decode_target_indications =
574         frame.dependency_info.decode_target_indications;
575     generic_frame_info.temporal_id = frame_config.packetizer_temporal_idx;
576   }
577 
578   if (!frame.expired) {
579     for (Vp8BufferReference buffer : kAllBuffers) {
580       if (frame.updated_buffer_mask & static_cast<uint8_t>(buffer)) {
581         frames_since_buffer_refresh_[buffer] = 0;
582       }
583     }
584   }
585 
586   pending_frames_.erase(pending_frame);
587 }
588 
OnFrameDropped(size_t stream_index,uint32_t rtp_timestamp)589 void DefaultTemporalLayers::OnFrameDropped(size_t stream_index,
590                                            uint32_t rtp_timestamp) {
591   auto pending_frame = pending_frames_.find(rtp_timestamp);
592   RTC_DCHECK(pending_frame != pending_frames_.end());
593   pending_frames_.erase(pending_frame);
594 }
595 
OnPacketLossRateUpdate(float packet_loss_rate)596 void DefaultTemporalLayers::OnPacketLossRateUpdate(float packet_loss_rate) {}
597 
OnRttUpdate(int64_t rtt_ms)598 void DefaultTemporalLayers::OnRttUpdate(int64_t rtt_ms) {}
599 
OnLossNotification(const VideoEncoder::LossNotification & loss_notification)600 void DefaultTemporalLayers::OnLossNotification(
601     const VideoEncoder::LossNotification& loss_notification) {}
602 
GetTemplateStructure(int num_layers) const603 FrameDependencyStructure DefaultTemporalLayers::GetTemplateStructure(
604     int num_layers) const {
605   RTC_CHECK_LT(num_layers, 5);
606   RTC_CHECK_GT(num_layers, 0);
607 
608   FrameDependencyStructure template_structure;
609   template_structure.num_decode_targets = num_layers;
610 
611   switch (num_layers) {
612     case 1: {
613       template_structure.templates.resize(2);
614       template_structure.templates[0].T(0).Dtis("S");
615       template_structure.templates[1].T(0).Dtis("S").FrameDiffs({1});
616       return template_structure;
617     }
618     case 2: {
619       template_structure.templates.resize(5);
620       template_structure.templates[0].T(0).Dtis("SS");
621       template_structure.templates[1].T(0).Dtis("SS").FrameDiffs({2});
622       template_structure.templates[2].T(0).Dtis("SR").FrameDiffs({2});
623       template_structure.templates[3].T(1).Dtis("-S").FrameDiffs({1});
624       template_structure.templates[4].T(1).Dtis("-D").FrameDiffs({2, 1});
625       return template_structure;
626     }
627     case 3: {
628       if (field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) {
629         template_structure.templates.resize(5);
630         template_structure.templates[0].T(0).Dtis("SSS");
631         template_structure.templates[1].T(0).Dtis("SSS").FrameDiffs({4});
632         template_structure.templates[2].T(1).Dtis("-DR").FrameDiffs({2});
633         template_structure.templates[3].T(2).Dtis("--S").FrameDiffs({1});
634         template_structure.templates[4].T(2).Dtis("--D").FrameDiffs({2, 1});
635       } else {
636         template_structure.templates.resize(7);
637         template_structure.templates[0].T(0).Dtis("SSS");
638         template_structure.templates[1].T(0).Dtis("SSS").FrameDiffs({4});
639         template_structure.templates[2].T(0).Dtis("SRR").FrameDiffs({4});
640         template_structure.templates[3].T(1).Dtis("-SS").FrameDiffs({2});
641         template_structure.templates[4].T(1).Dtis("-DS").FrameDiffs({4, 2});
642         template_structure.templates[5].T(2).Dtis("--D").FrameDiffs({1});
643         template_structure.templates[6].T(2).Dtis("--D").FrameDiffs({3, 1});
644       }
645       return template_structure;
646     }
647     case 4: {
648       template_structure.templates.resize(8);
649       template_structure.templates[0].T(0).Dtis("SSSS");
650       template_structure.templates[1].T(0).Dtis("SSSS").FrameDiffs({8});
651       template_structure.templates[2].T(1).Dtis("-SRR").FrameDiffs({4});
652       template_structure.templates[3].T(1).Dtis("-SRR").FrameDiffs({4, 8});
653       template_structure.templates[4].T(2).Dtis("--SR").FrameDiffs({2});
654       template_structure.templates[5].T(2).Dtis("--SR").FrameDiffs({2, 4});
655       template_structure.templates[6].T(3).Dtis("---D").FrameDiffs({1});
656       template_structure.templates[7].T(3).Dtis("---D").FrameDiffs({1, 3});
657       return template_structure;
658     }
659     default:
660       RTC_NOTREACHED();
661       // To make the compiler happy!
662       return template_structure;
663   }
664 }
665 
666 // Returns list of temporal dependencies for each frame in the temporal pattern.
667 // Values are lists of indecies in the pattern.
GetTemporalDependencies(int num_temporal_layers)668 std::vector<std::set<uint8_t>> GetTemporalDependencies(
669     int num_temporal_layers) {
670   switch (num_temporal_layers) {
671     case 1:
672       return {{0}};
673     case 2:
674       if (!field_trial::IsDisabled("WebRTC-UseShortVP8TL2Pattern")) {
675         return {{2}, {0}, {0}, {1, 2}};
676       } else {
677         return {{6}, {0}, {0}, {1, 2}, {2}, {3, 4}, {4}, {5, 6}};
678       }
679     case 3:
680       if (field_trial::IsEnabled("WebRTC-UseShortVP8TL3Pattern")) {
681         return {{0}, {0}, {0}, {0, 1, 2}};
682       } else {
683         return {{4}, {0}, {0}, {0, 2}, {0}, {2, 4}, {2, 4}, {4, 6}};
684       }
685     case 4:
686       return {{8},    {0},         {0},         {0, 2},
687               {0},    {0, 2, 4},   {0, 2, 4},   {0, 4, 6},
688               {0},    {4, 6, 8},   {4, 6, 8},   {4, 8, 10},
689               {4, 8}, {8, 10, 12}, {8, 10, 12}, {8, 12, 14}};
690     default:
691       RTC_NOTREACHED();
692       return {};
693   }
694 }
695 
DefaultTemporalLayersChecker(int num_temporal_layers)696 DefaultTemporalLayersChecker::DefaultTemporalLayersChecker(
697     int num_temporal_layers)
698     : TemporalLayersChecker(num_temporal_layers),
699       num_layers_(std::max(1, num_temporal_layers)),
700       temporal_ids_(GetTemporalIds(num_layers_)),
701       temporal_dependencies_(GetTemporalDependencies(num_layers_)),
702       pattern_idx_(255) {
703   int i = 0;
704   while (temporal_ids_.size() < temporal_dependencies_.size()) {
705     temporal_ids_.push_back(temporal_ids_[i++]);
706   }
707 }
708 
709 DefaultTemporalLayersChecker::~DefaultTemporalLayersChecker() = default;
710 
CheckTemporalConfig(bool frame_is_keyframe,const Vp8FrameConfig & frame_config)711 bool DefaultTemporalLayersChecker::CheckTemporalConfig(
712     bool frame_is_keyframe,
713     const Vp8FrameConfig& frame_config) {
714   if (!TemporalLayersChecker::CheckTemporalConfig(frame_is_keyframe,
715                                                   frame_config)) {
716     return false;
717   }
718   if (frame_config.drop_frame) {
719     return true;
720   }
721 
722   if (frame_is_keyframe) {
723     pattern_idx_ = 0;
724     last_ = BufferState();
725     golden_ = BufferState();
726     arf_ = BufferState();
727     return true;
728   }
729 
730   ++pattern_idx_;
731   if (pattern_idx_ == temporal_ids_.size()) {
732     // All non key-frame buffers should be updated each pattern cycle.
733     if (!last_.is_keyframe && !last_.is_updated_this_cycle) {
734       RTC_LOG(LS_ERROR) << "Last buffer was not updated during pattern cycle.";
735       return false;
736     }
737     if (!arf_.is_keyframe && !arf_.is_updated_this_cycle) {
738       RTC_LOG(LS_ERROR) << "Arf buffer was not updated during pattern cycle.";
739       return false;
740     }
741     if (!golden_.is_keyframe && !golden_.is_updated_this_cycle) {
742       RTC_LOG(LS_ERROR)
743           << "Golden buffer was not updated during pattern cycle.";
744       return false;
745     }
746     last_.is_updated_this_cycle = false;
747     arf_.is_updated_this_cycle = false;
748     golden_.is_updated_this_cycle = false;
749     pattern_idx_ = 0;
750   }
751   uint8_t expected_tl_idx = temporal_ids_[pattern_idx_];
752   if (frame_config.packetizer_temporal_idx != expected_tl_idx) {
753     RTC_LOG(LS_ERROR) << "Frame has an incorrect temporal index. Expected: "
754                       << static_cast<int>(expected_tl_idx) << " Actual: "
755                       << static_cast<int>(frame_config.packetizer_temporal_idx);
756     return false;
757   }
758 
759   bool need_sync = temporal_ids_[pattern_idx_] > 0 &&
760                    temporal_ids_[pattern_idx_] != kNoTemporalIdx;
761   std::vector<int> dependencies;
762 
763   if (frame_config.last_buffer_flags & BufferFlags::kReference) {
764     uint8_t referenced_layer = temporal_ids_[last_.pattern_idx];
765     if (referenced_layer > 0) {
766       need_sync = false;
767     }
768     if (!last_.is_keyframe) {
769       dependencies.push_back(last_.pattern_idx);
770     }
771   } else if (frame_config.first_reference == Vp8BufferReference::kLast ||
772              frame_config.second_reference == Vp8BufferReference::kLast) {
773     RTC_LOG(LS_ERROR)
774         << "Last buffer not referenced, but present in search order.";
775     return false;
776   }
777 
778   if (frame_config.arf_buffer_flags & BufferFlags::kReference) {
779     uint8_t referenced_layer = temporal_ids_[arf_.pattern_idx];
780     if (referenced_layer > 0) {
781       need_sync = false;
782     }
783     if (!arf_.is_keyframe) {
784       dependencies.push_back(arf_.pattern_idx);
785     }
786   } else if (frame_config.first_reference == Vp8BufferReference::kAltref ||
787              frame_config.second_reference == Vp8BufferReference::kAltref) {
788     RTC_LOG(LS_ERROR)
789         << "Altret buffer not referenced, but present in search order.";
790     return false;
791   }
792 
793   if (frame_config.golden_buffer_flags & BufferFlags::kReference) {
794     uint8_t referenced_layer = temporal_ids_[golden_.pattern_idx];
795     if (referenced_layer > 0) {
796       need_sync = false;
797     }
798     if (!golden_.is_keyframe) {
799       dependencies.push_back(golden_.pattern_idx);
800     }
801   } else if (frame_config.first_reference == Vp8BufferReference::kGolden ||
802              frame_config.second_reference == Vp8BufferReference::kGolden) {
803     RTC_LOG(LS_ERROR)
804         << "Golden buffer not referenced, but present in search order.";
805     return false;
806   }
807 
808   if (need_sync != frame_config.layer_sync) {
809     RTC_LOG(LS_ERROR) << "Sync bit is set incorrectly on a frame. Expected: "
810                       << need_sync << " Actual: " << frame_config.layer_sync;
811     return false;
812   }
813 
814   if (!frame_is_keyframe) {
815     size_t i;
816     for (i = 0; i < dependencies.size(); ++i) {
817       if (temporal_dependencies_[pattern_idx_].find(dependencies[i]) ==
818           temporal_dependencies_[pattern_idx_].end()) {
819         RTC_LOG(LS_ERROR)
820             << "Illegal temporal dependency out of defined pattern "
821                "from position "
822             << static_cast<int>(pattern_idx_) << " to position "
823             << static_cast<int>(dependencies[i]);
824         return false;
825       }
826     }
827   }
828 
829   if (frame_config.last_buffer_flags & BufferFlags::kUpdate) {
830     last_.is_updated_this_cycle = true;
831     last_.pattern_idx = pattern_idx_;
832     last_.is_keyframe = false;
833   }
834   if (frame_config.arf_buffer_flags & BufferFlags::kUpdate) {
835     arf_.is_updated_this_cycle = true;
836     arf_.pattern_idx = pattern_idx_;
837     arf_.is_keyframe = false;
838   }
839   if (frame_config.golden_buffer_flags & BufferFlags::kUpdate) {
840     golden_.is_updated_this_cycle = true;
841     golden_.pattern_idx = pattern_idx_;
842     golden_.is_keyframe = false;
843   }
844   return true;
845 }
846 
847 }  // namespace webrtc
848