Chromium Code Reviews| Index: webrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc |
| diff --git a/webrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc b/webrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc |
| index 9a0f3db145a82dedf6ee53250cc955ee8d4c09f7..299d41cf1157c50f22c34a0785c6b53ab385b58e 100644 |
| --- a/webrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc |
| +++ b/webrtc/modules/video_coding/codecs/vp8/test/vp8_impl_unittest.cc |
| @@ -19,6 +19,7 @@ |
| #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
| #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" |
| #include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h" |
| +#include "webrtc/modules/video_coding/include/video_codec_interface.h" |
| #include "webrtc/test/frame_utils.h" |
| #include "webrtc/test/gtest.h" |
| #include "webrtc/test/testsupport/fileutils.h" |
| @@ -26,26 +27,31 @@ |
| namespace webrtc { |
| namespace { |
| + |
| void Calc16ByteAlignedStride(int width, int* stride_y, int* stride_uv) { |
| *stride_y = 16 * ((width + 15) / 16); |
| *stride_uv = 16 * ((width + 31) / 32); |
| } |
| -} // Anonymous namespace |
| - |
| enum { kMaxWaitEncTimeMs = 100 }; |
| enum { kMaxWaitDecTimeMs = 25 }; |
| -static const uint32_t kTestTimestamp = 123; |
| -static const int64_t kTestNtpTimeMs = 456; |
| +constexpr uint32_t kTestTimestamp = 123; |
| +constexpr int64_t kTestNtpTimeMs = 456; |
| +constexpr uint32_t kTimestampIncrementPerFrame = 3000; |
| + |
| +} // namespace |
| // TODO(mikhal): Replace these with mocks. |
| class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback { |
| public: |
| Vp8UnitTestEncodeCompleteCallback(EncodedImage* frame, |
| + CodecSpecificInfo* codec_specific_info, |
| unsigned int decoderSpecificSize, |
| void* decoderSpecificInfo) |
| - : encoded_frame_(frame), encode_complete_(false) {} |
| + : encoded_frame_(frame), |
| + codec_specific_info_(codec_specific_info), |
| + encode_complete_(false) {} |
| Result OnEncodedImage(const EncodedImage& encoded_frame_, |
| const CodecSpecificInfo* codec_specific_info, |
| @@ -54,6 +60,7 @@ class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback { |
| private: |
| EncodedImage* const encoded_frame_; |
| + CodecSpecificInfo* const codec_specific_info_; |
| std::unique_ptr<uint8_t[]> frame_buffer_; |
| bool encode_complete_; |
| }; |
| @@ -77,6 +84,9 @@ Vp8UnitTestEncodeCompleteCallback::OnEncodedImage( |
| encoded_frame_->_frameType = encoded_frame._frameType; |
| encoded_frame_->_completeFrame = encoded_frame._completeFrame; |
| encoded_frame_->qp_ = encoded_frame.qp_; |
| + codec_specific_info_->codecType = codec_specific_info->codecType; |
| + // Skip |codec_name|, to avoid allocating. |
| + codec_specific_info_->codecSpecific = codec_specific_info->codecSpecific; |
| encode_complete_ = true; |
| return Result(Result::OK, 0); |
| } |
| @@ -136,8 +146,8 @@ class TestVp8Impl : public ::testing::Test { |
| encoder_.reset(VP8Encoder::Create()); |
| decoder_.reset(VP8Decoder::Create()); |
| memset(&codec_inst_, 0, sizeof(codec_inst_)); |
| - encode_complete_callback_.reset( |
| - new Vp8UnitTestEncodeCompleteCallback(&encoded_frame_, 0, NULL)); |
| + encode_complete_callback_.reset(new Vp8UnitTestEncodeCompleteCallback( |
| + &encoded_frame_, &codec_specific_info_, 0, nullptr)); |
| decode_complete_callback_.reset( |
| new Vp8UnitTestDecodeCompleteCallback(&decoded_frame_, &decoded_qp_)); |
| encoder_->RegisterEncodeCompleteCallback(encode_complete_callback_.get()); |
| @@ -145,7 +155,7 @@ class TestVp8Impl : public ::testing::Test { |
| // Using a QCIF image (aligned stride (u,v planes) > width). |
| // Processing only one frame. |
| source_file_ = fopen(test::ResourcePath("paris_qcif", "yuv").c_str(), "rb"); |
| - ASSERT_TRUE(source_file_ != NULL); |
| + ASSERT_TRUE(source_file_ != nullptr); |
| rtc::scoped_refptr<VideoFrameBuffer> compact_buffer( |
| test::ReadI420Buffer(kWidth, kHeight, source_file_)); |
| ASSERT_TRUE(compact_buffer); |
| @@ -205,6 +215,13 @@ class TestVp8Impl : public ::testing::Test { |
| return 0; |
| } |
| + void ExpectFrame(int16_t picture_id, int tl0_pic_idx, uint8_t temporal_idx) { |
|
stefan-webrtc
2017/05/02 07:21:50
ExpectFrameWith() might be a better name
brandtr
2017/05/02 07:48:50
Done.
|
| + ASSERT_TRUE(WaitForEncodedFrame()); |
| + EXPECT_EQ(picture_id, codec_specific_info_.codecSpecific.VP8.pictureId); |
| + EXPECT_EQ(tl0_pic_idx, codec_specific_info_.codecSpecific.VP8.tl0PicIdx); |
| + EXPECT_EQ(temporal_idx, codec_specific_info_.codecSpecific.VP8.temporalIdx); |
| + } |
| + |
| const int kWidth = 172; |
| const int kHeight = 144; |
| @@ -216,6 +233,7 @@ class TestVp8Impl : public ::testing::Test { |
| std::unique_ptr<VideoEncoder> encoder_; |
| std::unique_ptr<VideoDecoder> decoder_; |
| EncodedImage encoded_frame_; |
| + CodecSpecificInfo codec_specific_info_; |
| rtc::Optional<VideoFrame> decoded_frame_; |
| rtc::Optional<uint8_t> decoded_qp_; |
| VideoCodec codec_inst_; |
| @@ -274,13 +292,13 @@ TEST_F(TestVp8Impl, DecodedQpEqualsEncodedQp) { |
| #endif |
| TEST_F(TestVp8Impl, MAYBE_AlignedStrideEncodeDecode) { |
| SetUpEncodeDecode(); |
| - encoder_->Encode(*input_frame_, NULL, NULL); |
| + encoder_->Encode(*input_frame_, nullptr, nullptr); |
| EXPECT_GT(WaitForEncodedFrame(), 0u); |
| // First frame should be a key frame. |
| encoded_frame_._frameType = kVideoFrameKey; |
| encoded_frame_.ntp_time_ms_ = kTestNtpTimeMs; |
| EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| - decoder_->Decode(encoded_frame_, false, NULL)); |
| + decoder_->Decode(encoded_frame_, false, nullptr)); |
| EXPECT_GT(WaitForDecodedFrame(), 0u); |
| ASSERT_TRUE(decoded_frame_); |
| // Compute PSNR on all planes (faster than SSIM). |
| @@ -296,23 +314,91 @@ TEST_F(TestVp8Impl, MAYBE_AlignedStrideEncodeDecode) { |
| #endif |
| TEST_F(TestVp8Impl, MAYBE_DecodeWithACompleteKeyFrame) { |
| SetUpEncodeDecode(); |
| - encoder_->Encode(*input_frame_, NULL, NULL); |
| + encoder_->Encode(*input_frame_, nullptr, nullptr); |
| EXPECT_GT(WaitForEncodedFrame(), 0u); |
| // Setting complete to false -> should return an error. |
| encoded_frame_._completeFrame = false; |
| EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, |
| - decoder_->Decode(encoded_frame_, false, NULL)); |
| + decoder_->Decode(encoded_frame_, false, nullptr)); |
| // Setting complete back to true. Forcing a delta frame. |
| encoded_frame_._frameType = kVideoFrameDelta; |
| encoded_frame_._completeFrame = true; |
| EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR, |
| - decoder_->Decode(encoded_frame_, false, NULL)); |
| + decoder_->Decode(encoded_frame_, false, nullptr)); |
| // Now setting a key frame. |
| encoded_frame_._frameType = kVideoFrameKey; |
| EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| - decoder_->Decode(encoded_frame_, false, NULL)); |
| + decoder_->Decode(encoded_frame_, false, nullptr)); |
| ASSERT_TRUE(decoded_frame_); |
| EXPECT_GT(I420PSNR(input_frame_.get(), &*decoded_frame_), 36); |
| } |
| +TEST_F(TestVp8Impl, EncoderRetainsRtpStateAfterRelease) { |
| + SetUpEncodeDecode(); |
| + // Override default settings. |
| + codec_inst_.VP8()->numberOfTemporalLayers = 2; |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codec_inst_, 1, 1440)); |
| + |
| + // Temporal layer 0. |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ASSERT_TRUE(WaitForEncodedFrame()); |
| + EXPECT_EQ(0, codec_specific_info_.codecSpecific.VP8.temporalIdx); |
| + int16_t picture_id = codec_specific_info_.codecSpecific.VP8.pictureId; |
| + int tl0_pic_idx = codec_specific_info_.codecSpecific.VP8.tl0PicIdx; |
| + |
| + // Temporal layer 1. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 1) % (1 << 15), tl0_pic_idx, 1); |
| + |
| + // Temporal layer 0. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 2) % (1 << 15), (tl0_pic_idx + 1) % (1 << 8), 0); |
| + |
| + // Temporal layer 1. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 3) % (1 << 15), (tl0_pic_idx + 1) % (1 << 8), 1); |
| + |
| + // Reinit. |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release()); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->InitEncode(&codec_inst_, 1, 1440)); |
| + |
| + // Temporal layer 0. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 4) % (1 << 15), (tl0_pic_idx + 2) % (1 << 8), 0); |
| + |
| + // Temporal layer 1. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 5) % (1 << 15), (tl0_pic_idx + 2) % (1 << 8), 1); |
| + |
| + // Temporal layer 0. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 6) % (1 << 15), (tl0_pic_idx + 3) % (1 << 8), 0); |
| + |
| + // Temporal layer 1. |
| + input_frame_->set_timestamp(input_frame_->timestamp() + |
| + kTimestampIncrementPerFrame); |
| + EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, |
| + encoder_->Encode(*input_frame_, nullptr, nullptr)); |
| + ExpectFrame((picture_id + 7) % (1 << 15), (tl0_pic_idx + 3) % (1 << 8), 1); |
| +} |
| + |
| } // namespace webrtc |