1/*
2 *  Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
12#include "vpx/vpx_encoder.h"
13#include "vpx/vp8cx.h"
14#include "webrtc/modules/video_coding/codecs/vp8/reference_picture_selection.h"
15
16using webrtc::ReferencePictureSelection;
17
18// The minimum time between reference frame updates. Should match the values
19// set in reference_picture_selection.h
20static const uint32_t kMinUpdateInterval = 10;
21// The minimum time between decoder refreshes through restricted prediction.
22// Should match the values set in reference_picture_selection.h
23static const int kRtt = 10;
24
25static const int kNoPropagationGolden    = VP8_EFLAG_NO_REF_ARF |
26                                           VP8_EFLAG_NO_UPD_GF |
27                                           VP8_EFLAG_NO_UPD_ARF;
28static const int kNoPropagationAltRef    = VP8_EFLAG_NO_REF_GF |
29                                           VP8_EFLAG_NO_UPD_GF |
30                                           VP8_EFLAG_NO_UPD_ARF;
31static const int kPropagateGolden        = VP8_EFLAG_FORCE_GF |
32                                           VP8_EFLAG_NO_UPD_ARF |
33                                           VP8_EFLAG_NO_REF_GF |
34                                           VP8_EFLAG_NO_REF_LAST;
35static const int kPropagateAltRef        = VP8_EFLAG_FORCE_ARF |
36                                           VP8_EFLAG_NO_UPD_GF |
37                                           VP8_EFLAG_NO_REF_ARF |
38                                           VP8_EFLAG_NO_REF_LAST;
39static const int kRefreshFromGolden      = VP8_EFLAG_NO_REF_LAST |
40                                           VP8_EFLAG_NO_REF_ARF;
41static const int kRefreshFromAltRef      = VP8_EFLAG_NO_REF_LAST |
42                                           VP8_EFLAG_NO_REF_GF;
43
44
45class TestRPS : public ::testing::Test {
46 protected:
47  virtual void SetUp() {
48    rps_.Init();
49    // Initialize with sending a key frame and acknowledging it.
50    rps_.EncodedKeyFrame(0);
51    rps_.ReceivedRPSI(0);
52    rps_.SetRtt(kRtt);
53  }
54
55  ReferencePictureSelection rps_;
56};
57
58TEST_F(TestRPS, TestPropagateReferenceFrames) {
59  // Should propagate the alt-ref reference.
60  uint32_t time = (4 * kMinUpdateInterval) / 3 + 1;
61  EXPECT_EQ(rps_.EncodeFlags(1, false, 90 * time), kPropagateAltRef);
62  rps_.ReceivedRPSI(1);
63  time += (4 * (time + kMinUpdateInterval)) / 3 + 1;
64  // Should propagate the golden reference.
65  EXPECT_EQ(rps_.EncodeFlags(2, false, 90 * time), kPropagateGolden);
66  rps_.ReceivedRPSI(2);
67  // Should propagate the alt-ref reference.
68  time = (4 * (time + kMinUpdateInterval)) / 3 + 1;
69  EXPECT_EQ(rps_.EncodeFlags(3, false, 90 * time), kPropagateAltRef);
70  rps_.ReceivedRPSI(3);
71  // Shouldn't propagate any reference frames (except last), and the established
72  // reference is alt-ref.
73  time = time + kMinUpdateInterval;
74  EXPECT_EQ(rps_.EncodeFlags(4, false, 90 * time), kNoPropagationAltRef);
75}
76
77TEST_F(TestRPS, TestDecoderRefresh) {
78  uint32_t time = kRtt + 1;
79  // No more than one refresh per RTT.
80  EXPECT_EQ(rps_.ReceivedSLI(90 * time), true);
81  time += 5;
82  EXPECT_EQ(rps_.ReceivedSLI(90 * time), false);
83  time += kRtt - 4;
84  EXPECT_EQ(rps_.ReceivedSLI(90 * time), true);
85  // Enough time have elapsed since the previous reference propagation, we will
86  // therefore get both a refresh from golden and a propagation of alt-ref.
87  EXPECT_EQ(rps_.EncodeFlags(5, true, 90 * time), kRefreshFromGolden |
88            kPropagateAltRef);
89  rps_.ReceivedRPSI(5);
90  time += kRtt + 1;
91  // Enough time for a new refresh, but not enough time for a reference
92  // propagation.
93  EXPECT_EQ(rps_.ReceivedSLI(90 * time), true);
94  EXPECT_EQ(rps_.EncodeFlags(6, true, 90 * time), kRefreshFromAltRef |
95            kNoPropagationAltRef);
96}
97
98TEST_F(TestRPS, TestWrap) {
99  EXPECT_EQ(rps_.ReceivedSLI(0xffffffff), true);
100  EXPECT_EQ(rps_.ReceivedSLI(1), false);
101  EXPECT_EQ(rps_.ReceivedSLI(90 * 100), true);
102
103  EXPECT_EQ(rps_.EncodeFlags(7, false, 0xffffffff), kPropagateAltRef);
104  EXPECT_EQ(rps_.EncodeFlags(8, false, 1), kNoPropagationGolden);
105  EXPECT_EQ(rps_.EncodeFlags(10, false, 90 * 100), kPropagateAltRef);
106}
107