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, ¤t_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