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