blob: b7664a719b3a7d155d23666df94663928087bc8c [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
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000011
henrik.lundin@webrtc.org1a3a6e52013-10-28 10:16:14 +000012#include <algorithm> // std::max
13
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000014#include "webrtc/base/checks.h"
pbos854e84c2015-11-16 16:39:06 -080015#include "webrtc/base/logging.h"
philipel5908c712015-12-21 08:23:20 -080016#include "webrtc/common_types.h"
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000017#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010018#include "webrtc/modules/video_coding/include/video_codec_interface.h"
19#include "webrtc/modules/video_coding/encoded_frame.h"
kjellander@webrtc.orgb7ce9642015-11-18 23:04:10 +010020#include "webrtc/modules/video_coding/utility/quality_scaler.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010021#include "webrtc/modules/video_coding/video_coding_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010022#include "webrtc/system_wrappers/include/clock.h"
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000023
24namespace webrtc {
25namespace vcm {
26
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000027VideoSender::VideoSender(Clock* clock,
pbos@webrtc.org891d4832015-02-26 13:15:22 +000028 EncodedImageCallback* post_encode_callback,
perkj376b1922016-05-02 11:35:24 -070029 VCMSendStatisticsCallback* send_stats_callback)
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000030 : clock_(clock),
Peter Boström9dbbcfb2015-04-21 15:55:11 +020031 _encoder(nullptr),
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000032 _mediaOpt(clock_),
perkj376b1922016-05-02 11:35:24 -070033 _encodedFrameCallback(post_encode_callback, &_mediaOpt),
34 send_stats_callback_(send_stats_callback),
perkjf5b2e512016-07-05 08:34:04 -070035 _codecDataBase(&_encodedFrameCallback),
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000036 frame_dropper_enabled_(true),
andresp@webrtc.orge682aa52013-12-19 10:59:48 +000037 _sendStatsTimer(1000, clock_),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000038 current_codec_(),
sprang1369c832016-11-10 08:30:33 -080039 encoder_params_({0, 0, 0, 0}),
Peter Boström233bfd22016-01-18 20:23:40 +010040 encoder_has_internal_source_(false),
41 next_frame_types_(1, kVideoFrameDelta) {
Peter Boströmad6fc5a2016-05-12 03:01:31 +020042 _mediaOpt.Reset();
tommi@webrtc.org658d2012015-03-05 12:21:54 +000043 // Allow VideoSender to be created on one thread but used on another, post
44 // construction. This is currently how this class is being used by at least
45 // one external project (diffractor).
perkj4e417b22016-07-14 23:35:55 -070046 sequenced_checker_.Detach();
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000047}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000048
Peter Boströmdcb89982015-09-15 14:43:47 +020049VideoSender::~VideoSender() {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000050
pbosa26ac922016-02-25 04:50:01 -080051void VideoSender::Process() {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000052 if (_sendStatsTimer.TimeUntilProcess() == 0) {
perkj376b1922016-05-02 11:35:24 -070053 // |_sendStatsTimer.Processed()| must be called. Otherwise
54 // VideoSender::Process() will be called in an infinite loop.
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000055 _sendStatsTimer.Processed();
perkj376b1922016-05-02 11:35:24 -070056 if (send_stats_callback_) {
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000057 uint32_t bitRate = _mediaOpt.SentBitRate();
58 uint32_t frameRate = _mediaOpt.SentFrameRate();
perkj275afc52016-09-01 00:21:16 -070059 send_stats_callback_->SendStatistics(bitRate, frameRate);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000060 }
61 }
62
Erik Språng66a641a2015-06-11 14:20:07 +020063 {
Peter Boström233bfd22016-01-18 20:23:40 +010064 rtc::CritScope cs(&params_crit_);
Erik Språng66a641a2015-06-11 14:20:07 +020065 // Force an encoder parameters update, so that incoming frame rate is
66 // updated even if bandwidth hasn't changed.
67 encoder_params_.input_frame_rate = _mediaOpt.InputFrameRate();
Erik Språng66a641a2015-06-11 14:20:07 +020068 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000069}
70
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000071int64_t VideoSender::TimeUntilNextProcess() {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000072 return _sendStatsTimer.TimeUntilProcess();
73}
74
75// Register the send codec to be used.
76int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec,
77 uint32_t numberOfCores,
78 uint32_t maxPayloadSize) {
perkj4e417b22016-07-14 23:35:55 -070079 RTC_DCHECK(sequenced_checker_.CalledSequentially());
Peter Boström233bfd22016-01-18 20:23:40 +010080 rtc::CritScope lock(&encoder_crit_);
mflodmanfcf54bd2015-04-14 21:28:08 +020081 if (sendCodec == nullptr) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000082 return VCM_PARAMETER_ERROR;
83 }
84
Peter Boström4f5db112015-10-29 16:53:59 +010085 bool ret =
86 _codecDataBase.SetSendCodec(sendCodec, numberOfCores, maxPayloadSize);
pbos@webrtc.orgda2c4ce2013-09-17 09:38:41 +000087
88 // Update encoder regardless of result to make sure that we're not holding on
89 // to a deleted instance.
90 _encoder = _codecDataBase.GetEncoder();
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000091 // Cache the current codec here so they can be fetched from this thread
92 // without requiring the _sendCritSect lock.
93 current_codec_ = *sendCodec;
pbos@webrtc.orgda2c4ce2013-09-17 09:38:41 +000094
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000095 if (!ret) {
pbos@webrtc.org0b52ceb2015-03-24 11:20:54 +000096 LOG(LS_ERROR) << "Failed to initialize set encoder with payload name '"
97 << sendCodec->plName << "'.";
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000098 return VCM_CODEC_ERROR;
99 }
100
Peter Boström233bfd22016-01-18 20:23:40 +0100101 // SetSendCodec succeeded, _encoder should be set.
102 RTC_DCHECK(_encoder);
103
ivicac7199c22015-10-07 06:43:33 -0700104 int numLayers;
105 if (sendCodec->codecType == kVideoCodecVP8) {
hta257dc392016-10-25 09:05:06 -0700106 numLayers = sendCodec->VP8().numberOfTemporalLayers;
ivicac7199c22015-10-07 06:43:33 -0700107 } else if (sendCodec->codecType == kVideoCodecVP9) {
hta257dc392016-10-25 09:05:06 -0700108 numLayers = sendCodec->VP9().numberOfTemporalLayers;
ivicac7199c22015-10-07 06:43:33 -0700109 } else {
110 numLayers = 1;
111 }
112
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000113 // If we have screensharing and we have layers, we disable frame dropper.
114 bool disable_frame_dropper =
115 numLayers > 1 && sendCodec->mode == kScreensharing;
116 if (disable_frame_dropper) {
117 _mediaOpt.EnableFrameDropper(false);
118 } else if (frame_dropper_enabled_) {
119 _mediaOpt.EnableFrameDropper(true);
120 }
Peter Boström233bfd22016-01-18 20:23:40 +0100121 {
122 rtc::CritScope cs(&params_crit_);
123 next_frame_types_.clear();
124 next_frame_types_.resize(VCM_MAX(sendCodec->numberOfSimulcastStreams, 1),
125 kVideoFrameKey);
126 // Cache InternalSource() to have this available from IntraFrameRequest()
127 // without having to acquire encoder_crit_ (avoid blocking on encoder use).
128 encoder_has_internal_source_ = _encoder->InternalSource();
129 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000130
isheriff7620be82016-03-06 23:22:33 -0800131 LOG(LS_VERBOSE) << " max bitrate " << sendCodec->maxBitrate
132 << " start bitrate " << sendCodec->startBitrate
133 << " max frame rate " << sendCodec->maxFramerate
134 << " max payload size " << maxPayloadSize;
Per69b332d2016-06-02 15:45:42 +0200135 _mediaOpt.SetEncodingData(sendCodec->maxBitrate * 1000,
philipel5908c712015-12-21 08:23:20 -0800136 sendCodec->startBitrate * 1000, sendCodec->width,
137 sendCodec->height, sendCodec->maxFramerate,
138 numLayers, maxPayloadSize);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000139 return VCM_OK;
140}
141
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000142// Register an external decoder object.
143// This can not be used together with external decoder callbacks.
Peter Boström795dbe42015-11-27 14:09:07 +0100144void VideoSender::RegisterExternalEncoder(VideoEncoder* externalEncoder,
philipel5908c712015-12-21 08:23:20 -0800145 uint8_t payloadType,
146 bool internalSource /*= false*/) {
perkj4e417b22016-07-14 23:35:55 -0700147 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000148
Peter Boström233bfd22016-01-18 20:23:40 +0100149 rtc::CritScope lock(&encoder_crit_);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000150
mflodmanfcf54bd2015-04-14 21:28:08 +0200151 if (externalEncoder == nullptr) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000152 bool wasSendCodec = false;
Peter Boström795dbe42015-11-27 14:09:07 +0100153 RTC_CHECK(
154 _codecDataBase.DeregisterExternalEncoder(payloadType, &wasSendCodec));
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000155 if (wasSendCodec) {
156 // Make sure the VCM doesn't use the de-registered codec
Peter Boström233bfd22016-01-18 20:23:40 +0100157 rtc::CritScope params_lock(&params_crit_);
mflodmanfcf54bd2015-04-14 21:28:08 +0200158 _encoder = nullptr;
Peter Boström233bfd22016-01-18 20:23:40 +0100159 encoder_has_internal_source_ = false;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000160 }
Peter Boström795dbe42015-11-27 14:09:07 +0100161 return;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000162 }
philipel5908c712015-12-21 08:23:20 -0800163 _codecDataBase.RegisterExternalEncoder(externalEncoder, payloadType,
164 internalSource);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000165}
166
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000167// Get encode bitrate
168int VideoSender::Bitrate(unsigned int* bitrate) const {
perkj4e417b22016-07-14 23:35:55 -0700169 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000170 // Since we're running on the thread that's the only thread known to modify
171 // the value of _encoder, we don't need to grab the lock here.
172
Peter Boström69ccb332015-10-29 16:30:23 +0100173 if (!_encoder)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000174 return VCM_UNINITIALIZED;
sprang1369c832016-11-10 08:30:33 -0800175 *bitrate = _encoder->GetEncoderParameters().target_bitrate;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000176 return 0;
177}
178
179// Get encode frame rate
180int VideoSender::FrameRate(unsigned int* framerate) const {
perkj4e417b22016-07-14 23:35:55 -0700181 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000182 // Since we're running on the thread that's the only thread known to modify
183 // the value of _encoder, we don't need to grab the lock here.
184
Peter Boström69ccb332015-10-29 16:30:23 +0100185 if (!_encoder)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000186 return VCM_UNINITIALIZED;
Peter Boström69ccb332015-10-29 16:30:23 +0100187
188 *framerate = _encoder->GetEncoderParameters().input_frame_rate;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000189 return 0;
190}
191
sprang1369c832016-11-10 08:30:33 -0800192int32_t VideoSender::SetChannelParameters(uint32_t target_bitrate,
193 uint8_t lossRate,
194 int64_t rtt) {
195 uint32_t target_rate =
196 _mediaOpt.SetTargetRates(target_bitrate, lossRate, rtt);
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000197
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000198 uint32_t input_frame_rate = _mediaOpt.InputFrameRate();
199
sprang1369c832016-11-10 08:30:33 -0800200 EncoderParameters encoder_params = {target_rate, lossRate, rtt,
noahricd4badbc2016-04-13 14:59:48 -0700201 input_frame_rate};
202 bool encoder_has_internal_source;
203 {
204 rtc::CritScope cs(&params_crit_);
205 encoder_params_ = encoder_params;
206 encoder_has_internal_source = encoder_has_internal_source_;
207 }
208
209 // For encoders with internal sources, we need to tell the encoder directly,
210 // instead of waiting for an AddVideoFrame that will never come (internal
211 // source encoders don't get input frames).
212 if (encoder_has_internal_source) {
213 rtc::CritScope cs(&encoder_crit_);
214 if (_encoder) {
perkj57c21f92016-06-17 07:27:16 -0700215 SetEncoderParameters(encoder_params, encoder_has_internal_source);
noahricd4badbc2016-04-13 14:59:48 -0700216 }
217 }
Erik Språng66a641a2015-06-11 14:20:07 +0200218
219 return VCM_OK;
220}
221
perkj57c21f92016-06-17 07:27:16 -0700222void VideoSender::SetEncoderParameters(EncoderParameters params,
223 bool has_internal_source) {
perkjfea93092016-05-14 00:58:48 -0700224 // |target_bitrate == 0 | means that the network is down or the send pacer is
perkj57c21f92016-06-17 07:27:16 -0700225 // full. We currently only report this if the encoder has an internal source.
226 // If the encoder does not have an internal source, higher levels are expected
227 // to not call AddVideoFrame. We do this since its unclear how current
228 // encoder implementations behave when given a zero target bitrate.
229 // TODO(perkj): Make sure all known encoder implementations handle zero
230 // target bitrate and remove this check.
sprang1369c832016-11-10 08:30:33 -0800231 if (!has_internal_source && params.target_bitrate == 0)
Peter Boströmdcb89982015-09-15 14:43:47 +0200232 return;
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000233
Erik Språng66a641a2015-06-11 14:20:07 +0200234 if (params.input_frame_rate == 0) {
235 // No frame rate estimate available, use default.
236 params.input_frame_rate = current_codec_.maxFramerate;
237 }
Peter Boström69ccb332015-10-29 16:30:23 +0100238 if (_encoder != nullptr)
239 _encoder->SetEncoderParameters(params);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000240}
241
Per69b332d2016-06-02 15:45:42 +0200242// Deprecated:
243// TODO(perkj): Remove once no projects call this method. It currently do
244// nothing.
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000245int32_t VideoSender::RegisterProtectionCallback(
andresp@webrtc.orge682aa52013-12-19 10:59:48 +0000246 VCMProtectionCallback* protection_callback) {
Per69b332d2016-06-02 15:45:42 +0200247 // Deprecated:
248 // TODO(perkj): Remove once no projects call this method. It currently do
249 // nothing.
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000250 return VCM_OK;
251}
252
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000253// Add one raw video frame to the encoder, blocking.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700254int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame,
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000255 const CodecSpecificInfo* codecSpecificInfo) {
Peter Boströmdcb89982015-09-15 14:43:47 +0200256 EncoderParameters encoder_params;
Peter Boström233bfd22016-01-18 20:23:40 +0100257 std::vector<FrameType> next_frame_types;
perkj57c21f92016-06-17 07:27:16 -0700258 bool encoder_has_internal_source = false;
Peter Boströmdcb89982015-09-15 14:43:47 +0200259 {
Peter Boström233bfd22016-01-18 20:23:40 +0100260 rtc::CritScope lock(&params_crit_);
Peter Boströmdcb89982015-09-15 14:43:47 +0200261 encoder_params = encoder_params_;
Peter Boström233bfd22016-01-18 20:23:40 +0100262 next_frame_types = next_frame_types_;
perkj57c21f92016-06-17 07:27:16 -0700263 encoder_has_internal_source = encoder_has_internal_source_;
Peter Boströmdcb89982015-09-15 14:43:47 +0200264 }
Peter Boström233bfd22016-01-18 20:23:40 +0100265 rtc::CritScope lock(&encoder_crit_);
Peter Boström69ccb332015-10-29 16:30:23 +0100266 if (_encoder == nullptr)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000267 return VCM_UNINITIALIZED;
perkj57c21f92016-06-17 07:27:16 -0700268 SetEncoderParameters(encoder_params, encoder_has_internal_source);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000269 if (_mediaOpt.DropFrame()) {
isheriff7620be82016-03-06 23:22:33 -0800270 LOG(LS_VERBOSE) << "Drop Frame "
sprang1369c832016-11-10 08:30:33 -0800271 << "target bitrate " << encoder_params.target_bitrate
isheriff7620be82016-03-06 23:22:33 -0800272 << " loss rate " << encoder_params.loss_rate << " rtt "
273 << encoder_params.rtt << " input frame rate "
274 << encoder_params.input_frame_rate;
jackychen61b4d512015-04-21 15:30:11 -0700275 _encoder->OnDroppedFrame();
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000276 return VCM_OK;
277 }
pbos@webrtc.org67a9e402015-03-05 13:57:37 +0000278 // TODO(pbos): Make sure setting send codec is synchronized with video
279 // processing so frame size always matches.
280 if (!_codecDataBase.MatchesCurrentResolution(videoFrame.width(),
281 videoFrame.height())) {
282 LOG(LS_ERROR) << "Incoming frame doesn't match set resolution. Dropping.";
283 return VCM_PARAMETER_ERROR;
284 }
Peter Boströmeb66e802015-06-05 11:08:03 +0200285 VideoFrame converted_frame = videoFrame;
nisse26acec42016-04-15 03:43:39 -0700286 if (converted_frame.video_frame_buffer()->native_handle() &&
287 !_encoder->SupportsNativeHandle()) {
Peter Boströmeb66e802015-06-05 11:08:03 +0200288 // This module only supports software encoding.
289 // TODO(pbos): Offload conversion from the encoder thread.
nisseca6d5d12016-06-17 05:03:04 -0700290 rtc::scoped_refptr<VideoFrameBuffer> converted_buffer(
291 converted_frame.video_frame_buffer()->NativeToI420Buffer());
292
293 if (!converted_buffer) {
294 LOG(LS_ERROR) << "Frame conversion failed, dropping frame.";
295 return VCM_PARAMETER_ERROR;
296 }
297 converted_frame = VideoFrame(converted_buffer,
298 converted_frame.timestamp(),
299 converted_frame.render_time_ms(),
300 converted_frame.rotation());
Peter Boströmeb66e802015-06-05 11:08:03 +0200301 }
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000302 int32_t ret =
Peter Boström233bfd22016-01-18 20:23:40 +0100303 _encoder->Encode(converted_frame, codecSpecificInfo, next_frame_types);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000304 if (ret < 0) {
305 LOG(LS_ERROR) << "Failed to encode frame. Error code: " << ret;
306 return ret;
307 }
perkj376b1922016-05-02 11:35:24 -0700308
Peter Boström233bfd22016-01-18 20:23:40 +0100309 {
Peter Boström233bfd22016-01-18 20:23:40 +0100310 rtc::CritScope lock(&params_crit_);
perkj376b1922016-05-02 11:35:24 -0700311 // Change all keyframe requests to encode delta frames the next time.
Peter Boström233bfd22016-01-18 20:23:40 +0100312 for (size_t i = 0; i < next_frame_types_.size(); ++i) {
313 // Check for equality (same requested as before encoding) to not
314 // accidentally drop a keyframe request while encoding.
315 if (next_frame_types[i] == next_frame_types_[i])
316 next_frame_types_[i] = kVideoFrameDelta;
317 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000318 }
319 return VCM_OK;
320}
321
perkj600246e2016-05-04 11:26:51 -0700322int32_t VideoSender::IntraFrameRequest(size_t stream_index) {
Peter Boström233bfd22016-01-18 20:23:40 +0100323 {
324 rtc::CritScope lock(&params_crit_);
perkj600246e2016-05-04 11:26:51 -0700325 if (stream_index >= next_frame_types_.size()) {
Peter Boström233bfd22016-01-18 20:23:40 +0100326 return -1;
327 }
328 next_frame_types_[stream_index] = kVideoFrameKey;
329 if (!encoder_has_internal_source_)
330 return VCM_OK;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000331 }
Peter Boström233bfd22016-01-18 20:23:40 +0100332 // TODO(pbos): Remove when InternalSource() is gone. Both locks have to be
333 // held here for internal consistency, since _encoder could be removed while
334 // not holding encoder_crit_. Checks have to be performed again since
335 // params_crit_ was dropped to not cause lock-order inversions with
336 // encoder_crit_.
337 rtc::CritScope lock(&encoder_crit_);
338 rtc::CritScope params_lock(&params_crit_);
perkj600246e2016-05-04 11:26:51 -0700339 if (stream_index >= next_frame_types_.size())
Peter Boström233bfd22016-01-18 20:23:40 +0100340 return -1;
mflodmanfcf54bd2015-04-14 21:28:08 +0200341 if (_encoder != nullptr && _encoder->InternalSource()) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000342 // Try to request the frame if we have an external encoder with
343 // internal source since AddVideoFrame never will be called.
Peter Boström233bfd22016-01-18 20:23:40 +0100344 if (_encoder->RequestFrame(next_frame_types_) == WEBRTC_VIDEO_CODEC_OK) {
345 // Try to remove just-performed keyframe request, if stream still exists.
346 next_frame_types_[stream_index] = kVideoFrameDelta;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000347 }
348 }
349 return VCM_OK;
350}
351
352int32_t VideoSender::EnableFrameDropper(bool enable) {
Peter Boström233bfd22016-01-18 20:23:40 +0100353 rtc::CritScope lock(&encoder_crit_);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000354 frame_dropper_enabled_ = enable;
355 _mediaOpt.EnableFrameDropper(enable);
356 return VCM_OK;
357}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000358} // namespace vcm
359} // namespace webrtc