Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "testing/gtest/include/gtest/gtest.h"
     12 #include "webrtc/modules/video_coding/codecs/test_framework/unit_test.h"
     13 #include "webrtc/modules/video_coding/codecs/test_framework/video_source.h"
     14 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
     15 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
     16 #include "webrtc/system_wrappers/interface/tick_util.h"
     17 #include "webrtc/test/testsupport/fileutils.h"
     18 #include "webrtc/test/testsupport/gtest_disable.h"
     19 
     20 namespace webrtc {
     21 
     22 enum { kMaxWaitEncTimeMs = 100 };
     23 enum { kMaxWaitDecTimeMs = 25 };
     24 
     25 static const uint32_t kTestTimestamp = 123;
     26 static const int64_t kTestNtpTimeMs = 456;
     27 
     28 // TODO(mikhal): Replace these with mocks.
     29 class Vp8UnitTestEncodeCompleteCallback : public webrtc::EncodedImageCallback {
     30  public:
     31   Vp8UnitTestEncodeCompleteCallback(VideoFrame* frame,
     32                                     unsigned int decoderSpecificSize,
     33                                     void* decoderSpecificInfo)
     34      : encoded_video_frame_(frame),
     35        encode_complete_(false) {}
     36   int Encoded(EncodedImage& encodedImage,
     37               const CodecSpecificInfo* codecSpecificInfo,
     38               const RTPFragmentationHeader*);
     39   bool EncodeComplete();
     40   // Note that this only makes sense if an encode has been completed
     41   VideoFrameType EncodedFrameType() const {return  encoded_frame_type_;}
     42 
     43  private:
     44   VideoFrame* encoded_video_frame_;
     45   bool encode_complete_;
     46   VideoFrameType encoded_frame_type_;
     47 };
     48 
     49 int Vp8UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
     50     const CodecSpecificInfo* codecSpecificInfo,
     51     const RTPFragmentationHeader* fragmentation) {
     52   encoded_video_frame_->VerifyAndAllocate(encodedImage._size);
     53   encoded_video_frame_->CopyFrame(encodedImage._size, encodedImage._buffer);
     54   encoded_video_frame_->SetLength(encodedImage._length);
     55   // TODO(mikhal): Update frame type API.
     56   // encoded_video_frame_->SetFrameType(encodedImage._frameType);
     57   encoded_video_frame_->SetWidth(encodedImage._encodedWidth);
     58   encoded_video_frame_->SetHeight(encodedImage._encodedHeight);
     59   encoded_video_frame_->SetTimeStamp(encodedImage._timeStamp);
     60   encode_complete_ = true;
     61   encoded_frame_type_ = encodedImage._frameType;
     62   return 0;
     63 }
     64 
     65 bool Vp8UnitTestEncodeCompleteCallback::EncodeComplete() {
     66   if (encode_complete_) {
     67     encode_complete_ = false;
     68     return true;
     69   }
     70   return false;
     71 }
     72 
     73 class Vp8UnitTestDecodeCompleteCallback : public webrtc::DecodedImageCallback {
     74  public:
     75   explicit Vp8UnitTestDecodeCompleteCallback(I420VideoFrame* frame)
     76       : decoded_video_frame_(frame),
     77         decode_complete(false) {}
     78   int Decoded(webrtc::I420VideoFrame& frame);
     79   bool DecodeComplete();
     80  private:
     81   I420VideoFrame* decoded_video_frame_;
     82   bool decode_complete;
     83 };
     84 
     85 bool Vp8UnitTestDecodeCompleteCallback::DecodeComplete() {
     86   if (decode_complete) {
     87     decode_complete = false;
     88     return true;
     89   }
     90   return false;
     91 }
     92 
     93 int Vp8UnitTestDecodeCompleteCallback::Decoded(I420VideoFrame& image) {
     94   decoded_video_frame_->CopyFrame(image);
     95   decode_complete = true;
     96   return 0;
     97 }
     98 
     99 class TestVp8Impl : public ::testing::Test {
    100  protected:
    101   virtual void SetUp() {
    102     encoder_.reset(VP8Encoder::Create());
    103     decoder_.reset(VP8Decoder::Create());
    104     memset(&codec_inst_, 0, sizeof(codec_inst_));
    105     encode_complete_callback_.reset(new
    106         Vp8UnitTestEncodeCompleteCallback(&encoded_video_frame_, 0, NULL));
    107     decode_complete_callback_.reset(new
    108         Vp8UnitTestDecodeCompleteCallback(&decoded_video_frame_));
    109     encoder_->RegisterEncodeCompleteCallback(encode_complete_callback_.get());
    110     decoder_->RegisterDecodeCompleteCallback(decode_complete_callback_.get());
    111     // Using a QCIF image (aligned stride (u,v planes) > width).
    112     // Processing only one frame.
    113     const VideoSource source(test::ResourcePath("paris_qcif", "yuv"), kQCIF);
    114     length_source_frame_ = source.GetFrameLength();
    115     source_buffer_.reset(new uint8_t[length_source_frame_]);
    116     source_file_ = fopen(source.GetFileName().c_str(), "rb");
    117     ASSERT_TRUE(source_file_ != NULL);
    118     // Set input frame.
    119     ASSERT_EQ(fread(source_buffer_.get(), 1, length_source_frame_,
    120         source_file_), length_source_frame_);
    121     codec_inst_.width = source.GetWidth();
    122     codec_inst_.height = source.GetHeight();
    123     codec_inst_.maxFramerate = source.GetFrameRate();
    124     // Setting aligned stride values.
    125     int stride_uv = 0;
    126     int stride_y = 0;
    127     Calc16ByteAlignedStride(codec_inst_.width, &stride_y, &stride_uv);
    128     EXPECT_EQ(stride_y, 176);
    129     EXPECT_EQ(stride_uv, 96);
    130 
    131     input_frame_.CreateEmptyFrame(codec_inst_.width, codec_inst_.height,
    132                                   stride_y, stride_uv, stride_uv);
    133     input_frame_.set_timestamp(kTestTimestamp);
    134     // Using ConvertToI420 to add stride to the image.
    135     EXPECT_EQ(0, ConvertToI420(kI420, source_buffer_.get(), 0, 0,
    136                                codec_inst_.width, codec_inst_.height,
    137                                0, kRotateNone, &input_frame_));
    138   }
    139 
    140   void SetUpEncodeDecode() {
    141     codec_inst_.startBitrate = 300;
    142     codec_inst_.maxBitrate = 4000;
    143     codec_inst_.qpMax = 56;
    144     codec_inst_.codecSpecific.VP8.denoisingOn = true;
    145 
    146     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
    147         encoder_->InitEncode(&codec_inst_, 1, 1440));
    148     EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_inst_, 1));
    149   }
    150 
    151   int WaitForEncodedFrame() const {
    152     int64_t startTime = TickTime::MillisecondTimestamp();
    153     while (TickTime::MillisecondTimestamp() - startTime < kMaxWaitEncTimeMs) {
    154       if (encode_complete_callback_->EncodeComplete()) {
    155         return encoded_video_frame_.Length();
    156       }
    157     }
    158     return 0;
    159   }
    160 
    161   int WaitForDecodedFrame() const {
    162     int64_t startTime = TickTime::MillisecondTimestamp();
    163     while (TickTime::MillisecondTimestamp() - startTime < kMaxWaitDecTimeMs) {
    164       if (decode_complete_callback_->DecodeComplete()) {
    165         return CalcBufferSize(kI420, decoded_video_frame_.width(),
    166                               decoded_video_frame_.height());
    167       }
    168     }
    169     return 0;
    170   }
    171 
    172   void VideoFrameToEncodedImage(VideoFrame& frame, EncodedImage &image) {
    173     image._buffer = frame.Buffer();
    174     image._length = frame.Length();
    175     image._size = frame.Size();
    176     image._timeStamp = frame.TimeStamp();
    177     image._encodedWidth = frame.Width();
    178     image._encodedHeight = frame.Height();
    179     image._completeFrame = true;
    180   }
    181 
    182   scoped_ptr<Vp8UnitTestEncodeCompleteCallback> encode_complete_callback_;
    183   scoped_ptr<Vp8UnitTestDecodeCompleteCallback> decode_complete_callback_;
    184   scoped_ptr<uint8_t[]> source_buffer_;
    185   FILE* source_file_;
    186   I420VideoFrame input_frame_;
    187   scoped_ptr<VideoEncoder> encoder_;
    188   scoped_ptr<VideoDecoder> decoder_;
    189   VideoFrame encoded_video_frame_;
    190   I420VideoFrame decoded_video_frame_;
    191   unsigned int length_source_frame_;
    192   VideoCodec codec_inst_;
    193 };
    194 
    195 TEST_F(TestVp8Impl, DISABLED_ON_ANDROID(BaseUnitTest)) {
    196   // TODO(mikhal): Remove dependency. Move all test code here.
    197   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
    198   UnitTest unittest;
    199   unittest.SetEncoder(encoder_.get());
    200   unittest.SetDecoder(decoder_.get());
    201   unittest.Setup();
    202   unittest.Perform();
    203   unittest.Print();
    204 }
    205 
    206 TEST_F(TestVp8Impl, EncoderParameterTest) {
    207   strncpy(codec_inst_.plName, "VP8", 31);
    208   codec_inst_.plType = 126;
    209   codec_inst_.maxBitrate = 0;
    210   codec_inst_.minBitrate = 0;
    211   codec_inst_.width = 1440;
    212   codec_inst_.height = 1080;
    213   codec_inst_.maxFramerate = 30;
    214   codec_inst_.startBitrate = 300;
    215   codec_inst_.qpMax = 56;
    216   codec_inst_.codecSpecific.VP8.complexity = kComplexityNormal;
    217   codec_inst_.codecSpecific.VP8.numberOfTemporalLayers = 1;
    218   // Calls before InitEncode().
    219   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, encoder_->Release());
    220   int bit_rate = 300;
    221   EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
    222             encoder_->SetRates(bit_rate, codec_inst_.maxFramerate));
    223 
    224   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
    225             encoder_->InitEncode(&codec_inst_, 1, 1440));
    226 
    227   // Decoder parameter tests.
    228   // Calls before InitDecode().
    229   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Release());
    230   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->InitDecode(&codec_inst_, 1));
    231 }
    232 
    233 TEST_F(TestVp8Impl, DISABLED_ON_ANDROID(AlignedStrideEncodeDecode)) {
    234   SetUpEncodeDecode();
    235   encoder_->Encode(input_frame_, NULL, NULL);
    236   EXPECT_GT(WaitForEncodedFrame(), 0);
    237   EncodedImage encodedImage;
    238   VideoFrameToEncodedImage(encoded_video_frame_, encodedImage);
    239   // First frame should be a key frame.
    240   encodedImage._frameType = kKeyFrame;
    241   encodedImage.ntp_time_ms_ = kTestNtpTimeMs;
    242   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, decoder_->Decode(encodedImage, false, NULL));
    243   EXPECT_GT(WaitForDecodedFrame(), 0);
    244   // Compute PSNR on all planes (faster than SSIM).
    245   EXPECT_GT(I420PSNR(&input_frame_, &decoded_video_frame_), 36);
    246   EXPECT_EQ(kTestTimestamp, decoded_video_frame_.timestamp());
    247   EXPECT_EQ(kTestNtpTimeMs, decoded_video_frame_.ntp_time_ms());
    248 }
    249 
    250 TEST_F(TestVp8Impl, DISABLED_ON_ANDROID(DecodeWithACompleteKeyFrame)) {
    251   SetUpEncodeDecode();
    252   encoder_->Encode(input_frame_, NULL, NULL);
    253   EXPECT_GT(WaitForEncodedFrame(), 0);
    254   EncodedImage encodedImage;
    255   VideoFrameToEncodedImage(encoded_video_frame_, encodedImage);
    256   // Setting complete to false -> should return an error.
    257   encodedImage._completeFrame = false;
    258   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
    259       decoder_->Decode(encodedImage, false, NULL));
    260   // Setting complete back to true. Forcing a delta frame.
    261   encodedImage._frameType = kDeltaFrame;
    262   encodedImage._completeFrame = true;
    263   EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
    264       decoder_->Decode(encodedImage, false, NULL));
    265   // Now setting a key frame.
    266   encodedImage._frameType = kKeyFrame;
    267   EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
    268       decoder_->Decode(encodedImage, false, NULL));
    269   EXPECT_GT(I420PSNR(&input_frame_, &decoded_video_frame_), 36);
    270 }
    271 
    272 }  // namespace webrtc
    273