blob: 608cf181a0b2246f74ce2524abb5e2cbe5850b5f [file] [log] [blame]
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +00001/*
pwestin@webrtc.org8d89b582012-09-20 20:49:12 +00002 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +00003 *
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 Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/codecs/vp8/default_temporal_layers.h"
Yves Gerey3e707812018-11-28 16:47:49 +010012
13#include <cstdint>
14
Elad Alonf5b216a2019-01-28 14:25:17 +010015#include "absl/memory/memory.h"
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "api/video/video_bitrate_allocation.h"
17#include "api/video_codecs/video_codec.h"
Elad Alon411b49b2019-01-29 14:05:55 +010018#include "api/video_codecs/vp8_frame_config.h"
Erik Språngcc681cc2018-03-14 17:52:55 +010019#include "modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/video_coding/include/video_codec_interface.h"
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020021#include "modules/video_coding/utility/simulcast_rate_allocator.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/field_trial.h"
23#include "test/gtest.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "vpx/vp8cx.h"
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +000025
26namespace webrtc {
sprangff19d352017-09-06 07:14:02 -070027namespace test {
Erik Språngbb60a3a2018-03-19 18:25:10 +010028namespace {
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +000029enum {
philipelcce46fc2015-12-21 03:04:49 -080030 kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
sprangff19d352017-09-06 07:14:02 -070031 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF,
philipelcce46fc2015-12-21 03:04:49 -080032 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 |
sprangff19d352017-09-06 07:14:02 -070042 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,
philipelcce46fc2015-12-21 03:04:49 -080052 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.orgdb221d22011-12-02 11:31:08 +000059};
60
Elad Alon7abfd562019-02-19 11:26:26 +010061using BufferFlags = Vp8FrameConfig::BufferFlags;
62using Vp8BufferReference = Vp8FrameConfig::Vp8BufferReference;
63
64constexpr uint8_t kNone = static_cast<uint8_t>(Vp8BufferReference::kNone);
65constexpr uint8_t kLast = static_cast<uint8_t>(Vp8BufferReference::kLast);
66constexpr uint8_t kGolden = static_cast<uint8_t>(Vp8BufferReference::kGolden);
67constexpr uint8_t kAltref = static_cast<uint8_t>(Vp8BufferReference::kAltref);
68
69constexpr 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ångbb60a3a2018-03-19 18:25:10 +010081std::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ångbb60a3a2018-03-19 18:25:10 +010087 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ång82fad3d2018-03-21 09:57:23 +010093 SimulcastRateAllocator allocator(codec);
Erik Språngbb60a3a2018-03-19 18:25:10 +010094 return allocator.GetAllocation(target_bitrate_kbps, framerate_fps)
95 .GetTemporalLayerAllocation(0);
96}
97
Erik Språngb75d6b82018-08-13 16:05:33 +020098constexpr int kDefaultBitrateBps = 500;
99constexpr int kDefaultFramerate = 30;
100constexpr int kDefaultBytesPerFrame =
101 (kDefaultBitrateBps / 8) / kDefaultFramerate;
102constexpr int kDefaultQp = 2;
Erik Språngbb60a3a2018-03-19 18:25:10 +0100103} // namespace
104
Elad Alonf5b216a2019-01-28 14:25:17 +0100105class TemporalLayersTest : public ::testing::Test {
106 public:
107 ~TemporalLayersTest() override = default;
108
philipel9df33532019-03-04 16:37:50 +0100109 CodecSpecificInfo* IgnoredCodecSpecificInfo() {
Elad Alonf5b216a2019-01-28 14:25:17 +0100110 codec_specific_info_ = absl::make_unique<CodecSpecificInfo>();
philipel9df33532019-03-04 16:37:50 +0100111 return codec_specific_info_.get();
Elad Alonf5b216a2019-01-28 14:25:17 +0100112 }
113
114 private:
115 std::unique_ptr<CodecSpecificInfo> codec_specific_info_;
116};
117
118TEST_F(TemporalLayersTest, 2Layers) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200119 constexpr int kNumLayers = 2;
120 DefaultTemporalLayers tl(kNumLayers);
121 DefaultTemporalLayersChecker checker(kNumLayers);
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100122 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100123 tl.OnRatesUpdated(0,
124 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200125 kDefaultFramerate, kNumLayers),
126 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100127 tl.UpdateConfiguration(0, &cfg);
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000128
Elad Alon7abfd562019-02-19 11:26:26 +0100129 constexpr size_t kPatternSize = 4;
130 constexpr size_t kRepetitions = 4;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000131
Elad Alon7abfd562019-02-19 11:26:26 +0100132 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.org9fe3d512011-12-14 15:13:04 +0000140
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000141 uint32_t timestamp = 0;
Elad Alon7abfd562019-02-19 11:26:26 +0100142 for (size_t i = 0; i < kPatternSize * kRepetitions; ++i) {
143 const size_t ind = i % kPatternSize;
Elad Alonf5b216a2019-01-28 14:25:17 +0100144 CodecSpecificInfo info;
Elad Aloncde8ab22019-03-20 11:56:20 +0100145 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
Elad Alon7abfd562019-02-19 11:26:26 +0100146 EXPECT_EQ(expected_flags[ind], LibvpxVp8Encoder::EncodeFlags(tl_config))
147 << i;
Elad Aloncde8ab22019-03-20 11:56:20 +0100148 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100149 &info);
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200150 EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config));
philipel9df33532019-03-04 16:37:50 +0100151 EXPECT_EQ(expected_temporal_idx[ind], info.codecSpecific.VP8.temporalIdx);
Elad Alon7abfd562019-02-19 11:26:26 +0100152 EXPECT_EQ(expected_temporal_idx[ind], tl_config.packetizer_temporal_idx);
153 EXPECT_EQ(expected_temporal_idx[ind], tl_config.encoder_layer_id);
philipel9df33532019-03-04 16:37:50 +0100154 EXPECT_EQ(i == 0 || expected_layer_sync[ind],
155 info.codecSpecific.VP8.layerSync);
Elad Alon7abfd562019-02-19 11:26:26 +0100156 EXPECT_EQ(expected_layer_sync[ind], tl_config.layer_sync);
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000157 timestamp += 3000;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000158 }
159}
160
Elad Alonf5b216a2019-01-28 14:25:17 +0100161TEST_F(TemporalLayersTest, 3Layers) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200162 constexpr int kNumLayers = 3;
163 DefaultTemporalLayers tl(kNumLayers);
164 DefaultTemporalLayersChecker checker(kNumLayers);
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100165 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100166 tl.OnRatesUpdated(0,
167 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200168 kDefaultFramerate, kNumLayers),
169 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100170 tl.UpdateConfiguration(0, &cfg);
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000171
philipelcce46fc2015-12-21 03:04:49 -0800172 int expected_flags[16] = {
sprangff19d352017-09-06 07:14:02 -0700173 kTemporalUpdateLastRefAltRef,
philipelcce46fc2015-12-21 03:04:49 -0800174 kTemporalUpdateNoneNoRefGolden,
175 kTemporalUpdateGoldenWithoutDependencyRefAltRef,
176 kTemporalUpdateNone,
177 kTemporalUpdateLastRefAltRef,
178 kTemporalUpdateNone,
179 kTemporalUpdateGoldenRefAltRef,
180 kTemporalUpdateNone,
sprangff19d352017-09-06 07:14:02 -0700181 kTemporalUpdateLastRefAltRef,
philipelcce46fc2015-12-21 03:04:49 -0800182 kTemporalUpdateNoneNoRefGolden,
183 kTemporalUpdateGoldenWithoutDependencyRefAltRef,
184 kTemporalUpdateNone,
185 kTemporalUpdateLastRefAltRef,
186 kTemporalUpdateNone,
187 kTemporalUpdateGoldenRefAltRef,
188 kTemporalUpdateNone,
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000189 };
philipelcce46fc2015-12-21 03:04:49 -0800190 int expected_temporal_idx[16] = {0, 2, 1, 2, 0, 2, 1, 2,
191 0, 2, 1, 2, 0, 2, 1, 2};
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000192
philipelcce46fc2015-12-21 03:04:49 -0800193 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.org9fe3d512011-12-14 15:13:04 +0000196
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000197 unsigned int timestamp = 0;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000198 for (int i = 0; i < 16; ++i) {
Elad Alonf5b216a2019-01-28 14:25:17 +0100199 CodecSpecificInfo info;
Elad Aloncde8ab22019-03-20 11:56:20 +0100200 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
Erik Språngcc681cc2018-03-14 17:52:55 +0100201 EXPECT_EQ(expected_flags[i], LibvpxVp8Encoder::EncodeFlags(tl_config)) << i;
Elad Aloncde8ab22019-03-20 11:56:20 +0100202 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100203 &info);
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200204 EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config));
philipel9df33532019-03-04 16:37:50 +0100205 EXPECT_EQ(expected_temporal_idx[i], info.codecSpecific.VP8.temporalIdx);
sprangff19d352017-09-06 07:14:02 -0700206 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx);
207 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id);
philipel9df33532019-03-04 16:37:50 +0100208 EXPECT_EQ(i == 0 || expected_layer_sync[i],
209 info.codecSpecific.VP8.layerSync);
sprangff19d352017-09-06 07:14:02 -0700210 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync);
211 timestamp += 3000;
212 }
213}
214
Elad Alonf5b216a2019-01-28 14:25:17 +0100215TEST_F(TemporalLayersTest, Alternative3Layers) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200216 constexpr int kNumLayers = 3;
sprangff19d352017-09-06 07:14:02 -0700217 ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
Erik Språngb75d6b82018-08-13 16:05:33 +0200218 DefaultTemporalLayers tl(kNumLayers);
219 DefaultTemporalLayersChecker checker(kNumLayers);
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100220 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100221 tl.OnRatesUpdated(0,
222 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200223 kDefaultFramerate, kNumLayers),
224 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100225 tl.UpdateConfiguration(0, &cfg);
sprangff19d352017-09-06 07:14:02 -0700226
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 Alonf5b216a2019-01-28 14:25:17 +0100242 CodecSpecificInfo info;
Elad Aloncde8ab22019-03-20 11:56:20 +0100243 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
Erik Språngcc681cc2018-03-14 17:52:55 +0100244 EXPECT_EQ(expected_flags[i], LibvpxVp8Encoder::EncodeFlags(tl_config)) << i;
Elad Aloncde8ab22019-03-20 11:56:20 +0100245 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100246 &info);
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200247 EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config));
philipel9df33532019-03-04 16:37:50 +0100248 EXPECT_EQ(expected_temporal_idx[i], info.codecSpecific.VP8.temporalIdx);
pbos1777c5f2017-07-19 17:04:02 -0700249 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx);
250 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id);
philipel9df33532019-03-04 16:37:50 +0100251 EXPECT_EQ(i == 0 || expected_layer_sync[i],
252 info.codecSpecific.VP8.layerSync);
pbos1777c5f2017-07-19 17:04:02 -0700253 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync);
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000254 timestamp += 3000;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000255 }
256}
257
Elad Alonf5b216a2019-01-28 14:25:17 +0100258TEST_F(TemporalLayersTest, SearchOrder) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200259 constexpr int kNumLayers = 3;
260 ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
261 DefaultTemporalLayers tl(kNumLayers);
262 DefaultTemporalLayersChecker checker(kNumLayers);
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100263 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100264 tl.OnRatesUpdated(0,
265 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200266 kDefaultFramerate, kNumLayers),
267 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100268 tl.UpdateConfiguration(0, &cfg);
Erik Språngb75d6b82018-08-13 16:05:33 +0200269
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 Aloncde8ab22019-03-20 11:56:20 +0100275 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
276 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100277 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200278
279 // TL2 frame. First one only references TL0. Updates altref.
Elad Aloncde8ab22019-03-20 11:56:20 +0100280 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
281 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100282 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200283 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 Aloncde8ab22019-03-20 11:56:20 +0100287 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
288 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100289 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200290 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 Aloncde8ab22019-03-20 11:56:20 +0100295 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
296 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100297 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200298 EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kGolden);
299 EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kAltref);
300}
301
Elad Alonf5b216a2019-01-28 14:25:17 +0100302TEST_F(TemporalLayersTest, SearchOrderWithDrop) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200303 constexpr int kNumLayers = 3;
304 ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/");
305 DefaultTemporalLayers tl(kNumLayers);
306 DefaultTemporalLayersChecker checker(kNumLayers);
307 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100308 tl.OnRatesUpdated(0,
309 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200310 kDefaultFramerate, kNumLayers),
311 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100312 tl.UpdateConfiguration(0, &cfg);
Erik Språngb75d6b82018-08-13 16:05:33 +0200313
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 Aloncde8ab22019-03-20 11:56:20 +0100319 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
320 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100321 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200322
323 // TL2 frame. First one only references TL0. Updates altref.
Elad Aloncde8ab22019-03-20 11:56:20 +0100324 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
325 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100326 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200327 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 Aloncde8ab22019-03-20 11:56:20 +0100331 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
332 tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
Erik Språngb75d6b82018-08-13 16:05:33 +0200333
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 Aloncde8ab22019-03-20 11:56:20 +0100336 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
337 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100338 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200339 EXPECT_EQ(tl_config.first_reference, Vp8BufferReference::kAltref);
340 EXPECT_EQ(tl_config.second_reference, Vp8BufferReference::kLast);
341}
342
Elad Alonf5b216a2019-01-28 14:25:17 +0100343TEST_F(TemporalLayersTest, 4Layers) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200344 constexpr int kNumLayers = 4;
345 DefaultTemporalLayers tl(kNumLayers);
346 DefaultTemporalLayersChecker checker(kNumLayers);
347 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100348 tl.OnRatesUpdated(0,
349 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200350 kDefaultFramerate, kNumLayers),
351 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100352 tl.UpdateConfiguration(0, &cfg);
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000353 int expected_flags[16] = {
354 kTemporalUpdateLast,
sprangff19d352017-09-06 07:14:02 -0700355 kTemporalUpdateNoneNoRefGoldenAltRef,
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000356 kTemporalUpdateAltrefWithoutDependency,
sprangff19d352017-09-06 07:14:02 -0700357 kTemporalUpdateNoneNoRefGolden,
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000358 kTemporalUpdateGoldenWithoutDependency,
359 kTemporalUpdateNone,
360 kTemporalUpdateAltref,
361 kTemporalUpdateNone,
362 kTemporalUpdateLast,
363 kTemporalUpdateNone,
364 kTemporalUpdateAltref,
365 kTemporalUpdateNone,
366 kTemporalUpdateGolden,
367 kTemporalUpdateNone,
368 kTemporalUpdateAltref,
369 kTemporalUpdateNone,
370 };
philipelcce46fc2015-12-21 03:04:49 -0800371 int expected_temporal_idx[16] = {0, 3, 2, 3, 1, 3, 2, 3,
372 0, 3, 2, 3, 1, 3, 2, 3};
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000373
sprangff19d352017-09-06 07:14:02 -0700374 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.org9fe3d512011-12-14 15:13:04 +0000377
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000378 uint32_t timestamp = 0;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000379 for (int i = 0; i < 16; ++i) {
Elad Alonf5b216a2019-01-28 14:25:17 +0100380 CodecSpecificInfo info;
Elad Aloncde8ab22019-03-20 11:56:20 +0100381 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
Erik Språngcc681cc2018-03-14 17:52:55 +0100382 EXPECT_EQ(expected_flags[i], LibvpxVp8Encoder::EncodeFlags(tl_config)) << i;
Elad Aloncde8ab22019-03-20 11:56:20 +0100383 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, i == 0, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100384 &info);
Ilya Nikolaevskiybf352982017-10-02 10:08:25 +0200385 EXPECT_TRUE(checker.CheckTemporalConfig(i == 0, tl_config));
philipel9df33532019-03-04 16:37:50 +0100386 EXPECT_EQ(expected_temporal_idx[i], info.codecSpecific.VP8.temporalIdx);
pbos1777c5f2017-07-19 17:04:02 -0700387 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx);
388 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id);
philipel9df33532019-03-04 16:37:50 +0100389 EXPECT_EQ(i == 0 || expected_layer_sync[i],
390 info.codecSpecific.VP8.layerSync);
pbos1777c5f2017-07-19 17:04:02 -0700391 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync);
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000392 timestamp += 3000;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000393 }
394}
395
Elad Alonf5b216a2019-01-28 14:25:17 +0100396TEST_F(TemporalLayersTest, DoesNotReferenceDroppedFrames) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200397 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 Carlssonbeabdcb2018-01-24 10:25:15 +0100403 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100404 tl.OnRatesUpdated(0,
405 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200406 kDefaultFramerate, kNumLayers),
407 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100408 tl.UpdateConfiguration(0, &cfg);
Erik Språngb75d6b82018-08-13 16:05:33 +0200409
410 // Start with a keyframe.
411 uint32_t timestamp = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100412 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
413 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100414 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200415
416 // Dropped TL2 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100417 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
418 tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
Erik Språngb75d6b82018-08-13 16:05:33 +0200419
420 // Dropped TL1 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100421 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
422 tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
Erik Språngb75d6b82018-08-13 16:05:33 +0200423
424 // TL2 frame. Can reference all three buffers, valid since golden and altref
425 // both contain the last keyframe.
Elad Aloncde8ab22019-03-20 11:56:20 +0100426 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
427 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100428 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200429 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 Aloncde8ab22019-03-20 11:56:20 +0100436 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
437 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100438 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200439
440 // TL2 frame, updating altref.
Elad Aloncde8ab22019-03-20 11:56:20 +0100441 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
442 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100443 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200444
445 // TL1 frame, updating golden.
Elad Aloncde8ab22019-03-20 11:56:20 +0100446 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
447 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100448 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200449
450 // TL2 frame. Can still reference all buffer since they have been update this
451 // cycle.
Elad Aloncde8ab22019-03-20 11:56:20 +0100452 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
453 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100454 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200455 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 Aloncde8ab22019-03-20 11:56:20 +0100462 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
463 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100464 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200465
466 // Dropped TL2 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100467 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
468 tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
Erik Språngb75d6b82018-08-13 16:05:33 +0200469
470 // Dropped TL1 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100471 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
472 tl.OnEncodeDone(0, timestamp, 0, false, 0, nullptr);
Erik Språngb75d6b82018-08-13 16:05:33 +0200473
474 // TL2 frame. This time golden and altref contain data from the previous cycle
475 // and cannot be referenced.
Elad Aloncde8ab22019-03-20 11:56:20 +0100476 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
477 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100478 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200479 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 Alonf5b216a2019-01-28 14:25:17 +0100484TEST_F(TemporalLayersTest, DoesNotReferenceUnlessGuaranteedToExist) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200485 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 Aloncde8ab22019-03-20 11:56:20 +0100491 tl.OnRatesUpdated(0,
492 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200493 kDefaultFramerate, kNumLayers),
494 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100495 tl.UpdateConfiguration(0, &cfg);
Erik Språngb75d6b82018-08-13 16:05:33 +0200496
497 // Start with a keyframe.
498 uint32_t timestamp = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100499 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
500 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100501 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200502
503 // Do a full cycle of the pattern.
504 for (int i = 0; i < 7; ++i) {
Elad Aloncde8ab22019-03-20 11:56:20 +0100505 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
506 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100507 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200508 }
509
510 // TL0 base layer frame, starting the cycle over.
Elad Aloncde8ab22019-03-20 11:56:20 +0100511 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
512 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100513 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200514
515 // TL2 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100516 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
517 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100518 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200519
520 // Encoder has a hiccup and builds a queue, so frame encoding is delayed.
521 // TL1 frame, updating golden.
Elad Aloncde8ab22019-03-20 11:56:20 +0100522 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
Erik Språngb75d6b82018-08-13 16:05:33 +0200523
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 Aloncde8ab22019-03-20 11:56:20 +0100526 tl_config = tl.UpdateLayerConfig(0, timestamp + 1);
Erik Språngb75d6b82018-08-13 16:05:33 +0200527 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 Aloncde8ab22019-03-20 11:56:20 +0100532 tl_config = tl.UpdateLayerConfig(0, timestamp + 2);
Erik Språngb75d6b82018-08-13 16:05:33 +0200533
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 Aloncde8ab22019-03-20 11:56:20 +0100537 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100538 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200539 // Enqueued TL2 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100540 tl.OnEncodeDone(0, ++timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100541 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200542 // Enqueued TL0 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100543 tl.OnEncodeDone(0, ++timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100544 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200545
546 // TL2 frame, all buffers are now in a known good state, OK to reference.
Elad Aloncde8ab22019-03-20 11:56:20 +0100547 tl_config = tl.UpdateLayerConfig(0, ++timestamp + 1);
Erik Språngb75d6b82018-08-13 16:05:33 +0200548 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 Alonf5b216a2019-01-28 14:25:17 +0100553TEST_F(TemporalLayersTest, DoesNotReferenceUnlessGuaranteedToExistLongDelay) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200554 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 Aloncde8ab22019-03-20 11:56:20 +0100561 tl.OnRatesUpdated(0,
562 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200563 kDefaultFramerate, kNumLayers),
564 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100565 tl.UpdateConfiguration(0, &cfg);
Erik Språngb75d6b82018-08-13 16:05:33 +0200566
567 // Start with a keyframe.
568 uint32_t timestamp = 0;
Elad Aloncde8ab22019-03-20 11:56:20 +0100569 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
570 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100571 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200572
573 // Do a full cycle of the pattern.
574 for (int i = 0; i < 3; ++i) {
Elad Aloncde8ab22019-03-20 11:56:20 +0100575 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
576 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100577 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200578 }
579
580 // TL0 base layer frame, starting the cycle over.
Elad Aloncde8ab22019-03-20 11:56:20 +0100581 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
582 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100583 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200584
585 // TL2 frame.
Elad Aloncde8ab22019-03-20 11:56:20 +0100586 tl_config = tl.UpdateLayerConfig(0, ++timestamp);
587 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100588 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200589
590 // Encoder has a hiccup and builds a queue, so frame encoding is delayed.
591 // Encoded, but delayed frames in TL 1, 2.
Elad Aloncde8ab22019-03-20 11:56:20 +0100592 tl_config = tl.UpdateLayerConfig(0, timestamp + 1);
593 tl_config = tl.UpdateLayerConfig(0, timestamp + 2);
Erik Språngb75d6b82018-08-13 16:05:33 +0200594
595 // Restart of the pattern!
596
597 // Encoded, but delayed frames in TL 2, 1.
Elad Aloncde8ab22019-03-20 11:56:20 +0100598 tl_config = tl.UpdateLayerConfig(0, timestamp + 3);
599 tl_config = tl.UpdateLayerConfig(0, timestamp + 4);
Erik Språngb75d6b82018-08-13 16:05:33 +0200600
601 // TL1 frame from last cycle is ready.
Elad Aloncde8ab22019-03-20 11:56:20 +0100602 tl.OnEncodeDone(0, timestamp + 1, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100603 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200604 // TL2 frame from last cycle is ready.
Elad Aloncde8ab22019-03-20 11:56:20 +0100605 tl.OnEncodeDone(0, timestamp + 2, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100606 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200607
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 Aloncde8ab22019-03-20 11:56:20 +0100611 tl_config = tl.UpdateLayerConfig(0, timestamp + 5);
Erik Språngb75d6b82018-08-13 16:05:33 +0200612 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 Alonf5b216a2019-01-28 14:25:17 +0100617TEST_F(TemporalLayersTest, KeyFrame) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200618 constexpr int kNumLayers = 3;
619 DefaultTemporalLayers tl(kNumLayers);
620 DefaultTemporalLayersChecker checker(kNumLayers);
621 Vp8EncoderConfig cfg;
Elad Aloncde8ab22019-03-20 11:56:20 +0100622 tl.OnRatesUpdated(0,
623 GetTemporalLayerRates(kDefaultBytesPerFrame,
Erik Språngb75d6b82018-08-13 16:05:33 +0200624 kDefaultFramerate, kNumLayers),
625 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100626 tl.UpdateConfiguration(0, &cfg);
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000627
628 int expected_flags[8] = {
sprangff19d352017-09-06 07:14:02 -0700629 kTemporalUpdateLastRefAltRef,
marpan@webrtc.org1e685772012-08-31 21:17:12 +0000630 kTemporalUpdateNoneNoRefGolden,
631 kTemporalUpdateGoldenWithoutDependencyRefAltRef,
632 kTemporalUpdateNone,
633 kTemporalUpdateLastRefAltRef,
634 kTemporalUpdateNone,
635 kTemporalUpdateGoldenRefAltRef,
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000636 kTemporalUpdateNone,
637 };
pbos1777c5f2017-07-19 17:04:02 -0700638 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2};
Erik Språngb75d6b82018-08-13 16:05:33 +0200639 bool expected_layer_sync[8] = {true, true, true, false,
pbos1777c5f2017-07-19 17:04:02 -0700640 false, false, false, false};
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000641
stefan@webrtc.orgeb917922013-02-18 14:40:18 +0000642 uint32_t timestamp = 0;
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000643 for (int i = 0; i < 7; ++i) {
Erik Språngb75d6b82018-08-13 16:05:33 +0200644 // 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 Aloncde8ab22019-03-20 11:56:20 +0100649 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
Erik Språngb75d6b82018-08-13 16:05:33 +0200650 EXPECT_EQ(expected_flags[j], LibvpxVp8Encoder::EncodeFlags(tl_config))
651 << j;
Elad Aloncde8ab22019-03-20 11:56:20 +0100652 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, false, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100653 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200654 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 Alonf5b216a2019-01-28 14:25:17 +0100661 CodecSpecificInfo info;
Elad Aloncde8ab22019-03-20 11:56:20 +0100662 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp);
663 tl.OnEncodeDone(0, timestamp, kDefaultBytesPerFrame, true, kDefaultQp,
664 &info);
philipel9df33532019-03-04 16:37:50 +0100665 EXPECT_TRUE(info.codecSpecific.VP8.layerSync)
666 << "Key frame should be marked layer sync.";
667 EXPECT_EQ(0, info.codecSpecific.VP8.temporalIdx)
pbos1777c5f2017-07-19 17:04:02 -0700668 << "Key frame should always be packetized as layer 0";
Erik Språngb75d6b82018-08-13 16:05:33 +0200669 EXPECT_TRUE(checker.CheckTemporalConfig(true, tl_config));
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000670 }
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000671}
sprangff19d352017-09-06 07:14:02 -0700672
Elad Alonf5b216a2019-01-28 14:25:17 +0100673class TemporalLayersReferenceTest : public TemporalLayersTest,
674 public ::testing::WithParamInterface<int> {
sprangff19d352017-09-06 07:14:02 -0700675 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 Alon411b49b2019-01-29 14:05:55 +0100694 bool UpdateSyncRefState(const BufferFlags& flags, BufferState* buffer_state) {
695 if (flags & BufferFlags::kReference) {
sprangff19d352017-09-06 07:14:02 -0700696 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 Alon411b49b2019-01-29 14:05:55 +0100709 void ValidateReference(const BufferFlags& flags,
sprangff19d352017-09-06 07:14:02 -0700710 const BufferState& buffer_state,
711 int temporal_layer) {
Elad Alon411b49b2019-01-29 14:05:55 +0100712 if (flags & BufferFlags::kReference) {
sprangff19d352017-09-06 07:14:02 -0700713 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 Bonadeic84f6612019-01-31 12:20:57 +0100731INSTANTIATE_TEST_SUITE_P(DefaultTemporalLayersTest,
732 TemporalLayersReferenceTest,
733 ::testing::Range(1, kMaxTemporalStreams + 1));
sprangff19d352017-09-06 07:14:02 -0700734
735TEST_P(TemporalLayersReferenceTest, ValidFrameConfigs) {
736 const int num_layers = GetParam();
Niels Möller150dcb02018-03-27 14:16:55 +0200737 DefaultTemporalLayers tl(num_layers);
Anders Carlssonbeabdcb2018-01-24 10:25:15 +0100738 Vp8EncoderConfig cfg;
Erik Språngb75d6b82018-08-13 16:05:33 +0200739 tl.OnRatesUpdated(
Elad Aloncde8ab22019-03-20 11:56:20 +0100740 0, GetTemporalLayerRates(kDefaultBytesPerFrame, kDefaultFramerate, 1),
Erik Språngb75d6b82018-08-13 16:05:33 +0200741 kDefaultFramerate);
Elad Aloncde8ab22019-03-20 11:56:20 +0100742 tl.UpdateConfiguration(0, &cfg);
sprangff19d352017-09-06 07:14:02 -0700743
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 Alon411b49b2019-01-29 14:05:55 +0100749 std::vector<Vp8FrameConfig> tl_configs(kMaxPatternLength);
sprangff19d352017-09-06 07:14:02 -0700750 for (int i = 0; i < kMaxPatternLength; ++i) {
Elad Aloncde8ab22019-03-20 11:56:20 +0100751 Vp8FrameConfig tl_config = tl.UpdateLayerConfig(0, timestamp_);
752 tl.OnEncodeDone(0, timestamp_, kDefaultBytesPerFrame, i == 0, kDefaultQp,
philipel9df33532019-03-04 16:37:50 +0100753 IgnoredCodecSpecificInfo());
Erik Språngb75d6b82018-08-13 16:05:33 +0200754 ++timestamp_;
sprangff19d352017-09-06 07:14:02 -0700755 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 Alon411b49b2019-01-29 14:05:55 +0100792 if (tl_config.last_buffer_flags & BufferFlags::kUpdate)
sprangff19d352017-09-06 07:14:02 -0700793 last_state = state;
Elad Alon411b49b2019-01-29 14:05:55 +0100794 if (tl_config.golden_buffer_flags & BufferFlags::kUpdate)
sprangff19d352017-09-06 07:14:02 -0700795 golden_state = state;
Elad Alon411b49b2019-01-29 14:05:55 +0100796 if (tl_config.arf_buffer_flags & BufferFlags::kUpdate)
sprangff19d352017-09-06 07:14:02 -0700797 altref_state = state;
798 }
799}
800} // namespace test
pwestin@webrtc.orgdb221d22011-12-02 11:31:08 +0000801} // namespace webrtc