blob: e0597b75788bc40418d1f999334bbe7770bb9666 [file] [log] [blame]
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020011
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +000012#include <algorithm> // std::max
13
Jiawei Ou4206a0a2018-07-20 15:49:43 -070014#include "api/video/video_bitrate_allocator.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020015#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "common_video/libyuv/include/webrtc_libyuv.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/video_coding/encoded_frame.h"
18#include "modules/video_coding/include/video_codec_interface.h"
19#include "modules/video_coding/utility/default_video_bitrate_allocator.h"
20#include "modules/video_coding/utility/quality_scaler.h"
21#include "modules/video_coding/video_coding_impl.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/logging.h"
24#include "system_wrappers/include/clock.h"
Rasmus Brandt5438bce2018-09-03 13:30:46 +020025#include "system_wrappers/include/field_trial.h"
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000026
27namespace webrtc {
28namespace vcm {
29
Rasmus Brandt5438bce2018-09-03 13:30:46 +020030namespace {
31
32constexpr char kFrameDropperFieldTrial[] = "WebRTC-FrameDropper";
33
34} // namespace
35
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000036VideoSender::VideoSender(Clock* clock,
Niels Möllera0565992017-10-24 11:37:08 +020037 EncodedImageCallback* post_encode_callback)
38 : _encoder(nullptr),
39 _mediaOpt(clock),
perkj376b1922016-05-02 11:35:24 -070040 _encodedFrameCallback(post_encode_callback, &_mediaOpt),
kthelgason876222f2016-11-29 01:44:11 -080041 post_encode_callback_(post_encode_callback),
perkjf5b2e512016-07-05 08:34:04 -070042 _codecDataBase(&_encodedFrameCallback),
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000043 frame_dropper_enabled_(true),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000044 current_codec_(),
Erik Språng566124a2018-04-23 12:32:22 +020045 encoder_params_({VideoBitrateAllocation(), 0, 0, 0}),
Peter Boström233bfd22016-01-18 20:23:40 +010046 encoder_has_internal_source_(false),
47 next_frame_types_(1, kVideoFrameDelta) {
Peter Boströmad6fc5a2016-05-12 03:01:31 +020048 _mediaOpt.Reset();
tommi@webrtc.org658d2012015-03-05 12:21:54 +000049 // Allow VideoSender to be created on one thread but used on another, post
50 // construction. This is currently how this class is being used by at least
51 // one external project (diffractor).
perkj4e417b22016-07-14 23:35:55 -070052 sequenced_checker_.Detach();
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000053}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000054
Peter Boströmdcb89982015-09-15 14:43:47 +020055VideoSender::~VideoSender() {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000056
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000057// Register the send codec to be used.
58int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec,
59 uint32_t numberOfCores,
60 uint32_t maxPayloadSize) {
perkj4e417b22016-07-14 23:35:55 -070061 RTC_DCHECK(sequenced_checker_.CalledSequentially());
Peter Boström233bfd22016-01-18 20:23:40 +010062 rtc::CritScope lock(&encoder_crit_);
mflodmanfcf54bd2015-04-14 21:28:08 +020063 if (sendCodec == nullptr) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000064 return VCM_PARAMETER_ERROR;
65 }
66
Peter Boström4f5db112015-10-29 16:53:59 +010067 bool ret =
68 _codecDataBase.SetSendCodec(sendCodec, numberOfCores, maxPayloadSize);
pbos@webrtc.orgda2c4ce2013-09-17 09:38:41 +000069
70 // Update encoder regardless of result to make sure that we're not holding on
71 // to a deleted instance.
72 _encoder = _codecDataBase.GetEncoder();
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000073 // Cache the current codec here so they can be fetched from this thread
74 // without requiring the _sendCritSect lock.
75 current_codec_ = *sendCodec;
pbos@webrtc.orgda2c4ce2013-09-17 09:38:41 +000076
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000077 if (!ret) {
Niels Möller2e1d7842018-02-23 15:41:13 +010078 RTC_LOG(LS_ERROR) << "Failed to initialize set encoder with codec type '"
79 << sendCodec->codecType << "'.";
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000080 return VCM_CODEC_ERROR;
81 }
82
Peter Boström233bfd22016-01-18 20:23:40 +010083 // SetSendCodec succeeded, _encoder should be set.
84 RTC_DCHECK(_encoder);
85
ivicac7199c22015-10-07 06:43:33 -070086 int numLayers;
87 if (sendCodec->codecType == kVideoCodecVP8) {
hta257dc392016-10-25 09:05:06 -070088 numLayers = sendCodec->VP8().numberOfTemporalLayers;
ivicac7199c22015-10-07 06:43:33 -070089 } else if (sendCodec->codecType == kVideoCodecVP9) {
hta257dc392016-10-25 09:05:06 -070090 numLayers = sendCodec->VP9().numberOfTemporalLayers;
sprang4847ae62017-06-27 07:06:52 -070091 } else if (sendCodec->codecType == kVideoCodecGeneric &&
92 sendCodec->numberOfSimulcastStreams > 0) {
93 // This is mainly for unit testing, disabling frame dropping.
94 // TODO(sprang): Add a better way to disable frame dropping.
95 numLayers = sendCodec->simulcastStream[0].numberOfTemporalLayers;
ivicac7199c22015-10-07 06:43:33 -070096 } else {
97 numLayers = 1;
98 }
99
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000100 // If we have screensharing and we have layers, we disable frame dropper.
Rasmus Brandt5438bce2018-09-03 13:30:46 +0200101 const bool disable_frame_dropper =
102 field_trial::IsDisabled(kFrameDropperFieldTrial) ||
103 (numLayers > 1 && sendCodec->mode == VideoCodecMode::kScreensharing);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000104 if (disable_frame_dropper) {
105 _mediaOpt.EnableFrameDropper(false);
106 } else if (frame_dropper_enabled_) {
107 _mediaOpt.EnableFrameDropper(true);
108 }
sprang1a646ee2016-12-01 06:34:11 -0800109
Peter Boström233bfd22016-01-18 20:23:40 +0100110 {
111 rtc::CritScope cs(&params_crit_);
112 next_frame_types_.clear();
113 next_frame_types_.resize(VCM_MAX(sendCodec->numberOfSimulcastStreams, 1),
114 kVideoFrameKey);
115 // Cache InternalSource() to have this available from IntraFrameRequest()
116 // without having to acquire encoder_crit_ (avoid blocking on encoder use).
117 encoder_has_internal_source_ = _encoder->InternalSource();
118 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000119
Mirko Bonadei675513b2017-11-09 11:09:25 +0100120 RTC_LOG(LS_VERBOSE) << " max bitrate " << sendCodec->maxBitrate
121 << " start bitrate " << sendCodec->startBitrate
122 << " max frame rate " << sendCodec->maxFramerate
123 << " max payload size " << maxPayloadSize;
Per69b332d2016-06-02 15:45:42 +0200124 _mediaOpt.SetEncodingData(sendCodec->maxBitrate * 1000,
asapersson60dfbdb2017-08-07 00:03:03 -0700125 sendCodec->startBitrate * 1000,
126 sendCodec->maxFramerate);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000127 return VCM_OK;
128}
129
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000130// Register an external decoder object.
131// This can not be used together with external decoder callbacks.
Peter Boström795dbe42015-11-27 14:09:07 +0100132void VideoSender::RegisterExternalEncoder(VideoEncoder* externalEncoder,
philipel5908c712015-12-21 08:23:20 -0800133 bool internalSource /*= false*/) {
perkj4e417b22016-07-14 23:35:55 -0700134 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000135
Peter Boström233bfd22016-01-18 20:23:40 +0100136 rtc::CritScope lock(&encoder_crit_);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000137
mflodmanfcf54bd2015-04-14 21:28:08 +0200138 if (externalEncoder == nullptr) {
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100139 _codecDataBase.DeregisterExternalEncoder();
140 {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000141 // Make sure the VCM doesn't use the de-registered codec
Peter Boström233bfd22016-01-18 20:23:40 +0100142 rtc::CritScope params_lock(&params_crit_);
mflodmanfcf54bd2015-04-14 21:28:08 +0200143 _encoder = nullptr;
Peter Boström233bfd22016-01-18 20:23:40 +0100144 encoder_has_internal_source_ = false;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000145 }
Peter Boström795dbe42015-11-27 14:09:07 +0100146 return;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000147 }
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200148 _codecDataBase.RegisterExternalEncoder(externalEncoder,
149 internalSource);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000150}
151
Erik Språng08127a92016-11-16 16:41:30 +0100152EncoderParameters VideoSender::UpdateEncoderParameters(
153 const EncoderParameters& params,
154 VideoBitrateAllocator* bitrate_allocator,
155 uint32_t target_bitrate_bps) {
asapersson9abd2752016-12-08 02:19:40 -0800156 uint32_t video_target_rate_bps = _mediaOpt.SetTargetRates(target_bitrate_bps);
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000157 uint32_t input_frame_rate = _mediaOpt.InputFrameRate();
sprang40217c32016-11-21 05:41:52 -0800158 if (input_frame_rate == 0)
159 input_frame_rate = current_codec_.maxFramerate;
160
Erik Språng566124a2018-04-23 12:32:22 +0200161 VideoBitrateAllocation bitrate_allocation;
sprang4847ae62017-06-27 07:06:52 -0700162 // Only call allocators if bitrate > 0 (ie, not suspended), otherwise they
163 // might cap the bitrate to the min bitrate configured.
164 if (target_bitrate_bps > 0) {
165 if (bitrate_allocator) {
166 bitrate_allocation = bitrate_allocator->GetAllocation(
167 video_target_rate_bps, input_frame_rate);
168 } else {
169 DefaultVideoBitrateAllocator default_allocator(current_codec_);
170 bitrate_allocation = default_allocator.GetAllocation(
171 video_target_rate_bps, input_frame_rate);
172 }
Erik Språng08127a92016-11-16 16:41:30 +0100173 }
Erik Språng08127a92016-11-16 16:41:30 +0100174 EncoderParameters new_encoder_params = {bitrate_allocation, params.loss_rate,
175 params.rtt, input_frame_rate};
176 return new_encoder_params;
177}
178
Niels Möller96d7f762018-01-30 11:27:16 +0100179void VideoSender::UpdateChannelParameters(
sprang1a646ee2016-12-01 06:34:11 -0800180 VideoBitrateAllocator* bitrate_allocator,
181 VideoBitrateAllocationObserver* bitrate_updated_callback) {
Erik Språng566124a2018-04-23 12:32:22 +0200182 VideoBitrateAllocation target_rate;
sprang1a646ee2016-12-01 06:34:11 -0800183 {
184 rtc::CritScope cs(&params_crit_);
185 encoder_params_ =
186 UpdateEncoderParameters(encoder_params_, bitrate_allocator,
187 encoder_params_.target_bitrate.get_sum_bps());
188 target_rate = encoder_params_.target_bitrate;
189 }
sprang4847ae62017-06-27 07:06:52 -0700190 if (bitrate_updated_callback && target_rate.get_sum_bps() > 0)
sprang1a646ee2016-12-01 06:34:11 -0800191 bitrate_updated_callback->OnBitrateAllocationUpdated(target_rate);
Erik Språng08127a92016-11-16 16:41:30 +0100192}
193
194int32_t VideoSender::SetChannelParameters(
195 uint32_t target_bitrate_bps,
sprang1a646ee2016-12-01 06:34:11 -0800196 uint8_t loss_rate,
Erik Språng08127a92016-11-16 16:41:30 +0100197 int64_t rtt,
sprang1a646ee2016-12-01 06:34:11 -0800198 VideoBitrateAllocator* bitrate_allocator,
199 VideoBitrateAllocationObserver* bitrate_updated_callback) {
Erik Språng08127a92016-11-16 16:41:30 +0100200 EncoderParameters encoder_params;
sprang1a646ee2016-12-01 06:34:11 -0800201 encoder_params.loss_rate = loss_rate;
Erik Språng08127a92016-11-16 16:41:30 +0100202 encoder_params.rtt = rtt;
203 encoder_params = UpdateEncoderParameters(encoder_params, bitrate_allocator,
204 target_bitrate_bps);
sprang4847ae62017-06-27 07:06:52 -0700205 if (bitrate_updated_callback && target_bitrate_bps > 0) {
sprang1a646ee2016-12-01 06:34:11 -0800206 bitrate_updated_callback->OnBitrateAllocationUpdated(
207 encoder_params.target_bitrate);
208 }
Erik Språng08127a92016-11-16 16:41:30 +0100209
noahricd4badbc2016-04-13 14:59:48 -0700210 bool encoder_has_internal_source;
211 {
212 rtc::CritScope cs(&params_crit_);
213 encoder_params_ = encoder_params;
214 encoder_has_internal_source = encoder_has_internal_source_;
215 }
216
217 // For encoders with internal sources, we need to tell the encoder directly,
218 // instead of waiting for an AddVideoFrame that will never come (internal
219 // source encoders don't get input frames).
220 if (encoder_has_internal_source) {
221 rtc::CritScope cs(&encoder_crit_);
222 if (_encoder) {
perkj57c21f92016-06-17 07:27:16 -0700223 SetEncoderParameters(encoder_params, encoder_has_internal_source);
noahricd4badbc2016-04-13 14:59:48 -0700224 }
225 }
Erik Språng66a641a2015-06-11 14:20:07 +0200226
227 return VCM_OK;
228}
229
perkj57c21f92016-06-17 07:27:16 -0700230void VideoSender::SetEncoderParameters(EncoderParameters params,
231 bool has_internal_source) {
perkjfea93092016-05-14 00:58:48 -0700232 // |target_bitrate == 0 | means that the network is down or the send pacer is
perkj57c21f92016-06-17 07:27:16 -0700233 // full. We currently only report this if the encoder has an internal source.
234 // If the encoder does not have an internal source, higher levels are expected
235 // to not call AddVideoFrame. We do this since its unclear how current
236 // encoder implementations behave when given a zero target bitrate.
237 // TODO(perkj): Make sure all known encoder implementations handle zero
238 // target bitrate and remove this check.
Erik Språng08127a92016-11-16 16:41:30 +0100239 if (!has_internal_source && params.target_bitrate.get_sum_bps() == 0)
Peter Boströmdcb89982015-09-15 14:43:47 +0200240 return;
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000241
Erik Språng66a641a2015-06-11 14:20:07 +0200242 if (params.input_frame_rate == 0) {
243 // No frame rate estimate available, use default.
244 params.input_frame_rate = current_codec_.maxFramerate;
245 }
Peter Boström69ccb332015-10-29 16:30:23 +0100246 if (_encoder != nullptr)
247 _encoder->SetEncoderParameters(params);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000248}
249
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000250// Add one raw video frame to the encoder, blocking.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700251int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame,
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000252 const CodecSpecificInfo* codecSpecificInfo) {
Peter Boströmdcb89982015-09-15 14:43:47 +0200253 EncoderParameters encoder_params;
Peter Boström233bfd22016-01-18 20:23:40 +0100254 std::vector<FrameType> next_frame_types;
perkj57c21f92016-06-17 07:27:16 -0700255 bool encoder_has_internal_source = false;
Peter Boströmdcb89982015-09-15 14:43:47 +0200256 {
Peter Boström233bfd22016-01-18 20:23:40 +0100257 rtc::CritScope lock(&params_crit_);
Peter Boströmdcb89982015-09-15 14:43:47 +0200258 encoder_params = encoder_params_;
Peter Boström233bfd22016-01-18 20:23:40 +0100259 next_frame_types = next_frame_types_;
perkj57c21f92016-06-17 07:27:16 -0700260 encoder_has_internal_source = encoder_has_internal_source_;
Peter Boströmdcb89982015-09-15 14:43:47 +0200261 }
Peter Boström233bfd22016-01-18 20:23:40 +0100262 rtc::CritScope lock(&encoder_crit_);
Peter Boström69ccb332015-10-29 16:30:23 +0100263 if (_encoder == nullptr)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000264 return VCM_UNINITIALIZED;
perkj57c21f92016-06-17 07:27:16 -0700265 SetEncoderParameters(encoder_params, encoder_has_internal_source);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000266 if (_mediaOpt.DropFrame()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100267 RTC_LOG(LS_VERBOSE) << "Drop Frame "
268 << "target bitrate "
269 << encoder_params.target_bitrate.get_sum_bps()
270 << " loss rate " << encoder_params.loss_rate << " rtt "
271 << encoder_params.rtt << " input frame rate "
272 << encoder_params.input_frame_rate;
Ilya Nikolaevskiyd79314f2017-10-23 10:45:37 +0200273 post_encode_callback_->OnDroppedFrame(
274 EncodedImageCallback::DropReason::kDroppedByMediaOptimizations);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000275 return VCM_OK;
276 }
pbos@webrtc.org67a9e402015-03-05 13:57:37 +0000277 // TODO(pbos): Make sure setting send codec is synchronized with video
278 // processing so frame size always matches.
279 if (!_codecDataBase.MatchesCurrentResolution(videoFrame.width(),
280 videoFrame.height())) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100281 RTC_LOG(LS_ERROR)
282 << "Incoming frame doesn't match set resolution. Dropping.";
pbos@webrtc.org67a9e402015-03-05 13:57:37 +0000283 return VCM_PARAMETER_ERROR;
284 }
Peter Boströmeb66e802015-06-05 11:08:03 +0200285 VideoFrame converted_frame = videoFrame;
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000286 const VideoFrameBuffer::Type buffer_type =
287 converted_frame.video_frame_buffer()->type();
288 const bool is_buffer_type_supported =
289 buffer_type == VideoFrameBuffer::Type::kI420 ||
290 (buffer_type == VideoFrameBuffer::Type::kNative &&
291 _encoder->SupportsNativeHandle());
292 if (!is_buffer_type_supported) {
Peter Boströmeb66e802015-06-05 11:08:03 +0200293 // This module only supports software encoding.
294 // TODO(pbos): Offload conversion from the encoder thread.
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000295 rtc::scoped_refptr<I420BufferInterface> converted_buffer(
296 converted_frame.video_frame_buffer()->ToI420());
nisseca6d5d12016-06-17 05:03:04 -0700297
298 if (!converted_buffer) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100299 RTC_LOG(LS_ERROR) << "Frame conversion failed, dropping frame.";
nisseca6d5d12016-06-17 05:03:04 -0700300 return VCM_PARAMETER_ERROR;
301 }
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200302 converted_frame = VideoFrame(converted_buffer,
303 converted_frame.timestamp(),
nisseca6d5d12016-06-17 05:03:04 -0700304 converted_frame.render_time_ms(),
305 converted_frame.rotation());
Peter Boströmeb66e802015-06-05 11:08:03 +0200306 }
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000307 int32_t ret =
Peter Boström233bfd22016-01-18 20:23:40 +0100308 _encoder->Encode(converted_frame, codecSpecificInfo, next_frame_types);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000309 if (ret < 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100310 RTC_LOG(LS_ERROR) << "Failed to encode frame. Error code: " << ret;
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000311 return ret;
312 }
perkj376b1922016-05-02 11:35:24 -0700313
Peter Boström233bfd22016-01-18 20:23:40 +0100314 {
Peter Boström233bfd22016-01-18 20:23:40 +0100315 rtc::CritScope lock(&params_crit_);
perkj376b1922016-05-02 11:35:24 -0700316 // Change all keyframe requests to encode delta frames the next time.
Peter Boström233bfd22016-01-18 20:23:40 +0100317 for (size_t i = 0; i < next_frame_types_.size(); ++i) {
318 // Check for equality (same requested as before encoding) to not
319 // accidentally drop a keyframe request while encoding.
320 if (next_frame_types[i] == next_frame_types_[i])
321 next_frame_types_[i] = kVideoFrameDelta;
322 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000323 }
324 return VCM_OK;
325}
326
perkj600246e2016-05-04 11:26:51 -0700327int32_t VideoSender::IntraFrameRequest(size_t stream_index) {
Peter Boström233bfd22016-01-18 20:23:40 +0100328 {
329 rtc::CritScope lock(&params_crit_);
perkj600246e2016-05-04 11:26:51 -0700330 if (stream_index >= next_frame_types_.size()) {
Peter Boström233bfd22016-01-18 20:23:40 +0100331 return -1;
332 }
333 next_frame_types_[stream_index] = kVideoFrameKey;
334 if (!encoder_has_internal_source_)
335 return VCM_OK;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000336 }
Peter Boström233bfd22016-01-18 20:23:40 +0100337 // TODO(pbos): Remove when InternalSource() is gone. Both locks have to be
338 // held here for internal consistency, since _encoder could be removed while
339 // not holding encoder_crit_. Checks have to be performed again since
340 // params_crit_ was dropped to not cause lock-order inversions with
341 // encoder_crit_.
342 rtc::CritScope lock(&encoder_crit_);
343 rtc::CritScope params_lock(&params_crit_);
perkj600246e2016-05-04 11:26:51 -0700344 if (stream_index >= next_frame_types_.size())
Peter Boström233bfd22016-01-18 20:23:40 +0100345 return -1;
mflodmanfcf54bd2015-04-14 21:28:08 +0200346 if (_encoder != nullptr && _encoder->InternalSource()) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000347 // Try to request the frame if we have an external encoder with
348 // internal source since AddVideoFrame never will be called.
Peter Boström233bfd22016-01-18 20:23:40 +0100349 if (_encoder->RequestFrame(next_frame_types_) == WEBRTC_VIDEO_CODEC_OK) {
350 // Try to remove just-performed keyframe request, if stream still exists.
351 next_frame_types_[stream_index] = kVideoFrameDelta;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000352 }
353 }
354 return VCM_OK;
355}
356
357int32_t VideoSender::EnableFrameDropper(bool enable) {
Peter Boström233bfd22016-01-18 20:23:40 +0100358 rtc::CritScope lock(&encoder_crit_);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000359 frame_dropper_enabled_ = enable;
360 _mediaOpt.EnableFrameDropper(enable);
361 return VCM_OK;
362}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000363} // namespace vcm
364} // namespace webrtc