OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" | 11 #include "webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.h" |
12 #include "vpx/vp8cx.h" | 12 #include "vpx/vp8cx.h" |
13 #include "vpx/vpx_encoder.h" | 13 #include "vpx/vpx_encoder.h" |
14 #include "webrtc/modules/video_coding/codecs/vp8/vp8_impl.h" | 14 #include "webrtc/modules/video_coding/codecs/vp8/vp8_impl.h" |
15 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 15 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
| 16 #include "webrtc/test/field_trial.h" |
16 #include "webrtc/test/gtest.h" | 17 #include "webrtc/test/gtest.h" |
17 | 18 |
18 namespace webrtc { | 19 namespace webrtc { |
| 20 namespace test { |
19 | 21 |
20 enum { | 22 enum { |
21 kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | | 23 kTemporalUpdateLast = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
22 VP8_EFLAG_NO_REF_GF | | 24 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF, |
23 VP8_EFLAG_NO_REF_ARF, | |
24 kTemporalUpdateGoldenWithoutDependency = | 25 kTemporalUpdateGoldenWithoutDependency = |
25 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | | 26 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | |
26 VP8_EFLAG_NO_UPD_LAST, | 27 VP8_EFLAG_NO_UPD_LAST, |
27 kTemporalUpdateGolden = | 28 kTemporalUpdateGolden = |
28 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, | 29 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
29 kTemporalUpdateAltrefWithoutDependency = | 30 kTemporalUpdateAltrefWithoutDependency = |
30 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | | 31 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | |
31 VP8_EFLAG_NO_UPD_LAST, | 32 VP8_EFLAG_NO_UPD_LAST, |
32 kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, | 33 kTemporalUpdateAltref = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST, |
33 kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | | 34 kTemporalUpdateNone = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
34 VP8_EFLAG_NO_UPD_LAST | | 35 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
35 VP8_EFLAG_NO_UPD_ENTROPY, | 36 kTemporalUpdateNoneNoRefAltRef = |
36 kTemporalUpdateNoneNoRefAltRef = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | | 37 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
37 VP8_EFLAG_NO_UPD_ARF | | 38 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
38 VP8_EFLAG_NO_UPD_LAST | | 39 kTemporalUpdateNoneNoRefGolden = |
39 VP8_EFLAG_NO_UPD_ENTROPY, | 40 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | |
40 kTemporalUpdateNoneNoRefGolden = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | | 41 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
41 VP8_EFLAG_NO_UPD_ARF | | 42 kTemporalUpdateNoneNoRefGoldenAltRef = |
42 VP8_EFLAG_NO_UPD_LAST | | 43 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_REF_ARF | |
43 VP8_EFLAG_NO_UPD_ENTROPY, | 44 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY, |
44 kTemporalUpdateGoldenWithoutDependencyRefAltRef = | 45 kTemporalUpdateGoldenWithoutDependencyRefAltRef = |
45 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, | 46 VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
46 kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, | 47 kTemporalUpdateGoldenRefAltRef = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST, |
47 kTemporalUpdateLastRefAltRef = | 48 kTemporalUpdateLastRefAltRef = |
48 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, | 49 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, |
49 kTemporalUpdateLastAndGoldenRefAltRef = | 50 kTemporalUpdateLastAndGoldenRefAltRef = |
50 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, | 51 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF, |
51 }; | 52 }; |
52 | 53 |
53 TEST(TemporalLayersTest, 2Layers) { | 54 TEST(TemporalLayersTest, 2Layers) { |
54 DefaultTemporalLayers tl(2, 0); | 55 DefaultTemporalLayers tl(2, 0); |
55 vpx_codec_enc_cfg_t cfg; | 56 vpx_codec_enc_cfg_t cfg; |
56 CodecSpecificInfoVP8 vp8_info; | 57 CodecSpecificInfoVP8 vp8_info; |
57 tl.OnRatesUpdated(500, 500, 30); | 58 tl.OnRatesUpdated(500, 500, 30); |
58 tl.UpdateConfiguration(&cfg); | 59 tl.UpdateConfiguration(&cfg); |
59 | 60 |
60 int expected_flags[16] = { | 61 int expected_flags[16] = { |
61 kTemporalUpdateLastAndGoldenRefAltRef, | 62 kTemporalUpdateLastRefAltRef, |
62 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 63 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
63 kTemporalUpdateLastRefAltRef, | 64 kTemporalUpdateLastRefAltRef, |
64 kTemporalUpdateGoldenRefAltRef, | 65 kTemporalUpdateGoldenRefAltRef, |
65 kTemporalUpdateLastRefAltRef, | 66 kTemporalUpdateLastRefAltRef, |
66 kTemporalUpdateGoldenRefAltRef, | 67 kTemporalUpdateGoldenRefAltRef, |
67 kTemporalUpdateLastRefAltRef, | 68 kTemporalUpdateLastRefAltRef, |
68 kTemporalUpdateNone, | 69 kTemporalUpdateNone, |
69 kTemporalUpdateLastAndGoldenRefAltRef, | 70 kTemporalUpdateLastRefAltRef, |
70 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 71 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
71 kTemporalUpdateLastRefAltRef, | 72 kTemporalUpdateLastRefAltRef, |
72 kTemporalUpdateGoldenRefAltRef, | 73 kTemporalUpdateGoldenRefAltRef, |
73 kTemporalUpdateLastRefAltRef, | 74 kTemporalUpdateLastRefAltRef, |
74 kTemporalUpdateGoldenRefAltRef, | 75 kTemporalUpdateGoldenRefAltRef, |
75 kTemporalUpdateLastRefAltRef, | 76 kTemporalUpdateLastRefAltRef, |
76 kTemporalUpdateNone, | 77 kTemporalUpdateNone, |
77 }; | 78 }; |
78 int expected_temporal_idx[16] = {0, 1, 0, 1, 0, 1, 0, 1, | 79 int expected_temporal_idx[16] = {0, 1, 0, 1, 0, 1, 0, 1, |
79 0, 1, 0, 1, 0, 1, 0, 1}; | 80 0, 1, 0, 1, 0, 1, 0, 1}; |
80 | 81 |
81 bool expected_layer_sync[16] = {false, true, false, false, false, false, | 82 bool expected_layer_sync[16] = {false, true, false, false, false, false, |
82 false, false, false, true, false, false, | 83 false, false, false, true, false, false, |
83 false, false, false, false}; | 84 false, false, false, false}; |
84 | 85 |
85 uint32_t timestamp = 0; | 86 uint32_t timestamp = 0; |
86 for (int i = 0; i < 16; ++i) { | 87 for (int i = 0; i < 16; ++i) { |
87 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 88 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
88 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 89 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
89 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 90 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
90 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); | 91 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
91 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 92 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
92 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 93 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
93 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); | 94 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
94 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 95 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
95 timestamp += 3000; | 96 timestamp += 3000; |
96 } | 97 } |
97 } | 98 } |
98 | 99 |
99 TEST(TemporalLayersTest, 3Layers) { | 100 TEST(TemporalLayersTest, 3Layers) { |
100 DefaultTemporalLayers tl(3, 0); | 101 DefaultTemporalLayers tl(3, 0); |
101 vpx_codec_enc_cfg_t cfg; | 102 vpx_codec_enc_cfg_t cfg; |
102 CodecSpecificInfoVP8 vp8_info; | 103 CodecSpecificInfoVP8 vp8_info; |
103 tl.OnRatesUpdated(500, 500, 30); | 104 tl.OnRatesUpdated(500, 500, 30); |
104 tl.UpdateConfiguration(&cfg); | 105 tl.UpdateConfiguration(&cfg); |
105 | 106 |
106 int expected_flags[16] = { | 107 int expected_flags[16] = { |
107 kTemporalUpdateLastAndGoldenRefAltRef, | 108 kTemporalUpdateLastRefAltRef, |
108 kTemporalUpdateNoneNoRefGolden, | 109 kTemporalUpdateNoneNoRefGolden, |
109 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 110 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
110 kTemporalUpdateNone, | 111 kTemporalUpdateNone, |
111 kTemporalUpdateLastRefAltRef, | 112 kTemporalUpdateLastRefAltRef, |
112 kTemporalUpdateNone, | 113 kTemporalUpdateNone, |
113 kTemporalUpdateGoldenRefAltRef, | 114 kTemporalUpdateGoldenRefAltRef, |
114 kTemporalUpdateNone, | 115 kTemporalUpdateNone, |
115 kTemporalUpdateLastAndGoldenRefAltRef, | 116 kTemporalUpdateLastRefAltRef, |
116 kTemporalUpdateNoneNoRefGolden, | 117 kTemporalUpdateNoneNoRefGolden, |
117 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 118 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
118 kTemporalUpdateNone, | 119 kTemporalUpdateNone, |
119 kTemporalUpdateLastRefAltRef, | 120 kTemporalUpdateLastRefAltRef, |
120 kTemporalUpdateNone, | 121 kTemporalUpdateNone, |
121 kTemporalUpdateGoldenRefAltRef, | 122 kTemporalUpdateGoldenRefAltRef, |
122 kTemporalUpdateNone, | 123 kTemporalUpdateNone, |
123 }; | 124 }; |
124 int expected_temporal_idx[16] = {0, 2, 1, 2, 0, 2, 1, 2, | 125 int expected_temporal_idx[16] = {0, 2, 1, 2, 0, 2, 1, 2, |
125 0, 2, 1, 2, 0, 2, 1, 2}; | 126 0, 2, 1, 2, 0, 2, 1, 2}; |
126 | 127 |
127 bool expected_layer_sync[16] = {false, true, true, false, false, false, | 128 bool expected_layer_sync[16] = {false, true, true, false, false, false, |
128 false, false, false, true, true, false, | 129 false, false, false, true, true, false, |
129 false, false, false, false}; | 130 false, false, false, false}; |
130 | 131 |
131 unsigned int timestamp = 0; | 132 unsigned int timestamp = 0; |
132 for (int i = 0; i < 16; ++i) { | 133 for (int i = 0; i < 16; ++i) { |
133 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 134 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
134 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 135 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
135 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 136 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
136 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); | 137 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
137 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 138 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
| 139 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
| 140 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
| 141 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
| 142 timestamp += 3000; |
| 143 } |
| 144 } |
| 145 |
| 146 TEST(TemporalLayersTest, Alternative3Layers) { |
| 147 ScopedFieldTrials field_trial("WebRTC-UseShortVP8TL3Pattern/Enabled/"); |
| 148 DefaultTemporalLayers tl(3, 0); |
| 149 vpx_codec_enc_cfg_t cfg; |
| 150 CodecSpecificInfoVP8 vp8_info; |
| 151 tl.OnRatesUpdated(500, 500, 30); |
| 152 tl.UpdateConfiguration(&cfg); |
| 153 |
| 154 int expected_flags[8] = {kTemporalUpdateLast, |
| 155 kTemporalUpdateAltrefWithoutDependency, |
| 156 kTemporalUpdateGoldenWithoutDependency, |
| 157 kTemporalUpdateNone, |
| 158 kTemporalUpdateLast, |
| 159 kTemporalUpdateAltrefWithoutDependency, |
| 160 kTemporalUpdateGoldenWithoutDependency, |
| 161 kTemporalUpdateNone}; |
| 162 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; |
| 163 |
| 164 bool expected_layer_sync[8] = {false, true, true, false, |
| 165 false, true, true, false}; |
| 166 |
| 167 unsigned int timestamp = 0; |
| 168 for (int i = 0; i < 8; ++i) { |
| 169 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
| 170 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
| 171 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
| 172 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
| 173 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
138 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 174 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
139 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); | 175 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
140 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 176 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
141 timestamp += 3000; | 177 timestamp += 3000; |
142 } | 178 } |
143 } | 179 } |
144 | 180 |
145 TEST(TemporalLayersTest, 4Layers) { | 181 TEST(TemporalLayersTest, 4Layers) { |
146 DefaultTemporalLayers tl(4, 0); | 182 DefaultTemporalLayers tl(4, 0); |
147 vpx_codec_enc_cfg_t cfg; | 183 vpx_codec_enc_cfg_t cfg; |
148 CodecSpecificInfoVP8 vp8_info; | 184 CodecSpecificInfoVP8 vp8_info; |
149 tl.OnRatesUpdated(500, 500, 30); | 185 tl.OnRatesUpdated(500, 500, 30); |
150 tl.UpdateConfiguration(&cfg); | 186 tl.UpdateConfiguration(&cfg); |
151 int expected_flags[16] = { | 187 int expected_flags[16] = { |
152 kTemporalUpdateLast, | 188 kTemporalUpdateLast, |
153 kTemporalUpdateNone, | 189 kTemporalUpdateNoneNoRefGoldenAltRef, |
154 kTemporalUpdateAltrefWithoutDependency, | 190 kTemporalUpdateAltrefWithoutDependency, |
155 kTemporalUpdateNone, | 191 kTemporalUpdateNoneNoRefGolden, |
156 kTemporalUpdateGoldenWithoutDependency, | 192 kTemporalUpdateGoldenWithoutDependency, |
157 kTemporalUpdateNone, | 193 kTemporalUpdateNone, |
158 kTemporalUpdateAltref, | 194 kTemporalUpdateAltref, |
159 kTemporalUpdateNone, | 195 kTemporalUpdateNone, |
160 kTemporalUpdateLast, | 196 kTemporalUpdateLast, |
161 kTemporalUpdateNone, | 197 kTemporalUpdateNone, |
162 kTemporalUpdateAltref, | 198 kTemporalUpdateAltref, |
163 kTemporalUpdateNone, | 199 kTemporalUpdateNone, |
164 kTemporalUpdateGolden, | 200 kTemporalUpdateGolden, |
165 kTemporalUpdateNone, | 201 kTemporalUpdateNone, |
166 kTemporalUpdateAltref, | 202 kTemporalUpdateAltref, |
167 kTemporalUpdateNone, | 203 kTemporalUpdateNone, |
168 }; | 204 }; |
169 int expected_temporal_idx[16] = {0, 3, 2, 3, 1, 3, 2, 3, | 205 int expected_temporal_idx[16] = {0, 3, 2, 3, 1, 3, 2, 3, |
170 0, 3, 2, 3, 1, 3, 2, 3}; | 206 0, 3, 2, 3, 1, 3, 2, 3}; |
171 | 207 |
172 bool expected_layer_sync[16] = {false, true, true, true, true, true, | 208 bool expected_layer_sync[16] = {false, true, true, false, true, false, |
173 false, true, false, true, false, true, | 209 false, false, false, false, false, false, |
174 false, true, false, true}; | 210 false, false, false, false}; |
175 | 211 |
176 uint32_t timestamp = 0; | 212 uint32_t timestamp = 0; |
177 for (int i = 0; i < 16; ++i) { | 213 for (int i = 0; i < 16; ++i) { |
178 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 214 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
179 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 215 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
180 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 216 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
181 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); | 217 EXPECT_EQ(expected_temporal_idx[i], vp8_info.temporalIdx); |
182 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 218 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
183 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 219 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
184 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); | 220 EXPECT_EQ(expected_layer_sync[i], vp8_info.layerSync); |
185 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 221 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
186 timestamp += 3000; | 222 timestamp += 3000; |
187 } | 223 } |
188 } | 224 } |
189 | 225 |
190 TEST(TemporalLayersTest, KeyFrame) { | 226 TEST(TemporalLayersTest, KeyFrame) { |
191 DefaultTemporalLayers tl(3, 0); | 227 DefaultTemporalLayers tl(3, 0); |
192 vpx_codec_enc_cfg_t cfg; | 228 vpx_codec_enc_cfg_t cfg; |
193 CodecSpecificInfoVP8 vp8_info; | 229 CodecSpecificInfoVP8 vp8_info; |
194 tl.OnRatesUpdated(500, 500, 30); | 230 tl.OnRatesUpdated(500, 500, 30); |
195 tl.UpdateConfiguration(&cfg); | 231 tl.UpdateConfiguration(&cfg); |
196 | 232 |
197 int expected_flags[8] = { | 233 int expected_flags[8] = { |
198 kTemporalUpdateLastAndGoldenRefAltRef, | 234 kTemporalUpdateLastRefAltRef, |
199 kTemporalUpdateNoneNoRefGolden, | 235 kTemporalUpdateNoneNoRefGolden, |
200 kTemporalUpdateGoldenWithoutDependencyRefAltRef, | 236 kTemporalUpdateGoldenWithoutDependencyRefAltRef, |
201 kTemporalUpdateNone, | 237 kTemporalUpdateNone, |
202 kTemporalUpdateLastRefAltRef, | 238 kTemporalUpdateLastRefAltRef, |
203 kTemporalUpdateNone, | 239 kTemporalUpdateNone, |
204 kTemporalUpdateGoldenRefAltRef, | 240 kTemporalUpdateGoldenRefAltRef, |
205 kTemporalUpdateNone, | 241 kTemporalUpdateNone, |
206 }; | 242 }; |
207 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; | 243 int expected_temporal_idx[8] = {0, 2, 1, 2, 0, 2, 1, 2}; |
208 bool expected_layer_sync[8] = {false, true, true, false, | 244 bool expected_layer_sync[8] = {false, true, true, false, |
209 false, false, false, false}; | 245 false, false, false, false}; |
210 | 246 |
211 uint32_t timestamp = 0; | 247 uint32_t timestamp = 0; |
212 for (int i = 0; i < 7; ++i) { | 248 for (int i = 0; i < 7; ++i) { |
213 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 249 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
214 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)); | 250 EXPECT_EQ(expected_flags[i], VP8EncoderImpl::EncodeFlags(tl_config)) << i; |
215 tl.PopulateCodecSpecific(true, tl_config, &vp8_info, 0); | 251 tl.PopulateCodecSpecific(true, tl_config, &vp8_info, 0); |
216 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); | 252 EXPECT_EQ(expected_temporal_idx[i], tl_config.packetizer_temporal_idx); |
217 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); | 253 EXPECT_EQ(expected_temporal_idx[i], tl_config.encoder_layer_id); |
218 EXPECT_EQ(0, vp8_info.temporalIdx) | 254 EXPECT_EQ(0, vp8_info.temporalIdx) |
219 << "Key frame should always be packetized as layer 0"; | 255 << "Key frame should always be packetized as layer 0"; |
220 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); | 256 EXPECT_EQ(expected_layer_sync[i], tl_config.layer_sync); |
221 EXPECT_TRUE(vp8_info.layerSync) << "Key frame should be marked layer sync."; | 257 EXPECT_TRUE(vp8_info.layerSync) << "Key frame should be marked layer sync."; |
222 timestamp += 3000; | 258 timestamp += 3000; |
223 } | 259 } |
224 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); | 260 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp); |
225 EXPECT_EQ(expected_flags[7], VP8EncoderImpl::EncodeFlags(tl_config)); | 261 EXPECT_EQ(expected_flags[7], VP8EncoderImpl::EncodeFlags(tl_config)); |
226 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); | 262 tl.PopulateCodecSpecific(false, tl_config, &vp8_info, 0); |
227 EXPECT_NE(0, vp8_info.temporalIdx) | 263 EXPECT_NE(0, vp8_info.temporalIdx) |
228 << "To test something useful, this frame should not use layer 0."; | 264 << "To test something useful, this frame should not use layer 0."; |
229 EXPECT_EQ(expected_temporal_idx[7], vp8_info.temporalIdx) | 265 EXPECT_EQ(expected_temporal_idx[7], vp8_info.temporalIdx) |
230 << "Non-keyframe, should use frame temporal index."; | 266 << "Non-keyframe, should use frame temporal index."; |
231 EXPECT_EQ(expected_temporal_idx[7], tl_config.packetizer_temporal_idx); | 267 EXPECT_EQ(expected_temporal_idx[7], tl_config.packetizer_temporal_idx); |
232 EXPECT_EQ(expected_temporal_idx[7], tl_config.encoder_layer_id); | 268 EXPECT_EQ(expected_temporal_idx[7], tl_config.encoder_layer_id); |
233 EXPECT_FALSE(tl_config.layer_sync); | 269 EXPECT_FALSE(tl_config.layer_sync); |
234 EXPECT_TRUE(vp8_info.layerSync) << "Frame after keyframe should always be " | 270 EXPECT_TRUE(vp8_info.layerSync) << "Frame after keyframe should always be " |
235 "marked layer sync since it only depends " | 271 "marked layer sync since it only depends " |
236 "on the base layer."; | 272 "on the base layer."; |
237 } | 273 } |
| 274 |
| 275 class TemporalLayersReferenceTest : public ::testing::TestWithParam<int> { |
| 276 public: |
| 277 TemporalLayersReferenceTest() |
| 278 : timestamp_(1), |
| 279 last_sync_timestamp_(timestamp_), |
| 280 tl0_reference_(nullptr) {} |
| 281 virtual ~TemporalLayersReferenceTest() {} |
| 282 |
| 283 protected: |
| 284 static const int kMaxPatternLength = 32; |
| 285 |
| 286 struct BufferState { |
| 287 BufferState() : BufferState(-1, 0, false) {} |
| 288 BufferState(int temporal_idx, uint32_t timestamp, bool sync) |
| 289 : temporal_idx(temporal_idx), timestamp(timestamp), sync(sync) {} |
| 290 int temporal_idx; |
| 291 uint32_t timestamp; |
| 292 bool sync; |
| 293 }; |
| 294 |
| 295 bool UpdateSyncRefState(const TemporalLayers::BufferFlags& flags, |
| 296 BufferState* buffer_state) { |
| 297 if (flags & TemporalLayers::kReference) { |
| 298 if (buffer_state->temporal_idx == -1) |
| 299 return true; // References key-frame. |
| 300 if (buffer_state->temporal_idx == 0) { |
| 301 // No more than one reference to TL0 frame. |
| 302 EXPECT_EQ(nullptr, tl0_reference_); |
| 303 tl0_reference_ = buffer_state; |
| 304 return true; |
| 305 } |
| 306 return false; // References higher layer. |
| 307 } |
| 308 return true; // No reference, does not affect sync frame status. |
| 309 } |
| 310 |
| 311 void ValidateReference(const TemporalLayers::BufferFlags& flags, |
| 312 const BufferState& buffer_state, |
| 313 int temporal_layer) { |
| 314 if (flags & TemporalLayers::kReference) { |
| 315 if (temporal_layer > 0 && buffer_state.timestamp > 0) { |
| 316 // Check that high layer reference does not go past last sync frame. |
| 317 EXPECT_GE(buffer_state.timestamp, last_sync_timestamp_); |
| 318 } |
| 319 // No reference to buffer in higher layer. |
| 320 EXPECT_LE(buffer_state.temporal_idx, temporal_layer); |
| 321 } |
| 322 } |
| 323 |
| 324 uint32_t timestamp_ = 1; |
| 325 uint32_t last_sync_timestamp_ = timestamp_; |
| 326 BufferState* tl0_reference_; |
| 327 |
| 328 BufferState last_state; |
| 329 BufferState golden_state; |
| 330 BufferState altref_state; |
| 331 }; |
| 332 |
| 333 INSTANTIATE_TEST_CASE_P(DefaultTemporalLayersTest, |
| 334 TemporalLayersReferenceTest, |
| 335 ::testing::Range(1, kMaxTemporalStreams + 1)); |
| 336 |
| 337 TEST_P(TemporalLayersReferenceTest, ValidFrameConfigs) { |
| 338 const int num_layers = GetParam(); |
| 339 DefaultTemporalLayers tl(num_layers, 0); |
| 340 vpx_codec_enc_cfg_t cfg; |
| 341 tl.OnRatesUpdated(500, 500, 30); |
| 342 tl.UpdateConfiguration(&cfg); |
| 343 |
| 344 // Run through the pattern and store the frame dependencies, plus keep track |
| 345 // of the buffer state; which buffers references which temporal layers (if |
| 346 // (any). If a given buffer is never updated, it is legal to reference it |
| 347 // even for sync frames. In order to be general, don't assume TL0 always |
| 348 // updates |last|. |
| 349 std::vector<TemporalLayers::FrameConfig> tl_configs(kMaxPatternLength); |
| 350 for (int i = 0; i < kMaxPatternLength; ++i) { |
| 351 TemporalLayers::FrameConfig tl_config = tl.UpdateLayerConfig(timestamp_++); |
| 352 EXPECT_FALSE(tl_config.drop_frame); |
| 353 tl_configs.push_back(tl_config); |
| 354 int temporal_idx = tl_config.encoder_layer_id; |
| 355 // For the default layers, always keep encoder and rtp layers in sync. |
| 356 EXPECT_EQ(tl_config.packetizer_temporal_idx, temporal_idx); |
| 357 |
| 358 // Determine if this frame is in a higher layer but references only TL0 |
| 359 // or untouched buffers, if so verify it is marked as a layer sync. |
| 360 bool is_sync_frame = true; |
| 361 tl0_reference_ = nullptr; |
| 362 if (temporal_idx <= 0) { |
| 363 is_sync_frame = false; // TL0 by definition not a sync frame. |
| 364 } else if (!UpdateSyncRefState(tl_config.last_buffer_flags, &last_state)) { |
| 365 is_sync_frame = false; |
| 366 } else if (!UpdateSyncRefState(tl_config.golden_buffer_flags, |
| 367 &golden_state)) { |
| 368 is_sync_frame = false; |
| 369 } else if (!UpdateSyncRefState(tl_config.arf_buffer_flags, &altref_state)) { |
| 370 is_sync_frame = false; |
| 371 } |
| 372 if (is_sync_frame) { |
| 373 // Cache timestamp for last found sync frame, so that we can verify no |
| 374 // references back past this frame. |
| 375 ASSERT_TRUE(tl0_reference_); |
| 376 last_sync_timestamp_ = tl0_reference_->timestamp; |
| 377 } |
| 378 EXPECT_EQ(tl_config.layer_sync, is_sync_frame); |
| 379 |
| 380 // Validate no reference from lower to high temporal layer, or backwards |
| 381 // past last reference frame. |
| 382 ValidateReference(tl_config.last_buffer_flags, last_state, temporal_idx); |
| 383 ValidateReference(tl_config.golden_buffer_flags, golden_state, |
| 384 temporal_idx); |
| 385 ValidateReference(tl_config.arf_buffer_flags, altref_state, temporal_idx); |
| 386 |
| 387 // Update the current layer state. |
| 388 BufferState state = {temporal_idx, timestamp_, is_sync_frame}; |
| 389 if (tl_config.last_buffer_flags & TemporalLayers::kUpdate) |
| 390 last_state = state; |
| 391 if (tl_config.golden_buffer_flags & TemporalLayers::kUpdate) |
| 392 golden_state = state; |
| 393 if (tl_config.arf_buffer_flags & TemporalLayers::kUpdate) |
| 394 altref_state = state; |
| 395 } |
| 396 } |
| 397 } // namespace test |
238 } // namespace webrtc | 398 } // namespace webrtc |
OLD | NEW |