blob: 4f2db75498bad3b98158eb12e8de0695bb7ec033 [file] [log] [blame]
/*
* Copyright (c) 2012 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 "webrtc/video_engine/test/libvietest/include/vie_file_capture_device.h"
#include <assert.h>
#include "webrtc/common_types.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
#include "webrtc/system_wrappers/interface/event_wrapper.h"
#include "webrtc/system_wrappers/interface/tick_util.h"
#include "webrtc/video_engine/include/vie_capture.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_ = 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);
size_t read = fread(frame_buffer, 1, frame_length_, input_file_);
if (feof(input_file_) || read != frame_length_) {
rewind(input_file_);
}
webrtc::I420VideoFrame frame;
frame.CreateFrame(frame_buffer, width_, height_, webrtc::kVideoRotation_0);
frame.set_render_time_ms(webrtc::TickTime::MillisecondTimestamp());
input_sink_->IncomingFrame(frame);
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);
fclose(input_file_);
}