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