1 /*
2 * Copyright (c) 2013 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
11 #include "webrtc/test/frame_generator_capturer.h"
12
13 #include "webrtc/base/criticalsection.h"
14 #include "webrtc/base/platform_thread.h"
15 #include "webrtc/system_wrappers/include/clock.h"
16 #include "webrtc/system_wrappers/include/event_wrapper.h"
17 #include "webrtc/system_wrappers/include/sleep.h"
18 #include "webrtc/test/frame_generator.h"
19 #include "webrtc/video_send_stream.h"
20
21 namespace webrtc {
22 namespace test {
23
Create(VideoCaptureInput * input,size_t width,size_t height,int target_fps,Clock * clock)24 FrameGeneratorCapturer* FrameGeneratorCapturer::Create(VideoCaptureInput* input,
25 size_t width,
26 size_t height,
27 int target_fps,
28 Clock* clock) {
29 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
30 clock, input, FrameGenerator::CreateChromaGenerator(width, height),
31 target_fps);
32 if (!capturer->Init()) {
33 delete capturer;
34 return NULL;
35 }
36
37 return capturer;
38 }
39
CreateFromYuvFile(VideoCaptureInput * input,const std::string & file_name,size_t width,size_t height,int target_fps,Clock * clock)40 FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile(
41 VideoCaptureInput* input,
42 const std::string& file_name,
43 size_t width,
44 size_t height,
45 int target_fps,
46 Clock* clock) {
47 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer(
48 clock, input,
49 FrameGenerator::CreateFromYuvFile(std::vector<std::string>(1, file_name),
50 width, height, 1),
51 target_fps);
52 if (!capturer->Init()) {
53 delete capturer;
54 return NULL;
55 }
56
57 return capturer;
58 }
59
FrameGeneratorCapturer(Clock * clock,VideoCaptureInput * input,FrameGenerator * frame_generator,int target_fps)60 FrameGeneratorCapturer::FrameGeneratorCapturer(Clock* clock,
61 VideoCaptureInput* input,
62 FrameGenerator* frame_generator,
63 int target_fps)
64 : VideoCapturer(input),
65 clock_(clock),
66 sending_(false),
67 tick_(EventTimerWrapper::Create()),
68 thread_(FrameGeneratorCapturer::Run, this, "FrameGeneratorCapturer"),
69 frame_generator_(frame_generator),
70 target_fps_(target_fps),
71 first_frame_capture_time_(-1) {
72 assert(input != NULL);
73 assert(frame_generator != NULL);
74 assert(target_fps > 0);
75 }
76
~FrameGeneratorCapturer()77 FrameGeneratorCapturer::~FrameGeneratorCapturer() {
78 Stop();
79
80 thread_.Stop();
81 }
82
Init()83 bool FrameGeneratorCapturer::Init() {
84 // This check is added because frame_generator_ might be file based and should
85 // not crash because a file moved.
86 if (frame_generator_.get() == NULL)
87 return false;
88
89 if (!tick_->StartTimer(true, 1000 / target_fps_))
90 return false;
91 thread_.Start();
92 thread_.SetPriority(rtc::kHighPriority);
93 return true;
94 }
95
Run(void * obj)96 bool FrameGeneratorCapturer::Run(void* obj) {
97 static_cast<FrameGeneratorCapturer*>(obj)->InsertFrame();
98 return true;
99 }
100
InsertFrame()101 void FrameGeneratorCapturer::InsertFrame() {
102 {
103 rtc::CritScope cs(&lock_);
104 if (sending_) {
105 VideoFrame* frame = frame_generator_->NextFrame();
106 frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds());
107 if (first_frame_capture_time_ == -1) {
108 first_frame_capture_time_ = frame->ntp_time_ms();
109 }
110 input_->IncomingCapturedFrame(*frame);
111 }
112 }
113 tick_->Wait(WEBRTC_EVENT_INFINITE);
114 }
115
Start()116 void FrameGeneratorCapturer::Start() {
117 rtc::CritScope cs(&lock_);
118 sending_ = true;
119 }
120
Stop()121 void FrameGeneratorCapturer::Stop() {
122 rtc::CritScope cs(&lock_);
123 sending_ = false;
124 }
125
ForceFrame()126 void FrameGeneratorCapturer::ForceFrame() {
127 tick_->Set();
128 }
129 } // test
130 } // webrtc
131