xref: /aosp_15_r20/external/webrtc/modules/video_coding/jitter_buffer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2012 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 #include "modules/video_coding/jitter_buffer.h"
11*d9f75844SAndroid Build Coastguard Worker 
12*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
13*d9f75844SAndroid Build Coastguard Worker #include <limits>
14*d9f75844SAndroid Build Coastguard Worker #include <utility>
15*d9f75844SAndroid Build Coastguard Worker 
16*d9f75844SAndroid Build Coastguard Worker #include "api/units/timestamp.h"
17*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/frame_buffer.h"
18*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/include/video_coding.h"
19*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/internal_defines.h"
20*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/jitter_buffer_common.h"
21*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/packet.h"
22*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/timing/inter_frame_delay.h"
23*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/timing/jitter_estimator.h"
24*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
25*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
26*d9f75844SAndroid Build Coastguard Worker #include "system_wrappers/include/clock.h"
27*d9f75844SAndroid Build Coastguard Worker 
28*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
29*d9f75844SAndroid Build Coastguard Worker // Use this rtt if no value has been reported.
30*d9f75844SAndroid Build Coastguard Worker static const int64_t kDefaultRtt = 200;
31*d9f75844SAndroid Build Coastguard Worker 
32*d9f75844SAndroid Build Coastguard Worker typedef std::pair<uint32_t, VCMFrameBuffer*> FrameListPair;
33*d9f75844SAndroid Build Coastguard Worker 
IsKeyFrame(FrameListPair pair)34*d9f75844SAndroid Build Coastguard Worker bool IsKeyFrame(FrameListPair pair) {
35*d9f75844SAndroid Build Coastguard Worker   return pair.second->FrameType() == VideoFrameType::kVideoFrameKey;
36*d9f75844SAndroid Build Coastguard Worker }
37*d9f75844SAndroid Build Coastguard Worker 
HasNonEmptyState(FrameListPair pair)38*d9f75844SAndroid Build Coastguard Worker bool HasNonEmptyState(FrameListPair pair) {
39*d9f75844SAndroid Build Coastguard Worker   return pair.second->GetState() != kStateEmpty;
40*d9f75844SAndroid Build Coastguard Worker }
41*d9f75844SAndroid Build Coastguard Worker 
InsertFrame(VCMFrameBuffer * frame)42*d9f75844SAndroid Build Coastguard Worker void FrameList::InsertFrame(VCMFrameBuffer* frame) {
43*d9f75844SAndroid Build Coastguard Worker   insert(rbegin().base(), FrameListPair(frame->Timestamp(), frame));
44*d9f75844SAndroid Build Coastguard Worker }
45*d9f75844SAndroid Build Coastguard Worker 
PopFrame(uint32_t timestamp)46*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer* FrameList::PopFrame(uint32_t timestamp) {
47*d9f75844SAndroid Build Coastguard Worker   FrameList::iterator it = find(timestamp);
48*d9f75844SAndroid Build Coastguard Worker   if (it == end())
49*d9f75844SAndroid Build Coastguard Worker     return NULL;
50*d9f75844SAndroid Build Coastguard Worker   VCMFrameBuffer* frame = it->second;
51*d9f75844SAndroid Build Coastguard Worker   erase(it);
52*d9f75844SAndroid Build Coastguard Worker   return frame;
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker 
Front() const55*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer* FrameList::Front() const {
56*d9f75844SAndroid Build Coastguard Worker   return begin()->second;
57*d9f75844SAndroid Build Coastguard Worker }
58*d9f75844SAndroid Build Coastguard Worker 
Back() const59*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer* FrameList::Back() const {
60*d9f75844SAndroid Build Coastguard Worker   return rbegin()->second;
61*d9f75844SAndroid Build Coastguard Worker }
62*d9f75844SAndroid Build Coastguard Worker 
RecycleFramesUntilKeyFrame(FrameList::iterator * key_frame_it,UnorderedFrameList * free_frames)63*d9f75844SAndroid Build Coastguard Worker int FrameList::RecycleFramesUntilKeyFrame(FrameList::iterator* key_frame_it,
64*d9f75844SAndroid Build Coastguard Worker                                           UnorderedFrameList* free_frames) {
65*d9f75844SAndroid Build Coastguard Worker   int drop_count = 0;
66*d9f75844SAndroid Build Coastguard Worker   FrameList::iterator it = begin();
67*d9f75844SAndroid Build Coastguard Worker   while (!empty()) {
68*d9f75844SAndroid Build Coastguard Worker     // Throw at least one frame.
69*d9f75844SAndroid Build Coastguard Worker     it->second->Reset();
70*d9f75844SAndroid Build Coastguard Worker     free_frames->push_back(it->second);
71*d9f75844SAndroid Build Coastguard Worker     erase(it++);
72*d9f75844SAndroid Build Coastguard Worker     ++drop_count;
73*d9f75844SAndroid Build Coastguard Worker     if (it != end() &&
74*d9f75844SAndroid Build Coastguard Worker         it->second->FrameType() == VideoFrameType::kVideoFrameKey) {
75*d9f75844SAndroid Build Coastguard Worker       *key_frame_it = it;
76*d9f75844SAndroid Build Coastguard Worker       return drop_count;
77*d9f75844SAndroid Build Coastguard Worker     }
78*d9f75844SAndroid Build Coastguard Worker   }
79*d9f75844SAndroid Build Coastguard Worker   *key_frame_it = end();
80*d9f75844SAndroid Build Coastguard Worker   return drop_count;
81*d9f75844SAndroid Build Coastguard Worker }
82*d9f75844SAndroid Build Coastguard Worker 
CleanUpOldOrEmptyFrames(VCMDecodingState * decoding_state,UnorderedFrameList * free_frames)83*d9f75844SAndroid Build Coastguard Worker void FrameList::CleanUpOldOrEmptyFrames(VCMDecodingState* decoding_state,
84*d9f75844SAndroid Build Coastguard Worker                                         UnorderedFrameList* free_frames) {
85*d9f75844SAndroid Build Coastguard Worker   while (!empty()) {
86*d9f75844SAndroid Build Coastguard Worker     VCMFrameBuffer* oldest_frame = Front();
87*d9f75844SAndroid Build Coastguard Worker     bool remove_frame = false;
88*d9f75844SAndroid Build Coastguard Worker     if (oldest_frame->GetState() == kStateEmpty && size() > 1) {
89*d9f75844SAndroid Build Coastguard Worker       // This frame is empty, try to update the last decoded state and drop it
90*d9f75844SAndroid Build Coastguard Worker       // if successful.
91*d9f75844SAndroid Build Coastguard Worker       remove_frame = decoding_state->UpdateEmptyFrame(oldest_frame);
92*d9f75844SAndroid Build Coastguard Worker     } else {
93*d9f75844SAndroid Build Coastguard Worker       remove_frame = decoding_state->IsOldFrame(oldest_frame);
94*d9f75844SAndroid Build Coastguard Worker     }
95*d9f75844SAndroid Build Coastguard Worker     if (!remove_frame) {
96*d9f75844SAndroid Build Coastguard Worker       break;
97*d9f75844SAndroid Build Coastguard Worker     }
98*d9f75844SAndroid Build Coastguard Worker     free_frames->push_back(oldest_frame);
99*d9f75844SAndroid Build Coastguard Worker     erase(begin());
100*d9f75844SAndroid Build Coastguard Worker   }
101*d9f75844SAndroid Build Coastguard Worker }
102*d9f75844SAndroid Build Coastguard Worker 
Reset(UnorderedFrameList * free_frames)103*d9f75844SAndroid Build Coastguard Worker void FrameList::Reset(UnorderedFrameList* free_frames) {
104*d9f75844SAndroid Build Coastguard Worker   while (!empty()) {
105*d9f75844SAndroid Build Coastguard Worker     begin()->second->Reset();
106*d9f75844SAndroid Build Coastguard Worker     free_frames->push_back(begin()->second);
107*d9f75844SAndroid Build Coastguard Worker     erase(begin());
108*d9f75844SAndroid Build Coastguard Worker   }
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker 
VCMJitterBuffer(Clock * clock,std::unique_ptr<EventWrapper> event,const FieldTrialsView & field_trials)111*d9f75844SAndroid Build Coastguard Worker VCMJitterBuffer::VCMJitterBuffer(Clock* clock,
112*d9f75844SAndroid Build Coastguard Worker                                  std::unique_ptr<EventWrapper> event,
113*d9f75844SAndroid Build Coastguard Worker                                  const FieldTrialsView& field_trials)
114*d9f75844SAndroid Build Coastguard Worker     : clock_(clock),
115*d9f75844SAndroid Build Coastguard Worker       running_(false),
116*d9f75844SAndroid Build Coastguard Worker       frame_event_(std::move(event)),
117*d9f75844SAndroid Build Coastguard Worker       max_number_of_frames_(kStartNumberOfFrames),
118*d9f75844SAndroid Build Coastguard Worker       free_frames_(),
119*d9f75844SAndroid Build Coastguard Worker       decodable_frames_(),
120*d9f75844SAndroid Build Coastguard Worker       incomplete_frames_(),
121*d9f75844SAndroid Build Coastguard Worker       last_decoded_state_(),
122*d9f75844SAndroid Build Coastguard Worker       first_packet_since_reset_(true),
123*d9f75844SAndroid Build Coastguard Worker       num_consecutive_old_packets_(0),
124*d9f75844SAndroid Build Coastguard Worker       num_packets_(0),
125*d9f75844SAndroid Build Coastguard Worker       num_duplicated_packets_(0),
126*d9f75844SAndroid Build Coastguard Worker       jitter_estimate_(clock, field_trials),
127*d9f75844SAndroid Build Coastguard Worker       missing_sequence_numbers_(SequenceNumberLessThan()),
128*d9f75844SAndroid Build Coastguard Worker       latest_received_sequence_number_(0),
129*d9f75844SAndroid Build Coastguard Worker       max_nack_list_size_(0),
130*d9f75844SAndroid Build Coastguard Worker       max_packet_age_to_nack_(0),
131*d9f75844SAndroid Build Coastguard Worker       max_incomplete_time_ms_(0),
132*d9f75844SAndroid Build Coastguard Worker       average_packets_per_frame_(0.0f),
133*d9f75844SAndroid Build Coastguard Worker       frame_counter_(0) {
134*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < kStartNumberOfFrames; i++)
135*d9f75844SAndroid Build Coastguard Worker     free_frames_.push_back(new VCMFrameBuffer());
136*d9f75844SAndroid Build Coastguard Worker }
137*d9f75844SAndroid Build Coastguard Worker 
~VCMJitterBuffer()138*d9f75844SAndroid Build Coastguard Worker VCMJitterBuffer::~VCMJitterBuffer() {
139*d9f75844SAndroid Build Coastguard Worker   Stop();
140*d9f75844SAndroid Build Coastguard Worker   for (UnorderedFrameList::iterator it = free_frames_.begin();
141*d9f75844SAndroid Build Coastguard Worker        it != free_frames_.end(); ++it) {
142*d9f75844SAndroid Build Coastguard Worker     delete *it;
143*d9f75844SAndroid Build Coastguard Worker   }
144*d9f75844SAndroid Build Coastguard Worker   for (FrameList::iterator it = incomplete_frames_.begin();
145*d9f75844SAndroid Build Coastguard Worker        it != incomplete_frames_.end(); ++it) {
146*d9f75844SAndroid Build Coastguard Worker     delete it->second;
147*d9f75844SAndroid Build Coastguard Worker   }
148*d9f75844SAndroid Build Coastguard Worker   for (FrameList::iterator it = decodable_frames_.begin();
149*d9f75844SAndroid Build Coastguard Worker        it != decodable_frames_.end(); ++it) {
150*d9f75844SAndroid Build Coastguard Worker     delete it->second;
151*d9f75844SAndroid Build Coastguard Worker   }
152*d9f75844SAndroid Build Coastguard Worker }
153*d9f75844SAndroid Build Coastguard Worker 
Start()154*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::Start() {
155*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
156*d9f75844SAndroid Build Coastguard Worker   running_ = true;
157*d9f75844SAndroid Build Coastguard Worker 
158*d9f75844SAndroid Build Coastguard Worker   num_consecutive_old_packets_ = 0;
159*d9f75844SAndroid Build Coastguard Worker   num_packets_ = 0;
160*d9f75844SAndroid Build Coastguard Worker   num_duplicated_packets_ = 0;
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   // Start in a non-signaled state.
163*d9f75844SAndroid Build Coastguard Worker   waiting_for_completion_.frame_size = 0;
164*d9f75844SAndroid Build Coastguard Worker   waiting_for_completion_.timestamp = 0;
165*d9f75844SAndroid Build Coastguard Worker   waiting_for_completion_.latest_packet_time = -1;
166*d9f75844SAndroid Build Coastguard Worker   first_packet_since_reset_ = true;
167*d9f75844SAndroid Build Coastguard Worker   last_decoded_state_.Reset();
168*d9f75844SAndroid Build Coastguard Worker 
169*d9f75844SAndroid Build Coastguard Worker   decodable_frames_.Reset(&free_frames_);
170*d9f75844SAndroid Build Coastguard Worker   incomplete_frames_.Reset(&free_frames_);
171*d9f75844SAndroid Build Coastguard Worker }
172*d9f75844SAndroid Build Coastguard Worker 
Stop()173*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::Stop() {
174*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
175*d9f75844SAndroid Build Coastguard Worker   running_ = false;
176*d9f75844SAndroid Build Coastguard Worker   last_decoded_state_.Reset();
177*d9f75844SAndroid Build Coastguard Worker 
178*d9f75844SAndroid Build Coastguard Worker   // Make sure we wake up any threads waiting on these events.
179*d9f75844SAndroid Build Coastguard Worker   frame_event_->Set();
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker 
Running() const182*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::Running() const {
183*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
184*d9f75844SAndroid Build Coastguard Worker   return running_;
185*d9f75844SAndroid Build Coastguard Worker }
186*d9f75844SAndroid Build Coastguard Worker 
Flush()187*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::Flush() {
188*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
189*d9f75844SAndroid Build Coastguard Worker   decodable_frames_.Reset(&free_frames_);
190*d9f75844SAndroid Build Coastguard Worker   incomplete_frames_.Reset(&free_frames_);
191*d9f75844SAndroid Build Coastguard Worker   last_decoded_state_.Reset();  // TODO(mikhal): sync reset.
192*d9f75844SAndroid Build Coastguard Worker   num_consecutive_old_packets_ = 0;
193*d9f75844SAndroid Build Coastguard Worker   // Also reset the jitter and delay estimates
194*d9f75844SAndroid Build Coastguard Worker   jitter_estimate_.Reset();
195*d9f75844SAndroid Build Coastguard Worker   inter_frame_delay_.Reset();
196*d9f75844SAndroid Build Coastguard Worker   waiting_for_completion_.frame_size = 0;
197*d9f75844SAndroid Build Coastguard Worker   waiting_for_completion_.timestamp = 0;
198*d9f75844SAndroid Build Coastguard Worker   waiting_for_completion_.latest_packet_time = -1;
199*d9f75844SAndroid Build Coastguard Worker   first_packet_since_reset_ = true;
200*d9f75844SAndroid Build Coastguard Worker   missing_sequence_numbers_.clear();
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker 
num_packets() const203*d9f75844SAndroid Build Coastguard Worker int VCMJitterBuffer::num_packets() const {
204*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
205*d9f75844SAndroid Build Coastguard Worker   return num_packets_;
206*d9f75844SAndroid Build Coastguard Worker }
207*d9f75844SAndroid Build Coastguard Worker 
num_duplicated_packets() const208*d9f75844SAndroid Build Coastguard Worker int VCMJitterBuffer::num_duplicated_packets() const {
209*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
210*d9f75844SAndroid Build Coastguard Worker   return num_duplicated_packets_;
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker 
213*d9f75844SAndroid Build Coastguard Worker // Returns immediately or a `max_wait_time_ms` ms event hang waiting for a
214*d9f75844SAndroid Build Coastguard Worker // complete frame, `max_wait_time_ms` decided by caller.
NextCompleteFrame(uint32_t max_wait_time_ms)215*d9f75844SAndroid Build Coastguard Worker VCMEncodedFrame* VCMJitterBuffer::NextCompleteFrame(uint32_t max_wait_time_ms) {
216*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
217*d9f75844SAndroid Build Coastguard Worker   if (!running_) {
218*d9f75844SAndroid Build Coastguard Worker     return nullptr;
219*d9f75844SAndroid Build Coastguard Worker   }
220*d9f75844SAndroid Build Coastguard Worker   CleanUpOldOrEmptyFrames();
221*d9f75844SAndroid Build Coastguard Worker 
222*d9f75844SAndroid Build Coastguard Worker   if (decodable_frames_.empty() ||
223*d9f75844SAndroid Build Coastguard Worker       decodable_frames_.Front()->GetState() != kStateComplete) {
224*d9f75844SAndroid Build Coastguard Worker     const int64_t end_wait_time_ms =
225*d9f75844SAndroid Build Coastguard Worker         clock_->TimeInMilliseconds() + max_wait_time_ms;
226*d9f75844SAndroid Build Coastguard Worker     int64_t wait_time_ms = max_wait_time_ms;
227*d9f75844SAndroid Build Coastguard Worker     while (wait_time_ms > 0) {
228*d9f75844SAndroid Build Coastguard Worker       mutex_.Unlock();
229*d9f75844SAndroid Build Coastguard Worker       const EventTypeWrapper ret =
230*d9f75844SAndroid Build Coastguard Worker           frame_event_->Wait(static_cast<uint32_t>(wait_time_ms));
231*d9f75844SAndroid Build Coastguard Worker       mutex_.Lock();
232*d9f75844SAndroid Build Coastguard Worker       if (ret == kEventSignaled) {
233*d9f75844SAndroid Build Coastguard Worker         // Are we shutting down the jitter buffer?
234*d9f75844SAndroid Build Coastguard Worker         if (!running_) {
235*d9f75844SAndroid Build Coastguard Worker           return nullptr;
236*d9f75844SAndroid Build Coastguard Worker         }
237*d9f75844SAndroid Build Coastguard Worker         // Finding oldest frame ready for decoder.
238*d9f75844SAndroid Build Coastguard Worker         CleanUpOldOrEmptyFrames();
239*d9f75844SAndroid Build Coastguard Worker         if (decodable_frames_.empty() ||
240*d9f75844SAndroid Build Coastguard Worker             decodable_frames_.Front()->GetState() != kStateComplete) {
241*d9f75844SAndroid Build Coastguard Worker           wait_time_ms = end_wait_time_ms - clock_->TimeInMilliseconds();
242*d9f75844SAndroid Build Coastguard Worker         } else {
243*d9f75844SAndroid Build Coastguard Worker           break;
244*d9f75844SAndroid Build Coastguard Worker         }
245*d9f75844SAndroid Build Coastguard Worker       } else {
246*d9f75844SAndroid Build Coastguard Worker         break;
247*d9f75844SAndroid Build Coastguard Worker       }
248*d9f75844SAndroid Build Coastguard Worker     }
249*d9f75844SAndroid Build Coastguard Worker   }
250*d9f75844SAndroid Build Coastguard Worker   if (decodable_frames_.empty() ||
251*d9f75844SAndroid Build Coastguard Worker       decodable_frames_.Front()->GetState() != kStateComplete) {
252*d9f75844SAndroid Build Coastguard Worker     return nullptr;
253*d9f75844SAndroid Build Coastguard Worker   }
254*d9f75844SAndroid Build Coastguard Worker   return decodable_frames_.Front();
255*d9f75844SAndroid Build Coastguard Worker }
256*d9f75844SAndroid Build Coastguard Worker 
ExtractAndSetDecode(uint32_t timestamp)257*d9f75844SAndroid Build Coastguard Worker VCMEncodedFrame* VCMJitterBuffer::ExtractAndSetDecode(uint32_t timestamp) {
258*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
259*d9f75844SAndroid Build Coastguard Worker   if (!running_) {
260*d9f75844SAndroid Build Coastguard Worker     return NULL;
261*d9f75844SAndroid Build Coastguard Worker   }
262*d9f75844SAndroid Build Coastguard Worker   // Extract the frame with the desired timestamp.
263*d9f75844SAndroid Build Coastguard Worker   VCMFrameBuffer* frame = decodable_frames_.PopFrame(timestamp);
264*d9f75844SAndroid Build Coastguard Worker   bool continuous = true;
265*d9f75844SAndroid Build Coastguard Worker   if (!frame) {
266*d9f75844SAndroid Build Coastguard Worker     frame = incomplete_frames_.PopFrame(timestamp);
267*d9f75844SAndroid Build Coastguard Worker     if (frame)
268*d9f75844SAndroid Build Coastguard Worker       continuous = last_decoded_state_.ContinuousFrame(frame);
269*d9f75844SAndroid Build Coastguard Worker     else
270*d9f75844SAndroid Build Coastguard Worker       return NULL;
271*d9f75844SAndroid Build Coastguard Worker   }
272*d9f75844SAndroid Build Coastguard Worker   // Frame pulled out from jitter buffer, update the jitter estimate.
273*d9f75844SAndroid Build Coastguard Worker   const bool retransmitted = (frame->GetNackCount() > 0);
274*d9f75844SAndroid Build Coastguard Worker   if (retransmitted) {
275*d9f75844SAndroid Build Coastguard Worker     jitter_estimate_.FrameNacked();
276*d9f75844SAndroid Build Coastguard Worker   } else if (frame->size() > 0) {
277*d9f75844SAndroid Build Coastguard Worker     // Ignore retransmitted and empty frames.
278*d9f75844SAndroid Build Coastguard Worker     if (waiting_for_completion_.latest_packet_time >= 0) {
279*d9f75844SAndroid Build Coastguard Worker       UpdateJitterEstimate(waiting_for_completion_, true);
280*d9f75844SAndroid Build Coastguard Worker     }
281*d9f75844SAndroid Build Coastguard Worker     if (frame->GetState() == kStateComplete) {
282*d9f75844SAndroid Build Coastguard Worker       UpdateJitterEstimate(*frame, false);
283*d9f75844SAndroid Build Coastguard Worker     } else {
284*d9f75844SAndroid Build Coastguard Worker       // Wait for this one to get complete.
285*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.frame_size = frame->size();
286*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.latest_packet_time = frame->LatestPacketTimeMs();
287*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.timestamp = frame->Timestamp();
288*d9f75844SAndroid Build Coastguard Worker     }
289*d9f75844SAndroid Build Coastguard Worker   }
290*d9f75844SAndroid Build Coastguard Worker 
291*d9f75844SAndroid Build Coastguard Worker   // The state must be changed to decoding before cleaning up zero sized
292*d9f75844SAndroid Build Coastguard Worker   // frames to avoid empty frames being cleaned up and then given to the
293*d9f75844SAndroid Build Coastguard Worker   // decoder. Propagates the missing_frame bit.
294*d9f75844SAndroid Build Coastguard Worker   frame->PrepareForDecode(continuous);
295*d9f75844SAndroid Build Coastguard Worker 
296*d9f75844SAndroid Build Coastguard Worker   // We have a frame - update the last decoded state and nack list.
297*d9f75844SAndroid Build Coastguard Worker   last_decoded_state_.SetState(frame);
298*d9f75844SAndroid Build Coastguard Worker   DropPacketsFromNackList(last_decoded_state_.sequence_num());
299*d9f75844SAndroid Build Coastguard Worker 
300*d9f75844SAndroid Build Coastguard Worker   UpdateAveragePacketsPerFrame(frame->NumPackets());
301*d9f75844SAndroid Build Coastguard Worker 
302*d9f75844SAndroid Build Coastguard Worker   return frame;
303*d9f75844SAndroid Build Coastguard Worker }
304*d9f75844SAndroid Build Coastguard Worker 
305*d9f75844SAndroid Build Coastguard Worker // Release frame when done with decoding. Should never be used to release
306*d9f75844SAndroid Build Coastguard Worker // frames from within the jitter buffer.
ReleaseFrame(VCMEncodedFrame * frame)307*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::ReleaseFrame(VCMEncodedFrame* frame) {
308*d9f75844SAndroid Build Coastguard Worker   RTC_CHECK(frame != nullptr);
309*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
310*d9f75844SAndroid Build Coastguard Worker   VCMFrameBuffer* frame_buffer = static_cast<VCMFrameBuffer*>(frame);
311*d9f75844SAndroid Build Coastguard Worker   RecycleFrameBuffer(frame_buffer);
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker 
314*d9f75844SAndroid Build Coastguard Worker // Gets frame to use for this timestamp. If no match, get empty frame.
GetFrame(const VCMPacket & packet,VCMFrameBuffer ** frame,FrameList ** frame_list)315*d9f75844SAndroid Build Coastguard Worker VCMFrameBufferEnum VCMJitterBuffer::GetFrame(const VCMPacket& packet,
316*d9f75844SAndroid Build Coastguard Worker                                              VCMFrameBuffer** frame,
317*d9f75844SAndroid Build Coastguard Worker                                              FrameList** frame_list) {
318*d9f75844SAndroid Build Coastguard Worker   *frame = incomplete_frames_.PopFrame(packet.timestamp);
319*d9f75844SAndroid Build Coastguard Worker   if (*frame != NULL) {
320*d9f75844SAndroid Build Coastguard Worker     *frame_list = &incomplete_frames_;
321*d9f75844SAndroid Build Coastguard Worker     return kNoError;
322*d9f75844SAndroid Build Coastguard Worker   }
323*d9f75844SAndroid Build Coastguard Worker   *frame = decodable_frames_.PopFrame(packet.timestamp);
324*d9f75844SAndroid Build Coastguard Worker   if (*frame != NULL) {
325*d9f75844SAndroid Build Coastguard Worker     *frame_list = &decodable_frames_;
326*d9f75844SAndroid Build Coastguard Worker     return kNoError;
327*d9f75844SAndroid Build Coastguard Worker   }
328*d9f75844SAndroid Build Coastguard Worker 
329*d9f75844SAndroid Build Coastguard Worker   *frame_list = NULL;
330*d9f75844SAndroid Build Coastguard Worker   // No match, return empty frame.
331*d9f75844SAndroid Build Coastguard Worker   *frame = GetEmptyFrame();
332*d9f75844SAndroid Build Coastguard Worker   if (*frame == NULL) {
333*d9f75844SAndroid Build Coastguard Worker     // No free frame! Try to reclaim some...
334*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING) << "Unable to get empty frame; Recycling.";
335*d9f75844SAndroid Build Coastguard Worker     bool found_key_frame = RecycleFramesUntilKeyFrame();
336*d9f75844SAndroid Build Coastguard Worker     *frame = GetEmptyFrame();
337*d9f75844SAndroid Build Coastguard Worker     RTC_CHECK(*frame);
338*d9f75844SAndroid Build Coastguard Worker     if (!found_key_frame) {
339*d9f75844SAndroid Build Coastguard Worker       RecycleFrameBuffer(*frame);
340*d9f75844SAndroid Build Coastguard Worker       return kFlushIndicator;
341*d9f75844SAndroid Build Coastguard Worker     }
342*d9f75844SAndroid Build Coastguard Worker   }
343*d9f75844SAndroid Build Coastguard Worker   (*frame)->Reset();
344*d9f75844SAndroid Build Coastguard Worker   return kNoError;
345*d9f75844SAndroid Build Coastguard Worker }
346*d9f75844SAndroid Build Coastguard Worker 
LastPacketTime(const VCMEncodedFrame * frame,bool * retransmitted) const347*d9f75844SAndroid Build Coastguard Worker int64_t VCMJitterBuffer::LastPacketTime(const VCMEncodedFrame* frame,
348*d9f75844SAndroid Build Coastguard Worker                                         bool* retransmitted) const {
349*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(retransmitted);
350*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
351*d9f75844SAndroid Build Coastguard Worker   const VCMFrameBuffer* frame_buffer =
352*d9f75844SAndroid Build Coastguard Worker       static_cast<const VCMFrameBuffer*>(frame);
353*d9f75844SAndroid Build Coastguard Worker   *retransmitted = (frame_buffer->GetNackCount() > 0);
354*d9f75844SAndroid Build Coastguard Worker   return frame_buffer->LatestPacketTimeMs();
355*d9f75844SAndroid Build Coastguard Worker }
356*d9f75844SAndroid Build Coastguard Worker 
InsertPacket(const VCMPacket & packet,bool * retransmitted)357*d9f75844SAndroid Build Coastguard Worker VCMFrameBufferEnum VCMJitterBuffer::InsertPacket(const VCMPacket& packet,
358*d9f75844SAndroid Build Coastguard Worker                                                  bool* retransmitted) {
359*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
360*d9f75844SAndroid Build Coastguard Worker 
361*d9f75844SAndroid Build Coastguard Worker   ++num_packets_;
362*d9f75844SAndroid Build Coastguard Worker   // Does this packet belong to an old frame?
363*d9f75844SAndroid Build Coastguard Worker   if (last_decoded_state_.IsOldPacket(&packet)) {
364*d9f75844SAndroid Build Coastguard Worker     // Account only for media packets.
365*d9f75844SAndroid Build Coastguard Worker     if (packet.sizeBytes > 0) {
366*d9f75844SAndroid Build Coastguard Worker       num_consecutive_old_packets_++;
367*d9f75844SAndroid Build Coastguard Worker     }
368*d9f75844SAndroid Build Coastguard Worker     // Update last decoded sequence number if the packet arrived late and
369*d9f75844SAndroid Build Coastguard Worker     // belongs to a frame with a timestamp equal to the last decoded
370*d9f75844SAndroid Build Coastguard Worker     // timestamp.
371*d9f75844SAndroid Build Coastguard Worker     last_decoded_state_.UpdateOldPacket(&packet);
372*d9f75844SAndroid Build Coastguard Worker     DropPacketsFromNackList(last_decoded_state_.sequence_num());
373*d9f75844SAndroid Build Coastguard Worker 
374*d9f75844SAndroid Build Coastguard Worker     // Also see if this old packet made more incomplete frames continuous.
375*d9f75844SAndroid Build Coastguard Worker     FindAndInsertContinuousFramesWithState(last_decoded_state_);
376*d9f75844SAndroid Build Coastguard Worker 
377*d9f75844SAndroid Build Coastguard Worker     if (num_consecutive_old_packets_ > kMaxConsecutiveOldPackets) {
378*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING)
379*d9f75844SAndroid Build Coastguard Worker           << num_consecutive_old_packets_
380*d9f75844SAndroid Build Coastguard Worker           << " consecutive old packets received. Flushing the jitter buffer.";
381*d9f75844SAndroid Build Coastguard Worker       Flush();
382*d9f75844SAndroid Build Coastguard Worker       return kFlushIndicator;
383*d9f75844SAndroid Build Coastguard Worker     }
384*d9f75844SAndroid Build Coastguard Worker     return kOldPacket;
385*d9f75844SAndroid Build Coastguard Worker   }
386*d9f75844SAndroid Build Coastguard Worker 
387*d9f75844SAndroid Build Coastguard Worker   num_consecutive_old_packets_ = 0;
388*d9f75844SAndroid Build Coastguard Worker 
389*d9f75844SAndroid Build Coastguard Worker   VCMFrameBuffer* frame;
390*d9f75844SAndroid Build Coastguard Worker   FrameList* frame_list;
391*d9f75844SAndroid Build Coastguard Worker   const VCMFrameBufferEnum error = GetFrame(packet, &frame, &frame_list);
392*d9f75844SAndroid Build Coastguard Worker   if (error != kNoError)
393*d9f75844SAndroid Build Coastguard Worker     return error;
394*d9f75844SAndroid Build Coastguard Worker 
395*d9f75844SAndroid Build Coastguard Worker   Timestamp now = clock_->CurrentTime();
396*d9f75844SAndroid Build Coastguard Worker   // We are keeping track of the first and latest seq numbers, and
397*d9f75844SAndroid Build Coastguard Worker   // the number of wraps to be able to calculate how many packets we expect.
398*d9f75844SAndroid Build Coastguard Worker   if (first_packet_since_reset_) {
399*d9f75844SAndroid Build Coastguard Worker     // Now it's time to start estimating jitter
400*d9f75844SAndroid Build Coastguard Worker     // reset the delay estimate.
401*d9f75844SAndroid Build Coastguard Worker     inter_frame_delay_.Reset();
402*d9f75844SAndroid Build Coastguard Worker   }
403*d9f75844SAndroid Build Coastguard Worker 
404*d9f75844SAndroid Build Coastguard Worker   // Empty packets may bias the jitter estimate (lacking size component),
405*d9f75844SAndroid Build Coastguard Worker   // therefore don't let empty packet trigger the following updates:
406*d9f75844SAndroid Build Coastguard Worker   if (packet.video_header.frame_type != VideoFrameType::kEmptyFrame) {
407*d9f75844SAndroid Build Coastguard Worker     if (waiting_for_completion_.timestamp == packet.timestamp) {
408*d9f75844SAndroid Build Coastguard Worker       // This can get bad if we have a lot of duplicate packets,
409*d9f75844SAndroid Build Coastguard Worker       // we will then count some packet multiple times.
410*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.frame_size += packet.sizeBytes;
411*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.latest_packet_time = now.ms();
412*d9f75844SAndroid Build Coastguard Worker     } else if (waiting_for_completion_.latest_packet_time >= 0 &&
413*d9f75844SAndroid Build Coastguard Worker                waiting_for_completion_.latest_packet_time + 2000 <= now.ms()) {
414*d9f75844SAndroid Build Coastguard Worker       // A packet should never be more than two seconds late
415*d9f75844SAndroid Build Coastguard Worker       UpdateJitterEstimate(waiting_for_completion_, true);
416*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.latest_packet_time = -1;
417*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.frame_size = 0;
418*d9f75844SAndroid Build Coastguard Worker       waiting_for_completion_.timestamp = 0;
419*d9f75844SAndroid Build Coastguard Worker     }
420*d9f75844SAndroid Build Coastguard Worker   }
421*d9f75844SAndroid Build Coastguard Worker 
422*d9f75844SAndroid Build Coastguard Worker   VCMFrameBufferStateEnum previous_state = frame->GetState();
423*d9f75844SAndroid Build Coastguard Worker   // Insert packet.
424*d9f75844SAndroid Build Coastguard Worker   FrameData frame_data;
425*d9f75844SAndroid Build Coastguard Worker   frame_data.rtt_ms = kDefaultRtt;
426*d9f75844SAndroid Build Coastguard Worker   frame_data.rolling_average_packets_per_frame = average_packets_per_frame_;
427*d9f75844SAndroid Build Coastguard Worker   VCMFrameBufferEnum buffer_state =
428*d9f75844SAndroid Build Coastguard Worker       frame->InsertPacket(packet, now.ms(), frame_data);
429*d9f75844SAndroid Build Coastguard Worker 
430*d9f75844SAndroid Build Coastguard Worker   if (buffer_state > 0) {
431*d9f75844SAndroid Build Coastguard Worker     if (first_packet_since_reset_) {
432*d9f75844SAndroid Build Coastguard Worker       latest_received_sequence_number_ = packet.seqNum;
433*d9f75844SAndroid Build Coastguard Worker       first_packet_since_reset_ = false;
434*d9f75844SAndroid Build Coastguard Worker     } else {
435*d9f75844SAndroid Build Coastguard Worker       if (IsPacketRetransmitted(packet)) {
436*d9f75844SAndroid Build Coastguard Worker         frame->IncrementNackCount();
437*d9f75844SAndroid Build Coastguard Worker       }
438*d9f75844SAndroid Build Coastguard Worker       if (!UpdateNackList(packet.seqNum) &&
439*d9f75844SAndroid Build Coastguard Worker           packet.video_header.frame_type != VideoFrameType::kVideoFrameKey) {
440*d9f75844SAndroid Build Coastguard Worker         buffer_state = kFlushIndicator;
441*d9f75844SAndroid Build Coastguard Worker       }
442*d9f75844SAndroid Build Coastguard Worker 
443*d9f75844SAndroid Build Coastguard Worker       latest_received_sequence_number_ =
444*d9f75844SAndroid Build Coastguard Worker           LatestSequenceNumber(latest_received_sequence_number_, packet.seqNum);
445*d9f75844SAndroid Build Coastguard Worker     }
446*d9f75844SAndroid Build Coastguard Worker   }
447*d9f75844SAndroid Build Coastguard Worker 
448*d9f75844SAndroid Build Coastguard Worker   // Is the frame already in the decodable list?
449*d9f75844SAndroid Build Coastguard Worker   bool continuous = IsContinuous(*frame);
450*d9f75844SAndroid Build Coastguard Worker   switch (buffer_state) {
451*d9f75844SAndroid Build Coastguard Worker     case kGeneralError:
452*d9f75844SAndroid Build Coastguard Worker     case kTimeStampError:
453*d9f75844SAndroid Build Coastguard Worker     case kSizeError: {
454*d9f75844SAndroid Build Coastguard Worker       RecycleFrameBuffer(frame);
455*d9f75844SAndroid Build Coastguard Worker       break;
456*d9f75844SAndroid Build Coastguard Worker     }
457*d9f75844SAndroid Build Coastguard Worker     case kCompleteSession: {
458*d9f75844SAndroid Build Coastguard Worker       if (previous_state != kStateComplete) {
459*d9f75844SAndroid Build Coastguard Worker         if (continuous) {
460*d9f75844SAndroid Build Coastguard Worker           // Signal that we have a complete session.
461*d9f75844SAndroid Build Coastguard Worker           frame_event_->Set();
462*d9f75844SAndroid Build Coastguard Worker         }
463*d9f75844SAndroid Build Coastguard Worker       }
464*d9f75844SAndroid Build Coastguard Worker 
465*d9f75844SAndroid Build Coastguard Worker       *retransmitted = (frame->GetNackCount() > 0);
466*d9f75844SAndroid Build Coastguard Worker       if (continuous) {
467*d9f75844SAndroid Build Coastguard Worker         decodable_frames_.InsertFrame(frame);
468*d9f75844SAndroid Build Coastguard Worker         FindAndInsertContinuousFrames(*frame);
469*d9f75844SAndroid Build Coastguard Worker       } else {
470*d9f75844SAndroid Build Coastguard Worker         incomplete_frames_.InsertFrame(frame);
471*d9f75844SAndroid Build Coastguard Worker       }
472*d9f75844SAndroid Build Coastguard Worker       break;
473*d9f75844SAndroid Build Coastguard Worker     }
474*d9f75844SAndroid Build Coastguard Worker     case kIncomplete: {
475*d9f75844SAndroid Build Coastguard Worker       if (frame->GetState() == kStateEmpty &&
476*d9f75844SAndroid Build Coastguard Worker           last_decoded_state_.UpdateEmptyFrame(frame)) {
477*d9f75844SAndroid Build Coastguard Worker         RecycleFrameBuffer(frame);
478*d9f75844SAndroid Build Coastguard Worker         return kNoError;
479*d9f75844SAndroid Build Coastguard Worker       } else {
480*d9f75844SAndroid Build Coastguard Worker         incomplete_frames_.InsertFrame(frame);
481*d9f75844SAndroid Build Coastguard Worker       }
482*d9f75844SAndroid Build Coastguard Worker       break;
483*d9f75844SAndroid Build Coastguard Worker     }
484*d9f75844SAndroid Build Coastguard Worker     case kNoError:
485*d9f75844SAndroid Build Coastguard Worker     case kOutOfBoundsPacket:
486*d9f75844SAndroid Build Coastguard Worker     case kDuplicatePacket: {
487*d9f75844SAndroid Build Coastguard Worker       // Put back the frame where it came from.
488*d9f75844SAndroid Build Coastguard Worker       if (frame_list != NULL) {
489*d9f75844SAndroid Build Coastguard Worker         frame_list->InsertFrame(frame);
490*d9f75844SAndroid Build Coastguard Worker       } else {
491*d9f75844SAndroid Build Coastguard Worker         RecycleFrameBuffer(frame);
492*d9f75844SAndroid Build Coastguard Worker       }
493*d9f75844SAndroid Build Coastguard Worker       ++num_duplicated_packets_;
494*d9f75844SAndroid Build Coastguard Worker       break;
495*d9f75844SAndroid Build Coastguard Worker     }
496*d9f75844SAndroid Build Coastguard Worker     case kFlushIndicator:
497*d9f75844SAndroid Build Coastguard Worker       RecycleFrameBuffer(frame);
498*d9f75844SAndroid Build Coastguard Worker       return kFlushIndicator;
499*d9f75844SAndroid Build Coastguard Worker     default:
500*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
501*d9f75844SAndroid Build Coastguard Worker   }
502*d9f75844SAndroid Build Coastguard Worker   return buffer_state;
503*d9f75844SAndroid Build Coastguard Worker }
504*d9f75844SAndroid Build Coastguard Worker 
IsContinuousInState(const VCMFrameBuffer & frame,const VCMDecodingState & decoding_state) const505*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::IsContinuousInState(
506*d9f75844SAndroid Build Coastguard Worker     const VCMFrameBuffer& frame,
507*d9f75844SAndroid Build Coastguard Worker     const VCMDecodingState& decoding_state) const {
508*d9f75844SAndroid Build Coastguard Worker   // Is this frame complete and continuous?
509*d9f75844SAndroid Build Coastguard Worker   return (frame.GetState() == kStateComplete) &&
510*d9f75844SAndroid Build Coastguard Worker          decoding_state.ContinuousFrame(&frame);
511*d9f75844SAndroid Build Coastguard Worker }
512*d9f75844SAndroid Build Coastguard Worker 
IsContinuous(const VCMFrameBuffer & frame) const513*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::IsContinuous(const VCMFrameBuffer& frame) const {
514*d9f75844SAndroid Build Coastguard Worker   if (IsContinuousInState(frame, last_decoded_state_)) {
515*d9f75844SAndroid Build Coastguard Worker     return true;
516*d9f75844SAndroid Build Coastguard Worker   }
517*d9f75844SAndroid Build Coastguard Worker   VCMDecodingState decoding_state;
518*d9f75844SAndroid Build Coastguard Worker   decoding_state.CopyFrom(last_decoded_state_);
519*d9f75844SAndroid Build Coastguard Worker   for (FrameList::const_iterator it = decodable_frames_.begin();
520*d9f75844SAndroid Build Coastguard Worker        it != decodable_frames_.end(); ++it) {
521*d9f75844SAndroid Build Coastguard Worker     VCMFrameBuffer* decodable_frame = it->second;
522*d9f75844SAndroid Build Coastguard Worker     if (IsNewerTimestamp(decodable_frame->Timestamp(), frame.Timestamp())) {
523*d9f75844SAndroid Build Coastguard Worker       break;
524*d9f75844SAndroid Build Coastguard Worker     }
525*d9f75844SAndroid Build Coastguard Worker     decoding_state.SetState(decodable_frame);
526*d9f75844SAndroid Build Coastguard Worker     if (IsContinuousInState(frame, decoding_state)) {
527*d9f75844SAndroid Build Coastguard Worker       return true;
528*d9f75844SAndroid Build Coastguard Worker     }
529*d9f75844SAndroid Build Coastguard Worker   }
530*d9f75844SAndroid Build Coastguard Worker   return false;
531*d9f75844SAndroid Build Coastguard Worker }
532*d9f75844SAndroid Build Coastguard Worker 
FindAndInsertContinuousFrames(const VCMFrameBuffer & new_frame)533*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::FindAndInsertContinuousFrames(
534*d9f75844SAndroid Build Coastguard Worker     const VCMFrameBuffer& new_frame) {
535*d9f75844SAndroid Build Coastguard Worker   VCMDecodingState decoding_state;
536*d9f75844SAndroid Build Coastguard Worker   decoding_state.CopyFrom(last_decoded_state_);
537*d9f75844SAndroid Build Coastguard Worker   decoding_state.SetState(&new_frame);
538*d9f75844SAndroid Build Coastguard Worker   FindAndInsertContinuousFramesWithState(decoding_state);
539*d9f75844SAndroid Build Coastguard Worker }
540*d9f75844SAndroid Build Coastguard Worker 
FindAndInsertContinuousFramesWithState(const VCMDecodingState & original_decoded_state)541*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::FindAndInsertContinuousFramesWithState(
542*d9f75844SAndroid Build Coastguard Worker     const VCMDecodingState& original_decoded_state) {
543*d9f75844SAndroid Build Coastguard Worker   // Copy original_decoded_state so we can move the state forward with each
544*d9f75844SAndroid Build Coastguard Worker   // decodable frame we find.
545*d9f75844SAndroid Build Coastguard Worker   VCMDecodingState decoding_state;
546*d9f75844SAndroid Build Coastguard Worker   decoding_state.CopyFrom(original_decoded_state);
547*d9f75844SAndroid Build Coastguard Worker 
548*d9f75844SAndroid Build Coastguard Worker   // When temporal layers are available, we search for a complete or decodable
549*d9f75844SAndroid Build Coastguard Worker   // frame until we hit one of the following:
550*d9f75844SAndroid Build Coastguard Worker   // 1. Continuous base or sync layer.
551*d9f75844SAndroid Build Coastguard Worker   // 2. The end of the list was reached.
552*d9f75844SAndroid Build Coastguard Worker   for (FrameList::iterator it = incomplete_frames_.begin();
553*d9f75844SAndroid Build Coastguard Worker        it != incomplete_frames_.end();) {
554*d9f75844SAndroid Build Coastguard Worker     VCMFrameBuffer* frame = it->second;
555*d9f75844SAndroid Build Coastguard Worker     if (IsNewerTimestamp(original_decoded_state.time_stamp(),
556*d9f75844SAndroid Build Coastguard Worker                          frame->Timestamp())) {
557*d9f75844SAndroid Build Coastguard Worker       ++it;
558*d9f75844SAndroid Build Coastguard Worker       continue;
559*d9f75844SAndroid Build Coastguard Worker     }
560*d9f75844SAndroid Build Coastguard Worker     if (IsContinuousInState(*frame, decoding_state)) {
561*d9f75844SAndroid Build Coastguard Worker       decodable_frames_.InsertFrame(frame);
562*d9f75844SAndroid Build Coastguard Worker       incomplete_frames_.erase(it++);
563*d9f75844SAndroid Build Coastguard Worker       decoding_state.SetState(frame);
564*d9f75844SAndroid Build Coastguard Worker     } else if (frame->TemporalId() <= 0) {
565*d9f75844SAndroid Build Coastguard Worker       break;
566*d9f75844SAndroid Build Coastguard Worker     } else {
567*d9f75844SAndroid Build Coastguard Worker       ++it;
568*d9f75844SAndroid Build Coastguard Worker     }
569*d9f75844SAndroid Build Coastguard Worker   }
570*d9f75844SAndroid Build Coastguard Worker }
571*d9f75844SAndroid Build Coastguard Worker 
EstimatedJitterMs()572*d9f75844SAndroid Build Coastguard Worker uint32_t VCMJitterBuffer::EstimatedJitterMs() {
573*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
574*d9f75844SAndroid Build Coastguard Worker   const double rtt_mult = 1.0f;
575*d9f75844SAndroid Build Coastguard Worker   return jitter_estimate_.GetJitterEstimate(rtt_mult, absl::nullopt).ms();
576*d9f75844SAndroid Build Coastguard Worker }
577*d9f75844SAndroid Build Coastguard Worker 
SetNackSettings(size_t max_nack_list_size,int max_packet_age_to_nack,int max_incomplete_time_ms)578*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::SetNackSettings(size_t max_nack_list_size,
579*d9f75844SAndroid Build Coastguard Worker                                       int max_packet_age_to_nack,
580*d9f75844SAndroid Build Coastguard Worker                                       int max_incomplete_time_ms) {
581*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
582*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(max_packet_age_to_nack, 0);
583*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(max_incomplete_time_ms_, 0);
584*d9f75844SAndroid Build Coastguard Worker   max_nack_list_size_ = max_nack_list_size;
585*d9f75844SAndroid Build Coastguard Worker   max_packet_age_to_nack_ = max_packet_age_to_nack;
586*d9f75844SAndroid Build Coastguard Worker   max_incomplete_time_ms_ = max_incomplete_time_ms;
587*d9f75844SAndroid Build Coastguard Worker }
588*d9f75844SAndroid Build Coastguard Worker 
NonContinuousOrIncompleteDuration()589*d9f75844SAndroid Build Coastguard Worker int VCMJitterBuffer::NonContinuousOrIncompleteDuration() {
590*d9f75844SAndroid Build Coastguard Worker   if (incomplete_frames_.empty()) {
591*d9f75844SAndroid Build Coastguard Worker     return 0;
592*d9f75844SAndroid Build Coastguard Worker   }
593*d9f75844SAndroid Build Coastguard Worker   uint32_t start_timestamp = incomplete_frames_.Front()->Timestamp();
594*d9f75844SAndroid Build Coastguard Worker   if (!decodable_frames_.empty()) {
595*d9f75844SAndroid Build Coastguard Worker     start_timestamp = decodable_frames_.Back()->Timestamp();
596*d9f75844SAndroid Build Coastguard Worker   }
597*d9f75844SAndroid Build Coastguard Worker   return incomplete_frames_.Back()->Timestamp() - start_timestamp;
598*d9f75844SAndroid Build Coastguard Worker }
599*d9f75844SAndroid Build Coastguard Worker 
EstimatedLowSequenceNumber(const VCMFrameBuffer & frame) const600*d9f75844SAndroid Build Coastguard Worker uint16_t VCMJitterBuffer::EstimatedLowSequenceNumber(
601*d9f75844SAndroid Build Coastguard Worker     const VCMFrameBuffer& frame) const {
602*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_GE(frame.GetLowSeqNum(), 0);
603*d9f75844SAndroid Build Coastguard Worker   if (frame.HaveFirstPacket())
604*d9f75844SAndroid Build Coastguard Worker     return frame.GetLowSeqNum();
605*d9f75844SAndroid Build Coastguard Worker 
606*d9f75844SAndroid Build Coastguard Worker   // This estimate is not accurate if more than one packet with lower sequence
607*d9f75844SAndroid Build Coastguard Worker   // number is lost.
608*d9f75844SAndroid Build Coastguard Worker   return frame.GetLowSeqNum() - 1;
609*d9f75844SAndroid Build Coastguard Worker }
610*d9f75844SAndroid Build Coastguard Worker 
GetNackList(bool * request_key_frame)611*d9f75844SAndroid Build Coastguard Worker std::vector<uint16_t> VCMJitterBuffer::GetNackList(bool* request_key_frame) {
612*d9f75844SAndroid Build Coastguard Worker   MutexLock lock(&mutex_);
613*d9f75844SAndroid Build Coastguard Worker   *request_key_frame = false;
614*d9f75844SAndroid Build Coastguard Worker   if (last_decoded_state_.in_initial_state()) {
615*d9f75844SAndroid Build Coastguard Worker     VCMFrameBuffer* next_frame = NextFrame();
616*d9f75844SAndroid Build Coastguard Worker     const bool first_frame_is_key =
617*d9f75844SAndroid Build Coastguard Worker         next_frame &&
618*d9f75844SAndroid Build Coastguard Worker         next_frame->FrameType() == VideoFrameType::kVideoFrameKey &&
619*d9f75844SAndroid Build Coastguard Worker         next_frame->HaveFirstPacket();
620*d9f75844SAndroid Build Coastguard Worker     if (!first_frame_is_key) {
621*d9f75844SAndroid Build Coastguard Worker       bool have_non_empty_frame =
622*d9f75844SAndroid Build Coastguard Worker           decodable_frames_.end() != find_if(decodable_frames_.begin(),
623*d9f75844SAndroid Build Coastguard Worker                                              decodable_frames_.end(),
624*d9f75844SAndroid Build Coastguard Worker                                              HasNonEmptyState);
625*d9f75844SAndroid Build Coastguard Worker       if (!have_non_empty_frame) {
626*d9f75844SAndroid Build Coastguard Worker         have_non_empty_frame =
627*d9f75844SAndroid Build Coastguard Worker             incomplete_frames_.end() != find_if(incomplete_frames_.begin(),
628*d9f75844SAndroid Build Coastguard Worker                                                 incomplete_frames_.end(),
629*d9f75844SAndroid Build Coastguard Worker                                                 HasNonEmptyState);
630*d9f75844SAndroid Build Coastguard Worker       }
631*d9f75844SAndroid Build Coastguard Worker       bool found_key_frame = RecycleFramesUntilKeyFrame();
632*d9f75844SAndroid Build Coastguard Worker       if (!found_key_frame) {
633*d9f75844SAndroid Build Coastguard Worker         *request_key_frame = have_non_empty_frame;
634*d9f75844SAndroid Build Coastguard Worker         return std::vector<uint16_t>();
635*d9f75844SAndroid Build Coastguard Worker       }
636*d9f75844SAndroid Build Coastguard Worker     }
637*d9f75844SAndroid Build Coastguard Worker   }
638*d9f75844SAndroid Build Coastguard Worker   if (TooLargeNackList()) {
639*d9f75844SAndroid Build Coastguard Worker     *request_key_frame = !HandleTooLargeNackList();
640*d9f75844SAndroid Build Coastguard Worker   }
641*d9f75844SAndroid Build Coastguard Worker   if (max_incomplete_time_ms_ > 0) {
642*d9f75844SAndroid Build Coastguard Worker     int non_continuous_incomplete_duration =
643*d9f75844SAndroid Build Coastguard Worker         NonContinuousOrIncompleteDuration();
644*d9f75844SAndroid Build Coastguard Worker     if (non_continuous_incomplete_duration > 90 * max_incomplete_time_ms_) {
645*d9f75844SAndroid Build Coastguard Worker       RTC_LOG_F(LS_WARNING) << "Too long non-decodable duration: "
646*d9f75844SAndroid Build Coastguard Worker                             << non_continuous_incomplete_duration << " > "
647*d9f75844SAndroid Build Coastguard Worker                             << 90 * max_incomplete_time_ms_;
648*d9f75844SAndroid Build Coastguard Worker       FrameList::reverse_iterator rit = find_if(
649*d9f75844SAndroid Build Coastguard Worker           incomplete_frames_.rbegin(), incomplete_frames_.rend(), IsKeyFrame);
650*d9f75844SAndroid Build Coastguard Worker       if (rit == incomplete_frames_.rend()) {
651*d9f75844SAndroid Build Coastguard Worker         // Request a key frame if we don't have one already.
652*d9f75844SAndroid Build Coastguard Worker         *request_key_frame = true;
653*d9f75844SAndroid Build Coastguard Worker         return std::vector<uint16_t>();
654*d9f75844SAndroid Build Coastguard Worker       } else {
655*d9f75844SAndroid Build Coastguard Worker         // Skip to the last key frame. If it's incomplete we will start
656*d9f75844SAndroid Build Coastguard Worker         // NACKing it.
657*d9f75844SAndroid Build Coastguard Worker         // Note that the estimated low sequence number is correct for VP8
658*d9f75844SAndroid Build Coastguard Worker         // streams because only the first packet of a key frame is marked.
659*d9f75844SAndroid Build Coastguard Worker         last_decoded_state_.Reset();
660*d9f75844SAndroid Build Coastguard Worker         DropPacketsFromNackList(EstimatedLowSequenceNumber(*rit->second));
661*d9f75844SAndroid Build Coastguard Worker       }
662*d9f75844SAndroid Build Coastguard Worker     }
663*d9f75844SAndroid Build Coastguard Worker   }
664*d9f75844SAndroid Build Coastguard Worker   std::vector<uint16_t> nack_list(missing_sequence_numbers_.begin(),
665*d9f75844SAndroid Build Coastguard Worker                                   missing_sequence_numbers_.end());
666*d9f75844SAndroid Build Coastguard Worker   return nack_list;
667*d9f75844SAndroid Build Coastguard Worker }
668*d9f75844SAndroid Build Coastguard Worker 
NextFrame() const669*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer* VCMJitterBuffer::NextFrame() const {
670*d9f75844SAndroid Build Coastguard Worker   if (!decodable_frames_.empty())
671*d9f75844SAndroid Build Coastguard Worker     return decodable_frames_.Front();
672*d9f75844SAndroid Build Coastguard Worker   if (!incomplete_frames_.empty())
673*d9f75844SAndroid Build Coastguard Worker     return incomplete_frames_.Front();
674*d9f75844SAndroid Build Coastguard Worker   return NULL;
675*d9f75844SAndroid Build Coastguard Worker }
676*d9f75844SAndroid Build Coastguard Worker 
UpdateNackList(uint16_t sequence_number)677*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::UpdateNackList(uint16_t sequence_number) {
678*d9f75844SAndroid Build Coastguard Worker   // Make sure we don't add packets which are already too old to be decoded.
679*d9f75844SAndroid Build Coastguard Worker   if (!last_decoded_state_.in_initial_state()) {
680*d9f75844SAndroid Build Coastguard Worker     latest_received_sequence_number_ = LatestSequenceNumber(
681*d9f75844SAndroid Build Coastguard Worker         latest_received_sequence_number_, last_decoded_state_.sequence_num());
682*d9f75844SAndroid Build Coastguard Worker   }
683*d9f75844SAndroid Build Coastguard Worker   if (IsNewerSequenceNumber(sequence_number,
684*d9f75844SAndroid Build Coastguard Worker                             latest_received_sequence_number_)) {
685*d9f75844SAndroid Build Coastguard Worker     // Push any missing sequence numbers to the NACK list.
686*d9f75844SAndroid Build Coastguard Worker     for (uint16_t i = latest_received_sequence_number_ + 1;
687*d9f75844SAndroid Build Coastguard Worker          IsNewerSequenceNumber(sequence_number, i); ++i) {
688*d9f75844SAndroid Build Coastguard Worker       missing_sequence_numbers_.insert(missing_sequence_numbers_.end(), i);
689*d9f75844SAndroid Build Coastguard Worker     }
690*d9f75844SAndroid Build Coastguard Worker     if (TooLargeNackList() && !HandleTooLargeNackList()) {
691*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING) << "Requesting key frame due to too large NACK list.";
692*d9f75844SAndroid Build Coastguard Worker       return false;
693*d9f75844SAndroid Build Coastguard Worker     }
694*d9f75844SAndroid Build Coastguard Worker     if (MissingTooOldPacket(sequence_number) &&
695*d9f75844SAndroid Build Coastguard Worker         !HandleTooOldPackets(sequence_number)) {
696*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_WARNING)
697*d9f75844SAndroid Build Coastguard Worker           << "Requesting key frame due to missing too old packets";
698*d9f75844SAndroid Build Coastguard Worker       return false;
699*d9f75844SAndroid Build Coastguard Worker     }
700*d9f75844SAndroid Build Coastguard Worker   } else {
701*d9f75844SAndroid Build Coastguard Worker     missing_sequence_numbers_.erase(sequence_number);
702*d9f75844SAndroid Build Coastguard Worker   }
703*d9f75844SAndroid Build Coastguard Worker   return true;
704*d9f75844SAndroid Build Coastguard Worker }
705*d9f75844SAndroid Build Coastguard Worker 
TooLargeNackList() const706*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::TooLargeNackList() const {
707*d9f75844SAndroid Build Coastguard Worker   return missing_sequence_numbers_.size() > max_nack_list_size_;
708*d9f75844SAndroid Build Coastguard Worker }
709*d9f75844SAndroid Build Coastguard Worker 
HandleTooLargeNackList()710*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::HandleTooLargeNackList() {
711*d9f75844SAndroid Build Coastguard Worker   // Recycle frames until the NACK list is small enough. It is likely cheaper to
712*d9f75844SAndroid Build Coastguard Worker   // request a key frame than to retransmit this many missing packets.
713*d9f75844SAndroid Build Coastguard Worker   RTC_LOG_F(LS_WARNING) << "NACK list has grown too large: "
714*d9f75844SAndroid Build Coastguard Worker                         << missing_sequence_numbers_.size() << " > "
715*d9f75844SAndroid Build Coastguard Worker                         << max_nack_list_size_;
716*d9f75844SAndroid Build Coastguard Worker   bool key_frame_found = false;
717*d9f75844SAndroid Build Coastguard Worker   while (TooLargeNackList()) {
718*d9f75844SAndroid Build Coastguard Worker     key_frame_found = RecycleFramesUntilKeyFrame();
719*d9f75844SAndroid Build Coastguard Worker   }
720*d9f75844SAndroid Build Coastguard Worker   return key_frame_found;
721*d9f75844SAndroid Build Coastguard Worker }
722*d9f75844SAndroid Build Coastguard Worker 
MissingTooOldPacket(uint16_t latest_sequence_number) const723*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::MissingTooOldPacket(
724*d9f75844SAndroid Build Coastguard Worker     uint16_t latest_sequence_number) const {
725*d9f75844SAndroid Build Coastguard Worker   if (missing_sequence_numbers_.empty()) {
726*d9f75844SAndroid Build Coastguard Worker     return false;
727*d9f75844SAndroid Build Coastguard Worker   }
728*d9f75844SAndroid Build Coastguard Worker   const uint16_t age_of_oldest_missing_packet =
729*d9f75844SAndroid Build Coastguard Worker       latest_sequence_number - *missing_sequence_numbers_.begin();
730*d9f75844SAndroid Build Coastguard Worker   // Recycle frames if the NACK list contains too old sequence numbers as
731*d9f75844SAndroid Build Coastguard Worker   // the packets may have already been dropped by the sender.
732*d9f75844SAndroid Build Coastguard Worker   return age_of_oldest_missing_packet > max_packet_age_to_nack_;
733*d9f75844SAndroid Build Coastguard Worker }
734*d9f75844SAndroid Build Coastguard Worker 
HandleTooOldPackets(uint16_t latest_sequence_number)735*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::HandleTooOldPackets(uint16_t latest_sequence_number) {
736*d9f75844SAndroid Build Coastguard Worker   bool key_frame_found = false;
737*d9f75844SAndroid Build Coastguard Worker   const uint16_t age_of_oldest_missing_packet =
738*d9f75844SAndroid Build Coastguard Worker       latest_sequence_number - *missing_sequence_numbers_.begin();
739*d9f75844SAndroid Build Coastguard Worker   RTC_LOG_F(LS_WARNING) << "NACK list contains too old sequence numbers: "
740*d9f75844SAndroid Build Coastguard Worker                         << age_of_oldest_missing_packet << " > "
741*d9f75844SAndroid Build Coastguard Worker                         << max_packet_age_to_nack_;
742*d9f75844SAndroid Build Coastguard Worker   while (MissingTooOldPacket(latest_sequence_number)) {
743*d9f75844SAndroid Build Coastguard Worker     key_frame_found = RecycleFramesUntilKeyFrame();
744*d9f75844SAndroid Build Coastguard Worker   }
745*d9f75844SAndroid Build Coastguard Worker   return key_frame_found;
746*d9f75844SAndroid Build Coastguard Worker }
747*d9f75844SAndroid Build Coastguard Worker 
DropPacketsFromNackList(uint16_t last_decoded_sequence_number)748*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::DropPacketsFromNackList(
749*d9f75844SAndroid Build Coastguard Worker     uint16_t last_decoded_sequence_number) {
750*d9f75844SAndroid Build Coastguard Worker   // Erase all sequence numbers from the NACK list which we won't need any
751*d9f75844SAndroid Build Coastguard Worker   // longer.
752*d9f75844SAndroid Build Coastguard Worker   missing_sequence_numbers_.erase(
753*d9f75844SAndroid Build Coastguard Worker       missing_sequence_numbers_.begin(),
754*d9f75844SAndroid Build Coastguard Worker       missing_sequence_numbers_.upper_bound(last_decoded_sequence_number));
755*d9f75844SAndroid Build Coastguard Worker }
756*d9f75844SAndroid Build Coastguard Worker 
GetEmptyFrame()757*d9f75844SAndroid Build Coastguard Worker VCMFrameBuffer* VCMJitterBuffer::GetEmptyFrame() {
758*d9f75844SAndroid Build Coastguard Worker   if (free_frames_.empty()) {
759*d9f75844SAndroid Build Coastguard Worker     if (!TryToIncreaseJitterBufferSize()) {
760*d9f75844SAndroid Build Coastguard Worker       return NULL;
761*d9f75844SAndroid Build Coastguard Worker     }
762*d9f75844SAndroid Build Coastguard Worker   }
763*d9f75844SAndroid Build Coastguard Worker   VCMFrameBuffer* frame = free_frames_.front();
764*d9f75844SAndroid Build Coastguard Worker   free_frames_.pop_front();
765*d9f75844SAndroid Build Coastguard Worker   return frame;
766*d9f75844SAndroid Build Coastguard Worker }
767*d9f75844SAndroid Build Coastguard Worker 
TryToIncreaseJitterBufferSize()768*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::TryToIncreaseJitterBufferSize() {
769*d9f75844SAndroid Build Coastguard Worker   if (max_number_of_frames_ >= kMaxNumberOfFrames)
770*d9f75844SAndroid Build Coastguard Worker     return false;
771*d9f75844SAndroid Build Coastguard Worker   free_frames_.push_back(new VCMFrameBuffer());
772*d9f75844SAndroid Build Coastguard Worker   ++max_number_of_frames_;
773*d9f75844SAndroid Build Coastguard Worker   return true;
774*d9f75844SAndroid Build Coastguard Worker }
775*d9f75844SAndroid Build Coastguard Worker 
776*d9f75844SAndroid Build Coastguard Worker // Recycle oldest frames up to a key frame, used if jitter buffer is completely
777*d9f75844SAndroid Build Coastguard Worker // full.
RecycleFramesUntilKeyFrame()778*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::RecycleFramesUntilKeyFrame() {
779*d9f75844SAndroid Build Coastguard Worker   // First release incomplete frames, and only release decodable frames if there
780*d9f75844SAndroid Build Coastguard Worker   // are no incomplete ones.
781*d9f75844SAndroid Build Coastguard Worker   FrameList::iterator key_frame_it;
782*d9f75844SAndroid Build Coastguard Worker   bool key_frame_found = false;
783*d9f75844SAndroid Build Coastguard Worker   int dropped_frames = 0;
784*d9f75844SAndroid Build Coastguard Worker   dropped_frames += incomplete_frames_.RecycleFramesUntilKeyFrame(
785*d9f75844SAndroid Build Coastguard Worker       &key_frame_it, &free_frames_);
786*d9f75844SAndroid Build Coastguard Worker   key_frame_found = key_frame_it != incomplete_frames_.end();
787*d9f75844SAndroid Build Coastguard Worker   if (dropped_frames == 0) {
788*d9f75844SAndroid Build Coastguard Worker     dropped_frames += decodable_frames_.RecycleFramesUntilKeyFrame(
789*d9f75844SAndroid Build Coastguard Worker         &key_frame_it, &free_frames_);
790*d9f75844SAndroid Build Coastguard Worker     key_frame_found = key_frame_it != decodable_frames_.end();
791*d9f75844SAndroid Build Coastguard Worker   }
792*d9f75844SAndroid Build Coastguard Worker   if (key_frame_found) {
793*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << "Found key frame while dropping frames.";
794*d9f75844SAndroid Build Coastguard Worker     // Reset last decoded state to make sure the next frame decoded is a key
795*d9f75844SAndroid Build Coastguard Worker     // frame, and start NACKing from here.
796*d9f75844SAndroid Build Coastguard Worker     last_decoded_state_.Reset();
797*d9f75844SAndroid Build Coastguard Worker     DropPacketsFromNackList(EstimatedLowSequenceNumber(*key_frame_it->second));
798*d9f75844SAndroid Build Coastguard Worker   } else if (decodable_frames_.empty()) {
799*d9f75844SAndroid Build Coastguard Worker     // All frames dropped. Reset the decoding state and clear missing sequence
800*d9f75844SAndroid Build Coastguard Worker     // numbers as we're starting fresh.
801*d9f75844SAndroid Build Coastguard Worker     last_decoded_state_.Reset();
802*d9f75844SAndroid Build Coastguard Worker     missing_sequence_numbers_.clear();
803*d9f75844SAndroid Build Coastguard Worker   }
804*d9f75844SAndroid Build Coastguard Worker   return key_frame_found;
805*d9f75844SAndroid Build Coastguard Worker }
806*d9f75844SAndroid Build Coastguard Worker 
UpdateAveragePacketsPerFrame(int current_number_packets)807*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::UpdateAveragePacketsPerFrame(int current_number_packets) {
808*d9f75844SAndroid Build Coastguard Worker   if (frame_counter_ > kFastConvergeThreshold) {
809*d9f75844SAndroid Build Coastguard Worker     average_packets_per_frame_ =
810*d9f75844SAndroid Build Coastguard Worker         average_packets_per_frame_ * (1 - kNormalConvergeMultiplier) +
811*d9f75844SAndroid Build Coastguard Worker         current_number_packets * kNormalConvergeMultiplier;
812*d9f75844SAndroid Build Coastguard Worker   } else if (frame_counter_ > 0) {
813*d9f75844SAndroid Build Coastguard Worker     average_packets_per_frame_ =
814*d9f75844SAndroid Build Coastguard Worker         average_packets_per_frame_ * (1 - kFastConvergeMultiplier) +
815*d9f75844SAndroid Build Coastguard Worker         current_number_packets * kFastConvergeMultiplier;
816*d9f75844SAndroid Build Coastguard Worker     frame_counter_++;
817*d9f75844SAndroid Build Coastguard Worker   } else {
818*d9f75844SAndroid Build Coastguard Worker     average_packets_per_frame_ = current_number_packets;
819*d9f75844SAndroid Build Coastguard Worker     frame_counter_++;
820*d9f75844SAndroid Build Coastguard Worker   }
821*d9f75844SAndroid Build Coastguard Worker }
822*d9f75844SAndroid Build Coastguard Worker 
823*d9f75844SAndroid Build Coastguard Worker // Must be called under the critical section `mutex_`.
CleanUpOldOrEmptyFrames()824*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::CleanUpOldOrEmptyFrames() {
825*d9f75844SAndroid Build Coastguard Worker   decodable_frames_.CleanUpOldOrEmptyFrames(&last_decoded_state_,
826*d9f75844SAndroid Build Coastguard Worker                                             &free_frames_);
827*d9f75844SAndroid Build Coastguard Worker   incomplete_frames_.CleanUpOldOrEmptyFrames(&last_decoded_state_,
828*d9f75844SAndroid Build Coastguard Worker                                              &free_frames_);
829*d9f75844SAndroid Build Coastguard Worker   if (!last_decoded_state_.in_initial_state()) {
830*d9f75844SAndroid Build Coastguard Worker     DropPacketsFromNackList(last_decoded_state_.sequence_num());
831*d9f75844SAndroid Build Coastguard Worker   }
832*d9f75844SAndroid Build Coastguard Worker }
833*d9f75844SAndroid Build Coastguard Worker 
834*d9f75844SAndroid Build Coastguard Worker // Must be called from within `mutex_`.
IsPacketRetransmitted(const VCMPacket & packet) const835*d9f75844SAndroid Build Coastguard Worker bool VCMJitterBuffer::IsPacketRetransmitted(const VCMPacket& packet) const {
836*d9f75844SAndroid Build Coastguard Worker   return missing_sequence_numbers_.find(packet.seqNum) !=
837*d9f75844SAndroid Build Coastguard Worker          missing_sequence_numbers_.end();
838*d9f75844SAndroid Build Coastguard Worker }
839*d9f75844SAndroid Build Coastguard Worker 
840*d9f75844SAndroid Build Coastguard Worker // Must be called under the critical section `mutex_`. Should never be
841*d9f75844SAndroid Build Coastguard Worker // called with retransmitted frames, they must be filtered out before this
842*d9f75844SAndroid Build Coastguard Worker // function is called.
UpdateJitterEstimate(const VCMJitterSample & sample,bool incomplete_frame)843*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::UpdateJitterEstimate(const VCMJitterSample& sample,
844*d9f75844SAndroid Build Coastguard Worker                                            bool incomplete_frame) {
845*d9f75844SAndroid Build Coastguard Worker   if (sample.latest_packet_time == -1) {
846*d9f75844SAndroid Build Coastguard Worker     return;
847*d9f75844SAndroid Build Coastguard Worker   }
848*d9f75844SAndroid Build Coastguard Worker   UpdateJitterEstimate(sample.latest_packet_time, sample.timestamp,
849*d9f75844SAndroid Build Coastguard Worker                        sample.frame_size, incomplete_frame);
850*d9f75844SAndroid Build Coastguard Worker }
851*d9f75844SAndroid Build Coastguard Worker 
852*d9f75844SAndroid Build Coastguard Worker // Must be called under the critical section mutex_. Should never be
853*d9f75844SAndroid Build Coastguard Worker // called with retransmitted frames, they must be filtered out before this
854*d9f75844SAndroid Build Coastguard Worker // function is called.
UpdateJitterEstimate(const VCMFrameBuffer & frame,bool incomplete_frame)855*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::UpdateJitterEstimate(const VCMFrameBuffer& frame,
856*d9f75844SAndroid Build Coastguard Worker                                            bool incomplete_frame) {
857*d9f75844SAndroid Build Coastguard Worker   if (frame.LatestPacketTimeMs() == -1) {
858*d9f75844SAndroid Build Coastguard Worker     return;
859*d9f75844SAndroid Build Coastguard Worker   }
860*d9f75844SAndroid Build Coastguard Worker   // No retransmitted frames should be a part of the jitter
861*d9f75844SAndroid Build Coastguard Worker   // estimate.
862*d9f75844SAndroid Build Coastguard Worker   UpdateJitterEstimate(frame.LatestPacketTimeMs(), frame.Timestamp(),
863*d9f75844SAndroid Build Coastguard Worker                        frame.size(), incomplete_frame);
864*d9f75844SAndroid Build Coastguard Worker }
865*d9f75844SAndroid Build Coastguard Worker 
866*d9f75844SAndroid Build Coastguard Worker // Must be called under the critical section `mutex_`. Should never be
867*d9f75844SAndroid Build Coastguard Worker // called with retransmitted frames, they must be filtered out before this
868*d9f75844SAndroid Build Coastguard Worker // function is called.
UpdateJitterEstimate(int64_t latest_packet_time_ms,uint32_t timestamp,unsigned int frame_size,bool)869*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::UpdateJitterEstimate(int64_t latest_packet_time_ms,
870*d9f75844SAndroid Build Coastguard Worker                                            uint32_t timestamp,
871*d9f75844SAndroid Build Coastguard Worker                                            unsigned int frame_size,
872*d9f75844SAndroid Build Coastguard Worker                                            bool /*incomplete_frame*/) {
873*d9f75844SAndroid Build Coastguard Worker   if (latest_packet_time_ms == -1) {
874*d9f75844SAndroid Build Coastguard Worker     return;
875*d9f75844SAndroid Build Coastguard Worker   }
876*d9f75844SAndroid Build Coastguard Worker   auto frame_delay = inter_frame_delay_.CalculateDelay(
877*d9f75844SAndroid Build Coastguard Worker       timestamp, Timestamp::Millis(latest_packet_time_ms));
878*d9f75844SAndroid Build Coastguard Worker 
879*d9f75844SAndroid Build Coastguard Worker   bool not_reordered = frame_delay.has_value();
880*d9f75844SAndroid Build Coastguard Worker   // Filter out frames which have been reordered in time by the network
881*d9f75844SAndroid Build Coastguard Worker   if (not_reordered) {
882*d9f75844SAndroid Build Coastguard Worker     // Update the jitter estimate with the new samples
883*d9f75844SAndroid Build Coastguard Worker     jitter_estimate_.UpdateEstimate(*frame_delay, DataSize::Bytes(frame_size));
884*d9f75844SAndroid Build Coastguard Worker   }
885*d9f75844SAndroid Build Coastguard Worker }
886*d9f75844SAndroid Build Coastguard Worker 
RecycleFrameBuffer(VCMFrameBuffer * frame)887*d9f75844SAndroid Build Coastguard Worker void VCMJitterBuffer::RecycleFrameBuffer(VCMFrameBuffer* frame) {
888*d9f75844SAndroid Build Coastguard Worker   frame->Reset();
889*d9f75844SAndroid Build Coastguard Worker   free_frames_.push_back(frame);
890*d9f75844SAndroid Build Coastguard Worker }
891*d9f75844SAndroid Build Coastguard Worker 
892*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
893