1 /*
2  *  Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "modules/video_coding/frame_buffer2.h"
12 
13 #include <algorithm>
14 #include <cstring>
15 #include <limits>
16 #include <memory>
17 #include <vector>
18 
19 #include "modules/video_coding/frame_object.h"
20 #include "modules/video_coding/jitter_estimator.h"
21 #include "modules/video_coding/timing.h"
22 #include "rtc_base/numerics/sequence_number_util.h"
23 #include "rtc_base/platform_thread.h"
24 #include "rtc_base/random.h"
25 #include "system_wrappers/include/clock.h"
26 #include "test/field_trial.h"
27 #include "test/gmock.h"
28 #include "test/gtest.h"
29 #include "test/time_controller/simulated_time_controller.h"
30 
31 using ::testing::_;
32 using ::testing::Return;
33 
34 namespace webrtc {
35 namespace video_coding {
36 
37 class VCMTimingFake : public VCMTiming {
38  public:
VCMTimingFake(Clock * clock)39   explicit VCMTimingFake(Clock* clock) : VCMTiming(clock) {}
40 
RenderTimeMs(uint32_t frame_timestamp,int64_t now_ms) const41   int64_t RenderTimeMs(uint32_t frame_timestamp,
42                        int64_t now_ms) const override {
43     if (last_ms_ == -1) {
44       last_ms_ = now_ms + kDelayMs;
45       last_timestamp_ = frame_timestamp;
46     }
47 
48     uint32_t diff = MinDiff(frame_timestamp, last_timestamp_);
49     if (AheadOf(frame_timestamp, last_timestamp_))
50       last_ms_ += diff / 90;
51     else
52       last_ms_ -= diff / 90;
53 
54     last_timestamp_ = frame_timestamp;
55     return last_ms_;
56   }
57 
MaxWaitingTime(int64_t render_time_ms,int64_t now_ms) const58   int64_t MaxWaitingTime(int64_t render_time_ms,
59                          int64_t now_ms) const override {
60     return render_time_ms - now_ms - kDecodeTime;
61   }
62 
GetTimings(int * max_decode_ms,int * current_delay_ms,int * target_delay_ms,int * jitter_buffer_ms,int * min_playout_delay_ms,int * render_delay_ms) const63   bool GetTimings(int* max_decode_ms,
64                   int* current_delay_ms,
65                   int* target_delay_ms,
66                   int* jitter_buffer_ms,
67                   int* min_playout_delay_ms,
68                   int* render_delay_ms) const override {
69     return true;
70   }
71 
GetCurrentJitter()72   int GetCurrentJitter() {
73     int max_decode_ms;
74     int current_delay_ms;
75     int target_delay_ms;
76     int jitter_buffer_ms;
77     int min_playout_delay_ms;
78     int render_delay_ms;
79     VCMTiming::GetTimings(&max_decode_ms, &current_delay_ms, &target_delay_ms,
80                           &jitter_buffer_ms, &min_playout_delay_ms,
81                           &render_delay_ms);
82     return jitter_buffer_ms;
83   }
84 
85  private:
86   static constexpr int kDelayMs = 50;
87   static constexpr int kDecodeTime = kDelayMs / 2;
88   mutable uint32_t last_timestamp_ = 0;
89   mutable int64_t last_ms_ = -1;
90 };
91 
92 class FrameObjectFake : public EncodedFrame {
93  public:
ReceivedTime() const94   int64_t ReceivedTime() const override { return 0; }
95 
RenderTime() const96   int64_t RenderTime() const override { return _renderTimeMs; }
97 
delayed_by_retransmission() const98   bool delayed_by_retransmission() const override {
99     return delayed_by_retransmission_;
100   }
set_delayed_by_retransmission(bool delayed)101   void set_delayed_by_retransmission(bool delayed) {
102     delayed_by_retransmission_ = delayed;
103   }
104 
105  private:
106   bool delayed_by_retransmission_ = false;
107 };
108 
109 class VCMReceiveStatisticsCallbackMock : public VCMReceiveStatisticsCallback {
110  public:
111   MOCK_METHOD(void,
112               OnCompleteFrame,
113               (bool is_keyframe,
114                size_t size_bytes,
115                VideoContentType content_type),
116               (override));
117   MOCK_METHOD(void, OnDroppedFrames, (uint32_t frames_dropped), (override));
118   MOCK_METHOD(void,
119               OnFrameBufferTimingsUpdated,
120               (int max_decode_ms,
121                int current_delay_ms,
122                int target_delay_ms,
123                int jitter_buffer_ms,
124                int min_playout_delay_ms,
125                int render_delay_ms),
126               (override));
127   MOCK_METHOD(void,
128               OnTimingFrameInfoUpdated,
129               (const TimingFrameInfo& info),
130               (override));
131 };
132 
133 class TestFrameBuffer2 : public ::testing::Test {
134  protected:
135   static constexpr int kMaxReferences = 5;
136   static constexpr int kFps1 = 1000;
137   static constexpr int kFps10 = kFps1 / 10;
138   static constexpr int kFps20 = kFps1 / 20;
139   static constexpr size_t kFrameSize = 10;
140 
TestFrameBuffer2()141   TestFrameBuffer2()
142       : trial_("WebRTC-AddRttToPlayoutDelay/Enabled/"),
143         time_controller_(Timestamp::Seconds(0)),
144         time_task_queue_(
145             time_controller_.GetTaskQueueFactory()->CreateTaskQueue(
146                 "extract queue",
147                 TaskQueueFactory::Priority::NORMAL)),
148         timing_(time_controller_.GetClock()),
149         buffer_(new FrameBuffer(time_controller_.GetClock(),
150                                 &timing_,
151                                 &stats_callback_)),
152         rand_(0x34678213) {}
153 
154   template <typename... T>
CreateFrame(uint16_t picture_id,uint8_t spatial_layer,int64_t ts_ms,bool last_spatial_layer,size_t frame_size_bytes,T...refs)155   std::unique_ptr<FrameObjectFake> CreateFrame(uint16_t picture_id,
156                                                uint8_t spatial_layer,
157                                                int64_t ts_ms,
158                                                bool last_spatial_layer,
159                                                size_t frame_size_bytes,
160                                                T... refs) {
161     static_assert(sizeof...(refs) <= kMaxReferences,
162                   "To many references specified for EncodedFrame.");
163     std::array<uint16_t, sizeof...(refs)> references = {
164         {rtc::checked_cast<uint16_t>(refs)...}};
165 
166     auto frame = std::make_unique<FrameObjectFake>();
167     frame->SetId(picture_id);
168     frame->SetSpatialIndex(spatial_layer);
169     frame->SetTimestamp(ts_ms * 90);
170     frame->num_references = references.size();
171     frame->is_last_spatial_layer = last_spatial_layer;
172     // Add some data to buffer.
173     frame->SetEncodedData(EncodedImageBuffer::Create(frame_size_bytes));
174     for (size_t r = 0; r < references.size(); ++r)
175       frame->references[r] = references[r];
176     return frame;
177   }
178 
179   template <typename... T>
InsertFrame(uint16_t picture_id,uint8_t spatial_layer,int64_t ts_ms,bool last_spatial_layer,size_t frame_size_bytes,T...refs)180   int InsertFrame(uint16_t picture_id,
181                   uint8_t spatial_layer,
182                   int64_t ts_ms,
183                   bool last_spatial_layer,
184                   size_t frame_size_bytes,
185                   T... refs) {
186     return buffer_->InsertFrame(CreateFrame(picture_id, spatial_layer, ts_ms,
187                                             last_spatial_layer,
188                                             frame_size_bytes, refs...));
189   }
190 
InsertNackedFrame(uint16_t picture_id,int64_t ts_ms)191   int InsertNackedFrame(uint16_t picture_id, int64_t ts_ms) {
192     std::unique_ptr<FrameObjectFake> frame =
193         CreateFrame(picture_id, 0, ts_ms, true, kFrameSize);
194     frame->set_delayed_by_retransmission(true);
195     return buffer_->InsertFrame(std::move(frame));
196   }
197 
ExtractFrame(int64_t max_wait_time=0,bool keyframe_required=false)198   void ExtractFrame(int64_t max_wait_time = 0, bool keyframe_required = false) {
199     time_task_queue_.PostTask([this, max_wait_time, keyframe_required]() {
200       buffer_->NextFrame(
201           max_wait_time, keyframe_required, &time_task_queue_,
202           [this](std::unique_ptr<EncodedFrame> frame,
203                  video_coding::FrameBuffer::ReturnReason reason) {
204             if (reason != FrameBuffer::ReturnReason::kStopped) {
205               frames_.emplace_back(std::move(frame));
206             }
207           });
208     });
209     if (max_wait_time == 0) {
210       time_controller_.AdvanceTime(TimeDelta::Millis(0));
211     }
212   }
213 
CheckFrame(size_t index,int picture_id,int spatial_layer)214   void CheckFrame(size_t index, int picture_id, int spatial_layer) {
215     ASSERT_LT(index, frames_.size());
216     ASSERT_TRUE(frames_[index]);
217     ASSERT_EQ(picture_id, frames_[index]->Id());
218     ASSERT_EQ(spatial_layer, frames_[index]->SpatialIndex().value_or(0));
219   }
220 
CheckFrameSize(size_t index,size_t size)221   void CheckFrameSize(size_t index, size_t size) {
222     ASSERT_LT(index, frames_.size());
223     ASSERT_TRUE(frames_[index]);
224     ASSERT_EQ(frames_[index]->size(), size);
225   }
226 
CheckNoFrame(size_t index)227   void CheckNoFrame(size_t index) {
228     ASSERT_LT(index, frames_.size());
229     ASSERT_FALSE(frames_[index]);
230   }
231 
Rand()232   uint32_t Rand() { return rand_.Rand<uint32_t>(); }
233 
234   // The ProtectionMode tests depends on rtt-multiplier experiment.
235   test::ScopedFieldTrials trial_;
236   webrtc::GlobalSimulatedTimeController time_controller_;
237   rtc::TaskQueue time_task_queue_;
238   VCMTimingFake timing_;
239   std::unique_ptr<FrameBuffer> buffer_;
240   std::vector<std::unique_ptr<EncodedFrame>> frames_;
241   Random rand_;
242   ::testing::NiceMock<VCMReceiveStatisticsCallbackMock> stats_callback_;
243 };
244 
245 // From https://en.cppreference.com/w/cpp/language/static: "If ... a constexpr
246 // static data member (since C++11) is odr-used, a definition at namespace scope
247 // is still required... This definition is deprecated for constexpr data members
248 // since C++17."
249 // kFrameSize is odr-used since it is passed by reference to EXPECT_EQ().
250 #if __cplusplus < 201703L
251 constexpr size_t TestFrameBuffer2::kFrameSize;
252 #endif
253 
TEST_F(TestFrameBuffer2,WaitForFrame)254 TEST_F(TestFrameBuffer2, WaitForFrame) {
255   uint16_t pid = Rand();
256   uint32_t ts = Rand();
257 
258   ExtractFrame(50);
259   InsertFrame(pid, 0, ts, true, kFrameSize);
260   time_controller_.AdvanceTime(TimeDelta::Millis(50));
261   CheckFrame(0, pid, 0);
262 }
263 
TEST_F(TestFrameBuffer2,OneSuperFrame)264 TEST_F(TestFrameBuffer2, OneSuperFrame) {
265   uint16_t pid = Rand();
266   uint32_t ts = Rand();
267 
268   InsertFrame(pid, 0, ts, false, kFrameSize);
269   InsertFrame(pid + 1, 1, ts, true, kFrameSize);
270   ExtractFrame();
271 
272   CheckFrame(0, pid, 1);
273 }
274 
TEST_F(TestFrameBuffer2,ZeroPlayoutDelay)275 TEST_F(TestFrameBuffer2, ZeroPlayoutDelay) {
276   VCMTiming timing(time_controller_.GetClock());
277   buffer_.reset(
278       new FrameBuffer(time_controller_.GetClock(), &timing, &stats_callback_));
279   const VideoPlayoutDelay kPlayoutDelayMs = {0, 0};
280   std::unique_ptr<FrameObjectFake> test_frame(new FrameObjectFake());
281   test_frame->SetId(0);
282   test_frame->SetPlayoutDelay(kPlayoutDelayMs);
283   buffer_->InsertFrame(std::move(test_frame));
284   ExtractFrame(0, false);
285   CheckFrame(0, 0, 0);
286   EXPECT_EQ(0, frames_[0]->RenderTimeMs());
287 }
288 
289 // Flaky test, see bugs.webrtc.org/7068.
TEST_F(TestFrameBuffer2,DISABLED_OneUnorderedSuperFrame)290 TEST_F(TestFrameBuffer2, DISABLED_OneUnorderedSuperFrame) {
291   uint16_t pid = Rand();
292   uint32_t ts = Rand();
293 
294   ExtractFrame(50);
295   InsertFrame(pid, 1, ts, true, kFrameSize);
296   InsertFrame(pid, 0, ts, false, kFrameSize);
297   time_controller_.AdvanceTime(TimeDelta::Millis(0));
298 
299   CheckFrame(0, pid, 0);
300   CheckFrame(1, pid, 1);
301 }
302 
TEST_F(TestFrameBuffer2,DISABLED_OneLayerStreamReordered)303 TEST_F(TestFrameBuffer2, DISABLED_OneLayerStreamReordered) {
304   uint16_t pid = Rand();
305   uint32_t ts = Rand();
306 
307   InsertFrame(pid, 0, ts, false, true, kFrameSize);
308   ExtractFrame();
309   CheckFrame(0, pid, 0);
310   for (int i = 1; i < 10; i += 2) {
311     ExtractFrame(50);
312     InsertFrame(pid + i + 1, 0, ts + (i + 1) * kFps10, true, kFrameSize,
313                 pid + i);
314     time_controller_.AdvanceTime(TimeDelta::Millis(kFps10));
315     InsertFrame(pid + i, 0, ts + i * kFps10, true, kFrameSize, pid + i - 1);
316     time_controller_.AdvanceTime(TimeDelta::Millis(kFps10));
317     ExtractFrame();
318     CheckFrame(i, pid + i, 0);
319     CheckFrame(i + 1, pid + i + 1, 0);
320   }
321 }
322 
TEST_F(TestFrameBuffer2,ExtractFromEmptyBuffer)323 TEST_F(TestFrameBuffer2, ExtractFromEmptyBuffer) {
324   ExtractFrame();
325   CheckNoFrame(0);
326 }
327 
TEST_F(TestFrameBuffer2,MissingFrame)328 TEST_F(TestFrameBuffer2, MissingFrame) {
329   uint16_t pid = Rand();
330   uint32_t ts = Rand();
331 
332   InsertFrame(pid, 0, ts, true, kFrameSize);
333   InsertFrame(pid + 2, 0, ts, true, kFrameSize, pid);
334   InsertFrame(pid + 3, 0, ts, true, kFrameSize, pid + 1, pid + 2);
335   ExtractFrame();
336   ExtractFrame();
337   ExtractFrame();
338 
339   CheckFrame(0, pid, 0);
340   CheckFrame(1, pid + 2, 0);
341   CheckNoFrame(2);
342 }
343 
TEST_F(TestFrameBuffer2,OneLayerStream)344 TEST_F(TestFrameBuffer2, OneLayerStream) {
345   uint16_t pid = Rand();
346   uint32_t ts = Rand();
347 
348   InsertFrame(pid, 0, ts, true, kFrameSize);
349   ExtractFrame();
350   CheckFrame(0, pid, 0);
351   for (int i = 1; i < 10; ++i) {
352     InsertFrame(pid + i, 0, ts + i * kFps10, true, kFrameSize, pid + i - 1);
353     ExtractFrame();
354     time_controller_.AdvanceTime(TimeDelta::Millis(kFps10));
355     CheckFrame(i, pid + i, 0);
356   }
357 }
358 
TEST_F(TestFrameBuffer2,DropTemporalLayerSlowDecoder)359 TEST_F(TestFrameBuffer2, DropTemporalLayerSlowDecoder) {
360   uint16_t pid = Rand();
361   uint32_t ts = Rand();
362 
363   InsertFrame(pid, 0, ts, true, kFrameSize);
364   InsertFrame(pid + 1, 0, ts + kFps20, true, kFrameSize, pid);
365   for (int i = 2; i < 10; i += 2) {
366     uint32_t ts_tl0 = ts + i / 2 * kFps10;
367     InsertFrame(pid + i, 0, ts_tl0, true, kFrameSize, pid + i - 2);
368     InsertFrame(pid + i + 1, 0, ts_tl0 + kFps20, true, kFrameSize, pid + i,
369                 pid + i - 1);
370   }
371 
372   EXPECT_CALL(stats_callback_, OnDroppedFrames(1)).Times(3);
373 
374   for (int i = 0; i < 10; ++i) {
375     ExtractFrame();
376     time_controller_.AdvanceTime(TimeDelta::Millis(70));
377   }
378 
379   CheckFrame(0, pid, 0);
380   CheckFrame(1, pid + 1, 0);
381   CheckFrame(2, pid + 2, 0);
382   CheckFrame(3, pid + 4, 0);
383   CheckFrame(4, pid + 6, 0);
384   CheckFrame(5, pid + 8, 0);
385   CheckNoFrame(6);
386   CheckNoFrame(7);
387   CheckNoFrame(8);
388   CheckNoFrame(9);
389 }
390 
TEST_F(TestFrameBuffer2,DropFramesIfSystemIsStalled)391 TEST_F(TestFrameBuffer2, DropFramesIfSystemIsStalled) {
392   uint16_t pid = Rand();
393   uint32_t ts = Rand();
394 
395   InsertFrame(pid, 0, ts, true, kFrameSize);
396   InsertFrame(pid + 1, 0, ts + 1 * kFps10, true, kFrameSize, pid);
397   InsertFrame(pid + 2, 0, ts + 2 * kFps10, true, kFrameSize, pid + 1);
398   InsertFrame(pid + 3, 0, ts + 3 * kFps10, true, kFrameSize);
399 
400   ExtractFrame();
401   // Jump forward in time, simulating the system being stalled for some reason.
402   time_controller_.AdvanceTime(TimeDelta::Millis(3) * kFps10);
403   // Extract one more frame, expect second and third frame to be dropped.
404   EXPECT_CALL(stats_callback_, OnDroppedFrames(2)).Times(1);
405   ExtractFrame();
406 
407   CheckFrame(0, pid + 0, 0);
408   CheckFrame(1, pid + 3, 0);
409 }
410 
TEST_F(TestFrameBuffer2,DroppedFramesCountedOnClear)411 TEST_F(TestFrameBuffer2, DroppedFramesCountedOnClear) {
412   uint16_t pid = Rand();
413   uint32_t ts = Rand();
414 
415   InsertFrame(pid, 0, ts, true, kFrameSize);
416   for (int i = 1; i < 5; ++i) {
417     InsertFrame(pid + i, 0, ts + i * kFps10, true, kFrameSize, pid + i - 1);
418   }
419 
420   // All frames should be dropped when Clear is called.
421   EXPECT_CALL(stats_callback_, OnDroppedFrames(5)).Times(1);
422   buffer_->Clear();
423 }
424 
TEST_F(TestFrameBuffer2,InsertLateFrame)425 TEST_F(TestFrameBuffer2, InsertLateFrame) {
426   uint16_t pid = Rand();
427   uint32_t ts = Rand();
428 
429   InsertFrame(pid, 0, ts, true, kFrameSize);
430   ExtractFrame();
431   InsertFrame(pid + 2, 0, ts, true, kFrameSize);
432   ExtractFrame();
433   InsertFrame(pid + 1, 0, ts, true, kFrameSize, pid);
434   ExtractFrame();
435 
436   CheckFrame(0, pid, 0);
437   CheckFrame(1, pid + 2, 0);
438   CheckNoFrame(2);
439 }
440 
TEST_F(TestFrameBuffer2,ProtectionModeNackFEC)441 TEST_F(TestFrameBuffer2, ProtectionModeNackFEC) {
442   uint16_t pid = Rand();
443   uint32_t ts = Rand();
444   constexpr int64_t kRttMs = 200;
445   buffer_->UpdateRtt(kRttMs);
446 
447   // Jitter estimate unaffected by RTT in this protection mode.
448   buffer_->SetProtectionMode(kProtectionNackFEC);
449   InsertNackedFrame(pid, ts);
450   InsertNackedFrame(pid + 1, ts + 100);
451   InsertNackedFrame(pid + 2, ts + 200);
452   InsertFrame(pid + 3, 0, ts + 300, true, kFrameSize);
453   ExtractFrame();
454   ExtractFrame();
455   ExtractFrame();
456   ExtractFrame();
457   ASSERT_EQ(4u, frames_.size());
458   EXPECT_LT(timing_.GetCurrentJitter(), kRttMs);
459 }
460 
TEST_F(TestFrameBuffer2,ProtectionModeNack)461 TEST_F(TestFrameBuffer2, ProtectionModeNack) {
462   uint16_t pid = Rand();
463   uint32_t ts = Rand();
464   constexpr int64_t kRttMs = 200;
465 
466   buffer_->UpdateRtt(kRttMs);
467 
468   // Jitter estimate includes RTT (after 3 retransmitted packets)
469   buffer_->SetProtectionMode(kProtectionNack);
470   InsertNackedFrame(pid, ts);
471   InsertNackedFrame(pid + 1, ts + 100);
472   InsertNackedFrame(pid + 2, ts + 200);
473   InsertFrame(pid + 3, 0, ts + 300, true, kFrameSize);
474   ExtractFrame();
475   ExtractFrame();
476   ExtractFrame();
477   ExtractFrame();
478   ASSERT_EQ(4u, frames_.size());
479 
480   EXPECT_GT(timing_.GetCurrentJitter(), kRttMs);
481 }
482 
TEST_F(TestFrameBuffer2,NoContinuousFrame)483 TEST_F(TestFrameBuffer2, NoContinuousFrame) {
484   uint16_t pid = Rand();
485   uint32_t ts = Rand();
486 
487   EXPECT_EQ(-1, InsertFrame(pid + 1, 0, ts, true, kFrameSize, pid));
488 }
489 
TEST_F(TestFrameBuffer2,LastContinuousFrameSingleLayer)490 TEST_F(TestFrameBuffer2, LastContinuousFrameSingleLayer) {
491   uint16_t pid = Rand();
492   uint32_t ts = Rand();
493 
494   EXPECT_EQ(pid, InsertFrame(pid, 0, ts, true, kFrameSize));
495   EXPECT_EQ(pid, InsertFrame(pid + 2, 0, ts, true, kFrameSize, pid + 1));
496   EXPECT_EQ(pid + 2, InsertFrame(pid + 1, 0, ts, true, kFrameSize, pid));
497   EXPECT_EQ(pid + 2, InsertFrame(pid + 4, 0, ts, true, kFrameSize, pid + 3));
498   EXPECT_EQ(pid + 5, InsertFrame(pid + 5, 0, ts, true, kFrameSize));
499 }
500 
TEST_F(TestFrameBuffer2,LastContinuousFrameTwoLayers)501 TEST_F(TestFrameBuffer2, LastContinuousFrameTwoLayers) {
502   uint16_t pid = Rand();
503   uint32_t ts = Rand();
504 
505   EXPECT_EQ(pid, InsertFrame(pid, 0, ts, false, kFrameSize));
506   EXPECT_EQ(pid + 1, InsertFrame(pid + 1, 1, ts, true, kFrameSize));
507   EXPECT_EQ(pid + 1,
508             InsertFrame(pid + 3, 1, ts, true, kFrameSize, pid + 1, pid + 2));
509   EXPECT_EQ(pid + 1, InsertFrame(pid + 4, 0, ts, false, kFrameSize, pid + 2));
510   EXPECT_EQ(pid + 1,
511             InsertFrame(pid + 5, 1, ts, true, kFrameSize, pid + 3, pid + 4));
512   EXPECT_EQ(pid + 1, InsertFrame(pid + 6, 0, ts, false, kFrameSize, pid + 4));
513   EXPECT_EQ(pid + 6, InsertFrame(pid + 2, 0, ts, false, kFrameSize, pid));
514   EXPECT_EQ(pid + 7,
515             InsertFrame(pid + 7, 1, ts, true, kFrameSize, pid + 5, pid + 6));
516 }
517 
TEST_F(TestFrameBuffer2,PictureIdJumpBack)518 TEST_F(TestFrameBuffer2, PictureIdJumpBack) {
519   uint16_t pid = Rand();
520   uint32_t ts = Rand();
521 
522   EXPECT_EQ(pid, InsertFrame(pid, 0, ts, true, kFrameSize));
523   EXPECT_EQ(pid + 1, InsertFrame(pid + 1, 0, ts + 1, true, kFrameSize, pid));
524   ExtractFrame();
525   CheckFrame(0, pid, 0);
526 
527   // Jump back in pid but increase ts.
528   EXPECT_EQ(pid - 1, InsertFrame(pid - 1, 0, ts + 2, true, kFrameSize));
529   ExtractFrame();
530   ExtractFrame();
531   CheckFrame(1, pid - 1, 0);
532   CheckNoFrame(2);
533 }
534 
TEST_F(TestFrameBuffer2,StatsCallback)535 TEST_F(TestFrameBuffer2, StatsCallback) {
536   uint16_t pid = Rand();
537   uint32_t ts = Rand();
538   const int kFrameSize = 5000;
539 
540   EXPECT_CALL(stats_callback_,
541               OnCompleteFrame(true, kFrameSize, VideoContentType::UNSPECIFIED));
542   EXPECT_CALL(stats_callback_, OnFrameBufferTimingsUpdated(_, _, _, _, _, _));
543 
544   {
545     std::unique_ptr<FrameObjectFake> frame(new FrameObjectFake());
546     frame->SetEncodedData(EncodedImageBuffer::Create(kFrameSize));
547     frame->SetId(pid);
548     frame->SetTimestamp(ts);
549     frame->num_references = 0;
550 
551     EXPECT_EQ(buffer_->InsertFrame(std::move(frame)), pid);
552   }
553 
554   ExtractFrame();
555   CheckFrame(0, pid, 0);
556 }
557 
TEST_F(TestFrameBuffer2,ForwardJumps)558 TEST_F(TestFrameBuffer2, ForwardJumps) {
559   EXPECT_EQ(5453, InsertFrame(5453, 0, 1, true, kFrameSize));
560   ExtractFrame();
561   EXPECT_EQ(5454, InsertFrame(5454, 0, 1, true, kFrameSize, 5453));
562   ExtractFrame();
563   EXPECT_EQ(15670, InsertFrame(15670, 0, 1, true, kFrameSize));
564   ExtractFrame();
565   EXPECT_EQ(29804, InsertFrame(29804, 0, 1, true, kFrameSize));
566   ExtractFrame();
567   EXPECT_EQ(29805, InsertFrame(29805, 0, 1, true, kFrameSize, 29804));
568   ExtractFrame();
569   EXPECT_EQ(29806, InsertFrame(29806, 0, 1, true, kFrameSize, 29805));
570   ExtractFrame();
571   EXPECT_EQ(33819, InsertFrame(33819, 0, 1, true, kFrameSize));
572   ExtractFrame();
573   EXPECT_EQ(41248, InsertFrame(41248, 0, 1, true, kFrameSize));
574   ExtractFrame();
575 }
576 
TEST_F(TestFrameBuffer2,DuplicateFrames)577 TEST_F(TestFrameBuffer2, DuplicateFrames) {
578   EXPECT_EQ(22256, InsertFrame(22256, 0, 1, true, kFrameSize));
579   ExtractFrame();
580   EXPECT_EQ(22256, InsertFrame(22256, 0, 1, true, kFrameSize));
581 }
582 
583 // TODO(philipel): implement more unittests related to invalid references.
TEST_F(TestFrameBuffer2,InvalidReferences)584 TEST_F(TestFrameBuffer2, InvalidReferences) {
585   EXPECT_EQ(-1, InsertFrame(0, 0, 1000, true, kFrameSize, 2));
586   EXPECT_EQ(1, InsertFrame(1, 0, 2000, true, kFrameSize));
587   ExtractFrame();
588   EXPECT_EQ(2, InsertFrame(2, 0, 3000, true, kFrameSize, 1));
589 }
590 
TEST_F(TestFrameBuffer2,KeyframeRequired)591 TEST_F(TestFrameBuffer2, KeyframeRequired) {
592   EXPECT_EQ(1, InsertFrame(1, 0, 1000, true, kFrameSize));
593   EXPECT_EQ(2, InsertFrame(2, 0, 2000, true, kFrameSize, 1));
594   EXPECT_EQ(3, InsertFrame(3, 0, 3000, true, kFrameSize));
595   ExtractFrame();
596   ExtractFrame(0, true);
597   ExtractFrame();
598 
599   CheckFrame(0, 1, 0);
600   CheckFrame(1, 3, 0);
601   CheckNoFrame(2);
602 }
603 
TEST_F(TestFrameBuffer2,KeyframeClearsFullBuffer)604 TEST_F(TestFrameBuffer2, KeyframeClearsFullBuffer) {
605   const int kMaxBufferSize = 600;
606 
607   for (int i = 1; i <= kMaxBufferSize; ++i)
608     EXPECT_EQ(-1, InsertFrame(i, 0, i * 1000, true, kFrameSize, i - 1));
609   ExtractFrame();
610   CheckNoFrame(0);
611 
612   EXPECT_EQ(kMaxBufferSize + 1,
613             InsertFrame(kMaxBufferSize + 1, 0, (kMaxBufferSize + 1) * 1000,
614                         true, kFrameSize));
615   ExtractFrame();
616   CheckFrame(1, kMaxBufferSize + 1, 0);
617 }
618 
TEST_F(TestFrameBuffer2,DontUpdateOnUndecodableFrame)619 TEST_F(TestFrameBuffer2, DontUpdateOnUndecodableFrame) {
620   InsertFrame(1, 0, 0, true, kFrameSize);
621   ExtractFrame(0, true);
622   InsertFrame(3, 0, 0, true, kFrameSize, 2, 0);
623   InsertFrame(3, 0, 0, true, kFrameSize, 0);
624   InsertFrame(2, 0, 0, true, kFrameSize);
625   ExtractFrame(0, true);
626   ExtractFrame(0, true);
627 }
628 
TEST_F(TestFrameBuffer2,DontDecodeOlderTimestamp)629 TEST_F(TestFrameBuffer2, DontDecodeOlderTimestamp) {
630   InsertFrame(2, 0, 1, true, kFrameSize);
631   InsertFrame(1, 0, 2, true,
632               kFrameSize);  // Older picture id but newer timestamp.
633   ExtractFrame(0);
634   ExtractFrame(0);
635   CheckFrame(0, 1, 0);
636   CheckNoFrame(1);
637 
638   InsertFrame(3, 0, 4, true, kFrameSize);
639   InsertFrame(4, 0, 3, true,
640               kFrameSize);  // Newer picture id but older timestamp.
641   ExtractFrame(0);
642   ExtractFrame(0);
643   CheckFrame(2, 3, 0);
644   CheckNoFrame(3);
645 }
646 
TEST_F(TestFrameBuffer2,CombineFramesToSuperframe)647 TEST_F(TestFrameBuffer2, CombineFramesToSuperframe) {
648   uint16_t pid = Rand();
649   uint32_t ts = Rand();
650 
651   InsertFrame(pid, 0, ts, false, kFrameSize);
652   InsertFrame(pid + 1, 1, ts, true, 2 * kFrameSize, pid);
653   ExtractFrame(0);
654   ExtractFrame(0);
655   CheckFrame(0, pid, 1);
656   CheckNoFrame(1);
657   // Two frames should be combined and returned together.
658   CheckFrameSize(0, 3 * kFrameSize);
659 
660   EXPECT_EQ(frames_[0]->SpatialIndex(), 1);
661   EXPECT_EQ(frames_[0]->SpatialLayerFrameSize(0), kFrameSize);
662   EXPECT_EQ(frames_[0]->SpatialLayerFrameSize(1), 2 * kFrameSize);
663 }
664 
TEST_F(TestFrameBuffer2,HigherSpatialLayerNonDecodable)665 TEST_F(TestFrameBuffer2, HigherSpatialLayerNonDecodable) {
666   uint16_t pid = Rand();
667   uint32_t ts = Rand();
668 
669   InsertFrame(pid, 0, ts, false, kFrameSize);
670   InsertFrame(pid + 1, 1, ts, true, kFrameSize, pid);
671 
672   ExtractFrame(0);
673   CheckFrame(0, pid, 1);
674 
675   InsertFrame(pid + 3, 1, ts + kFps20, true, kFrameSize, pid);
676   InsertFrame(pid + 4, 0, ts + kFps10, false, kFrameSize, pid);
677   InsertFrame(pid + 5, 1, ts + kFps10, true, kFrameSize, pid + 3, pid + 4);
678 
679   time_controller_.AdvanceTime(TimeDelta::Millis(1000));
680   // Frame pid+3 is decodable but too late.
681   // In superframe pid+4 is decodable, but frame pid+5 is not.
682   // Incorrect implementation might skip pid+2 frame and output undecodable
683   // pid+5 instead.
684   ExtractFrame();
685   ExtractFrame();
686   CheckFrame(1, pid + 3, 1);
687   CheckFrame(2, pid + 4, 1);
688 }
689 
690 }  // namespace video_coding
691 }  // namespace webrtc
692