blob: e4caa2a3003d5d5681b5958f88a7c15f979e9c0e [file] [log] [blame]
/*
* 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 "vie_file_capture_device.h"
#include <assert.h>
#include "common_types.h"
#include "critical_section_wrapper.h"
#include "event_wrapper.h"
#include "module_common_types.h"
#include "vie_autotest_defines.h"
#include "vie_capture.h"
#include "tick_util.h"
// This class ensures we are not exceeding the max FPS.
class FramePacemaker {
public:
explicit FramePacemaker(uint32_t max_fps)
: time_per_frame_ms_(1000 / max_fps) {
frame_start_ = webrtc::TickTime::MillisecondTimestamp();
}
void SleepIfNecessary(webrtc::EventWrapper* sleeper) {
uint64_t now = webrtc::TickTime::MillisecondTimestamp();
if (now - frame_start_ < time_per_frame_ms_) {
sleeper->Wait(time_per_frame_ms_ - (now - frame_start_));
}
}
private:
uint64_t frame_start_;
uint64_t time_per_frame_ms_;
};
ViEFileCaptureDevice::ViEFileCaptureDevice(
webrtc::ViEExternalCapture* input_sink)
: input_sink_(input_sink),
input_file_(NULL) {
mutex_ = webrtc::CriticalSectionWrapper::CreateCriticalSection();
}
ViEFileCaptureDevice::~ViEFileCaptureDevice() {
delete mutex_;
}
bool ViEFileCaptureDevice::OpenI420File(const std::string& path,
int width,
int height) {
webrtc::CriticalSectionScoped cs(*mutex_);
assert(input_file_ == NULL);
input_file_ = std::fopen(path.c_str(), "rb");
if (input_file_ == NULL) {
return false;
}
frame_length_ = 3 * width * height / 2;
width_ = width;
height_ = height;
return true;
}
void ViEFileCaptureDevice::ReadFileFor(uint64_t time_slice_ms,
uint32_t max_fps) {
webrtc::CriticalSectionScoped cs(*mutex_);
assert(input_file_ != NULL);
unsigned char* frame_buffer = new unsigned char[frame_length_];
webrtc::EventWrapper* sleeper = webrtc::EventWrapper::Create();
uint64_t start_time_ms = webrtc::TickTime::MillisecondTimestamp();
uint64_t elapsed_ms = 0;
while (elapsed_ms < time_slice_ms) {
FramePacemaker pacemaker(max_fps);
int read = std::fread(frame_buffer, 1, frame_length_, input_file_);
if (std::feof(input_file_)) {
std::rewind(input_file_);
}
input_sink_->IncomingFrame(frame_buffer, read, width_, height_,
webrtc::kVideoI420,
webrtc::TickTime::MillisecondTimestamp());
pacemaker.SleepIfNecessary(sleeper);
elapsed_ms = webrtc::TickTime::MillisecondTimestamp() - start_time_ms;
}
delete sleeper;
delete[] frame_buffer;
}
void ViEFileCaptureDevice::CloseFile() {
webrtc::CriticalSectionScoped cs(*mutex_);
assert(input_file_ != NULL);
std::fclose(input_file_);
}