1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/video_coding/codecs/vp8/include/temporal_layers_checker.h"
12
13 #include <memory>
14
15 #include "modules/video_coding/codecs/interface/common_constants.h"
16 #include "modules/video_coding/codecs/vp8/default_temporal_layers.h"
17 #include "rtc_base/logging.h"
18
19 namespace webrtc {
20
21 std::unique_ptr<TemporalLayersChecker>
CreateTemporalLayersChecker(Vp8TemporalLayersType type,int num_temporal_layers)22 TemporalLayersChecker::CreateTemporalLayersChecker(Vp8TemporalLayersType type,
23 int num_temporal_layers) {
24 switch (type) {
25 case Vp8TemporalLayersType::kFixedPattern:
26 return std::make_unique<DefaultTemporalLayersChecker>(
27 num_temporal_layers);
28 case Vp8TemporalLayersType::kBitrateDynamic:
29 // Conference mode temporal layering for screen content in base stream.
30 return std::make_unique<TemporalLayersChecker>(num_temporal_layers);
31 }
32 }
33
TemporalLayersChecker(int num_temporal_layers)34 TemporalLayersChecker::TemporalLayersChecker(int num_temporal_layers)
35 : num_temporal_layers_(num_temporal_layers),
36 sequence_number_(0),
37 last_sync_sequence_number_(0),
38 last_tl0_sequence_number_(0) {}
39
CheckAndUpdateBufferState(BufferState * state,bool * need_sync,bool frame_is_keyframe,uint8_t temporal_layer,Vp8FrameConfig::BufferFlags flags,uint32_t sequence_number,uint32_t * lowest_sequence_referenced)40 bool TemporalLayersChecker::CheckAndUpdateBufferState(
41 BufferState* state,
42 bool* need_sync,
43 bool frame_is_keyframe,
44 uint8_t temporal_layer,
45 Vp8FrameConfig::BufferFlags flags,
46 uint32_t sequence_number,
47 uint32_t* lowest_sequence_referenced) {
48 if (flags & Vp8FrameConfig::BufferFlags::kReference) {
49 if (state->temporal_layer > 0 && !state->is_keyframe) {
50 *need_sync = false;
51 }
52 if (!state->is_keyframe && !frame_is_keyframe &&
53 state->sequence_number < *lowest_sequence_referenced) {
54 *lowest_sequence_referenced = state->sequence_number;
55 }
56 if (!frame_is_keyframe && !state->is_keyframe &&
57 state->temporal_layer > temporal_layer) {
58 RTC_LOG(LS_ERROR) << "Frame is referencing higher temporal layer.";
59 return false;
60 }
61 }
62 if ((flags & Vp8FrameConfig::BufferFlags::kUpdate)) {
63 state->temporal_layer = temporal_layer;
64 state->sequence_number = sequence_number;
65 state->is_keyframe = frame_is_keyframe;
66 }
67 if (frame_is_keyframe)
68 state->is_keyframe = true;
69 return true;
70 }
71
CheckTemporalConfig(bool frame_is_keyframe,const Vp8FrameConfig & frame_config)72 bool TemporalLayersChecker::CheckTemporalConfig(
73 bool frame_is_keyframe,
74 const Vp8FrameConfig& frame_config) {
75 if (frame_config.drop_frame ||
76 frame_config.packetizer_temporal_idx == kNoTemporalIdx) {
77 return true;
78 }
79 ++sequence_number_;
80 if (frame_config.packetizer_temporal_idx >= num_temporal_layers_ ||
81 (frame_config.packetizer_temporal_idx == kNoTemporalIdx &&
82 num_temporal_layers_ > 1)) {
83 RTC_LOG(LS_ERROR) << "Incorrect temporal layer set for frame: "
84 << frame_config.packetizer_temporal_idx
85 << " num_temporal_layers: " << num_temporal_layers_;
86 return false;
87 }
88
89 uint32_t lowest_sequence_referenced = sequence_number_;
90 bool need_sync = frame_config.packetizer_temporal_idx > 0 &&
91 frame_config.packetizer_temporal_idx != kNoTemporalIdx;
92
93 if (!CheckAndUpdateBufferState(
94 &last_, &need_sync, frame_is_keyframe,
95 frame_config.packetizer_temporal_idx, frame_config.last_buffer_flags,
96 sequence_number_, &lowest_sequence_referenced)) {
97 RTC_LOG(LS_ERROR) << "Error in the Last buffer";
98 return false;
99 }
100 if (!CheckAndUpdateBufferState(&golden_, &need_sync, frame_is_keyframe,
101 frame_config.packetizer_temporal_idx,
102 frame_config.golden_buffer_flags,
103 sequence_number_,
104 &lowest_sequence_referenced)) {
105 RTC_LOG(LS_ERROR) << "Error in the Golden buffer";
106 return false;
107 }
108 if (!CheckAndUpdateBufferState(
109 &arf_, &need_sync, frame_is_keyframe,
110 frame_config.packetizer_temporal_idx, frame_config.arf_buffer_flags,
111 sequence_number_, &lowest_sequence_referenced)) {
112 RTC_LOG(LS_ERROR) << "Error in the Arf buffer";
113 return false;
114 }
115
116 if (lowest_sequence_referenced < last_sync_sequence_number_ &&
117 !frame_is_keyframe) {
118 RTC_LOG(LS_ERROR) << "Reference past the last sync frame. Referenced "
119 << lowest_sequence_referenced << ", but sync was at "
120 << last_sync_sequence_number_;
121 return false;
122 }
123
124 if (frame_config.packetizer_temporal_idx == 0) {
125 last_tl0_sequence_number_ = sequence_number_;
126 }
127
128 if (frame_is_keyframe) {
129 last_sync_sequence_number_ = sequence_number_;
130 }
131
132 if (need_sync) {
133 last_sync_sequence_number_ = last_tl0_sequence_number_;
134 }
135
136 // Ignore sync flag on key-frames as it really doesn't matter.
137 if (need_sync != frame_config.layer_sync && !frame_is_keyframe) {
138 RTC_LOG(LS_ERROR) << "Sync bit is set incorrectly on a frame. Expected: "
139 << need_sync << " Actual: " << frame_config.layer_sync;
140 return false;
141 }
142 return true;
143 }
144
145 } // namespace webrtc
146