/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "video_source.h" #include "vplib.h" #include #include VideoSource::VideoSource() : _fileName("../../../../testFiles/foreman.yuv"), _width(352), _height(288), _type(webrtc::kI420), _frameRate(30) { } VideoSource::VideoSource(std::string fileName, VideoSize size, int frameRate /*= 30*/, webrtc::VideoType type /*= webrtc::kI420*/) : _fileName(fileName), _type(type), _frameRate(frameRate) { assert(size != kUndefined && size != kNumberOfVideoSizes); assert(type != webrtc::kUnknown); assert(frameRate > 0); assert(GetWidthHeight(size, _width, _height) == 0); } VideoSource::VideoSource(std::string fileName, int width, int height, int frameRate /*= 30*/, webrtc::VideoType type /*= webrtc::kI420*/) : _fileName(fileName), _width(width), _height(height), _type(type), _frameRate(frameRate) { assert(width > 0); assert(height > 0); assert(type != webrtc::kUnknown); assert(frameRate > 0); } VideoSize VideoSource::GetSize() const { return GetSize(_width, _height); } VideoSize VideoSource::GetSize(WebRtc_UWord16 width, WebRtc_UWord16 height) { if(width == 128 && height == 96) { return kSQCIF; }else if(width == 160 && height == 120) { return kQQVGA; }else if(width == 176 && height == 144) { return kQCIF; }else if(width == 320 && height == 240) { return kQVGA; }else if(width == 352 && height == 288) { return kCIF; }else if(width == 640 && height == 480) { return kVGA; }else if(width == 720 && height == 480) { return kNTSC; }else if(width == 704 && height == 576) { return k4CIF; }else if(width == 800 && height == 600) { return kSVGA; }else if(width == 960 && height == 720) { return kHD; }else if(width == 1024 && height == 768) { return kXGA; }else if(width == 1440 && height == 1080) { return kFullHD; }else if(width == 400 && height == 240) { return kWQVGA; }else if(width == 800 && height == 480) { return kWVGA; }else if(width == 1280 && height == 720) { return kWHD; }else if(width == 1920 && height == 1080) { return kWFullHD; } return kUndefined; } unsigned int VideoSource::GetFrameLength() const { return webrtc::CalcBufferSize(_type, _width, _height); } const char* VideoSource::GetMySizeString() const { return VideoSource::GetSizeString(GetSize()); } const char* VideoSource::GetSizeString(VideoSize size) { switch (size) { case kSQCIF: return "SQCIF"; case kQQVGA: return "QQVGA"; case kQCIF: return "QCIF"; case kQVGA: return "QVGA"; case kCIF: return "CIF"; case kVGA: return "VGA"; case kNTSC: return "NTSC"; case k4CIF: return "4CIF"; case kSVGA: return "SVGA"; case kHD: return "HD"; case kXGA: return "XGA"; case kFullHD: return "Full_HD"; case kWQVGA: return "WQVGA"; case kWHD: return "WHD"; case kWFullHD: return "WFull_HD"; default: return "Undefined"; } } std::string VideoSource::GetFilePath() const { size_t slashPos = _fileName.find_last_of("/\\"); if (slashPos == std::string::npos) { return "."; } return _fileName.substr(0, slashPos); } std::string VideoSource::GetName() const { // Remove path. size_t slashPos = _fileName.find_last_of("/\\"); if (slashPos == std::string::npos) { slashPos = 0; } else { slashPos++; } // Remove extension and underscored suffix if it exists. return _fileName.substr(slashPos, std::min(_fileName.find_last_of("_"), _fileName.find_last_of(".")) - slashPos); } void VideoSource::Convert(const VideoSource &target, bool force /* = false */) const { // Ensure target rate is less than or equal to source // (i.e. we are only temporally downsampling). assert(target.GetFrameRate() <= _frameRate); // Only supports YUV420 currently. assert(_type == webrtc::kI420 && target.GetType() == webrtc::kI420); if (!force && (FileExists(target.GetFileName().c_str()) || (target.GetWidth() == _width && target.GetHeight() == _height && target.GetFrameRate() == _frameRate))) { // Assume that the filename uniquely defines the content. // If the file already exists, it is the correct file. return; } FILE *inFile = NULL; FILE *outFile = NULL; inFile = fopen(_fileName.c_str(), "rb"); assert(inFile != NULL); outFile = fopen(target.GetFileName().c_str(), "wb"); assert(outFile != NULL); FrameDropper fd; fd.SetFrameRate(target.GetFrameRate(), _frameRate); const size_t lengthOutFrame = webrtc::CalcBufferSize(target.GetType(), target.GetWidth(), target.GetHeight()); assert(lengthOutFrame > 0); unsigned char *outFrame = new unsigned char[lengthOutFrame]; const size_t lengthInFrame = webrtc::CalcBufferSize(_type, _width, _height); assert(lengthInFrame > 0); unsigned char *inFrame = new unsigned char[lengthInFrame]; while (fread(inFrame, 1, lengthInFrame, inFile) == lengthInFrame) { if (!fd.DropFrame()) { assert(target.GetWidth() == _width && target.GetHeight() == _height); // Add video interpolator here! fwrite(outFrame, 1, lengthOutFrame, outFile); } } delete inFrame; delete outFrame; fclose(inFile); fclose(outFile); } bool VideoSource::FileExists(const char* fileName) { FILE* fp = NULL; fp = fopen(fileName, "rb"); if(fp != NULL) { fclose(fp); return true; } return false; } int VideoSource::GetWidthHeight( VideoSize size, int & width, int& height) { switch(size) { case kSQCIF: width = 128; height = 96; return 0; case kQQVGA: width = 160; height = 120; return 0; case kQCIF: width = 176; height = 144; return 0; case kCGA: width = 320; height = 200; return 0; case kQVGA: width = 320; height = 240; return 0; case kSIF: width = 352; height = 240; return 0; case kWQVGA: width = 400; height = 240; return 0; case kCIF: width = 352; height = 288; return 0; case kW288p: width = 512; height = 288; return 0; case k448p: width = 576; height = 448; return 0; case kVGA: width = 640; height = 480; return 0; case k432p: width = 720; height = 432; return 0; case kW432p: width = 768; height = 432; return 0; case k4SIF: width = 704; height = 480; return 0; case kW448p: width = 768; height = 448; return 0; case kNTSC: width = 720; height = 480; return 0; case kFW448p: width = 800; height = 448; return 0; case kWVGA: width = 800; height = 480; return 0; case k4CIF: width = 704; height = 576; return 0; case kSVGA: width = 800; height = 600; return 0; case kW544p: width = 960; height = 544; return 0; case kW576p: width = 1024; height = 576; return 0; case kHD: width = 960; height = 720; return 0; case kXGA: width = 1024; height = 768; return 0; case kFullHD: width = 1440; height = 1080; return 0; case kWHD: width = 1280; height = 720; return 0; case kWFullHD: width = 1920; height = 1080; return 0; default: return -1; } } FrameDropper::FrameDropper() : _dropsBetweenRenders(0), _frameCounter(0) { } bool FrameDropper::DropFrame() { _frameCounter++; if (_frameCounter > _dropsBetweenRenders) { _frameCounter = 0; return false; } return true; } unsigned int FrameDropper::DropsBetweenRenders() { return _dropsBetweenRenders; } void FrameDropper::SetFrameRate(double frameRate, double maxFrameRate) { if (frameRate >= 1.0) { _dropsBetweenRenders = static_cast(maxFrameRate / frameRate + 0.5) - 1; } else { _dropsBetweenRenders = 0; } }