blob: bdfb4ad41bb2cc2e954e37c0c14108a99a603819 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
2 * Copyright (c) 2011 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
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000011#include "video_engine/vie_codec_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
niklase@google.com470e71d2011-07-07 08:21:25 +000013#include "engine_configurations.h"
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000014#include "modules/video_coding/main/interface/video_coding.h"
15#include "system_wrappers/interface/trace.h"
mflodman@webrtc.orga4863db2011-12-22 08:51:52 +000016#include "video_engine/include/vie_errors.h"
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000017#include "video_engine/vie_capturer.h"
18#include "video_engine/vie_channel.h"
19#include "video_engine/vie_channel_manager.h"
20#include "video_engine/vie_defines.h"
21#include "video_engine/vie_encoder.h"
22#include "video_engine/vie_impl.h"
23#include "video_engine/vie_input_manager.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000024
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000025namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000026
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000027ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000028#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000029 if (!video_engine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000030 return NULL;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000031 }
32 VideoEngineImpl* vie_impl = reinterpret_cast<VideoEngineImpl*>(video_engine);
33 ViECodecImpl* vie_codec_impl = vie_impl;
34 // Increase ref count.
35 (*vie_codec_impl)++;
36 return vie_codec_impl;
37#else
38 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000039#endif
40}
41
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000042int ViECodecImpl::Release() {
43 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, instance_id_,
niklase@google.com470e71d2011-07-07 08:21:25 +000044 "ViECodecImpl::Release()");
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000045 // Decrease ref count.
46 (*this)--;
niklase@google.com470e71d2011-07-07 08:21:25 +000047
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000048 WebRtc_Word32 ref_count = GetCount();
49 if (ref_count < 0) {
50 WEBRTC_TRACE(kTraceWarning, kTraceVideo, instance_id_,
51 "ViECodec released too many times");
52 SetLastError(kViEAPIDoesNotExist);
53 return -1;
54 }
55 WEBRTC_TRACE(kTraceInfo, kTraceVideo, instance_id_,
56 "ViECodec reference count: %d", ref_count);
57 return ref_count;
niklase@google.com470e71d2011-07-07 08:21:25 +000058}
59
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000060ViECodecImpl::ViECodecImpl() {
61 WEBRTC_TRACE(kTraceMemory, kTraceVideo, instance_id_,
niklase@google.com470e71d2011-07-07 08:21:25 +000062 "ViECodecImpl::ViECodecImpl() Ctor");
63}
64
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000065ViECodecImpl::~ViECodecImpl() {
66 WEBRTC_TRACE(kTraceMemory, kTraceVideo, instance_id_,
niklase@google.com470e71d2011-07-07 08:21:25 +000067 "ViECodecImpl::~ViECodecImpl() Dtor");
68}
69
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000070int ViECodecImpl::NumberOfCodecs() const {
71 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +000072 __FUNCTION__);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000073 // +2 because of FEC(RED and ULPFEC)
74 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
niklase@google.com470e71d2011-07-07 08:21:25 +000075}
76
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000077int ViECodecImpl::GetCodec(const unsigned char list_number,
78 VideoCodec& video_codec) const {
79 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_),
80 "%s(list_number: %d, codec_type: %d)", __FUNCTION__,
81 list_number, video_codec.codecType);
82 if (list_number == VideoCodingModule::NumberOfCodecs()) {
83 memset(&video_codec, 0, sizeof(VideoCodec));
84 strcpy(video_codec.plName, "RED");
85 video_codec.codecType = kVideoCodecRED;
86 video_codec.plType = VCM_RED_PAYLOAD_TYPE;
87 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
88 memset(&video_codec, 0, sizeof(VideoCodec));
89 strcpy(video_codec.plName, "ULPFEC");
90 video_codec.codecType = kVideoCodecULPFEC;
91 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
92 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
93 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_),
94 "%s: Could not get codec for list_number: %u", __FUNCTION__,
95 list_number);
96 SetLastError(kViECodecInvalidArgument);
97 return -1;
98 }
99 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000100}
101
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000102int ViECodecImpl::SetSendCodec(const int video_channel,
103 const VideoCodec& video_codec) {
104 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
105 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
106 video_channel, video_codec.codecType);
107 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
108 "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d"
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000109 "maxBr: %d, min_br: %d, frame_rate: %d, qpMax: %u,"
110 "numberOfSimulcastStreams: %u )", __FUNCTION__,
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000111 video_codec.codecType, video_codec.plType, video_codec.width,
112 video_codec.height, video_codec.startBitrate,
113 video_codec.maxBitrate, video_codec.minBitrate,
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000114 video_codec.maxFramerate, video_codec.qpMax,
115 video_codec.numberOfSimulcastStreams);
116 if (video_codec.codecType == kVideoCodecVP8) {
117 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
118 "pictureLossIndicationOn: %d, feedbackModeOn: %d, "
119 "complexity: %d, resilience: %d, numberOfTemporalLayers: %u",
120 video_codec.codecSpecific.VP8.pictureLossIndicationOn,
121 video_codec.codecSpecific.VP8.feedbackModeOn,
122 video_codec.codecSpecific.VP8.complexity,
123 video_codec.codecSpecific.VP8.resilience,
124 video_codec.codecSpecific.VP8.numberOfTemporalLayers);
125 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000126 if (!CodecValid(video_codec)) {
127 // Error logged.
128 SetLastError(kViECodecInvalidCodec);
129 return -1;
130 }
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000131
mflodman@webrtc.org471e83e2011-11-24 15:16:00 +0000132 ViEChannelManagerScoped cs(channel_manager_);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000133 ViEChannel* vie_channel = cs.Channel(video_channel);
134 if (!vie_channel) {
135 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
136 "%s: No channel %d", __FUNCTION__, video_channel);
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000137 SetLastError(kViECodecInvalidChannelId);
138 return -1;
139 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000140
141 // Set a max_bitrate if the user hasn't set one.
142 VideoCodec video_codec_internal;
143 memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
144 if (video_codec_internal.maxBitrate == 0) {
145 // Max is one bit per pixel.
146 video_codec_internal.maxBitrate = (video_codec_internal.width *
147 video_codec_internal.height *
148 video_codec_internal.maxFramerate)
149 / 1000;
150 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
151 // Don't limit the set start bitrate.
152 video_codec_internal.maxBitrate = video_codec_internal.startBitrate;
153 }
154 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
155 "%s: New max bitrate set to %d kbps", __FUNCTION__,
156 video_codec_internal.maxBitrate);
157 }
158
159 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
160 if (!vie_encoder) {
161 assert(false);
162 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
163 "%s: No encoder found for channel %d", __FUNCTION__);
164 SetLastError(kViECodecInvalidChannelId);
165 return -1;
166 }
167
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000168 VideoCodec encoder;
169 vie_encoder->GetEncoder(encoder);
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000170 if (encoder.codecType != video_codec_internal.codecType &&
171 cs.ChannelUsingViEEncoder(video_channel)) {
172 // We don't allow changing codec type when several channels share encoder.
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000173 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
174 "%s: Settings differs from other channels using encoder",
175 __FUNCTION__);
176 SetLastError(kViECodecInUse);
177 return -1;
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000178 }
179 // Make sure to generate a new SSRC if the codec type and/or resolution has
180 // changed. This won't have any effect if the user has set an SSRC.
181 bool new_rtp_stream = false;
182 if (encoder.codecType != video_codec_internal.codecType ||
183 encoder.width != video_codec_internal.width ||
184 encoder.height != video_codec_internal.height) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000185 new_rtp_stream = true;
186 }
187 if (video_codec_internal.numberOfSimulcastStreams > 1) {
188 if (cs.ChannelUsingViEEncoder(video_channel)) {
189 // We don't allow simulcast channels to share encoder.
190 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
191 "%s: Can't share simulcast encoder",
192 __FUNCTION__);
193 SetLastError(kViECodecInUse);
194 return -1;
195 }
196 }
197
198 ViEInputManagerScoped is(input_manager_);
199 ViEFrameProviderBase* frame_provider = NULL;
200
201 // Stop the media flow while reconfiguring.
202 vie_encoder->Pause();
203
204 // Check if we have a frame provider that is a camera and can provide this
205 // codec for us.
206 bool use_capture_device_as_encoder = false;
207 frame_provider = is.FrameProvider(vie_encoder);
208 if (frame_provider) {
209 if (frame_provider->Id() >= kViECaptureIdBase &&
210 frame_provider->Id() <= kViECaptureIdMax) {
211 ViECapturer* vie_capture = static_cast<ViECapturer*>(frame_provider);
212 // Try to get preencoded. Nothing to do if it is not supported.
213 if (vie_capture && vie_capture->PreEncodeToViEEncoder(
214 video_codec_internal,
215 *vie_encoder,
216 video_channel) == 0) {
217 use_capture_device_as_encoder = true;
218 }
219 }
220 }
221
222 // Update the encoder settings if we are not using a capture device capable
223 // of this codec.
224 if (!use_capture_device_as_encoder &&
225 vie_encoder->SetEncoder(video_codec_internal) != 0) {
226 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
227 "%s: Could not change encoder for channel %d", __FUNCTION__,
228 video_channel);
229 SetLastError(kViECodecUnknownError);
230 return -1;
231 }
232
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000233 // Give the channel(s) the new information.
234 ChannelList channels;
235 cs.ChannelsUsingViEEncoder(video_channel, &channels);
236 for (ChannelList::iterator it = channels.begin(); it != channels.end();
237 ++it) {
238 bool ret = true;
239 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
240 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
241 "%s: Could not set send codec for channel %d", __FUNCTION__,
242 video_channel);
243 ret = false;
244 }
245 if (!ret) {
246 SetLastError(kViECodecUnknownError);
247 return -1;
248 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000249 }
250
251 // Update the protection mode, we might be switching NACK/FEC.
252 vie_encoder->UpdateProtectionMethod();
253
254 // Get new best format for frame provider.
255 if (frame_provider) {
256 frame_provider->FrameCallbackChanged();
257 }
258 // Restart the media flow
259 if (new_rtp_stream) {
260 // Stream settings changed, make sure we get a key frame.
261 vie_encoder->SendKeyFrame();
262 }
263 vie_encoder->Restart();
264 return 0;
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000265}
266
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000267int ViECodecImpl::GetSendCodec(const int video_channel,
268 VideoCodec& video_codec) const {
269 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
270 "%s(video_channel: %d)", __FUNCTION__, video_channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000271
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000272 ViEChannelManagerScoped cs(channel_manager_);
273 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
274 if (!vie_encoder) {
275 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
276 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
277 SetLastError(kViECodecInvalidChannelId);
278 return -1;
279 }
280 return vie_encoder->GetEncoder(video_codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000283int ViECodecImpl::SetReceiveCodec(const int video_channel,
284 const VideoCodec& video_codec) {
285 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
286 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
287 video_channel, video_codec.codecType);
288 WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(instance_id_, video_channel),
289 "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d,"
290 "maxBr: %d, min_br: %d, frame_rate: %d", __FUNCTION__,
291 video_codec.codecType, video_codec.plType, video_codec.width,
292 video_codec.height, video_codec.startBitrate,
293 video_codec.maxBitrate, video_codec.minBitrate,
294 video_codec.maxFramerate);
niklase@google.com470e71d2011-07-07 08:21:25 +0000295
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000296 if (CodecValid(video_codec) == false) {
297 // Error logged.
298 SetLastError(kViECodecInvalidCodec);
299 return -1;
300 }
301
302 ViEChannelManagerScoped cs(channel_manager_);
303 ViEChannel* vie_channel = cs.Channel(video_channel);
304 if (!vie_channel) {
305 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
306 "%s: No channel %d", __FUNCTION__, video_channel);
307 SetLastError(kViECodecInvalidChannelId);
308 return -1;
309 }
310
311 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
312 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
313 "%s: Could not set receive codec for channel %d",
314 __FUNCTION__, video_channel);
315 SetLastError(kViECodecUnknownError);
316 return -1;
317 }
318 return 0;
319}
320
321int ViECodecImpl::GetReceiveCodec(const int video_channel,
322 VideoCodec& video_codec) const {
323 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
324 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
325 video_channel, video_codec.codecType);
326
327 ViEChannelManagerScoped cs(channel_manager_);
328 ViEChannel* vie_channel = cs.Channel(video_channel);
329 if (!vie_channel) {
330 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
331 "%s: No channel %d", __FUNCTION__, video_channel);
332 SetLastError(kViECodecInvalidChannelId);
333 return -1;
334 }
335
336 if (vie_channel->GetReceiveCodec(video_codec) != 0) {
337 SetLastError(kViECodecUnknownError);
338 return -1;
339 }
340 return 0;
341}
342
343int ViECodecImpl::GetCodecConfigParameters(
344 const int video_channel,
345 unsigned char config_parameters[kConfigParameterSize],
346 unsigned char& config_parameters_size) const {
347 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
348 "%s(video_channel: %d)", __FUNCTION__, video_channel);
349
350 ViEChannelManagerScoped cs(channel_manager_);
351 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
352 if (!vie_encoder) {
353 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
354 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
355 SetLastError(kViECodecInvalidChannelId);
356 return -1;
357 }
358
359 if (vie_encoder->GetCodecConfigParameters(config_parameters,
360 config_parameters_size) != 0) {
361 SetLastError(kViECodecUnknownError);
362 return -1;
363 }
364 return 0;
365}
366
367int ViECodecImpl::SetImageScaleStatus(const int video_channel,
368 const bool enable) {
369 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
370 "%s(video_channel: %d, enable: %d)", __FUNCTION__, video_channel,
371 enable);
372
373 ViEChannelManagerScoped cs(channel_manager_);
374 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
375 if (!vie_encoder) {
376 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
377 "%s: No channel %d", __FUNCTION__, video_channel);
378 SetLastError(kViECodecInvalidChannelId);
379 return -1;
380 }
381
382 if (vie_encoder->ScaleInputImage(enable) != 0) {
383 SetLastError(kViECodecUnknownError);
384 return -1;
385 }
386 return 0;
387}
388
389int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
390 unsigned int& key_frames,
391 unsigned int& delta_frames) const {
392 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
393 "%s(video_channel %d)", __FUNCTION__, video_channel);
394
395 ViEChannelManagerScoped cs(channel_manager_);
396 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
397 if (!vie_encoder) {
398 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
399 "%s: No send codec for channel %d", __FUNCTION__,
400 video_channel);
401 SetLastError(kViECodecInvalidChannelId);
402 return -1;
403 }
404
405 if (vie_encoder->SendCodecStatistics(key_frames, delta_frames) != 0) {
406 SetLastError(kViECodecUnknownError);
407 return -1;
408 }
409 return 0;
410}
411
412int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
413 unsigned int& key_frames,
414 unsigned int& delta_frames) const {
415 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
416 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
417 video_channel);
418
419 ViEChannelManagerScoped cs(channel_manager_);
420 ViEChannel* vie_channel = cs.Channel(video_channel);
421 if (!vie_channel) {
422 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
423 "%s: No channel %d", __FUNCTION__, video_channel);
424 SetLastError(kViECodecInvalidChannelId);
425 return -1;
426 }
427 if (vie_channel->ReceiveCodecStatistics(key_frames, delta_frames) != 0) {
428 SetLastError(kViECodecUnknownError);
429 return -1;
430 }
431 return 0;
432}
433
434unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
435 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
436 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
437 video_channel);
438
439 ViEChannelManagerScoped cs(channel_manager_);
440 ViEChannel* vie_channel = cs.Channel(video_channel);
441 if (!vie_channel) {
442 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
443 "%s: No channel %d", __FUNCTION__, video_channel);
444 SetLastError(kViECodecInvalidChannelId);
445 return -1;
446 }
447 return vie_channel->DiscardedPackets();
448}
449
450int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
451 const bool enable) {
452 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
453 "%s(video_channel: %d)", __FUNCTION__, video_channel);
454
455 ViEChannelManagerScoped cs(channel_manager_);
456 ViEChannel* vie_channel = cs.Channel(video_channel);
457 if (!vie_channel) {
458 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
459 "%s: No channel %d", __FUNCTION__, video_channel);
460 SetLastError(kViECodecInvalidChannelId);
461 return -1;
462 }
463 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
464 SetLastError(kViECodecUnknownError);
465 return -1;
466 }
467 return 0;
468}
469
470int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
niklase@google.com470e71d2011-07-07 08:21:25 +0000471 const bool enable,
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000472 const bool only_key_frames) {
473 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_, video_channel),
474 "%s(video_channel: %d, enable: %d, only_key_frames: %d)",
475 __FUNCTION__, video_channel, enable);
niklase@google.com470e71d2011-07-07 08:21:25 +0000476
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000477 ViEChannelManagerScoped cs(channel_manager_);
478 ViEChannel* vie_channel = cs.Channel(video_channel);
479 if (!vie_channel) {
480 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
481 "%s: No channel %d", __FUNCTION__, video_channel);
482 SetLastError(kViECodecInvalidChannelId);
483 return -1;
484 }
485 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
486 SetLastError(kViECodecUnknownError);
487 return -1;
488 }
489 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000490}
491
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000492int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
493 ViEEncoderObserver& observer) {
494 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000495 __FUNCTION__);
496
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000497 ViEChannelManagerScoped cs(channel_manager_);
498 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
499 if (!vie_encoder) {
500 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
501 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
502 SetLastError(kViECodecInvalidChannelId);
503 return -1;
504 }
505 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
506 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
507 "%s: Could not register codec observer at channel",
508 __FUNCTION__);
509 SetLastError(kViECodecObserverAlreadyRegistered);
510 return -1;
511 }
512 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000513}
514
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000515int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
516 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000517 __FUNCTION__);
518
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000519 ViEChannelManagerScoped cs(channel_manager_);
520 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
521 if (!vie_encoder) {
522 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
523 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
524 SetLastError(kViECodecInvalidChannelId);
525 return -1;
526 }
527 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
528 SetLastError(kViECodecObserverNotRegistered);
529 return -1;
530 }
531 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000532}
533
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000534int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
535 ViEDecoderObserver& observer) {
536 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000537 __FUNCTION__);
538
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000539 ViEChannelManagerScoped cs(channel_manager_);
540 ViEChannel* vie_channel = cs.Channel(video_channel);
541 if (!vie_channel) {
542 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
543 "%s: No channel %d", __FUNCTION__, video_channel);
544 SetLastError(kViECodecInvalidChannelId);
545 return -1;
546 }
547 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
548 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
549 "%s: Could not register codec observer at channel",
550 __FUNCTION__);
551 SetLastError(kViECodecObserverAlreadyRegistered);
552 return -1;
553 }
554 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000555}
556
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000557int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
558 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_), "%s",
niklase@google.com470e71d2011-07-07 08:21:25 +0000559 __FUNCTION__);
560
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000561 ViEChannelManagerScoped cs(channel_manager_);
562 ViEChannel* vie_channel = cs.Channel(video_channel);
563 if (!vie_channel) {
564 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
565 "%s: No channel %d", __FUNCTION__, video_channel);
566 SetLastError(kViECodecInvalidChannelId);
567 return -1;
568 }
569 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
570 SetLastError(kViECodecObserverNotRegistered);
571 return -1;
572 }
573 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000574}
575
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000576int ViECodecImpl::SendKeyFrame(const int video_channel) {
577 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_),
578 "%s(video_channel: %d)", __FUNCTION__, video_channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000579
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000580 ViEChannelManagerScoped cs(channel_manager_);
581 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
582 if (!vie_encoder) {
583 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
584 "%s: No channel %d", __FUNCTION__, video_channel);
585 SetLastError(kViECodecInvalidChannelId);
586 return -1;
587 }
588 if (vie_encoder->SendKeyFrame() != 0) {
589 SetLastError(kViECodecUnknownError);
590 return -1;
591 }
592 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000593}
594
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000595int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
596 const bool wait) {
597 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_),
598 "%s(video_channel: %d, wait: %d)", __FUNCTION__, video_channel,
niklase@google.com470e71d2011-07-07 08:21:25 +0000599 wait);
600
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000601 ViEChannelManagerScoped cs(channel_manager_);
602 ViEChannel* vie_channel = cs.Channel(video_channel);
603 if (!vie_channel) {
604 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
605 "%s: No channel %d", __FUNCTION__, video_channel);
606 SetLastError(kViECodecInvalidChannelId);
607 return -1;
608 }
609 if (vie_channel->WaitForKeyFrame(wait) != 0) {
610 SetLastError(kViECodecUnknownError);
611 return -1;
612 }
613 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000614}
615
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000616int ViECodecImpl::SetInverseH263Logic(int video_channel, bool enable) {
617 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(instance_id_),
618 "%s(video_channel: %d)", __FUNCTION__, video_channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000619
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000620 ViEChannelManagerScoped cs(channel_manager_);
621 ViEChannel* vie_channel = cs.Channel(video_channel);
622 if (!vie_channel) {
623 WEBRTC_TRACE(kTraceError, kTraceVideo, ViEId(instance_id_, video_channel),
624 "%s: No channel %d", __FUNCTION__, video_channel);
625 SetLastError(kViECodecInvalidChannelId);
626 return -1;
627 }
628 if (vie_channel->SetInverseH263Logic(enable) != 0) {
629 SetLastError(kViECodecUnknownError);
630 return -1;
631 }
632 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000633}
634
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000635bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
636 // Check pl_name matches codec_type.
637 if (video_codec.codecType == kVideoCodecRED) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000638#if defined(WIN32)
mflodman@webrtc.org1fe2ada2011-12-21 12:23:15 +0000639 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000640#else
641 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000642#endif
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000643 // We only care about the type and name for red.
644 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000645 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000646 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
647 "Codec type doesn't match pl_name", video_codec.plType);
648 return false;
649 } else if (video_codec.codecType == kVideoCodecULPFEC) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000650#if defined(WIN32)
mflodman@webrtc.org1fe2ada2011-12-21 12:23:15 +0000651 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000652#else
653 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000654#endif
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000655 // We only care about the type and name for ULPFEC.
656 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000657 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000658 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
659 "Codec type doesn't match pl_name", video_codec.plType);
660 return false;
661 } else if ((video_codec.codecType == kVideoCodecH263 &&
662 strncmp(video_codec.plName, "H263", 4) == 0) ||
663 (video_codec.codecType == kVideoCodecH263 &&
664 strncmp(video_codec.plName, "H263-1998", 9) == 0) ||
665 (video_codec.codecType == kVideoCodecVP8 &&
666 strncmp(video_codec.plName, "VP8", 4) == 0) ||
667 (video_codec.codecType == kVideoCodecI420 &&
668 strncmp(video_codec.plName, "I420", 4) == 0) ||
669 (video_codec.codecType == kVideoCodecH264 &&
670 strncmp(video_codec.plName, "H264", 4) == 0)) {
671 // OK.
672 } else {
673 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
674 "Codec type doesn't match pl_name", video_codec.plType);
675 return false;
676 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000677
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000678 if (video_codec.plType == 0 && video_codec.plType > 127) {
679 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
680 "Invalid codec payload type: %d", video_codec.plType);
681 return false;
682 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000683
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000684 if (video_codec.width > kViEMaxCodecWidth ||
685 video_codec.height > kViEMaxCodecHeight) {
686 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid codec size: %u x %u",
687 video_codec.width, video_codec.height);
688 return false;
689 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000690
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000691 if (video_codec.startBitrate < kViEMinCodecBitrate) {
692 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid start_bitrate: %u",
693 video_codec.startBitrate);
694 return false;
695 }
696 if (video_codec.minBitrate < kViEMinCodecBitrate) {
697 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid min_bitrate: %u",
698 video_codec.minBitrate);
699 return false;
700 }
701 if (video_codec.numberOfSimulcastStreams == 1) {
702 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
703 "Number of Simulcast streams can not be 1");
704 return false;
705 }
706 if (video_codec.codecType == kVideoCodecH263) {
707 if ((video_codec.width == 704 && video_codec.height == 576) ||
708 (video_codec.width == 352 && video_codec.height == 288) ||
709 (video_codec.width == 176 && video_codec.height == 144) ||
710 (video_codec.width == 128 && video_codec.height == 96)) {
711 // OK.
712 } else {
713 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid size for H.263");
714 return false;
niklase@google.com470e71d2011-07-07 08:21:25 +0000715 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000716 }
717 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000718}
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000719
720} // namespace webrtc