Home | History | Annotate | Download | only in helpers
      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