OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 |
(...skipping 26 matching lines...) Expand all Loading... |
37 const int kDefaultHeight = 720; | 37 const int kDefaultHeight = 720; |
38 const int kNumberOfSimulcastStreams = 3; | 38 const int kNumberOfSimulcastStreams = 3; |
39 const int kColorY = 66; | 39 const int kColorY = 66; |
40 const int kColorU = 22; | 40 const int kColorU = 22; |
41 const int kColorV = 33; | 41 const int kColorV = 33; |
42 const int kMaxBitrates[kNumberOfSimulcastStreams] = {150, 600, 1200}; | 42 const int kMaxBitrates[kNumberOfSimulcastStreams] = {150, 600, 1200}; |
43 const int kMinBitrates[kNumberOfSimulcastStreams] = {50, 150, 600}; | 43 const int kMinBitrates[kNumberOfSimulcastStreams] = {50, 150, 600}; |
44 const int kTargetBitrates[kNumberOfSimulcastStreams] = {100, 450, 1000}; | 44 const int kTargetBitrates[kNumberOfSimulcastStreams] = {100, 450, 1000}; |
45 const int kDefaultTemporalLayerProfile[3] = {3, 3, 3}; | 45 const int kDefaultTemporalLayerProfile[3] = {3, 3, 3}; |
46 | 46 |
47 template<typename T> void SetExpectedValues3(T value0, | 47 template <typename T> |
48 T value1, | 48 void SetExpectedValues3(T value0, T value1, T value2, T* expected_values) { |
49 T value2, | |
50 T* expected_values) { | |
51 expected_values[0] = value0; | 49 expected_values[0] = value0; |
52 expected_values[1] = value1; | 50 expected_values[1] = value1; |
53 expected_values[2] = value2; | 51 expected_values[2] = value2; |
54 } | 52 } |
55 | 53 |
56 class Vp8TestEncodedImageCallback : public EncodedImageCallback { | 54 class Vp8TestEncodedImageCallback : public EncodedImageCallback { |
57 public: | 55 public: |
58 Vp8TestEncodedImageCallback() | 56 Vp8TestEncodedImageCallback() : picture_id_(-1) { |
59 : picture_id_(-1) { | |
60 memset(temporal_layer_, -1, sizeof(temporal_layer_)); | 57 memset(temporal_layer_, -1, sizeof(temporal_layer_)); |
61 memset(layer_sync_, false, sizeof(layer_sync_)); | 58 memset(layer_sync_, false, sizeof(layer_sync_)); |
62 } | 59 } |
63 | 60 |
64 ~Vp8TestEncodedImageCallback() { | 61 ~Vp8TestEncodedImageCallback() { |
65 delete [] encoded_key_frame_._buffer; | 62 delete[] encoded_key_frame_._buffer; |
66 delete [] encoded_frame_._buffer; | 63 delete[] encoded_frame_._buffer; |
67 } | 64 } |
68 | 65 |
69 virtual int32_t Encoded(const EncodedImage& encoded_image, | 66 virtual int32_t Encoded(const EncodedImage& encoded_image, |
70 const CodecSpecificInfo* codec_specific_info, | 67 const CodecSpecificInfo* codec_specific_info, |
71 const RTPFragmentationHeader* fragmentation) { | 68 const RTPFragmentationHeader* fragmentation) { |
72 // Only store the base layer. | 69 // Only store the base layer. |
73 if (codec_specific_info->codecSpecific.VP8.simulcastIdx == 0) { | 70 if (codec_specific_info->codecSpecific.VP8.simulcastIdx == 0) { |
74 if (encoded_image._frameType == kVideoFrameKey) { | 71 if (encoded_image._frameType == kVideoFrameKey) { |
75 delete [] encoded_key_frame_._buffer; | 72 delete[] encoded_key_frame_._buffer; |
76 encoded_key_frame_._buffer = new uint8_t[encoded_image._size]; | 73 encoded_key_frame_._buffer = new uint8_t[encoded_image._size]; |
77 encoded_key_frame_._size = encoded_image._size; | 74 encoded_key_frame_._size = encoded_image._size; |
78 encoded_key_frame_._length = encoded_image._length; | 75 encoded_key_frame_._length = encoded_image._length; |
79 encoded_key_frame_._frameType = kVideoFrameKey; | 76 encoded_key_frame_._frameType = kVideoFrameKey; |
80 encoded_key_frame_._completeFrame = encoded_image._completeFrame; | 77 encoded_key_frame_._completeFrame = encoded_image._completeFrame; |
81 memcpy(encoded_key_frame_._buffer, | 78 memcpy(encoded_key_frame_._buffer, encoded_image._buffer, |
82 encoded_image._buffer, | |
83 encoded_image._length); | 79 encoded_image._length); |
84 } else { | 80 } else { |
85 delete [] encoded_frame_._buffer; | 81 delete[] encoded_frame_._buffer; |
86 encoded_frame_._buffer = new uint8_t[encoded_image._size]; | 82 encoded_frame_._buffer = new uint8_t[encoded_image._size]; |
87 encoded_frame_._size = encoded_image._size; | 83 encoded_frame_._size = encoded_image._size; |
88 encoded_frame_._length = encoded_image._length; | 84 encoded_frame_._length = encoded_image._length; |
89 memcpy(encoded_frame_._buffer, | 85 memcpy(encoded_frame_._buffer, encoded_image._buffer, |
90 encoded_image._buffer, | |
91 encoded_image._length); | 86 encoded_image._length); |
92 } | 87 } |
93 } | 88 } |
94 picture_id_ = codec_specific_info->codecSpecific.VP8.pictureId; | 89 picture_id_ = codec_specific_info->codecSpecific.VP8.pictureId; |
95 layer_sync_[codec_specific_info->codecSpecific.VP8.simulcastIdx] = | 90 layer_sync_[codec_specific_info->codecSpecific.VP8.simulcastIdx] = |
96 codec_specific_info->codecSpecific.VP8.layerSync; | 91 codec_specific_info->codecSpecific.VP8.layerSync; |
97 temporal_layer_[codec_specific_info->codecSpecific.VP8.simulcastIdx] = | 92 temporal_layer_[codec_specific_info->codecSpecific.VP8.simulcastIdx] = |
98 codec_specific_info->codecSpecific.VP8.temporalIdx; | 93 codec_specific_info->codecSpecific.VP8.temporalIdx; |
99 return 0; | 94 return 0; |
100 } | 95 } |
101 void GetLastEncodedFrameInfo(int* picture_id, int* temporal_layer, | 96 void GetLastEncodedFrameInfo(int* picture_id, |
102 bool* layer_sync, int stream) { | 97 int* temporal_layer, |
| 98 bool* layer_sync, |
| 99 int stream) { |
103 *picture_id = picture_id_; | 100 *picture_id = picture_id_; |
104 *temporal_layer = temporal_layer_[stream]; | 101 *temporal_layer = temporal_layer_[stream]; |
105 *layer_sync = layer_sync_[stream]; | 102 *layer_sync = layer_sync_[stream]; |
106 } | 103 } |
107 void GetLastEncodedKeyFrame(EncodedImage* encoded_key_frame) { | 104 void GetLastEncodedKeyFrame(EncodedImage* encoded_key_frame) { |
108 *encoded_key_frame = encoded_key_frame_; | 105 *encoded_key_frame = encoded_key_frame_; |
109 } | 106 } |
110 void GetLastEncodedFrame(EncodedImage* encoded_frame) { | 107 void GetLastEncodedFrame(EncodedImage* encoded_frame) { |
111 *encoded_frame = encoded_frame_; | 108 *encoded_frame = encoded_frame_; |
112 } | 109 } |
113 | 110 |
114 private: | 111 private: |
115 EncodedImage encoded_key_frame_; | 112 EncodedImage encoded_key_frame_; |
116 EncodedImage encoded_frame_; | 113 EncodedImage encoded_frame_; |
117 int picture_id_; | 114 int picture_id_; |
118 int temporal_layer_[kNumberOfSimulcastStreams]; | 115 int temporal_layer_[kNumberOfSimulcastStreams]; |
119 bool layer_sync_[kNumberOfSimulcastStreams]; | 116 bool layer_sync_[kNumberOfSimulcastStreams]; |
120 }; | 117 }; |
121 | 118 |
122 class Vp8TestDecodedImageCallback : public DecodedImageCallback { | 119 class Vp8TestDecodedImageCallback : public DecodedImageCallback { |
123 public: | 120 public: |
124 Vp8TestDecodedImageCallback() | 121 Vp8TestDecodedImageCallback() : decoded_frames_(0) {} |
125 : decoded_frames_(0) { | |
126 } | |
127 int32_t Decoded(VideoFrame& decoded_image) override { | 122 int32_t Decoded(VideoFrame& decoded_image) override { |
128 for (int i = 0; i < decoded_image.width(); ++i) { | 123 for (int i = 0; i < decoded_image.width(); ++i) { |
129 EXPECT_NEAR(kColorY, decoded_image.buffer(kYPlane)[i], 1); | 124 EXPECT_NEAR(kColorY, decoded_image.buffer(kYPlane)[i], 1); |
130 } | 125 } |
131 | 126 |
132 // TODO(mikhal): Verify the difference between U,V and the original. | 127 // TODO(mikhal): Verify the difference between U,V and the original. |
133 for (int i = 0; i < ((decoded_image.width() + 1) / 2); ++i) { | 128 for (int i = 0; i < ((decoded_image.width() + 1) / 2); ++i) { |
134 EXPECT_NEAR(kColorU, decoded_image.buffer(kUPlane)[i], 4); | 129 EXPECT_NEAR(kColorU, decoded_image.buffer(kUPlane)[i], 4); |
135 EXPECT_NEAR(kColorV, decoded_image.buffer(kVPlane)[i], 4); | 130 EXPECT_NEAR(kColorV, decoded_image.buffer(kVPlane)[i], 4); |
136 } | 131 } |
137 decoded_frames_++; | 132 decoded_frames_++; |
138 return 0; | 133 return 0; |
139 } | 134 } |
140 int32_t Decoded(VideoFrame& decoded_image, int64_t decode_time_ms) override { | 135 int32_t Decoded(VideoFrame& decoded_image, int64_t decode_time_ms) override { |
141 RTC_NOTREACHED(); | 136 RTC_NOTREACHED(); |
142 return -1; | 137 return -1; |
143 } | 138 } |
144 int DecodedFrames() { | 139 int DecodedFrames() { return decoded_frames_; } |
145 return decoded_frames_; | |
146 } | |
147 | 140 |
148 private: | 141 private: |
149 int decoded_frames_; | 142 int decoded_frames_; |
150 }; | 143 }; |
151 | 144 |
152 class SkipEncodingUnusedStreamsTest { | 145 class SkipEncodingUnusedStreamsTest { |
153 public: | 146 public: |
154 std::vector<unsigned int> RunTest(VP8Encoder* encoder, | 147 std::vector<unsigned int> RunTest(VP8Encoder* encoder, |
155 VideoCodec* settings, | 148 VideoCodec* settings, |
156 uint32_t target_bitrate) { | 149 uint32_t target_bitrate) { |
157 Config options; | 150 Config options; |
158 SpyingTemporalLayersFactory* spy_factory = | 151 SpyingTemporalLayersFactory* spy_factory = |
159 new SpyingTemporalLayersFactory(); | 152 new SpyingTemporalLayersFactory(); |
160 options.Set<TemporalLayers::Factory>(spy_factory); | 153 options.Set<TemporalLayers::Factory>(spy_factory); |
161 settings->extra_options = &options; | 154 settings->extra_options = &options; |
162 EXPECT_EQ(0, encoder->InitEncode(settings, 1, 1200)); | 155 EXPECT_EQ(0, encoder->InitEncode(settings, 1, 1200)); |
163 | 156 |
164 encoder->SetRates(target_bitrate, 30); | 157 encoder->SetRates(target_bitrate, 30); |
165 | 158 |
166 std::vector<unsigned int> configured_bitrates; | 159 std::vector<unsigned int> configured_bitrates; |
167 for (std::vector<TemporalLayers*>::const_iterator it = | 160 for (std::vector<TemporalLayers*>::const_iterator it = |
168 spy_factory->spying_layers_.begin(); | 161 spy_factory->spying_layers_.begin(); |
169 it != spy_factory->spying_layers_.end(); | 162 it != spy_factory->spying_layers_.end(); ++it) { |
170 ++it) { | |
171 configured_bitrates.push_back( | 163 configured_bitrates.push_back( |
172 static_cast<SpyingTemporalLayers*>(*it)->configured_bitrate_); | 164 static_cast<SpyingTemporalLayers*>(*it)->configured_bitrate_); |
173 } | 165 } |
174 return configured_bitrates; | 166 return configured_bitrates; |
175 } | 167 } |
176 | 168 |
177 class SpyingTemporalLayers : public TemporalLayers { | 169 class SpyingTemporalLayers : public TemporalLayers { |
178 public: | 170 public: |
179 explicit SpyingTemporalLayers(TemporalLayers* layers) | 171 explicit SpyingTemporalLayers(TemporalLayers* layers) |
180 : configured_bitrate_(0), layers_(layers) {} | 172 : configured_bitrate_(0), layers_(layers) {} |
181 | 173 |
182 virtual ~SpyingTemporalLayers() { delete layers_; } | 174 virtual ~SpyingTemporalLayers() { delete layers_; } |
183 | 175 |
184 virtual int EncodeFlags(uint32_t timestamp) { | 176 virtual int EncodeFlags(uint32_t timestamp) { |
185 return layers_->EncodeFlags(timestamp); | 177 return layers_->EncodeFlags(timestamp); |
186 } | 178 } |
187 | 179 |
188 bool ConfigureBitrates(int bitrate_kbit, | 180 bool ConfigureBitrates(int bitrate_kbit, |
189 int max_bitrate_kbit, | 181 int max_bitrate_kbit, |
190 int framerate, | 182 int framerate, |
191 vpx_codec_enc_cfg_t* cfg) override { | 183 vpx_codec_enc_cfg_t* cfg) override { |
192 configured_bitrate_ = bitrate_kbit; | 184 configured_bitrate_ = bitrate_kbit; |
193 return layers_->ConfigureBitrates( | 185 return layers_->ConfigureBitrates(bitrate_kbit, max_bitrate_kbit, |
194 bitrate_kbit, max_bitrate_kbit, framerate, cfg); | 186 framerate, cfg); |
195 } | 187 } |
196 | 188 |
197 void PopulateCodecSpecific(bool base_layer_sync, | 189 void PopulateCodecSpecific(bool base_layer_sync, |
198 CodecSpecificInfoVP8* vp8_info, | 190 CodecSpecificInfoVP8* vp8_info, |
199 uint32_t timestamp) override { | 191 uint32_t timestamp) override { |
200 layers_->PopulateCodecSpecific(base_layer_sync, vp8_info, timestamp); | 192 layers_->PopulateCodecSpecific(base_layer_sync, vp8_info, timestamp); |
201 } | 193 } |
202 | 194 |
203 void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override { | 195 void FrameEncoded(unsigned int size, uint32_t timestamp, int qp) override { |
204 layers_->FrameEncoded(size, timestamp, qp); | 196 layers_->FrameEncoded(size, timestamp, qp); |
(...skipping 21 matching lines...) Expand all Loading... |
226 return layers; | 218 return layers; |
227 } | 219 } |
228 | 220 |
229 mutable std::vector<TemporalLayers*> spying_layers_; | 221 mutable std::vector<TemporalLayers*> spying_layers_; |
230 }; | 222 }; |
231 }; | 223 }; |
232 | 224 |
233 class TestVp8Simulcast : public ::testing::Test { | 225 class TestVp8Simulcast : public ::testing::Test { |
234 public: | 226 public: |
235 TestVp8Simulcast(VP8Encoder* encoder, VP8Decoder* decoder) | 227 TestVp8Simulcast(VP8Encoder* encoder, VP8Decoder* decoder) |
236 : encoder_(encoder), | 228 : encoder_(encoder), decoder_(decoder) {} |
237 decoder_(decoder) {} | |
238 | 229 |
239 // Creates an VideoFrame from |plane_colors|. | 230 // Creates an VideoFrame from |plane_colors|. |
240 static void CreateImage(VideoFrame* frame, int plane_colors[kNumOfPlanes]) { | 231 static void CreateImage(VideoFrame* frame, int plane_colors[kNumOfPlanes]) { |
241 for (int plane_num = 0; plane_num < kNumOfPlanes; ++plane_num) { | 232 for (int plane_num = 0; plane_num < kNumOfPlanes; ++plane_num) { |
242 int width = (plane_num != kYPlane ? (frame->width() + 1) / 2 : | 233 int width = |
243 frame->width()); | 234 (plane_num != kYPlane ? (frame->width() + 1) / 2 : frame->width()); |
244 int height = (plane_num != kYPlane ? (frame->height() + 1) / 2 : | 235 int height = |
245 frame->height()); | 236 (plane_num != kYPlane ? (frame->height() + 1) / 2 : frame->height()); |
246 PlaneType plane_type = static_cast<PlaneType>(plane_num); | 237 PlaneType plane_type = static_cast<PlaneType>(plane_num); |
247 uint8_t* data = frame->buffer(plane_type); | 238 uint8_t* data = frame->buffer(plane_type); |
248 // Setting allocated area to zero - setting only image size to | 239 // Setting allocated area to zero - setting only image size to |
249 // requested values - will make it easier to distinguish between image | 240 // requested values - will make it easier to distinguish between image |
250 // size and frame size (accounting for stride). | 241 // size and frame size (accounting for stride). |
251 memset(frame->buffer(plane_type), 0, frame->allocated_size(plane_type)); | 242 memset(frame->buffer(plane_type), 0, frame->allocated_size(plane_type)); |
252 for (int i = 0; i < height; i++) { | 243 for (int i = 0; i < height; i++) { |
253 memset(data, plane_colors[plane_num], width); | 244 memset(data, plane_colors[plane_num], width); |
254 data += frame->stride(plane_type); | 245 data += frame->stride(plane_type); |
255 } | 246 } |
256 } | 247 } |
257 } | 248 } |
258 | 249 |
259 static void DefaultSettings(VideoCodec* settings, | 250 static void DefaultSettings(VideoCodec* settings, |
260 const int* temporal_layer_profile) { | 251 const int* temporal_layer_profile) { |
261 assert(settings); | 252 assert(settings); |
262 memset(settings, 0, sizeof(VideoCodec)); | 253 memset(settings, 0, sizeof(VideoCodec)); |
263 strncpy(settings->plName, "VP8", 4); | 254 strncpy(settings->plName, "VP8", 4); |
264 settings->codecType = kVideoCodecVP8; | 255 settings->codecType = kVideoCodecVP8; |
265 // 96 to 127 dynamic payload types for video codecs | 256 // 96 to 127 dynamic payload types for video codecs |
266 settings->plType = 120; | 257 settings->plType = 120; |
267 settings->startBitrate = 300; | 258 settings->startBitrate = 300; |
268 settings->minBitrate = 30; | 259 settings->minBitrate = 30; |
269 settings->maxBitrate = 0; | 260 settings->maxBitrate = 0; |
270 settings->maxFramerate = 30; | 261 settings->maxFramerate = 30; |
271 settings->width = kDefaultWidth; | 262 settings->width = kDefaultWidth; |
272 settings->height = kDefaultHeight; | 263 settings->height = kDefaultHeight; |
273 settings->numberOfSimulcastStreams = kNumberOfSimulcastStreams; | 264 settings->numberOfSimulcastStreams = kNumberOfSimulcastStreams; |
274 ASSERT_EQ(3, kNumberOfSimulcastStreams); | 265 ASSERT_EQ(3, kNumberOfSimulcastStreams); |
275 ConfigureStream(kDefaultWidth / 4, kDefaultHeight / 4, | 266 ConfigureStream(kDefaultWidth / 4, kDefaultHeight / 4, kMaxBitrates[0], |
276 kMaxBitrates[0], | 267 kMinBitrates[0], kTargetBitrates[0], |
277 kMinBitrates[0], | 268 &settings->simulcastStream[0], temporal_layer_profile[0]); |
278 kTargetBitrates[0], | 269 ConfigureStream(kDefaultWidth / 2, kDefaultHeight / 2, kMaxBitrates[1], |
279 &settings->simulcastStream[0], | 270 kMinBitrates[1], kTargetBitrates[1], |
280 temporal_layer_profile[0]); | 271 &settings->simulcastStream[1], temporal_layer_profile[1]); |
281 ConfigureStream(kDefaultWidth / 2, kDefaultHeight / 2, | 272 ConfigureStream(kDefaultWidth, kDefaultHeight, kMaxBitrates[2], |
282 kMaxBitrates[1], | 273 kMinBitrates[2], kTargetBitrates[2], |
283 kMinBitrates[1], | 274 &settings->simulcastStream[2], temporal_layer_profile[2]); |
284 kTargetBitrates[1], | |
285 &settings->simulcastStream[1], | |
286 temporal_layer_profile[1]); | |
287 ConfigureStream(kDefaultWidth, kDefaultHeight, | |
288 kMaxBitrates[2], | |
289 kMinBitrates[2], | |
290 kTargetBitrates[2], | |
291 &settings->simulcastStream[2], | |
292 temporal_layer_profile[2]); | |
293 settings->codecSpecific.VP8.resilience = kResilientStream; | 275 settings->codecSpecific.VP8.resilience = kResilientStream; |
294 settings->codecSpecific.VP8.denoisingOn = true; | 276 settings->codecSpecific.VP8.denoisingOn = true; |
295 settings->codecSpecific.VP8.errorConcealmentOn = false; | 277 settings->codecSpecific.VP8.errorConcealmentOn = false; |
296 settings->codecSpecific.VP8.automaticResizeOn = false; | 278 settings->codecSpecific.VP8.automaticResizeOn = false; |
297 settings->codecSpecific.VP8.feedbackModeOn = false; | 279 settings->codecSpecific.VP8.feedbackModeOn = false; |
298 settings->codecSpecific.VP8.frameDroppingOn = true; | 280 settings->codecSpecific.VP8.frameDroppingOn = true; |
299 settings->codecSpecific.VP8.keyFrameInterval = 3000; | 281 settings->codecSpecific.VP8.keyFrameInterval = 3000; |
300 } | 282 } |
301 | 283 |
302 static void ConfigureStream(int width, | 284 static void ConfigureStream(int width, |
303 int height, | 285 int height, |
304 int max_bitrate, | 286 int max_bitrate, |
305 int min_bitrate, | 287 int min_bitrate, |
306 int target_bitrate, | 288 int target_bitrate, |
307 SimulcastStream* stream, | 289 SimulcastStream* stream, |
308 int num_temporal_layers) { | 290 int num_temporal_layers) { |
309 assert(stream); | 291 assert(stream); |
310 stream->width = width; | 292 stream->width = width; |
311 stream->height = height; | 293 stream->height = height; |
312 stream->maxBitrate = max_bitrate; | 294 stream->maxBitrate = max_bitrate; |
313 stream->minBitrate = min_bitrate; | 295 stream->minBitrate = min_bitrate; |
314 stream->targetBitrate = target_bitrate; | 296 stream->targetBitrate = target_bitrate; |
315 stream->numberOfTemporalLayers = num_temporal_layers; | 297 stream->numberOfTemporalLayers = num_temporal_layers; |
316 stream->qpMax = 45; | 298 stream->qpMax = 45; |
317 } | 299 } |
318 | 300 |
319 protected: | 301 protected: |
320 virtual void SetUp() { | 302 virtual void SetUp() { SetUpCodec(kDefaultTemporalLayerProfile); } |
321 SetUpCodec(kDefaultTemporalLayerProfile); | |
322 } | |
323 | 303 |
324 virtual void SetUpCodec(const int* temporal_layer_profile) { | 304 virtual void SetUpCodec(const int* temporal_layer_profile) { |
325 encoder_->RegisterEncodeCompleteCallback(&encoder_callback_); | 305 encoder_->RegisterEncodeCompleteCallback(&encoder_callback_); |
326 decoder_->RegisterDecodeCompleteCallback(&decoder_callback_); | 306 decoder_->RegisterDecodeCompleteCallback(&decoder_callback_); |
327 DefaultSettings(&settings_, temporal_layer_profile); | 307 DefaultSettings(&settings_, temporal_layer_profile); |
328 EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); | 308 EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); |
329 EXPECT_EQ(0, decoder_->InitDecode(&settings_, 1)); | 309 EXPECT_EQ(0, decoder_->InitDecode(&settings_, 1)); |
330 int half_width = (kDefaultWidth + 1) / 2; | 310 int half_width = (kDefaultWidth + 1) / 2; |
331 input_frame_.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, | 311 input_frame_.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, kDefaultWidth, |
332 kDefaultWidth, half_width, half_width); | 312 half_width, half_width); |
333 memset(input_frame_.buffer(kYPlane), 0, | 313 memset(input_frame_.buffer(kYPlane), 0, |
334 input_frame_.allocated_size(kYPlane)); | 314 input_frame_.allocated_size(kYPlane)); |
335 memset(input_frame_.buffer(kUPlane), 0, | 315 memset(input_frame_.buffer(kUPlane), 0, |
336 input_frame_.allocated_size(kUPlane)); | 316 input_frame_.allocated_size(kUPlane)); |
337 memset(input_frame_.buffer(kVPlane), 0, | 317 memset(input_frame_.buffer(kVPlane), 0, |
338 input_frame_.allocated_size(kVPlane)); | 318 input_frame_.allocated_size(kVPlane)); |
339 } | 319 } |
340 | 320 |
341 virtual void TearDown() { | 321 virtual void TearDown() { |
342 encoder_->Release(); | 322 encoder_->Release(); |
343 decoder_->Release(); | 323 decoder_->Release(); |
344 } | 324 } |
345 | 325 |
346 void ExpectStreams(FrameType frame_type, int expected_video_streams) { | 326 void ExpectStreams(FrameType frame_type, int expected_video_streams) { |
347 ASSERT_GE(expected_video_streams, 0); | 327 ASSERT_GE(expected_video_streams, 0); |
348 ASSERT_LE(expected_video_streams, kNumberOfSimulcastStreams); | 328 ASSERT_LE(expected_video_streams, kNumberOfSimulcastStreams); |
349 if (expected_video_streams >= 1) { | 329 if (expected_video_streams >= 1) { |
350 EXPECT_CALL(encoder_callback_, Encoded( | 330 EXPECT_CALL( |
351 AllOf(Field(&EncodedImage::_frameType, frame_type), | 331 encoder_callback_, |
352 Field(&EncodedImage::_encodedWidth, kDefaultWidth / 4), | 332 Encoded( |
353 Field(&EncodedImage::_encodedHeight, kDefaultHeight / 4)), _, _) | 333 AllOf(Field(&EncodedImage::_frameType, frame_type), |
354 ) | 334 Field(&EncodedImage::_encodedWidth, kDefaultWidth / 4), |
| 335 Field(&EncodedImage::_encodedHeight, kDefaultHeight / 4)), |
| 336 _, _)) |
355 .Times(1) | 337 .Times(1) |
356 .WillRepeatedly(Return(0)); | 338 .WillRepeatedly(Return(0)); |
357 } | 339 } |
358 if (expected_video_streams >= 2) { | 340 if (expected_video_streams >= 2) { |
359 EXPECT_CALL(encoder_callback_, Encoded( | 341 EXPECT_CALL( |
360 AllOf(Field(&EncodedImage::_frameType, frame_type), | 342 encoder_callback_, |
361 Field(&EncodedImage::_encodedWidth, kDefaultWidth / 2), | 343 Encoded( |
362 Field(&EncodedImage::_encodedHeight, kDefaultHeight / 2)), _, _) | 344 AllOf(Field(&EncodedImage::_frameType, frame_type), |
363 ) | 345 Field(&EncodedImage::_encodedWidth, kDefaultWidth / 2), |
| 346 Field(&EncodedImage::_encodedHeight, kDefaultHeight / 2)), |
| 347 _, _)) |
364 .Times(1) | 348 .Times(1) |
365 .WillRepeatedly(Return(0)); | 349 .WillRepeatedly(Return(0)); |
366 } | 350 } |
367 if (expected_video_streams >= 3) { | 351 if (expected_video_streams >= 3) { |
368 EXPECT_CALL(encoder_callback_, Encoded( | 352 EXPECT_CALL( |
369 AllOf(Field(&EncodedImage::_frameType, frame_type), | 353 encoder_callback_, |
370 Field(&EncodedImage::_encodedWidth, kDefaultWidth), | 354 Encoded(AllOf(Field(&EncodedImage::_frameType, frame_type), |
371 Field(&EncodedImage::_encodedHeight, kDefaultHeight)), _, _)) | 355 Field(&EncodedImage::_encodedWidth, kDefaultWidth), |
| 356 Field(&EncodedImage::_encodedHeight, kDefaultHeight)), |
| 357 _, _)) |
372 .Times(1) | 358 .Times(1) |
373 .WillRepeatedly(Return(0)); | 359 .WillRepeatedly(Return(0)); |
374 } | 360 } |
375 } | 361 } |
376 | 362 |
377 void VerifyTemporalIdxAndSyncForAllSpatialLayers( | 363 void VerifyTemporalIdxAndSyncForAllSpatialLayers( |
378 Vp8TestEncodedImageCallback* encoder_callback, | 364 Vp8TestEncodedImageCallback* encoder_callback, |
379 const int* expected_temporal_idx, | 365 const int* expected_temporal_idx, |
380 const bool* expected_layer_sync, | 366 const bool* expected_layer_sync, |
381 int num_spatial_layers) { | 367 int num_spatial_layers) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 461 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
476 | 462 |
477 ExpectStreams(kVideoFrameDelta, 2); | 463 ExpectStreams(kVideoFrameDelta, 2); |
478 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 464 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
479 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 465 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
480 } | 466 } |
481 | 467 |
482 void TestPaddingOneStreamTwoMaxedOut() { | 468 void TestPaddingOneStreamTwoMaxedOut() { |
483 // We are just below limit of sending third stream, so we should get | 469 // We are just below limit of sending third stream, so we should get |
484 // first stream's rate maxed out at |targetBitrate|, second at |maxBitrate|. | 470 // first stream's rate maxed out at |targetBitrate|, second at |maxBitrate|. |
485 encoder_->SetRates(kTargetBitrates[0] + kTargetBitrates[1] + | 471 encoder_->SetRates( |
486 kMinBitrates[2] - 1, 30); | 472 kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] - 1, 30); |
487 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, | 473 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
488 kVideoFrameDelta); | 474 kVideoFrameDelta); |
489 ExpectStreams(kVideoFrameKey, 2); | 475 ExpectStreams(kVideoFrameKey, 2); |
490 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 476 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
491 | 477 |
492 ExpectStreams(kVideoFrameDelta, 2); | 478 ExpectStreams(kVideoFrameDelta, 2); |
493 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 479 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
494 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 480 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
495 } | 481 } |
496 | 482 |
497 void TestSendAllStreams() { | 483 void TestSendAllStreams() { |
498 // We have just enough to send all streams. | 484 // We have just enough to send all streams. |
499 encoder_->SetRates(kTargetBitrates[0] + kTargetBitrates[1] + | 485 encoder_->SetRates( |
500 kMinBitrates[2], 30); | 486 kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2], 30); |
501 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, | 487 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
502 kVideoFrameDelta); | 488 kVideoFrameDelta); |
503 ExpectStreams(kVideoFrameKey, 3); | 489 ExpectStreams(kVideoFrameKey, 3); |
504 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 490 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
505 | 491 |
506 ExpectStreams(kVideoFrameDelta, 3); | 492 ExpectStreams(kVideoFrameDelta, 3); |
507 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 493 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
508 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 494 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
509 } | 495 } |
510 | 496 |
511 void TestDisablingStreams() { | 497 void TestDisablingStreams() { |
512 // We should get three media streams. | 498 // We should get three media streams. |
513 encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1] + | 499 encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1] + kMaxBitrates[2], 30); |
514 kMaxBitrates[2], 30); | |
515 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, | 500 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
516 kVideoFrameDelta); | 501 kVideoFrameDelta); |
517 ExpectStreams(kVideoFrameKey, 3); | 502 ExpectStreams(kVideoFrameKey, 3); |
518 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 503 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
519 | 504 |
520 ExpectStreams(kVideoFrameDelta, 3); | 505 ExpectStreams(kVideoFrameDelta, 3); |
521 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 506 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
522 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 507 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
523 | 508 |
524 // We should only get two streams and padding for one. | 509 // We should only get two streams and padding for one. |
525 encoder_->SetRates(kTargetBitrates[0] + kTargetBitrates[1] + | 510 encoder_->SetRates( |
526 kMinBitrates[2] / 2, 30); | 511 kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); |
527 ExpectStreams(kVideoFrameDelta, 2); | 512 ExpectStreams(kVideoFrameDelta, 2); |
528 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 513 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
529 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 514 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
530 | 515 |
531 // We should only get the first stream and padding for two. | 516 // We should only get the first stream and padding for two. |
532 encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30); | 517 encoder_->SetRates(kTargetBitrates[0] + kMinBitrates[1] / 2, 30); |
533 ExpectStreams(kVideoFrameDelta, 1); | 518 ExpectStreams(kVideoFrameDelta, 1); |
534 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 519 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
535 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 520 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
536 | 521 |
537 // We don't have enough bitrate for the thumbnail stream, but we should get | 522 // We don't have enough bitrate for the thumbnail stream, but we should get |
538 // it anyway with current configuration. | 523 // it anyway with current configuration. |
539 encoder_->SetRates(kTargetBitrates[0] - 1, 30); | 524 encoder_->SetRates(kTargetBitrates[0] - 1, 30); |
540 ExpectStreams(kVideoFrameDelta, 1); | 525 ExpectStreams(kVideoFrameDelta, 1); |
541 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 526 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
542 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 527 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
543 | 528 |
544 // We should only get two streams and padding for one. | 529 // We should only get two streams and padding for one. |
545 encoder_->SetRates(kTargetBitrates[0] + kTargetBitrates[1] + | 530 encoder_->SetRates( |
546 kMinBitrates[2] / 2, 30); | 531 kTargetBitrates[0] + kTargetBitrates[1] + kMinBitrates[2] / 2, 30); |
547 // We get a key frame because a new stream is being enabled. | 532 // We get a key frame because a new stream is being enabled. |
548 ExpectStreams(kVideoFrameKey, 2); | 533 ExpectStreams(kVideoFrameKey, 2); |
549 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 534 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
550 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 535 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
551 | 536 |
552 // We should get all three streams. | 537 // We should get all three streams. |
553 encoder_->SetRates(kTargetBitrates[0] + kTargetBitrates[1] + | 538 encoder_->SetRates( |
554 kTargetBitrates[2], 30); | 539 kTargetBitrates[0] + kTargetBitrates[1] + kTargetBitrates[2], 30); |
555 // We get a key frame because a new stream is being enabled. | 540 // We get a key frame because a new stream is being enabled. |
556 ExpectStreams(kVideoFrameKey, 3); | 541 ExpectStreams(kVideoFrameKey, 3); |
557 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 542 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
558 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 543 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
559 } | 544 } |
560 | 545 |
561 void SwitchingToOneStream(int width, int height) { | 546 void SwitchingToOneStream(int width, int height) { |
562 // Disable all streams except the last and set the bitrate of the last to | 547 // Disable all streams except the last and set the bitrate of the last to |
563 // 100 kbps. This verifies the way GTP switches to screenshare mode. | 548 // 100 kbps. This verifies the way GTP switches to screenshare mode. |
564 settings_.codecSpecific.VP8.numberOfTemporalLayers = 1; | 549 settings_.codecSpecific.VP8.numberOfTemporalLayers = 1; |
565 settings_.maxBitrate = 100; | 550 settings_.maxBitrate = 100; |
566 settings_.startBitrate = 100; | 551 settings_.startBitrate = 100; |
567 settings_.width = width; | 552 settings_.width = width; |
568 settings_.height = height; | 553 settings_.height = height; |
569 for (int i = 0; i < settings_.numberOfSimulcastStreams - 1; ++i) { | 554 for (int i = 0; i < settings_.numberOfSimulcastStreams - 1; ++i) { |
570 settings_.simulcastStream[i].maxBitrate = 0; | 555 settings_.simulcastStream[i].maxBitrate = 0; |
571 settings_.simulcastStream[i].width = settings_.width; | 556 settings_.simulcastStream[i].width = settings_.width; |
572 settings_.simulcastStream[i].height = settings_.height; | 557 settings_.simulcastStream[i].height = settings_.height; |
573 } | 558 } |
574 // Setting input image to new resolution. | 559 // Setting input image to new resolution. |
575 int half_width = (settings_.width + 1) / 2; | 560 int half_width = (settings_.width + 1) / 2; |
576 input_frame_.CreateEmptyFrame(settings_.width, settings_.height, | 561 input_frame_.CreateEmptyFrame(settings_.width, settings_.height, |
577 settings_.width, half_width, half_width); | 562 settings_.width, half_width, half_width); |
578 memset(input_frame_.buffer(kYPlane), 0, | 563 memset(input_frame_.buffer(kYPlane), 0, |
579 input_frame_.allocated_size(kYPlane)); | 564 input_frame_.allocated_size(kYPlane)); |
580 memset(input_frame_.buffer(kUPlane), 0, | 565 memset(input_frame_.buffer(kUPlane), 0, |
581 input_frame_.allocated_size(kUPlane)); | 566 input_frame_.allocated_size(kUPlane)); |
582 memset(input_frame_.buffer(kVPlane), 0, | 567 memset(input_frame_.buffer(kVPlane), 0, |
583 input_frame_.allocated_size(kVPlane)); | 568 input_frame_.allocated_size(kVPlane)); |
584 | 569 |
585 // The for loop above did not set the bitrate of the highest layer. | 570 // The for loop above did not set the bitrate of the highest layer. |
586 settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1]. | 571 settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1] |
587 maxBitrate = 0; | 572 .maxBitrate = 0; |
588 // The highest layer has to correspond to the non-simulcast resolution. | 573 // The highest layer has to correspond to the non-simulcast resolution. |
589 settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1]. | 574 settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1].width = |
590 width = settings_.width; | 575 settings_.width; |
591 settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1]. | 576 settings_.simulcastStream[settings_.numberOfSimulcastStreams - 1].height = |
592 height = settings_.height; | 577 settings_.height; |
593 EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); | 578 EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); |
594 | 579 |
595 // Encode one frame and verify. | 580 // Encode one frame and verify. |
596 encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30); | 581 encoder_->SetRates(kMaxBitrates[0] + kMaxBitrates[1], 30); |
597 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, | 582 std::vector<FrameType> frame_types(kNumberOfSimulcastStreams, |
598 kVideoFrameDelta); | 583 kVideoFrameDelta); |
599 EXPECT_CALL(encoder_callback_, | 584 EXPECT_CALL(encoder_callback_, |
600 Encoded(AllOf(Field(&EncodedImage::_frameType, kVideoFrameKey), | 585 Encoded(AllOf(Field(&EncodedImage::_frameType, kVideoFrameKey), |
601 Field(&EncodedImage::_encodedWidth, width), | 586 Field(&EncodedImage::_encodedWidth, width), |
602 Field(&EncodedImage::_encodedHeight, height)), | 587 Field(&EncodedImage::_encodedHeight, height)), |
603 _, _)) | 588 _, _)) |
604 .Times(1) | 589 .Times(1) |
605 .WillRepeatedly(Return(0)); | 590 .WillRepeatedly(Return(0)); |
606 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 591 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
607 | 592 |
608 // Switch back. | 593 // Switch back. |
609 DefaultSettings(&settings_, kDefaultTemporalLayerProfile); | 594 DefaultSettings(&settings_, kDefaultTemporalLayerProfile); |
610 // Start at the lowest bitrate for enabling base stream. | 595 // Start at the lowest bitrate for enabling base stream. |
611 settings_.startBitrate = kMinBitrates[0]; | 596 settings_.startBitrate = kMinBitrates[0]; |
612 EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); | 597 EXPECT_EQ(0, encoder_->InitEncode(&settings_, 1, 1200)); |
613 encoder_->SetRates(settings_.startBitrate, 30); | 598 encoder_->SetRates(settings_.startBitrate, 30); |
614 ExpectStreams(kVideoFrameKey, 1); | 599 ExpectStreams(kVideoFrameKey, 1); |
615 // Resize |input_frame_| to the new resolution. | 600 // Resize |input_frame_| to the new resolution. |
616 half_width = (settings_.width + 1) / 2; | 601 half_width = (settings_.width + 1) / 2; |
617 input_frame_.CreateEmptyFrame(settings_.width, settings_.height, | 602 input_frame_.CreateEmptyFrame(settings_.width, settings_.height, |
618 settings_.width, half_width, half_width); | 603 settings_.width, half_width, half_width); |
619 memset(input_frame_.buffer(kYPlane), 0, | 604 memset(input_frame_.buffer(kYPlane), 0, |
620 input_frame_.allocated_size(kYPlane)); | 605 input_frame_.allocated_size(kYPlane)); |
621 memset(input_frame_.buffer(kUPlane), 0, | 606 memset(input_frame_.buffer(kUPlane), 0, |
622 input_frame_.allocated_size(kUPlane)); | 607 input_frame_.allocated_size(kUPlane)); |
623 memset(input_frame_.buffer(kVPlane), 0, | 608 memset(input_frame_.buffer(kVPlane), 0, |
624 input_frame_.allocated_size(kVPlane)); | 609 input_frame_.allocated_size(kVPlane)); |
625 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); | 610 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, &frame_types)); |
626 } | 611 } |
627 | 612 |
628 void TestSwitchingToOneStream() { | 613 void TestSwitchingToOneStream() { SwitchingToOneStream(1024, 768); } |
629 SwitchingToOneStream(1024, 768); | |
630 } | |
631 | 614 |
632 void TestSwitchingToOneOddStream() { | 615 void TestSwitchingToOneOddStream() { SwitchingToOneStream(1023, 769); } |
633 SwitchingToOneStream(1023, 769); | |
634 } | |
635 | 616 |
636 void TestRPSIEncoder() { | 617 void TestRPSIEncoder() { |
637 Vp8TestEncodedImageCallback encoder_callback; | 618 Vp8TestEncodedImageCallback encoder_callback; |
638 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); | 619 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
639 | 620 |
640 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. | 621 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
641 | 622 |
642 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 623 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
643 int picture_id = -1; | 624 int picture_id = -1; |
644 int temporal_layer = -1; | 625 int temporal_layer = -1; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
775 } | 756 } |
776 | 757 |
777 // Test the layer pattern and sync flag for various spatial-temporal patterns. | 758 // Test the layer pattern and sync flag for various spatial-temporal patterns. |
778 // 3-3-3 pattern: 3 temporal layers for all spatial streams, so same | 759 // 3-3-3 pattern: 3 temporal layers for all spatial streams, so same |
779 // temporal_layer id and layer_sync is expected for all streams. | 760 // temporal_layer id and layer_sync is expected for all streams. |
780 void TestSaptioTemporalLayers333PatternEncoder() { | 761 void TestSaptioTemporalLayers333PatternEncoder() { |
781 Vp8TestEncodedImageCallback encoder_callback; | 762 Vp8TestEncodedImageCallback encoder_callback; |
782 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); | 763 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
783 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. | 764 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
784 | 765 |
785 int expected_temporal_idx[3] = { -1, -1, -1}; | 766 int expected_temporal_idx[3] = {-1, -1, -1}; |
786 bool expected_layer_sync[3] = {false, false, false}; | 767 bool expected_layer_sync[3] = {false, false, false}; |
787 | 768 |
788 // First frame: #0. | 769 // First frame: #0. |
789 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 770 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
790 SetExpectedValues3<int>(0, 0, 0, expected_temporal_idx); | 771 SetExpectedValues3<int>(0, 0, 0, expected_temporal_idx); |
791 SetExpectedValues3<bool>(true, true, true, expected_layer_sync); | 772 SetExpectedValues3<bool>(true, true, true, expected_layer_sync); |
792 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 773 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
793 expected_temporal_idx, | 774 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
794 expected_layer_sync, | |
795 3); | |
796 | 775 |
797 // Next frame: #1. | 776 // Next frame: #1. |
798 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 777 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
799 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 778 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
800 SetExpectedValues3<int>(2, 2, 2, expected_temporal_idx); | 779 SetExpectedValues3<int>(2, 2, 2, expected_temporal_idx); |
801 SetExpectedValues3<bool>(true, true, true, expected_layer_sync); | 780 SetExpectedValues3<bool>(true, true, true, expected_layer_sync); |
802 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 781 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
803 expected_temporal_idx, | 782 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
804 expected_layer_sync, | |
805 3); | |
806 | 783 |
807 // Next frame: #2. | 784 // Next frame: #2. |
808 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 785 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
809 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 786 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
810 SetExpectedValues3<int>(1, 1, 1, expected_temporal_idx); | 787 SetExpectedValues3<int>(1, 1, 1, expected_temporal_idx); |
811 SetExpectedValues3<bool>(true, true, true, expected_layer_sync); | 788 SetExpectedValues3<bool>(true, true, true, expected_layer_sync); |
812 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 789 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
813 expected_temporal_idx, | 790 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
814 expected_layer_sync, | |
815 3); | |
816 | 791 |
817 // Next frame: #3. | 792 // Next frame: #3. |
818 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 793 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
819 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 794 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
820 SetExpectedValues3<int>(2, 2, 2, expected_temporal_idx); | 795 SetExpectedValues3<int>(2, 2, 2, expected_temporal_idx); |
821 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); | 796 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); |
822 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 797 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
823 expected_temporal_idx, | 798 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
824 expected_layer_sync, | |
825 3); | |
826 | 799 |
827 // Next frame: #4. | 800 // Next frame: #4. |
828 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 801 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
829 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 802 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
830 SetExpectedValues3<int>(0, 0, 0, expected_temporal_idx); | 803 SetExpectedValues3<int>(0, 0, 0, expected_temporal_idx); |
831 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); | 804 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); |
832 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 805 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
833 expected_temporal_idx, | 806 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
834 expected_layer_sync, | |
835 3); | |
836 | 807 |
837 // Next frame: #5. | 808 // Next frame: #5. |
838 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 809 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
839 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 810 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
840 SetExpectedValues3<int>(2, 2, 2, expected_temporal_idx); | 811 SetExpectedValues3<int>(2, 2, 2, expected_temporal_idx); |
841 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); | 812 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); |
842 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 813 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
843 expected_temporal_idx, | 814 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
844 expected_layer_sync, | |
845 3); | |
846 } | 815 } |
847 | 816 |
848 // Test the layer pattern and sync flag for various spatial-temporal patterns. | 817 // Test the layer pattern and sync flag for various spatial-temporal patterns. |
849 // 3-2-1 pattern: 3 temporal layers for lowest resolution, 2 for middle, and | 818 // 3-2-1 pattern: 3 temporal layers for lowest resolution, 2 for middle, and |
850 // 1 temporal layer for highest resolution. | 819 // 1 temporal layer for highest resolution. |
851 // For this profile, we expect the temporal index pattern to be: | 820 // For this profile, we expect the temporal index pattern to be: |
852 // 1st stream: 0, 2, 1, 2, .... | 821 // 1st stream: 0, 2, 1, 2, .... |
853 // 2nd stream: 0, 1, 0, 1, ... | 822 // 2nd stream: 0, 1, 0, 1, ... |
854 // 3rd stream: -1, -1, -1, -1, .... | 823 // 3rd stream: -1, -1, -1, -1, .... |
855 // Regarding the 3rd stream, note that a stream/encoder with 1 temporal layer | 824 // Regarding the 3rd stream, note that a stream/encoder with 1 temporal layer |
856 // should always have temporal layer idx set to kNoTemporalIdx = -1. | 825 // should always have temporal layer idx set to kNoTemporalIdx = -1. |
857 // Since CodecSpecificInfoVP8.temporalIdx is uint8_t, this will wrap to 255. | 826 // Since CodecSpecificInfoVP8.temporalIdx is uint8_t, this will wrap to 255. |
858 // TODO(marpan): Although this seems safe for now, we should fix this. | 827 // TODO(marpan): Although this seems safe for now, we should fix this. |
859 void TestSpatioTemporalLayers321PatternEncoder() { | 828 void TestSpatioTemporalLayers321PatternEncoder() { |
860 int temporal_layer_profile[3] = {3, 2, 1}; | 829 int temporal_layer_profile[3] = {3, 2, 1}; |
861 SetUpCodec(temporal_layer_profile); | 830 SetUpCodec(temporal_layer_profile); |
862 Vp8TestEncodedImageCallback encoder_callback; | 831 Vp8TestEncodedImageCallback encoder_callback; |
863 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); | 832 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
864 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. | 833 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
865 | 834 |
866 int expected_temporal_idx[3] = { -1, -1, -1}; | 835 int expected_temporal_idx[3] = {-1, -1, -1}; |
867 bool expected_layer_sync[3] = {false, false, false}; | 836 bool expected_layer_sync[3] = {false, false, false}; |
868 | 837 |
869 // First frame: #0. | 838 // First frame: #0. |
870 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 839 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
871 SetExpectedValues3<int>(0, 0, 255, expected_temporal_idx); | 840 SetExpectedValues3<int>(0, 0, 255, expected_temporal_idx); |
872 SetExpectedValues3<bool>(true, true, false, expected_layer_sync); | 841 SetExpectedValues3<bool>(true, true, false, expected_layer_sync); |
873 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 842 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
874 expected_temporal_idx, | 843 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
875 expected_layer_sync, | |
876 3); | |
877 | 844 |
878 // Next frame: #1. | 845 // Next frame: #1. |
879 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 846 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
880 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 847 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
881 SetExpectedValues3<int>(2, 1, 255, expected_temporal_idx); | 848 SetExpectedValues3<int>(2, 1, 255, expected_temporal_idx); |
882 SetExpectedValues3<bool>(true, true, false, expected_layer_sync); | 849 SetExpectedValues3<bool>(true, true, false, expected_layer_sync); |
883 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 850 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
884 expected_temporal_idx, | 851 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
885 expected_layer_sync, | |
886 3); | |
887 | 852 |
888 // Next frame: #2. | 853 // Next frame: #2. |
889 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 854 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
890 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 855 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
891 SetExpectedValues3<int>(1, 0, 255, expected_temporal_idx); | 856 SetExpectedValues3<int>(1, 0, 255, expected_temporal_idx); |
892 SetExpectedValues3<bool>(true, false, false, expected_layer_sync); | 857 SetExpectedValues3<bool>(true, false, false, expected_layer_sync); |
893 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 858 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
894 expected_temporal_idx, | 859 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
895 expected_layer_sync, | |
896 3); | |
897 | 860 |
898 // Next frame: #3. | 861 // Next frame: #3. |
899 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 862 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
900 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 863 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
901 SetExpectedValues3<int>(2, 1, 255, expected_temporal_idx); | 864 SetExpectedValues3<int>(2, 1, 255, expected_temporal_idx); |
902 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); | 865 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); |
903 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 866 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
904 expected_temporal_idx, | 867 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
905 expected_layer_sync, | |
906 3); | |
907 | 868 |
908 // Next frame: #4. | 869 // Next frame: #4. |
909 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 870 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
910 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 871 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
911 SetExpectedValues3<int>(0, 0, 255, expected_temporal_idx); | 872 SetExpectedValues3<int>(0, 0, 255, expected_temporal_idx); |
912 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); | 873 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); |
913 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 874 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
914 expected_temporal_idx, | 875 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
915 expected_layer_sync, | |
916 3); | |
917 | 876 |
918 // Next frame: #5. | 877 // Next frame: #5. |
919 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 878 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
920 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 879 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
921 SetExpectedValues3<int>(2, 1, 255, expected_temporal_idx); | 880 SetExpectedValues3<int>(2, 1, 255, expected_temporal_idx); |
922 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); | 881 SetExpectedValues3<bool>(false, false, false, expected_layer_sync); |
923 VerifyTemporalIdxAndSyncForAllSpatialLayers(&encoder_callback, | 882 VerifyTemporalIdxAndSyncForAllSpatialLayers( |
924 expected_temporal_idx, | 883 &encoder_callback, expected_temporal_idx, expected_layer_sync, 3); |
925 expected_layer_sync, | |
926 3); | |
927 } | 884 } |
928 | 885 |
929 void TestStrideEncodeDecode() { | 886 void TestStrideEncodeDecode() { |
930 Vp8TestEncodedImageCallback encoder_callback; | 887 Vp8TestEncodedImageCallback encoder_callback; |
931 Vp8TestDecodedImageCallback decoder_callback; | 888 Vp8TestDecodedImageCallback decoder_callback; |
932 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); | 889 encoder_->RegisterEncodeCompleteCallback(&encoder_callback); |
933 decoder_->RegisterDecodeCompleteCallback(&decoder_callback); | 890 decoder_->RegisterDecodeCompleteCallback(&decoder_callback); |
934 | 891 |
935 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. | 892 encoder_->SetRates(kMaxBitrates[2], 30); // To get all three streams. |
936 // Setting two (possibly) problematic use cases for stride: | 893 // Setting two (possibly) problematic use cases for stride: |
937 // 1. stride > width 2. stride_y != stride_uv/2 | 894 // 1. stride > width 2. stride_y != stride_uv/2 |
938 int stride_y = kDefaultWidth + 20; | 895 int stride_y = kDefaultWidth + 20; |
939 int stride_uv = ((kDefaultWidth + 1) / 2) + 5; | 896 int stride_uv = ((kDefaultWidth + 1) / 2) + 5; |
940 input_frame_.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, | 897 input_frame_.CreateEmptyFrame(kDefaultWidth, kDefaultHeight, stride_y, |
941 stride_y, stride_uv, stride_uv); | 898 stride_uv, stride_uv); |
942 // Set color. | 899 // Set color. |
943 int plane_offset[kNumOfPlanes]; | 900 int plane_offset[kNumOfPlanes]; |
944 plane_offset[kYPlane] = kColorY; | 901 plane_offset[kYPlane] = kColorY; |
945 plane_offset[kUPlane] = kColorU; | 902 plane_offset[kUPlane] = kColorU; |
946 plane_offset[kVPlane] = kColorV; | 903 plane_offset[kVPlane] = kColorV; |
947 CreateImage(&input_frame_, plane_offset); | 904 CreateImage(&input_frame_, plane_offset); |
948 | 905 |
949 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 906 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
950 | 907 |
951 // Change color. | 908 // Change color. |
952 plane_offset[kYPlane] += 1; | 909 plane_offset[kYPlane] += 1; |
953 plane_offset[kUPlane] += 1; | 910 plane_offset[kUPlane] += 1; |
954 plane_offset[kVPlane] += 1; | 911 plane_offset[kVPlane] += 1; |
955 CreateImage(&input_frame_, plane_offset); | 912 CreateImage(&input_frame_, plane_offset); |
956 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); | 913 input_frame_.set_timestamp(input_frame_.timestamp() + 3000); |
957 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); | 914 EXPECT_EQ(0, encoder_->Encode(input_frame_, NULL, NULL)); |
958 | 915 |
959 EncodedImage encoded_frame; | 916 EncodedImage encoded_frame; |
960 // Only encoding one frame - so will be a key frame. | 917 // Only encoding one frame - so will be a key frame. |
961 encoder_callback.GetLastEncodedKeyFrame(&encoded_frame); | 918 encoder_callback.GetLastEncodedKeyFrame(&encoded_frame); |
962 EXPECT_EQ(0, decoder_->Decode(encoded_frame, false, NULL)); | 919 EXPECT_EQ(0, decoder_->Decode(encoded_frame, false, NULL)); |
963 encoder_callback.GetLastEncodedFrame(&encoded_frame); | 920 encoder_callback.GetLastEncodedFrame(&encoded_frame); |
964 decoder_->Decode(encoded_frame, false, NULL); | 921 decoder_->Decode(encoded_frame, false, NULL); |
965 EXPECT_EQ(2, decoder_callback.DecodedFrames()); | 922 EXPECT_EQ(2, decoder_callback.DecodedFrames()); |
966 } | 923 } |
967 | 924 |
968 void TestSkipEncodingUnusedStreams() { | 925 void TestSkipEncodingUnusedStreams() { |
969 SkipEncodingUnusedStreamsTest test; | 926 SkipEncodingUnusedStreamsTest test; |
970 std::vector<unsigned int> configured_bitrate = | 927 std::vector<unsigned int> configured_bitrate = |
971 test.RunTest(encoder_.get(), | 928 test.RunTest(encoder_.get(), &settings_, |
972 &settings_, | 929 1); // Target bit rate 1, to force all streams but the |
973 1); // Target bit rate 1, to force all streams but the | 930 // base one to be exceeding bandwidth constraints. |
974 // base one to be exceeding bandwidth constraints. | |
975 EXPECT_EQ(static_cast<size_t>(kNumberOfSimulcastStreams), | 931 EXPECT_EQ(static_cast<size_t>(kNumberOfSimulcastStreams), |
976 configured_bitrate.size()); | 932 configured_bitrate.size()); |
977 | 933 |
978 unsigned int min_bitrate = | 934 unsigned int min_bitrate = |
979 std::max(settings_.simulcastStream[0].minBitrate, settings_.minBitrate); | 935 std::max(settings_.simulcastStream[0].minBitrate, settings_.minBitrate); |
980 int stream = 0; | 936 int stream = 0; |
981 for (std::vector<unsigned int>::const_iterator it = | 937 for (std::vector<unsigned int>::const_iterator it = |
982 configured_bitrate.begin(); | 938 configured_bitrate.begin(); |
983 it != configured_bitrate.end(); | 939 it != configured_bitrate.end(); ++it) { |
984 ++it) { | |
985 if (stream == 0) { | 940 if (stream == 0) { |
986 EXPECT_EQ(min_bitrate, *it); | 941 EXPECT_EQ(min_bitrate, *it); |
987 } else { | 942 } else { |
988 EXPECT_EQ(0u, *it); | 943 EXPECT_EQ(0u, *it); |
989 } | 944 } |
990 ++stream; | 945 ++stream; |
991 } | 946 } |
992 } | 947 } |
993 | 948 |
994 rtc::scoped_ptr<VP8Encoder> encoder_; | 949 rtc::scoped_ptr<VP8Encoder> encoder_; |
995 MockEncodedImageCallback encoder_callback_; | 950 MockEncodedImageCallback encoder_callback_; |
996 rtc::scoped_ptr<VP8Decoder> decoder_; | 951 rtc::scoped_ptr<VP8Decoder> decoder_; |
997 MockDecodedImageCallback decoder_callback_; | 952 MockDecodedImageCallback decoder_callback_; |
998 VideoCodec settings_; | 953 VideoCodec settings_; |
999 VideoFrame input_frame_; | 954 VideoFrame input_frame_; |
1000 }; | 955 }; |
1001 | 956 |
1002 } // namespace testing | 957 } // namespace testing |
1003 } // namespace webrtc | 958 } // namespace webrtc |
1004 | 959 |
1005 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_UNITTEST_H_ | 960 #endif // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP8_SIMULCAST_UNITTEST_H_ |
OLD | NEW |