• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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