OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 <stdio.h> | 11 #include <stdio.h> |
12 | 12 |
13 #include <memory> | 13 #include <memory> |
14 | 14 |
15 #include "webrtc/api/video/i420_buffer.h" | 15 #include "webrtc/api/video/i420_buffer.h" |
16 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 16 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
17 #include "webrtc/modules/video_coding/codecs/test/video_codec_test.h" | 17 #include "webrtc/modules/video_coding/codecs/test/video_codec_test.h" |
18 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" | 18 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" |
19 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" | 19 #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" |
20 #include "webrtc/rtc_base/checks.h" | 20 #include "webrtc/rtc_base/checks.h" |
21 #include "webrtc/rtc_base/optional.h" | 21 #include "webrtc/rtc_base/optional.h" |
22 #include "webrtc/rtc_base/timeutils.h" | 22 #include "webrtc/rtc_base/timeutils.h" |
| 23 #include "webrtc/test/field_trial.h" |
23 #include "webrtc/test/frame_utils.h" | 24 #include "webrtc/test/frame_utils.h" |
24 #include "webrtc/test/gtest.h" | 25 #include "webrtc/test/gtest.h" |
25 #include "webrtc/test/testsupport/fileutils.h" | 26 #include "webrtc/test/testsupport/fileutils.h" |
| 27 #include "webrtc/test/video_codec_settings.h" |
26 | 28 |
27 namespace webrtc { | 29 namespace webrtc { |
28 | 30 |
29 namespace { | 31 namespace { |
30 | 32 |
31 void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) { | 33 void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) { |
32 *stride_y = 16 * ((width + 15) / 16); | 34 *stride_y = 16 * ((width + 15) / 16); |
33 *stride_uv = 16 * ((width + 31) / 32); | 35 *stride_uv = 16 * ((width + 31) / 32); |
34 } | 36 } |
35 | 37 |
36 enum { kMaxWaitEncTimeMs = 100 }; | 38 enum { kMaxWaitEncTimeMs = 100 }; |
37 enum { kMaxWaitDecTimeMs = 25 }; | 39 enum { kMaxWaitDecTimeMs = 25 }; |
38 | 40 |
39 constexpr uint32_t kTestTimestamp = 123; | 41 constexpr uint32_t kTestTimestamp = 123; |
40 constexpr int64_t kTestNtpTimeMs = 456; | 42 constexpr int64_t kTestNtpTimeMs = 456; |
41 constexpr uint32_t kTimestampIncrementPerFrame = 3000; | 43 constexpr uint32_t kTimestampIncrementPerFrame = 3000; |
| 44 constexpr int kNumCores = 1; |
| 45 constexpr size_t kMaxPayloadSize = 1440; |
| 46 constexpr int kMinPixelsPerFrame = 12345; |
| 47 constexpr int kDefaultMinPixelsPerFrame = 320 * 180; |
42 | 48 |
43 } // namespace | 49 } // namespace |
44 | 50 |
45 // TODO(mikhal): Replace these with mocks. | 51 // TODO(mikhal): Replace these with mocks. |
46 class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback { | 52 class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback { |
47 public: | 53 public: |
48 Vp8UnitTestEncodeCompleteCallback(EncodedImage* frame, | 54 Vp8UnitTestEncodeCompleteCallback(EncodedImage* frame, |
49 CodecSpecificInfo* codec_specific_info, | 55 CodecSpecificInfo* codec_specific_info, |
50 unsigned int decoderSpecificSize, | 56 unsigned int decoderSpecificSize, |
51 void* decoderSpecificInfo) | 57 void* decoderSpecificInfo) |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 VideoFrame& frame, | 142 VideoFrame& frame, |
137 rtc::Optional<int32_t> decode_time_ms, | 143 rtc::Optional<int32_t> decode_time_ms, |
138 rtc::Optional<uint8_t> qp) { | 144 rtc::Optional<uint8_t> qp) { |
139 *decoded_frame_ = rtc::Optional<VideoFrame>(frame); | 145 *decoded_frame_ = rtc::Optional<VideoFrame>(frame); |
140 *decoded_qp_ = qp; | 146 *decoded_qp_ = qp; |
141 decode_complete = true; | 147 decode_complete = true; |
142 } | 148 } |
143 | 149 |
144 class TestVp8Impl : public ::testing::Test { | 150 class TestVp8Impl : public ::testing::Test { |
145 protected: | 151 protected: |
| 152 TestVp8Impl() : TestVp8Impl("") {} |
| 153 explicit TestVp8Impl(const std::string& field_trials) |
| 154 : override_field_trials_(field_trials) {} |
| 155 |
146 virtual void SetUp() { | 156 virtual void SetUp() { |
147 encoder_.reset(VP8Encoder::Create()); | 157 encoder_.reset(VP8Encoder::Create()); |
148 decoder_.reset(VP8Decoder::Create()); | 158 decoder_.reset(VP8Decoder::Create()); |
149 memset(&codec_settings_, 0, sizeof(codec_settings_)); | 159 memset(&codec_settings_, 0, sizeof(codec_settings_)); |
150 encode_complete_callback_.reset(new Vp8UnitTestEncodeCompleteCallback( | 160 encode_complete_callback_.reset(new Vp8UnitTestEncodeCompleteCallback( |
151 &encoded_frame_, &codec_specific_info_, 0, nullptr)); | 161 &encoded_frame_, &codec_specific_info_, 0, nullptr)); |
152 decode_complete_callback_.reset( | 162 decode_complete_callback_.reset( |
153 new Vp8UnitTestDecodeCompleteCallback(&decoded_frame_, &decoded_qp_)); | 163 new Vp8UnitTestDecodeCompleteCallback(&decoded_frame_, &decoded_qp_)); |
154 encoder_->RegisterEncodeCompleteCallback(encode_complete_callback_.get()); | 164 encoder_->RegisterEncodeCompleteCallback(encode_complete_callback_.get()); |
155 decoder_->RegisterDecodeCompleteCallback(decode_complete_callback_.get()); | 165 decoder_->RegisterDecodeCompleteCallback(decode_complete_callback_.get()); |
(...skipping 27 matching lines...) Expand all Loading... |
183 } | 193 } |
184 | 194 |
185 void SetUpEncodeDecode() { | 195 void SetUpEncodeDecode() { |
186 codec_settings_.startBitrate = 300; | 196 codec_settings_.startBitrate = 300; |
187 codec_settings_.maxBitrate = 4000; | 197 codec_settings_.maxBitrate = 4000; |
188 codec_settings_.qpMax = 56; | 198 codec_settings_.qpMax = 56; |
189 codec_settings_.VP8()->denoisingOn = true; | 199 codec_settings_.VP8()->denoisingOn = true; |
190 codec_settings_.VP8()->tl_factory = &tl_factory_; | 200 codec_settings_.VP8()->tl_factory = &tl_factory_; |
191 codec_settings_.VP8()->numberOfTemporalLayers = 1; | 201 codec_settings_.VP8()->numberOfTemporalLayers = 1; |
192 | 202 |
| 203 EXPECT_EQ( |
| 204 WEBRTC_VIDEO_CODEC_OK, |
| 205 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
193 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 206 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
194 encoder_->InitEncode(&codec_settings_, 1, 1440)); | 207 decoder_->InitDecode(&codec_settings_, kNumCores)); |
195 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_settings_, 1)); | |
196 } | 208 } |
197 | 209 |
198 size_t WaitForEncodedFrame() const { | 210 size_t WaitForEncodedFrame() const { |
199 int64_t startTime = rtc::TimeMillis(); | 211 int64_t startTime = rtc::TimeMillis(); |
200 while (rtc::TimeMillis() - startTime < kMaxWaitEncTimeMs) { | 212 while (rtc::TimeMillis() - startTime < kMaxWaitEncTimeMs) { |
201 if (encode_complete_callback_->EncodeComplete()) { | 213 if (encode_complete_callback_->EncodeComplete()) { |
202 return encoded_frame_._length; | 214 return encoded_frame_._length; |
203 } | 215 } |
204 } | 216 } |
205 return 0; | 217 return 0; |
(...skipping 15 matching lines...) Expand all Loading... |
221 uint8_t temporal_idx) { | 233 uint8_t temporal_idx) { |
222 ASSERT_TRUE(WaitForEncodedFrame()); | 234 ASSERT_TRUE(WaitForEncodedFrame()); |
223 EXPECT_EQ(picture_id, codec_specific_info_.codecSpecific.VP8.pictureId); | 235 EXPECT_EQ(picture_id, codec_specific_info_.codecSpecific.VP8.pictureId); |
224 EXPECT_EQ(tl0_pic_idx, codec_specific_info_.codecSpecific.VP8.tl0PicIdx); | 236 EXPECT_EQ(tl0_pic_idx, codec_specific_info_.codecSpecific.VP8.tl0PicIdx); |
225 EXPECT_EQ(temporal_idx, codec_specific_info_.codecSpecific.VP8.temporalIdx); | 237 EXPECT_EQ(temporal_idx, codec_specific_info_.codecSpecific.VP8.temporalIdx); |
226 } | 238 } |
227 | 239 |
228 const int kWidth = 172; | 240 const int kWidth = 172; |
229 const int kHeight = 144; | 241 const int kHeight = 144; |
230 | 242 |
| 243 test::ScopedFieldTrials override_field_trials_; |
231 std::unique_ptr<Vp8UnitTestEncodeCompleteCallback> encode_complete_callback_; | 244 std::unique_ptr<Vp8UnitTestEncodeCompleteCallback> encode_complete_callback_; |
232 std::unique_ptr<Vp8UnitTestDecodeCompleteCallback> decode_complete_callback_; | 245 std::unique_ptr<Vp8UnitTestDecodeCompleteCallback> decode_complete_callback_; |
233 std::unique_ptr<uint8_t[]> source_buffer_; | 246 std::unique_ptr<uint8_t[]> source_buffer_; |
234 FILE* source_file_; | 247 FILE* source_file_; |
235 std::unique_ptr<VideoFrame> input_frame_; | 248 std::unique_ptr<VideoFrame> input_frame_; |
236 std::unique_ptr<VideoEncoder> encoder_; | 249 std::unique_ptr<VideoEncoder> encoder_; |
237 std::unique_ptr<VideoDecoder> decoder_; | 250 std::unique_ptr<VideoDecoder> decoder_; |
238 EncodedImage encoded_frame_; | 251 EncodedImage encoded_frame_; |
239 CodecSpecificInfo codec_specific_info_; | 252 CodecSpecificInfo codec_specific_info_; |
240 rtc::Optional<VideoFrame> decoded_frame_; | 253 rtc::Optional<VideoFrame> decoded_frame_; |
(...skipping 18 matching lines...) Expand all Loading... |
259 // Calls before InitEncode(). | 272 // Calls before InitEncode(). |
260 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); | 273 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); |
261 int bit_rate = 300; | 274 int bit_rate = 300; |
262 BitrateAllocation bitrate_allocation; | 275 BitrateAllocation bitrate_allocation; |
263 bitrate_allocation.SetBitrate(0, 0, bit_rate * 1000); | 276 bitrate_allocation.SetBitrate(0, 0, bit_rate * 1000); |
264 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, | 277 EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED, |
265 encoder_->SetRateAllocation(bitrate_allocation, | 278 encoder_->SetRateAllocation(bitrate_allocation, |
266 codec_settings_.maxFramerate)); | 279 codec_settings_.maxFramerate)); |
267 | 280 |
268 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 281 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
269 encoder_->InitEncode(&codec_settings_, 1, 1440)); | 282 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
270 | 283 |
271 // Decoder parameter tests. | 284 // Decoder parameter tests. |
272 // Calls before InitDecode(). | 285 // Calls before InitDecode(). |
273 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release()); | 286 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release()); |
274 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_settings_, 1)); | 287 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 288 decoder_->InitDecode(&codec_settings_, kNumCores)); |
275 } | 289 } |
276 | 290 |
277 // We only test the encoder here, since the decoded frame rotation is set based | 291 // We only test the encoder here, since the decoded frame rotation is set based |
278 // on the CVO RTP header extension in VCMDecodedFrameCallback::Decoded. | 292 // on the CVO RTP header extension in VCMDecodedFrameCallback::Decoded. |
279 // TODO(brandtr): Consider passing through the rotation flag through the decoder | 293 // TODO(brandtr): Consider passing through the rotation flag through the decoder |
280 // in the same way as done in the encoder. | 294 // in the same way as done in the encoder. |
281 TEST_F(TestVp8Impl, EncodedRotationEqualsInputRotation) { | 295 TEST_F(TestVp8Impl, EncodedRotationEqualsInputRotation) { |
282 SetUpEncodeDecode(); | 296 SetUpEncodeDecode(); |
283 | 297 |
284 input_frame_->set_rotation(kVideoRotation_0); | 298 input_frame_->set_rotation(kVideoRotation_0); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 decoder_->Decode(encoded_frame_, false, nullptr)); | 381 decoder_->Decode(encoded_frame_, false, nullptr)); |
368 ASSERT_TRUE(decoded_frame_); | 382 ASSERT_TRUE(decoded_frame_); |
369 EXPECT_GT(I420PSNR(input_frame_.get(), &*decoded_frame_), 36); | 383 EXPECT_GT(I420PSNR(input_frame_.get(), &*decoded_frame_), 36); |
370 } | 384 } |
371 | 385 |
372 TEST_F(TestVp8Impl, EncoderRetainsRtpStateAfterRelease) { | 386 TEST_F(TestVp8Impl, EncoderRetainsRtpStateAfterRelease) { |
373 SetUpEncodeDecode(); | 387 SetUpEncodeDecode(); |
374 // Override default settings. | 388 // Override default settings. |
375 codec_settings_.VP8()->numberOfTemporalLayers = 2; | 389 codec_settings_.VP8()->numberOfTemporalLayers = 2; |
376 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 390 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
377 encoder_->InitEncode(&codec_settings_, 1, 1440)); | 391 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
378 | 392 |
379 // Temporal layer 0. | 393 // Temporal layer 0. |
380 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 394 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
381 encoder_->Encode(*input_frame_, nullptr, nullptr)); | 395 encoder_->Encode(*input_frame_, nullptr, nullptr)); |
382 ASSERT_TRUE(WaitForEncodedFrame()); | 396 ASSERT_TRUE(WaitForEncodedFrame()); |
383 EXPECT_EQ(0, codec_specific_info_.codecSpecific.VP8.temporalIdx); | 397 EXPECT_EQ(0, codec_specific_info_.codecSpecific.VP8.temporalIdx); |
384 int16_t picture_id = codec_specific_info_.codecSpecific.VP8.pictureId; | 398 int16_t picture_id = codec_specific_info_.codecSpecific.VP8.pictureId; |
385 int tl0_pic_idx = codec_specific_info_.codecSpecific.VP8.tl0PicIdx; | 399 int tl0_pic_idx = codec_specific_info_.codecSpecific.VP8.tl0PicIdx; |
386 | 400 |
387 // Temporal layer 1. | 401 // Temporal layer 1. |
(...skipping 15 matching lines...) Expand all Loading... |
403 input_frame_->set_timestamp(input_frame_->timestamp() + | 417 input_frame_->set_timestamp(input_frame_->timestamp() + |
404 kTimestampIncrementPerFrame); | 418 kTimestampIncrementPerFrame); |
405 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 419 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
406 encoder_->Encode(*input_frame_, nullptr, nullptr)); | 420 encoder_->Encode(*input_frame_, nullptr, nullptr)); |
407 ExpectFrameWith((picture_id + 3) % (1 << 15), (tl0_pic_idx + 1) % (1 << 8), | 421 ExpectFrameWith((picture_id + 3) % (1 << 15), (tl0_pic_idx + 1) % (1 << 8), |
408 1); | 422 1); |
409 | 423 |
410 // Reinit. | 424 // Reinit. |
411 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); | 425 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); |
412 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 426 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
413 encoder_->InitEncode(&codec_settings_, 1, 1440)); | 427 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
414 | 428 |
415 // Temporal layer 0. | 429 // Temporal layer 0. |
416 input_frame_->set_timestamp(input_frame_->timestamp() + | 430 input_frame_->set_timestamp(input_frame_->timestamp() + |
417 kTimestampIncrementPerFrame); | 431 kTimestampIncrementPerFrame); |
418 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 432 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
419 encoder_->Encode(*input_frame_, nullptr, nullptr)); | 433 encoder_->Encode(*input_frame_, nullptr, nullptr)); |
420 ExpectFrameWith((picture_id + 4) % (1 << 15), (tl0_pic_idx + 2) % (1 << 8), | 434 ExpectFrameWith((picture_id + 4) % (1 << 15), (tl0_pic_idx + 2) % (1 << 8), |
421 0); | 435 0); |
422 | 436 |
423 // Temporal layer 1. | 437 // Temporal layer 1. |
(...skipping 14 matching lines...) Expand all Loading... |
438 | 452 |
439 // Temporal layer 1. | 453 // Temporal layer 1. |
440 input_frame_->set_timestamp(input_frame_->timestamp() + | 454 input_frame_->set_timestamp(input_frame_->timestamp() + |
441 kTimestampIncrementPerFrame); | 455 kTimestampIncrementPerFrame); |
442 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, | 456 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
443 encoder_->Encode(*input_frame_, nullptr, nullptr)); | 457 encoder_->Encode(*input_frame_, nullptr, nullptr)); |
444 ExpectFrameWith((picture_id + 7) % (1 << 15), (tl0_pic_idx + 3) % (1 << 8), | 458 ExpectFrameWith((picture_id + 7) % (1 << 15), (tl0_pic_idx + 3) % (1 << 8), |
445 1); | 459 1); |
446 } | 460 } |
447 | 461 |
| 462 TEST_F(TestVp8Impl, ScalingDisabledIfAutomaticResizeOff) { |
| 463 webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_); |
| 464 codec_settings_.VP8()->tl_factory = &tl_factory_; |
| 465 codec_settings_.VP8()->automaticResizeOn = false; |
| 466 |
| 467 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 468 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
| 469 VideoEncoder::ScalingSettings settings = encoder_->GetScalingSettings(); |
| 470 EXPECT_FALSE(settings.enabled); |
| 471 } |
| 472 |
| 473 TEST_F(TestVp8Impl, ScalingEnabledIfAutomaticResizeOn) { |
| 474 webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_); |
| 475 codec_settings_.VP8()->tl_factory = &tl_factory_; |
| 476 codec_settings_.VP8()->automaticResizeOn = true; |
| 477 |
| 478 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 479 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
| 480 VideoEncoder::ScalingSettings settings = encoder_->GetScalingSettings(); |
| 481 EXPECT_TRUE(settings.enabled); |
| 482 EXPECT_EQ(kDefaultMinPixelsPerFrame, settings.min_pixels_per_frame); |
| 483 } |
| 484 |
| 485 class TestVp8ImplWithForcedFallbackEnabled : public TestVp8Impl { |
| 486 public: |
| 487 TestVp8ImplWithForcedFallbackEnabled() |
| 488 : TestVp8Impl("WebRTC-VP8-Forced-Fallback-Encoder/Enabled-1,2,3," + |
| 489 std::to_string(kMinPixelsPerFrame) + "/") {} |
| 490 }; |
| 491 |
| 492 TEST_F(TestVp8ImplWithForcedFallbackEnabled, MinPixelsPerFrameConfigured) { |
| 493 webrtc::test::CodecSettings(kVideoCodecVP8, &codec_settings_); |
| 494 codec_settings_.VP8()->tl_factory = &tl_factory_; |
| 495 codec_settings_.VP8()->automaticResizeOn = true; |
| 496 |
| 497 EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| 498 encoder_->InitEncode(&codec_settings_, kNumCores, kMaxPayloadSize)); |
| 499 VideoEncoder::ScalingSettings settings = encoder_->GetScalingSettings(); |
| 500 EXPECT_TRUE(settings.enabled); |
| 501 EXPECT_EQ(kMinPixelsPerFrame, settings.min_pixels_per_frame); |
| 502 } |
| 503 |
448 } // namespace webrtc | 504 } // namespace webrtc |
OLD | NEW |