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 #include "webrtc/video_engine/test/libvietest/include/vie_file_capture_device.h" 11 12 #include <assert.h> 13 14 #include "webrtc/common_types.h" 15 #include "webrtc/modules/interface/module_common_types.h" 16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 17 #include "webrtc/system_wrappers/interface/event_wrapper.h" 18 #include "webrtc/system_wrappers/interface/tick_util.h" 19 #include "webrtc/video_engine/include/vie_capture.h" 20 21 // This class ensures we are not exceeding the max FPS. 22 class FramePacemaker { 23 public: 24 explicit FramePacemaker(uint32_t max_fps) 25 : time_per_frame_ms_(1000 / max_fps) { 26 frame_start_ = webrtc::TickTime::MillisecondTimestamp(); 27 } 28 29 void SleepIfNecessary(webrtc::EventWrapper* sleeper) { 30 uint64_t now = webrtc::TickTime::MillisecondTimestamp(); 31 if (now - frame_start_ < time_per_frame_ms_) { 32 sleeper->Wait(time_per_frame_ms_ - (now - frame_start_)); 33 } 34 } 35 36 private: 37 uint64_t frame_start_; 38 uint64_t time_per_frame_ms_; 39 }; 40 41 ViEFileCaptureDevice::ViEFileCaptureDevice( 42 webrtc::ViEExternalCapture* input_sink) 43 : input_sink_(input_sink), 44 input_file_(NULL) { 45 mutex_ = webrtc::CriticalSectionWrapper::CreateCriticalSection(); 46 } 47 48 ViEFileCaptureDevice::~ViEFileCaptureDevice() { 49 delete mutex_; 50 } 51 52 bool ViEFileCaptureDevice::OpenI420File(const std::string& path, 53 int width, 54 int height) { 55 webrtc::CriticalSectionScoped cs(mutex_); 56 assert(input_file_ == NULL); 57 58 input_file_ = fopen(path.c_str(), "rb"); 59 if (input_file_ == NULL) { 60 return false; 61 } 62 63 frame_length_ = 3 * width * height / 2; 64 width_ = width; 65 height_ = height; 66 return true; 67 } 68 69 void ViEFileCaptureDevice::ReadFileFor(uint64_t time_slice_ms, 70 uint32_t max_fps) { 71 webrtc::CriticalSectionScoped cs(mutex_); 72 assert(input_file_ != NULL); 73 74 unsigned char* frame_buffer = new unsigned char[frame_length_]; 75 76 webrtc::EventWrapper* sleeper = webrtc::EventWrapper::Create(); 77 78 uint64_t start_time_ms = webrtc::TickTime::MillisecondTimestamp(); 79 uint64_t elapsed_ms = 0; 80 81 while (elapsed_ms < time_slice_ms) { 82 FramePacemaker pacemaker(max_fps); 83 int read = fread(frame_buffer, 1, frame_length_, input_file_); 84 85 if (feof(input_file_)) { 86 rewind(input_file_); 87 } 88 input_sink_->IncomingFrame(frame_buffer, read, width_, height_, 89 webrtc::kVideoI420, 90 webrtc::TickTime::MillisecondTimestamp()); 91 92 pacemaker.SleepIfNecessary(sleeper); 93 elapsed_ms = webrtc::TickTime::MillisecondTimestamp() - start_time_ms; 94 } 95 96 delete sleeper; 97 delete[] frame_buffer; 98 } 99 100 void ViEFileCaptureDevice::CloseFile() { 101 webrtc::CriticalSectionScoped cs(mutex_); 102 assert(input_file_ != NULL); 103 104 fclose(input_file_); 105 } 106