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

Side by Side Diff: webrtc/video/video_send_stream.cc

Issue 1757313002: Initialize/configure video encoders asychronously. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 9 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
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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 // out). This should effectively turn off CPU adaptations for systems that 141 // out). This should effectively turn off CPU adaptations for systems that
142 // remotely cope with the load right now. 142 // remotely cope with the load right now.
143 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { 143 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) {
144 CpuOveruseOptions options; 144 CpuOveruseOptions options;
145 if (full_overuse_time) { 145 if (full_overuse_time) {
146 options.low_encode_usage_threshold_percent = 150; 146 options.low_encode_usage_threshold_percent = 150;
147 options.high_encode_usage_threshold_percent = 200; 147 options.high_encode_usage_threshold_percent = 200;
148 } 148 }
149 return options; 149 return options;
150 } 150 }
151
152 VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config,
153 const std::string& payload_name,
154 int payload_type) {
155 const std::vector<VideoStream>& streams = config.streams;
156 static const int kEncoderMinBitrateKbps = 30;
157 RTC_DCHECK(!streams.empty());
158 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
159
160 VideoCodec video_codec;
161 memset(&video_codec, 0, sizeof(video_codec));
162 video_codec.codecType = PayloadNameToCodecType(payload_name);
163
164 switch (config.content_type) {
165 case VideoEncoderConfig::ContentType::kRealtimeVideo:
166 video_codec.mode = kRealtimeVideo;
167 break;
168 case VideoEncoderConfig::ContentType::kScreen:
169 video_codec.mode = kScreensharing;
170 if (config.streams.size() == 1 &&
171 config.streams[0].temporal_layer_thresholds_bps.size() == 1) {
172 video_codec.targetBitrate =
173 config.streams[0].temporal_layer_thresholds_bps[0] / 1000;
174 }
175 break;
176 }
177
178 if (video_codec.codecType == kVideoCodecVP8) {
stefan-webrtc 2016/03/14 13:14:03 Maybe change this to a switch {}?
pbos-webrtc 2016/03/14 15:12:58 Done.
179 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
180 } else if (video_codec.codecType == kVideoCodecVP9) {
181 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
182 } else if (video_codec.codecType == kVideoCodecH264) {
183 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
184 }
185
186 if (video_codec.codecType == kVideoCodecVP8) {
187 if (config.encoder_specific_settings != nullptr) {
188 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>(
189 config.encoder_specific_settings);
190 }
191 video_codec.codecSpecific.VP8.numberOfTemporalLayers =
192 static_cast<unsigned char>(
193 streams.back().temporal_layer_thresholds_bps.size() + 1);
194 } else if (video_codec.codecType == kVideoCodecVP9) {
195 if (config.encoder_specific_settings != nullptr) {
196 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>(
197 config.encoder_specific_settings);
198 if (video_codec.mode == kScreensharing) {
199 video_codec.codecSpecific.VP9.flexibleMode = true;
200 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
201 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1);
202 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2);
203 }
204 }
205 video_codec.codecSpecific.VP9.numberOfTemporalLayers =
206 static_cast<unsigned char>(
207 streams.back().temporal_layer_thresholds_bps.size() + 1);
208 } else if (video_codec.codecType == kVideoCodecH264) {
209 if (config.encoder_specific_settings != nullptr) {
210 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>(
211 config.encoder_specific_settings);
212 }
213 } else {
214 // TODO(pbos): Support encoder_settings codec-agnostically.
215 RTC_DCHECK(config.encoder_specific_settings == nullptr)
216 << "Encoder-specific settings for codec type not wired up.";
217 }
218
219 strncpy(video_codec.plName, payload_name.c_str(), kPayloadNameSize - 1);
220 video_codec.plName[kPayloadNameSize - 1] = '\0';
221 video_codec.plType = payload_type;
222 video_codec.numberOfSimulcastStreams =
223 static_cast<unsigned char>(streams.size());
224 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
225 if (video_codec.minBitrate < kEncoderMinBitrateKbps)
226 video_codec.minBitrate = kEncoderMinBitrateKbps;
227 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
228 if (video_codec.codecType == kVideoCodecVP9) {
229 // If the vector is empty, bitrates will be configured automatically.
230 RTC_DCHECK(config.spatial_layers.empty() ||
231 config.spatial_layers.size() ==
232 video_codec.codecSpecific.VP9.numberOfSpatialLayers);
233 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers,
234 kMaxSimulcastStreams);
235 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
236 video_codec.spatialLayers[i] = config.spatial_layers[i];
237 }
238 for (size_t i = 0; i < streams.size(); ++i) {
239 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
240 RTC_DCHECK_GT(streams[i].width, 0u);
241 RTC_DCHECK_GT(streams[i].height, 0u);
242 RTC_DCHECK_GT(streams[i].max_framerate, 0);
243 // Different framerates not supported per stream at the moment.
244 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
245 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
246 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
247 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
248 RTC_DCHECK_GE(streams[i].max_qp, 0);
249
250 sim_stream->width = static_cast<uint16_t>(streams[i].width);
251 sim_stream->height = static_cast<uint16_t>(streams[i].height);
252 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
253 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
254 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
255 sim_stream->qpMax = streams[i].max_qp;
256 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
257 streams[i].temporal_layer_thresholds_bps.size() + 1);
258
259 video_codec.width = std::max(video_codec.width,
260 static_cast<uint16_t>(streams[i].width));
261 video_codec.height = std::max(
262 video_codec.height, static_cast<uint16_t>(streams[i].height));
263 video_codec.minBitrate =
264 std::min(static_cast<uint16_t>(video_codec.minBitrate),
265 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
266 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
267 video_codec.qpMax = std::max(video_codec.qpMax,
268 static_cast<unsigned int>(streams[i].max_qp));
269 }
270
271 if (video_codec.maxBitrate == 0) {
272 // Unset max bitrate -> cap to one bit per pixel.
273 video_codec.maxBitrate =
274 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
275 1000;
276 }
277 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
278 video_codec.maxBitrate = kEncoderMinBitrateKbps;
279
280 RTC_DCHECK_GT(streams[0].max_framerate, 0);
281 video_codec.maxFramerate = streams[0].max_framerate;
282
283 return video_codec;
284 }
285
151 } // namespace 286 } // namespace
152 287
153 namespace internal { 288 namespace internal {
154 VideoSendStream::VideoSendStream( 289 VideoSendStream::VideoSendStream(
155 int num_cpu_cores, 290 int num_cpu_cores,
156 ProcessThread* module_process_thread, 291 ProcessThread* module_process_thread,
157 CallStats* call_stats, 292 CallStats* call_stats,
158 CongestionController* congestion_controller, 293 CongestionController* congestion_controller,
159 VieRemb* remb, 294 VieRemb* remb,
160 BitrateAllocator* bitrate_allocator, 295 BitrateAllocator* bitrate_allocator,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); 414 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_);
280 rtp_rtcp->SetMaxTransferUnit(mtu); 415 rtp_rtcp->SetMaxTransferUnit(mtu);
281 rtp_rtcp->RegisterVideoSendPayload( 416 rtp_rtcp->RegisterVideoSendPayload(
282 config_.encoder_settings.payload_type, 417 config_.encoder_settings.payload_type,
283 config_.encoder_settings.payload_name.c_str()); 418 config_.encoder_settings.payload_name.c_str());
284 } 419 }
285 420
286 RTC_DCHECK(config.encoder_settings.encoder != nullptr); 421 RTC_DCHECK(config.encoder_settings.encoder != nullptr);
287 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); 422 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0);
288 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); 423 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127);
289 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder(
290 config.encoder_settings.encoder,
291 config.encoder_settings.payload_type,
292 config.encoder_settings.internal_source));
293
294 ReconfigureVideoEncoder(encoder_config); 424 ReconfigureVideoEncoder(encoder_config);
295 425
296 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); 426 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_);
297 427
298 if (config_.post_encode_callback) 428 if (config_.post_encode_callback)
299 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); 429 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_);
300 430
301 if (config_.suspend_below_min_bitrate)
302 vie_encoder_.SuspendBelowMinBitrate();
303
304 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); 431 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_);
305 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); 432 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_);
306 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); 433 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_);
307 434
308 module_process_thread_->RegisterModule(&overuse_detector_); 435 module_process_thread_->RegisterModule(&overuse_detector_);
309 436
310 encoder_thread_.Start(); 437 encoder_thread_.Start();
311 encoder_thread_.SetPriority(rtc::kHighPriority); 438 encoder_thread_.SetPriority(rtc::kHighPriority);
312 } 439 }
313 440
314 VideoSendStream::~VideoSendStream() { 441 VideoSendStream::~VideoSendStream() {
315 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); 442 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString();
316 Stop(); 443 Stop();
317 444
318 // Stop the encoder thread permanently. 445 // Stop the encoder thread permanently.
319 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); 446 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1);
320 encoder_wakeup_event_.Set(); 447 encoder_wakeup_event_.Set();
321 encoder_thread_.Stop(); 448 encoder_thread_.Stop();
322 449
323 module_process_thread_->DeRegisterModule(&overuse_detector_); 450 module_process_thread_->DeRegisterModule(&overuse_detector_);
324 vie_channel_.RegisterSendFrameCountObserver(nullptr); 451 vie_channel_.RegisterSendFrameCountObserver(nullptr);
325 vie_channel_.RegisterSendBitrateObserver(nullptr); 452 vie_channel_.RegisterSendBitrateObserver(nullptr);
326 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); 453 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr);
327 454
328 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
329
330 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); 455 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver());
331 rtp_rtcp_modules_[0]->SetREMBStatus(false); 456 rtp_rtcp_modules_[0]->SetREMBStatus(false);
332 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); 457 remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
333 458
334 // ViEChannel outlives ViEEncoder so remove encoder from feedback before 459 // ViEChannel outlives ViEEncoder so remove encoder from feedback before
335 // destruction. 460 // destruction.
336 encoder_feedback_.TearDown(); 461 encoder_feedback_.TearDown();
337 462
338 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( 463 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream(
339 vie_receiver_->GetRemoteSsrc()); 464 vie_receiver_->GetRemoteSsrc());
(...skipping 22 matching lines...) Expand all
362 vie_receiver_->StopReceive(); 487 vie_receiver_->StopReceive();
363 } 488 }
364 489
365 bool VideoSendStream::EncoderThreadFunction(void* obj) { 490 bool VideoSendStream::EncoderThreadFunction(void* obj) {
366 static_cast<VideoSendStream*>(obj)->EncoderProcess(); 491 static_cast<VideoSendStream*>(obj)->EncoderProcess();
367 // We're done, return false to abort. 492 // We're done, return false to abort.
368 return false; 493 return false;
369 } 494 }
370 495
371 void VideoSendStream::EncoderProcess() { 496 void VideoSendStream::EncoderProcess() {
497 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder(
stefan-webrtc 2016/03/14 13:14:03 Is there anything we should DCHECK before this to
pbos-webrtc 2016/03/14 15:12:58 Don't think we have any good primitives for checki
498 config_.encoder_settings.encoder,
499 config_.encoder_settings.payload_type,
500 config_.encoder_settings.internal_source));
501
372 while (true) { 502 while (true) {
373 encoder_wakeup_event_.Wait(rtc::Event::kForever); 503 encoder_wakeup_event_.Wait(rtc::Event::kForever);
374 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) 504 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_))
375 return; 505 break;
506 rtc::Optional<EncoderSettings> encoder_settings;
507 {
508 rtc::CritScope lock(&encoder_settings_crit_);
509 if (pending_encoder_settings_) {
510 encoder_settings = pending_encoder_settings_;
511 pending_encoder_settings_ = rtc::Optional<EncoderSettings>();
512 }
513 }
514 if (encoder_settings) {
515 vie_encoder_.SetEncoder(encoder_settings->video_codec,
516 encoder_settings->min_transmit_bitrate_bps);
517 if (config_.suspend_below_min_bitrate)
518 vie_encoder_.SuspendBelowMinBitrate();
519 // We might've gotten new settings while configuring the encoder settings,
520 // restart from the top to see if that's the case before trying to encode
521 // a frame (which might correspond to the last frame size).
522 encoder_wakeup_event_.Set();
523 continue;
524 }
376 525
377 VideoFrame frame; 526 VideoFrame frame;
378 if (input_.GetVideoFrame(&frame)) 527 if (input_.GetVideoFrame(&frame))
379 vie_encoder_.EncodeVideoFrame(frame); 528 vie_encoder_.EncodeVideoFrame(frame);
380 } 529 }
530 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
381 } 531 }
382 532
383 void VideoSendStream::ReconfigureVideoEncoder( 533 void VideoSendStream::ReconfigureVideoEncoder(
384 const VideoEncoderConfig& config) { 534 const VideoEncoderConfig& config) {
385 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); 535 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder");
386 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); 536 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString();
387 const std::vector<VideoStream>& streams = config.streams; 537 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size());
388 static const int kEncoderMinBitrateKbps = 30; 538 VideoCodec video_codec = VideoEncoderConfigToVideoCodec(
389 RTC_DCHECK(!streams.empty()); 539 config, config_.encoder_settings.payload_name,
390 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size()); 540 config_.encoder_settings.payload_type);
391 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); 541 rtc::CritScope lock(&encoder_settings_crit_);
stefan-webrtc 2016/03/14 13:14:03 Maybe put this within its own scope?
pbos-webrtc 2016/03/14 15:12:58 Done.
392 542 pending_encoder_settings_ = rtc::Optional<EncoderSettings>(
393 VideoCodec video_codec; 543 {video_codec, config.min_transmit_bitrate_bps});
394 memset(&video_codec, 0, sizeof(video_codec)); 544 encoder_wakeup_event_.Set();
395 video_codec.codecType =
396 PayloadNameToCodecType(config_.encoder_settings.payload_name);
397
398 switch (config.content_type) {
399 case VideoEncoderConfig::ContentType::kRealtimeVideo:
400 video_codec.mode = kRealtimeVideo;
401 break;
402 case VideoEncoderConfig::ContentType::kScreen:
403 video_codec.mode = kScreensharing;
404 if (config.streams.size() == 1 &&
405 config.streams[0].temporal_layer_thresholds_bps.size() == 1) {
406 video_codec.targetBitrate =
407 config.streams[0].temporal_layer_thresholds_bps[0] / 1000;
408 }
409 break;
410 }
411
412 if (video_codec.codecType == kVideoCodecVP8) {
413 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
414 } else if (video_codec.codecType == kVideoCodecVP9) {
415 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
416 } else if (video_codec.codecType == kVideoCodecH264) {
417 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
418 }
419
420 if (video_codec.codecType == kVideoCodecVP8) {
421 if (config.encoder_specific_settings != nullptr) {
422 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>(
423 config.encoder_specific_settings);
424 }
425 video_codec.codecSpecific.VP8.numberOfTemporalLayers =
426 static_cast<unsigned char>(
427 streams.back().temporal_layer_thresholds_bps.size() + 1);
428 } else if (video_codec.codecType == kVideoCodecVP9) {
429 if (config.encoder_specific_settings != nullptr) {
430 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>(
431 config.encoder_specific_settings);
432 if (video_codec.mode == kScreensharing) {
433 video_codec.codecSpecific.VP9.flexibleMode = true;
434 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
435 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1);
436 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2);
437 }
438 }
439 video_codec.codecSpecific.VP9.numberOfTemporalLayers =
440 static_cast<unsigned char>(
441 streams.back().temporal_layer_thresholds_bps.size() + 1);
442 } else if (video_codec.codecType == kVideoCodecH264) {
443 if (config.encoder_specific_settings != nullptr) {
444 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>(
445 config.encoder_specific_settings);
446 }
447 } else {
448 // TODO(pbos): Support encoder_settings codec-agnostically.
449 RTC_DCHECK(config.encoder_specific_settings == nullptr)
450 << "Encoder-specific settings for codec type not wired up.";
451 }
452
453 strncpy(video_codec.plName,
454 config_.encoder_settings.payload_name.c_str(),
455 kPayloadNameSize - 1);
456 video_codec.plName[kPayloadNameSize - 1] = '\0';
457 video_codec.plType = config_.encoder_settings.payload_type;
458 video_codec.numberOfSimulcastStreams =
459 static_cast<unsigned char>(streams.size());
460 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
461 if (video_codec.minBitrate < kEncoderMinBitrateKbps)
462 video_codec.minBitrate = kEncoderMinBitrateKbps;
463 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
464 if (video_codec.codecType == kVideoCodecVP9) {
465 // If the vector is empty, bitrates will be configured automatically.
466 RTC_DCHECK(config.spatial_layers.empty() ||
467 config.spatial_layers.size() ==
468 video_codec.codecSpecific.VP9.numberOfSpatialLayers);
469 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers,
470 kMaxSimulcastStreams);
471 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
472 video_codec.spatialLayers[i] = config.spatial_layers[i];
473 }
474 for (size_t i = 0; i < streams.size(); ++i) {
475 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
476 RTC_DCHECK_GT(streams[i].width, 0u);
477 RTC_DCHECK_GT(streams[i].height, 0u);
478 RTC_DCHECK_GT(streams[i].max_framerate, 0);
479 // Different framerates not supported per stream at the moment.
480 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
481 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
482 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
483 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
484 RTC_DCHECK_GE(streams[i].max_qp, 0);
485
486 sim_stream->width = static_cast<uint16_t>(streams[i].width);
487 sim_stream->height = static_cast<uint16_t>(streams[i].height);
488 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
489 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
490 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
491 sim_stream->qpMax = streams[i].max_qp;
492 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
493 streams[i].temporal_layer_thresholds_bps.size() + 1);
494
495 video_codec.width = std::max(video_codec.width,
496 static_cast<uint16_t>(streams[i].width));
497 video_codec.height = std::max(
498 video_codec.height, static_cast<uint16_t>(streams[i].height));
499 video_codec.minBitrate =
500 std::min(static_cast<uint16_t>(video_codec.minBitrate),
501 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
502 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
503 video_codec.qpMax = std::max(video_codec.qpMax,
504 static_cast<unsigned int>(streams[i].max_qp));
505 }
506
507 if (video_codec.maxBitrate == 0) {
508 // Unset max bitrate -> cap to one bit per pixel.
509 video_codec.maxBitrate =
510 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
511 1000;
512 }
513 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
514 video_codec.maxBitrate = kEncoderMinBitrateKbps;
515
516 RTC_DCHECK_GT(streams[0].max_framerate, 0);
517 video_codec.maxFramerate = streams[0].max_framerate;
518
519 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps);
520 } 545 }
521 546
522 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { 547 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
523 return vie_receiver_->DeliverRtcp(packet, length); 548 return vie_receiver_->DeliverRtcp(packet, length);
524 } 549 }
525 550
526 VideoSendStream::Stats VideoSendStream::GetStats() { 551 VideoSendStream::Stats VideoSendStream::GetStats() {
527 return stats_proxy_.GetStats(); 552 return stats_proxy_.GetStats();
528 } 553 }
529 554
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) 634 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
610 rtp_rtcp->SetRTCPStatus(RtcpMode::kOff); 635 rtp_rtcp->SetRTCPStatus(RtcpMode::kOff);
611 } 636 }
612 } 637 }
613 638
614 int VideoSendStream::GetPaddingNeededBps() const { 639 int VideoSendStream::GetPaddingNeededBps() const {
615 return vie_encoder_.GetPaddingNeededBps(); 640 return vie_encoder_.GetPaddingNeededBps();
616 } 641 }
617 } // namespace internal 642 } // namespace internal
618 } // namespace webrtc 643 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698