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 <assert.h>
12 #include <math.h>
13 #include <stdlib.h>
14 #include <string.h>
15
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webrtc/modules/video_coding/codecs/test_framework/unit_test.h"
18 #include "webrtc/modules/video_coding/codecs/test_framework/video_source.h"
19 #include "webrtc/system_wrappers/interface/tick_util.h"
20 #include "webrtc/test/testsupport/fileutils.h"
21
22 using namespace webrtc;
23
UnitTest()24 UnitTest::UnitTest()
25 :
26 CodecTest("UnitTest", "Unit test"),
27 _tests(0),
28 _errors(0),
29 _source(NULL),
30 _refFrame(NULL),
31 _refEncFrame(NULL),
32 _refDecFrame(NULL),
33 _refEncFrameLength(0),
34 _sourceFile(NULL),
35 is_key_frame_(false),
36 _encodeCompleteCallback(NULL),
37 _decodeCompleteCallback(NULL)
38 {
39 }
40
UnitTest(std::string name,std::string description)41 UnitTest::UnitTest(std::string name, std::string description)
42 :
43 CodecTest(name, description),
44 _tests(0),
45 _errors(0),
46 _source(NULL),
47 _refFrame(NULL),
48 _refEncFrame(NULL),
49 _refDecFrame(NULL),
50 _refEncFrameLength(0),
51 _sourceFile(NULL),
52 is_key_frame_(false),
53 _encodeCompleteCallback(NULL),
54 _decodeCompleteCallback(NULL)
55 {
56 }
57
~UnitTest()58 UnitTest::~UnitTest()
59 {
60 if (_encodeCompleteCallback) {
61 delete _encodeCompleteCallback;
62 }
63
64 if (_decodeCompleteCallback) {
65 delete _decodeCompleteCallback;
66 }
67
68 if (_source) {
69 delete _source;
70 }
71
72 if (_refFrame) {
73 delete [] _refFrame;
74 }
75
76 if (_refDecFrame) {
77 delete [] _refDecFrame;
78 }
79
80 if (_sourceBuffer) {
81 delete [] _sourceBuffer;
82 }
83
84 if (_sourceFile) {
85 fclose(_sourceFile);
86 }
87
88 if (_refEncFrame) {
89 delete [] _refEncFrame;
90 }
91 }
92
93 int32_t
Encoded(EncodedImage & encodedImage,const webrtc::CodecSpecificInfo * codecSpecificInfo,const webrtc::RTPFragmentationHeader * fragmentation)94 UnitTestEncodeCompleteCallback::Encoded(EncodedImage& encodedImage,
95 const webrtc::CodecSpecificInfo* codecSpecificInfo,
96 const webrtc::RTPFragmentationHeader*
97 fragmentation)
98 {
99 _encodedVideoBuffer->VerifyAndAllocate(encodedImage._size);
100 _encodedVideoBuffer->CopyFrame(encodedImage._size, encodedImage._buffer);
101 _encodedVideoBuffer->SetLength(encodedImage._length);
102 // TODO(mikhal): Update frame type API.
103 // _encodedVideoBuffer->SetFrameType(encodedImage._frameType);
104 _encodedVideoBuffer->SetWidth(
105 (uint16_t)encodedImage._encodedWidth);
106 _encodedVideoBuffer->SetHeight(
107 (uint16_t)encodedImage._encodedHeight);
108 _encodedVideoBuffer->SetTimeStamp(encodedImage._timeStamp);
109 _encodeComplete = true;
110 _encodedFrameType = encodedImage._frameType;
111 return 0;
112 }
113
Decoded(I420VideoFrame & image)114 int32_t UnitTestDecodeCompleteCallback::Decoded(I420VideoFrame& image)
115 {
116 _decodedVideoBuffer->CopyFrame(image);
117 _decodeComplete = true;
118 return 0;
119 }
120
121 bool
EncodeComplete()122 UnitTestEncodeCompleteCallback::EncodeComplete()
123 {
124 if (_encodeComplete)
125 {
126 _encodeComplete = false;
127 return true;
128 }
129 return false;
130 }
131
132 VideoFrameType
EncodedFrameType() const133 UnitTestEncodeCompleteCallback::EncodedFrameType() const
134 {
135 return _encodedFrameType;
136 }
137
138 bool
DecodeComplete()139 UnitTestDecodeCompleteCallback::DecodeComplete()
140 {
141 if (_decodeComplete)
142 {
143 _decodeComplete = false;
144 return true;
145 }
146 return false;
147 }
148
149 uint32_t
WaitForEncodedFrame() const150 UnitTest::WaitForEncodedFrame() const
151 {
152 int64_t startTime = TickTime::MillisecondTimestamp();
153 while (TickTime::MillisecondTimestamp() - startTime < kMaxWaitEncTimeMs)
154 {
155 if (_encodeCompleteCallback->EncodeComplete())
156 {
157 return _encodedVideoBuffer.Length();
158 }
159 }
160 return 0;
161 }
162
163 uint32_t
WaitForDecodedFrame() const164 UnitTest::WaitForDecodedFrame() const
165 {
166 int64_t startTime = TickTime::MillisecondTimestamp();
167 while (TickTime::MillisecondTimestamp() - startTime < kMaxWaitDecTimeMs)
168 {
169 if (_decodeCompleteCallback->DecodeComplete())
170 {
171 return webrtc::CalcBufferSize(kI420, _decodedVideoBuffer.width(),
172 _decodedVideoBuffer.height());
173 }
174 }
175 return 0;
176 }
177
178 uint32_t
CodecSpecific_SetBitrate(uint32_t bitRate,uint32_t)179 UnitTest::CodecSpecific_SetBitrate(uint32_t bitRate,
180 uint32_t /* frameRate */)
181 {
182 return _encoder->SetRates(bitRate, _inst.maxFramerate);
183 }
184
185 void
Setup()186 UnitTest::Setup()
187 {
188 // Use _sourceFile as a check to prevent multiple Setup() calls.
189 if (_sourceFile != NULL)
190 {
191 return;
192 }
193
194 if (_encodeCompleteCallback == NULL)
195 {
196 _encodeCompleteCallback =
197 new UnitTestEncodeCompleteCallback(&_encodedVideoBuffer);
198 }
199 if (_decodeCompleteCallback == NULL)
200 {
201 _decodeCompleteCallback =
202 new UnitTestDecodeCompleteCallback(&_decodedVideoBuffer);
203 }
204
205 _encoder->RegisterEncodeCompleteCallback(_encodeCompleteCallback);
206 _decoder->RegisterDecodeCompleteCallback(_decodeCompleteCallback);
207
208 _source = new VideoSource(webrtc::test::ProjectRootPath() +
209 "resources/foreman_cif.yuv", kCIF);
210
211 _lengthSourceFrame = _source->GetFrameLength();
212 _refFrame = new unsigned char[_lengthSourceFrame];
213 _refDecFrame = new unsigned char[_lengthSourceFrame];
214 _sourceBuffer = new unsigned char [_lengthSourceFrame];
215 _sourceFile = fopen(_source->GetFileName().c_str(), "rb");
216 ASSERT_TRUE(_sourceFile != NULL);
217
218 _inst.maxFramerate = _source->GetFrameRate();
219 _bitRate = 300;
220 _inst.startBitrate = 300;
221 _inst.maxBitrate = 4000;
222 _inst.width = _source->GetWidth();
223 _inst.height = _source->GetHeight();
224 _inst.qpMax = 56;
225 _inst.codecSpecific.VP8.denoisingOn = true;
226
227 // Get input frame.
228 ASSERT_TRUE(fread(_refFrame, 1, _lengthSourceFrame, _sourceFile)
229 == _lengthSourceFrame);
230 int size_y = _inst.width * _inst.height;
231 int size_uv = ((_inst.width + 1) / 2) * ((_inst.height + 1) / 2);
232 _inputVideoBuffer.CreateFrame(size_y, _refFrame,
233 size_uv, _refFrame + size_y,
234 size_uv, _refFrame + size_y + size_uv,
235 _inst.width, _inst.height,
236 _inst.width,
237 (_inst.width + 1) / 2, (_inst.width + 1) / 2);
238 rewind(_sourceFile);
239
240 // Get a reference encoded frame.
241 _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
242
243 // Ensures our initial parameters are valid.
244 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
245 _encoder->Encode(_inputVideoBuffer, NULL, NULL);
246 _refEncFrameLength = WaitForEncodedFrame();
247 ASSERT_TRUE(_refEncFrameLength > 0);
248 _refEncFrame = new unsigned char[_refEncFrameLength];
249 memcpy(_refEncFrame, _encodedVideoBuffer.Buffer(), _refEncFrameLength);
250
251 // Get a reference decoded frame.
252 _decodedVideoBuffer.CreateEmptyFrame(_inst.width, _inst.height, _inst.width,
253 (_inst.width + 1) / 2,
254 (_inst.width + 1) / 2);
255 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
256 ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
257
258 unsigned int frameLength = 0;
259 int i = 0;
260 _inputVideoBuffer.CreateEmptyFrame(_inst.width, _inst.height, _inst.width,
261 (_inst.width + 1) / 2,
262 (_inst.width + 1) / 2);
263 while (frameLength == 0)
264 {
265 EncodedImage encodedImage;
266 if (i > 0)
267 {
268 // Insert yet another frame.
269 ASSERT_TRUE(fread(_refFrame, 1, _lengthSourceFrame,
270 _sourceFile) == _lengthSourceFrame);
271 EXPECT_EQ(0, ConvertToI420(kI420, _refFrame, 0, 0, _width, _height,
272 0, kRotateNone, &_inputVideoBuffer));
273 _encoder->Encode(_inputVideoBuffer, NULL, NULL);
274 ASSERT_TRUE(WaitForEncodedFrame() > 0);
275 } else {
276 // The first frame is always a key frame.
277 encodedImage._frameType = kKeyFrame;
278 }
279
280 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
281 ASSERT_TRUE(_decoder->Decode(encodedImage, 0, NULL)
282 == WEBRTC_VIDEO_CODEC_OK);
283 frameLength = WaitForDecodedFrame();
284 _encodedVideoBuffer.SetLength(0);
285 i++;
286 }
287 rewind(_sourceFile);
288 EXPECT_TRUE(frameLength == _lengthSourceFrame);
289 ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame, _refDecFrame);
290 }
291
292 void
Teardown()293 UnitTest::Teardown()
294 {
295 // Use _sourceFile as a check to prevent multiple Teardown() calls.
296 if (_sourceFile == NULL)
297 {
298 return;
299 }
300
301 _encoder->Release();
302 _decoder->Release();
303
304 fclose(_sourceFile);
305 _sourceFile = NULL;
306 delete [] _refFrame;
307 _refFrame = NULL;
308 delete [] _refEncFrame;
309 _refEncFrame = NULL;
310 delete [] _refDecFrame;
311 _refDecFrame = NULL;
312 delete [] _sourceBuffer;
313 _sourceBuffer = NULL;
314 }
315
316 void
Print()317 UnitTest::Print()
318 {
319 }
320
321 int
DecodeWithoutAssert()322 UnitTest::DecodeWithoutAssert()
323 {
324 EncodedImage encodedImage;
325 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
326 int ret = _decoder->Decode(encodedImage, 0, NULL);
327 int frameLength = WaitForDecodedFrame();
328 _encodedVideoBuffer.SetLength(0);
329 return ret == WEBRTC_VIDEO_CODEC_OK ? frameLength : ret;
330 }
331
332 int
Decode()333 UnitTest::Decode()
334 {
335 EncodedImage encodedImage;
336 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
337 if (encodedImage._length == 0)
338 {
339 return WEBRTC_VIDEO_CODEC_OK;
340 }
341 if (is_key_frame_) {
342 encodedImage._frameType = kKeyFrame;
343 }
344
345 int ret = _decoder->Decode(encodedImage, 0, NULL);
346 unsigned int frameLength = WaitForDecodedFrame();
347 assert(ret == WEBRTC_VIDEO_CODEC_OK && (frameLength == 0 || frameLength
348 == _lengthSourceFrame));
349 EXPECT_TRUE(ret == WEBRTC_VIDEO_CODEC_OK && (frameLength == 0 || frameLength
350 == _lengthSourceFrame));
351 _encodedVideoBuffer.SetLength(0);
352 return ret == WEBRTC_VIDEO_CODEC_OK ? frameLength : ret;
353 }
354
355 // Test pure virtual VideoEncoder and VideoDecoder APIs.
356 void
Perform()357 UnitTest::Perform()
358 {
359 UnitTest::Setup();
360 int frameLength;
361 I420VideoFrame inputImage;
362 EncodedImage encodedImage;
363
364 //----- Encoder parameter tests -----
365
366 //-- Calls before InitEncode() --
367 // We want to revert the initialization done in Setup().
368 EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
369 EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL)
370 == WEBRTC_VIDEO_CODEC_UNINITIALIZED);
371
372 //-- InitEncode() errors --
373 // Null pointer.
374 EXPECT_TRUE(_encoder->InitEncode(NULL, 1, 1440) ==
375 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
376 // bit rate exceeds max bit rate
377 int32_t tmpBitRate = _inst.startBitrate;
378 int32_t tmpMaxBitRate = _inst.maxBitrate;
379 _inst.startBitrate = 4000;
380 _inst.maxBitrate = 3000;
381 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
382 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
383 _inst.startBitrate = tmpBitRate;
384 _inst.maxBitrate = tmpMaxBitRate; //unspecified value
385
386 // Bad framerate.
387 _inst.maxFramerate = 0;
388 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
389 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
390 // Seems like we should allow any framerate in range [0, 255].
391 //_inst.frameRate = 100;
392 //EXPECT_TRUE(_encoder->InitEncode(&_inst, 1) == -1); // FAILS
393 _inst.maxFramerate = 30;
394
395 // Bad bitrate.
396 _inst.startBitrate = -1;
397 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
398 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
399 _inst.maxBitrate = _inst.startBitrate - 1;
400 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
401 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
402 _inst.maxBitrate = 0;
403 _inst.startBitrate = 300;
404
405 // Bad maxBitRate.
406 _inst.maxBitrate = 200;
407 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
408 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
409 _inst.maxBitrate = 4000;
410
411 // Bad width.
412 _inst.width = 0;
413 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) < 0);
414 _inst.width = _source->GetWidth();
415
416 // Bad height.
417 _inst.height = 0;
418 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) < 0);
419 _inst.height = _source->GetHeight();
420
421 // Bad number of cores.
422 EXPECT_TRUE(_encoder->InitEncode(&_inst, -1, 1440) ==
423 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
424
425 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
426
427 //-- Encode() errors --
428 inputImage.ResetSize();
429 EXPECT_TRUE(_encoder->Encode(inputImage, NULL, NULL) ==
430 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
431 int width = _source->GetWidth();
432 int half_width = (width + 1) / 2;
433 int height = _source->GetHeight();
434 int half_height = (height + 1) / 2;
435 int size_y = width * height;
436 int size_uv = half_width * half_height;
437 _inputVideoBuffer.CreateFrame(size_y, _refFrame,
438 size_uv, _refFrame + size_y,
439 size_uv, _refFrame + size_y + size_uv,
440 width, height,
441 width, half_width, half_width);
442 //----- Encoder stress tests -----
443
444 // Vary frame rate and I-frame request.
445 for (int i = 1; i <= 60; i++)
446 {
447 VideoFrameType frame_type = !(i % 2) ? kKeyFrame : kDeltaFrame;
448 std::vector<VideoFrameType> frame_types(1, frame_type);
449 EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, &frame_types) ==
450 WEBRTC_VIDEO_CODEC_OK);
451 EXPECT_TRUE(WaitForEncodedFrame() > 0);
452 }
453
454 // Init then encode.
455 _encodedVideoBuffer.SetLength(0);
456 EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
457 WEBRTC_VIDEO_CODEC_OK);
458 EXPECT_TRUE(WaitForEncodedFrame() > 0);
459
460 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
461 _encoder->Encode(_inputVideoBuffer, NULL, NULL);
462 frameLength = WaitForEncodedFrame();
463 EXPECT_TRUE(frameLength > 0);
464 EXPECT_TRUE(CheckIfBitExact(_refEncFrame, _refEncFrameLength,
465 _encodedVideoBuffer.Buffer(), frameLength) == true);
466
467 // Reset then encode.
468 _encodedVideoBuffer.SetLength(0);
469 EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
470 WEBRTC_VIDEO_CODEC_OK);
471 WaitForEncodedFrame();
472 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
473 _encoder->Encode(_inputVideoBuffer, NULL, NULL);
474 frameLength = WaitForEncodedFrame();
475 EXPECT_TRUE(frameLength > 0);
476 EXPECT_TRUE(CheckIfBitExact(_refEncFrame, _refEncFrameLength,
477 _encodedVideoBuffer.Buffer(), frameLength) == true);
478
479 // Release then encode.
480 _encodedVideoBuffer.SetLength(0);
481 EXPECT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
482 WEBRTC_VIDEO_CODEC_OK);
483 WaitForEncodedFrame();
484 EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
485 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
486 _encoder->Encode(_inputVideoBuffer, NULL, NULL);
487 frameLength = WaitForEncodedFrame();
488 EXPECT_TRUE(frameLength > 0);
489 EXPECT_TRUE(CheckIfBitExact(_refEncFrame, _refEncFrameLength,
490 _encodedVideoBuffer.Buffer(), frameLength) == true);
491
492 //----- Decoder parameter tests -----
493
494 //-- Calls before InitDecode() --
495 // We want to revert the initialization done in Setup().
496 EXPECT_TRUE(_decoder->Release() == WEBRTC_VIDEO_CODEC_OK);
497 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
498 EXPECT_TRUE(_decoder->Decode(encodedImage, false, NULL) ==
499 WEBRTC_VIDEO_CODEC_UNINITIALIZED);
500 WaitForDecodedFrame();
501 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_UNINITIALIZED);
502 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
503 ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
504
505 //-- Decode() errors --
506 // Unallocated encodedVideoBuffer.
507 _encodedVideoBuffer.Free();
508 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
509 encodedImage._length = 10; // Buffer NULL but length > 0
510 EXPECT_EQ(_decoder->Decode(encodedImage, false, NULL),
511 WEBRTC_VIDEO_CODEC_ERR_PARAMETER);
512 _encodedVideoBuffer.VerifyAndAllocate(_lengthSourceFrame);
513
514 //----- Decoder stress tests -----
515 unsigned char* tmpBuf = new unsigned char[_lengthSourceFrame];
516
517 // "Random" and zero data.
518 // We either expect an error, or at the least, no output.
519 // This relies on the codec's ability to detect an erroneous bitstream.
520 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
521 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
522 ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
523 for (int i = 0; i < 100; i++)
524 {
525 ASSERT_TRUE(fread(tmpBuf, 1, _refEncFrameLength, _sourceFile)
526 == _refEncFrameLength);
527 _encodedVideoBuffer.CopyFrame(_refEncFrameLength, tmpBuf);
528 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
529 int ret = _decoder->Decode(encodedImage, false, NULL);
530 EXPECT_TRUE(ret <= 0);
531 if (ret == 0)
532 {
533 EXPECT_TRUE(WaitForDecodedFrame() == 0);
534 }
535
536 memset(tmpBuf, 0, _refEncFrameLength);
537 _encodedVideoBuffer.CopyFrame(_refEncFrameLength, tmpBuf);
538 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
539 if (i == 0) {
540 // First frame is a key frame.
541 is_key_frame_ = true;
542 }
543 ret = _decoder->Decode(encodedImage, false, NULL);
544 EXPECT_TRUE(ret <= 0);
545 if (ret == 0)
546 {
547 EXPECT_TRUE(WaitForDecodedFrame() == 0);
548 }
549 }
550 rewind(_sourceFile);
551
552 _encodedVideoBuffer.SetLength(_refEncFrameLength);
553 _encodedVideoBuffer.CopyFrame(_refEncFrameLength, _refEncFrame);
554
555 // Init then decode.
556 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
557 ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
558 frameLength = 0;
559 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
560 // first frame is a key frame.
561 encodedImage._frameType = kKeyFrame;
562 while (frameLength == 0)
563 {
564 _decoder->Decode(encodedImage, false, NULL);
565 frameLength = WaitForDecodedFrame();
566 }
567 unsigned int length = CalcBufferSize(kI420, width, height);
568 scoped_ptr<uint8_t[]> decoded_buffer(new uint8_t[length]);
569 ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame,
570 decoded_buffer.get());
571 EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength, _refDecFrame,
572 _lengthSourceFrame) == true);
573
574 // Reset then decode.
575 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
576 frameLength = 0;
577 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
578 while (frameLength == 0)
579 {
580 _decoder->Decode(encodedImage, false, NULL);
581 frameLength = WaitForDecodedFrame();
582 }
583 ExtractBuffer(_decodedVideoBuffer, _lengthSourceFrame,
584 decoded_buffer.get());
585 EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength,
586 _refDecFrame, _lengthSourceFrame) == true);
587
588 // Decode with other size, reset, then decode with original size again
589 // to verify that decoder is reset to a "fresh" state upon Reset().
590 {
591 // Assert that input frame size is a factor of two, so that we can use
592 // quarter size below.
593 EXPECT_TRUE((_inst.width % 2 == 0) && (_inst.height % 2 == 0));
594
595 VideoCodec tempInst;
596 memcpy(&tempInst, &_inst, sizeof(VideoCodec));
597 tempInst.width /= 2;
598 tempInst.height /= 2;
599 int tmpHalfWidth = (tempInst.width + 1) / 2;
600 int tmpHalfHeight = (tempInst.height + 1) / 2;
601
602 int tmpSizeY = tempInst.width * tempInst.height;
603 int tmpSizeUv = tmpHalfWidth * tmpHalfHeight;
604
605 // Encode reduced (quarter) frame size.
606 EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
607 EXPECT_TRUE(_encoder->InitEncode(&tempInst, 1, 1440) ==
608 WEBRTC_VIDEO_CODEC_OK);
609 webrtc::I420VideoFrame tempInput;
610 tempInput.CreateFrame(tmpSizeY, _inputVideoBuffer.buffer(kYPlane),
611 tmpSizeUv, _inputVideoBuffer.buffer(kUPlane),
612 tmpSizeUv, _inputVideoBuffer.buffer(kVPlane),
613 tempInst.width, tempInst.height,
614 tempInst.width, tmpHalfWidth, tmpHalfWidth);
615 _encoder->Encode(tempInput, NULL, NULL);
616 frameLength = WaitForEncodedFrame();
617 EXPECT_TRUE(frameLength > 0);
618 // Reset then decode.
619 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
620 frameLength = 0;
621 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
622 while (frameLength == 0)
623 {
624 _decoder->Decode(encodedImage, false, NULL);
625 frameLength = WaitForDecodedFrame();
626 }
627
628 // Encode original frame again
629 EXPECT_TRUE(_encoder->Release() == WEBRTC_VIDEO_CODEC_OK);
630 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) ==
631 WEBRTC_VIDEO_CODEC_OK);
632 _encoder->Encode(_inputVideoBuffer, NULL, NULL);
633 frameLength = WaitForEncodedFrame();
634 EXPECT_TRUE(frameLength > 0);
635
636 // Reset then decode original frame again.
637 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
638 frameLength = 0;
639 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
640 while (frameLength == 0)
641 {
642 _decoder->Decode(encodedImage, false, NULL);
643 frameLength = WaitForDecodedFrame();
644 }
645
646 // check that decoded frame matches with reference
647 unsigned int length = CalcBufferSize(kI420, width, height);
648 scoped_ptr<uint8_t[]> decoded_buffer(new uint8_t[length]);
649 ExtractBuffer(_decodedVideoBuffer, length, decoded_buffer.get());
650 EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), length,
651 _refDecFrame, _lengthSourceFrame) == true);
652 }
653
654 // Release then decode.
655 EXPECT_TRUE(_decoder->Release() == WEBRTC_VIDEO_CODEC_OK);
656 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
657 ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
658 frameLength = 0;
659 VideoEncodedBufferToEncodedImage(_encodedVideoBuffer, encodedImage);
660 while (frameLength == 0)
661 {
662 _decoder->Decode(encodedImage, false, NULL);
663 frameLength = WaitForDecodedFrame();
664 }
665 ExtractBuffer(_decodedVideoBuffer, length, decoded_buffer.get());
666 EXPECT_TRUE(CheckIfBitExact(decoded_buffer.get(), frameLength,
667 _refDecFrame, _lengthSourceFrame) == true);
668 _encodedVideoBuffer.SetLength(0);
669
670 delete [] tmpBuf;
671
672 //----- Function tests -----
673 int frames = 0;
674 // Do not specify maxBitRate (as in ViE).
675 _inst.maxBitrate = 0;
676
677 //-- Timestamp propagation --
678 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
679 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
680 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
681 ASSERT_FALSE(SetCodecSpecificParameters() != WEBRTC_VIDEO_CODEC_OK);
682
683 frames = 0;
684 int frameDelay = 0;
685 int encTimeStamp;
686 _decodedVideoBuffer.set_timestamp(0);
687 while (fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile) ==
688 _lengthSourceFrame)
689 {
690 _inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
691 size_uv, _sourceBuffer + size_y,
692 size_uv, _sourceBuffer + size_y + size_uv,
693 width, height,
694 width, half_width, half_width);
695
696 _inputVideoBuffer.set_timestamp(frames);
697 ASSERT_TRUE(_encoder->Encode(_inputVideoBuffer, NULL, NULL) ==
698 WEBRTC_VIDEO_CODEC_OK);
699 frameLength = WaitForEncodedFrame();
700 //ASSERT_TRUE(frameLength);
701 EXPECT_TRUE(frameLength > 0);
702 encTimeStamp = _encodedVideoBuffer.TimeStamp();
703 EXPECT_TRUE(_inputVideoBuffer.timestamp() ==
704 static_cast<unsigned>(encTimeStamp));
705 if (frames == 0) {
706 // First frame is always a key frame.
707 is_key_frame_ = true;
708 }
709
710 frameLength = Decode();
711 if (frameLength == 0)
712 {
713 frameDelay++;
714 }
715
716 encTimeStamp -= frameDelay;
717 if (encTimeStamp < 0)
718 {
719 encTimeStamp = 0;
720 }
721 EXPECT_TRUE(_decodedVideoBuffer.timestamp() ==
722 static_cast<unsigned>(encTimeStamp));
723 frames++;
724 }
725 ASSERT_TRUE(feof(_sourceFile) != 0);
726 rewind(_sourceFile);
727
728 RateControlTests();
729
730 Teardown();
731 }
732
733 void
RateControlTests()734 UnitTest::RateControlTests()
735 {
736 int frames = 0;
737 VideoFrame inputImage;
738 uint32_t frameLength;
739
740 // Do not specify maxBitRate (as in ViE).
741 _inst.maxBitrate = 0;
742 // Verify rate control. For this test turn on codec frame dropper.
743 // At least one other test (BasicUnitTest) assumes frame dropper off, so
744 // for now we only set frame dropper on for this (rate control) test.
745 _inst.codecSpecific.VP8.frameDroppingOn = true;
746 EXPECT_TRUE(_encoder->InitEncode(&_inst, 1, 1440) == WEBRTC_VIDEO_CODEC_OK);
747 EXPECT_TRUE(_decoder->Reset() == WEBRTC_VIDEO_CODEC_OK);
748 EXPECT_TRUE(_decoder->InitDecode(&_inst, 1) == WEBRTC_VIDEO_CODEC_OK);
749 // add: should also be 0, and 1
750 const int bitRate[] = {100, 500};
751 const int nBitrates = sizeof(bitRate)/sizeof(*bitRate);
752
753 printf("\nRate control test\n");
754 for (int i = 0; i < nBitrates; i++)
755 {
756 _bitRate = bitRate[i];
757 int totalBytes = 0;
758 _inst.startBitrate = _bitRate;
759 _encoder->InitEncode(&_inst, 4, 1440);
760 _decoder->Reset();
761 _decoder->InitDecode(&_inst, 1);
762 frames = 0;
763
764 if (_bitRate > _inst.maxBitrate)
765 {
766 CodecSpecific_SetBitrate(_bitRate, _inst.maxFramerate);
767 }
768 else
769 {
770 CodecSpecific_SetBitrate(_bitRate, _inst.maxFramerate);
771 }
772 int width = _source->GetWidth();
773 int half_width = (width + 1) / 2;
774 int height = _source->GetHeight();
775 int half_height = (height + 1) / 2;
776 int size_y = width * height;
777 int size_uv = half_width * half_height;
778 while (fread(_sourceBuffer, 1, _lengthSourceFrame, _sourceFile) ==
779 _lengthSourceFrame)
780 {
781 _inputVideoBuffer.CreateFrame(size_y, _sourceBuffer,
782 size_uv, _sourceBuffer + size_y,
783 size_uv, _sourceBuffer + size_y +
784 size_uv,
785 width, height,
786 width, half_width, half_width);
787 _inputVideoBuffer.set_timestamp(static_cast<uint32_t>(9e4 /
788 static_cast<float>(_inst.maxFramerate)));
789 ASSERT_EQ(_encoder->Encode(_inputVideoBuffer, NULL, NULL),
790 WEBRTC_VIDEO_CODEC_OK);
791 frameLength = WaitForEncodedFrame();
792 ASSERT_GE(frameLength, 0u);
793 totalBytes += frameLength;
794 frames++;
795
796 _encodedVideoBuffer.SetLength(0);
797 }
798 uint32_t actualBitrate =
799 (totalBytes / frames * _inst.maxFramerate * 8)/1000;
800 printf("Target bitrate: %d kbps, actual bitrate: %d kbps\n", _bitRate,
801 actualBitrate);
802 // Test for close match over reasonable range.
803 EXPECT_TRUE(abs(int32_t(actualBitrate - _bitRate)) <
804 0.12 * _bitRate);
805 ASSERT_TRUE(feof(_sourceFile) != 0);
806 rewind(_sourceFile);
807 }
808 }
809
810 bool
CheckIfBitExact(const void * ptrA,unsigned int aLengthBytes,const void * ptrB,unsigned int bLengthBytes)811 UnitTest::CheckIfBitExact(const void* ptrA, unsigned int aLengthBytes,
812 const void* ptrB, unsigned int bLengthBytes)
813 {
814 if (aLengthBytes != bLengthBytes)
815 {
816 return false;
817 }
818
819 return memcmp(ptrA, ptrB, aLengthBytes) == 0;
820 }
821