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 RTC_CHECK_NOTREACHED();
33 }
34
TemporalLayersChecker(int num_temporal_layers)35 TemporalLayersChecker::TemporalLayersChecker(int num_temporal_layers)
36 : num_temporal_layers_(num_temporal_layers),
37 sequence_number_(0),
38 last_sync_sequence_number_(0),
39 last_tl0_sequence_number_(0) {}
40
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)41 bool TemporalLayersChecker::CheckAndUpdateBufferState(
42 BufferState* state,
43 bool* need_sync,
44 bool frame_is_keyframe,
45 uint8_t temporal_layer,
46 Vp8FrameConfig::BufferFlags flags,
47 uint32_t sequence_number,
48 uint32_t* lowest_sequence_referenced) {
49 if (flags & Vp8FrameConfig::BufferFlags::kReference) {
50 if (state->temporal_layer > 0 && !state->is_keyframe) {
51 *need_sync = false;
52 }
53 if (!state->is_keyframe && !frame_is_keyframe &&
54 state->sequence_number < *lowest_sequence_referenced) {
55 *lowest_sequence_referenced = state->sequence_number;
56 }
57 if (!frame_is_keyframe && !state->is_keyframe &&
58 state->temporal_layer > temporal_layer) {
59 RTC_LOG(LS_ERROR) << "Frame is referencing higher temporal layer.";
60 return false;
61 }
62 }
63 if ((flags & Vp8FrameConfig::BufferFlags::kUpdate)) {
64 state->temporal_layer = temporal_layer;
65 state->sequence_number = sequence_number;
66 state->is_keyframe = frame_is_keyframe;
67 }
68 if (frame_is_keyframe)
69 state->is_keyframe = true;
70 return true;
71 }
72
CheckTemporalConfig(bool frame_is_keyframe,const Vp8FrameConfig & frame_config)73 bool TemporalLayersChecker::CheckTemporalConfig(
74 bool frame_is_keyframe,
75 const Vp8FrameConfig& frame_config) {
76 if (frame_config.drop_frame ||
77 frame_config.packetizer_temporal_idx == kNoTemporalIdx) {
78 return true;
79 }
80 ++sequence_number_;
81 if (frame_config.packetizer_temporal_idx >= num_temporal_layers_ ||
82 (frame_config.packetizer_temporal_idx == kNoTemporalIdx &&
83 num_temporal_layers_ > 1)) {
84 RTC_LOG(LS_ERROR) << "Incorrect temporal layer set for frame: "
85 << frame_config.packetizer_temporal_idx
86 << " num_temporal_layers: " << num_temporal_layers_;
87 return false;
88 }
89
90 uint32_t lowest_sequence_referenced = sequence_number_;
91 bool need_sync = frame_config.packetizer_temporal_idx > 0 &&
92 frame_config.packetizer_temporal_idx != kNoTemporalIdx;
93
94 if (!CheckAndUpdateBufferState(
95 &last_, &need_sync, frame_is_keyframe,
96 frame_config.packetizer_temporal_idx, frame_config.last_buffer_flags,
97 sequence_number_, &lowest_sequence_referenced)) {
98 RTC_LOG(LS_ERROR) << "Error in the Last buffer";
99 return false;
100 }
101 if (!CheckAndUpdateBufferState(&golden_, &need_sync, frame_is_keyframe,
102 frame_config.packetizer_temporal_idx,
103 frame_config.golden_buffer_flags,
104 sequence_number_,
105 &lowest_sequence_referenced)) {
106 RTC_LOG(LS_ERROR) << "Error in the Golden buffer";
107 return false;
108 }
109 if (!CheckAndUpdateBufferState(
110 &arf_, &need_sync, frame_is_keyframe,
111 frame_config.packetizer_temporal_idx, frame_config.arf_buffer_flags,
112 sequence_number_, &lowest_sequence_referenced)) {
113 RTC_LOG(LS_ERROR) << "Error in the Arf buffer";
114 return false;
115 }
116
117 if (lowest_sequence_referenced < last_sync_sequence_number_ &&
118 !frame_is_keyframe) {
119 RTC_LOG(LS_ERROR) << "Reference past the last sync frame. Referenced "
120 << lowest_sequence_referenced << ", but sync was at "
121 << last_sync_sequence_number_;
122 return false;
123 }
124
125 if (frame_config.packetizer_temporal_idx == 0) {
126 last_tl0_sequence_number_ = sequence_number_;
127 }
128
129 if (frame_is_keyframe) {
130 last_sync_sequence_number_ = sequence_number_;
131 }
132
133 if (need_sync) {
134 last_sync_sequence_number_ = last_tl0_sequence_number_;
135 }
136
137 // Ignore sync flag on key-frames as it really doesn't matter.
138 if (need_sync != frame_config.layer_sync && !frame_is_keyframe) {
139 RTC_LOG(LS_ERROR) << "Sync bit is set incorrectly on a frame. Expected: "
140 << need_sync << " Actual: " << frame_config.layer_sync;
141 return false;
142 }
143 return true;
144 }
145
146 } // namespace webrtc
147