aboutsummaryrefslogtreecommitdiff
path: root/webrtc/modules/video_coding/main/source/video_sender.cc
diff options
context:
space:
mode:
Diffstat (limited to 'webrtc/modules/video_coding/main/source/video_sender.cc')
-rw-r--r--webrtc/modules/video_coding/main/source/video_sender.cc376
1 files changed, 0 insertions, 376 deletions
diff --git a/webrtc/modules/video_coding/main/source/video_sender.cc b/webrtc/modules/video_coding/main/source/video_sender.cc
deleted file mode 100644
index 98230b1e9e..0000000000
--- a/webrtc/modules/video_coding/main/source/video_sender.cc
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "webrtc/common_types.h"
-
-#include <algorithm> // std::max
-
-#include "webrtc/base/checks.h"
-#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
-#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
-#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
-#include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
-#include "webrtc/modules/video_coding/utility/include/quality_scaler.h"
-#include "webrtc/system_wrappers/include/clock.h"
-#include "webrtc/system_wrappers/include/logging.h"
-
-namespace webrtc {
-namespace vcm {
-
-VideoSender::VideoSender(Clock* clock,
- EncodedImageCallback* post_encode_callback,
- VideoEncoderRateObserver* encoder_rate_observer,
- VCMQMSettingsCallback* qm_settings_callback)
- : clock_(clock),
- process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
- _encoder(nullptr),
- _encodedFrameCallback(post_encode_callback),
- _nextFrameTypes(1, kVideoFrameDelta),
- _mediaOpt(clock_),
- _sendStatsCallback(nullptr),
- _codecDataBase(encoder_rate_observer, &_encodedFrameCallback),
- frame_dropper_enabled_(true),
- _sendStatsTimer(1000, clock_),
- current_codec_(),
- qm_settings_callback_(qm_settings_callback),
- protection_callback_(nullptr),
- encoder_params_({0, 0, 0, 0}) {
- // Allow VideoSender to be created on one thread but used on another, post
- // construction. This is currently how this class is being used by at least
- // one external project (diffractor).
- _mediaOpt.EnableQM(qm_settings_callback_ != nullptr);
- _mediaOpt.Reset();
- main_thread_.DetachFromThread();
-}
-
-VideoSender::~VideoSender() {}
-
-int32_t VideoSender::Process() {
- int32_t returnValue = VCM_OK;
-
- if (_sendStatsTimer.TimeUntilProcess() == 0) {
- _sendStatsTimer.Processed();
- CriticalSectionScoped cs(process_crit_sect_.get());
- if (_sendStatsCallback != nullptr) {
- uint32_t bitRate = _mediaOpt.SentBitRate();
- uint32_t frameRate = _mediaOpt.SentFrameRate();
- _sendStatsCallback->SendStatistics(bitRate, frameRate);
- }
- }
-
- {
- rtc::CritScope cs(&params_lock_);
- // Force an encoder parameters update, so that incoming frame rate is
- // updated even if bandwidth hasn't changed.
- encoder_params_.input_frame_rate = _mediaOpt.InputFrameRate();
- }
-
- return returnValue;
-}
-
-int64_t VideoSender::TimeUntilNextProcess() {
- return _sendStatsTimer.TimeUntilProcess();
-}
-
-// Register the send codec to be used.
-int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec,
- uint32_t numberOfCores,
- uint32_t maxPayloadSize) {
- RTC_DCHECK(main_thread_.CalledOnValidThread());
- rtc::CritScope lock(&send_crit_);
- if (sendCodec == nullptr) {
- return VCM_PARAMETER_ERROR;
- }
-
- bool ret =
- _codecDataBase.SetSendCodec(sendCodec, numberOfCores, maxPayloadSize);
-
- // Update encoder regardless of result to make sure that we're not holding on
- // to a deleted instance.
- _encoder = _codecDataBase.GetEncoder();
- // Cache the current codec here so they can be fetched from this thread
- // without requiring the _sendCritSect lock.
- current_codec_ = *sendCodec;
-
- if (!ret) {
- LOG(LS_ERROR) << "Failed to initialize set encoder with payload name '"
- << sendCodec->plName << "'.";
- return VCM_CODEC_ERROR;
- }
-
- int numLayers;
- if (sendCodec->codecType == kVideoCodecVP8) {
- numLayers = sendCodec->codecSpecific.VP8.numberOfTemporalLayers;
- } else if (sendCodec->codecType == kVideoCodecVP9) {
- numLayers = sendCodec->codecSpecific.VP9.numberOfTemporalLayers;
- } else {
- numLayers = 1;
- }
-
- // If we have screensharing and we have layers, we disable frame dropper.
- bool disable_frame_dropper =
- numLayers > 1 && sendCodec->mode == kScreensharing;
- if (disable_frame_dropper) {
- _mediaOpt.EnableFrameDropper(false);
- } else if (frame_dropper_enabled_) {
- _mediaOpt.EnableFrameDropper(true);
- }
- _nextFrameTypes.clear();
- _nextFrameTypes.resize(VCM_MAX(sendCodec->numberOfSimulcastStreams, 1),
- kVideoFrameDelta);
-
- _mediaOpt.SetEncodingData(sendCodec->codecType,
- sendCodec->maxBitrate * 1000,
- sendCodec->startBitrate * 1000,
- sendCodec->width,
- sendCodec->height,
- sendCodec->maxFramerate,
- numLayers,
- maxPayloadSize);
- return VCM_OK;
-}
-
-const VideoCodec& VideoSender::GetSendCodec() const {
- RTC_DCHECK(main_thread_.CalledOnValidThread());
- return current_codec_;
-}
-
-int32_t VideoSender::SendCodecBlocking(VideoCodec* currentSendCodec) const {
- rtc::CritScope lock(&send_crit_);
- if (currentSendCodec == nullptr) {
- return VCM_PARAMETER_ERROR;
- }
- return _codecDataBase.SendCodec(currentSendCodec) ? 0 : -1;
-}
-
-VideoCodecType VideoSender::SendCodecBlocking() const {
- rtc::CritScope lock(&send_crit_);
- return _codecDataBase.SendCodec();
-}
-
-// Register an external decoder object.
-// This can not be used together with external decoder callbacks.
-int32_t VideoSender::RegisterExternalEncoder(VideoEncoder* externalEncoder,
- uint8_t payloadType,
- bool internalSource /*= false*/) {
- RTC_DCHECK(main_thread_.CalledOnValidThread());
-
- rtc::CritScope lock(&send_crit_);
-
- if (externalEncoder == nullptr) {
- bool wasSendCodec = false;
- const bool ret =
- _codecDataBase.DeregisterExternalEncoder(payloadType, &wasSendCodec);
- if (wasSendCodec) {
- // Make sure the VCM doesn't use the de-registered codec
- _encoder = nullptr;
- }
- return ret ? 0 : -1;
- }
- _codecDataBase.RegisterExternalEncoder(
- externalEncoder, payloadType, internalSource);
- return 0;
-}
-
-// Get encode bitrate
-int VideoSender::Bitrate(unsigned int* bitrate) const {
- RTC_DCHECK(main_thread_.CalledOnValidThread());
- // Since we're running on the thread that's the only thread known to modify
- // the value of _encoder, we don't need to grab the lock here.
-
- if (!_encoder)
- return VCM_UNINITIALIZED;
- *bitrate = _encoder->GetEncoderParameters().target_bitrate;
- return 0;
-}
-
-// Get encode frame rate
-int VideoSender::FrameRate(unsigned int* framerate) const {
- RTC_DCHECK(main_thread_.CalledOnValidThread());
- // Since we're running on the thread that's the only thread known to modify
- // the value of _encoder, we don't need to grab the lock here.
-
- if (!_encoder)
- return VCM_UNINITIALIZED;
-
- *framerate = _encoder->GetEncoderParameters().input_frame_rate;
- return 0;
-}
-
-int32_t VideoSender::SetChannelParameters(uint32_t target_bitrate,
- uint8_t lossRate,
- int64_t rtt) {
- uint32_t target_rate =
- _mediaOpt.SetTargetRates(target_bitrate, lossRate, rtt,
- protection_callback_, qm_settings_callback_);
-
- uint32_t input_frame_rate = _mediaOpt.InputFrameRate();
-
- rtc::CritScope cs(&params_lock_);
- encoder_params_ = {target_rate, lossRate, rtt, input_frame_rate};
-
- return VCM_OK;
-}
-
-void VideoSender::SetEncoderParameters(EncoderParameters params) {
- if (params.target_bitrate == 0)
- return;
-
- if (params.input_frame_rate == 0) {
- // No frame rate estimate available, use default.
- params.input_frame_rate = current_codec_.maxFramerate;
- }
- if (_encoder != nullptr)
- _encoder->SetEncoderParameters(params);
-}
-
-int32_t VideoSender::RegisterTransportCallback(
- VCMPacketizationCallback* transport) {
- rtc::CritScope lock(&send_crit_);
- _encodedFrameCallback.SetMediaOpt(&_mediaOpt);
- _encodedFrameCallback.SetTransportCallback(transport);
- return VCM_OK;
-}
-
-// Register video output information callback which will be called to deliver
-// information about the video stream produced by the encoder, for instance the
-// average frame rate and bit rate.
-int32_t VideoSender::RegisterSendStatisticsCallback(
- VCMSendStatisticsCallback* sendStats) {
- CriticalSectionScoped cs(process_crit_sect_.get());
- _sendStatsCallback = sendStats;
- return VCM_OK;
-}
-
-// Register a video protection callback which will be called to deliver the
-// requested FEC rate and NACK status (on/off).
-// Note: this callback is assumed to only be registered once and before it is
-// used in this class.
-int32_t VideoSender::RegisterProtectionCallback(
- VCMProtectionCallback* protection_callback) {
- RTC_DCHECK(protection_callback == nullptr || protection_callback_ == nullptr);
- protection_callback_ = protection_callback;
- return VCM_OK;
-}
-
-// Enable or disable a video protection method.
-void VideoSender::SetVideoProtection(VCMVideoProtection videoProtection) {
- rtc::CritScope lock(&send_crit_);
- switch (videoProtection) {
- case kProtectionNone:
- _mediaOpt.SetProtectionMethod(media_optimization::kNone);
- break;
- case kProtectionNack:
- _mediaOpt.SetProtectionMethod(media_optimization::kNack);
- break;
- case kProtectionNackFEC:
- _mediaOpt.SetProtectionMethod(media_optimization::kNackFec);
- break;
- case kProtectionFEC:
- _mediaOpt.SetProtectionMethod(media_optimization::kFec);
- break;
- }
-}
-// Add one raw video frame to the encoder, blocking.
-int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame,
- const VideoContentMetrics* contentMetrics,
- const CodecSpecificInfo* codecSpecificInfo) {
- EncoderParameters encoder_params;
- {
- rtc::CritScope lock(&params_lock_);
- encoder_params = encoder_params_;
- }
- rtc::CritScope lock(&send_crit_);
- if (_encoder == nullptr)
- return VCM_UNINITIALIZED;
- SetEncoderParameters(encoder_params);
- // TODO(holmer): Add support for dropping frames per stream. Currently we
- // only have one frame dropper for all streams.
- if (_nextFrameTypes[0] == kEmptyFrame) {
- return VCM_OK;
- }
- if (_mediaOpt.DropFrame()) {
- _encoder->OnDroppedFrame();
- return VCM_OK;
- }
- _mediaOpt.UpdateContentData(contentMetrics);
- // TODO(pbos): Make sure setting send codec is synchronized with video
- // processing so frame size always matches.
- if (!_codecDataBase.MatchesCurrentResolution(videoFrame.width(),
- videoFrame.height())) {
- LOG(LS_ERROR) << "Incoming frame doesn't match set resolution. Dropping.";
- return VCM_PARAMETER_ERROR;
- }
- VideoFrame converted_frame = videoFrame;
- if (converted_frame.native_handle() && !_encoder->SupportsNativeHandle()) {
- // This module only supports software encoding.
- // TODO(pbos): Offload conversion from the encoder thread.
- converted_frame = converted_frame.ConvertNativeToI420Frame();
- RTC_CHECK(!converted_frame.IsZeroSize())
- << "Frame conversion failed, won't be able to encode frame.";
- }
- int32_t ret =
- _encoder->Encode(converted_frame, codecSpecificInfo, _nextFrameTypes);
- if (ret < 0) {
- LOG(LS_ERROR) << "Failed to encode frame. Error code: " << ret;
- return ret;
- }
- for (size_t i = 0; i < _nextFrameTypes.size(); ++i) {
- _nextFrameTypes[i] = kVideoFrameDelta; // Default frame type.
- }
- if (qm_settings_callback_)
- qm_settings_callback_->SetTargetFramerate(_encoder->GetTargetFramerate());
- return VCM_OK;
-}
-
-int32_t VideoSender::IntraFrameRequest(int stream_index) {
- rtc::CritScope lock(&send_crit_);
- if (stream_index < 0 ||
- static_cast<unsigned int>(stream_index) >= _nextFrameTypes.size()) {
- return -1;
- }
- _nextFrameTypes[stream_index] = kVideoFrameKey;
- if (_encoder != nullptr && _encoder->InternalSource()) {
- // Try to request the frame if we have an external encoder with
- // internal source since AddVideoFrame never will be called.
- if (_encoder->RequestFrame(_nextFrameTypes) == WEBRTC_VIDEO_CODEC_OK) {
- _nextFrameTypes[stream_index] = kVideoFrameDelta;
- }
- }
- return VCM_OK;
-}
-
-int32_t VideoSender::EnableFrameDropper(bool enable) {
- rtc::CritScope lock(&send_crit_);
- frame_dropper_enabled_ = enable;
- _mediaOpt.EnableFrameDropper(enable);
- return VCM_OK;
-}
-
-void VideoSender::SuspendBelowMinBitrate() {
- RTC_DCHECK(main_thread_.CalledOnValidThread());
- int threshold_bps;
- if (current_codec_.numberOfSimulcastStreams == 0) {
- threshold_bps = current_codec_.minBitrate * 1000;
- } else {
- threshold_bps = current_codec_.simulcastStream[0].minBitrate * 1000;
- }
- // Set the hysteresis window to be at 10% of the threshold, but at least
- // 10 kbps.
- int window_bps = std::max(threshold_bps / 10, 10000);
- _mediaOpt.SuspendBelowMinBitrate(threshold_bps, window_bps);
-}
-
-bool VideoSender::VideoSuspended() const {
- rtc::CritScope lock(&send_crit_);
- return _mediaOpt.IsVideoSuspended();
-}
-} // namespace vcm
-} // namespace webrtc