1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/test/libvietest/include/vie_file_capture_device.h"
11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <assert.h>
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
14281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/common_types.h"
15281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/interface/module_common_types.h"
16281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h"
18281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
19281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/include/vie_capture.h"
20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// This class ensures we are not exceeding the max FPS.
22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass FramePacemaker {
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  explicit FramePacemaker(uint32_t max_fps)
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      : time_per_frame_ms_(1000 / max_fps) {
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    frame_start_ = webrtc::TickTime::MillisecondTimestamp();
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void SleepIfNecessary(webrtc::EventWrapper* sleeper) {
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    uint64_t now = webrtc::TickTime::MillisecondTimestamp();
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (now - frame_start_ < time_per_frame_ms_) {
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      sleeper->Wait(time_per_frame_ms_ - (now - frame_start_));
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint64_t frame_start_;
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint64_t time_per_frame_ms_;
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEFileCaptureDevice::ViEFileCaptureDevice(
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    webrtc::ViEExternalCapture* input_sink)
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    : input_sink_(input_sink),
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      input_file_(NULL) {
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  mutex_ = webrtc::CriticalSectionWrapper::CreateCriticalSection();
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEFileCaptureDevice::~ViEFileCaptureDevice() {
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete mutex_;
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ViEFileCaptureDevice::OpenI420File(const std::string& path,
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        int width,
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                        int height) {
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::CriticalSectionScoped cs(mutex_);
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(input_file_ == NULL);
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
583f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org  input_file_ = fopen(path.c_str(), "rb");
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (input_file_ == NULL) {
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  frame_length_ = 3 * width * height / 2;
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  width_  = width;
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  height_ = height;
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return true;
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEFileCaptureDevice::ReadFileFor(uint64_t time_slice_ms,
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                       uint32_t max_fps) {
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::CriticalSectionScoped cs(mutex_);
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(input_file_ != NULL);
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  unsigned char* frame_buffer = new unsigned char[frame_length_];
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::EventWrapper* sleeper = webrtc::EventWrapper::Create();
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint64_t start_time_ms = webrtc::TickTime::MillisecondTimestamp();
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  uint64_t elapsed_ms = 0;
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  while (elapsed_ms < time_slice_ms) {
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    FramePacemaker pacemaker(max_fps);
833f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org    int read = fread(frame_buffer, 1, frame_length_, input_file_);
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
853f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org    if (feof(input_file_)) {
863f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org      rewind(input_file_);
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    input_sink_->IncomingFrame(frame_buffer, read, width_, height_,
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               webrtc::kVideoI420,
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               webrtc::TickTime::MillisecondTimestamp());
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    pacemaker.SleepIfNecessary(sleeper);
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    elapsed_ms = webrtc::TickTime::MillisecondTimestamp() - start_time_ms;
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete sleeper;
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete[] frame_buffer;
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEFileCaptureDevice::CloseFile() {
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::CriticalSectionScoped cs(mutex_);
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(input_file_ != NULL);
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1043f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org  fclose(input_file_);
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
106