OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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/media/engine/webrtcvideoengine2.h" | 11 #include "webrtc/media/engine/webrtcvideoengine2.h" |
12 | 12 |
13 #include <stdio.h> | 13 #include <stdio.h> |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <set> | 15 #include <set> |
16 #include <string> | 16 #include <string> |
17 #include <utility> | |
17 | 18 |
18 #include "webrtc/base/copyonwritebuffer.h" | 19 #include "webrtc/base/copyonwritebuffer.h" |
19 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
20 #include "webrtc/base/stringutils.h" | 21 #include "webrtc/base/stringutils.h" |
21 #include "webrtc/base/timeutils.h" | 22 #include "webrtc/base/timeutils.h" |
22 #include "webrtc/base/trace_event.h" | 23 #include "webrtc/base/trace_event.h" |
23 #include "webrtc/call.h" | 24 #include "webrtc/call.h" |
24 #include "webrtc/media/engine/constants.h" | 25 #include "webrtc/media/engine/constants.h" |
25 #include "webrtc/media/engine/simulcast.h" | 26 #include "webrtc/media/engine/simulcast.h" |
26 #include "webrtc/media/engine/webrtcmediaengine.h" | 27 #include "webrtc/media/engine/webrtcmediaengine.h" |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 } | 316 } |
316 | 317 |
317 int GetDefaultVp9TemporalLayers() { | 318 int GetDefaultVp9TemporalLayers() { |
318 int num_sl; | 319 int num_sl; |
319 int num_tl; | 320 int num_tl; |
320 if (GetVp9LayersFromFieldTrialGroup(&num_sl, &num_tl)) { | 321 if (GetVp9LayersFromFieldTrialGroup(&num_sl, &num_tl)) { |
321 return num_tl; | 322 return num_tl; |
322 } | 323 } |
323 return 1; | 324 return 1; |
324 } | 325 } |
326 | |
327 class EncoderStreamFactory | |
328 : public webrtc::VideoEncoderConfig::VideoStreamFactoryInterface { | |
329 public: | |
330 EncoderStreamFactory(std::string codec_name, | |
331 int max_qp, | |
332 int max_framerate, | |
333 bool is_screencast, | |
334 bool conference_mode) | |
335 : codec_name_(codec_name), | |
336 max_qp_(max_qp), | |
337 max_framerate_(max_framerate), | |
338 is_screencast_(is_screencast), | |
339 conference_mode_(conference_mode) {} | |
340 | |
341 private: | |
342 std::vector<webrtc::VideoStream> CreateEncoderStreams( | |
343 int width, | |
344 int height, | |
345 const webrtc::VideoEncoderConfig& encoder_config) override { | |
346 if (encoder_config.number_of_streams > 1) { | |
347 return GetSimulcastConfig(encoder_config.number_of_streams, width, height, | |
348 encoder_config.max_bitrate_bps, max_qp_, | |
349 max_framerate_); | |
350 } | |
351 | |
352 // For unset max bitrates set default bitrate for non-simulcast. | |
353 int max_bitrate_bps = | |
354 (encoder_config.max_bitrate_bps > 0) | |
355 ? encoder_config.max_bitrate_bps | |
356 : GetMaxDefaultVideoBitrateKbps(width, height) * 1000; | |
357 | |
358 webrtc::VideoStream stream; | |
359 stream.width = width; | |
360 stream.height = height; | |
361 stream.max_framerate = max_framerate_; | |
362 stream.min_bitrate_bps = kMinVideoBitrateKbps * 1000; | |
363 stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps; | |
364 stream.max_qp = max_qp_; | |
365 | |
366 // Conference mode screencast uses 2 temporal layers split at 100kbit. | |
367 if (conference_mode_ && is_screencast_) { | |
368 ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); | |
369 // For screenshare in conference mode, tl0 and tl1 bitrates are | |
370 // piggybacked | |
371 // on the VideoCodec struct as target and max bitrates, respectively. | |
372 // See eg. webrtc::VP8EncoderImpl::SetRates(). | |
373 stream.target_bitrate_bps = config.tl0_bitrate_kbps * 1000; | |
374 stream.max_bitrate_bps = config.tl1_bitrate_kbps * 1000; | |
375 stream.temporal_layer_thresholds_bps.clear(); | |
376 stream.temporal_layer_thresholds_bps.push_back(config.tl0_bitrate_kbps * | |
377 1000); | |
378 } | |
379 | |
380 if (CodecNamesEq(codec_name_, kVp9CodecName) && !is_screencast_) { | |
381 stream.temporal_layer_thresholds_bps.resize( | |
382 GetDefaultVp9TemporalLayers() - 1); | |
383 } | |
384 | |
385 std::vector<webrtc::VideoStream> streams; | |
386 streams.push_back(stream); | |
387 return streams; | |
388 } | |
389 | |
390 const std::string codec_name_; | |
391 const int max_qp_; | |
392 const int max_framerate_; | |
393 const bool is_screencast_; | |
394 const bool conference_mode_; | |
395 }; | |
396 | |
325 } // namespace | 397 } // namespace |
326 | 398 |
327 // Constants defined in webrtc/media/engine/constants.h | 399 // Constants defined in webrtc/media/engine/constants.h |
328 // TODO(pbos): Move these to a separate constants.cc file. | 400 // TODO(pbos): Move these to a separate constants.cc file. |
329 const int kMinVideoBitrate = 30; | 401 const int kMinVideoBitrateKbps = 30; |
330 const int kStartVideoBitrate = 300; | |
331 | 402 |
332 const int kVideoMtu = 1200; | 403 const int kVideoMtu = 1200; |
333 const int kVideoRtpBufferSize = 65536; | 404 const int kVideoRtpBufferSize = 65536; |
334 | 405 |
335 // This constant is really an on/off, lower-level configurable NACK history | 406 // This constant is really an on/off, lower-level configurable NACK history |
336 // duration hasn't been implemented. | 407 // duration hasn't been implemented. |
337 static const int kNackHistoryMs = 1000; | 408 static const int kNackHistoryMs = 1000; |
338 | 409 |
339 static const int kDefaultQpMax = 56; | 410 static const int kDefaultQpMax = 56; |
340 | 411 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); | 462 codec.SetParam(kH264FmtpLevelAsymmetryAllowed, "1"); |
392 codec.SetParam(kH264FmtpPacketizationMode, "1"); | 463 codec.SetParam(kH264FmtpPacketizationMode, "1"); |
393 AddCodecAndMaybeRtxCodec(codec, &codecs); | 464 AddCodecAndMaybeRtxCodec(codec, &codecs); |
394 } | 465 } |
395 AddCodecAndMaybeRtxCodec(VideoCodec(kDefaultRedPlType, kRedCodecName), | 466 AddCodecAndMaybeRtxCodec(VideoCodec(kDefaultRedPlType, kRedCodecName), |
396 &codecs); | 467 &codecs); |
397 codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); | 468 codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); |
398 return codecs; | 469 return codecs; |
399 } | 470 } |
400 | 471 |
401 std::vector<webrtc::VideoStream> | |
402 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams( | |
403 const VideoCodec& codec, | |
404 const VideoOptions& options, | |
405 int max_bitrate_bps, | |
406 size_t num_streams) { | |
407 int max_qp = kDefaultQpMax; | |
408 codec.GetParam(kCodecParamMaxQuantization, &max_qp); | |
409 | |
410 return GetSimulcastConfig( | |
411 num_streams, codec.width, codec.height, max_bitrate_bps, max_qp, | |
412 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate); | |
413 } | |
414 | |
415 std::vector<webrtc::VideoStream> | |
416 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams( | |
417 const VideoCodec& codec, | |
418 const VideoOptions& options, | |
419 int max_bitrate_bps, | |
420 size_t num_streams) { | |
421 int codec_max_bitrate_kbps; | |
422 if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) { | |
423 max_bitrate_bps = codec_max_bitrate_kbps * 1000; | |
424 } | |
425 if (num_streams != 1) { | |
426 return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps, | |
427 num_streams); | |
428 } | |
429 | |
430 // For unset max bitrates set default bitrate for non-simulcast. | |
431 if (max_bitrate_bps <= 0) { | |
432 max_bitrate_bps = | |
433 GetMaxDefaultVideoBitrateKbps(codec.width, codec.height) * 1000; | |
434 } | |
435 | |
436 webrtc::VideoStream stream; | |
437 stream.width = codec.width; | |
438 stream.height = codec.height; | |
439 stream.max_framerate = | |
440 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate; | |
441 | |
442 stream.min_bitrate_bps = kMinVideoBitrate * 1000; | |
443 stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps; | |
444 | |
445 int max_qp = kDefaultQpMax; | |
446 codec.GetParam(kCodecParamMaxQuantization, &max_qp); | |
447 stream.max_qp = max_qp; | |
448 std::vector<webrtc::VideoStream> streams; | |
449 streams.push_back(stream); | |
450 return streams; | |
451 } | |
452 | |
453 void* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( | 472 void* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( |
454 const VideoCodec& codec) { | 473 const VideoCodec& codec) { |
474 RTC_DCHECK_RUN_ON(&thread_checker_); | |
455 bool is_screencast = parameters_.options.is_screencast.value_or(false); | 475 bool is_screencast = parameters_.options.is_screencast.value_or(false); |
456 // No automatic resizing when using simulcast or screencast. | 476 // No automatic resizing when using simulcast or screencast. |
457 bool automatic_resize = | 477 bool automatic_resize = |
458 !is_screencast && parameters_.config.rtp.ssrcs.size() == 1; | 478 !is_screencast && parameters_.config.rtp.ssrcs.size() == 1; |
459 bool frame_dropping = !is_screencast; | 479 bool frame_dropping = !is_screencast; |
460 bool denoising; | 480 bool denoising; |
461 bool codec_default_denoising = false; | 481 bool codec_default_denoising = false; |
462 if (is_screencast) { | 482 if (is_screencast) { |
463 denoising = false; | 483 denoising = false; |
464 } else { | 484 } else { |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1532 | 1552 |
1533 WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: | 1553 WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: |
1534 VideoSendStreamParameters( | 1554 VideoSendStreamParameters( |
1535 webrtc::VideoSendStream::Config config, | 1555 webrtc::VideoSendStream::Config config, |
1536 const VideoOptions& options, | 1556 const VideoOptions& options, |
1537 int max_bitrate_bps, | 1557 int max_bitrate_bps, |
1538 const rtc::Optional<VideoCodecSettings>& codec_settings) | 1558 const rtc::Optional<VideoCodecSettings>& codec_settings) |
1539 : config(std::move(config)), | 1559 : config(std::move(config)), |
1540 options(options), | 1560 options(options), |
1541 max_bitrate_bps(max_bitrate_bps), | 1561 max_bitrate_bps(max_bitrate_bps), |
1562 conference_mode(false), | |
1542 codec_settings(codec_settings) {} | 1563 codec_settings(codec_settings) {} |
1543 | 1564 |
1544 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder( | 1565 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder( |
1545 webrtc::VideoEncoder* encoder, | 1566 webrtc::VideoEncoder* encoder, |
1546 webrtc::VideoCodecType type, | 1567 webrtc::VideoCodecType type, |
1547 bool external) | 1568 bool external) |
1548 : encoder(encoder), | 1569 : encoder(encoder), |
1549 external_encoder(nullptr), | 1570 external_encoder(nullptr), |
1550 type(type), | 1571 type(type), |
1551 external(external) { | 1572 external(external) { |
(...skipping 24 matching lines...) Expand all Loading... | |
1576 cpu_restricted_counter_(0), | 1597 cpu_restricted_counter_(0), |
1577 number_of_cpu_adapt_changes_(0), | 1598 number_of_cpu_adapt_changes_(0), |
1578 frame_count_(0), | 1599 frame_count_(0), |
1579 cpu_restricted_frame_count_(0), | 1600 cpu_restricted_frame_count_(0), |
1580 source_(nullptr), | 1601 source_(nullptr), |
1581 external_encoder_factory_(external_encoder_factory), | 1602 external_encoder_factory_(external_encoder_factory), |
1582 stream_(nullptr), | 1603 stream_(nullptr), |
1583 encoder_sink_(nullptr), | 1604 encoder_sink_(nullptr), |
1584 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), | 1605 parameters_(std::move(config), options, max_bitrate_bps, codec_settings), |
1585 rtp_parameters_(CreateRtpParametersWithOneEncoding()), | 1606 rtp_parameters_(CreateRtpParametersWithOneEncoding()), |
1586 pending_encoder_reconfiguration_(false), | |
1587 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), | 1607 allocated_encoder_(nullptr, webrtc::kVideoCodecUnknown, false), |
1588 sending_(false), | 1608 sending_(false), |
1589 last_frame_timestamp_us_(0) { | 1609 last_frame_timestamp_us_(0) { |
1590 parameters_.config.rtp.max_packet_size = kVideoMtu; | 1610 parameters_.config.rtp.max_packet_size = kVideoMtu; |
1591 parameters_.conference_mode = send_params.conference_mode; | 1611 parameters_.conference_mode = send_params.conference_mode; |
1592 | 1612 |
1593 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); | 1613 sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |
1594 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, | 1614 sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |
1595 ¶meters_.config.rtp.rtx.ssrcs); | 1615 ¶meters_.config.rtp.rtx.ssrcs); |
1596 parameters_.config.rtp.c_name = sp.cname; | 1616 parameters_.config.rtp.c_name = sp.cname; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1644 rtc::CritScope cs(&lock_); | 1664 rtc::CritScope cs(&lock_); |
1645 | 1665 |
1646 if (video_frame.width() != last_frame_info_.width || | 1666 if (video_frame.width() != last_frame_info_.width || |
1647 video_frame.height() != last_frame_info_.height || | 1667 video_frame.height() != last_frame_info_.height || |
1648 video_frame.rotation() != last_frame_info_.rotation || | 1668 video_frame.rotation() != last_frame_info_.rotation || |
1649 video_frame.is_texture() != last_frame_info_.is_texture) { | 1669 video_frame.is_texture() != last_frame_info_.is_texture) { |
1650 last_frame_info_.width = video_frame.width(); | 1670 last_frame_info_.width = video_frame.width(); |
1651 last_frame_info_.height = video_frame.height(); | 1671 last_frame_info_.height = video_frame.height(); |
1652 last_frame_info_.rotation = video_frame.rotation(); | 1672 last_frame_info_.rotation = video_frame.rotation(); |
1653 last_frame_info_.is_texture = video_frame.is_texture(); | 1673 last_frame_info_.is_texture = video_frame.is_texture(); |
1654 pending_encoder_reconfiguration_ = true; | |
1655 | 1674 |
1656 LOG(LS_INFO) << "Video frame parameters changed: dimensions=" | 1675 LOG(LS_INFO) << "Video frame parameters changed: dimensions=" |
1657 << last_frame_info_.width << "x" << last_frame_info_.height | 1676 << last_frame_info_.width << "x" << last_frame_info_.height |
1658 << ", rotation=" << last_frame_info_.rotation | 1677 << ", rotation=" << last_frame_info_.rotation |
1659 << ", texture=" << last_frame_info_.is_texture; | 1678 << ", texture=" << last_frame_info_.is_texture; |
1660 } | 1679 } |
1661 | 1680 |
1662 if (encoder_sink_ == NULL) { | 1681 if (encoder_sink_ == NULL) { |
1663 // Frame input before send codecs are configured, dropping frame. | 1682 // Frame input before send codecs are configured, dropping frame. |
1664 return; | 1683 return; |
1665 } | 1684 } |
1666 | 1685 |
1667 last_frame_timestamp_us_ = video_frame.timestamp_us(); | 1686 last_frame_timestamp_us_ = video_frame.timestamp_us(); |
1668 | 1687 |
1669 if (pending_encoder_reconfiguration_) { | |
1670 ReconfigureEncoder(); | |
1671 pending_encoder_reconfiguration_ = false; | |
1672 } | |
1673 | |
1674 // Not sending, abort after reconfiguration. Reconfiguration should still | |
1675 // occur to permit sending this input as quickly as possible once we start | |
1676 // sending (without having to reconfigure then). | |
1677 if (!sending_) { | |
1678 return; | |
1679 } | |
1680 | |
1681 ++frame_count_; | 1688 ++frame_count_; |
1682 if (cpu_restricted_counter_ > 0) | 1689 if (cpu_restricted_counter_ > 0) |
1683 ++cpu_restricted_frame_count_; | 1690 ++cpu_restricted_frame_count_; |
1684 | 1691 |
1692 // Forward frame to the encoder regardless if we are sending or not. This is | |
1693 // to ensure that the encoder can be reconfigured with the correct frame size | |
1694 // as quickly as possible. | |
1685 encoder_sink_->OnFrame(video_frame); | 1695 encoder_sink_->OnFrame(video_frame); |
1686 } | 1696 } |
1687 | 1697 |
1688 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( | 1698 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoSend( |
1689 bool enable, | 1699 bool enable, |
1690 const VideoOptions* options, | 1700 const VideoOptions* options, |
1691 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { | 1701 rtc::VideoSourceInterface<cricket::VideoFrame>* source) { |
1692 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); | 1702 TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetVideoSend"); |
1693 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1703 RTC_DCHECK_RUN_ON(&thread_checker_); |
1694 | 1704 |
1695 // Ignore |options| pointer if |enable| is false. | 1705 // Ignore |options| pointer if |enable| is false. |
1696 bool options_present = enable && options; | 1706 bool options_present = enable && options; |
1697 bool source_changing = source_ != source; | 1707 bool source_changing = source_ != source; |
1698 if (source_changing) { | 1708 if (source_changing) { |
1699 DisconnectSource(); | 1709 DisconnectSource(); |
1700 } | 1710 } |
1701 | 1711 |
1702 if (options_present || source_changing) { | 1712 if (options_present || source_changing) { |
sprang_webrtc
2016/09/22 13:06:16
This looks redundant?
perkj_webrtc
2016/09/26 12:09:42
Done.
| |
1703 rtc::CritScope cs(&lock_); | |
1704 | |
1705 if (options_present) { | 1713 if (options_present) { |
1706 VideoOptions old_options = parameters_.options; | 1714 VideoOptions old_options = parameters_.options; |
1707 parameters_.options.SetAll(*options); | 1715 parameters_.options.SetAll(*options); |
1708 // Reconfigure encoder settings on the next frame or stream | 1716 // If options has changed and SetCodec has been called. |
1709 // recreation if the options changed. | 1717 if (parameters_.options != old_options && stream_) { |
1710 if (parameters_.options != old_options) { | 1718 ReconfigureEncoder(); |
1711 pending_encoder_reconfiguration_ = true; | |
1712 } | 1719 } |
1713 } | 1720 } |
1714 | 1721 |
1715 if (source_changing) { | 1722 if (source_changing) { |
1716 if (source == nullptr && encoder_sink_ != nullptr) { | 1723 rtc::CritScope cs(&lock_); |
1724 if (source == nullptr && encoder_sink_ != nullptr && | |
1725 last_frame_info_.width > 0) { | |
1717 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; | 1726 LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; |
1718 // Force this black frame not to be dropped due to timestamp order | 1727 // Force this black frame not to be dropped due to timestamp order |
1719 // check. As IncomingCapturedFrame will drop the frame if this frame's | 1728 // check. As IncomingCapturedFrame will drop the frame if this frame's |
1720 // timestamp is less than or equal to last frame's timestamp, it is | 1729 // timestamp is less than or equal to last frame's timestamp, it is |
1721 // necessary to give this black frame a larger timestamp than the | 1730 // necessary to give this black frame a larger timestamp than the |
1722 // previous one. | 1731 // previous one. |
1723 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; | 1732 last_frame_timestamp_us_ += rtc::kNumMicrosecsPerMillisec; |
1724 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( | 1733 rtc::scoped_refptr<webrtc::I420Buffer> black_buffer( |
1725 webrtc::I420Buffer::Create(last_frame_info_.width, | 1734 webrtc::I420Buffer::Create(last_frame_info_.width, |
1726 last_frame_info_.height)); | 1735 last_frame_info_.height)); |
1727 black_buffer->SetToBlack(); | 1736 black_buffer->SetToBlack(); |
1728 | 1737 |
1729 encoder_sink_->OnFrame(webrtc::VideoFrame( | 1738 encoder_sink_->OnFrame(webrtc::VideoFrame( |
1730 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); | 1739 black_buffer, last_frame_info_.rotation, last_frame_timestamp_us_)); |
1731 } | 1740 } |
1732 source_ = source; | 1741 source_ = source; |
1733 } | 1742 } |
1734 } | 1743 } |
1735 | 1744 |
1736 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | |
1737 // that might cause a lock order inversion. | |
1738 if (source_changing && source_) { | 1745 if (source_changing && source_) { |
1746 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | |
1747 // that might cause a lock order inversion. | |
1739 source_->AddOrUpdateSink(this, sink_wants_); | 1748 source_->AddOrUpdateSink(this, sink_wants_); |
1740 } | 1749 } |
1741 return true; | 1750 return true; |
1742 } | 1751 } |
1743 | 1752 |
1744 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { | 1753 void WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectSource() { |
1745 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 1754 RTC_DCHECK_RUN_ON(&thread_checker_); |
1746 if (source_ == nullptr) { | 1755 if (source_ == nullptr) { |
1747 return; | 1756 return; |
1748 } | 1757 } |
1749 | 1758 |
1750 // |source_->RemoveSink| may not be called while holding |lock_| since | 1759 // |source_->RemoveSink| may not be called while holding |lock_| since |
1751 // that might cause a lock order inversion. | 1760 // that might cause a lock order inversion. |
1752 source_->RemoveSink(this); | 1761 source_->RemoveSink(this); |
1753 source_ = nullptr; | 1762 source_ = nullptr; |
1754 // Reset |cpu_restricted_counter_| if the source is changed. It is not | 1763 // Reset |cpu_restricted_counter_| if the source is changed. It is not |
1755 // possible to know if the video resolution is restricted by CPU usage after | 1764 // possible to know if the video resolution is restricted by CPU usage after |
(...skipping 14 matching lines...) Expand all Loading... | |
1770 return webrtc::kVideoCodecVP9; | 1779 return webrtc::kVideoCodecVP9; |
1771 } else if (CodecNamesEq(name, kH264CodecName)) { | 1780 } else if (CodecNamesEq(name, kH264CodecName)) { |
1772 return webrtc::kVideoCodecH264; | 1781 return webrtc::kVideoCodecH264; |
1773 } | 1782 } |
1774 return webrtc::kVideoCodecUnknown; | 1783 return webrtc::kVideoCodecUnknown; |
1775 } | 1784 } |
1776 | 1785 |
1777 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder | 1786 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder |
1778 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( | 1787 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( |
1779 const VideoCodec& codec) { | 1788 const VideoCodec& codec) { |
1789 RTC_DCHECK_RUN_ON(&thread_checker_); | |
1780 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); | 1790 webrtc::VideoCodecType type = CodecTypeFromName(codec.name); |
1781 | 1791 |
1782 // Do not re-create encoders of the same type. | 1792 // Do not re-create encoders of the same type. |
1783 if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { | 1793 if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { |
1784 return allocated_encoder_; | 1794 return allocated_encoder_; |
1785 } | 1795 } |
1786 | 1796 |
1787 if (external_encoder_factory_ != NULL) { | 1797 if (external_encoder_factory_ != NULL) { |
1788 webrtc::VideoEncoder* encoder = | 1798 webrtc::VideoEncoder* encoder = |
1789 external_encoder_factory_->CreateVideoEncoder(type); | 1799 external_encoder_factory_->CreateVideoEncoder(type); |
(...skipping 14 matching lines...) Expand all Loading... | |
1804 } | 1814 } |
1805 | 1815 |
1806 // This shouldn't happen, we should not be trying to create something we don't | 1816 // This shouldn't happen, we should not be trying to create something we don't |
1807 // support. | 1817 // support. |
1808 RTC_DCHECK(false); | 1818 RTC_DCHECK(false); |
1809 return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); | 1819 return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); |
1810 } | 1820 } |
1811 | 1821 |
1812 void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( | 1822 void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( |
1813 AllocatedEncoder* encoder) { | 1823 AllocatedEncoder* encoder) { |
1824 RTC_DCHECK_RUN_ON(&thread_checker_); | |
1814 if (encoder->external) { | 1825 if (encoder->external) { |
1815 external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder); | 1826 external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder); |
1816 } | 1827 } |
1817 delete encoder->encoder; | 1828 delete encoder->encoder; |
1818 } | 1829 } |
1819 | 1830 |
1820 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( | 1831 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( |
1821 const VideoCodecSettings& codec_settings) { | 1832 const VideoCodecSettings& codec_settings) { |
1833 RTC_DCHECK_RUN_ON(&thread_checker_); | |
1822 parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec); | 1834 parameters_.encoder_config = CreateVideoEncoderConfig(codec_settings.codec); |
1823 RTC_DCHECK(!parameters_.encoder_config.streams.empty()); | 1835 RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u); |
1824 | 1836 |
1825 AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); | 1837 AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); |
1826 parameters_.config.encoder_settings.encoder = new_encoder.encoder; | 1838 parameters_.config.encoder_settings.encoder = new_encoder.encoder; |
1827 parameters_.config.encoder_settings.full_overuse_time = new_encoder.external; | 1839 parameters_.config.encoder_settings.full_overuse_time = new_encoder.external; |
1828 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; | 1840 parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; |
1829 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; | 1841 parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; |
1830 if (new_encoder.external) { | 1842 if (new_encoder.external) { |
1831 webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); | 1843 webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); |
1832 parameters_.config.encoder_settings.internal_source = | 1844 parameters_.config.encoder_settings.internal_source = |
1833 external_encoder_factory_->EncoderTypeHasInternalSource(type); | 1845 external_encoder_factory_->EncoderTypeHasInternalSource(type); |
(...skipping 20 matching lines...) Expand all Loading... | |
1854 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec."; | 1866 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetCodec."; |
1855 RecreateWebRtcStream(); | 1867 RecreateWebRtcStream(); |
1856 if (allocated_encoder_.encoder != new_encoder.encoder) { | 1868 if (allocated_encoder_.encoder != new_encoder.encoder) { |
1857 DestroyVideoEncoder(&allocated_encoder_); | 1869 DestroyVideoEncoder(&allocated_encoder_); |
1858 allocated_encoder_ = new_encoder; | 1870 allocated_encoder_ = new_encoder; |
1859 } | 1871 } |
1860 } | 1872 } |
1861 | 1873 |
1862 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters( | 1874 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters( |
1863 const ChangedSendParameters& params) { | 1875 const ChangedSendParameters& params) { |
1864 { | 1876 RTC_DCHECK_RUN_ON(&thread_checker_); |
1865 rtc::CritScope cs(&lock_); | 1877 // |recreate_stream| means construction-time parameters have changed and the |
1866 // |recreate_stream| means construction-time parameters have changed and the | 1878 // sending stream needs to be reset with the new config. |
1867 // sending stream needs to be reset with the new config. | 1879 bool recreate_stream = false; |
1868 bool recreate_stream = false; | 1880 if (params.rtcp_mode) { |
1869 if (params.rtcp_mode) { | 1881 parameters_.config.rtp.rtcp_mode = *params.rtcp_mode; |
1870 parameters_.config.rtp.rtcp_mode = *params.rtcp_mode; | 1882 recreate_stream = true; |
1871 recreate_stream = true; | 1883 } |
1872 } | 1884 if (params.rtp_header_extensions) { |
1873 if (params.rtp_header_extensions) { | 1885 parameters_.config.rtp.extensions = *params.rtp_header_extensions; |
1874 parameters_.config.rtp.extensions = *params.rtp_header_extensions; | 1886 recreate_stream = true; |
1875 recreate_stream = true; | 1887 } |
1876 } | 1888 if (params.max_bandwidth_bps) { |
1877 if (params.max_bandwidth_bps) { | 1889 parameters_.max_bitrate_bps = *params.max_bandwidth_bps; |
1878 parameters_.max_bitrate_bps = *params.max_bandwidth_bps; | 1890 ReconfigureEncoder(); |
1879 pending_encoder_reconfiguration_ = true; | 1891 } |
1880 } | 1892 if (params.conference_mode) { |
1881 if (params.conference_mode) { | 1893 parameters_.conference_mode = *params.conference_mode; |
1882 parameters_.conference_mode = *params.conference_mode; | 1894 } |
1883 } | |
1884 | 1895 |
1885 // Set codecs and options. | 1896 // Set codecs and options. |
1886 if (params.codec) { | 1897 if (params.codec) { |
1887 SetCodec(*params.codec); | 1898 SetCodec(*params.codec); |
1888 recreate_stream = false; // SetCodec has already recreated the stream. | 1899 recreate_stream = false; // SetCodec has already recreated the stream. |
1889 } else if (params.conference_mode && parameters_.codec_settings) { | 1900 } else if (params.conference_mode && parameters_.codec_settings) { |
1890 SetCodec(*parameters_.codec_settings); | 1901 SetCodec(*parameters_.codec_settings); |
1891 recreate_stream = false; // SetCodec has already recreated the stream. | 1902 recreate_stream = false; // SetCodec has already recreated the stream. |
1892 } | 1903 } |
1893 if (recreate_stream) { | 1904 if (recreate_stream) { |
1894 LOG(LS_INFO) | 1905 LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; |
1895 << "RecreateWebRtcStream (send) because of SetSendParameters"; | 1906 RecreateWebRtcStream(); |
1896 RecreateWebRtcStream(); | 1907 } |
1897 } | |
1898 } // release |lock_| | |
1899 | 1908 |
1900 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 1909 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since |
1901 // that might cause a lock order inversion. | 1910 // that might cause a lock order inversion. |
1902 if (params.rtp_header_extensions) { | 1911 if (params.rtp_header_extensions) { |
1903 sink_wants_.rotation_applied = !ContainsHeaderExtension( | 1912 sink_wants_.rotation_applied = !ContainsHeaderExtension( |
1904 *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri); | 1913 *params.rtp_header_extensions, webrtc::RtpExtension::kVideoRotationUri); |
1905 if (source_) { | 1914 if (source_) { |
1906 source_->AddOrUpdateSink(this, sink_wants_); | 1915 source_->AddOrUpdateSink(this, sink_wants_); |
1907 } | 1916 } |
1908 } | 1917 } |
1909 } | 1918 } |
1910 | 1919 |
1911 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( | 1920 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpParameters( |
1912 const webrtc::RtpParameters& new_parameters) { | 1921 const webrtc::RtpParameters& new_parameters) { |
1922 RTC_DCHECK_RUN_ON(&thread_checker_); | |
1913 if (!ValidateRtpParameters(new_parameters)) { | 1923 if (!ValidateRtpParameters(new_parameters)) { |
1914 return false; | 1924 return false; |
1915 } | 1925 } |
1916 | 1926 |
1917 rtc::CritScope cs(&lock_); | 1927 bool reconfigure_encoder = new_parameters.encodings[0].max_bitrate_bps != |
1918 if (new_parameters.encodings[0].max_bitrate_bps != | 1928 rtp_parameters_.encodings[0].max_bitrate_bps; |
1919 rtp_parameters_.encodings[0].max_bitrate_bps) { | |
1920 pending_encoder_reconfiguration_ = true; | |
1921 } | |
1922 rtp_parameters_ = new_parameters; | 1929 rtp_parameters_ = new_parameters; |
1923 // Codecs are currently handled at the WebRtcVideoChannel2 level. | 1930 // Codecs are currently handled at the WebRtcVideoChannel2 level. |
1924 rtp_parameters_.codecs.clear(); | 1931 rtp_parameters_.codecs.clear(); |
1932 if (reconfigure_encoder) { | |
1933 ReconfigureEncoder(); | |
1934 } | |
1925 // Encoding may have been activated/deactivated. | 1935 // Encoding may have been activated/deactivated. |
1926 UpdateSendState(); | 1936 UpdateSendState(); |
1927 return true; | 1937 return true; |
1928 } | 1938 } |
1929 | 1939 |
1930 webrtc::RtpParameters | 1940 webrtc::RtpParameters |
1931 WebRtcVideoChannel2::WebRtcVideoSendStream::GetRtpParameters() const { | 1941 WebRtcVideoChannel2::WebRtcVideoSendStream::GetRtpParameters() const { |
1932 rtc::CritScope cs(&lock_); | 1942 RTC_DCHECK_RUN_ON(&thread_checker_); |
1933 return rtp_parameters_; | 1943 return rtp_parameters_; |
1934 } | 1944 } |
1935 | 1945 |
1936 bool WebRtcVideoChannel2::WebRtcVideoSendStream::ValidateRtpParameters( | 1946 bool WebRtcVideoChannel2::WebRtcVideoSendStream::ValidateRtpParameters( |
1937 const webrtc::RtpParameters& rtp_parameters) { | 1947 const webrtc::RtpParameters& rtp_parameters) { |
1938 if (rtp_parameters.encodings.size() != 1) { | 1948 if (rtp_parameters.encodings.size() != 1) { |
1939 LOG(LS_ERROR) | 1949 LOG(LS_ERROR) |
1940 << "Attempted to set RtpParameters without exactly one encoding"; | 1950 << "Attempted to set RtpParameters without exactly one encoding"; |
1941 return false; | 1951 return false; |
1942 } | 1952 } |
1943 return true; | 1953 return true; |
1944 } | 1954 } |
1945 | 1955 |
1946 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() { | 1956 void WebRtcVideoChannel2::WebRtcVideoSendStream::UpdateSendState() { |
1957 RTC_DCHECK_RUN_ON(&thread_checker_); | |
1947 // TODO(deadbeef): Need to handle more than one encoding in the future. | 1958 // TODO(deadbeef): Need to handle more than one encoding in the future. |
1948 RTC_DCHECK(rtp_parameters_.encodings.size() == 1u); | 1959 RTC_DCHECK(rtp_parameters_.encodings.size() == 1u); |
1949 if (sending_ && rtp_parameters_.encodings[0].active) { | 1960 if (sending_ && rtp_parameters_.encodings[0].active) { |
1950 RTC_DCHECK(stream_ != nullptr); | 1961 RTC_DCHECK(stream_ != nullptr); |
1951 stream_->Start(); | 1962 stream_->Start(); |
1952 } else { | 1963 } else { |
1953 if (stream_ != nullptr) { | 1964 if (stream_ != nullptr) { |
1954 stream_->Stop(); | 1965 stream_->Stop(); |
1955 } | 1966 } |
1956 } | 1967 } |
1957 } | 1968 } |
1958 | 1969 |
1959 webrtc::VideoEncoderConfig | 1970 webrtc::VideoEncoderConfig |
1960 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( | 1971 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( |
1961 const VideoCodec& codec) const { | 1972 const VideoCodec& codec) const { |
1973 RTC_DCHECK_RUN_ON(&thread_checker_); | |
1962 webrtc::VideoEncoderConfig encoder_config; | 1974 webrtc::VideoEncoderConfig encoder_config; |
1963 bool is_screencast = parameters_.options.is_screencast.value_or(false); | 1975 bool is_screencast = parameters_.options.is_screencast.value_or(false); |
1964 if (is_screencast) { | 1976 if (is_screencast) { |
1965 encoder_config.min_transmit_bitrate_bps = | 1977 encoder_config.min_transmit_bitrate_bps = |
1966 1000 * parameters_.options.screencast_min_bitrate_kbps.value_or(0); | 1978 1000 * parameters_.options.screencast_min_bitrate_kbps.value_or(0); |
1967 encoder_config.content_type = | 1979 encoder_config.content_type = |
1968 webrtc::VideoEncoderConfig::ContentType::kScreen; | 1980 webrtc::VideoEncoderConfig::ContentType::kScreen; |
1969 } else { | 1981 } else { |
1970 encoder_config.min_transmit_bitrate_bps = 0; | 1982 encoder_config.min_transmit_bitrate_bps = 0; |
1971 encoder_config.content_type = | 1983 encoder_config.content_type = |
1972 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo; | 1984 webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo; |
1973 } | 1985 } |
1974 | 1986 |
1975 // Restrict dimensions according to codec max. | |
1976 int width = last_frame_info_.width; | |
1977 int height = last_frame_info_.height; | |
1978 if (!is_screencast) { | |
1979 if (codec.width < width) | |
1980 width = codec.width; | |
1981 if (codec.height < height) | |
1982 height = codec.height; | |
1983 } | |
1984 | |
1985 VideoCodec clamped_codec = codec; | |
1986 clamped_codec.width = width; | |
1987 clamped_codec.height = height; | |
1988 | |
1989 // By default, the stream count for the codec configuration should match the | 1987 // By default, the stream count for the codec configuration should match the |
1990 // number of negotiated ssrcs. But if the codec is blacklisted for simulcast | 1988 // number of negotiated ssrcs. But if the codec is blacklisted for simulcast |
1991 // or a screencast, only configure a single stream. | 1989 // or a screencast, only configure a single stream. |
1992 size_t stream_count = parameters_.config.rtp.ssrcs.size(); | 1990 encoder_config.number_of_streams = parameters_.config.rtp.ssrcs.size(); |
1993 if (IsCodecBlacklistedForSimulcast(codec.name) || is_screencast) { | 1991 if (IsCodecBlacklistedForSimulcast(codec.name) || is_screencast) { |
1994 stream_count = 1; | 1992 encoder_config.number_of_streams = 1; |
1995 } | 1993 } |
1996 | 1994 |
1997 int stream_max_bitrate = | 1995 int stream_max_bitrate = |
1998 MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps, | 1996 MinPositive(rtp_parameters_.encodings[0].max_bitrate_bps, |
1999 parameters_.max_bitrate_bps); | 1997 parameters_.max_bitrate_bps); |
2000 encoder_config.streams = CreateVideoStreams( | |
2001 clamped_codec, parameters_.options, stream_max_bitrate, stream_count); | |
2002 encoder_config.expect_encode_from_texture = last_frame_info_.is_texture; | |
2003 | 1998 |
2004 // Conference mode screencast uses 2 temporal layers split at 100kbit. | 1999 int codec_max_bitrate_kbps; |
2005 if (parameters_.conference_mode && is_screencast && | 2000 if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) { |
2006 encoder_config.streams.size() == 1) { | 2001 stream_max_bitrate = codec_max_bitrate_kbps * 1000; |
2007 ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); | 2002 } |
2003 encoder_config.max_bitrate_bps = stream_max_bitrate; | |
2008 | 2004 |
2009 // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked | 2005 int max_qp = kDefaultQpMax; |
2010 // on the VideoCodec struct as target and max bitrates, respectively. | 2006 codec.GetParam(kCodecParamMaxQuantization, &max_qp); |
2011 // See eg. webrtc::VP8EncoderImpl::SetRates(). | 2007 int max_framerate = |
2012 encoder_config.streams[0].target_bitrate_bps = | 2008 codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate; |
2013 config.tl0_bitrate_kbps * 1000; | 2009 |
2014 encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000; | 2010 encoder_config.encoder_stream_factory = |
2015 encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); | 2011 new rtc::RefCountedObject<EncoderStreamFactory>( |
2016 encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( | 2012 codec.name, max_qp, max_framerate, is_screencast, |
2017 config.tl0_bitrate_kbps * 1000); | 2013 parameters_.conference_mode); |
2018 } | |
2019 if (CodecNamesEq(codec.name, kVp9CodecName) && !is_screencast && | |
2020 encoder_config.streams.size() == 1) { | |
2021 encoder_config.streams[0].temporal_layer_thresholds_bps.resize( | |
2022 GetDefaultVp9TemporalLayers() - 1); | |
2023 } | |
2024 return encoder_config; | 2014 return encoder_config; |
2025 } | 2015 } |
2026 | 2016 |
2027 void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() { | 2017 void WebRtcVideoChannel2::WebRtcVideoSendStream::ReconfigureEncoder() { |
2028 RTC_DCHECK(!parameters_.encoder_config.streams.empty()); | 2018 RTC_DCHECK_RUN_ON(&thread_checker_); |
2019 RTC_DCHECK_GT(parameters_.encoder_config.number_of_streams, 0u); | |
2029 | 2020 |
2030 RTC_CHECK(parameters_.codec_settings); | 2021 RTC_CHECK(parameters_.codec_settings); |
2031 VideoCodecSettings codec_settings = *parameters_.codec_settings; | 2022 VideoCodecSettings codec_settings = *parameters_.codec_settings; |
2032 | 2023 |
2033 webrtc::VideoEncoderConfig encoder_config = | 2024 webrtc::VideoEncoderConfig encoder_config = |
2034 CreateVideoEncoderConfig(codec_settings.codec); | 2025 CreateVideoEncoderConfig(codec_settings.codec); |
2035 | 2026 |
2036 encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings( | 2027 encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings( |
2037 codec_settings.codec); | 2028 codec_settings.codec); |
2038 | 2029 |
2039 stream_->ReconfigureVideoEncoder(encoder_config.Copy()); | 2030 stream_->ReconfigureVideoEncoder(encoder_config.Copy()); |
2040 | 2031 |
2041 encoder_config.encoder_specific_settings = NULL; | 2032 encoder_config.encoder_specific_settings = NULL; |
2042 | 2033 |
2043 parameters_.encoder_config = std::move(encoder_config); | 2034 parameters_.encoder_config = std::move(encoder_config); |
2044 } | 2035 } |
2045 | 2036 |
2046 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { | 2037 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSend(bool send) { |
2047 rtc::CritScope cs(&lock_); | 2038 RTC_DCHECK_RUN_ON(&thread_checker_); |
2048 sending_ = send; | 2039 sending_ = send; |
2049 UpdateSendState(); | 2040 UpdateSendState(); |
2050 } | 2041 } |
2051 | 2042 |
2052 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( | 2043 void WebRtcVideoChannel2::WebRtcVideoSendStream::AddOrUpdateSink( |
2053 VideoSinkInterface<webrtc::VideoFrame>* sink, | 2044 VideoSinkInterface<webrtc::VideoFrame>* sink, |
2054 const rtc::VideoSinkWants& wants) { | 2045 const rtc::VideoSinkWants& wants) { |
2055 // TODO(perkj): Actually consider the encoder |wants| and remove | 2046 // TODO(perkj): Actually consider the encoder |wants| and remove |
2056 // WebRtcVideoSendStream::OnLoadUpdate(Load load). | 2047 // WebRtcVideoSendStream::OnLoadUpdate(Load load). |
2057 rtc::CritScope cs(&lock_); | 2048 rtc::CritScope cs(&lock_); |
2058 RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); | 2049 RTC_DCHECK(!encoder_sink_ || encoder_sink_ == sink); |
2059 encoder_sink_ = sink; | 2050 encoder_sink_ = sink; |
2060 } | 2051 } |
2061 | 2052 |
2062 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( | 2053 void WebRtcVideoChannel2::WebRtcVideoSendStream::RemoveSink( |
2063 VideoSinkInterface<webrtc::VideoFrame>* sink) { | 2054 VideoSinkInterface<webrtc::VideoFrame>* sink) { |
2064 rtc::CritScope cs(&lock_); | 2055 rtc::CritScope cs(&lock_); |
2065 RTC_DCHECK_EQ(encoder_sink_, sink); | 2056 RTC_DCHECK_EQ(encoder_sink_, sink); |
2066 encoder_sink_ = nullptr; | 2057 encoder_sink_ = nullptr; |
2067 } | 2058 } |
2068 | 2059 |
2069 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { | 2060 void WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate(Load load) { |
2070 if (worker_thread_ != rtc::Thread::Current()) { | 2061 if (worker_thread_ != rtc::Thread::Current()) { |
2071 invoker_.AsyncInvoke<void>( | 2062 invoker_.AsyncInvoke<void>( |
2072 RTC_FROM_HERE, worker_thread_, | 2063 RTC_FROM_HERE, worker_thread_, |
2073 rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate, | 2064 rtc::Bind(&WebRtcVideoChannel2::WebRtcVideoSendStream::OnLoadUpdate, |
2074 this, load)); | 2065 this, load)); |
2075 return; | 2066 return; |
2076 } | 2067 } |
2077 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2068 RTC_DCHECK_RUN_ON(&thread_checker_); |
2078 if (!source_) { | 2069 if (!source_) { |
2079 return; | 2070 return; |
2080 } | 2071 } |
2081 { | 2072 |
2073 LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: " | |
2074 << (parameters_.options.is_screencast | |
2075 ? (*parameters_.options.is_screencast ? "true" : "false") | |
2076 : "unset"); | |
2077 // Do not adapt resolution for screen content as this will likely result in | |
2078 // blurry and unreadable text. | |
2079 if (parameters_.options.is_screencast.value_or(false)) | |
2080 return; | |
2081 | |
2082 rtc::Optional<int> max_pixel_count; | |
2083 rtc::Optional<int> max_pixel_count_step_up; | |
2084 if (load == kOveruse) { | |
2082 rtc::CritScope cs(&lock_); | 2085 rtc::CritScope cs(&lock_); |
2083 LOG(LS_INFO) << "OnLoadUpdate " << load << ", is_screencast: " | 2086 if (cpu_restricted_counter_ >= kMaxCpuDowngrades) { |
2084 << (parameters_.options.is_screencast | |
2085 ? (*parameters_.options.is_screencast ? "true" | |
2086 : "false") | |
2087 : "unset"); | |
2088 // Do not adapt resolution for screen content as this will likely result in | |
2089 // blurry and unreadable text. | |
2090 if (parameters_.options.is_screencast.value_or(false)) | |
2091 return; | 2087 return; |
2092 | |
2093 rtc::Optional<int> max_pixel_count; | |
2094 rtc::Optional<int> max_pixel_count_step_up; | |
2095 if (load == kOveruse) { | |
2096 if (cpu_restricted_counter_ >= kMaxCpuDowngrades) { | |
2097 return; | |
2098 } | |
2099 // The input video frame size will have a resolution with less than or | |
2100 // equal to |max_pixel_count| depending on how the source can scale the | |
2101 // input frame size. | |
2102 max_pixel_count = rtc::Optional<int>( | |
2103 (last_frame_info_.height * last_frame_info_.width * 3) / 5); | |
2104 // Increase |number_of_cpu_adapt_changes_| if | |
2105 // sink_wants_.max_pixel_count will be changed since | |
2106 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
2107 // result in a new request for the source to change resolution. | |
2108 if (!sink_wants_.max_pixel_count || | |
2109 *sink_wants_.max_pixel_count > *max_pixel_count) { | |
2110 ++number_of_cpu_adapt_changes_; | |
2111 ++cpu_restricted_counter_; | |
2112 } | |
2113 } else { | |
2114 RTC_DCHECK(load == kUnderuse); | |
2115 // The input video frame size will have a resolution with "one step up" | |
2116 // pixels than |max_pixel_count_step_up| where "one step up" depends on | |
2117 // how the source can scale the input frame size. | |
2118 max_pixel_count_step_up = | |
2119 rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width); | |
2120 // Increase |number_of_cpu_adapt_changes_| if | |
2121 // sink_wants_.max_pixel_count_step_up will be changed since | |
2122 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
2123 // result in a new request for the source to change resolution. | |
2124 if (sink_wants_.max_pixel_count || | |
2125 (sink_wants_.max_pixel_count_step_up && | |
2126 *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) { | |
2127 ++number_of_cpu_adapt_changes_; | |
2128 --cpu_restricted_counter_; | |
2129 } | |
2130 } | 2088 } |
2131 sink_wants_.max_pixel_count = max_pixel_count; | 2089 // The input video frame size will have a resolution with less than or |
2132 sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up; | 2090 // equal to |max_pixel_count| depending on how the source can scale the |
2091 // input frame size. | |
2092 max_pixel_count = rtc::Optional<int>( | |
2093 (last_frame_info_.height * last_frame_info_.width * 3) / 5); | |
2094 // Increase |number_of_cpu_adapt_changes_| if | |
2095 // sink_wants_.max_pixel_count will be changed since | |
2096 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
2097 // result in a new request for the source to change resolution. | |
2098 if (!sink_wants_.max_pixel_count || | |
2099 *sink_wants_.max_pixel_count > *max_pixel_count) { | |
2100 ++number_of_cpu_adapt_changes_; | |
2101 ++cpu_restricted_counter_; | |
2102 } | |
2103 } else { | |
2104 RTC_DCHECK(load == kUnderuse); | |
2105 rtc::CritScope cs(&lock_); | |
2106 // The input video frame size will have a resolution with "one step up" | |
2107 // pixels than |max_pixel_count_step_up| where "one step up" depends on | |
2108 // how the source can scale the input frame size. | |
2109 max_pixel_count_step_up = | |
2110 rtc::Optional<int>(last_frame_info_.height * last_frame_info_.width); | |
2111 // Increase |number_of_cpu_adapt_changes_| if | |
2112 // sink_wants_.max_pixel_count_step_up will be changed since | |
2113 // last time |source_->AddOrUpdateSink| was called. That is, this will | |
2114 // result in a new request for the source to change resolution. | |
2115 if (sink_wants_.max_pixel_count || | |
2116 (sink_wants_.max_pixel_count_step_up && | |
2117 *sink_wants_.max_pixel_count_step_up < *max_pixel_count_step_up)) { | |
2118 ++number_of_cpu_adapt_changes_; | |
2119 --cpu_restricted_counter_; | |
2120 } | |
2133 } | 2121 } |
2122 sink_wants_.max_pixel_count = max_pixel_count; | |
2123 sink_wants_.max_pixel_count_step_up = max_pixel_count_step_up; | |
2134 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since | 2124 // |source_->AddOrUpdateSink| may not be called while holding |lock_| since |
2135 // that might cause a lock order inversion. | 2125 // that might cause a lock order inversion. |
2136 source_->AddOrUpdateSink(this, sink_wants_); | 2126 source_->AddOrUpdateSink(this, sink_wants_); |
2137 } | 2127 } |
2138 | 2128 |
2139 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( | 2129 VideoSenderInfo WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo( |
2140 bool log_stats) { | 2130 bool log_stats) { |
2141 VideoSenderInfo info; | 2131 VideoSenderInfo info; |
2142 webrtc::VideoSendStream::Stats stats; | 2132 webrtc::VideoSendStream::Stats stats; |
2143 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 2133 RTC_DCHECK_RUN_ON(&thread_checker_); |
2144 { | 2134 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) |
2145 rtc::CritScope cs(&lock_); | 2135 info.add_ssrc(ssrc); |
2146 for (uint32_t ssrc : parameters_.config.rtp.ssrcs) | |
2147 info.add_ssrc(ssrc); | |
2148 | 2136 |
2149 if (parameters_.codec_settings) | 2137 if (parameters_.codec_settings) |
2150 info.codec_name = parameters_.codec_settings->codec.name; | 2138 info.codec_name = parameters_.codec_settings->codec.name; |
2151 for (size_t i = 0; i < parameters_.encoder_config.streams.size(); ++i) { | |
2152 if (i == parameters_.encoder_config.streams.size() - 1) { | |
2153 info.preferred_bitrate += | |
2154 parameters_.encoder_config.streams[i].max_bitrate_bps; | |
2155 } else { | |
2156 info.preferred_bitrate += | |
2157 parameters_.encoder_config.streams[i].target_bitrate_bps; | |
2158 } | |
2159 } | |
2160 | 2139 |
2161 if (stream_ == NULL) | 2140 if (stream_ == NULL) |
2162 return info; | 2141 return info; |
2163 | 2142 |
2164 stats = stream_->GetStats(); | 2143 stats = stream_->GetStats(); |
2165 } | |
2166 | 2144 |
2167 if (log_stats) | 2145 if (log_stats) |
2168 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); | 2146 LOG(LS_INFO) << stats.ToString(rtc::TimeMillis()); |
2169 | 2147 |
2170 info.adapt_changes = number_of_cpu_adapt_changes_; | 2148 info.adapt_changes = number_of_cpu_adapt_changes_; |
2171 info.adapt_reason = | 2149 info.adapt_reason = |
2172 cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU; | 2150 cpu_restricted_counter_ <= 0 ? ADAPTREASON_NONE : ADAPTREASON_CPU; |
2173 | 2151 |
2174 // Get bandwidth limitation info from stream_->GetStats(). | 2152 // Get bandwidth limitation info from stream_->GetStats(). |
2175 // Input resolution (output from video_adapter) can be further scaled down or | 2153 // Input resolution (output from video_adapter) can be further scaled down or |
2176 // higher video layer(s) can be dropped due to bitrate constraints. | 2154 // higher video layer(s) can be dropped due to bitrate constraints. |
2177 // Note, adapt_changes only include changes from the video_adapter. | 2155 // Note, adapt_changes only include changes from the video_adapter. |
2178 if (stats.bw_limited_resolution) | 2156 if (stats.bw_limited_resolution) |
2179 info.adapt_reason |= ADAPTREASON_BANDWIDTH; | 2157 info.adapt_reason |= ADAPTREASON_BANDWIDTH; |
2180 | 2158 |
2181 info.encoder_implementation_name = stats.encoder_implementation_name; | 2159 info.encoder_implementation_name = stats.encoder_implementation_name; |
2182 info.ssrc_groups = ssrc_groups_; | 2160 info.ssrc_groups = ssrc_groups_; |
2183 info.framerate_input = stats.input_frame_rate; | 2161 info.framerate_input = stats.input_frame_rate; |
2184 info.framerate_sent = stats.encode_frame_rate; | 2162 info.framerate_sent = stats.encode_frame_rate; |
2185 info.avg_encode_ms = stats.avg_encode_time_ms; | 2163 info.avg_encode_ms = stats.avg_encode_time_ms; |
2186 info.encode_usage_percent = stats.encode_usage_percent; | 2164 info.encode_usage_percent = stats.encode_usage_percent; |
2187 | 2165 |
2188 info.nominal_bitrate = stats.media_bitrate_bps; | 2166 info.nominal_bitrate = stats.media_bitrate_bps; |
2167 info.preferred_bitrate = stats.preffered_media_bitrate_bps; | |
2189 | 2168 |
2190 info.send_frame_width = 0; | 2169 info.send_frame_width = 0; |
2191 info.send_frame_height = 0; | 2170 info.send_frame_height = 0; |
2192 for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = | 2171 for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = |
2193 stats.substreams.begin(); | 2172 stats.substreams.begin(); |
2194 it != stats.substreams.end(); ++it) { | 2173 it != stats.substreams.end(); ++it) { |
2195 // TODO(pbos): Wire up additional stats, such as padding bytes. | 2174 // TODO(pbos): Wire up additional stats, such as padding bytes. |
2196 webrtc::VideoSendStream::StreamStats stream_stats = it->second; | 2175 webrtc::VideoSendStream::StreamStats stream_stats = it->second; |
2197 info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes + | 2176 info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes + |
2198 stream_stats.rtp_stats.transmitted.header_bytes + | 2177 stream_stats.rtp_stats.transmitted.header_bytes + |
(...skipping 16 matching lines...) Expand all Loading... | |
2215 info.fraction_lost = | 2194 info.fraction_lost = |
2216 static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / | 2195 static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / |
2217 (1 << 8); | 2196 (1 << 8); |
2218 } | 2197 } |
2219 | 2198 |
2220 return info; | 2199 return info; |
2221 } | 2200 } |
2222 | 2201 |
2223 void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( | 2202 void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( |
2224 BandwidthEstimationInfo* bwe_info) { | 2203 BandwidthEstimationInfo* bwe_info) { |
2225 rtc::CritScope cs(&lock_); | 2204 RTC_DCHECK_RUN_ON(&thread_checker_); |
2226 if (stream_ == NULL) { | 2205 if (stream_ == NULL) { |
2227 return; | 2206 return; |
2228 } | 2207 } |
2229 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); | 2208 webrtc::VideoSendStream::Stats stats = stream_->GetStats(); |
2230 for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = | 2209 for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = |
2231 stats.substreams.begin(); | 2210 stats.substreams.begin(); |
2232 it != stats.substreams.end(); ++it) { | 2211 it != stats.substreams.end(); ++it) { |
2233 bwe_info->transmit_bitrate += it->second.total_bitrate_bps; | 2212 bwe_info->transmit_bitrate += it->second.total_bitrate_bps; |
2234 bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; | 2213 bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; |
2235 } | 2214 } |
2236 bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps; | 2215 bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps; |
2237 bwe_info->actual_enc_bitrate += stats.media_bitrate_bps; | 2216 bwe_info->actual_enc_bitrate += stats.media_bitrate_bps; |
2238 } | 2217 } |
2239 | 2218 |
2240 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { | 2219 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { |
2220 RTC_DCHECK_RUN_ON(&thread_checker_); | |
2241 if (stream_ != NULL) { | 2221 if (stream_ != NULL) { |
2242 call_->DestroyVideoSendStream(stream_); | 2222 call_->DestroyVideoSendStream(stream_); |
2243 } | 2223 } |
2244 | 2224 |
2245 RTC_CHECK(parameters_.codec_settings); | 2225 RTC_CHECK(parameters_.codec_settings); |
2246 RTC_DCHECK_EQ((parameters_.encoder_config.content_type == | 2226 RTC_DCHECK_EQ((parameters_.encoder_config.content_type == |
2247 webrtc::VideoEncoderConfig::ContentType::kScreen), | 2227 webrtc::VideoEncoderConfig::ContentType::kScreen), |
2248 parameters_.options.is_screencast.value_or(false)) | 2228 parameters_.options.is_screencast.value_or(false)) |
2249 << "encoder content type inconsistent with screencast option"; | 2229 << "encoder content type inconsistent with screencast option"; |
2250 parameters_.encoder_config.encoder_specific_settings = | 2230 parameters_.encoder_config.encoder_specific_settings = |
2251 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); | 2231 ConfigureVideoEncoderSettings(parameters_.codec_settings->codec); |
2252 | 2232 |
2253 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); | 2233 webrtc::VideoSendStream::Config config = parameters_.config.Copy(); |
2254 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { | 2234 if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { |
2255 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " | 2235 LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |
2256 "payload type the set codec. Ignoring RTX."; | 2236 "payload type the set codec. Ignoring RTX."; |
2257 config.rtp.rtx.ssrcs.clear(); | 2237 config.rtp.rtx.ssrcs.clear(); |
2258 } | 2238 } |
2259 stream_ = call_->CreateVideoSendStream(std::move(config), | 2239 stream_ = call_->CreateVideoSendStream(std::move(config), |
2260 parameters_.encoder_config.Copy()); | 2240 parameters_.encoder_config.Copy()); |
2261 stream_->SetSource(this); | 2241 stream_->SetSource(this); |
2262 | 2242 |
2263 parameters_.encoder_config.encoder_specific_settings = NULL; | 2243 parameters_.encoder_config.encoder_specific_settings = NULL; |
2264 pending_encoder_reconfiguration_ = false; | |
2265 | 2244 |
2266 // Call stream_->Start() if necessary conditions are met. | 2245 // Call stream_->Start() if necessary conditions are met. |
2267 UpdateSendState(); | 2246 UpdateSendState(); |
2268 } | 2247 } |
2269 | 2248 |
2270 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( | 2249 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |
2271 webrtc::Call* call, | 2250 webrtc::Call* call, |
2272 const StreamParams& sp, | 2251 const StreamParams& sp, |
2273 webrtc::VideoReceiveStream::Config config, | 2252 webrtc::VideoReceiveStream::Config config, |
2274 WebRtcVideoDecoderFactory* external_decoder_factory, | 2253 WebRtcVideoDecoderFactory* external_decoder_factory, |
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2710 rtx_mapping[video_codecs[i].codec.id] != | 2689 rtx_mapping[video_codecs[i].codec.id] != |
2711 fec_settings.red_payload_type) { | 2690 fec_settings.red_payload_type) { |
2712 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; | 2691 video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |
2713 } | 2692 } |
2714 } | 2693 } |
2715 | 2694 |
2716 return video_codecs; | 2695 return video_codecs; |
2717 } | 2696 } |
2718 | 2697 |
2719 } // namespace cricket | 2698 } // namespace cricket |
OLD | NEW |