pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 1 | /* |
pwestin@webrtc.org | 8d89b58 | 2012-09-20 20:49:12 +0000 | [diff] [blame] | 2 | * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 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 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #include "modules/video_coding/codecs/vp8/default_temporal_layers.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 12 | |
| 13 | #include <cstdint> |
| 14 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 15 | #include "absl/memory/memory.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 16 | #include "api/video/video_bitrate_allocation.h" |
| 17 | #include "api/video_codecs/video_codec.h" |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 18 | #include "api/video_codecs/vp8_frame_config.h" |
Erik Språng | cc681cc | 2018-03-14 17:52:55 +0100 | [diff] [blame] | 19 | #include "modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 20 | #include "modules/video_coding/include/video_codec_interface.h" |
Sergio Garcia Murillo | 43800f9 | 2018-06-21 16:16:38 +0200 | [diff] [blame] | 21 | #include "modules/video_coding/utility/simulcast_rate_allocator.h" |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 22 | #include "test/field_trial.h" |
| 23 | #include "test/gtest.h" |
Yves Gerey | 3e70781 | 2018-11-28 16:47:49 +0100 | [diff] [blame] | 24 | #include "vpx/vp8cx.h" |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 25 | |
| 26 | namespace webrtc { |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 27 | namespace test { |
Erik Språng | bb60a3a | 2018-03-19 18:25:10 +0100 | [diff] [blame] | 28 | namespace { |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 29 | enum { |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 30 | kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 31 | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF, |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 32 | kTemporalUpdateGoldenWithoutDependency = |
| 33 | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | |
| 34 | VP8_EFLAG_NO_UPD_LAST, |
| 35 | kTemporalUpdateGolden = |
| 36 | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
| 37 | kTemporalUpdateAltrefWithoutDependency = |
| 38 | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | |
| 39 | VP8_EFLAG_NO_UPD_LAST, |
| 40 | kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, |
| 41 | kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 42 | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 43 | kTemporalUpdateNoneNoRefAltRef = |
| 44 | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
| 45 | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 46 | kTemporalUpdateNoneNoRefGolden = |
| 47 | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
| 48 | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
| 49 | kTemporalUpdateNoneNoRefGoldenAltRef = |
| 50 | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_REF_ARF | |
| 51 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 52 | kTemporalUpdateGoldenWithoutDependencyRefAltRef = |
| 53 | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
| 54 | kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
| 55 | kTemporalUpdateLastRefAltRef = |
| 56 | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, |
| 57 | kTemporalUpdateLastAndGoldenRefAltRef = |
| 58 | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 59 | }; |
| 60 | |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 61 | using BufferFlags = Vp8FrameConfig::BufferFlags; |
| 62 | using Vp8BufferReference = Vp8FrameConfig::Vp8BufferReference; |
| 63 | |
| 64 | constexpr uint8_t kNone = static_cast<uint8_t>(Vp8BufferReference::kNone); |
| 65 | constexpr uint8_t kLast = static_cast<uint8_t>(Vp8BufferReference::kLast); |
| 66 | constexpr uint8_t kGolden = static_cast<uint8_t>(Vp8BufferReference::kGolden); |
| 67 | constexpr uint8_t kAltref = static_cast<uint8_t>(Vp8BufferReference::kAltref); |
| 68 | |
| 69 | constexpr int ToVp8CodecFlags(uint8_t referenced_buffers, |
| 70 | uint8_t updated_buffers, |
| 71 | bool update_entropy) { |
| 72 | return (((referenced_buffers & kLast) == 0) ? VP8_EFLAG_NO_REF_LAST : 0) | |
| 73 | (((referenced_buffers & kGolden) == 0) ? VP8_EFLAG_NO_REF_GF : 0) | |
| 74 | (((referenced_buffers & kAltref) == 0) ? VP8_EFLAG_NO_REF_ARF : 0) | |
| 75 | (((updated_buffers & kLast) == 0) ? VP8_EFLAG_NO_UPD_LAST : 0) | |
| 76 | (((updated_buffers & kGolden) == 0) ? VP8_EFLAG_NO_UPD_GF : 0) | |
| 77 | (((updated_buffers & kAltref) == 0) ? VP8_EFLAG_NO_UPD_ARF : 0) | |
| 78 | (update_entropy ? 0 : VP8_EFLAG_NO_UPD_ENTROPY); |
| 79 | } |
| 80 | |
Erik Språng | bb60a3a | 2018-03-19 18:25:10 +0100 | [diff] [blame] | 81 | std::vector<uint32_t> GetTemporalLayerRates(int target_bitrate_kbps, |
| 82 | int framerate_fps, |
| 83 | int num_temporal_layers) { |
| 84 | VideoCodec codec; |
| 85 | codec.codecType = VideoCodecType::kVideoCodecVP8; |
| 86 | codec.numberOfSimulcastStreams = 1; |
Erik Språng | bb60a3a | 2018-03-19 18:25:10 +0100 | [diff] [blame] | 87 | codec.maxBitrate = target_bitrate_kbps; |
| 88 | codec.maxFramerate = framerate_fps; |
| 89 | codec.simulcastStream[0].targetBitrate = target_bitrate_kbps; |
| 90 | codec.simulcastStream[0].maxBitrate = target_bitrate_kbps; |
| 91 | codec.simulcastStream[0].numberOfTemporalLayers = num_temporal_layers; |
| 92 | codec.simulcastStream[0].active = true; |
Erik Språng | 82fad3d | 2018-03-21 09:57:23 +0100 | [diff] [blame] | 93 | SimulcastRateAllocator allocator(codec); |
Erik Språng | bb60a3a | 2018-03-19 18:25:10 +0100 | [diff] [blame] | 94 | return allocator.GetAllocation(target_bitrate_kbps, framerate_fps) |
| 95 | .GetTemporalLayerAllocation(0); |
| 96 | } |
| 97 | |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 98 | constexpr int kDefaultBitrateBps = 500; |
| 99 | constexpr int kDefaultFramerate = 30; |
| 100 | constexpr int kDefaultBytesPerFrame = |
| 101 | (kDefaultBitrateBps / 8) / kDefaultFramerate; |
| 102 | constexpr int kDefaultQp = 2; |
Erik Språng | bb60a3a | 2018-03-19 18:25:10 +0100 | [diff] [blame] | 103 | } // namespace |
| 104 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 105 | class TemporalLayersTest : public ::testing::Test { |
| 106 | public: |
| 107 | ~TemporalLayersTest() override = default; |
| 108 | |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 109 | CodecSpecificInfo* IgnoredCodecSpecificInfo() { |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 110 | codec_specific_info_ = absl::make_unique<CodecSpecificInfo>(); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 111 | return codec_specific_info_.get(); |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | private: |
| 115 | std::unique_ptr<CodecSpecificInfo> codec_specific_info_; |
| 116 | }; |
| 117 | |
| 118 | TEST_F(TemporalLayersTest, 2Layers) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 119 | constexpr int kNumLayers = 2; |
| 120 | DefaultTemporalLayers tl(kNumLayers); |
| 121 | DefaultTemporalLayersChecker checker(kNumLayers); |
Anders Carlsson | beabdcb | 2018-01-24 10:25:15 +0100 | [diff] [blame] | 122 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 123 | tl.OnRatesUpdated(0, |
| 124 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 125 | kDefaultFramerate, kNumLayers), |
| 126 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 127 | tl.UpdateConfiguration(0, &cfg); |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 128 | |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 129 | constexpr size_t kPatternSize = 4; |
| 130 | constexpr size_t kRepetitions = 4; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 131 | |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 132 | const int expected_flags[kPatternSize] = { |
| 133 | ToVp8CodecFlags(kLast, kLast, true), |
| 134 | ToVp8CodecFlags(kLast, kGolden, true), |
| 135 | ToVp8CodecFlags(kLast, kLast, true), |
| 136 | ToVp8CodecFlags(kLast | kGolden, kNone, false), |
| 137 | }; |
| 138 | const int expected_temporal_idx[kPatternSize] = {0, 1, 0, 1}; |
| 139 | const bool expected_layer_sync[kPatternSize] = {false, true, false, false}; |
pwestin@webrtc.org | 9fe3d51 | 2011-12-14 15:13:04 +0000 | [diff] [blame] | 140 | |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 141 | uint32_t timestamp = 0; |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 142 | for (size_t i = 0; i < kPatternSize * kRepetitions; ++i) { |
| 143 | const size_t ind = i % kPatternSize; |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 144 | CodecSpecificInfo info; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 145 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 146 | EXPECT_EQ(expected_flags[ind], LibvpxVp8Encoder::EncodeFlags(tl_config)) |
| 147 | << i; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 148 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 149 | &info); |
Ilya Nikolaevskiy | bf35298 | 2017-10-02 10:08:25 +0200 | [diff] [blame] | 150 | EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config)); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 151 | EXPECT_EQ(expected_temporal_idx[ind], info.codecSpecific.VP8.temporalIdx); |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 152 | EXPECT_EQ(expected_temporal_idx[ind], tl_config.packetizer_temporal_idx); |
| 153 | EXPECT_EQ(expected_temporal_idx[ind], tl_config.encoder_layer_id); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 154 | EXPECT_EQ(i == 0 || expected_layer_sync[ind], |
| 155 | info.codecSpecific.VP8.layerSync); |
Elad Alon | 7abfd56 | 2019-02-19 11:26:26 +0100 | [diff] [blame] | 156 | EXPECT_EQ(expected_layer_sync[ind], tl_config.layer_sync); |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 157 | timestamp += 3000; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 158 | } |
| 159 | } |
| 160 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 161 | TEST_F(TemporalLayersTest, 3Layers) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 162 | constexpr int kNumLayers = 3; |
| 163 | DefaultTemporalLayers tl(kNumLayers); |
| 164 | DefaultTemporalLayersChecker checker(kNumLayers); |
Anders Carlsson | beabdcb | 2018-01-24 10:25:15 +0100 | [diff] [blame] | 165 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 166 | tl.OnRatesUpdated(0, |
| 167 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 168 | kDefaultFramerate, kNumLayers), |
| 169 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 170 | tl.UpdateConfiguration(0, &cfg); |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 171 | |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 172 | int expected_flags[16] = { |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 173 | kTemporalUpdateLastRefAltRef, |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 174 | kTemporalUpdateNoneNoRefGolden, |
| 175 | kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 176 | kTemporalUpdateNone, |
| 177 | kTemporalUpdateLastRefAltRef, |
| 178 | kTemporalUpdateNone, |
| 179 | kTemporalUpdateGoldenRefAltRef, |
| 180 | kTemporalUpdateNone, |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 181 | kTemporalUpdateLastRefAltRef, |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 182 | kTemporalUpdateNoneNoRefGolden, |
| 183 | kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 184 | kTemporalUpdateNone, |
| 185 | kTemporalUpdateLastRefAltRef, |
| 186 | kTemporalUpdateNone, |
| 187 | kTemporalUpdateGoldenRefAltRef, |
| 188 | kTemporalUpdateNone, |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 189 | }; |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 190 | int expected_temporal_idx[16] = {0, 2, 1, 2, 0, 2, 1, 2, |
| 191 | 0, 2, 1, 2, 0, 2, 1, 2}; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 192 | |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 193 | bool expected_layer_sync[16] = {false, true, true, false, false, false, |
| 194 | false, false, false, true, true, false, |
| 195 | false, false, false, false}; |
pwestin@webrtc.org | 9fe3d51 | 2011-12-14 15:13:04 +0000 | [diff] [blame] | 196 | |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 197 | unsigned int timestamp = 0; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 198 | for (int i = 0; i < 16; ++i) { |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 199 | CodecSpecificInfo info; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 200 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
Erik Språng | cc681cc | 2018-03-14 17:52:55 +0100 | [diff] [blame] | 201 | EXPECT_EQ(expected_flags[i], LibvpxVp8Encoder::EncodeFlags(tl_config)) << i; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 202 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 203 | &info); |
Ilya Nikolaevskiy | bf35298 | 2017-10-02 10:08:25 +0200 | [diff] [blame] | 204 | EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config)); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 205 | EXPECT_EQ(expected_temporal_idx[i], info.codecSpecific.VP8.temporalIdx); |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 206 | EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 207 | EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 208 | EXPECT_EQ(i == 0 || expected_layer_sync[i], |
| 209 | info.codecSpecific.VP8.layerSync); |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 210 | EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 211 | timestamp += 3000; |
| 212 | } |
| 213 | } |
| 214 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 215 | TEST_F(TemporalLayersTest, Alternative3Layers) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 216 | constexpr int kNumLayers = 3; |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 217 | ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 218 | DefaultTemporalLayers tl(kNumLayers); |
| 219 | DefaultTemporalLayersChecker checker(kNumLayers); |
Anders Carlsson | beabdcb | 2018-01-24 10:25:15 +0100 | [diff] [blame] | 220 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 221 | tl.OnRatesUpdated(0, |
| 222 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 223 | kDefaultFramerate, kNumLayers), |
| 224 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 225 | tl.UpdateConfiguration(0, &cfg); |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 226 | |
| 227 | int expected_flags[8] = {kTemporalUpdateLast, |
| 228 | kTemporalUpdateAltrefWithoutDependency, |
| 229 | kTemporalUpdateGoldenWithoutDependency, |
| 230 | kTemporalUpdateNone, |
| 231 | kTemporalUpdateLast, |
| 232 | kTemporalUpdateAltrefWithoutDependency, |
| 233 | kTemporalUpdateGoldenWithoutDependency, |
| 234 | kTemporalUpdateNone}; |
| 235 | int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; |
| 236 | |
| 237 | bool expected_layer_sync[8] = {false, true, true, false, |
| 238 | false, true, true, false}; |
| 239 | |
| 240 | unsigned int timestamp = 0; |
| 241 | for (int i = 0; i < 8; ++i) { |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 242 | CodecSpecificInfo info; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 243 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
Erik Språng | cc681cc | 2018-03-14 17:52:55 +0100 | [diff] [blame] | 244 | EXPECT_EQ(expected_flags[i], LibvpxVp8Encoder::EncodeFlags(tl_config)) << i; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 245 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 246 | &info); |
Ilya Nikolaevskiy | bf35298 | 2017-10-02 10:08:25 +0200 | [diff] [blame] | 247 | EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config)); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 248 | EXPECT_EQ(expected_temporal_idx[i], info.codecSpecific.VP8.temporalIdx); |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 249 | EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 250 | EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 251 | EXPECT_EQ(i == 0 || expected_layer_sync[i], |
| 252 | info.codecSpecific.VP8.layerSync); |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 253 | EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 254 | timestamp += 3000; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 255 | } |
| 256 | } |
| 257 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 258 | TEST_F(TemporalLayersTest, SearchOrder) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 259 | constexpr int kNumLayers = 3; |
| 260 | ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
| 261 | DefaultTemporalLayers tl(kNumLayers); |
| 262 | DefaultTemporalLayersChecker checker(kNumLayers); |
Anders Carlsson | beabdcb | 2018-01-24 10:25:15 +0100 | [diff] [blame] | 263 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 264 | tl.OnRatesUpdated(0, |
| 265 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 266 | kDefaultFramerate, kNumLayers), |
| 267 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 268 | tl.UpdateConfiguration(0, &cfg); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 269 | |
| 270 | // Use a repeating pattern of tl 0, 2, 1, 2. |
| 271 | // Tl 0, 1, 2 update last, golden, altref respectively. |
| 272 | |
| 273 | // Start with a key-frame. tl_config flags can be ignored. |
| 274 | uint32_t timestamp = 0; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 275 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
| 276 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 277 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 278 | |
| 279 | // TL2 frame. First one only references TL0. Updates altref. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 280 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 281 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 282 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 283 | EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kLast); |
| 284 | EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kNone); |
| 285 | |
| 286 | // TL1 frame. Can only reference TL0. Updated golden. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 287 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 288 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 289 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 290 | EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kLast); |
| 291 | EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kNone); |
| 292 | |
| 293 | // TL2 frame. Can reference all three buffers. Golden was the last to be |
| 294 | // updated, the next to last was altref. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 295 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 296 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 297 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 298 | EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kGolden); |
| 299 | EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kAltref); |
| 300 | } |
| 301 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 302 | TEST_F(TemporalLayersTest, SearchOrderWithDrop) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 303 | constexpr int kNumLayers = 3; |
| 304 | ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
| 305 | DefaultTemporalLayers tl(kNumLayers); |
| 306 | DefaultTemporalLayersChecker checker(kNumLayers); |
| 307 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 308 | tl.OnRatesUpdated(0, |
| 309 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 310 | kDefaultFramerate, kNumLayers), |
| 311 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 312 | tl.UpdateConfiguration(0, &cfg); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 313 | |
| 314 | // Use a repeating pattern of tl 0, 2, 1, 2. |
| 315 | // Tl 0, 1, 2 update last, golden, altref respectively. |
| 316 | |
| 317 | // Start with a key-frame. tl_config flags can be ignored. |
| 318 | uint32_t timestamp = 0; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 319 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
| 320 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 321 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 322 | |
| 323 | // TL2 frame. First one only references TL0. Updates altref. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 324 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 325 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 326 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 327 | EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kLast); |
| 328 | EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kNone); |
| 329 | |
| 330 | // Dropped TL1 frame. Can only reference TL0. Should have updated golden. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 331 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 332 | tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 333 | |
| 334 | // TL2 frame. Can normally reference all three buffers, but golden has not |
| 335 | // been populated this cycle. Altref was last to be updated, before that last. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 336 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 337 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 338 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 339 | EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kAltref); |
| 340 | EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kLast); |
| 341 | } |
| 342 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 343 | TEST_F(TemporalLayersTest, 4Layers) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 344 | constexpr int kNumLayers = 4; |
| 345 | DefaultTemporalLayers tl(kNumLayers); |
| 346 | DefaultTemporalLayersChecker checker(kNumLayers); |
| 347 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 348 | tl.OnRatesUpdated(0, |
| 349 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 350 | kDefaultFramerate, kNumLayers), |
| 351 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 352 | tl.UpdateConfiguration(0, &cfg); |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 353 | int expected_flags[16] = { |
| 354 | kTemporalUpdateLast, |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 355 | kTemporalUpdateNoneNoRefGoldenAltRef, |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 356 | kTemporalUpdateAltrefWithoutDependency, |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 357 | kTemporalUpdateNoneNoRefGolden, |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 358 | kTemporalUpdateGoldenWithoutDependency, |
| 359 | kTemporalUpdateNone, |
| 360 | kTemporalUpdateAltref, |
| 361 | kTemporalUpdateNone, |
| 362 | kTemporalUpdateLast, |
| 363 | kTemporalUpdateNone, |
| 364 | kTemporalUpdateAltref, |
| 365 | kTemporalUpdateNone, |
| 366 | kTemporalUpdateGolden, |
| 367 | kTemporalUpdateNone, |
| 368 | kTemporalUpdateAltref, |
| 369 | kTemporalUpdateNone, |
| 370 | }; |
philipel | cce46fc | 2015-12-21 03:04:49 -0800 | [diff] [blame] | 371 | int expected_temporal_idx[16] = {0, 3, 2, 3, 1, 3, 2, 3, |
| 372 | 0, 3, 2, 3, 1, 3, 2, 3}; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 373 | |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 374 | bool expected_layer_sync[16] = {false, true, true, false, true, false, |
| 375 | false, false, false, false, false, false, |
| 376 | false, false, false, false}; |
pwestin@webrtc.org | 9fe3d51 | 2011-12-14 15:13:04 +0000 | [diff] [blame] | 377 | |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 378 | uint32_t timestamp = 0; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 379 | for (int i = 0; i < 16; ++i) { |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 380 | CodecSpecificInfo info; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 381 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
Erik Språng | cc681cc | 2018-03-14 17:52:55 +0100 | [diff] [blame] | 382 | EXPECT_EQ(expected_flags[i], LibvpxVp8Encoder::EncodeFlags(tl_config)) << i; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 383 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 384 | &info); |
Ilya Nikolaevskiy | bf35298 | 2017-10-02 10:08:25 +0200 | [diff] [blame] | 385 | EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config)); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 386 | EXPECT_EQ(expected_temporal_idx[i], info.codecSpecific.VP8.temporalIdx); |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 387 | EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 388 | EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 389 | EXPECT_EQ(i == 0 || expected_layer_sync[i], |
| 390 | info.codecSpecific.VP8.layerSync); |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 391 | EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 392 | timestamp += 3000; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 393 | } |
| 394 | } |
| 395 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 396 | TEST_F(TemporalLayersTest, DoesNotReferenceDroppedFrames) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 397 | constexpr int kNumLayers = 3; |
| 398 | // Use a repeating pattern of tl 0, 2, 1, 2. |
| 399 | // Tl 0, 1, 2 update last, golden, altref respectively. |
| 400 | ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
| 401 | DefaultTemporalLayers tl(kNumLayers); |
| 402 | DefaultTemporalLayersChecker checker(kNumLayers); |
Anders Carlsson | beabdcb | 2018-01-24 10:25:15 +0100 | [diff] [blame] | 403 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 404 | tl.OnRatesUpdated(0, |
| 405 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 406 | kDefaultFramerate, kNumLayers), |
| 407 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 408 | tl.UpdateConfiguration(0, &cfg); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 409 | |
| 410 | // Start with a keyframe. |
| 411 | uint32_t timestamp = 0; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 412 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
| 413 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 414 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 415 | |
| 416 | // Dropped TL2 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 417 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 418 | tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 419 | |
| 420 | // Dropped TL1 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 421 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 422 | tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 423 | |
| 424 | // TL2 frame. Can reference all three buffers, valid since golden and altref |
| 425 | // both contain the last keyframe. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 426 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 427 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 428 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 429 | EXPECT_TRUE(tl_config.last_buffer_flags & BufferFlags::kReference); |
| 430 | EXPECT_TRUE(tl_config.golden_buffer_flags & BufferFlags::kReference); |
| 431 | EXPECT_TRUE(tl_config.arf_buffer_flags & BufferFlags::kReference); |
| 432 | |
| 433 | // Restart of cycle! |
| 434 | |
| 435 | // TL0 base layer frame, updating and referencing last. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 436 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 437 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 438 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 439 | |
| 440 | // TL2 frame, updating altref. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 441 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 442 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 443 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 444 | |
| 445 | // TL1 frame, updating golden. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 446 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 447 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 448 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 449 | |
| 450 | // TL2 frame. Can still reference all buffer since they have been update this |
| 451 | // cycle. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 452 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 453 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 454 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 455 | EXPECT_TRUE(tl_config.last_buffer_flags & BufferFlags::kReference); |
| 456 | EXPECT_TRUE(tl_config.golden_buffer_flags & BufferFlags::kReference); |
| 457 | EXPECT_TRUE(tl_config.arf_buffer_flags & BufferFlags::kReference); |
| 458 | |
| 459 | // Restart of cycle! |
| 460 | |
| 461 | // TL0 base layer frame, updating and referencing last. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 462 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 463 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 464 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 465 | |
| 466 | // Dropped TL2 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 467 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 468 | tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 469 | |
| 470 | // Dropped TL1 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 471 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 472 | tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 473 | |
| 474 | // TL2 frame. This time golden and altref contain data from the previous cycle |
| 475 | // and cannot be referenced. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 476 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 477 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 478 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 479 | EXPECT_TRUE(tl_config.last_buffer_flags & BufferFlags::kReference); |
| 480 | EXPECT_FALSE(tl_config.golden_buffer_flags & BufferFlags::kReference); |
| 481 | EXPECT_FALSE(tl_config.arf_buffer_flags & BufferFlags::kReference); |
| 482 | } |
| 483 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 484 | TEST_F(TemporalLayersTest, DoesNotReferenceUnlessGuaranteedToExist) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 485 | constexpr int kNumLayers = 3; |
| 486 | // Use a repeating pattern of tl 0, 2, 1, 2. |
| 487 | // Tl 0, 1 updates last, golden respectively. Altref is always last keyframe. |
| 488 | DefaultTemporalLayers tl(kNumLayers); |
| 489 | DefaultTemporalLayersChecker checker(kNumLayers); |
| 490 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 491 | tl.OnRatesUpdated(0, |
| 492 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 493 | kDefaultFramerate, kNumLayers), |
| 494 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 495 | tl.UpdateConfiguration(0, &cfg); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 496 | |
| 497 | // Start with a keyframe. |
| 498 | uint32_t timestamp = 0; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 499 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
| 500 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 501 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 502 | |
| 503 | // Do a full cycle of the pattern. |
| 504 | for (int i = 0; i < 7; ++i) { |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 505 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 506 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 507 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 508 | } |
| 509 | |
| 510 | // TL0 base layer frame, starting the cycle over. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 511 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 512 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 513 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 514 | |
| 515 | // TL2 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 516 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 517 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 518 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 519 | |
| 520 | // Encoder has a hiccup and builds a queue, so frame encoding is delayed. |
| 521 | // TL1 frame, updating golden. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 522 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 523 | |
| 524 | // TL2 frame, that should be referencing golden, but we can't be certain it's |
| 525 | // not going to be dropped, so that is not allowed. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 526 | tl_config = tl.UpdateLayerConfig(0, timestamp + 1); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 527 | EXPECT_TRUE(tl_config.last_buffer_flags & BufferFlags::kReference); |
| 528 | EXPECT_FALSE(tl_config.golden_buffer_flags & BufferFlags::kReference); |
| 529 | EXPECT_TRUE(tl_config.arf_buffer_flags & BufferFlags::kReference); |
| 530 | |
| 531 | // TL0 base layer frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 532 | tl_config = tl.UpdateLayerConfig(0, timestamp + 2); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 533 | |
| 534 | // The previous four enqueued frames finally get encoded, and the updated |
| 535 | // buffers are now OK to reference. |
| 536 | // Enqueued TL1 frame ready. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 537 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 538 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 539 | // Enqueued TL2 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 540 | tl.OnEncodeDone(0, ++timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 541 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 542 | // Enqueued TL0 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 543 | tl.OnEncodeDone(0, ++timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 544 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 545 | |
| 546 | // TL2 frame, all buffers are now in a known good state, OK to reference. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 547 | tl_config = tl.UpdateLayerConfig(0, ++timestamp + 1); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 548 | EXPECT_TRUE(tl_config.last_buffer_flags & BufferFlags::kReference); |
| 549 | EXPECT_TRUE(tl_config.golden_buffer_flags & BufferFlags::kReference); |
| 550 | EXPECT_TRUE(tl_config.arf_buffer_flags & BufferFlags::kReference); |
| 551 | } |
| 552 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 553 | TEST_F(TemporalLayersTest, DoesNotReferenceUnlessGuaranteedToExistLongDelay) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 554 | constexpr int kNumLayers = 3; |
| 555 | // Use a repeating pattern of tl 0, 2, 1, 2. |
| 556 | // Tl 0, 1 updates last, golden, altref respectively. |
| 557 | ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
| 558 | DefaultTemporalLayers tl(kNumLayers); |
| 559 | DefaultTemporalLayersChecker checker(kNumLayers); |
| 560 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 561 | tl.OnRatesUpdated(0, |
| 562 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 563 | kDefaultFramerate, kNumLayers), |
| 564 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 565 | tl.UpdateConfiguration(0, &cfg); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 566 | |
| 567 | // Start with a keyframe. |
| 568 | uint32_t timestamp = 0; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 569 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
| 570 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 571 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 572 | |
| 573 | // Do a full cycle of the pattern. |
| 574 | for (int i = 0; i < 3; ++i) { |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 575 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 576 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 577 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 578 | } |
| 579 | |
| 580 | // TL0 base layer frame, starting the cycle over. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 581 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 582 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 583 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 584 | |
| 585 | // TL2 frame. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 586 | tl_config = tl.UpdateLayerConfig(0, ++timestamp); |
| 587 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 588 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 589 | |
| 590 | // Encoder has a hiccup and builds a queue, so frame encoding is delayed. |
| 591 | // Encoded, but delayed frames in TL 1, 2. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 592 | tl_config = tl.UpdateLayerConfig(0, timestamp + 1); |
| 593 | tl_config = tl.UpdateLayerConfig(0, timestamp + 2); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 594 | |
| 595 | // Restart of the pattern! |
| 596 | |
| 597 | // Encoded, but delayed frames in TL 2, 1. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 598 | tl_config = tl.UpdateLayerConfig(0, timestamp + 3); |
| 599 | tl_config = tl.UpdateLayerConfig(0, timestamp + 4); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 600 | |
| 601 | // TL1 frame from last cycle is ready. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 602 | tl.OnEncodeDone(0, timestamp + 1, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 603 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 604 | // TL2 frame from last cycle is ready. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 605 | tl.OnEncodeDone(0, timestamp + 2, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 606 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 607 | |
| 608 | // TL2 frame, that should be referencing all buffers, but altref and golden |
| 609 | // haven not been updated this cycle. (Don't be fooled by the late frames from |
| 610 | // the last cycle!) |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 611 | tl_config = tl.UpdateLayerConfig(0, timestamp + 5); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 612 | EXPECT_TRUE(tl_config.last_buffer_flags & BufferFlags::kReference); |
| 613 | EXPECT_FALSE(tl_config.golden_buffer_flags & BufferFlags::kReference); |
| 614 | EXPECT_FALSE(tl_config.arf_buffer_flags & BufferFlags::kReference); |
| 615 | } |
| 616 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 617 | TEST_F(TemporalLayersTest, KeyFrame) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 618 | constexpr int kNumLayers = 3; |
| 619 | DefaultTemporalLayers tl(kNumLayers); |
| 620 | DefaultTemporalLayersChecker checker(kNumLayers); |
| 621 | Vp8EncoderConfig cfg; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 622 | tl.OnRatesUpdated(0, |
| 623 | GetTemporalLayerRates(kDefaultBytesPerFrame, |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 624 | kDefaultFramerate, kNumLayers), |
| 625 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 626 | tl.UpdateConfiguration(0, &cfg); |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 627 | |
| 628 | int expected_flags[8] = { |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 629 | kTemporalUpdateLastRefAltRef, |
marpan@webrtc.org | 1e68577 | 2012-08-31 21:17:12 +0000 | [diff] [blame] | 630 | kTemporalUpdateNoneNoRefGolden, |
| 631 | kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
| 632 | kTemporalUpdateNone, |
| 633 | kTemporalUpdateLastRefAltRef, |
| 634 | kTemporalUpdateNone, |
| 635 | kTemporalUpdateGoldenRefAltRef, |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 636 | kTemporalUpdateNone, |
| 637 | }; |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 638 | int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 639 | bool expected_layer_sync[8] = {true, true, true, false, |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 640 | false, false, false, false}; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 641 | |
stefan@webrtc.org | eb91792 | 2013-02-18 14:40:18 +0000 | [diff] [blame] | 642 | uint32_t timestamp = 0; |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 643 | for (int i = 0; i < 7; ++i) { |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 644 | // Temporal pattern starts from 0 after key frame. Let the first |i| - 1 |
| 645 | // frames be delta frames, and the |i|th one key frame. |
| 646 | for (int j = 1; j <= i; ++j) { |
| 647 | // Since last frame was always a keyframe and thus index 0 in the pattern, |
| 648 | // this loop starts at index 1. |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 649 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 650 | EXPECT_EQ(expected_flags[j], LibvpxVp8Encoder::EncodeFlags(tl_config)) |
| 651 | << j; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 652 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 653 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 654 | EXPECT_TRUE(checker.CheckTemporalConfig(false, tl_config)); |
| 655 | EXPECT_EQ(expected_temporal_idx[j], tl_config.packetizer_temporal_idx); |
| 656 | EXPECT_EQ(expected_temporal_idx[j], tl_config.encoder_layer_id); |
| 657 | EXPECT_EQ(expected_layer_sync[j], tl_config.layer_sync); |
| 658 | timestamp += 3000; |
| 659 | } |
| 660 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 661 | CodecSpecificInfo info; |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 662 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp); |
| 663 | tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp, |
| 664 | &info); |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 665 | EXPECT_TRUE(info.codecSpecific.VP8.layerSync) |
| 666 | << "Key frame should be marked layer sync."; |
| 667 | EXPECT_EQ(0, info.codecSpecific.VP8.temporalIdx) |
pbos | 1777c5f | 2017-07-19 17:04:02 -0700 | [diff] [blame] | 668 | << "Key frame should always be packetized as layer 0"; |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 669 | EXPECT_TRUE(checker.CheckTemporalConfig(true, tl_config)); |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 670 | } |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 671 | } |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 672 | |
Elad Alon | f5b216a | 2019-01-28 14:25:17 +0100 | [diff] [blame] | 673 | class TemporalLayersReferenceTest : public TemporalLayersTest, |
| 674 | public ::testing::WithParamInterface<int> { |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 675 | public: |
| 676 | TemporalLayersReferenceTest() |
| 677 | : timestamp_(1), |
| 678 | last_sync_timestamp_(timestamp_), |
| 679 | tl0_reference_(nullptr) {} |
| 680 | virtual ~TemporalLayersReferenceTest() {} |
| 681 | |
| 682 | protected: |
| 683 | static const int kMaxPatternLength = 32; |
| 684 | |
| 685 | struct BufferState { |
| 686 | BufferState() : BufferState(-1, 0, false) {} |
| 687 | BufferState(int temporal_idx, uint32_t timestamp, bool sync) |
| 688 | : temporal_idx(temporal_idx), timestamp(timestamp), sync(sync) {} |
| 689 | int temporal_idx; |
| 690 | uint32_t timestamp; |
| 691 | bool sync; |
| 692 | }; |
| 693 | |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 694 | bool UpdateSyncRefState(const BufferFlags& flags, BufferState* buffer_state) { |
| 695 | if (flags & BufferFlags::kReference) { |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 696 | if (buffer_state->temporal_idx == -1) |
| 697 | return true; // References key-frame. |
| 698 | if (buffer_state->temporal_idx == 0) { |
| 699 | // No more than one reference to TL0 frame. |
| 700 | EXPECT_EQ(nullptr, tl0_reference_); |
| 701 | tl0_reference_ = buffer_state; |
| 702 | return true; |
| 703 | } |
| 704 | return false; // References higher layer. |
| 705 | } |
| 706 | return true; // No reference, does not affect sync frame status. |
| 707 | } |
| 708 | |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 709 | void ValidateReference(const BufferFlags& flags, |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 710 | const BufferState& buffer_state, |
| 711 | int temporal_layer) { |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 712 | if (flags & BufferFlags::kReference) { |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 713 | if (temporal_layer > 0 && buffer_state.timestamp > 0) { |
| 714 | // Check that high layer reference does not go past last sync frame. |
| 715 | EXPECT_GE(buffer_state.timestamp, last_sync_timestamp_); |
| 716 | } |
| 717 | // No reference to buffer in higher layer. |
| 718 | EXPECT_LE(buffer_state.temporal_idx, temporal_layer); |
| 719 | } |
| 720 | } |
| 721 | |
| 722 | uint32_t timestamp_ = 1; |
| 723 | uint32_t last_sync_timestamp_ = timestamp_; |
| 724 | BufferState* tl0_reference_; |
| 725 | |
| 726 | BufferState last_state; |
| 727 | BufferState golden_state; |
| 728 | BufferState altref_state; |
| 729 | }; |
| 730 | |
Mirko Bonadei | c84f661 | 2019-01-31 12:20:57 +0100 | [diff] [blame] | 731 | INSTANTIATE_TEST_SUITE_P(DefaultTemporalLayersTest, |
| 732 | TemporalLayersReferenceTest, |
| 733 | ::testing::Range(1, kMaxTemporalStreams + 1)); |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 734 | |
| 735 | TEST_P(TemporalLayersReferenceTest, ValidFrameConfigs) { |
| 736 | const int num_layers = GetParam(); |
Niels Möller | 150dcb0 | 2018-03-27 14:16:55 +0200 | [diff] [blame] | 737 | DefaultTemporalLayers tl(num_layers); |
Anders Carlsson | beabdcb | 2018-01-24 10:25:15 +0100 | [diff] [blame] | 738 | Vp8EncoderConfig cfg; |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 739 | tl.OnRatesUpdated( |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 740 | 0, GetTemporalLayerRates(kDefaultBytesPerFrame, kDefaultFramerate, 1), |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 741 | kDefaultFramerate); |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 742 | tl.UpdateConfiguration(0, &cfg); |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 743 | |
| 744 | // Run through the pattern and store the frame dependencies, plus keep track |
| 745 | // of the buffer state; which buffers references which temporal layers (if |
| 746 | // (any). If a given buffer is never updated, it is legal to reference it |
| 747 | // even for sync frames. In order to be general, don't assume TL0 always |
| 748 | // updates |last|. |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 749 | std::vector<Vp8FrameConfig> tl_configs(kMaxPatternLength); |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 750 | for (int i = 0; i < kMaxPatternLength; ++i) { |
Elad Alon | cde8ab2 | 2019-03-20 11:56:20 +0100 | [diff] [blame] | 751 | Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp_); |
| 752 | tl.OnEncodeDone(0, timestamp_, kDefaultBytesPerFrame, i == 0, kDefaultQp, |
philipel | 9df3353 | 2019-03-04 16:37:50 +0100 | [diff] [blame] | 753 | IgnoredCodecSpecificInfo()); |
Erik Språng | b75d6b8 | 2018-08-13 16:05:33 +0200 | [diff] [blame] | 754 | ++timestamp_; |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 755 | EXPECT_FALSE(tl_config.drop_frame); |
| 756 | tl_configs.push_back(tl_config); |
| 757 | int temporal_idx = tl_config.encoder_layer_id; |
| 758 | // For the default layers, always keep encoder and rtp layers in sync. |
| 759 | EXPECT_EQ(tl_config.packetizer_temporal_idx, temporal_idx); |
| 760 | |
| 761 | // Determine if this frame is in a higher layer but references only TL0 |
| 762 | // or untouched buffers, if so verify it is marked as a layer sync. |
| 763 | bool is_sync_frame = true; |
| 764 | tl0_reference_ = nullptr; |
| 765 | if (temporal_idx <= 0) { |
| 766 | is_sync_frame = false; // TL0 by definition not a sync frame. |
| 767 | } else if (!UpdateSyncRefState(tl_config.last_buffer_flags, &last_state)) { |
| 768 | is_sync_frame = false; |
| 769 | } else if (!UpdateSyncRefState(tl_config.golden_buffer_flags, |
| 770 | &golden_state)) { |
| 771 | is_sync_frame = false; |
| 772 | } else if (!UpdateSyncRefState(tl_config.arf_buffer_flags, &altref_state)) { |
| 773 | is_sync_frame = false; |
| 774 | } |
| 775 | if (is_sync_frame) { |
| 776 | // Cache timestamp for last found sync frame, so that we can verify no |
| 777 | // references back past this frame. |
| 778 | ASSERT_TRUE(tl0_reference_); |
| 779 | last_sync_timestamp_ = tl0_reference_->timestamp; |
| 780 | } |
| 781 | EXPECT_EQ(tl_config.layer_sync, is_sync_frame); |
| 782 | |
| 783 | // Validate no reference from lower to high temporal layer, or backwards |
| 784 | // past last reference frame. |
| 785 | ValidateReference(tl_config.last_buffer_flags, last_state, temporal_idx); |
| 786 | ValidateReference(tl_config.golden_buffer_flags, golden_state, |
| 787 | temporal_idx); |
| 788 | ValidateReference(tl_config.arf_buffer_flags, altref_state, temporal_idx); |
| 789 | |
| 790 | // Update the current layer state. |
| 791 | BufferState state = {temporal_idx, timestamp_, is_sync_frame}; |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 792 | if (tl_config.last_buffer_flags & BufferFlags::kUpdate) |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 793 | last_state = state; |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 794 | if (tl_config.golden_buffer_flags & BufferFlags::kUpdate) |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 795 | golden_state = state; |
Elad Alon | 411b49b | 2019-01-29 14:05:55 +0100 | [diff] [blame] | 796 | if (tl_config.arf_buffer_flags & BufferFlags::kUpdate) |
sprang | ff19d35 | 2017-09-06 07:14:02 -0700 | [diff] [blame] | 797 | altref_state = state; |
| 798 | } |
| 799 | } |
| 800 | } // namespace test |
pwestin@webrtc.org | db221d2 | 2011-12-02 11:31:08 +0000 | [diff] [blame] | 801 | } // namespace webrtc |