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

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: feedback 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
« no previous file with comments | « webrtc/video/video_send_stream.h ('k') | webrtc/video/video_send_stream_tests.cc » ('j') | 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 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 switch (video_codec.codecType) {
179 case kVideoCodecVP8:
180 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
181 break;
182 case kVideoCodecVP9:
183 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
184 break;
185 case kVideoCodecH264:
186 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
187 break;
188 default:
189 break;
190 }
191
192 if (video_codec.codecType == kVideoCodecVP8) {
stefan-webrtc 2016/03/14 15:27:22 Maybe switch here too?
pbos-webrtc 2016/03/14 15:43:11 Merged into previous switch, done.
193 if (config.encoder_specific_settings != nullptr) {
194 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>(
195 config.encoder_specific_settings);
196 }
197 video_codec.codecSpecific.VP8.numberOfTemporalLayers =
198 static_cast<unsigned char>(
199 streams.back().temporal_layer_thresholds_bps.size() + 1);
200 } else if (video_codec.codecType == kVideoCodecVP9) {
201 if (config.encoder_specific_settings != nullptr) {
202 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>(
203 config.encoder_specific_settings);
204 if (video_codec.mode == kScreensharing) {
205 video_codec.codecSpecific.VP9.flexibleMode = true;
206 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
207 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1);
208 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2);
209 }
210 }
211 video_codec.codecSpecific.VP9.numberOfTemporalLayers =
212 static_cast<unsigned char>(
213 streams.back().temporal_layer_thresholds_bps.size() + 1);
214 } else if (video_codec.codecType == kVideoCodecH264) {
215 if (config.encoder_specific_settings != nullptr) {
216 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>(
217 config.encoder_specific_settings);
218 }
219 } else {
220 // TODO(pbos): Support encoder_settings codec-agnostically.
221 RTC_DCHECK(config.encoder_specific_settings == nullptr)
222 << "Encoder-specific settings for codec type not wired up.";
223 }
224
225 strncpy(video_codec.plName, payload_name.c_str(), kPayloadNameSize - 1);
226 video_codec.plName[kPayloadNameSize - 1] = '\0';
227 video_codec.plType = payload_type;
228 video_codec.numberOfSimulcastStreams =
229 static_cast<unsigned char>(streams.size());
230 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
231 if (video_codec.minBitrate < kEncoderMinBitrateKbps)
232 video_codec.minBitrate = kEncoderMinBitrateKbps;
233 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
234 if (video_codec.codecType == kVideoCodecVP9) {
235 // If the vector is empty, bitrates will be configured automatically.
236 RTC_DCHECK(config.spatial_layers.empty() ||
237 config.spatial_layers.size() ==
238 video_codec.codecSpecific.VP9.numberOfSpatialLayers);
239 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers,
240 kMaxSimulcastStreams);
241 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
242 video_codec.spatialLayers[i] = config.spatial_layers[i];
243 }
244 for (size_t i = 0; i < streams.size(); ++i) {
245 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
246 RTC_DCHECK_GT(streams[i].width, 0u);
247 RTC_DCHECK_GT(streams[i].height, 0u);
248 RTC_DCHECK_GT(streams[i].max_framerate, 0);
249 // Different framerates not supported per stream at the moment.
250 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
251 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
252 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
253 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
254 RTC_DCHECK_GE(streams[i].max_qp, 0);
255
256 sim_stream->width = static_cast<uint16_t>(streams[i].width);
257 sim_stream->height = static_cast<uint16_t>(streams[i].height);
258 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
259 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
260 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
261 sim_stream->qpMax = streams[i].max_qp;
262 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
263 streams[i].temporal_layer_thresholds_bps.size() + 1);
264
265 video_codec.width = std::max(video_codec.width,
266 static_cast<uint16_t>(streams[i].width));
267 video_codec.height = std::max(
268 video_codec.height, static_cast<uint16_t>(streams[i].height));
269 video_codec.minBitrate =
270 std::min(static_cast<uint16_t>(video_codec.minBitrate),
271 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
272 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
273 video_codec.qpMax = std::max(video_codec.qpMax,
274 static_cast<unsigned int>(streams[i].max_qp));
275 }
276
277 if (video_codec.maxBitrate == 0) {
278 // Unset max bitrate -> cap to one bit per pixel.
279 video_codec.maxBitrate =
280 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
281 1000;
282 }
283 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
284 video_codec.maxBitrate = kEncoderMinBitrateKbps;
285
286 RTC_DCHECK_GT(streams[0].max_framerate, 0);
287 video_codec.maxFramerate = streams[0].max_framerate;
288
289 return video_codec;
290 }
291
151 } // namespace 292 } // namespace
152 293
153 namespace internal { 294 namespace internal {
154 VideoSendStream::VideoSendStream( 295 VideoSendStream::VideoSendStream(
155 int num_cpu_cores, 296 int num_cpu_cores,
156 ProcessThread* module_process_thread, 297 ProcessThread* module_process_thread,
157 CallStats* call_stats, 298 CallStats* call_stats,
158 CongestionController* congestion_controller, 299 CongestionController* congestion_controller,
159 BitrateAllocator* bitrate_allocator, 300 BitrateAllocator* bitrate_allocator,
160 VieRemb* remb, 301 VieRemb* remb,
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_); 420 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(&stats_proxy_);
280 rtp_rtcp->SetMaxTransferUnit(mtu); 421 rtp_rtcp->SetMaxTransferUnit(mtu);
281 rtp_rtcp->RegisterVideoSendPayload( 422 rtp_rtcp->RegisterVideoSendPayload(
282 config_.encoder_settings.payload_type, 423 config_.encoder_settings.payload_type,
283 config_.encoder_settings.payload_name.c_str()); 424 config_.encoder_settings.payload_name.c_str());
284 } 425 }
285 426
286 RTC_DCHECK(config.encoder_settings.encoder != nullptr); 427 RTC_DCHECK(config.encoder_settings.encoder != nullptr);
287 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0); 428 RTC_DCHECK_GE(config.encoder_settings.payload_type, 0);
288 RTC_DCHECK_LE(config.encoder_settings.payload_type, 127); 429 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); 430 ReconfigureVideoEncoder(encoder_config);
295 431
296 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_); 432 vie_channel_.RegisterSendSideDelayObserver(&stats_proxy_);
297 433
298 if (config_.post_encode_callback) 434 if (config_.post_encode_callback)
299 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_); 435 vie_encoder_.RegisterPostEncodeImageCallback(&encoded_frame_proxy_);
300 436
301 if (config_.suspend_below_min_bitrate) {
302 vcm_->SuspendBelowMinBitrate();
303 bitrate_allocator_->EnforceMinBitrate(false);
304 }
305
306 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_); 437 vie_channel_.RegisterRtcpPacketTypeCounterObserver(&stats_proxy_);
307 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_); 438 vie_channel_.RegisterSendBitrateObserver(&stats_proxy_);
308 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_); 439 vie_channel_.RegisterSendFrameCountObserver(&stats_proxy_);
309 440
310 module_process_thread_->RegisterModule(&overuse_detector_); 441 module_process_thread_->RegisterModule(&overuse_detector_);
311 442
312 encoder_thread_.Start(); 443 encoder_thread_.Start();
313 encoder_thread_.SetPriority(rtc::kHighPriority); 444 encoder_thread_.SetPriority(rtc::kHighPriority);
314 } 445 }
315 446
316 VideoSendStream::~VideoSendStream() { 447 VideoSendStream::~VideoSendStream() {
317 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString(); 448 LOG(LS_INFO) << "~VideoSendStream: " << config_.ToString();
318 449
319 bitrate_allocator_->RemoveObserver(this); 450 bitrate_allocator_->RemoveObserver(this);
320 Stop(); 451 Stop();
321 452
322 // Stop the encoder thread permanently. 453 // Stop the encoder thread permanently.
323 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1); 454 rtc::AtomicOps::ReleaseStore(&stop_encoder_thread_, 1);
324 encoder_wakeup_event_.Set(); 455 encoder_wakeup_event_.Set();
325 encoder_thread_.Stop(); 456 encoder_thread_.Stop();
326 457
327 module_process_thread_->DeRegisterModule(&overuse_detector_); 458 module_process_thread_->DeRegisterModule(&overuse_detector_);
328 vie_channel_.RegisterSendFrameCountObserver(nullptr); 459 vie_channel_.RegisterSendFrameCountObserver(nullptr);
329 vie_channel_.RegisterSendBitrateObserver(nullptr); 460 vie_channel_.RegisterSendBitrateObserver(nullptr);
330 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr); 461 vie_channel_.RegisterRtcpPacketTypeCounterObserver(nullptr);
331 462
332 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
333
334 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver()); 463 call_stats_->DeregisterStatsObserver(vie_channel_.GetStatsObserver());
335 rtp_rtcp_modules_[0]->SetREMBStatus(false); 464 rtp_rtcp_modules_[0]->SetREMBStatus(false);
336 remb_->RemoveRembSender(rtp_rtcp_modules_[0]); 465 remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
337 466
338 // ViEChannel outlives ViEEncoder so remove encoder from feedback before 467 // ViEChannel outlives ViEEncoder so remove encoder from feedback before
339 // destruction. 468 // destruction.
340 encoder_feedback_.TearDown(); 469 encoder_feedback_.TearDown();
341 470
342 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream( 471 congestion_controller_->GetRemoteBitrateEstimator(false)->RemoveStream(
343 vie_receiver_->GetRemoteSsrc()); 472 vie_receiver_->GetRemoteSsrc());
(...skipping 22 matching lines...) Expand all
366 vie_receiver_->StopReceive(); 495 vie_receiver_->StopReceive();
367 } 496 }
368 497
369 bool VideoSendStream::EncoderThreadFunction(void* obj) { 498 bool VideoSendStream::EncoderThreadFunction(void* obj) {
370 static_cast<VideoSendStream*>(obj)->EncoderProcess(); 499 static_cast<VideoSendStream*>(obj)->EncoderProcess();
371 // We're done, return false to abort. 500 // We're done, return false to abort.
372 return false; 501 return false;
373 } 502 }
374 503
375 void VideoSendStream::EncoderProcess() { 504 void VideoSendStream::EncoderProcess() {
505 RTC_CHECK_EQ(0, vie_encoder_.RegisterExternalEncoder(
506 config_.encoder_settings.encoder,
507 config_.encoder_settings.payload_type,
508 config_.encoder_settings.internal_source));
509
376 while (true) { 510 while (true) {
377 encoder_wakeup_event_.Wait(rtc::Event::kForever); 511 encoder_wakeup_event_.Wait(rtc::Event::kForever);
378 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_)) 512 if (rtc::AtomicOps::AcquireLoad(&stop_encoder_thread_))
379 return; 513 break;
514 rtc::Optional<EncoderSettings> encoder_settings;
515 {
516 rtc::CritScope lock(&encoder_settings_crit_);
517 if (pending_encoder_settings_) {
518 encoder_settings = pending_encoder_settings_;
519 pending_encoder_settings_ = rtc::Optional<EncoderSettings>();
520 }
521 }
522 if (encoder_settings) {
523 encoder_settings->video_codec.startBitrate =
524 bitrate_allocator_->AddObserver(
525 this, encoder_settings->video_codec.minBitrate * 1000,
526 encoder_settings->video_codec.maxBitrate * 1000) /
527 1000;
528 vie_encoder_.SetEncoder(encoder_settings->video_codec,
529 encoder_settings->min_transmit_bitrate_bps);
530 if (config_.suspend_below_min_bitrate) {
531 vcm_->SuspendBelowMinBitrate();
532 bitrate_allocator_->EnforceMinBitrate(false);
533 }
534 // We might've gotten new settings while configuring the encoder settings,
535 // restart from the top to see if that's the case before trying to encode
536 // a frame (which might correspond to the last frame size).
537 encoder_wakeup_event_.Set();
538 continue;
539 }
380 540
381 VideoFrame frame; 541 VideoFrame frame;
382 if (input_.GetVideoFrame(&frame)) 542 if (input_.GetVideoFrame(&frame))
383 vie_encoder_.EncodeVideoFrame(frame); 543 vie_encoder_.EncodeVideoFrame(frame);
384 } 544 }
545 vie_encoder_.DeRegisterExternalEncoder(config_.encoder_settings.payload_type);
385 } 546 }
386 547
387 void VideoSendStream::ReconfigureVideoEncoder( 548 void VideoSendStream::ReconfigureVideoEncoder(
388 const VideoEncoderConfig& config) { 549 const VideoEncoderConfig& config) {
389 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder"); 550 TRACE_EVENT0("webrtc", "VideoSendStream::(Re)configureVideoEncoder");
390 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString(); 551 LOG(LS_INFO) << "(Re)configureVideoEncoder: " << config.ToString();
391 const std::vector<VideoStream>& streams = config.streams; 552 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), config.streams.size());
392 static const int kEncoderMinBitrateKbps = 30; 553 VideoCodec video_codec = VideoEncoderConfigToVideoCodec(
393 RTC_DCHECK(!streams.empty()); 554 config, config_.encoder_settings.payload_name,
394 RTC_DCHECK_GE(config_.rtp.ssrcs.size(), streams.size()); 555 config_.encoder_settings.payload_type);
395 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); 556 {
396 557 rtc::CritScope lock(&encoder_settings_crit_);
397 VideoCodec video_codec; 558 pending_encoder_settings_ = rtc::Optional<EncoderSettings>(
398 memset(&video_codec, 0, sizeof(video_codec)); 559 {video_codec, config.min_transmit_bitrate_bps});
399 video_codec.codecType =
400 PayloadNameToCodecType(config_.encoder_settings.payload_name);
401
402 switch (config.content_type) {
403 case VideoEncoderConfig::ContentType::kRealtimeVideo:
404 video_codec.mode = kRealtimeVideo;
405 break;
406 case VideoEncoderConfig::ContentType::kScreen:
407 video_codec.mode = kScreensharing;
408 if (config.streams.size() == 1 &&
409 config.streams[0].temporal_layer_thresholds_bps.size() == 1) {
410 video_codec.targetBitrate =
411 config.streams[0].temporal_layer_thresholds_bps[0] / 1000;
412 }
413 break;
414 } 560 }
415 561 encoder_wakeup_event_.Set();
416 if (video_codec.codecType == kVideoCodecVP8) {
417 video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
418 } else if (video_codec.codecType == kVideoCodecVP9) {
419 video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
420 } else if (video_codec.codecType == kVideoCodecH264) {
421 video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
422 }
423
424 if (video_codec.codecType == kVideoCodecVP8) {
425 if (config.encoder_specific_settings != nullptr) {
426 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>(
427 config.encoder_specific_settings);
428 }
429 video_codec.codecSpecific.VP8.numberOfTemporalLayers =
430 static_cast<unsigned char>(
431 streams.back().temporal_layer_thresholds_bps.size() + 1);
432 } else if (video_codec.codecType == kVideoCodecVP9) {
433 if (config.encoder_specific_settings != nullptr) {
434 video_codec.codecSpecific.VP9 = *reinterpret_cast<const VideoCodecVP9*>(
435 config.encoder_specific_settings);
436 if (video_codec.mode == kScreensharing) {
437 video_codec.codecSpecific.VP9.flexibleMode = true;
438 // For now VP9 screensharing use 1 temporal and 2 spatial layers.
439 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfTemporalLayers, 1);
440 RTC_DCHECK_EQ(video_codec.codecSpecific.VP9.numberOfSpatialLayers, 2);
441 }
442 }
443 video_codec.codecSpecific.VP9.numberOfTemporalLayers =
444 static_cast<unsigned char>(
445 streams.back().temporal_layer_thresholds_bps.size() + 1);
446 } else if (video_codec.codecType == kVideoCodecH264) {
447 if (config.encoder_specific_settings != nullptr) {
448 video_codec.codecSpecific.H264 = *reinterpret_cast<const VideoCodecH264*>(
449 config.encoder_specific_settings);
450 }
451 } else {
452 // TODO(pbos): Support encoder_settings codec-agnostically.
453 RTC_DCHECK(config.encoder_specific_settings == nullptr)
454 << "Encoder-specific settings for codec type not wired up.";
455 }
456
457 strncpy(video_codec.plName,
458 config_.encoder_settings.payload_name.c_str(),
459 kPayloadNameSize - 1);
460 video_codec.plName[kPayloadNameSize - 1] = '\0';
461 video_codec.plType = config_.encoder_settings.payload_type;
462 video_codec.numberOfSimulcastStreams =
463 static_cast<unsigned char>(streams.size());
464 video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
465 if (video_codec.minBitrate < kEncoderMinBitrateKbps)
466 video_codec.minBitrate = kEncoderMinBitrateKbps;
467 RTC_DCHECK_LE(streams.size(), static_cast<size_t>(kMaxSimulcastStreams));
468 if (video_codec.codecType == kVideoCodecVP9) {
469 // If the vector is empty, bitrates will be configured automatically.
470 RTC_DCHECK(config.spatial_layers.empty() ||
471 config.spatial_layers.size() ==
472 video_codec.codecSpecific.VP9.numberOfSpatialLayers);
473 RTC_DCHECK_LE(video_codec.codecSpecific.VP9.numberOfSpatialLayers,
474 kMaxSimulcastStreams);
475 for (size_t i = 0; i < config.spatial_layers.size(); ++i)
476 video_codec.spatialLayers[i] = config.spatial_layers[i];
477 }
478 for (size_t i = 0; i < streams.size(); ++i) {
479 SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
480 RTC_DCHECK_GT(streams[i].width, 0u);
481 RTC_DCHECK_GT(streams[i].height, 0u);
482 RTC_DCHECK_GT(streams[i].max_framerate, 0);
483 // Different framerates not supported per stream at the moment.
484 RTC_DCHECK_EQ(streams[i].max_framerate, streams[0].max_framerate);
485 RTC_DCHECK_GE(streams[i].min_bitrate_bps, 0);
486 RTC_DCHECK_GE(streams[i].target_bitrate_bps, streams[i].min_bitrate_bps);
487 RTC_DCHECK_GE(streams[i].max_bitrate_bps, streams[i].target_bitrate_bps);
488 RTC_DCHECK_GE(streams[i].max_qp, 0);
489
490 sim_stream->width = static_cast<uint16_t>(streams[i].width);
491 sim_stream->height = static_cast<uint16_t>(streams[i].height);
492 sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
493 sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
494 sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
495 sim_stream->qpMax = streams[i].max_qp;
496 sim_stream->numberOfTemporalLayers = static_cast<unsigned char>(
497 streams[i].temporal_layer_thresholds_bps.size() + 1);
498
499 video_codec.width = std::max(video_codec.width,
500 static_cast<uint16_t>(streams[i].width));
501 video_codec.height = std::max(
502 video_codec.height, static_cast<uint16_t>(streams[i].height));
503 video_codec.minBitrate =
504 std::min(static_cast<uint16_t>(video_codec.minBitrate),
505 static_cast<uint16_t>(streams[i].min_bitrate_bps / 1000));
506 video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
507 video_codec.qpMax = std::max(video_codec.qpMax,
508 static_cast<unsigned int>(streams[i].max_qp));
509 }
510
511 if (video_codec.maxBitrate == 0) {
512 // Unset max bitrate -> cap to one bit per pixel.
513 video_codec.maxBitrate =
514 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
515 1000;
516 }
517 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
518 video_codec.maxBitrate = kEncoderMinBitrateKbps;
519
520 RTC_DCHECK_GT(streams[0].max_framerate, 0);
521 video_codec.maxFramerate = streams[0].max_framerate;
522
523 video_codec.startBitrate =
524 bitrate_allocator_->AddObserver(this,
525 video_codec.minBitrate * 1000,
526 video_codec.maxBitrate * 1000) / 1000;
527 vie_encoder_.SetEncoder(video_codec, config.min_transmit_bitrate_bps);
528 } 562 }
529 563
530 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) { 564 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
531 return vie_receiver_->DeliverRtcp(packet, length); 565 return vie_receiver_->DeliverRtcp(packet, length);
532 } 566 }
533 567
534 VideoSendStream::Stats VideoSendStream::GetStats() { 568 VideoSendStream::Stats VideoSendStream::GetStats() {
535 return stats_proxy_.GetStats(); 569 return stats_proxy_.GetStats();
536 } 570 }
537 571
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 658 }
625 659
626 void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps, 660 void VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps,
627 uint8_t fraction_loss, 661 uint8_t fraction_loss,
628 int64_t rtt) { 662 int64_t rtt) {
629 vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt); 663 vie_encoder_.OnBitrateUpdated(bitrate_bps, fraction_loss, rtt);
630 } 664 }
631 665
632 } // namespace internal 666 } // namespace internal
633 } // namespace webrtc 667 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/video_send_stream.h ('k') | webrtc/video/video_send_stream_tests.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698