Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: webrtc/common_video/incoming_video_stream.cc

Issue 1419673014: Remove frame time scheduing in IncomingVideoStream (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Totally disable the functionality Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/common_video/interface/incoming_video_stream.h" 11 #include "webrtc/common_video/interface/incoming_video_stream.h"
12 12
13 #include <assert.h> 13 #include <assert.h>
14 14
15 #if defined(_WIN32) 15 #if defined(_WIN32)
16 #include <windows.h> 16 #include <windows.h>
17 #elif defined(WEBRTC_LINUX) 17 #elif defined(WEBRTC_LINUX)
18 #include <sys/time.h> 18 #include <sys/time.h>
19 #include <time.h> 19 #include <time.h>
20 #else 20 #else
21 #include <sys/time.h> 21 #include <sys/time.h>
22 #endif 22 #endif
23 23
24 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 24 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
25 #include "webrtc/common_video/video_render_frames.h"
26 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 25 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
27 #include "webrtc/system_wrappers/include/event_wrapper.h" 26 #include "webrtc/system_wrappers/include/event_wrapper.h"
28 #include "webrtc/system_wrappers/include/thread_wrapper.h" 27 #include "webrtc/system_wrappers/include/thread_wrapper.h"
29 #include "webrtc/system_wrappers/include/tick_util.h" 28 #include "webrtc/system_wrappers/include/tick_util.h"
30 #include "webrtc/system_wrappers/include/trace.h" 29 #include "webrtc/system_wrappers/include/trace.h"
31 30
32 namespace webrtc { 31 namespace webrtc {
33 32
34 IncomingVideoStream::IncomingVideoStream(uint32_t stream_id) 33 IncomingVideoStream::IncomingVideoStream(uint32_t stream_id)
35 : stream_id_(stream_id), 34 : stream_id_(stream_id),
36 stream_critsect_(CriticalSectionWrapper::CreateCriticalSection()), 35 stream_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
37 thread_critsect_(CriticalSectionWrapper::CreateCriticalSection()), 36 thread_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
38 buffer_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
39 incoming_render_thread_(),
40 deliver_buffer_event_(EventTimerWrapper::Create()),
41 running_(false), 37 running_(false),
42 external_callback_(nullptr), 38 external_callback_(nullptr),
43 render_callback_(nullptr), 39 render_callback_(nullptr),
44 render_buffers_(new VideoRenderFrames()),
45 incoming_rate_(0), 40 incoming_rate_(0),
46 last_rate_calculation_time_ms_(0), 41 last_rate_calculation_time_ms_(0),
47 num_frames_since_last_calculation_(0), 42 num_frames_since_last_calculation_(0),
48 last_render_time_ms_(0), 43 last_render_time_ms_(0),
49 temp_frame_(), 44 temp_frame_(),
50 start_image_(), 45 start_image_(),
51 timeout_image_(), 46 timeout_image_(),
52 timeout_time_() { 47 timeout_time_() {
53 } 48 }
54 49
55 IncomingVideoStream::~IncomingVideoStream() { 50 IncomingVideoStream::~IncomingVideoStream() {
56 Stop(); 51 Stop();
57 } 52 }
58 53
59 VideoRenderCallback* IncomingVideoStream::ModuleCallback() { 54 VideoRenderCallback* IncomingVideoStream::ModuleCallback() {
60 CriticalSectionScoped cs(stream_critsect_.get()); 55 CriticalSectionScoped cs(stream_critsect_.get());
61 return this; 56 return this;
62 } 57 }
63 58
64 int32_t IncomingVideoStream::RenderFrame(const uint32_t stream_id, 59 int32_t IncomingVideoStream::RenderFrame(const uint32_t stream_id,
65 const VideoFrame& video_frame) { 60 const VideoFrame& video_frame) {
66 CriticalSectionScoped csS(stream_critsect_.get()); 61 CriticalSectionScoped csS(stream_critsect_.get());
67
68 if (!running_) { 62 if (!running_) {
69 return -1; 63 return -1;
70 } 64 }
71 65
72 // Rate statistics. 66 // Rate statistics.
73 num_frames_since_last_calculation_++; 67 num_frames_since_last_calculation_++;
74 int64_t now_ms = TickTime::MillisecondTimestamp(); 68 int64_t now_ms = TickTime::MillisecondTimestamp();
75 if (now_ms >= last_rate_calculation_time_ms_ + kFrameRatePeriodMs) { 69 if (now_ms >= last_rate_calculation_time_ms_ + kFrameRatePeriodMs) {
76 incoming_rate_ = 70 incoming_rate_ =
77 static_cast<uint32_t>(1000 * num_frames_since_last_calculation_ / 71 static_cast<uint32_t>(1000 * num_frames_since_last_calculation_ /
78 (now_ms - last_rate_calculation_time_ms_)); 72 (now_ms - last_rate_calculation_time_ms_));
79 num_frames_since_last_calculation_ = 0; 73 num_frames_since_last_calculation_ = 0;
80 last_rate_calculation_time_ms_ = now_ms; 74 last_rate_calculation_time_ms_ = now_ms;
81 } 75 }
82 76
83 // Insert frame. 77 CriticalSectionScoped cs(thread_critsect_.get());
84 CriticalSectionScoped csB(buffer_critsect_.get()); 78 if (video_frame.IsZeroSize()) {
85 if (render_buffers_->AddFrame(video_frame) == 1) 79 if (render_callback_) {
86 deliver_buffer_event_->Set(); 80 if (last_render_time_ms_ == 0 && !start_image_.IsZeroSize()) {
81 // We have not rendered anything and have a start image.
82 temp_frame_.CopyFrame(start_image_);
83 render_callback_->RenderFrame(stream_id_, temp_frame_);
84 } else if (!timeout_image_.IsZeroSize() &&
85 last_render_time_ms_ + timeout_time_ <
86 TickTime::MillisecondTimestamp()) {
87 // Render a timeout image.
88 temp_frame_.CopyFrame(timeout_image_);
89 render_callback_->RenderFrame(stream_id_, temp_frame_);
90 }
91 }
92
93 // No frame.
94 return 0;
95 }
96
97 // Send frame for rendering.
98 if (external_callback_) {
99 external_callback_->RenderFrame(stream_id_, video_frame);
100 } else if (render_callback_) {
101 render_callback_->RenderFrame(stream_id_, video_frame);
102 }
103 last_render_time_ms_ = video_frame.render_time_ms();
87 104
88 return 0; 105 return 0;
89 } 106 }
90 107
91 int32_t IncomingVideoStream::SetStartImage(const VideoFrame& video_frame) { 108 int32_t IncomingVideoStream::SetStartImage(const VideoFrame& video_frame) {
92 CriticalSectionScoped csS(thread_critsect_.get()); 109 CriticalSectionScoped csS(thread_critsect_.get());
93 return start_image_.CopyFrame(video_frame); 110 return start_image_.CopyFrame(video_frame);
94 } 111 }
95 112
96 int32_t IncomingVideoStream::SetTimeoutImage(const VideoFrame& video_frame, 113 int32_t IncomingVideoStream::SetTimeoutImage(const VideoFrame& video_frame,
97 const uint32_t timeout) { 114 const uint32_t timeout) {
98 CriticalSectionScoped csS(thread_critsect_.get()); 115 CriticalSectionScoped csS(thread_critsect_.get());
99 timeout_time_ = timeout; 116 timeout_time_ = timeout;
100 return timeout_image_.CopyFrame(video_frame); 117 return timeout_image_.CopyFrame(video_frame);
101 } 118 }
102 119
103 void IncomingVideoStream::SetRenderCallback( 120 void IncomingVideoStream::SetRenderCallback(
104 VideoRenderCallback* render_callback) { 121 VideoRenderCallback* render_callback) {
105 CriticalSectionScoped cs(thread_critsect_.get()); 122 CriticalSectionScoped cs(thread_critsect_.get());
106 render_callback_ = render_callback; 123 render_callback_ = render_callback;
107 } 124 }
108 125
109 int32_t IncomingVideoStream::SetExpectedRenderDelay( 126 int32_t IncomingVideoStream::SetExpectedRenderDelay(
110 int32_t delay_ms) { 127 int32_t delay_ms) {
111 CriticalSectionScoped csS(stream_critsect_.get()); 128 CriticalSectionScoped csS(stream_critsect_.get());
112 if (running_) { 129 if (running_) {
113 return -1; 130 return -1;
114 } 131 }
115 CriticalSectionScoped cs(buffer_critsect_.get()); 132 return 0;
116 return render_buffers_->SetRenderDelay(delay_ms);
117 } 133 }
118 134
119 void IncomingVideoStream::SetExternalCallback( 135 void IncomingVideoStream::SetExternalCallback(
120 VideoRenderCallback* external_callback) { 136 VideoRenderCallback* external_callback) {
121 CriticalSectionScoped cs(thread_critsect_.get()); 137 CriticalSectionScoped cs(thread_critsect_.get());
122 external_callback_ = external_callback; 138 external_callback_ = external_callback;
123 } 139 }
124 140
125 int32_t IncomingVideoStream::Start() { 141 int32_t IncomingVideoStream::Start() {
126 CriticalSectionScoped csS(stream_critsect_.get()); 142 CriticalSectionScoped csS(stream_critsect_.get());
127 if (running_) {
128 return 0;
129 }
130
131 CriticalSectionScoped csT(thread_critsect_.get());
132 assert(incoming_render_thread_ == NULL);
133
134 incoming_render_thread_ = ThreadWrapper::CreateThread(
135 IncomingVideoStreamThreadFun, this, "IncomingVideoStreamThread");
136 if (!incoming_render_thread_) {
137 return -1;
138 }
139
140 if (incoming_render_thread_->Start()) {
141 } else {
142 return -1;
143 }
144 incoming_render_thread_->SetPriority(kRealtimePriority);
145 deliver_buffer_event_->StartTimer(false, kEventStartupTimeMs);
146
147 running_ = true; 143 running_ = true;
148 return 0; 144 return 0;
149 } 145 }
150 146
151 int32_t IncomingVideoStream::Stop() { 147 int32_t IncomingVideoStream::Stop() {
152 CriticalSectionScoped cs_stream(stream_critsect_.get()); 148 CriticalSectionScoped cs_stream(stream_critsect_.get());
153
154 if (!running_) {
155 return 0;
156 }
157
158 ThreadWrapper* thread = NULL;
159 {
160 CriticalSectionScoped cs_thread(thread_critsect_.get());
161 if (incoming_render_thread_) {
162 // Setting the incoming render thread to NULL marks that we're performing
163 // a shutdown and will make IncomingVideoStreamProcess abort after wakeup.
164 thread = incoming_render_thread_.release();
165 deliver_buffer_event_->StopTimer();
166 // Set the event to allow the thread to wake up and shut down without
167 // waiting for a timeout.
168 deliver_buffer_event_->Set();
169 }
170 }
171 if (thread) {
172 if (thread->Stop()) {
173 delete thread;
174 } else {
175 assert(false);
176 }
177 }
178 running_ = false; 149 running_ = false;
179 return 0; 150 return 0;
180 } 151 }
181 152
182 int32_t IncomingVideoStream::Reset() { 153 int32_t IncomingVideoStream::Reset() {
183 CriticalSectionScoped cs_buffer(buffer_critsect_.get());
184 render_buffers_->ReleaseAllFrames();
185 return 0; 154 return 0;
186 } 155 }
187 156
188 uint32_t IncomingVideoStream::StreamId() const { 157 uint32_t IncomingVideoStream::StreamId() const {
189 return stream_id_; 158 return stream_id_;
190 } 159 }
191 160
192 uint32_t IncomingVideoStream::IncomingRate() const { 161 uint32_t IncomingVideoStream::IncomingRate() const {
193 CriticalSectionScoped cs(stream_critsect_.get()); 162 CriticalSectionScoped cs(stream_critsect_.get());
194 return incoming_rate_; 163 return incoming_rate_;
195 } 164 }
196 165
197 bool IncomingVideoStream::IncomingVideoStreamThreadFun(void* obj) {
198 return static_cast<IncomingVideoStream*>(obj)->IncomingVideoStreamProcess();
199 }
200
201 bool IncomingVideoStream::IncomingVideoStreamProcess() {
202 if (kEventError != deliver_buffer_event_->Wait(kEventMaxWaitTimeMs)) {
203 CriticalSectionScoped cs(thread_critsect_.get());
204 if (incoming_render_thread_ == NULL) {
205 // Terminating
206 return false;
207 }
208 // Get a new frame to render and the time for the frame after this one.
209 VideoFrame frame_to_render;
210 uint32_t wait_time;
211 {
212 CriticalSectionScoped cs(buffer_critsect_.get());
213 frame_to_render = render_buffers_->FrameToRender();
214 wait_time = render_buffers_->TimeToNextFrameRelease();
215 }
216
217 // Set timer for next frame to render.
218 if (wait_time > kEventMaxWaitTimeMs) {
219 wait_time = kEventMaxWaitTimeMs;
220 }
221 deliver_buffer_event_->StartTimer(false, wait_time);
222
223 if (frame_to_render.IsZeroSize()) {
224 if (render_callback_) {
225 if (last_render_time_ms_ == 0 && !start_image_.IsZeroSize()) {
226 // We have not rendered anything and have a start image.
227 temp_frame_.CopyFrame(start_image_);
228 render_callback_->RenderFrame(stream_id_, temp_frame_);
229 } else if (!timeout_image_.IsZeroSize() &&
230 last_render_time_ms_ + timeout_time_ <
231 TickTime::MillisecondTimestamp()) {
232 // Render a timeout image.
233 temp_frame_.CopyFrame(timeout_image_);
234 render_callback_->RenderFrame(stream_id_, temp_frame_);
235 }
236 }
237
238 // No frame.
239 return true;
240 }
241
242 // Send frame for rendering.
243 if (external_callback_) {
244 external_callback_->RenderFrame(stream_id_, frame_to_render);
245 } else if (render_callback_) {
246 render_callback_->RenderFrame(stream_id_, frame_to_render);
247 }
248
249 // We're done with this frame.
250 if (!frame_to_render.IsZeroSize())
251 last_render_time_ms_ = frame_to_render.render_time_ms();
252 }
253 return true;
254 }
255
256 } // namespace webrtc 166 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698