xref: /aosp_15_r20/external/webrtc/api/video/frame_buffer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "api/video/frame_buffer.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
16*d9f75844SAndroid Build Coastguard Worker #include "absl/container/inlined_vector.h"
17*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/sequence_number_util.h"
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
21*d9f75844SAndroid Build Coastguard Worker namespace {
ValidReferences(const EncodedFrame & frame)22*d9f75844SAndroid Build Coastguard Worker bool ValidReferences(const EncodedFrame& frame) {
23*d9f75844SAndroid Build Coastguard Worker   // All references must point backwards, and duplicates are not allowed.
24*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i < frame.num_references; ++i) {
25*d9f75844SAndroid Build Coastguard Worker     if (frame.references[i] >= frame.Id())
26*d9f75844SAndroid Build Coastguard Worker       return false;
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker     for (size_t j = i + 1; j < frame.num_references; ++j) {
29*d9f75844SAndroid Build Coastguard Worker       if (frame.references[i] == frame.references[j])
30*d9f75844SAndroid Build Coastguard Worker         return false;
31*d9f75844SAndroid Build Coastguard Worker     }
32*d9f75844SAndroid Build Coastguard Worker   }
33*d9f75844SAndroid Build Coastguard Worker 
34*d9f75844SAndroid Build Coastguard Worker   return true;
35*d9f75844SAndroid Build Coastguard Worker }
36*d9f75844SAndroid Build Coastguard Worker 
37*d9f75844SAndroid Build Coastguard Worker // Since FrameBuffer::FrameInfo is private it can't be used in the function
38*d9f75844SAndroid Build Coastguard Worker // signature, hence the FrameIteratorT type.
39*d9f75844SAndroid Build Coastguard Worker template <typename FrameIteratorT>
GetReferences(const FrameIteratorT & it)40*d9f75844SAndroid Build Coastguard Worker rtc::ArrayView<const int64_t> GetReferences(const FrameIteratorT& it) {
41*d9f75844SAndroid Build Coastguard Worker   return {it->second.encoded_frame->references,
42*d9f75844SAndroid Build Coastguard Worker           std::min<size_t>(it->second.encoded_frame->num_references,
43*d9f75844SAndroid Build Coastguard Worker                            EncodedFrame::kMaxFrameReferences)};
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker 
46*d9f75844SAndroid Build Coastguard Worker template <typename FrameIteratorT>
GetFrameId(const FrameIteratorT & it)47*d9f75844SAndroid Build Coastguard Worker int64_t GetFrameId(const FrameIteratorT& it) {
48*d9f75844SAndroid Build Coastguard Worker   return it->first;
49*d9f75844SAndroid Build Coastguard Worker }
50*d9f75844SAndroid Build Coastguard Worker 
51*d9f75844SAndroid Build Coastguard Worker template <typename FrameIteratorT>
GetTimestamp(const FrameIteratorT & it)52*d9f75844SAndroid Build Coastguard Worker uint32_t GetTimestamp(const FrameIteratorT& it) {
53*d9f75844SAndroid Build Coastguard Worker   return it->second.encoded_frame->Timestamp();
54*d9f75844SAndroid Build Coastguard Worker }
55*d9f75844SAndroid Build Coastguard Worker 
56*d9f75844SAndroid Build Coastguard Worker template <typename FrameIteratorT>
IsLastFrameInTemporalUnit(const FrameIteratorT & it)57*d9f75844SAndroid Build Coastguard Worker bool IsLastFrameInTemporalUnit(const FrameIteratorT& it) {
58*d9f75844SAndroid Build Coastguard Worker   return it->second.encoded_frame->is_last_spatial_layer;
59*d9f75844SAndroid Build Coastguard Worker }
60*d9f75844SAndroid Build Coastguard Worker }  // namespace
61*d9f75844SAndroid Build Coastguard Worker 
FrameBuffer(int max_size,int max_decode_history,const FieldTrialsView & field_trials)62*d9f75844SAndroid Build Coastguard Worker FrameBuffer::FrameBuffer(int max_size,
63*d9f75844SAndroid Build Coastguard Worker                          int max_decode_history,
64*d9f75844SAndroid Build Coastguard Worker                          const FieldTrialsView& field_trials)
65*d9f75844SAndroid Build Coastguard Worker     : legacy_frame_id_jump_behavior_(
66*d9f75844SAndroid Build Coastguard Worker           !field_trials.IsDisabled("WebRTC-LegacyFrameIdJumpBehavior")),
67*d9f75844SAndroid Build Coastguard Worker       max_size_(max_size),
68*d9f75844SAndroid Build Coastguard Worker       decoded_frame_history_(max_decode_history) {}
69*d9f75844SAndroid Build Coastguard Worker 
InsertFrame(std::unique_ptr<EncodedFrame> frame)70*d9f75844SAndroid Build Coastguard Worker bool FrameBuffer::InsertFrame(std::unique_ptr<EncodedFrame> frame) {
71*d9f75844SAndroid Build Coastguard Worker   if (!ValidReferences(*frame)) {
72*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_WARNING) << "Frame " << frame->Id()
73*d9f75844SAndroid Build Coastguard Worker                          << " has invalid references, dropping frame.";
74*d9f75844SAndroid Build Coastguard Worker     return false;
75*d9f75844SAndroid Build Coastguard Worker   }
76*d9f75844SAndroid Build Coastguard Worker 
77*d9f75844SAndroid Build Coastguard Worker   if (frame->Id() <= decoded_frame_history_.GetLastDecodedFrameId()) {
78*d9f75844SAndroid Build Coastguard Worker     if (legacy_frame_id_jump_behavior_ && frame->is_keyframe() &&
79*d9f75844SAndroid Build Coastguard Worker         AheadOf(frame->Timestamp(),
80*d9f75844SAndroid Build Coastguard Worker                 *decoded_frame_history_.GetLastDecodedFrameTimestamp())) {
81*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_WARNING)
82*d9f75844SAndroid Build Coastguard Worker           << "Keyframe " << frame->Id()
83*d9f75844SAndroid Build Coastguard Worker           << " has newer timestamp but older picture id, clearing buffer.";
84*d9f75844SAndroid Build Coastguard Worker       Clear();
85*d9f75844SAndroid Build Coastguard Worker     } else {
86*d9f75844SAndroid Build Coastguard Worker       // Already decoded past this frame.
87*d9f75844SAndroid Build Coastguard Worker       return false;
88*d9f75844SAndroid Build Coastguard Worker     }
89*d9f75844SAndroid Build Coastguard Worker   }
90*d9f75844SAndroid Build Coastguard Worker 
91*d9f75844SAndroid Build Coastguard Worker   if (frames_.size() == max_size_) {
92*d9f75844SAndroid Build Coastguard Worker     if (frame->is_keyframe()) {
93*d9f75844SAndroid Build Coastguard Worker       RTC_DLOG(LS_WARNING) << "Keyframe " << frame->Id()
94*d9f75844SAndroid Build Coastguard Worker                            << " inserted into full buffer, clearing buffer.";
95*d9f75844SAndroid Build Coastguard Worker       Clear();
96*d9f75844SAndroid Build Coastguard Worker     } else {
97*d9f75844SAndroid Build Coastguard Worker       // No space for this frame.
98*d9f75844SAndroid Build Coastguard Worker       return false;
99*d9f75844SAndroid Build Coastguard Worker     }
100*d9f75844SAndroid Build Coastguard Worker   }
101*d9f75844SAndroid Build Coastguard Worker 
102*d9f75844SAndroid Build Coastguard Worker   const int64_t frame_id = frame->Id();
103*d9f75844SAndroid Build Coastguard Worker   auto insert_res = frames_.emplace(frame_id, FrameInfo{std::move(frame)});
104*d9f75844SAndroid Build Coastguard Worker   if (!insert_res.second) {
105*d9f75844SAndroid Build Coastguard Worker     // Frame has already been inserted.
106*d9f75844SAndroid Build Coastguard Worker     return false;
107*d9f75844SAndroid Build Coastguard Worker   }
108*d9f75844SAndroid Build Coastguard Worker 
109*d9f75844SAndroid Build Coastguard Worker   if (frames_.size() == max_size_) {
110*d9f75844SAndroid Build Coastguard Worker     RTC_DLOG(LS_WARNING) << "Frame " << frame_id
111*d9f75844SAndroid Build Coastguard Worker                          << " inserted, buffer is now full.";
112*d9f75844SAndroid Build Coastguard Worker   }
113*d9f75844SAndroid Build Coastguard Worker 
114*d9f75844SAndroid Build Coastguard Worker   PropagateContinuity(insert_res.first);
115*d9f75844SAndroid Build Coastguard Worker   FindNextAndLastDecodableTemporalUnit();
116*d9f75844SAndroid Build Coastguard Worker   return true;
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker 
119*d9f75844SAndroid Build Coastguard Worker absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4>
ExtractNextDecodableTemporalUnit()120*d9f75844SAndroid Build Coastguard Worker FrameBuffer::ExtractNextDecodableTemporalUnit() {
121*d9f75844SAndroid Build Coastguard Worker   absl::InlinedVector<std::unique_ptr<EncodedFrame>, 4> res;
122*d9f75844SAndroid Build Coastguard Worker   if (!next_decodable_temporal_unit_) {
123*d9f75844SAndroid Build Coastguard Worker     return res;
124*d9f75844SAndroid Build Coastguard Worker   }
125*d9f75844SAndroid Build Coastguard Worker 
126*d9f75844SAndroid Build Coastguard Worker   auto end_it = std::next(next_decodable_temporal_unit_->last_frame);
127*d9f75844SAndroid Build Coastguard Worker   for (auto it = next_decodable_temporal_unit_->first_frame; it != end_it;
128*d9f75844SAndroid Build Coastguard Worker        ++it) {
129*d9f75844SAndroid Build Coastguard Worker     decoded_frame_history_.InsertDecoded(GetFrameId(it), GetTimestamp(it));
130*d9f75844SAndroid Build Coastguard Worker     res.push_back(std::move(it->second.encoded_frame));
131*d9f75844SAndroid Build Coastguard Worker   }
132*d9f75844SAndroid Build Coastguard Worker 
133*d9f75844SAndroid Build Coastguard Worker   DropNextDecodableTemporalUnit();
134*d9f75844SAndroid Build Coastguard Worker   return res;
135*d9f75844SAndroid Build Coastguard Worker }
136*d9f75844SAndroid Build Coastguard Worker 
DropNextDecodableTemporalUnit()137*d9f75844SAndroid Build Coastguard Worker void FrameBuffer::DropNextDecodableTemporalUnit() {
138*d9f75844SAndroid Build Coastguard Worker   if (!next_decodable_temporal_unit_) {
139*d9f75844SAndroid Build Coastguard Worker     return;
140*d9f75844SAndroid Build Coastguard Worker   }
141*d9f75844SAndroid Build Coastguard Worker 
142*d9f75844SAndroid Build Coastguard Worker   auto end_it = std::next(next_decodable_temporal_unit_->last_frame);
143*d9f75844SAndroid Build Coastguard Worker   num_dropped_frames_ += std::count_if(
144*d9f75844SAndroid Build Coastguard Worker       frames_.begin(), end_it,
145*d9f75844SAndroid Build Coastguard Worker       [](const auto& f) { return f.second.encoded_frame != nullptr; });
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker   frames_.erase(frames_.begin(), end_it);
148*d9f75844SAndroid Build Coastguard Worker   FindNextAndLastDecodableTemporalUnit();
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker 
LastContinuousFrameId() const151*d9f75844SAndroid Build Coastguard Worker absl::optional<int64_t> FrameBuffer::LastContinuousFrameId() const {
152*d9f75844SAndroid Build Coastguard Worker   return last_continuous_frame_id_;
153*d9f75844SAndroid Build Coastguard Worker }
154*d9f75844SAndroid Build Coastguard Worker 
LastContinuousTemporalUnitFrameId() const155*d9f75844SAndroid Build Coastguard Worker absl::optional<int64_t> FrameBuffer::LastContinuousTemporalUnitFrameId() const {
156*d9f75844SAndroid Build Coastguard Worker   return last_continuous_temporal_unit_frame_id_;
157*d9f75844SAndroid Build Coastguard Worker }
158*d9f75844SAndroid Build Coastguard Worker 
159*d9f75844SAndroid Build Coastguard Worker absl::optional<FrameBuffer::DecodabilityInfo>
DecodableTemporalUnitsInfo() const160*d9f75844SAndroid Build Coastguard Worker FrameBuffer::DecodableTemporalUnitsInfo() const {
161*d9f75844SAndroid Build Coastguard Worker   return decodable_temporal_units_info_;
162*d9f75844SAndroid Build Coastguard Worker }
163*d9f75844SAndroid Build Coastguard Worker 
GetTotalNumberOfContinuousTemporalUnits() const164*d9f75844SAndroid Build Coastguard Worker int FrameBuffer::GetTotalNumberOfContinuousTemporalUnits() const {
165*d9f75844SAndroid Build Coastguard Worker   return num_continuous_temporal_units_;
166*d9f75844SAndroid Build Coastguard Worker }
GetTotalNumberOfDroppedFrames() const167*d9f75844SAndroid Build Coastguard Worker int FrameBuffer::GetTotalNumberOfDroppedFrames() const {
168*d9f75844SAndroid Build Coastguard Worker   return num_dropped_frames_;
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker 
CurrentSize() const171*d9f75844SAndroid Build Coastguard Worker size_t FrameBuffer::CurrentSize() const {
172*d9f75844SAndroid Build Coastguard Worker   return frames_.size();
173*d9f75844SAndroid Build Coastguard Worker }
174*d9f75844SAndroid Build Coastguard Worker 
IsContinuous(const FrameIterator & it) const175*d9f75844SAndroid Build Coastguard Worker bool FrameBuffer::IsContinuous(const FrameIterator& it) const {
176*d9f75844SAndroid Build Coastguard Worker   for (int64_t reference : GetReferences(it)) {
177*d9f75844SAndroid Build Coastguard Worker     if (decoded_frame_history_.WasDecoded(reference)) {
178*d9f75844SAndroid Build Coastguard Worker       continue;
179*d9f75844SAndroid Build Coastguard Worker     }
180*d9f75844SAndroid Build Coastguard Worker 
181*d9f75844SAndroid Build Coastguard Worker     auto reference_frame_it = frames_.find(reference);
182*d9f75844SAndroid Build Coastguard Worker     if (reference_frame_it != frames_.end() &&
183*d9f75844SAndroid Build Coastguard Worker         reference_frame_it->second.continuous) {
184*d9f75844SAndroid Build Coastguard Worker       continue;
185*d9f75844SAndroid Build Coastguard Worker     }
186*d9f75844SAndroid Build Coastguard Worker 
187*d9f75844SAndroid Build Coastguard Worker     return false;
188*d9f75844SAndroid Build Coastguard Worker   }
189*d9f75844SAndroid Build Coastguard Worker 
190*d9f75844SAndroid Build Coastguard Worker   return true;
191*d9f75844SAndroid Build Coastguard Worker }
192*d9f75844SAndroid Build Coastguard Worker 
PropagateContinuity(const FrameIterator & frame_it)193*d9f75844SAndroid Build Coastguard Worker void FrameBuffer::PropagateContinuity(const FrameIterator& frame_it) {
194*d9f75844SAndroid Build Coastguard Worker   for (auto it = frame_it; it != frames_.end(); ++it) {
195*d9f75844SAndroid Build Coastguard Worker     if (!it->second.continuous) {
196*d9f75844SAndroid Build Coastguard Worker       if (IsContinuous(it)) {
197*d9f75844SAndroid Build Coastguard Worker         it->second.continuous = true;
198*d9f75844SAndroid Build Coastguard Worker         if (last_continuous_frame_id_ < GetFrameId(it)) {
199*d9f75844SAndroid Build Coastguard Worker           last_continuous_frame_id_ = GetFrameId(it);
200*d9f75844SAndroid Build Coastguard Worker         }
201*d9f75844SAndroid Build Coastguard Worker         if (IsLastFrameInTemporalUnit(it)) {
202*d9f75844SAndroid Build Coastguard Worker           num_continuous_temporal_units_++;
203*d9f75844SAndroid Build Coastguard Worker           if (last_continuous_temporal_unit_frame_id_ < GetFrameId(it)) {
204*d9f75844SAndroid Build Coastguard Worker             last_continuous_temporal_unit_frame_id_ = GetFrameId(it);
205*d9f75844SAndroid Build Coastguard Worker           }
206*d9f75844SAndroid Build Coastguard Worker         }
207*d9f75844SAndroid Build Coastguard Worker       }
208*d9f75844SAndroid Build Coastguard Worker     }
209*d9f75844SAndroid Build Coastguard Worker   }
210*d9f75844SAndroid Build Coastguard Worker }
211*d9f75844SAndroid Build Coastguard Worker 
FindNextAndLastDecodableTemporalUnit()212*d9f75844SAndroid Build Coastguard Worker void FrameBuffer::FindNextAndLastDecodableTemporalUnit() {
213*d9f75844SAndroid Build Coastguard Worker   next_decodable_temporal_unit_.reset();
214*d9f75844SAndroid Build Coastguard Worker   decodable_temporal_units_info_.reset();
215*d9f75844SAndroid Build Coastguard Worker 
216*d9f75844SAndroid Build Coastguard Worker   if (!last_continuous_temporal_unit_frame_id_) {
217*d9f75844SAndroid Build Coastguard Worker     return;
218*d9f75844SAndroid Build Coastguard Worker   }
219*d9f75844SAndroid Build Coastguard Worker 
220*d9f75844SAndroid Build Coastguard Worker   FrameIterator first_frame_it = frames_.begin();
221*d9f75844SAndroid Build Coastguard Worker   FrameIterator last_frame_it = frames_.begin();
222*d9f75844SAndroid Build Coastguard Worker   absl::InlinedVector<int64_t, 4> frames_in_temporal_unit;
223*d9f75844SAndroid Build Coastguard Worker   uint32_t last_decodable_temporal_unit_timestamp;
224*d9f75844SAndroid Build Coastguard Worker   for (auto frame_it = frames_.begin(); frame_it != frames_.end();) {
225*d9f75844SAndroid Build Coastguard Worker     if (GetFrameId(frame_it) > *last_continuous_temporal_unit_frame_id_) {
226*d9f75844SAndroid Build Coastguard Worker       break;
227*d9f75844SAndroid Build Coastguard Worker     }
228*d9f75844SAndroid Build Coastguard Worker 
229*d9f75844SAndroid Build Coastguard Worker     if (GetTimestamp(frame_it) != GetTimestamp(first_frame_it)) {
230*d9f75844SAndroid Build Coastguard Worker       frames_in_temporal_unit.clear();
231*d9f75844SAndroid Build Coastguard Worker       first_frame_it = frame_it;
232*d9f75844SAndroid Build Coastguard Worker     }
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker     frames_in_temporal_unit.push_back(GetFrameId(frame_it));
235*d9f75844SAndroid Build Coastguard Worker 
236*d9f75844SAndroid Build Coastguard Worker     last_frame_it = frame_it++;
237*d9f75844SAndroid Build Coastguard Worker 
238*d9f75844SAndroid Build Coastguard Worker     if (IsLastFrameInTemporalUnit(last_frame_it)) {
239*d9f75844SAndroid Build Coastguard Worker       bool temporal_unit_decodable = true;
240*d9f75844SAndroid Build Coastguard Worker       for (auto it = first_frame_it; it != frame_it && temporal_unit_decodable;
241*d9f75844SAndroid Build Coastguard Worker            ++it) {
242*d9f75844SAndroid Build Coastguard Worker         for (int64_t reference : GetReferences(it)) {
243*d9f75844SAndroid Build Coastguard Worker           if (!decoded_frame_history_.WasDecoded(reference) &&
244*d9f75844SAndroid Build Coastguard Worker               !absl::c_linear_search(frames_in_temporal_unit, reference)) {
245*d9f75844SAndroid Build Coastguard Worker             // A frame in the temporal unit has a non-decoded reference outside
246*d9f75844SAndroid Build Coastguard Worker             // the temporal unit, so it's not yet ready to be decoded.
247*d9f75844SAndroid Build Coastguard Worker             temporal_unit_decodable = false;
248*d9f75844SAndroid Build Coastguard Worker             break;
249*d9f75844SAndroid Build Coastguard Worker           }
250*d9f75844SAndroid Build Coastguard Worker         }
251*d9f75844SAndroid Build Coastguard Worker       }
252*d9f75844SAndroid Build Coastguard Worker 
253*d9f75844SAndroid Build Coastguard Worker       if (temporal_unit_decodable) {
254*d9f75844SAndroid Build Coastguard Worker         if (!next_decodable_temporal_unit_) {
255*d9f75844SAndroid Build Coastguard Worker           next_decodable_temporal_unit_ = {first_frame_it, last_frame_it};
256*d9f75844SAndroid Build Coastguard Worker         }
257*d9f75844SAndroid Build Coastguard Worker 
258*d9f75844SAndroid Build Coastguard Worker         last_decodable_temporal_unit_timestamp = GetTimestamp(first_frame_it);
259*d9f75844SAndroid Build Coastguard Worker       }
260*d9f75844SAndroid Build Coastguard Worker     }
261*d9f75844SAndroid Build Coastguard Worker   }
262*d9f75844SAndroid Build Coastguard Worker 
263*d9f75844SAndroid Build Coastguard Worker   if (next_decodable_temporal_unit_) {
264*d9f75844SAndroid Build Coastguard Worker     decodable_temporal_units_info_ = {
265*d9f75844SAndroid Build Coastguard Worker         .next_rtp_timestamp =
266*d9f75844SAndroid Build Coastguard Worker             GetTimestamp(next_decodable_temporal_unit_->first_frame),
267*d9f75844SAndroid Build Coastguard Worker         .last_rtp_timestamp = last_decodable_temporal_unit_timestamp};
268*d9f75844SAndroid Build Coastguard Worker   }
269*d9f75844SAndroid Build Coastguard Worker }
270*d9f75844SAndroid Build Coastguard Worker 
Clear()271*d9f75844SAndroid Build Coastguard Worker void FrameBuffer::Clear() {
272*d9f75844SAndroid Build Coastguard Worker   frames_.clear();
273*d9f75844SAndroid Build Coastguard Worker   next_decodable_temporal_unit_.reset();
274*d9f75844SAndroid Build Coastguard Worker   decodable_temporal_units_info_.reset();
275*d9f75844SAndroid Build Coastguard Worker   last_continuous_frame_id_.reset();
276*d9f75844SAndroid Build Coastguard Worker   last_continuous_temporal_unit_frame_id_.reset();
277*d9f75844SAndroid Build Coastguard Worker   decoded_frame_history_.Clear();
278*d9f75844SAndroid Build Coastguard Worker }
279*d9f75844SAndroid Build Coastguard Worker 
280*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
281