xref: /aosp_15_r20/external/webrtc/modules/video_coding/codecs/vp8/temporal_layers_checker.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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