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 success = 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 |