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