blob: 054ff0fc613d976ef4ce74512e5d84f565937e2c [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
stefan@webrtc.org07b45a52012-02-02 08:37:48 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +000011#include "video_engine/vie_encoder.h"
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000012
13#include <cassert>
niklase@google.com470e71d2011-07-07 08:21:25 +000014
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +000015#include "modules/rtp_rtcp/interface/rtp_rtcp.h"
16#include "modules/utility/interface/process_thread.h"
17#include "modules/video_coding/codecs/interface/video_codec_interface.h"
18#include "modules/video_coding/main/interface/video_coding.h"
19#include "modules/video_coding/main/interface/video_coding_defines.h"
20#include "system_wrappers/interface/critical_section_wrapper.h"
21#include "system_wrappers/interface/tick_util.h"
22#include "system_wrappers/interface/trace.h"
23#include "video_engine/include/vie_codec.h"
24#include "video_engine/include/vie_image_process.h"
25#include "video_engine/vie_defines.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000026
niklase@google.com470e71d2011-07-07 08:21:25 +000027namespace webrtc {
28
stefan@webrtc.org439be292012-02-16 14:45:37 +000029class QMVideoSettingsCallback : public VCMQMSettingsCallback {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000030 public:
marpan@webrtc.orgefd01fd2012-04-18 15:56:34 +000031 explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
stefan@webrtc.org439be292012-02-16 14:45:37 +000032 ~QMVideoSettingsCallback();
niklase@google.com470e71d2011-07-07 08:21:25 +000033
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000034 // Update VPM with QM (quality modes: frame size & frame rate) settings.
35 WebRtc_Word32 SetVideoQMSettings(const WebRtc_UWord32 frame_rate,
36 const WebRtc_UWord32 width,
37 const WebRtc_UWord32 height);
niklase@google.com470e71d2011-07-07 08:21:25 +000038
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000039 private:
40 VideoProcessingModule* vpm_;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000041};
niklase@google.com470e71d2011-07-07 08:21:25 +000042
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000043class ViEBitrateObserver : public BitrateObserver {
44 public:
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +000045 explicit ViEBitrateObserver(ViEEncoder* owner)
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000046 : owner_(owner) {
47 }
48 // Implements BitrateObserver.
49 virtual void OnNetworkChanged(const uint32_t bitrate_bps,
50 const uint8_t fraction_lost,
51 const uint32_t rtt) {
52 owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt);
53 }
54 private:
55 ViEEncoder* owner_;
56};
niklase@google.com470e71d2011-07-07 08:21:25 +000057
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000058ViEEncoder::ViEEncoder(WebRtc_Word32 engine_id,
59 WebRtc_Word32 channel_id,
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000060 WebRtc_UWord32 number_of_cores,
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000061 ProcessThread& module_process_thread,
62 BitrateController* bitrate_controller)
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000063 : engine_id_(engine_id),
64 channel_id_(channel_id),
65 number_of_cores_(number_of_cores),
66 vcm_(*webrtc::VideoCodingModule::Create(ViEModuleId(engine_id,
67 channel_id))),
68 vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id,
69 channel_id))),
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000070 default_rtp_rtcp_(NULL),
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +000071 callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
72 data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000073 bitrate_controller_(bitrate_controller),
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000074 paused_(false),
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000075 time_last_intra_request_ms_(0),
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000076 channels_dropping_delta_frames_(0),
77 drop_next_frame_(false),
78 fec_enabled_(false),
79 nack_enabled_(false),
80 codec_observer_(NULL),
81 effect_filter_(NULL),
82 module_process_thread_(module_process_thread),
83 has_received_sli_(false),
84 picture_id_sli_(0),
85 has_received_rpsi_(false),
86 picture_id_rpsi_(0),
stefan@webrtc.org97845122012-04-13 07:47:05 +000087 file_recorder_(channel_id),
88 qm_callback_(NULL) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +000089 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
90 ViEId(engine_id, channel_id),
91 "%s(engine_id: %d) 0x%p - Constructor", __FUNCTION__, engine_id,
92 this);
pwestin@webrtc.orgce330352012-04-12 06:59:14 +000093
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +000094 RtpRtcp::Configuration configuration;
95 configuration.id = ViEModuleId(engine_id_, channel_id_);
96 configuration.audio = false; // Video.
97
98 default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +000099 bitrate_observer_.reset(new ViEBitrateObserver(this));
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000100}
101
102bool ViEEncoder::Init() {
103 if (vcm_.InitializeSender() != 0) {
104 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
105 ViEId(engine_id_, channel_id_),
106 "%s InitializeSender failure", __FUNCTION__);
107 return false;
108 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000109 vpm_.EnableTemporalDecimation(true);
110
111 // Enable/disable content analysis: off by default for now.
112 vpm_.EnableContentAnalysis(false);
113
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000114 if (module_process_thread_.RegisterModule(&vcm_) != 0) {
115 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
116 ViEId(engine_id_, channel_id_),
117 "%s RegisterModule failure", __FUNCTION__);
118 return false;
119 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000120 if (module_process_thread_.RegisterModule(default_rtp_rtcp_.get()) != 0) {
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000121 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
122 ViEId(engine_id_, channel_id_),
123 "%s RegisterModule failure", __FUNCTION__);
124 return false;
125 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000126
stefan@webrtc.org97845122012-04-13 07:47:05 +0000127 if (qm_callback_) {
128 delete qm_callback_;
129 }
marpan@webrtc.orgefd01fd2012-04-18 15:56:34 +0000130 qm_callback_ = new QMVideoSettingsCallback(&vpm_);
niklase@google.com470e71d2011-07-07 08:21:25 +0000131
132#ifdef VIDEOCODEC_VP8
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000133 VideoCodec video_codec;
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000134 if (vcm_.Codec(webrtc::kVideoCodecVP8, &video_codec) != VCM_OK) {
135 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
136 ViEId(engine_id_, channel_id_),
137 "%s Codec failure", __FUNCTION__);
138 return false;
139 }
140 if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000141 default_rtp_rtcp_->MaxDataPayloadLength()) != 0) {
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000142 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
143 ViEId(engine_id_, channel_id_),
144 "%s RegisterSendCodec failure", __FUNCTION__);
145 return false;
146 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000147 if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000148 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
149 ViEId(engine_id_, channel_id_),
150 "%s RegisterSendPayload failure", __FUNCTION__);
151 return false;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000152 }
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +0000153 if (default_rtp_rtcp_->RegisterSendRtpHeaderExtension(
154 kRtpExtensionTransmissionTimeOffset, 1) != 0) {
155 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
156 ViEId(engine_id_, channel_id_),
157 "%s RegisterSendRtpHeaderExtension failure", __FUNCTION__);
158 return false;
159 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000160#else
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000161 VideoCodec video_codec;
162 if (vcm_.Codec(webrtc::kVideoCodecI420, &video_codec) == VCM_OK) {
163 vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000164 default_rtp_rtcp_->MaxDataPayloadLength());
165 default_rtp_rtcp_->RegisterSendPayload(video_codec);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000166 } else {
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000167 return false;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000168 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000169#endif
170
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000171 if (vcm_.RegisterTransportCallback(this) != 0) {
172 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
173 ViEId(engine_id_, channel_id_),
mflodman@webrtc.orgcdeb4832012-01-18 09:00:04 +0000174 "ViEEncoder: VCM::RegisterTransportCallback failure");
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000175 return false;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000176 }
177 if (vcm_.RegisterSendStatisticsCallback(this) != 0) {
178 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
179 ViEId(engine_id_, channel_id_),
mflodman@webrtc.orgcdeb4832012-01-18 09:00:04 +0000180 "ViEEncoder: VCM::RegisterSendStatisticsCallback failure");
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000181 return false;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000182 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000183 if (vcm_.RegisterVideoQMCallback(qm_callback_) != 0) {
184 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
185 ViEId(engine_id_, channel_id_),
186 "VCM::RegisterQMCallback failure");
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000187 return false;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000188 }
wu@webrtc.org5d8c1022012-04-10 16:54:05 +0000189 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000190}
191
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000192ViEEncoder::~ViEEncoder() {
193 WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceVideo,
194 ViEId(engine_id_, channel_id_),
195 "ViEEncoder Destructor 0x%p, engine_id: %d", this, engine_id_);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000196 module_process_thread_.DeRegisterModule(&vcm_);
197 module_process_thread_.DeRegisterModule(&vpm_);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000198 module_process_thread_.DeRegisterModule(default_rtp_rtcp_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000199 delete &vcm_;
200 delete &vpm_;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000201 delete qm_callback_;
niklase@google.com470e71d2011-07-07 08:21:25 +0000202}
203
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000204int ViEEncoder::Owner() const {
205 return channel_id_;
206}
207
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000208void ViEEncoder::Pause() {
209 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
210 ViEId(engine_id_, channel_id_),
niklase@google.com470e71d2011-07-07 08:21:25 +0000211 "%s", __FUNCTION__);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000212 CriticalSectionScoped cs(data_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000213 paused_ = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000214}
215
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000216void ViEEncoder::Restart() {
217 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
218 ViEId(engine_id_, channel_id_),
219 "%s", __FUNCTION__);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000220 CriticalSectionScoped cs(data_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000221 paused_ = false;
222}
223
224WebRtc_Word32 ViEEncoder::DropDeltaAfterKey(bool enable) {
225 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
226 ViEId(engine_id_, channel_id_),
227 "%s(%d)", __FUNCTION__, enable);
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000228 CriticalSectionScoped cs(data_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000229
230 if (enable) {
231 channels_dropping_delta_frames_++;
232 } else {
233 channels_dropping_delta_frames_--;
234 if (channels_dropping_delta_frames_ < 0) {
235 channels_dropping_delta_frames_ = 0;
236 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
237 ViEId(engine_id_, channel_id_),
mflodman@webrtc.orgcdeb4832012-01-18 09:00:04 +0000238 "%s: Called too many times", __FUNCTION__);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000239 return -1;
240 }
241 }
242 return 0;
243}
244
245WebRtc_UWord8 ViEEncoder::NumberOfCodecs() {
246 return vcm_.NumberOfCodecs();
247}
248
249WebRtc_Word32 ViEEncoder::GetCodec(WebRtc_UWord8 list_index,
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000250 VideoCodec* video_codec) {
251 if (vcm_.Codec(list_index, video_codec) != 0) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000252 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
253 ViEId(engine_id_, channel_id_), "%s: Could not get codec",
254 __FUNCTION__);
255 return -1;
256 }
257 return 0;
258}
259
260WebRtc_Word32 ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder,
261 WebRtc_UWord8 pl_type) {
262 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
263 ViEId(engine_id_, channel_id_), "%s: pltype %u", __FUNCTION__,
264 pl_type);
265
266 if (encoder == NULL)
267 return -1;
268
269 if (vcm_.RegisterExternalEncoder(encoder, pl_type) != VCM_OK) {
270 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
271 ViEId(engine_id_, channel_id_),
272 "Could not register external encoder");
273 return -1;
274 }
275 return 0;
276}
277
278WebRtc_Word32 ViEEncoder::DeRegisterExternalEncoder(WebRtc_UWord8 pl_type) {
279 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
280 ViEId(engine_id_, channel_id_),
281 "%s: pltype %u", __FUNCTION__, pl_type);
282
283 webrtc::VideoCodec current_send_codec;
284 if (vcm_.SendCodec(&current_send_codec) == VCM_OK) {
stefan@webrtc.org439be292012-02-16 14:45:37 +0000285 if (vcm_.Bitrate(&current_send_codec.startBitrate) != 0) {
286 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
287 ViEId(engine_id_, channel_id_),
288 "Failed to get the current encoder target bitrate.");
289 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000290 }
291
292 if (vcm_.RegisterExternalEncoder(NULL, pl_type) != VCM_OK) {
293 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
294 ViEId(engine_id_, channel_id_),
295 "Could not deregister external encoder");
296 return -1;
297 }
298
299 // If the external encoder is the current send codeci, use vcm internal
300 // encoder.
301 if (current_send_codec.plType == pl_type) {
302 WebRtc_UWord16 max_data_payload_length =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000303 default_rtp_rtcp_->MaxDataPayloadLength();
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000304 if (vcm_.RegisterSendCodec(&current_send_codec, number_of_cores_,
305 max_data_payload_length) != VCM_OK) {
306 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
307 ViEId(engine_id_, channel_id_),
308 "Could not use internal encoder");
309 return -1;
310 }
311 }
312 return 0;
313}
314
315WebRtc_Word32 ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
316 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
317 ViEId(engine_id_, channel_id_),
318 "%s: CodecType: %d, width: %u, height: %u", __FUNCTION__,
319 video_codec.codecType, video_codec.width, video_codec.height);
320
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000321 // Setting target width and height for VPM.
322 if (vpm_.SetTargetResolution(video_codec.width, video_codec.height,
323 video_codec.maxFramerate) != VPM_OK) {
324 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
325 ViEId(engine_id_, channel_id_),
326 "Could not set VPM target dimensions");
327 return -1;
328 }
329
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000330 if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000331 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
332 ViEId(engine_id_, channel_id_),
333 "Could register RTP module video payload");
334 return -1;
335 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000336 // Convert from kbps to bps.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000337 default_rtp_rtcp_->SetTargetSendBitrate(video_codec.startBitrate * 1000);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000338
339 WebRtc_UWord16 max_data_payload_length =
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000340 default_rtp_rtcp_->MaxDataPayloadLength();
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000341
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000342 if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
343 max_data_payload_length) != VCM_OK) {
344 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
345 ViEId(engine_id_, channel_id_),
346 "Could not register send codec");
347 return -1;
348 }
349
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000350 // Set this module as sending right away, let the slave module in the channel
351 // start and stop sending.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000352 if (default_rtp_rtcp_->Sending() == false) {
353 if (default_rtp_rtcp_->SetSendingStatus(true) != 0) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000354 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
355 ViEId(engine_id_, channel_id_),
356 "Could start RTP module sending");
357 return -1;
358 }
359 }
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000360 bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(),
361 video_codec.startBitrate * 1000,
362 video_codec.minBitrate * 1000,
363 video_codec.maxBitrate * 1000);
364
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000365 return 0;
366}
367
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000368WebRtc_Word32 ViEEncoder::GetEncoder(VideoCodec* video_codec) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000369 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
370 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
371
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000372 if (vcm_.SendCodec(video_codec) != 0) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000373 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
374 ViEId(engine_id_, channel_id_),
375 "Could not get VCM send codec");
376 return -1;
377 }
378 return 0;
379}
niklase@google.com470e71d2011-07-07 08:21:25 +0000380
381WebRtc_Word32 ViEEncoder::GetCodecConfigParameters(
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000382 unsigned char config_parameters[kConfigParameterSize],
383 unsigned char& config_parameters_size) {
384 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
385 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000386
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000387 WebRtc_Word32 num_parameters =
388 vcm_.CodecConfigParameters(config_parameters, kConfigParameterSize);
389 if (num_parameters <= 0) {
390 config_parameters_size = 0;
391 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
392 ViEId(engine_id_, channel_id_),
393 "Could not get config parameters");
394 return -1;
395 }
396 config_parameters_size = static_cast<unsigned char>(num_parameters);
397 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000398}
399
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000400WebRtc_Word32 ViEEncoder::ScaleInputImage(bool enable) {
401 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
402 ViEId(engine_id_, channel_id_), "%s(enable %d)", __FUNCTION__,
403 enable);
niklase@google.com470e71d2011-07-07 08:21:25 +0000404
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000405 VideoFrameResampling resampling_mode = kFastRescaling;
406 if (enable == true) {
407 // kInterpolation is currently not supported.
408 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
409 ViEId(engine_id_, channel_id_), "%s not supported",
410 __FUNCTION__, enable);
411 return -1;
412 }
413 vpm_.SetInputFrameResampleMode(resampling_mode);
niklase@google.com470e71d2011-07-07 08:21:25 +0000414
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000415 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000416}
417
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000418RtpRtcp* ViEEncoder::SendRtpRtcpModule() {
419 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
420 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000421
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000422 return default_rtp_rtcp_.get();
niklase@google.com470e71d2011-07-07 08:21:25 +0000423}
424
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000425void ViEEncoder::DeliverFrame(int id,
426 VideoFrame* video_frame,
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000427 int num_csrcs,
428 const WebRtc_UWord32 CSRC[kRtpCsrcSize]) {
429 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
430 ViEId(engine_id_, channel_id_), "%s: %llu", __FUNCTION__,
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000431 video_frame->TimeStamp());
niklase@google.com470e71d2011-07-07 08:21:25 +0000432
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000433 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000434 CriticalSectionScoped cs(data_cs_.get());
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000435 if (paused_ || default_rtp_rtcp_->SendingMedia() == false) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000436 // We've paused or we have no channels attached, don't encode.
437 return;
438 }
439 if (drop_next_frame_) {
440 // Drop this frame.
441 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
442 ViEId(engine_id_, channel_id_),
443 "%s: Dropping frame %llu after a key fame", __FUNCTION__,
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000444 video_frame->TimeStamp());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000445 drop_next_frame_ = false;
446 return;
447 }
448 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000449
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000450 // Convert render time, in ms, to RTP timestamp.
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000451 const int kMsToRtpTimestamp = 90;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000452 const WebRtc_UWord32 time_stamp =
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000453 kMsToRtpTimestamp *
454 static_cast<WebRtc_UWord32>(video_frame->RenderTimeMs());
455 video_frame->SetTimeStamp(time_stamp);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000456 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000457 CriticalSectionScoped cs(callback_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000458 if (effect_filter_) {
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000459 effect_filter_->Transform(video_frame->Length(), video_frame->Buffer(),
460 video_frame->TimeStamp(),
461 video_frame->Width(), video_frame->Height());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000462 }
463 }
464 // Record raw frame.
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000465 file_recorder_.RecordVideoFrame(*video_frame);
niklase@google.com470e71d2011-07-07 08:21:25 +0000466
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000467 // Make sure the CSRC list is correct.
468 if (num_csrcs > 0) {
469 WebRtc_UWord32 tempCSRC[kRtpCsrcSize];
470 for (int i = 0; i < num_csrcs; i++) {
471 if (CSRC[i] == 1) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000472 tempCSRC[i] = default_rtp_rtcp_->SSRC();
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000473 } else {
474 tempCSRC[i] = CSRC[i];
475 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000476 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000477 default_rtp_rtcp_->SetCSRCs(tempCSRC, (WebRtc_UWord8) num_csrcs);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000478 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000479
480#ifdef VIDEOCODEC_VP8
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000481 if (vcm_.SendCodec() == webrtc::kVideoCodecVP8) {
482 webrtc::CodecSpecificInfo codec_specific_info;
483 codec_specific_info.codecType = webrtc::kVideoCodecVP8;
484 if (has_received_sli_ || has_received_rpsi_) {
485 {
486 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
487 has_received_rpsi_;
488 codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
489 has_received_sli_;
490 codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
491 picture_id_rpsi_;
492 codec_specific_info.codecSpecific.VP8.pictureIdSLI =
493 picture_id_sli_;
494 }
495 has_received_sli_ = false;
496 has_received_rpsi_ = false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000497 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000498 VideoFrame* decimated_frame = NULL;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000499 const int ret = vpm_.PreprocessFrame(video_frame, &decimated_frame);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000500 if (ret == 1) {
501 // Drop this frame.
502 return;
503 } else if (ret != VPM_OK) {
504 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
505 ViEId(engine_id_, channel_id_),
506 "%s: Error preprocessing frame %u", __FUNCTION__,
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000507 video_frame->TimeStamp());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000508 return;
509 }
510
511 VideoContentMetrics* content_metrics = NULL;
512 content_metrics = vpm_.ContentMetrics();
513
514 // Frame was not re-sampled => use original.
515 if (decimated_frame == NULL) {
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000516 decimated_frame = video_frame;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000517 }
518
519 if (vcm_.AddVideoFrame(*decimated_frame, content_metrics,
520 &codec_specific_info) != VCM_OK) {
521 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
522 ViEId(engine_id_, channel_id_),
523 "%s: Error encoding frame %u", __FUNCTION__,
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000524 video_frame->TimeStamp());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000525 }
526 return;
527 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000528#endif
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000529 // TODO(mflodman) Rewrite this to use code common to VP8 case.
530 // Pass frame via preprocessor.
531 VideoFrame* decimated_frame = NULL;
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000532 const int ret = vpm_.PreprocessFrame(video_frame, &decimated_frame);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000533 if (ret == 1) {
534 // Drop this frame.
535 return;
536 } else if (ret != VPM_OK) {
537 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
538 ViEId(engine_id_, channel_id_),
539 "%s: Error preprocessing frame %u", __FUNCTION__,
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000540 video_frame->TimeStamp());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000541 return;
542 }
543
544 // Frame was not sampled => use original.
545 if (decimated_frame == NULL) {
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000546 decimated_frame = video_frame;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000547 }
548 if (vcm_.AddVideoFrame(*decimated_frame) != VCM_OK) {
549 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
550 ViEId(engine_id_, channel_id_), "%s: Error encoding frame %u",
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000551 __FUNCTION__, video_frame->TimeStamp());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000552 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000553}
niklase@google.com470e71d2011-07-07 08:21:25 +0000554
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000555void ViEEncoder::DelayChanged(int id, int frame_delay) {
556 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
557 ViEId(engine_id_, channel_id_), "%s: %u", __FUNCTION__,
558 frame_delay);
niklase@google.com470e71d2011-07-07 08:21:25 +0000559
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000560 default_rtp_rtcp_->SetCameraDelay(frame_delay);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000561 file_recorder_.SetFrameDelay(frame_delay);
niklase@google.com470e71d2011-07-07 08:21:25 +0000562}
niklase@google.com470e71d2011-07-07 08:21:25 +0000563
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000564int ViEEncoder::GetPreferedFrameSettings(int* width,
565 int* height,
566 int* frame_rate) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000567 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
568 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
niklase@google.com470e71d2011-07-07 08:21:25 +0000569
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000570 webrtc::VideoCodec video_codec;
571 memset(&video_codec, 0, sizeof(video_codec));
572 if (vcm_.SendCodec(&video_codec) != VCM_OK) {
573 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
574 ViEId(engine_id_, channel_id_),
575 "Could not get VCM send codec");
576 return -1;
577 }
578
mflodman@webrtc.org8baed512012-06-21 12:11:50 +0000579 *width = video_codec.width;
580 *height = video_codec.height;
581 *frame_rate = video_codec.maxFramerate;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000582 return 0;
583}
584
pwestin@webrtc.orgce330352012-04-12 06:59:14 +0000585int ViEEncoder::SendKeyFrame() {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000586 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
587 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
pwestin@webrtc.orgce330352012-04-12 06:59:14 +0000588 return vcm_.IntraFrameRequest();
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000589}
590
591WebRtc_Word32 ViEEncoder::SendCodecStatistics(
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000592 WebRtc_UWord32* num_key_frames, WebRtc_UWord32* num_delta_frames) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000593 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
594 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
595
596 webrtc::VCMFrameCount sent_frames;
597 if (vcm_.SentFrameCount(sent_frames) != VCM_OK) {
598 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
599 ViEId(engine_id_, channel_id_),
600 "%s: Could not get sent frame information", __FUNCTION__);
601 return -1;
602 }
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000603 *num_key_frames = sent_frames.numKeyFrames;
604 *num_delta_frames = sent_frames.numDeltaFrames;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000605 return 0;
606}
607
stefan@webrtc.org439be292012-02-16 14:45:37 +0000608WebRtc_Word32 ViEEncoder::EstimatedSendBandwidth(
stefan@webrtc.org07b45a52012-02-02 08:37:48 +0000609 WebRtc_UWord32* available_bandwidth) const {
610 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
611 __FUNCTION__);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000612
613 if (!bitrate_controller_->AvailableBandwidth(available_bandwidth)) {
614 return -1;
615 }
616 return 0;
stefan@webrtc.org439be292012-02-16 14:45:37 +0000617}
618
619int ViEEncoder::CodecTargetBitrate(WebRtc_UWord32* bitrate) const {
620 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, channel_id_), "%s",
621 __FUNCTION__);
622 if (vcm_.Bitrate(bitrate) != 0)
623 return -1;
624 return 0;
stefan@webrtc.org07b45a52012-02-02 08:37:48 +0000625}
626
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000627WebRtc_Word32 ViEEncoder::UpdateProtectionMethod() {
628 bool fec_enabled = false;
629 WebRtc_UWord8 dummy_ptype_red = 0;
630 WebRtc_UWord8 dummy_ptypeFEC = 0;
631
632 // Updated protection method to VCM to get correct packetization sizes.
633 // FEC has larger overhead than NACK -> set FEC if used.
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000634 WebRtc_Word32 error = default_rtp_rtcp_->GenericFECStatus(fec_enabled,
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000635 dummy_ptype_red,
636 dummy_ptypeFEC);
637 if (error) {
638 return -1;
639 }
640
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000641 bool nack_enabled = (default_rtp_rtcp_->NACK() == kNackOff) ? false : true;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000642 if (fec_enabled_ == fec_enabled && nack_enabled_ == nack_enabled) {
643 // No change needed, we're already in correct state.
644 return 0;
645 }
646 fec_enabled_ = fec_enabled;
647 nack_enabled_ = nack_enabled;
648
649 // Set Video Protection for VCM.
650 if (fec_enabled && nack_enabled) {
651 vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true);
652 } else {
653 vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_);
654 vcm_.SetVideoProtection(webrtc::kProtectionNack, nack_enabled_);
655 vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, false);
656 }
657
658 if (fec_enabled || nack_enabled) {
659 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
660 ViEId(engine_id_, channel_id_), "%s: FEC status ",
661 __FUNCTION__, fec_enabled);
662 vcm_.RegisterProtectionCallback(this);
663 // The send codec must be registered to set correct MTU.
664 webrtc::VideoCodec codec;
665 if (vcm_.SendCodec(&codec) == 0) {
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000666 WebRtc_UWord16 max_pay_load = default_rtp_rtcp_->MaxDataPayloadLength();
stefan@webrtc.org439be292012-02-16 14:45:37 +0000667 if (vcm_.Bitrate(&codec.startBitrate) != 0) {
668 WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideo,
669 ViEId(engine_id_, channel_id_),
670 "Failed to get the current encoder target bitrate.");
671 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000672 if (vcm_.RegisterSendCodec(&codec, number_of_cores_, max_pay_load) != 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000674 ViEId(engine_id_, channel_id_),
675 "%s: Failed to update Sendcodec when enabling FEC",
676 __FUNCTION__, fec_enabled);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677 return -1;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000678 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000679 }
680 return 0;
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000681 } else {
682 // FEC and NACK are disabled.
683 vcm_.RegisterProtectionCallback(NULL);
684 }
685 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000686}
687
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000688WebRtc_Word32 ViEEncoder::SendData(
689 const FrameType frame_type,
690 const WebRtc_UWord8 payload_type,
691 const WebRtc_UWord32 time_stamp,
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +0000692 int64_t capture_time_ms,
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000693 const WebRtc_UWord8* payload_data,
694 const WebRtc_UWord32 payload_size,
695 const webrtc::RTPFragmentationHeader& fragmentation_header,
696 const RTPVideoHeader* rtp_video_hdr) {
697 {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000698 CriticalSectionScoped cs(data_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000699 if (paused_) {
700 // Paused, don't send this packet.
701 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000702 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000703 if (channels_dropping_delta_frames_ &&
704 frame_type == webrtc::kVideoFrameKey) {
705 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
706 ViEId(engine_id_, channel_id_),
707 "%s: Sending key frame, drop next frame", __FUNCTION__);
708 drop_next_frame_ = true;
709 }
710 }
711
712 // New encoded data, hand over to the rtp module.
stefan@webrtc.orgddfdfed2012-07-03 13:21:22 +0000713 return default_rtp_rtcp_->SendOutgoingData(frame_type,
714 payload_type,
715 time_stamp,
716 capture_time_ms,
717 payload_data,
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000718 payload_size,
719 &fragmentation_header,
720 rtp_video_hdr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000721}
722
stefan@webrtc.orgf4c82862011-12-13 15:38:14 +0000723WebRtc_Word32 ViEEncoder::ProtectionRequest(
stefan@webrtc.orge0d6fa42012-03-20 22:10:56 +0000724 const FecProtectionParams* delta_fec_params,
725 const FecProtectionParams* key_fec_params,
stefan@webrtc.orgf4c82862011-12-13 15:38:14 +0000726 WebRtc_UWord32* sent_video_rate_bps,
727 WebRtc_UWord32* sent_nack_rate_bps,
728 WebRtc_UWord32* sent_fec_rate_bps) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000729 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
730 ViEId(engine_id_, channel_id_),
731 "%s, deltaFECRate: %u, key_fecrate: %u, "
marpan@webrtc.org71707aa2012-07-13 16:27:51 +0000732 "delta_use_uep_protection: %d, key_use_uep_protection: %d, "
733 "delta_max_fec_frames: %d, key_max_fec_frames: %d, "
734 "delta_mask_type: %d, key_mask_type: %d, ",
stefan@webrtc.orge0d6fa42012-03-20 22:10:56 +0000735 __FUNCTION__,
736 delta_fec_params->fec_rate,
737 key_fec_params->fec_rate,
738 delta_fec_params->use_uep_protection,
marpan@webrtc.org71707aa2012-07-13 16:27:51 +0000739 key_fec_params->use_uep_protection,
740 delta_fec_params->max_fec_frames,
741 key_fec_params->max_fec_frames,
742 delta_fec_params->fec_mask_type,
743 key_fec_params->fec_mask_type);
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000744 if (default_rtp_rtcp_->SetFecParameters(delta_fec_params,
stefan@webrtc.orge0d6fa42012-03-20 22:10:56 +0000745 key_fec_params) != 0) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000746 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
747 ViEId(engine_id_, channel_id_),
stefan@webrtc.orge0d6fa42012-03-20 22:10:56 +0000748 "%s: Could not update FEC parameters", __FUNCTION__);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000749 }
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000750 default_rtp_rtcp_->BitrateSent(NULL,
stefan@webrtc.orgf4c82862011-12-13 15:38:14 +0000751 sent_video_rate_bps,
752 sent_fec_rate_bps,
753 sent_nack_rate_bps);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000754 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000755}
756
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000757WebRtc_Word32 ViEEncoder::SendStatistics(const WebRtc_UWord32 bit_rate,
758 const WebRtc_UWord32 frame_rate) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000759 CriticalSectionScoped cs(callback_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000760 if (codec_observer_) {
761 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
762 ViEId(engine_id_, channel_id_), "%s: bitrate %u, framerate %u",
763 __FUNCTION__, bit_rate, frame_rate);
764 codec_observer_->OutgoingRate(channel_id_, frame_rate, bit_rate);
765 }
766 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000767}
768
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000769WebRtc_Word32 ViEEncoder::RegisterCodecObserver(ViEEncoderObserver* observer) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000770 CriticalSectionScoped cs(callback_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000771 if (observer) {
772 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
773 ViEId(engine_id_, channel_id_), "%s: observer added",
774 __FUNCTION__);
775 if (codec_observer_) {
776 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
777 ViEId(engine_id_, channel_id_), "%s: observer already set.",
778 __FUNCTION__);
779 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000780 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000781 codec_observer_ = observer;
782 } else {
783 if (codec_observer_ == NULL) {
mflodman@webrtc.orgcdeb4832012-01-18 09:00:04 +0000784 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
785 ViEId(engine_id_, channel_id_),
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000786 "%s: observer does not exist.", __FUNCTION__);
787 return -1;
788 }
789 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
790 ViEId(engine_id_, channel_id_), "%s: observer removed",
791 __FUNCTION__);
792 codec_observer_ = NULL;
793 }
794 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000795}
796
andrew@webrtc.org96636862012-09-20 23:33:17 +0000797void ViEEncoder::OnReceivedSLI(uint32_t /*ssrc*/,
798 uint8_t picture_id) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000799 picture_id_sli_ = picture_id;
800 has_received_sli_ = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000801}
802
andrew@webrtc.org96636862012-09-20 23:33:17 +0000803void ViEEncoder::OnReceivedRPSI(uint32_t /*ssrc*/,
804 uint64_t picture_id) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000805 picture_id_rpsi_ = picture_id;
806 has_received_rpsi_ = true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000807}
808
andrew@webrtc.org96636862012-09-20 23:33:17 +0000809void ViEEncoder::OnReceivedIntraFrameRequest(uint32_t /*ssrc*/) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000810 // Key frame request from remote side, signal to VCM.
811 WEBRTC_TRACE(webrtc::kTraceStateInfo, webrtc::kTraceVideo,
812 ViEId(engine_id_, channel_id_), "%s", __FUNCTION__);
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +0000813
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000814 WebRtc_Word64 now = TickTime::MillisecondTimestamp();
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000815 if (time_last_intra_request_ms_ + kViEMinKeyRequestIntervalMs > now) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000816 WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideo,
817 ViEId(engine_id_, channel_id_),
818 "%s: Not not encoding new intra due to timing", __FUNCTION__);
819 return;
820 }
pwestin@webrtc.orgce330352012-04-12 06:59:14 +0000821 vcm_.IntraFrameRequest();
822 time_last_intra_request_ms_ = now;
niklase@google.com470e71d2011-07-07 08:21:25 +0000823}
824
mflodman@webrtc.orgaca26292012-10-05 16:17:41 +0000825void ViEEncoder::OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {
826}
827
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000828// Called from ViEBitrateObserver.
829void ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps,
830 const uint8_t fraction_lost,
831 const uint32_t round_trip_time_ms) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000832 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
833 ViEId(engine_id_, channel_id_),
834 "%s(bitrate_bps: %u, fraction_lost: %u, rtt_ms: %u",
835 __FUNCTION__, bitrate_bps, fraction_lost, round_trip_time_ms);
pwestin@webrtc.org1da1ce02011-10-13 15:19:55 +0000836
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000837 vcm_.SetChannelParameters(bitrate_bps / 1000, fraction_lost,
838 round_trip_time_ms);
pwestin@webrtc.org49888ce2012-04-27 05:25:53 +0000839
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000840 default_rtp_rtcp_->SetTargetSendBitrate(bitrate_bps);
niklase@google.com470e71d2011-07-07 08:21:25 +0000841}
842
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000843WebRtc_Word32 ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
mflodman@webrtc.orgd32c4472011-12-22 14:17:53 +0000844 CriticalSectionScoped cs(callback_cs_.get());
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000845 if (effect_filter == NULL) {
846 if (effect_filter_ == NULL) {
847 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
848 ViEId(engine_id_, channel_id_), "%s: no effect filter added",
849 __FUNCTION__);
850 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000851 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000852 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
853 ViEId(engine_id_, channel_id_), "%s: deregister effect filter",
854 __FUNCTION__);
855 } else {
856 WEBRTC_TRACE(webrtc::kTraceInfo, webrtc::kTraceVideo,
857 ViEId(engine_id_, channel_id_), "%s: register effect",
858 __FUNCTION__);
859 if (effect_filter_) {
860 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideo,
861 ViEId(engine_id_, channel_id_),
862 "%s: effect filter already added ", __FUNCTION__);
863 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000864 }
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000865 }
866 effect_filter_ = effect_filter;
867 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000868}
869
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000870ViEFileRecorder& ViEEncoder::GetOutgoingFileRecorder() {
871 return file_recorder_;
872}
niklase@google.com470e71d2011-07-07 08:21:25 +0000873
mikhal@webrtc.orge41bbdf2012-08-28 16:15:16 +0000874int ViEEncoder::StartDebugRecording(const char* fileNameUTF8) {
875 return vcm_.StartDebugRecording(fileNameUTF8);
876}
877
878int ViEEncoder::StopDebugRecording() {
879 return vcm_.StopDebugRecording();
880}
881
marpan@webrtc.orgefd01fd2012-04-18 15:56:34 +0000882QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm)
883 : vpm_(vpm) {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000884}
niklase@google.com470e71d2011-07-07 08:21:25 +0000885
stefan@webrtc.org439be292012-02-16 14:45:37 +0000886QMVideoSettingsCallback::~QMVideoSettingsCallback() {
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000887}
888
stefan@webrtc.org439be292012-02-16 14:45:37 +0000889WebRtc_Word32 QMVideoSettingsCallback::SetVideoQMSettings(
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000890 const WebRtc_UWord32 frame_rate,
891 const WebRtc_UWord32 width,
892 const WebRtc_UWord32 height) {
marpan@webrtc.orgcf706c22012-03-27 21:04:13 +0000893 return vpm_->SetTargetResolution(width, height, frame_rate);
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000894}
895
mflodman@webrtc.org84d17832011-12-01 17:02:23 +0000896} // namespace webrtc