Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / video_coding / codecs / vp8 / test / vp8_impl_unittest.cc
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