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 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 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 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 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 114 int32_t UnitTestDecodeCompleteCallback::Decoded(I420VideoFrame& image) 115 { 116 _decodedVideoBuffer->CopyFrame(image); 117 _decodeComplete = true; 118 return 0; 119 } 120 121 bool 122 UnitTestEncodeCompleteCallback::EncodeComplete() 123 { 124 if (_encodeComplete) 125 { 126 _encodeComplete = false; 127 return true; 128 } 129 return false; 130 } 131 132 VideoFrameType 133 UnitTestEncodeCompleteCallback::EncodedFrameType() const 134 { 135 return _encodedFrameType; 136 } 137 138 bool 139 UnitTestDecodeCompleteCallback::DecodeComplete() 140 { 141 if (_decodeComplete) 142 { 143 _decodeComplete = false; 144 return true; 145 } 146 return false; 147 } 148 149 uint32_t 150 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 164 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 179 UnitTest::CodecSpecific_SetBitrate(uint32_t bitRate, 180 uint32_t /* frameRate */) 181 { 182 return _encoder->SetRates(bitRate, _inst.maxFramerate); 183 } 184 185 void 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 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 317 UnitTest::Print() 318 { 319 } 320 321 int 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 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 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 = static_cast<unsigned int>(-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 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 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