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 "webrtc/modules/video_coding/codecs/test_framework/video_source.h" 12 13 #include <stdio.h> 14 15 #include "testing/gtest/include/gtest/gtest.h" 16 #include "webrtc/test/testsupport/fileutils.h" 17 18 VideoSource::VideoSource() 19 : 20 _fileName(webrtc::test::ProjectRootPath() + "resources/foreman_cif.yuv"), 21 _width(352), 22 _height(288), 23 _type(webrtc::kI420), 24 _frameRate(30) 25 { 26 } 27 28 VideoSource::VideoSource(std::string fileName, VideoSize size, 29 int frameRate /*= 30*/, webrtc::VideoType type /*= webrtc::kI420*/) 30 : 31 _fileName(fileName), 32 _type(type), 33 _frameRate(frameRate) 34 { 35 assert(size != kUndefined && size != kNumberOfVideoSizes); 36 assert(type != webrtc::kUnknown); 37 assert(frameRate > 0); 38 if (GetWidthHeight(size, _width, _height) != 0) { 39 assert(false); 40 } 41 } 42 43 VideoSource::VideoSource(std::string fileName, int width, int height, 44 int frameRate /*= 30*/, webrtc::VideoType type /*= webrtc::kI420*/) 45 : 46 _fileName(fileName), 47 _width(width), 48 _height(height), 49 _type(type), 50 _frameRate(frameRate) 51 { 52 assert(width > 0); 53 assert(height > 0); 54 assert(type != webrtc::kUnknown); 55 assert(frameRate > 0); 56 } 57 58 VideoSize 59 VideoSource::GetSize() const 60 { 61 return GetSize(_width, _height); 62 } 63 64 VideoSize 65 VideoSource::GetSize(uint16_t width, uint16_t height) 66 { 67 if(width == 128 && height == 96) 68 { 69 return kSQCIF; 70 }else if(width == 160 && height == 120) 71 { 72 return kQQVGA; 73 }else if(width == 176 && height == 144) 74 { 75 return kQCIF; 76 }else if(width == 320 && height == 240) 77 { 78 return kQVGA; 79 }else if(width == 352 && height == 288) 80 { 81 return kCIF; 82 }else if(width == 640 && height == 480) 83 { 84 return kVGA; 85 }else if(width == 720 && height == 480) 86 { 87 return kNTSC; 88 }else if(width == 704 && height == 576) 89 { 90 return k4CIF; 91 }else if(width == 800 && height == 600) 92 { 93 return kSVGA; 94 }else if(width == 960 && height == 720) 95 { 96 return kHD; 97 }else if(width == 1024 && height == 768) 98 { 99 return kXGA; 100 }else if(width == 1440 && height == 1080) 101 { 102 return kFullHD; 103 }else if(width == 400 && height == 240) 104 { 105 return kWQVGA; 106 }else if(width == 800 && height == 480) 107 { 108 return kWVGA; 109 }else if(width == 1280 && height == 720) 110 { 111 return kWHD; 112 }else if(width == 1920 && height == 1080) 113 { 114 return kWFullHD; 115 } 116 return kUndefined; 117 } 118 119 unsigned int 120 VideoSource::GetFrameLength() const 121 { 122 return webrtc::CalcBufferSize(_type, _width, _height); 123 } 124 125 const char* 126 VideoSource::GetMySizeString() const 127 { 128 return VideoSource::GetSizeString(GetSize()); 129 } 130 131 const char* 132 VideoSource::GetSizeString(VideoSize size) 133 { 134 switch (size) 135 { 136 case kSQCIF: 137 return "SQCIF"; 138 case kQQVGA: 139 return "QQVGA"; 140 case kQCIF: 141 return "QCIF"; 142 case kQVGA: 143 return "QVGA"; 144 case kCIF: 145 return "CIF"; 146 case kVGA: 147 return "VGA"; 148 case kNTSC: 149 return "NTSC"; 150 case k4CIF: 151 return "4CIF"; 152 case kSVGA: 153 return "SVGA"; 154 case kHD: 155 return "HD"; 156 case kXGA: 157 return "XGA"; 158 case kFullHD: 159 return "Full_HD"; 160 case kWQVGA: 161 return "WQVGA"; 162 case kWHD: 163 return "WHD"; 164 case kWFullHD: 165 return "WFull_HD"; 166 default: 167 return "Undefined"; 168 } 169 } 170 171 std::string 172 VideoSource::GetFilePath() const 173 { 174 size_t slashPos = _fileName.find_last_of("/\\"); 175 if (slashPos == std::string::npos) 176 { 177 return "."; 178 } 179 180 return _fileName.substr(0, slashPos); 181 } 182 183 std::string 184 VideoSource::GetName() const 185 { 186 // Remove path. 187 size_t slashPos = _fileName.find_last_of("/\\"); 188 if (slashPos == std::string::npos) 189 { 190 slashPos = 0; 191 } 192 else 193 { 194 slashPos++; 195 } 196 197 // Remove extension and underscored suffix if it exists. 198 return _fileName.substr(slashPos, std::min(_fileName.find_last_of("_"), 199 _fileName.find_last_of(".")) - slashPos); 200 } 201 202 void 203 VideoSource::Convert(const VideoSource &target, bool force /* = false */) const 204 { 205 // Ensure target rate is less than or equal to source 206 // (i.e. we are only temporally downsampling). 207 ASSERT_TRUE(target.GetFrameRate() <= _frameRate); 208 // Only supports YUV420 currently. 209 ASSERT_TRUE(_type == webrtc::kI420 && target.GetType() == webrtc::kI420); 210 if (!force && (FileExists(target.GetFileName().c_str()) || 211 (target.GetWidth() == _width && target.GetHeight() == _height && target.GetFrameRate() == _frameRate))) 212 { 213 // Assume that the filename uniquely defines the content. 214 // If the file already exists, it is the correct file. 215 return; 216 } 217 FILE *inFile = NULL; 218 FILE *outFile = NULL; 219 220 inFile = fopen(_fileName.c_str(), "rb"); 221 ASSERT_TRUE(inFile != NULL); 222 223 outFile = fopen(target.GetFileName().c_str(), "wb"); 224 ASSERT_TRUE(outFile != NULL); 225 226 FrameDropper fd; 227 fd.SetFrameRate(target.GetFrameRate(), _frameRate); 228 229 const size_t lengthOutFrame = webrtc::CalcBufferSize(target.GetType(), 230 target.GetWidth(), target.GetHeight()); 231 ASSERT_TRUE(lengthOutFrame > 0); 232 unsigned char *outFrame = new unsigned char[lengthOutFrame]; 233 234 const size_t lengthInFrame = webrtc::CalcBufferSize(_type, _width, _height); 235 ASSERT_TRUE(lengthInFrame > 0); 236 unsigned char *inFrame = new unsigned char[lengthInFrame]; 237 238 while (fread(inFrame, 1, lengthInFrame, inFile) == lengthInFrame) 239 { 240 if (!fd.DropFrame()) 241 { 242 ASSERT_TRUE(target.GetWidth() == _width && 243 target.GetHeight() == _height); 244 // Add video interpolator here! 245 if (fwrite(outFrame, 1, lengthOutFrame, 246 outFile) != lengthOutFrame) { 247 return; 248 } 249 } 250 } 251 252 delete inFrame; 253 delete outFrame; 254 fclose(inFile); 255 fclose(outFile); 256 } 257 258 bool VideoSource::FileExists(const char* fileName) 259 { 260 FILE* fp = NULL; 261 fp = fopen(fileName, "rb"); 262 if(fp != NULL) 263 { 264 fclose(fp); 265 return true; 266 } 267 return false; 268 } 269 270 271 int 272 VideoSource::GetWidthHeight( VideoSize size, int & width, int& height) 273 { 274 switch(size) 275 { 276 case kSQCIF: 277 width = 128; 278 height = 96; 279 return 0; 280 case kQQVGA: 281 width = 160; 282 height = 120; 283 return 0; 284 case kQCIF: 285 width = 176; 286 height = 144; 287 return 0; 288 case kCGA: 289 width = 320; 290 height = 200; 291 return 0; 292 case kQVGA: 293 width = 320; 294 height = 240; 295 return 0; 296 case kSIF: 297 width = 352; 298 height = 240; 299 return 0; 300 case kWQVGA: 301 width = 400; 302 height = 240; 303 return 0; 304 case kCIF: 305 width = 352; 306 height = 288; 307 return 0; 308 case kW288p: 309 width = 512; 310 height = 288; 311 return 0; 312 case k448p: 313 width = 576; 314 height = 448; 315 return 0; 316 case kVGA: 317 width = 640; 318 height = 480; 319 return 0; 320 case k432p: 321 width = 720; 322 height = 432; 323 return 0; 324 case kW432p: 325 width = 768; 326 height = 432; 327 return 0; 328 case k4SIF: 329 width = 704; 330 height = 480; 331 return 0; 332 case kW448p: 333 width = 768; 334 height = 448; 335 return 0; 336 case kNTSC: 337 width = 720; 338 height = 480; 339 return 0; 340 case kFW448p: 341 width = 800; 342 height = 448; 343 return 0; 344 case kWVGA: 345 width = 800; 346 height = 480; 347 return 0; 348 case k4CIF: 349 width = 704; 350 height = 576; 351 return 0; 352 case kSVGA: 353 width = 800; 354 height = 600; 355 return 0; 356 case kW544p: 357 width = 960; 358 height = 544; 359 return 0; 360 case kW576p: 361 width = 1024; 362 height = 576; 363 return 0; 364 case kHD: 365 width = 960; 366 height = 720; 367 return 0; 368 case kXGA: 369 width = 1024; 370 height = 768; 371 return 0; 372 case kFullHD: 373 width = 1440; 374 height = 1080; 375 return 0; 376 case kWHD: 377 width = 1280; 378 height = 720; 379 return 0; 380 case kWFullHD: 381 width = 1920; 382 height = 1080; 383 return 0; 384 default: 385 return -1; 386 } 387 } 388 389 FrameDropper::FrameDropper() 390 : 391 _dropsBetweenRenders(0), 392 _frameCounter(0) 393 { 394 } 395 396 bool 397 FrameDropper::DropFrame() 398 { 399 _frameCounter++; 400 if (_frameCounter > _dropsBetweenRenders) 401 { 402 _frameCounter = 0; 403 return false; 404 } 405 return true; 406 } 407 408 unsigned int 409 FrameDropper::DropsBetweenRenders() 410 { 411 return _dropsBetweenRenders; 412 } 413 414 void 415 FrameDropper::SetFrameRate(double frameRate, double maxFrameRate) 416 { 417 if (frameRate >= 1.0) 418 { 419 _dropsBetweenRenders = static_cast<unsigned int>(maxFrameRate / frameRate + 0.5) - 1; 420 } 421 else 422 { 423 _dropsBetweenRenders = 0; 424 } 425 } 426