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 |