blob: 3dabbfca097cc90a8aef8a30a2bff309fcdaaf39 [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"
Erik Språng08127a92016-11-16 16:41:30 +010017#include "webrtc/common_video/include/video_bitrate_allocator.h"
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000018#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
Erik Språng08127a92016-11-16 16:41:30 +010019#include "webrtc/modules/video_coding/codecs/vp8/temporal_layers.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010020#include "webrtc/modules/video_coding/include/video_codec_interface.h"
21#include "webrtc/modules/video_coding/encoded_frame.h"
Erik Språng08127a92016-11-16 16:41:30 +010022#include "webrtc/modules/video_coding/utility/default_video_bitrate_allocator.h"
kjellander@webrtc.orgb7ce9642015-11-18 23:04:10 +010023#include "webrtc/modules/video_coding/utility/quality_scaler.h"
Henrik Kjellander2557b862015-11-18 22:00:21 +010024#include "webrtc/modules/video_coding/video_coding_impl.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010025#include "webrtc/system_wrappers/include/clock.h"
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000026
27namespace webrtc {
28namespace vcm {
29
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000030VideoSender::VideoSender(Clock* clock,
pbos@webrtc.org891d4832015-02-26 13:15:22 +000031 EncodedImageCallback* post_encode_callback,
perkj376b1922016-05-02 11:35:24 -070032 VCMSendStatisticsCallback* send_stats_callback)
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000033 : clock_(clock),
Peter Boström9dbbcfb2015-04-21 15:55:11 +020034 _encoder(nullptr),
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000035 _mediaOpt(clock_),
perkj376b1922016-05-02 11:35:24 -070036 _encodedFrameCallback(post_encode_callback, &_mediaOpt),
kthelgason876222f2016-11-29 01:44:11 -080037 post_encode_callback_(post_encode_callback),
perkj376b1922016-05-02 11:35:24 -070038 send_stats_callback_(send_stats_callback),
perkjf5b2e512016-07-05 08:34:04 -070039 _codecDataBase(&_encodedFrameCallback),
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000040 frame_dropper_enabled_(true),
sprang40217c32016-11-21 05:41:52 -080041 _sendStatsTimer(VCMProcessTimer::kDefaultProcessIntervalMs, clock_),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000042 current_codec_(),
Erik Språng08127a92016-11-16 16:41:30 +010043 encoder_params_({BitrateAllocation(), 0, 0, 0}),
Peter Boström233bfd22016-01-18 20:23:40 +010044 encoder_has_internal_source_(false),
45 next_frame_types_(1, kVideoFrameDelta) {
Peter Boströmad6fc5a2016-05-12 03:01:31 +020046 _mediaOpt.Reset();
tommi@webrtc.org658d2012015-03-05 12:21:54 +000047 // Allow VideoSender to be created on one thread but used on another, post
48 // construction. This is currently how this class is being used by at least
49 // one external project (diffractor).
perkj4e417b22016-07-14 23:35:55 -070050 sequenced_checker_.Detach();
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000051}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000052
Peter Boströmdcb89982015-09-15 14:43:47 +020053VideoSender::~VideoSender() {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000054
pbosa26ac922016-02-25 04:50:01 -080055void VideoSender::Process() {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000056 if (_sendStatsTimer.TimeUntilProcess() == 0) {
perkj376b1922016-05-02 11:35:24 -070057 // |_sendStatsTimer.Processed()| must be called. Otherwise
58 // VideoSender::Process() will be called in an infinite loop.
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000059 _sendStatsTimer.Processed();
perkj376b1922016-05-02 11:35:24 -070060 if (send_stats_callback_) {
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000061 uint32_t bitRate = _mediaOpt.SentBitRate();
62 uint32_t frameRate = _mediaOpt.SentFrameRate();
perkj275afc52016-09-01 00:21:16 -070063 send_stats_callback_->SendStatistics(bitRate, frameRate);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000064 }
65 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000066}
67
pkasting@chromium.org0b1534c2014-12-15 22:09:40 +000068int64_t VideoSender::TimeUntilNextProcess() {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000069 return _sendStatsTimer.TimeUntilProcess();
70}
71
72// Register the send codec to be used.
73int32_t VideoSender::RegisterSendCodec(const VideoCodec* sendCodec,
74 uint32_t numberOfCores,
75 uint32_t maxPayloadSize) {
perkj4e417b22016-07-14 23:35:55 -070076 RTC_DCHECK(sequenced_checker_.CalledSequentially());
Peter Boström233bfd22016-01-18 20:23:40 +010077 rtc::CritScope lock(&encoder_crit_);
mflodmanfcf54bd2015-04-14 21:28:08 +020078 if (sendCodec == nullptr) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000079 return VCM_PARAMETER_ERROR;
80 }
81
Peter Boström4f5db112015-10-29 16:53:59 +010082 bool ret =
83 _codecDataBase.SetSendCodec(sendCodec, numberOfCores, maxPayloadSize);
pbos@webrtc.orgda2c4ce2013-09-17 09:38:41 +000084
85 // Update encoder regardless of result to make sure that we're not holding on
86 // to a deleted instance.
87 _encoder = _codecDataBase.GetEncoder();
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000088 // Cache the current codec here so they can be fetched from this thread
89 // without requiring the _sendCritSect lock.
90 current_codec_ = *sendCodec;
pbos@webrtc.orgda2c4ce2013-09-17 09:38:41 +000091
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000092 if (!ret) {
pbos@webrtc.org0b52ceb2015-03-24 11:20:54 +000093 LOG(LS_ERROR) << "Failed to initialize set encoder with payload name '"
94 << sendCodec->plName << "'.";
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000095 return VCM_CODEC_ERROR;
96 }
97
Peter Boström233bfd22016-01-18 20:23:40 +010098 // SetSendCodec succeeded, _encoder should be set.
99 RTC_DCHECK(_encoder);
100
ivicac7199c22015-10-07 06:43:33 -0700101 int numLayers;
102 if (sendCodec->codecType == kVideoCodecVP8) {
hta257dc392016-10-25 09:05:06 -0700103 numLayers = sendCodec->VP8().numberOfTemporalLayers;
ivicac7199c22015-10-07 06:43:33 -0700104 } else if (sendCodec->codecType == kVideoCodecVP9) {
hta257dc392016-10-25 09:05:06 -0700105 numLayers = sendCodec->VP9().numberOfTemporalLayers;
sprang4847ae62017-06-27 07:06:52 -0700106 } else if (sendCodec->codecType == kVideoCodecGeneric &&
107 sendCodec->numberOfSimulcastStreams > 0) {
108 // This is mainly for unit testing, disabling frame dropping.
109 // TODO(sprang): Add a better way to disable frame dropping.
110 numLayers = sendCodec->simulcastStream[0].numberOfTemporalLayers;
ivicac7199c22015-10-07 06:43:33 -0700111 } else {
112 numLayers = 1;
113 }
114
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000115 // If we have screensharing and we have layers, we disable frame dropper.
116 bool disable_frame_dropper =
117 numLayers > 1 && sendCodec->mode == kScreensharing;
118 if (disable_frame_dropper) {
119 _mediaOpt.EnableFrameDropper(false);
120 } else if (frame_dropper_enabled_) {
121 _mediaOpt.EnableFrameDropper(true);
122 }
sprang1a646ee2016-12-01 06:34:11 -0800123
Peter Boström233bfd22016-01-18 20:23:40 +0100124 {
125 rtc::CritScope cs(&params_crit_);
126 next_frame_types_.clear();
127 next_frame_types_.resize(VCM_MAX(sendCodec->numberOfSimulcastStreams, 1),
128 kVideoFrameKey);
129 // Cache InternalSource() to have this available from IntraFrameRequest()
130 // without having to acquire encoder_crit_ (avoid blocking on encoder use).
131 encoder_has_internal_source_ = _encoder->InternalSource();
132 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000133
isheriff7620be82016-03-06 23:22:33 -0800134 LOG(LS_VERBOSE) << " max bitrate " << sendCodec->maxBitrate
135 << " start bitrate " << sendCodec->startBitrate
136 << " max frame rate " << sendCodec->maxFramerate
137 << " max payload size " << maxPayloadSize;
Per69b332d2016-06-02 15:45:42 +0200138 _mediaOpt.SetEncodingData(sendCodec->maxBitrate * 1000,
philipel5908c712015-12-21 08:23:20 -0800139 sendCodec->startBitrate * 1000, sendCodec->width,
140 sendCodec->height, sendCodec->maxFramerate,
141 numLayers, maxPayloadSize);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000142 return VCM_OK;
143}
144
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000145// Register an external decoder object.
146// This can not be used together with external decoder callbacks.
Peter Boström795dbe42015-11-27 14:09:07 +0100147void VideoSender::RegisterExternalEncoder(VideoEncoder* externalEncoder,
philipel5908c712015-12-21 08:23:20 -0800148 uint8_t payloadType,
149 bool internalSource /*= false*/) {
perkj4e417b22016-07-14 23:35:55 -0700150 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000151
Peter Boström233bfd22016-01-18 20:23:40 +0100152 rtc::CritScope lock(&encoder_crit_);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000153
mflodmanfcf54bd2015-04-14 21:28:08 +0200154 if (externalEncoder == nullptr) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000155 bool wasSendCodec = false;
Peter Boström795dbe42015-11-27 14:09:07 +0100156 RTC_CHECK(
157 _codecDataBase.DeregisterExternalEncoder(payloadType, &wasSendCodec));
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000158 if (wasSendCodec) {
159 // Make sure the VCM doesn't use the de-registered codec
Peter Boström233bfd22016-01-18 20:23:40 +0100160 rtc::CritScope params_lock(&params_crit_);
mflodmanfcf54bd2015-04-14 21:28:08 +0200161 _encoder = nullptr;
Peter Boström233bfd22016-01-18 20:23:40 +0100162 encoder_has_internal_source_ = false;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000163 }
Peter Boström795dbe42015-11-27 14:09:07 +0100164 return;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000165 }
philipel5908c712015-12-21 08:23:20 -0800166 _codecDataBase.RegisterExternalEncoder(externalEncoder, payloadType,
167 internalSource);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000168}
169
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000170// Get encode bitrate
171int VideoSender::Bitrate(unsigned int* bitrate) const {
perkj4e417b22016-07-14 23:35:55 -0700172 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000173 // Since we're running on the thread that's the only thread known to modify
174 // the value of _encoder, we don't need to grab the lock here.
175
Peter Boström69ccb332015-10-29 16:30:23 +0100176 if (!_encoder)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000177 return VCM_UNINITIALIZED;
Erik Språng08127a92016-11-16 16:41:30 +0100178 *bitrate = _encoder->GetEncoderParameters().target_bitrate.get_sum_bps();
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000179 return 0;
180}
181
182// Get encode frame rate
183int VideoSender::FrameRate(unsigned int* framerate) const {
perkj4e417b22016-07-14 23:35:55 -0700184 RTC_DCHECK(sequenced_checker_.CalledSequentially());
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000185 // Since we're running on the thread that's the only thread known to modify
186 // the value of _encoder, we don't need to grab the lock here.
187
Peter Boström69ccb332015-10-29 16:30:23 +0100188 if (!_encoder)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000189 return VCM_UNINITIALIZED;
Peter Boström69ccb332015-10-29 16:30:23 +0100190
191 *framerate = _encoder->GetEncoderParameters().input_frame_rate;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000192 return 0;
193}
194
Erik Språng08127a92016-11-16 16:41:30 +0100195EncoderParameters VideoSender::UpdateEncoderParameters(
196 const EncoderParameters& params,
197 VideoBitrateAllocator* bitrate_allocator,
198 uint32_t target_bitrate_bps) {
asapersson9abd2752016-12-08 02:19:40 -0800199 uint32_t video_target_rate_bps = _mediaOpt.SetTargetRates(target_bitrate_bps);
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000200 uint32_t input_frame_rate = _mediaOpt.InputFrameRate();
sprang40217c32016-11-21 05:41:52 -0800201 if (input_frame_rate == 0)
202 input_frame_rate = current_codec_.maxFramerate;
203
Erik Språng08127a92016-11-16 16:41:30 +0100204 BitrateAllocation bitrate_allocation;
sprang4847ae62017-06-27 07:06:52 -0700205 // Only call allocators if bitrate > 0 (ie, not suspended), otherwise they
206 // might cap the bitrate to the min bitrate configured.
207 if (target_bitrate_bps > 0) {
208 if (bitrate_allocator) {
209 bitrate_allocation = bitrate_allocator->GetAllocation(
210 video_target_rate_bps, input_frame_rate);
211 } else {
212 DefaultVideoBitrateAllocator default_allocator(current_codec_);
213 bitrate_allocation = default_allocator.GetAllocation(
214 video_target_rate_bps, input_frame_rate);
215 }
Erik Språng08127a92016-11-16 16:41:30 +0100216 }
Erik Språng08127a92016-11-16 16:41:30 +0100217 EncoderParameters new_encoder_params = {bitrate_allocation, params.loss_rate,
218 params.rtt, input_frame_rate};
219 return new_encoder_params;
220}
221
222void VideoSender::UpdateChannelParemeters(
sprang1a646ee2016-12-01 06:34:11 -0800223 VideoBitrateAllocator* bitrate_allocator,
224 VideoBitrateAllocationObserver* bitrate_updated_callback) {
225 BitrateAllocation target_rate;
226 {
227 rtc::CritScope cs(&params_crit_);
228 encoder_params_ =
229 UpdateEncoderParameters(encoder_params_, bitrate_allocator,
230 encoder_params_.target_bitrate.get_sum_bps());
231 target_rate = encoder_params_.target_bitrate;
232 }
sprang4847ae62017-06-27 07:06:52 -0700233 if (bitrate_updated_callback && target_rate.get_sum_bps() > 0)
sprang1a646ee2016-12-01 06:34:11 -0800234 bitrate_updated_callback->OnBitrateAllocationUpdated(target_rate);
Erik Språng08127a92016-11-16 16:41:30 +0100235}
236
237int32_t VideoSender::SetChannelParameters(
238 uint32_t target_bitrate_bps,
sprang1a646ee2016-12-01 06:34:11 -0800239 uint8_t loss_rate,
Erik Språng08127a92016-11-16 16:41:30 +0100240 int64_t rtt,
sprang1a646ee2016-12-01 06:34:11 -0800241 VideoBitrateAllocator* bitrate_allocator,
242 VideoBitrateAllocationObserver* bitrate_updated_callback) {
Erik Språng08127a92016-11-16 16:41:30 +0100243 EncoderParameters encoder_params;
sprang1a646ee2016-12-01 06:34:11 -0800244 encoder_params.loss_rate = loss_rate;
Erik Språng08127a92016-11-16 16:41:30 +0100245 encoder_params.rtt = rtt;
246 encoder_params = UpdateEncoderParameters(encoder_params, bitrate_allocator,
247 target_bitrate_bps);
sprang4847ae62017-06-27 07:06:52 -0700248 if (bitrate_updated_callback && target_bitrate_bps > 0) {
sprang1a646ee2016-12-01 06:34:11 -0800249 bitrate_updated_callback->OnBitrateAllocationUpdated(
250 encoder_params.target_bitrate);
251 }
Erik Språng08127a92016-11-16 16:41:30 +0100252
noahricd4badbc2016-04-13 14:59:48 -0700253 bool encoder_has_internal_source;
254 {
255 rtc::CritScope cs(&params_crit_);
256 encoder_params_ = encoder_params;
257 encoder_has_internal_source = encoder_has_internal_source_;
258 }
259
260 // For encoders with internal sources, we need to tell the encoder directly,
261 // instead of waiting for an AddVideoFrame that will never come (internal
262 // source encoders don't get input frames).
263 if (encoder_has_internal_source) {
264 rtc::CritScope cs(&encoder_crit_);
265 if (_encoder) {
perkj57c21f92016-06-17 07:27:16 -0700266 SetEncoderParameters(encoder_params, encoder_has_internal_source);
noahricd4badbc2016-04-13 14:59:48 -0700267 }
268 }
Erik Språng66a641a2015-06-11 14:20:07 +0200269
270 return VCM_OK;
271}
272
perkj57c21f92016-06-17 07:27:16 -0700273void VideoSender::SetEncoderParameters(EncoderParameters params,
274 bool has_internal_source) {
perkjfea93092016-05-14 00:58:48 -0700275 // |target_bitrate == 0 | means that the network is down or the send pacer is
perkj57c21f92016-06-17 07:27:16 -0700276 // full. We currently only report this if the encoder has an internal source.
277 // If the encoder does not have an internal source, higher levels are expected
278 // to not call AddVideoFrame. We do this since its unclear how current
279 // encoder implementations behave when given a zero target bitrate.
280 // TODO(perkj): Make sure all known encoder implementations handle zero
281 // target bitrate and remove this check.
Erik Språng08127a92016-11-16 16:41:30 +0100282 if (!has_internal_source && params.target_bitrate.get_sum_bps() == 0)
Peter Boströmdcb89982015-09-15 14:43:47 +0200283 return;
tommi@webrtc.org558dc402015-03-07 20:55:56 +0000284
Erik Språng66a641a2015-06-11 14:20:07 +0200285 if (params.input_frame_rate == 0) {
286 // No frame rate estimate available, use default.
287 params.input_frame_rate = current_codec_.maxFramerate;
288 }
Peter Boström69ccb332015-10-29 16:30:23 +0100289 if (_encoder != nullptr)
290 _encoder->SetEncoderParameters(params);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000291}
292
Per69b332d2016-06-02 15:45:42 +0200293// Deprecated:
294// TODO(perkj): Remove once no projects call this method. It currently do
295// nothing.
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000296int32_t VideoSender::RegisterProtectionCallback(
andresp@webrtc.orge682aa52013-12-19 10:59:48 +0000297 VCMProtectionCallback* protection_callback) {
Per69b332d2016-06-02 15:45:42 +0200298 // Deprecated:
299 // TODO(perkj): Remove once no projects call this method. It currently do
300 // nothing.
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000301 return VCM_OK;
302}
303
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000304// Add one raw video frame to the encoder, blocking.
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700305int32_t VideoSender::AddVideoFrame(const VideoFrame& videoFrame,
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000306 const CodecSpecificInfo* codecSpecificInfo) {
Peter Boströmdcb89982015-09-15 14:43:47 +0200307 EncoderParameters encoder_params;
Peter Boström233bfd22016-01-18 20:23:40 +0100308 std::vector<FrameType> next_frame_types;
perkj57c21f92016-06-17 07:27:16 -0700309 bool encoder_has_internal_source = false;
Peter Boströmdcb89982015-09-15 14:43:47 +0200310 {
Peter Boström233bfd22016-01-18 20:23:40 +0100311 rtc::CritScope lock(&params_crit_);
Peter Boströmdcb89982015-09-15 14:43:47 +0200312 encoder_params = encoder_params_;
Peter Boström233bfd22016-01-18 20:23:40 +0100313 next_frame_types = next_frame_types_;
perkj57c21f92016-06-17 07:27:16 -0700314 encoder_has_internal_source = encoder_has_internal_source_;
Peter Boströmdcb89982015-09-15 14:43:47 +0200315 }
Peter Boström233bfd22016-01-18 20:23:40 +0100316 rtc::CritScope lock(&encoder_crit_);
Peter Boström69ccb332015-10-29 16:30:23 +0100317 if (_encoder == nullptr)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000318 return VCM_UNINITIALIZED;
perkj57c21f92016-06-17 07:27:16 -0700319 SetEncoderParameters(encoder_params, encoder_has_internal_source);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000320 if (_mediaOpt.DropFrame()) {
isheriff7620be82016-03-06 23:22:33 -0800321 LOG(LS_VERBOSE) << "Drop Frame "
Erik Språng08127a92016-11-16 16:41:30 +0100322 << "target bitrate "
323 << encoder_params.target_bitrate.get_sum_bps()
isheriff7620be82016-03-06 23:22:33 -0800324 << " loss rate " << encoder_params.loss_rate << " rtt "
325 << encoder_params.rtt << " input frame rate "
326 << encoder_params.input_frame_rate;
kthelgason876222f2016-11-29 01:44:11 -0800327 post_encode_callback_->OnDroppedFrame();
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000328 return VCM_OK;
329 }
pbos@webrtc.org67a9e402015-03-05 13:57:37 +0000330 // TODO(pbos): Make sure setting send codec is synchronized with video
331 // processing so frame size always matches.
332 if (!_codecDataBase.MatchesCurrentResolution(videoFrame.width(),
333 videoFrame.height())) {
334 LOG(LS_ERROR) << "Incoming frame doesn't match set resolution. Dropping.";
335 return VCM_PARAMETER_ERROR;
336 }
Peter Boströmeb66e802015-06-05 11:08:03 +0200337 VideoFrame converted_frame = videoFrame;
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000338 const VideoFrameBuffer::Type buffer_type =
339 converted_frame.video_frame_buffer()->type();
340 const bool is_buffer_type_supported =
341 buffer_type == VideoFrameBuffer::Type::kI420 ||
342 (buffer_type == VideoFrameBuffer::Type::kNative &&
343 _encoder->SupportsNativeHandle());
344 if (!is_buffer_type_supported) {
Peter Boströmeb66e802015-06-05 11:08:03 +0200345 // This module only supports software encoding.
346 // TODO(pbos): Offload conversion from the encoder thread.
Magnus Jedvert72dbe2a2017-06-10 17:03:37 +0000347 rtc::scoped_refptr<I420BufferInterface> converted_buffer(
348 converted_frame.video_frame_buffer()->ToI420());
nisseca6d5d12016-06-17 05:03:04 -0700349
350 if (!converted_buffer) {
351 LOG(LS_ERROR) << "Frame conversion failed, dropping frame.";
352 return VCM_PARAMETER_ERROR;
353 }
354 converted_frame = VideoFrame(converted_buffer,
355 converted_frame.timestamp(),
356 converted_frame.render_time_ms(),
357 converted_frame.rotation());
Peter Boströmeb66e802015-06-05 11:08:03 +0200358 }
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000359 int32_t ret =
Peter Boström233bfd22016-01-18 20:23:40 +0100360 _encoder->Encode(converted_frame, codecSpecificInfo, next_frame_types);
stefan@webrtc.org34c5da62014-04-11 14:08:35 +0000361 if (ret < 0) {
362 LOG(LS_ERROR) << "Failed to encode frame. Error code: " << ret;
363 return ret;
364 }
perkj376b1922016-05-02 11:35:24 -0700365
Peter Boström233bfd22016-01-18 20:23:40 +0100366 {
Peter Boström233bfd22016-01-18 20:23:40 +0100367 rtc::CritScope lock(&params_crit_);
perkj376b1922016-05-02 11:35:24 -0700368 // Change all keyframe requests to encode delta frames the next time.
Peter Boström233bfd22016-01-18 20:23:40 +0100369 for (size_t i = 0; i < next_frame_types_.size(); ++i) {
370 // Check for equality (same requested as before encoding) to not
371 // accidentally drop a keyframe request while encoding.
372 if (next_frame_types[i] == next_frame_types_[i])
373 next_frame_types_[i] = kVideoFrameDelta;
374 }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000375 }
376 return VCM_OK;
377}
378
perkj600246e2016-05-04 11:26:51 -0700379int32_t VideoSender::IntraFrameRequest(size_t stream_index) {
Peter Boström233bfd22016-01-18 20:23:40 +0100380 {
381 rtc::CritScope lock(&params_crit_);
perkj600246e2016-05-04 11:26:51 -0700382 if (stream_index >= next_frame_types_.size()) {
Peter Boström233bfd22016-01-18 20:23:40 +0100383 return -1;
384 }
385 next_frame_types_[stream_index] = kVideoFrameKey;
386 if (!encoder_has_internal_source_)
387 return VCM_OK;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000388 }
Peter Boström233bfd22016-01-18 20:23:40 +0100389 // TODO(pbos): Remove when InternalSource() is gone. Both locks have to be
390 // held here for internal consistency, since _encoder could be removed while
391 // not holding encoder_crit_. Checks have to be performed again since
392 // params_crit_ was dropped to not cause lock-order inversions with
393 // encoder_crit_.
394 rtc::CritScope lock(&encoder_crit_);
395 rtc::CritScope params_lock(&params_crit_);
perkj600246e2016-05-04 11:26:51 -0700396 if (stream_index >= next_frame_types_.size())
Peter Boström233bfd22016-01-18 20:23:40 +0100397 return -1;
mflodmanfcf54bd2015-04-14 21:28:08 +0200398 if (_encoder != nullptr && _encoder->InternalSource()) {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000399 // Try to request the frame if we have an external encoder with
400 // internal source since AddVideoFrame never will be called.
Peter Boström233bfd22016-01-18 20:23:40 +0100401 if (_encoder->RequestFrame(next_frame_types_) == WEBRTC_VIDEO_CODEC_OK) {
402 // Try to remove just-performed keyframe request, if stream still exists.
403 next_frame_types_[stream_index] = kVideoFrameDelta;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000404 }
405 }
406 return VCM_OK;
407}
408
409int32_t VideoSender::EnableFrameDropper(bool enable) {
Peter Boström233bfd22016-01-18 20:23:40 +0100410 rtc::CritScope lock(&encoder_crit_);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000411 frame_dropper_enabled_ = enable;
412 _mediaOpt.EnableFrameDropper(enable);
413 return VCM_OK;
414}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000415} // namespace vcm
416} // namespace webrtc