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

Side by Side Diff: webrtc/modules/video_coding/main/source/video_sender.cc

Issue 1336023004: Keep lock after updating encoder parameters. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: void -> Set.. Created 5 years, 3 months 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
« no previous file with comments | « webrtc/modules/video_coding/main/source/video_coding_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 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
(...skipping 12 matching lines...) Expand all
23 23
24 namespace webrtc { 24 namespace webrtc {
25 namespace vcm { 25 namespace vcm {
26 26
27 VideoSender::VideoSender(Clock* clock, 27 VideoSender::VideoSender(Clock* clock,
28 EncodedImageCallback* post_encode_callback, 28 EncodedImageCallback* post_encode_callback,
29 VideoEncoderRateObserver* encoder_rate_observer, 29 VideoEncoderRateObserver* encoder_rate_observer,
30 VCMQMSettingsCallback* qm_settings_callback) 30 VCMQMSettingsCallback* qm_settings_callback)
31 : clock_(clock), 31 : clock_(clock),
32 process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), 32 process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
33 _sendCritSect(CriticalSectionWrapper::CreateCriticalSection()),
34 _encoder(nullptr), 33 _encoder(nullptr),
35 _encodedFrameCallback(post_encode_callback), 34 _encodedFrameCallback(post_encode_callback),
36 _nextFrameTypes(1, kVideoFrameDelta), 35 _nextFrameTypes(1, kVideoFrameDelta),
37 _mediaOpt(clock_), 36 _mediaOpt(clock_),
38 _sendStatsCallback(nullptr), 37 _sendStatsCallback(nullptr),
39 _codecDataBase(encoder_rate_observer), 38 _codecDataBase(encoder_rate_observer),
40 frame_dropper_enabled_(true), 39 frame_dropper_enabled_(true),
41 _sendStatsTimer(1000, clock_), 40 _sendStatsTimer(1000, clock_),
42 current_codec_(), 41 current_codec_(),
43 qm_settings_callback_(qm_settings_callback), 42 qm_settings_callback_(qm_settings_callback),
44 protection_callback_(nullptr) { 43 protection_callback_(nullptr) {
45 encoder_params_ = {0, 0, 0, 0, false}; 44 encoder_params_ = {0, 0, 0, 0, false};
46 // Allow VideoSender to be created on one thread but used on another, post 45 // Allow VideoSender to be created on one thread but used on another, post
47 // construction. This is currently how this class is being used by at least 46 // construction. This is currently how this class is being used by at least
48 // one external project (diffractor). 47 // one external project (diffractor).
49 _mediaOpt.EnableQM(qm_settings_callback_ != nullptr); 48 _mediaOpt.EnableQM(qm_settings_callback_ != nullptr);
50 _mediaOpt.Reset(); 49 _mediaOpt.Reset();
51 main_thread_.DetachFromThread(); 50 main_thread_.DetachFromThread();
52 } 51 }
53 52
54 VideoSender::~VideoSender() { 53 VideoSender::~VideoSender() {}
55 delete _sendCritSect;
56 }
57 54
58 int32_t VideoSender::Process() { 55 int32_t VideoSender::Process() {
59 int32_t returnValue = VCM_OK; 56 int32_t returnValue = VCM_OK;
60 57
61 if (_sendStatsTimer.TimeUntilProcess() == 0) { 58 if (_sendStatsTimer.TimeUntilProcess() == 0) {
62 _sendStatsTimer.Processed(); 59 _sendStatsTimer.Processed();
63 CriticalSectionScoped cs(process_crit_sect_.get()); 60 CriticalSectionScoped cs(process_crit_sect_.get());
64 if (_sendStatsCallback != nullptr) { 61 if (_sendStatsCallback != nullptr) {
65 uint32_t bitRate = _mediaOpt.SentBitRate(); 62 uint32_t bitRate = _mediaOpt.SentBitRate();
66 uint32_t frameRate = _mediaOpt.SentFrameRate(); 63 uint32_t frameRate = _mediaOpt.SentFrameRate();
(...skipping 14 matching lines...) Expand all
81 78
82 int64_t VideoSender::TimeUntilNextProcess() { 79 int64_t VideoSender::TimeUntilNextProcess() {
83 return _sendStatsTimer.TimeUntilProcess(); 80 return _sendStatsTimer.TimeUntilProcess();
84 } 81 }
85 82
86 // Register the send codec to be used. 83 // Register the send codec to be used.
87 int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec, 84 int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec,
88 uint32_t numberOfCores, 85 uint32_t numberOfCores,
89 uint32_t maxPayloadSize) { 86 uint32_t maxPayloadSize) {
90 DCHECK(main_thread_.CalledOnValidThread()); 87 DCHECK(main_thread_.CalledOnValidThread());
91 CriticalSectionScoped cs(_sendCritSect); 88 rtc::CritScope lock(&send_crit_);
92 if (sendCodec == nullptr) { 89 if (sendCodec == nullptr) {
93 return VCM_PARAMETER_ERROR; 90 return VCM_PARAMETER_ERROR;
94 } 91 }
95 92
96 bool ret = _codecDataBase.SetSendCodec( 93 bool ret = _codecDataBase.SetSendCodec(
97 sendCodec, numberOfCores, maxPayloadSize, &_encodedFrameCallback); 94 sendCodec, numberOfCores, maxPayloadSize, &_encodedFrameCallback);
98 95
99 // Update encoder regardless of result to make sure that we're not holding on 96 // Update encoder regardless of result to make sure that we're not holding on
100 // to a deleted instance. 97 // to a deleted instance.
101 _encoder = _codecDataBase.GetEncoder(); 98 _encoder = _codecDataBase.GetEncoder();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 maxPayloadSize); 131 maxPayloadSize);
135 return VCM_OK; 132 return VCM_OK;
136 } 133 }
137 134
138 const VideoCodec& VideoSender::GetSendCodec() const { 135 const VideoCodec& VideoSender::GetSendCodec() const {
139 DCHECK(main_thread_.CalledOnValidThread()); 136 DCHECK(main_thread_.CalledOnValidThread());
140 return current_codec_; 137 return current_codec_;
141 } 138 }
142 139
143 int32_t VideoSender::SendCodecBlocking(VideoCodec* currentSendCodec) const { 140 int32_t VideoSender::SendCodecBlocking(VideoCodec* currentSendCodec) const {
144 CriticalSectionScoped cs(_sendCritSect); 141 rtc::CritScope lock(&send_crit_);
145 if (currentSendCodec == nullptr) { 142 if (currentSendCodec == nullptr) {
146 return VCM_PARAMETER_ERROR; 143 return VCM_PARAMETER_ERROR;
147 } 144 }
148 return _codecDataBase.SendCodec(currentSendCodec) ? 0 : -1; 145 return _codecDataBase.SendCodec(currentSendCodec) ? 0 : -1;
149 } 146 }
150 147
151 VideoCodecType VideoSender::SendCodecBlocking() const { 148 VideoCodecType VideoSender::SendCodecBlocking() const {
152 CriticalSectionScoped cs(_sendCritSect); 149 rtc::CritScope lock(&send_crit_);
153 return _codecDataBase.SendCodec(); 150 return _codecDataBase.SendCodec();
154 } 151 }
155 152
156 // Register an external decoder object. 153 // Register an external decoder object.
157 // This can not be used together with external decoder callbacks. 154 // This can not be used together with external decoder callbacks.
158 int32_t VideoSender::RegisterExternalEncoder(VideoEncoder* externalEncoder, 155 int32_t VideoSender::RegisterExternalEncoder(VideoEncoder* externalEncoder,
159 uint8_t payloadType, 156 uint8_t payloadType,
160 bool internalSource /*= false*/) { 157 bool internalSource /*= false*/) {
161 DCHECK(main_thread_.CalledOnValidThread()); 158 DCHECK(main_thread_.CalledOnValidThread());
162 159
163 CriticalSectionScoped cs(_sendCritSect); 160 rtc::CritScope lock(&send_crit_);
164 161
165 if (externalEncoder == nullptr) { 162 if (externalEncoder == nullptr) {
166 bool wasSendCodec = false; 163 bool wasSendCodec = false;
167 const bool ret = 164 const bool ret =
168 _codecDataBase.DeregisterExternalEncoder(payloadType, &wasSendCodec); 165 _codecDataBase.DeregisterExternalEncoder(payloadType, &wasSendCodec);
169 if (wasSendCodec) { 166 if (wasSendCodec) {
170 // Make sure the VCM doesn't use the de-registered codec 167 // Make sure the VCM doesn't use the de-registered codec
171 _encoder = nullptr; 168 _encoder = nullptr;
172 } 169 }
173 return ret ? 0 : -1; 170 return ret ? 0 : -1;
174 } 171 }
175 _codecDataBase.RegisterExternalEncoder( 172 _codecDataBase.RegisterExternalEncoder(
176 externalEncoder, payloadType, internalSource); 173 externalEncoder, payloadType, internalSource);
177 return 0; 174 return 0;
178 } 175 }
179 176
180 // Get codec config parameters 177 // Get codec config parameters
181 int32_t VideoSender::CodecConfigParameters(uint8_t* buffer, 178 int32_t VideoSender::CodecConfigParameters(uint8_t* buffer,
182 int32_t size) const { 179 int32_t size) const {
183 CriticalSectionScoped cs(_sendCritSect); 180 rtc::CritScope lock(&send_crit_);
184 if (_encoder != nullptr) { 181 if (_encoder != nullptr) {
185 return _encoder->CodecConfigParameters(buffer, size); 182 return _encoder->CodecConfigParameters(buffer, size);
186 } 183 }
187 return VCM_UNINITIALIZED; 184 return VCM_UNINITIALIZED;
188 } 185 }
189 186
190 // TODO(andresp): Make const once media_opt is thread-safe and this has a 187 // TODO(andresp): Make const once media_opt is thread-safe and this has a
191 // pointer to it. 188 // pointer to it.
192 int32_t VideoSender::SentFrameCount(VCMFrameCount* frameCount) { 189 int32_t VideoSender::SentFrameCount(VCMFrameCount* frameCount) {
193 *frameCount = _mediaOpt.SentFrameCount(); 190 *frameCount = _mediaOpt.SentFrameCount();
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 228
232 uint32_t input_frame_rate = _mediaOpt.InputFrameRate(); 229 uint32_t input_frame_rate = _mediaOpt.InputFrameRate();
233 230
234 rtc::CritScope cs(&params_lock_); 231 rtc::CritScope cs(&params_lock_);
235 encoder_params_ = 232 encoder_params_ =
236 EncoderParameters{target_rate, lossRate, rtt, input_frame_rate, true}; 233 EncoderParameters{target_rate, lossRate, rtt, input_frame_rate, true};
237 234
238 return VCM_OK; 235 return VCM_OK;
239 } 236 }
240 237
241 int32_t VideoSender::UpdateEncoderParameters() { 238 void VideoSender::SetEncoderParameters(EncoderParameters params) {
242 EncoderParameters params;
243 {
244 rtc::CritScope cs(&params_lock_);
245 params = encoder_params_;
246 encoder_params_.updated = false;
247 }
248
249 if (!params.updated || params.target_bitrate == 0) 239 if (!params.updated || params.target_bitrate == 0)
250 return VCM_OK; 240 return;
251
252 CriticalSectionScoped sendCs(_sendCritSect);
253 int32_t ret = VCM_UNINITIALIZED;
254 static_assert(VCM_UNINITIALIZED < 0, "VCM_UNINITIALIZED must be negative.");
255 241
256 if (params.input_frame_rate == 0) { 242 if (params.input_frame_rate == 0) {
257 // No frame rate estimate available, use default. 243 // No frame rate estimate available, use default.
258 params.input_frame_rate = current_codec_.maxFramerate; 244 params.input_frame_rate = current_codec_.maxFramerate;
259 } 245 }
260 if (_encoder != nullptr) { 246 if (_encoder != nullptr) {
261 ret = _encoder->SetChannelParameters(params.loss_rate, params.rtt); 247 _encoder->SetChannelParameters(params.loss_rate, params.rtt);
262 if (ret >= 0) { 248 _encoder->SetRates(params.target_bitrate, params.input_frame_rate);
263 ret = _encoder->SetRates(params.target_bitrate, params.input_frame_rate);
264 }
265 } 249 }
266 return ret; 250 return;
267 } 251 }
268 252
269 int32_t VideoSender::RegisterTransportCallback( 253 int32_t VideoSender::RegisterTransportCallback(
270 VCMPacketizationCallback* transport) { 254 VCMPacketizationCallback* transport) {
271 CriticalSectionScoped cs(_sendCritSect); 255 rtc::CritScope lock(&send_crit_);
272 _encodedFrameCallback.SetMediaOpt(&_mediaOpt); 256 _encodedFrameCallback.SetMediaOpt(&_mediaOpt);
273 _encodedFrameCallback.SetTransportCallback(transport); 257 _encodedFrameCallback.SetTransportCallback(transport);
274 return VCM_OK; 258 return VCM_OK;
275 } 259 }
276 260
277 // Register video output information callback which will be called to deliver 261 // Register video output information callback which will be called to deliver
278 // information about the video stream produced by the encoder, for instance the 262 // information about the video stream produced by the encoder, for instance the
279 // average frame rate and bit rate. 263 // average frame rate and bit rate.
280 int32_t VideoSender::RegisterSendStatisticsCallback( 264 int32_t VideoSender::RegisterSendStatisticsCallback(
281 VCMSendStatisticsCallback* sendStats) { 265 VCMSendStatisticsCallback* sendStats) {
282 CriticalSectionScoped cs(process_crit_sect_.get()); 266 CriticalSectionScoped cs(process_crit_sect_.get());
283 _sendStatsCallback = sendStats; 267 _sendStatsCallback = sendStats;
284 return VCM_OK; 268 return VCM_OK;
285 } 269 }
286 270
287 // Register a video protection callback which will be called to deliver the 271 // Register a video protection callback which will be called to deliver the
288 // requested FEC rate and NACK status (on/off). 272 // requested FEC rate and NACK status (on/off).
289 // Note: this callback is assumed to only be registered once and before it is 273 // Note: this callback is assumed to only be registered once and before it is
290 // used in this class. 274 // used in this class.
291 int32_t VideoSender::RegisterProtectionCallback( 275 int32_t VideoSender::RegisterProtectionCallback(
292 VCMProtectionCallback* protection_callback) { 276 VCMProtectionCallback* protection_callback) {
293 DCHECK(protection_callback == nullptr || protection_callback_ == nullptr); 277 DCHECK(protection_callback == nullptr || protection_callback_ == nullptr);
294 protection_callback_ = protection_callback; 278 protection_callback_ = protection_callback;
295 return VCM_OK; 279 return VCM_OK;
296 } 280 }
297 281
298 // Enable or disable a video protection method. 282 // Enable or disable a video protection method.
299 void VideoSender::SetVideoProtection(VCMVideoProtection videoProtection) { 283 void VideoSender::SetVideoProtection(VCMVideoProtection videoProtection) {
300 CriticalSectionScoped cs(_sendCritSect); 284 rtc::CritScope lock(&send_crit_);
301 switch (videoProtection) { 285 switch (videoProtection) {
302 case kProtectionNone: 286 case kProtectionNone:
303 _mediaOpt.SetProtectionMethod(media_optimization::kNone); 287 _mediaOpt.SetProtectionMethod(media_optimization::kNone);
304 break; 288 break;
305 case kProtectionNack: 289 case kProtectionNack:
306 _mediaOpt.SetProtectionMethod(media_optimization::kNack); 290 _mediaOpt.SetProtectionMethod(media_optimization::kNack);
307 break; 291 break;
308 case kProtectionNackFEC: 292 case kProtectionNackFEC:
309 _mediaOpt.SetProtectionMethod(media_optimization::kNackFec); 293 _mediaOpt.SetProtectionMethod(media_optimization::kNackFec);
310 break; 294 break;
311 case kProtectionFEC: 295 case kProtectionFEC:
312 _mediaOpt.SetProtectionMethod(media_optimization::kFec); 296 _mediaOpt.SetProtectionMethod(media_optimization::kFec);
313 break; 297 break;
314 } 298 }
315 } 299 }
316 // Add one raw video frame to the encoder, blocking. 300 // Add one raw video frame to the encoder, blocking.
317 int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame, 301 int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame,
318 const VideoContentMetrics* contentMetrics, 302 const VideoContentMetrics* contentMetrics,
319 const CodecSpecificInfo* codecSpecificInfo) { 303 const CodecSpecificInfo* codecSpecificInfo) {
320 UpdateEncoderParameters(); 304 EncoderParameters encoder_params;
321 CriticalSectionScoped cs(_sendCritSect); 305 {
306 rtc::CritScope lock(&params_lock_);
307 encoder_params = encoder_params_;
308 encoder_params_.updated = false;
309 }
310 rtc::CritScope lock(&send_crit_);
311 SetEncoderParameters(encoder_params);
322 if (_encoder == nullptr) { 312 if (_encoder == nullptr) {
323 return VCM_UNINITIALIZED; 313 return VCM_UNINITIALIZED;
324 } 314 }
325 // TODO(holmer): Add support for dropping frames per stream. Currently we 315 // TODO(holmer): Add support for dropping frames per stream. Currently we
326 // only have one frame dropper for all streams. 316 // only have one frame dropper for all streams.
327 if (_nextFrameTypes[0] == kFrameEmpty) { 317 if (_nextFrameTypes[0] == kFrameEmpty) {
328 return VCM_OK; 318 return VCM_OK;
329 } 319 }
330 if (_mediaOpt.DropFrame()) { 320 if (_mediaOpt.DropFrame()) {
331 _encoder->OnDroppedFrame(); 321 _encoder->OnDroppedFrame();
(...skipping 23 matching lines...) Expand all
355 } 345 }
356 for (size_t i = 0; i < _nextFrameTypes.size(); ++i) { 346 for (size_t i = 0; i < _nextFrameTypes.size(); ++i) {
357 _nextFrameTypes[i] = kVideoFrameDelta; // Default frame type. 347 _nextFrameTypes[i] = kVideoFrameDelta; // Default frame type.
358 } 348 }
359 if (qm_settings_callback_) 349 if (qm_settings_callback_)
360 qm_settings_callback_->SetTargetFramerate(_encoder->GetTargetFramerate()); 350 qm_settings_callback_->SetTargetFramerate(_encoder->GetTargetFramerate());
361 return VCM_OK; 351 return VCM_OK;
362 } 352 }
363 353
364 int32_t VideoSender::IntraFrameRequest(int stream_index) { 354 int32_t VideoSender::IntraFrameRequest(int stream_index) {
365 CriticalSectionScoped cs(_sendCritSect); 355 rtc::CritScope lock(&send_crit_);
366 if (stream_index < 0 || 356 if (stream_index < 0 ||
367 static_cast<unsigned int>(stream_index) >= _nextFrameTypes.size()) { 357 static_cast<unsigned int>(stream_index) >= _nextFrameTypes.size()) {
368 return -1; 358 return -1;
369 } 359 }
370 _nextFrameTypes[stream_index] = kVideoFrameKey; 360 _nextFrameTypes[stream_index] = kVideoFrameKey;
371 if (_encoder != nullptr && _encoder->InternalSource()) { 361 if (_encoder != nullptr && _encoder->InternalSource()) {
372 // Try to request the frame if we have an external encoder with 362 // Try to request the frame if we have an external encoder with
373 // internal source since AddVideoFrame never will be called. 363 // internal source since AddVideoFrame never will be called.
374 if (_encoder->RequestFrame(_nextFrameTypes) == WEBRTC_VIDEO_CODEC_OK) { 364 if (_encoder->RequestFrame(_nextFrameTypes) == WEBRTC_VIDEO_CODEC_OK) {
375 _nextFrameTypes[stream_index] = kVideoFrameDelta; 365 _nextFrameTypes[stream_index] = kVideoFrameDelta;
376 } 366 }
377 } 367 }
378 return VCM_OK; 368 return VCM_OK;
379 } 369 }
380 370
381 int32_t VideoSender::EnableFrameDropper(bool enable) { 371 int32_t VideoSender::EnableFrameDropper(bool enable) {
382 CriticalSectionScoped cs(_sendCritSect); 372 rtc::CritScope lock(&send_crit_);
383 frame_dropper_enabled_ = enable; 373 frame_dropper_enabled_ = enable;
384 _mediaOpt.EnableFrameDropper(enable); 374 _mediaOpt.EnableFrameDropper(enable);
385 return VCM_OK; 375 return VCM_OK;
386 } 376 }
387 377
388 void VideoSender::SuspendBelowMinBitrate() { 378 void VideoSender::SuspendBelowMinBitrate() {
389 DCHECK(main_thread_.CalledOnValidThread()); 379 DCHECK(main_thread_.CalledOnValidThread());
390 int threshold_bps; 380 int threshold_bps;
391 if (current_codec_.numberOfSimulcastStreams == 0) { 381 if (current_codec_.numberOfSimulcastStreams == 0) {
392 threshold_bps = current_codec_.minBitrate * 1000; 382 threshold_bps = current_codec_.minBitrate * 1000;
393 } else { 383 } else {
394 threshold_bps = current_codec_.simulcastStream[0].minBitrate * 1000; 384 threshold_bps = current_codec_.simulcastStream[0].minBitrate * 1000;
395 } 385 }
396 // Set the hysteresis window to be at 10% of the threshold, but at least 386 // Set the hysteresis window to be at 10% of the threshold, but at least
397 // 10 kbps. 387 // 10 kbps.
398 int window_bps = std::max(threshold_bps / 10, 10000); 388 int window_bps = std::max(threshold_bps / 10, 10000);
399 _mediaOpt.SuspendBelowMinBitrate(threshold_bps, window_bps); 389 _mediaOpt.SuspendBelowMinBitrate(threshold_bps, window_bps);
400 } 390 }
401 391
402 bool VideoSender::VideoSuspended() const { 392 bool VideoSender::VideoSuspended() const {
403 CriticalSectionScoped cs(_sendCritSect); 393 rtc::CritScope lock(&send_crit_);
404 return _mediaOpt.IsVideoSuspended(); 394 return _mediaOpt.IsVideoSuspended();
405 } 395 }
406 } // namespace vcm 396 } // namespace vcm
407 } // namespace webrtc 397 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/video_coding/main/source/video_coding_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698