| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "webrtc/video/overuse_frame_detector.h" | 31 #include "webrtc/video/overuse_frame_detector.h" |
| 32 #include "webrtc/video/payload_router.h" | 32 #include "webrtc/video/payload_router.h" |
| 33 #include "webrtc/video/send_statistics_proxy.h" | 33 #include "webrtc/video/send_statistics_proxy.h" |
| 34 #include "webrtc/video_frame.h" | 34 #include "webrtc/video_frame.h" |
| 35 | 35 |
| 36 namespace webrtc { | 36 namespace webrtc { |
| 37 | 37 |
| 38 static const float kStopPaddingThresholdMs = 2000; | 38 static const float kStopPaddingThresholdMs = 2000; |
| 39 static const int kMinKeyFrameRequestIntervalMs = 300; | 39 static const int kMinKeyFrameRequestIntervalMs = 300; |
| 40 | 40 |
| 41 std::vector<uint32_t> AllocateStreamBitrates( | |
| 42 uint32_t total_bitrate, | |
| 43 const SimulcastStream* stream_configs, | |
| 44 size_t number_of_streams) { | |
| 45 if (number_of_streams == 0) { | |
| 46 std::vector<uint32_t> stream_bitrates(1, 0); | |
| 47 stream_bitrates[0] = total_bitrate; | |
| 48 return stream_bitrates; | |
| 49 } | |
| 50 std::vector<uint32_t> stream_bitrates(number_of_streams, 0); | |
| 51 uint32_t bitrate_remainder = total_bitrate; | |
| 52 for (size_t i = 0; i < stream_bitrates.size() && bitrate_remainder > 0; ++i) { | |
| 53 if (stream_configs[i].maxBitrate * 1000 > bitrate_remainder) { | |
| 54 stream_bitrates[i] = bitrate_remainder; | |
| 55 } else { | |
| 56 stream_bitrates[i] = stream_configs[i].maxBitrate * 1000; | |
| 57 } | |
| 58 bitrate_remainder -= stream_bitrates[i]; | |
| 59 } | |
| 60 return stream_bitrates; | |
| 61 } | |
| 62 | |
| 63 class QMVideoSettingsCallback : public VCMQMSettingsCallback { | 41 class QMVideoSettingsCallback : public VCMQMSettingsCallback { |
| 64 public: | 42 public: |
| 65 explicit QMVideoSettingsCallback(VideoProcessing* vpm); | 43 explicit QMVideoSettingsCallback(VideoProcessing* vpm); |
| 66 | 44 |
| 67 ~QMVideoSettingsCallback(); | 45 ~QMVideoSettingsCallback(); |
| 68 | 46 |
| 69 // Update VPM with QM (quality modes: frame size & frame rate) settings. | 47 // Update VPM with QM (quality modes: frame size & frame rate) settings. |
| 70 int32_t SetVideoQMSettings(const uint32_t frame_rate, | 48 int32_t SetVideoQMSettings(const uint32_t frame_rate, |
| 71 const uint32_t width, | 49 const uint32_t width, |
| 72 const uint32_t height); | 50 const uint32_t height); |
| 73 | 51 |
| 74 private: | 52 private: |
| 75 VideoProcessing* vp_; | 53 VideoProcessing* vp_; |
| 76 }; | 54 }; |
| 77 | 55 |
| 78 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 56 ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
| 79 const std::vector<uint32_t>& ssrcs, | 57 const std::vector<uint32_t>& ssrcs, |
| 80 ProcessThread* module_process_thread, | 58 ProcessThread* module_process_thread, |
| 81 SendStatisticsProxy* stats_proxy, | 59 SendStatisticsProxy* stats_proxy, |
| 82 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, | 60 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, |
| 83 OveruseFrameDetector* overuse_detector, | 61 OveruseFrameDetector* overuse_detector, |
| 84 PacedSender* pacer, | 62 PacedSender* pacer) |
| 85 PayloadRouter* payload_router, | |
| 86 EncodedImageCallback* post_encode_callback) | |
| 87 : number_of_cores_(number_of_cores), | 63 : number_of_cores_(number_of_cores), |
| 88 ssrcs_(ssrcs), | 64 ssrcs_(ssrcs), |
| 89 vp_(VideoProcessing::Create()), | 65 vp_(VideoProcessing::Create()), |
| 90 qm_callback_(new QMVideoSettingsCallback(vp_.get())), | 66 qm_callback_(new QMVideoSettingsCallback(vp_.get())), |
| 91 video_sender_(Clock::GetRealTimeClock(), this, this, qm_callback_.get()), | 67 video_sender_(Clock::GetRealTimeClock(), this, this, qm_callback_.get()), |
| 92 stats_proxy_(stats_proxy), | 68 stats_proxy_(stats_proxy), |
| 93 pre_encode_callback_(pre_encode_callback), | 69 pre_encode_callback_(pre_encode_callback), |
| 94 overuse_detector_(overuse_detector), | 70 overuse_detector_(overuse_detector), |
| 95 pacer_(pacer), | 71 pacer_(pacer), |
| 96 send_payload_router_(payload_router), | |
| 97 post_encode_callback_(post_encode_callback), | |
| 98 time_of_last_frame_activity_ms_(0), | 72 time_of_last_frame_activity_ms_(0), |
| 99 encoder_config_(), | 73 encoder_config_(), |
| 100 min_transmit_bitrate_bps_(0), | 74 min_transmit_bitrate_bps_(0), |
| 101 last_observed_bitrate_bps_(0), | 75 last_observed_bitrate_bps_(0), |
| 102 network_is_transmitting_(true), | 76 network_is_transmitting_(true), |
| 103 encoder_paused_(false), | 77 encoder_paused_(true), |
| 104 encoder_paused_and_dropped_frame_(false), | 78 encoder_paused_and_dropped_frame_(false), |
| 105 time_last_intra_request_ms_(ssrcs.size(), -1), | 79 time_last_intra_request_ms_(ssrcs.size(), -1), |
| 106 module_process_thread_(module_process_thread), | 80 module_process_thread_(module_process_thread), |
| 107 has_received_sli_(false), | 81 has_received_sli_(false), |
| 108 picture_id_sli_(0), | 82 picture_id_sli_(0), |
| 109 has_received_rpsi_(false), | 83 has_received_rpsi_(false), |
| 110 picture_id_rpsi_(0), | 84 picture_id_rpsi_(0), |
| 111 video_suspended_(false) { | 85 video_suspended_(false) { |
| 112 module_process_thread_->RegisterModule(&video_sender_); | 86 module_process_thread_->RegisterModule(&video_sender_); |
| 113 } | 87 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 142 rtc::CritScope lock(&data_cs_); | 116 rtc::CritScope lock(&data_cs_); |
| 143 network_is_transmitting_ = is_transmitting; | 117 network_is_transmitting_ = is_transmitting; |
| 144 } | 118 } |
| 145 } | 119 } |
| 146 | 120 |
| 147 void ViEEncoder::Pause() { | 121 void ViEEncoder::Pause() { |
| 148 rtc::CritScope lock(&data_cs_); | 122 rtc::CritScope lock(&data_cs_); |
| 149 encoder_paused_ = true; | 123 encoder_paused_ = true; |
| 150 } | 124 } |
| 151 | 125 |
| 152 void ViEEncoder::Restart() { | 126 void ViEEncoder::Start() { |
| 153 rtc::CritScope lock(&data_cs_); | 127 rtc::CritScope lock(&data_cs_); |
| 154 encoder_paused_ = false; | 128 encoder_paused_ = false; |
| 155 } | 129 } |
| 156 | 130 |
| 157 int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder, | 131 int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder, |
| 158 uint8_t pl_type, | 132 uint8_t pl_type, |
| 159 bool internal_source) { | 133 bool internal_source) { |
| 160 video_sender_.RegisterExternalEncoder(encoder, pl_type, internal_source); | 134 video_sender_.RegisterExternalEncoder(encoder, pl_type, internal_source); |
| 161 return 0; | 135 return 0; |
| 162 } | 136 } |
| 163 | 137 |
| 164 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { | 138 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { |
| 165 video_sender_.RegisterExternalEncoder(nullptr, pl_type, false); | 139 video_sender_.RegisterExternalEncoder(nullptr, pl_type, false); |
| 166 return 0; | 140 return 0; |
| 167 } | 141 } |
| 168 void ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec, | 142 void ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec, |
| 169 int min_transmit_bitrate_bps) { | 143 int min_transmit_bitrate_bps, |
| 170 RTC_DCHECK(send_payload_router_); | 144 size_t max_data_payload_length, |
| 145 EncodedImageCallback* sink) { |
| 171 // Setting target width and height for VPM. | 146 // Setting target width and height for VPM. |
| 172 RTC_CHECK_EQ(VPM_OK, | 147 RTC_CHECK_EQ(VPM_OK, |
| 173 vp_->SetTargetResolution(video_codec.width, video_codec.height, | 148 vp_->SetTargetResolution(video_codec.width, video_codec.height, |
| 174 video_codec.maxFramerate)); | 149 video_codec.maxFramerate)); |
| 175 | 150 |
| 176 // Cache codec before calling AddBitrateObserver (which calls OnBitrateUpdated | 151 // Cache codec before calling AddBitrateObserver (which calls OnBitrateUpdated |
| 177 // that makes use of the number of simulcast streams configured). | 152 // that makes use of the number of simulcast streams configured). |
| 178 { | 153 { |
| 179 rtc::CritScope lock(&data_cs_); | 154 rtc::CritScope lock(&data_cs_); |
| 180 encoder_config_ = video_codec; | 155 encoder_config_ = video_codec; |
| 181 encoder_paused_ = true; | |
| 182 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps; | 156 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps; |
| 183 } | 157 } |
| 158 { |
| 159 rtc::CritScope lock(&sink_cs_); |
| 160 sink_ = sink; |
| 161 } |
| 184 | 162 |
| 185 size_t max_data_payload_length = send_payload_router_->MaxPayloadLength(); | |
| 186 bool success = video_sender_.RegisterSendCodec( | 163 bool success = video_sender_.RegisterSendCodec( |
| 187 &video_codec, number_of_cores_, | 164 &video_codec, number_of_cores_, |
| 188 static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; | 165 static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; |
| 189 if (!success) { | 166 if (!success) { |
| 190 LOG(LS_ERROR) << "Failed to configure encoder."; | 167 LOG(LS_ERROR) << "Failed to configure encoder."; |
| 191 RTC_DCHECK(success); | 168 RTC_DCHECK(success); |
| 192 } | 169 } |
| 193 | 170 |
| 194 send_payload_router_->SetSendingRtpModules( | |
| 195 video_codec.numberOfSimulcastStreams); | |
| 196 | |
| 197 // Restart the media flow | |
| 198 Restart(); | |
| 199 if (stats_proxy_) { | 171 if (stats_proxy_) { |
| 200 // Clear stats for disabled layers. | 172 // Clear stats for disabled layers. |
| 201 for (size_t i = video_codec.numberOfSimulcastStreams; i < ssrcs_.size(); | 173 for (size_t i = video_codec.numberOfSimulcastStreams; i < ssrcs_.size(); |
| 202 ++i) { | 174 ++i) { |
| 203 stats_proxy_->OnInactiveSsrc(ssrcs_[i]); | 175 stats_proxy_->OnInactiveSsrc(ssrcs_[i]); |
| 204 } | 176 } |
| 205 VideoEncoderConfig::ContentType content_type = | 177 VideoEncoderConfig::ContentType content_type = |
| 206 VideoEncoderConfig::ContentType::kRealtimeVideo; | 178 VideoEncoderConfig::ContentType::kRealtimeVideo; |
| 207 switch (video_codec.mode) { | 179 switch (video_codec.mode) { |
| 208 case kRealtimeVideo: | 180 case kRealtimeVideo: |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 | 272 |
| 301 void ViEEncoder::TraceFrameDropEnd() { | 273 void ViEEncoder::TraceFrameDropEnd() { |
| 302 // End trace event on first frame after encoder resumes, if frame was dropped. | 274 // End trace event on first frame after encoder resumes, if frame was dropped. |
| 303 if (encoder_paused_and_dropped_frame_) { | 275 if (encoder_paused_and_dropped_frame_) { |
| 304 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); | 276 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); |
| 305 } | 277 } |
| 306 encoder_paused_and_dropped_frame_ = false; | 278 encoder_paused_and_dropped_frame_ = false; |
| 307 } | 279 } |
| 308 | 280 |
| 309 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame) { | 281 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame) { |
| 310 if (!send_payload_router_->active()) { | |
| 311 // We've paused or we have no channels attached, don't waste resources on | |
| 312 // encoding. | |
| 313 return; | |
| 314 } | |
| 315 VideoCodecType codec_type; | 282 VideoCodecType codec_type; |
| 316 { | 283 { |
| 317 rtc::CritScope lock(&data_cs_); | 284 rtc::CritScope lock(&data_cs_); |
| 318 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); | 285 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); |
| 319 if (EncoderPaused()) { | 286 if (EncoderPaused()) { |
| 320 TraceFrameDropStart(); | 287 TraceFrameDropStart(); |
| 321 return; | 288 return; |
| 322 } | 289 } |
| 323 TraceFrameDropEnd(); | 290 TraceFrameDropEnd(); |
| 324 codec_type = encoder_config_.codecType; | 291 codec_type = encoder_config_.codecType; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 } | 354 } |
| 388 | 355 |
| 389 void ViEEncoder::OnEncoderImplementationName(const char* implementation_name) { | 356 void ViEEncoder::OnEncoderImplementationName(const char* implementation_name) { |
| 390 if (stats_proxy_) | 357 if (stats_proxy_) |
| 391 stats_proxy_->OnEncoderImplementationName(implementation_name); | 358 stats_proxy_->OnEncoderImplementationName(implementation_name); |
| 392 } | 359 } |
| 393 | 360 |
| 394 int32_t ViEEncoder::Encoded(const EncodedImage& encoded_image, | 361 int32_t ViEEncoder::Encoded(const EncodedImage& encoded_image, |
| 395 const CodecSpecificInfo* codec_specific_info, | 362 const CodecSpecificInfo* codec_specific_info, |
| 396 const RTPFragmentationHeader* fragmentation) { | 363 const RTPFragmentationHeader* fragmentation) { |
| 397 RTC_DCHECK(send_payload_router_); | |
| 398 | |
| 399 { | 364 { |
| 400 rtc::CritScope lock(&data_cs_); | 365 rtc::CritScope lock(&data_cs_); |
| 401 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); | 366 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); |
| 402 } | 367 } |
| 403 | |
| 404 if (post_encode_callback_) { | |
| 405 post_encode_callback_->Encoded(encoded_image, codec_specific_info, | |
| 406 fragmentation); | |
| 407 } | |
| 408 | |
| 409 if (stats_proxy_) { | 368 if (stats_proxy_) { |
| 410 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); | 369 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); |
| 411 } | 370 } |
| 412 int success = send_payload_router_->Encoded( | 371 |
| 413 encoded_image, codec_specific_info, fragmentation); | 372 int success = 0; |
| 373 { |
| 374 rtc::CritScope lock(&sink_cs_); |
| 375 success = sink_->Encoded(encoded_image, codec_specific_info, fragmentation); |
| 376 } |
| 377 |
| 414 overuse_detector_->FrameSent(encoded_image._timeStamp); | 378 overuse_detector_->FrameSent(encoded_image._timeStamp); |
| 415 | |
| 416 if (kEnableFrameRecording) { | 379 if (kEnableFrameRecording) { |
| 417 int layer = codec_specific_info->codecType == kVideoCodecVP8 | 380 int layer = codec_specific_info->codecType == kVideoCodecVP8 |
| 418 ? codec_specific_info->codecSpecific.VP8.simulcastIdx | 381 ? codec_specific_info->codecSpecific.VP8.simulcastIdx |
| 419 : 0; | 382 : 0; |
| 420 IvfFileWriter* file_writer; | 383 IvfFileWriter* file_writer; |
| 421 { | 384 { |
| 422 rtc::CritScope lock(&data_cs_); | 385 rtc::CritScope lock(&data_cs_); |
| 423 if (file_writers_[layer] == nullptr) { | 386 if (file_writers_[layer] == nullptr) { |
| 424 std::ostringstream oss; | 387 std::ostringstream oss; |
| 425 oss << "send_bitstream_ssrc"; | 388 oss << "send_bitstream_ssrc"; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 } | 445 } |
| 483 RTC_NOTREACHED() << "Should not receive keyframe requests on unknown SSRCs."; | 446 RTC_NOTREACHED() << "Should not receive keyframe requests on unknown SSRCs."; |
| 484 } | 447 } |
| 485 | 448 |
| 486 void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps, | 449 void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps, |
| 487 uint8_t fraction_lost, | 450 uint8_t fraction_lost, |
| 488 int64_t round_trip_time_ms) { | 451 int64_t round_trip_time_ms) { |
| 489 LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate" << bitrate_bps | 452 LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate" << bitrate_bps |
| 490 << " packet loss " << static_cast<int>(fraction_lost) | 453 << " packet loss " << static_cast<int>(fraction_lost) |
| 491 << " rtt " << round_trip_time_ms; | 454 << " rtt " << round_trip_time_ms; |
| 492 RTC_DCHECK(send_payload_router_); | |
| 493 video_sender_.SetChannelParameters(bitrate_bps, fraction_lost, | 455 video_sender_.SetChannelParameters(bitrate_bps, fraction_lost, |
| 494 round_trip_time_ms); | 456 round_trip_time_ms); |
| 495 bool video_is_suspended = video_sender_.VideoSuspended(); | 457 bool video_is_suspended = video_sender_.VideoSuspended(); |
| 496 bool video_suspension_changed; | 458 bool video_suspension_changed; |
| 497 VideoCodec send_codec; | |
| 498 { | 459 { |
| 499 rtc::CritScope lock(&data_cs_); | 460 rtc::CritScope lock(&data_cs_); |
| 500 last_observed_bitrate_bps_ = bitrate_bps; | 461 last_observed_bitrate_bps_ = bitrate_bps; |
| 501 video_suspension_changed = video_suspended_ != video_is_suspended; | 462 video_suspension_changed = video_suspended_ != video_is_suspended; |
| 502 video_suspended_ = video_is_suspended; | 463 video_suspended_ = video_is_suspended; |
| 503 send_codec = encoder_config_; | |
| 504 } | 464 } |
| 505 | 465 |
| 506 SimulcastStream* stream_configs = send_codec.simulcastStream; | |
| 507 // Allocate the bandwidth between the streams. | |
| 508 std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates( | |
| 509 bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams); | |
| 510 send_payload_router_->SetTargetSendBitrates(stream_bitrates); | |
| 511 | |
| 512 if (!video_suspension_changed) | 466 if (!video_suspension_changed) |
| 513 return; | 467 return; |
| 514 // Video suspend-state changed, inform codec observer. | 468 // Video suspend-state changed, inform codec observer. |
| 515 LOG(LS_INFO) << "Video suspend state changed " << video_is_suspended | 469 LOG(LS_INFO) << "Video suspend state changed " << video_is_suspended |
| 516 << " for ssrc " << ssrcs_[0]; | 470 << " for ssrc " << ssrcs_[0]; |
| 517 if (stats_proxy_) | 471 if (stats_proxy_) |
| 518 stats_proxy_->OnSuspendChange(video_is_suspended); | 472 stats_proxy_->OnSuspendChange(video_is_suspended); |
| 519 } | 473 } |
| 520 | 474 |
| 521 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessing* vpm) | 475 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessing* vpm) |
| 522 : vp_(vpm) { | 476 : vp_(vpm) { |
| 523 } | 477 } |
| 524 | 478 |
| 525 QMVideoSettingsCallback::~QMVideoSettingsCallback() { | 479 QMVideoSettingsCallback::~QMVideoSettingsCallback() { |
| 526 } | 480 } |
| 527 | 481 |
| 528 int32_t QMVideoSettingsCallback::SetVideoQMSettings( | 482 int32_t QMVideoSettingsCallback::SetVideoQMSettings( |
| 529 const uint32_t frame_rate, | 483 const uint32_t frame_rate, |
| 530 const uint32_t width, | 484 const uint32_t width, |
| 531 const uint32_t height) { | 485 const uint32_t height) { |
| 532 return vp_->SetTargetResolution(width, height, frame_rate); | 486 return vp_->SetTargetResolution(width, height, frame_rate); |
| 533 } | 487 } |
| 534 | 488 |
| 535 } // namespace webrtc | 489 } // namespace webrtc |
| OLD | NEW |