1c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org/*
2c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *
4c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *  Use of this source code is governed by a BSD-style license
5c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *  that can be found in the LICENSE file in the root of the source
6c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *  tree. An additional intellectual property rights grant can be found
7c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *  in the file PATENTS.  All contributing project authors may
8c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org */
10c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
1124e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/test/frame_generator_capturer.h"
12c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
13c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org#include "webrtc/test/frame_generator.h"
1428631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org#include "webrtc/system_wrappers/interface/clock.h"
15c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
162f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h"
17c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org#include "webrtc/system_wrappers/interface/sleep.h"
18c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h"
1924e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/video_send_stream.h"
20c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
21c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgnamespace webrtc {
22c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgnamespace test {
23c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
24c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgFrameGeneratorCapturer* FrameGeneratorCapturer::Create(
25c1797061756f40b9b1f3f3e82fc040ce18ecd43cpbos@webrtc.org    VideoSendStreamInput* input,
2628631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    size_t width,
2728631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    size_t height,
2828631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    int target_fps,
2928631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    Clock* clock) {
3028631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org  FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
31e2c52d725d7af76fc84e6bd1443c4bd7632c7331pbos@webrtc.org      clock, input, FrameGenerator::Create(width, height), target_fps);
32c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  if (!capturer->Init()) {
33c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org    delete capturer;
34c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org    return NULL;
35c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  }
36c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
37c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  return capturer;
38c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
39c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
4028631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.orgFrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile(
41c1797061756f40b9b1f3f3e82fc040ce18ecd43cpbos@webrtc.org    VideoSendStreamInput* input,
4228631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    const char* file_name,
4328631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    size_t width,
4428631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    size_t height,
4528631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    int target_fps,
4628631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    Clock* clock) {
4728631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org  FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
4828631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org      clock,
4928631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org      input,
5028631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org      FrameGenerator::CreateFromYuvFile(file_name, width, height),
5128631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org      target_fps);
5228631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org  if (!capturer->Init()) {
5328631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    delete capturer;
5428631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    return NULL;
5528631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org  }
5628631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org
5728631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org  return capturer;
5828631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org}
5928631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org
6028631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.orgFrameGeneratorCapturer::FrameGeneratorCapturer(Clock* clock,
6128631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org                                               VideoSendStreamInput* input,
6228631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org                                               FrameGenerator* frame_generator,
6328631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org                                               int target_fps)
64c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org    : VideoCapturer(input),
6528631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org      clock_(clock),
66c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org      sending_(false),
672f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org      tick_(EventWrapper::Create()),
68c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org      lock_(CriticalSectionWrapper::CreateCriticalSection()),
69c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org      frame_generator_(frame_generator),
70093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org      target_fps_(target_fps),
71093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org      first_frame_capture_time_(-1) {
72c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  assert(input != NULL);
73c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  assert(frame_generator != NULL);
74c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  assert(target_fps > 0);
75c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
76c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
77c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgFrameGeneratorCapturer::~FrameGeneratorCapturer() {
78c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  Stop();
79c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
802f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  if (thread_.get() != NULL)
812f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org    thread_->Stop();
82c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
83c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
84c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgbool FrameGeneratorCapturer::Init() {
85a24c3560787e59d93663a960ee48d36ec86f21d2pbos@webrtc.org  // This check is added because frame_generator_ might be file based and should
86a24c3560787e59d93663a960ee48d36ec86f21d2pbos@webrtc.org  // not crash because a file moved.
87a24c3560787e59d93663a960ee48d36ec86f21d2pbos@webrtc.org  if (frame_generator_.get() == NULL)
88a24c3560787e59d93663a960ee48d36ec86f21d2pbos@webrtc.org    return false;
89a24c3560787e59d93663a960ee48d36ec86f21d2pbos@webrtc.org
902f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  if (!tick_->StartTimer(true, 1000 / target_fps_))
912f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org    return false;
922f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  thread_.reset(ThreadWrapper::CreateThread(FrameGeneratorCapturer::Run,
932f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org                                            this,
942f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org                                            webrtc::kHighPriority,
952f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org                                            "FrameGeneratorCapturer"));
962f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  if (thread_.get() == NULL)
97c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org    return false;
98c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  unsigned int thread_id;
99c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  if (!thread_->Start(thread_id)) {
1002f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org    thread_.reset();
101c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org    return false;
102c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  }
103c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  return true;
104c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
105c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
106c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgbool FrameGeneratorCapturer::Run(void* obj) {
107c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  static_cast<FrameGeneratorCapturer*>(obj)->InsertFrame();
108c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  return true;
109c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
110c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
111c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgvoid FrameGeneratorCapturer::InsertFrame() {
112c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  {
1132f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org    CriticalSectionScoped cs(lock_.get());
11428631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    if (sending_) {
115c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org      I420VideoFrame* frame = frame_generator_->NextFrame();
116c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org      frame->set_render_time_ms(clock_->CurrentNtpInMilliseconds());
117093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org      if (first_frame_capture_time_ == -1) {
118093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org        first_frame_capture_time_ = frame->render_time_ms();
119093fc0b0b0b9ca4fe56a32e17c9c418382e802f0wu@webrtc.org      }
120c33d37ce205e22c0e090b0b285ed963686bf24dcpbos@webrtc.org      input_->SwapFrame(frame);
12128631e76cf7bcb40532069eecfe65f6290c05cd4andresp@webrtc.org    }
122c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  }
1232f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  tick_->Wait(WEBRTC_EVENT_INFINITE);
124c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
125c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
126c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgvoid FrameGeneratorCapturer::Start() {
1272f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  CriticalSectionScoped cs(lock_.get());
128c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  sending_ = true;
129c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
130c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org
131c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.orgvoid FrameGeneratorCapturer::Stop() {
1322f02da89501237cefea455cf31a1553125f62ad7pbos@webrtc.org  CriticalSectionScoped cs(lock_.get());
133c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org  sending_ = false;
134c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}
135c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}  // test
136c1506a215f1376938c91459abeb1cd05201df278pbos@webrtc.org}  // webrtc
137