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/test/frame_generator.h" 14 #include "webrtc/system_wrappers/interface/clock.h" 15 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 16 #include "webrtc/system_wrappers/interface/event_wrapper.h" 17 #include "webrtc/system_wrappers/interface/sleep.h" 18 #include "webrtc/system_wrappers/interface/thread_wrapper.h" 19 #include "webrtc/video_send_stream.h" 20 21 namespace webrtc { 22 namespace test { 23 24 FrameGeneratorCapturer* FrameGeneratorCapturer::Create( 25 VideoSendStreamInput* input, 26 size_t width, 27 size_t height, 28 int target_fps, 29 Clock* clock) { 30 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( 31 clock, input, FrameGenerator::Create(width, height), target_fps); 32 if (!capturer->Init()) { 33 delete capturer; 34 return NULL; 35 } 36 37 return capturer; 38 } 39 40 FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile( 41 VideoSendStreamInput* input, 42 const char* file_name, 43 size_t width, 44 size_t height, 45 int target_fps, 46 Clock* clock) { 47 FrameGeneratorCapturer* capturer = new FrameGeneratorCapturer( 48 clock, 49 input, 50 FrameGenerator::CreateFromYuvFile(file_name, width, height), 51 target_fps); 52 if (!capturer->Init()) { 53 delete capturer; 54 return NULL; 55 } 56 57 return capturer; 58 } 59 60 FrameGeneratorCapturer::FrameGeneratorCapturer(Clock* clock, 61 VideoSendStreamInput* input, 62 FrameGenerator* frame_generator, 63 int target_fps) 64 : VideoCapturer(input), 65 clock_(clock), 66 sending_(false), 67 tick_(EventWrapper::Create()), 68 lock_(CriticalSectionWrapper::CreateCriticalSection()), 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 77 FrameGeneratorCapturer::~FrameGeneratorCapturer() { 78 Stop(); 79 80 if (thread_.get() != NULL) 81 thread_->Stop(); 82 } 83 84 bool FrameGeneratorCapturer::Init() { 85 // This check is added because frame_generator_ might be file based and should 86 // not crash because a file moved. 87 if (frame_generator_.get() == NULL) 88 return false; 89 90 if (!tick_->StartTimer(true, 1000 / target_fps_)) 91 return false; 92 thread_.reset(ThreadWrapper::CreateThread(FrameGeneratorCapturer::Run, 93 this, 94 webrtc::kHighPriority, 95 "FrameGeneratorCapturer")); 96 if (thread_.get() == NULL) 97 return false; 98 unsigned int thread_id; 99 if (!thread_->Start(thread_id)) { 100 thread_.reset(); 101 return false; 102 } 103 return true; 104 } 105 106 bool FrameGeneratorCapturer::Run(void* obj) { 107 static_cast<FrameGeneratorCapturer*>(obj)->InsertFrame(); 108 return true; 109 } 110 111 void FrameGeneratorCapturer::InsertFrame() { 112 { 113 CriticalSectionScoped cs(lock_.get()); 114 if (sending_) { 115 I420VideoFrame* frame = frame_generator_->NextFrame(); 116 frame->set_render_time_ms(clock_->CurrentNtpInMilliseconds()); 117 if (first_frame_capture_time_ == -1) { 118 first_frame_capture_time_ = frame->render_time_ms(); 119 } 120 input_->SwapFrame(frame); 121 } 122 } 123 tick_->Wait(WEBRTC_EVENT_INFINITE); 124 } 125 126 void FrameGeneratorCapturer::Start() { 127 CriticalSectionScoped cs(lock_.get()); 128 sending_ = true; 129 } 130 131 void FrameGeneratorCapturer::Stop() { 132 CriticalSectionScoped cs(lock_.get()); 133 sending_ = false; 134 } 135 } // test 136 } // webrtc 137