| 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 } else { | 65 } else { |
| 66 stream_bitrates[i] = stream_configs[i].maxBitrate * 1000; | 66 stream_bitrates[i] = stream_configs[i].maxBitrate * 1000; |
| 67 } | 67 } |
| 68 bitrate_remainder -= stream_bitrates[i]; | 68 bitrate_remainder -= stream_bitrates[i]; |
| 69 } | 69 } |
| 70 return stream_bitrates; | 70 return stream_bitrates; |
| 71 } | 71 } |
| 72 | 72 |
| 73 class QMVideoSettingsCallback : public VCMQMSettingsCallback { | 73 class QMVideoSettingsCallback : public VCMQMSettingsCallback { |
| 74 public: | 74 public: |
| 75 explicit QMVideoSettingsCallback(VideoProcessingModule* vpm); | 75 explicit QMVideoSettingsCallback(VideoProcessing* vpm); |
| 76 | 76 |
| 77 ~QMVideoSettingsCallback(); | 77 ~QMVideoSettingsCallback(); |
| 78 | 78 |
| 79 // Update VPM with QM (quality modes: frame size & frame rate) settings. | 79 // Update VPM with QM (quality modes: frame size & frame rate) settings. |
| 80 int32_t SetVideoQMSettings(const uint32_t frame_rate, | 80 int32_t SetVideoQMSettings(const uint32_t frame_rate, |
| 81 const uint32_t width, | 81 const uint32_t width, |
| 82 const uint32_t height); | 82 const uint32_t height); |
| 83 | 83 |
| 84 // Update target frame rate. | 84 // Update target frame rate. |
| 85 void SetTargetFramerate(int frame_rate); | 85 void SetTargetFramerate(int frame_rate); |
| 86 | 86 |
| 87 private: | 87 private: |
| 88 VideoProcessingModule* vpm_; | 88 VideoProcessing* vp_; |
| 89 }; | 89 }; |
| 90 | 90 |
| 91 class ViEBitrateObserver : public BitrateObserver { | 91 class ViEBitrateObserver : public BitrateObserver { |
| 92 public: | 92 public: |
| 93 explicit ViEBitrateObserver(ViEEncoder* owner) | 93 explicit ViEBitrateObserver(ViEEncoder* owner) |
| 94 : owner_(owner) { | 94 : owner_(owner) { |
| 95 } | 95 } |
| 96 virtual ~ViEBitrateObserver() {} | 96 virtual ~ViEBitrateObserver() {} |
| 97 // Implements BitrateObserver. | 97 // Implements BitrateObserver. |
| 98 virtual void OnNetworkChanged(uint32_t bitrate_bps, | 98 virtual void OnNetworkChanged(uint32_t bitrate_bps, |
| 99 uint8_t fraction_lost, | 99 uint8_t fraction_lost, |
| 100 int64_t rtt) { | 100 int64_t rtt) { |
| 101 owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt); | 101 owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt); |
| 102 } | 102 } |
| 103 private: | 103 private: |
| 104 ViEEncoder* owner_; | 104 ViEEncoder* owner_; |
| 105 }; | 105 }; |
| 106 | 106 |
| 107 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 107 ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
| 108 ProcessThread* module_process_thread, | 108 ProcessThread* module_process_thread, |
| 109 SendStatisticsProxy* stats_proxy, | 109 SendStatisticsProxy* stats_proxy, |
| 110 I420FrameCallback* pre_encode_callback, | 110 I420FrameCallback* pre_encode_callback, |
| 111 PacedSender* pacer, | 111 PacedSender* pacer, |
| 112 BitrateAllocator* bitrate_allocator) | 112 BitrateAllocator* bitrate_allocator) |
| 113 : number_of_cores_(number_of_cores), | 113 : number_of_cores_(number_of_cores), |
| 114 vpm_(VideoProcessingModule::Create()), | 114 vp_(VideoProcessing::Create()), |
| 115 qm_callback_(new QMVideoSettingsCallback(vpm_.get())), | 115 qm_callback_(new QMVideoSettingsCallback(vp_.get())), |
| 116 vcm_(VideoCodingModule::Create(Clock::GetRealTimeClock(), | 116 vcm_(VideoCodingModule::Create(Clock::GetRealTimeClock(), |
| 117 this, | 117 this, |
| 118 qm_callback_.get())), | 118 qm_callback_.get())), |
| 119 send_payload_router_(NULL), | 119 send_payload_router_(NULL), |
| 120 data_cs_(CriticalSectionWrapper::CreateCriticalSection()), | 120 data_cs_(CriticalSectionWrapper::CreateCriticalSection()), |
| 121 stats_proxy_(stats_proxy), | 121 stats_proxy_(stats_proxy), |
| 122 pre_encode_callback_(pre_encode_callback), | 122 pre_encode_callback_(pre_encode_callback), |
| 123 pacer_(pacer), | 123 pacer_(pacer), |
| 124 bitrate_allocator_(bitrate_allocator), | 124 bitrate_allocator_(bitrate_allocator), |
| 125 time_of_last_frame_activity_ms_(0), | 125 time_of_last_frame_activity_ms_(0), |
| 126 encoder_config_(), | 126 encoder_config_(), |
| 127 min_transmit_bitrate_kbps_(0), | 127 min_transmit_bitrate_kbps_(0), |
| 128 last_observed_bitrate_bps_(0), | 128 last_observed_bitrate_bps_(0), |
| 129 target_delay_ms_(0), | 129 target_delay_ms_(0), |
| 130 network_is_transmitting_(true), | 130 network_is_transmitting_(true), |
| 131 encoder_paused_(false), | 131 encoder_paused_(false), |
| 132 encoder_paused_and_dropped_frame_(false), | 132 encoder_paused_and_dropped_frame_(false), |
| 133 module_process_thread_(module_process_thread), | 133 module_process_thread_(module_process_thread), |
| 134 has_received_sli_(false), | 134 has_received_sli_(false), |
| 135 picture_id_sli_(0), | 135 picture_id_sli_(0), |
| 136 has_received_rpsi_(false), | 136 has_received_rpsi_(false), |
| 137 picture_id_rpsi_(0), | 137 picture_id_rpsi_(0), |
| 138 video_suspended_(false) { | 138 video_suspended_(false) { |
| 139 bitrate_observer_.reset(new ViEBitrateObserver(this)); | 139 bitrate_observer_.reset(new ViEBitrateObserver(this)); |
| 140 } | 140 } |
| 141 | 141 |
| 142 bool ViEEncoder::Init() { | 142 bool ViEEncoder::Init() { |
| 143 vpm_->EnableTemporalDecimation(true); | 143 vp_->EnableTemporalDecimation(true); |
| 144 | 144 |
| 145 // Enable/disable content analysis: off by default for now. | 145 // Enable/disable content analysis: off by default for now. |
| 146 vpm_->EnableContentAnalysis(false); | 146 vp_->EnableContentAnalysis(false); |
| 147 | 147 |
| 148 if (vcm_->RegisterTransportCallback(this) != 0) { | 148 if (vcm_->RegisterTransportCallback(this) != 0) { |
| 149 return false; | 149 return false; |
| 150 } | 150 } |
| 151 if (vcm_->RegisterSendStatisticsCallback(this) != 0) { | 151 if (vcm_->RegisterSendStatisticsCallback(this) != 0) { |
| 152 return false; | 152 return false; |
| 153 } | 153 } |
| 154 return true; | 154 return true; |
| 155 } | 155 } |
| 156 | 156 |
| 157 void ViEEncoder::StartThreadsAndSetSharedMembers( | 157 void ViEEncoder::StartThreadsAndSetSharedMembers( |
| 158 rtc::scoped_refptr<PayloadRouter> send_payload_router, | 158 rtc::scoped_refptr<PayloadRouter> send_payload_router, |
| 159 VCMProtectionCallback* vcm_protection_callback) { | 159 VCMProtectionCallback* vcm_protection_callback) { |
| 160 RTC_DCHECK(send_payload_router_ == NULL); | 160 RTC_DCHECK(send_payload_router_ == NULL); |
| 161 | 161 |
| 162 send_payload_router_ = send_payload_router; | 162 send_payload_router_ = send_payload_router; |
| 163 vcm_->RegisterProtectionCallback(vcm_protection_callback); | 163 vcm_->RegisterProtectionCallback(vcm_protection_callback); |
| 164 module_process_thread_->RegisterModule(vcm_.get()); | 164 module_process_thread_->RegisterModule(vcm_.get()); |
| 165 } | 165 } |
| 166 | 166 |
| 167 void ViEEncoder::StopThreadsAndRemoveSharedMembers() { | 167 void ViEEncoder::StopThreadsAndRemoveSharedMembers() { |
| 168 if (bitrate_allocator_) | 168 if (bitrate_allocator_) |
| 169 bitrate_allocator_->RemoveBitrateObserver(bitrate_observer_.get()); | 169 bitrate_allocator_->RemoveBitrateObserver(bitrate_observer_.get()); |
| 170 module_process_thread_->DeRegisterModule(vcm_.get()); | 170 module_process_thread_->DeRegisterModule(vcm_.get()); |
| 171 module_process_thread_->DeRegisterModule(vpm_.get()); | |
| 172 } | 171 } |
| 173 | 172 |
| 174 ViEEncoder::~ViEEncoder() { | 173 ViEEncoder::~ViEEncoder() { |
| 175 } | 174 } |
| 176 | 175 |
| 177 void ViEEncoder::SetNetworkTransmissionState(bool is_transmitting) { | 176 void ViEEncoder::SetNetworkTransmissionState(bool is_transmitting) { |
| 178 { | 177 { |
| 179 CriticalSectionScoped cs(data_cs_.get()); | 178 CriticalSectionScoped cs(data_cs_.get()); |
| 180 network_is_transmitting_ = is_transmitting; | 179 network_is_transmitting_ = is_transmitting; |
| 181 } | 180 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 204 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { | 203 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { |
| 205 if (vcm_->RegisterExternalEncoder(NULL, pl_type) != VCM_OK) { | 204 if (vcm_->RegisterExternalEncoder(NULL, pl_type) != VCM_OK) { |
| 206 return -1; | 205 return -1; |
| 207 } | 206 } |
| 208 return 0; | 207 return 0; |
| 209 } | 208 } |
| 210 | 209 |
| 211 int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) { | 210 int32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) { |
| 212 RTC_DCHECK(send_payload_router_ != NULL); | 211 RTC_DCHECK(send_payload_router_ != NULL); |
| 213 // Setting target width and height for VPM. | 212 // Setting target width and height for VPM. |
| 214 if (vpm_->SetTargetResolution(video_codec.width, video_codec.height, | 213 if (vp_->SetTargetResolution(video_codec.width, video_codec.height, |
| 215 video_codec.maxFramerate) != VPM_OK) { | 214 video_codec.maxFramerate) != VPM_OK) { |
| 216 return -1; | 215 return -1; |
| 217 } | 216 } |
| 218 | 217 |
| 219 // Cache codec before calling AddBitrateObserver (which calls OnNetworkChanged | 218 // Cache codec before calling AddBitrateObserver (which calls OnNetworkChanged |
| 220 // that makes use of the number of simulcast streams configured). | 219 // that makes use of the number of simulcast streams configured). |
| 221 { | 220 { |
| 222 CriticalSectionScoped cs(data_cs_.get()); | 221 CriticalSectionScoped cs(data_cs_.get()); |
| 223 encoder_config_ = video_codec; | 222 encoder_config_ = video_codec; |
| 224 } | 223 } |
| 225 | 224 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 if (EncoderPaused()) { | 350 if (EncoderPaused()) { |
| 352 TraceFrameDropStart(); | 351 TraceFrameDropStart(); |
| 353 return; | 352 return; |
| 354 } | 353 } |
| 355 TraceFrameDropEnd(); | 354 TraceFrameDropEnd(); |
| 356 codec_type = encoder_config_.codecType; | 355 codec_type = encoder_config_.codecType; |
| 357 } | 356 } |
| 358 | 357 |
| 359 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), | 358 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), |
| 360 "Encode"); | 359 "Encode"); |
| 361 VideoFrame* decimated_frame = NULL; | 360 const VideoFrame* frame_to_send = &video_frame; |
| 362 // TODO(wuchengli): support texture frames. | 361 // TODO(wuchengli): support texture frames. |
| 363 if (video_frame.native_handle() == NULL) { | 362 if (video_frame.native_handle() == NULL) { |
| 364 // Pass frame via preprocessor. | 363 // Pass frame via preprocessor. |
| 365 const int ret = vpm_->PreprocessFrame(video_frame, &decimated_frame); | 364 frame_to_send = vp_->PreprocessFrame(video_frame); |
| 366 if (ret == 1) { | 365 if (!frame_to_send) { |
| 367 // Drop this frame. | 366 // Drop this frame, or there was an error processing it. |
| 368 return; | |
| 369 } | |
| 370 if (ret != VPM_OK) { | |
| 371 return; | 367 return; |
| 372 } | 368 } |
| 373 } | 369 } |
| 374 | 370 |
| 375 // If we haven't resampled the frame and we have a FrameCallback, we need to | 371 // If we haven't resampled the frame and we have a FrameCallback, we need to |
| 376 // make a deep copy of |video_frame|. | 372 // make a deep copy of |video_frame|. |
| 377 VideoFrame copied_frame; | 373 VideoFrame copied_frame; |
| 378 if (pre_encode_callback_) { | 374 if (pre_encode_callback_) { |
| 379 // If the frame was not resampled or scaled => use copy of original. | 375 copied_frame.CopyFrame(*frame_to_send); |
| 380 if (decimated_frame == NULL) { | 376 pre_encode_callback_->FrameCallback(&copied_frame); |
| 381 copied_frame.CopyFrame(video_frame); | 377 frame_to_send = &copied_frame; |
| 382 decimated_frame = &copied_frame; | |
| 383 } | |
| 384 pre_encode_callback_->FrameCallback(decimated_frame); | |
| 385 } | 378 } |
| 386 | 379 |
| 387 // If the frame was not resampled, scaled, or touched by FrameCallback => use | |
| 388 // original. The frame is const from here. | |
| 389 const VideoFrame* output_frame = | |
| 390 (decimated_frame != NULL) ? decimated_frame : &video_frame; | |
| 391 | |
| 392 if (codec_type == webrtc::kVideoCodecVP8) { | 380 if (codec_type == webrtc::kVideoCodecVP8) { |
| 393 webrtc::CodecSpecificInfo codec_specific_info; | 381 webrtc::CodecSpecificInfo codec_specific_info; |
| 394 codec_specific_info.codecType = webrtc::kVideoCodecVP8; | 382 codec_specific_info.codecType = webrtc::kVideoCodecVP8; |
| 395 { | 383 { |
| 396 CriticalSectionScoped cs(data_cs_.get()); | 384 CriticalSectionScoped cs(data_cs_.get()); |
| 397 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI = | 385 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI = |
| 398 has_received_rpsi_; | 386 has_received_rpsi_; |
| 399 codec_specific_info.codecSpecific.VP8.hasReceivedSLI = | 387 codec_specific_info.codecSpecific.VP8.hasReceivedSLI = |
| 400 has_received_sli_; | 388 has_received_sli_; |
| 401 codec_specific_info.codecSpecific.VP8.pictureIdRPSI = | 389 codec_specific_info.codecSpecific.VP8.pictureIdRPSI = |
| 402 picture_id_rpsi_; | 390 picture_id_rpsi_; |
| 403 codec_specific_info.codecSpecific.VP8.pictureIdSLI = | 391 codec_specific_info.codecSpecific.VP8.pictureIdSLI = |
| 404 picture_id_sli_; | 392 picture_id_sli_; |
| 405 has_received_sli_ = false; | 393 has_received_sli_ = false; |
| 406 has_received_rpsi_ = false; | 394 has_received_rpsi_ = false; |
| 407 } | 395 } |
| 408 | 396 |
| 409 vcm_->AddVideoFrame(*output_frame, vpm_->ContentMetrics(), | 397 vcm_->AddVideoFrame(*frame_to_send, vp_->GetContentMetrics(), |
| 410 &codec_specific_info); | 398 &codec_specific_info); |
| 411 return; | 399 return; |
| 412 } | 400 } |
| 413 vcm_->AddVideoFrame(*output_frame); | 401 vcm_->AddVideoFrame(*frame_to_send); |
| 414 } | 402 } |
| 415 | 403 |
| 416 int ViEEncoder::SendKeyFrame() { | 404 int ViEEncoder::SendKeyFrame() { |
| 417 return vcm_->IntraFrameRequest(0); | 405 return vcm_->IntraFrameRequest(0); |
| 418 } | 406 } |
| 419 | 407 |
| 420 uint32_t ViEEncoder::LastObservedBitrateBps() const { | 408 uint32_t ViEEncoder::LastObservedBitrateBps() const { |
| 421 CriticalSectionScoped cs(data_cs_.get()); | 409 CriticalSectionScoped cs(data_cs_.get()); |
| 422 return last_observed_bitrate_bps_; | 410 return last_observed_bitrate_bps_; |
| 423 } | 411 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 441 } | 429 } |
| 442 | 430 |
| 443 void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) { | 431 void ViEEncoder::SetSenderBufferingMode(int target_delay_ms) { |
| 444 { | 432 { |
| 445 CriticalSectionScoped cs(data_cs_.get()); | 433 CriticalSectionScoped cs(data_cs_.get()); |
| 446 target_delay_ms_ = target_delay_ms; | 434 target_delay_ms_ = target_delay_ms; |
| 447 } | 435 } |
| 448 if (target_delay_ms > 0) { | 436 if (target_delay_ms > 0) { |
| 449 // Disable external frame-droppers. | 437 // Disable external frame-droppers. |
| 450 vcm_->EnableFrameDropper(false); | 438 vcm_->EnableFrameDropper(false); |
| 451 vpm_->EnableTemporalDecimation(false); | 439 vp_->EnableTemporalDecimation(false); |
| 452 } else { | 440 } else { |
| 453 // Real-time mode - enable frame droppers. | 441 // Real-time mode - enable frame droppers. |
| 454 vpm_->EnableTemporalDecimation(true); | 442 vp_->EnableTemporalDecimation(true); |
| 455 vcm_->EnableFrameDropper(true); | 443 vcm_->EnableFrameDropper(true); |
| 456 } | 444 } |
| 457 } | 445 } |
| 458 | 446 |
| 459 void ViEEncoder::OnSetRates(uint32_t bitrate_bps, int framerate) { | 447 void ViEEncoder::OnSetRates(uint32_t bitrate_bps, int framerate) { |
| 460 if (stats_proxy_) | 448 if (stats_proxy_) |
| 461 stats_proxy_->OnSetRates(bitrate_bps, framerate); | 449 stats_proxy_->OnSetRates(bitrate_bps, framerate); |
| 462 } | 450 } |
| 463 | 451 |
| 464 int32_t ViEEncoder::SendData( | 452 int32_t ViEEncoder::SendData( |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 void ViEEncoder::SuspendBelowMinBitrate() { | 600 void ViEEncoder::SuspendBelowMinBitrate() { |
| 613 vcm_->SuspendBelowMinBitrate(); | 601 vcm_->SuspendBelowMinBitrate(); |
| 614 bitrate_allocator_->EnforceMinBitrate(false); | 602 bitrate_allocator_->EnforceMinBitrate(false); |
| 615 } | 603 } |
| 616 | 604 |
| 617 void ViEEncoder::RegisterPostEncodeImageCallback( | 605 void ViEEncoder::RegisterPostEncodeImageCallback( |
| 618 EncodedImageCallback* post_encode_callback) { | 606 EncodedImageCallback* post_encode_callback) { |
| 619 vcm_->RegisterPostEncodeImageCallback(post_encode_callback); | 607 vcm_->RegisterPostEncodeImageCallback(post_encode_callback); |
| 620 } | 608 } |
| 621 | 609 |
| 622 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm) | 610 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessing* vpm) |
| 623 : vpm_(vpm) { | 611 : vp_(vpm) { |
| 624 } | 612 } |
| 625 | 613 |
| 626 QMVideoSettingsCallback::~QMVideoSettingsCallback() { | 614 QMVideoSettingsCallback::~QMVideoSettingsCallback() { |
| 627 } | 615 } |
| 628 | 616 |
| 629 int32_t QMVideoSettingsCallback::SetVideoQMSettings( | 617 int32_t QMVideoSettingsCallback::SetVideoQMSettings( |
| 630 const uint32_t frame_rate, | 618 const uint32_t frame_rate, |
| 631 const uint32_t width, | 619 const uint32_t width, |
| 632 const uint32_t height) { | 620 const uint32_t height) { |
| 633 return vpm_->SetTargetResolution(width, height, frame_rate); | 621 return vp_->SetTargetResolution(width, height, frame_rate); |
| 634 } | 622 } |
| 635 | 623 |
| 636 void QMVideoSettingsCallback::SetTargetFramerate(int frame_rate) { | 624 void QMVideoSettingsCallback::SetTargetFramerate(int frame_rate) { |
| 637 vpm_->SetTargetFramerate(frame_rate); | 625 vp_->SetTargetFramerate(frame_rate); |
| 638 } | 626 } |
| 639 | 627 |
| 640 } // namespace webrtc | 628 } // namespace webrtc |
| OLD | NEW |