blob: 7518d175d21f4339798c5ae5787e1cf79dd137c6 [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001/*
2 * Copyright (c) 2012 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
11#include "video_engine/vie_codec_impl.h"
12
13#include <list>
14
15#include "engine_configurations.h" // NOLINT
16#include "modules/video_coding/main/interface/video_coding.h"
17#include "system_wrappers/interface/trace.h"
18#include "video_engine/include/vie_errors.h"
19#include "video_engine/vie_capturer.h"
20#include "video_engine/vie_channel.h"
21#include "video_engine/vie_channel_manager.h"
22#include "video_engine/vie_defines.h"
23#include "video_engine/vie_encoder.h"
24#include "video_engine/vie_impl.h"
25#include "video_engine/vie_input_manager.h"
26#include "video_engine/vie_shared_data.h"
27
28namespace webrtc {
29
30ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
31#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
32 if (!video_engine) {
33 return NULL;
34 }
35 VideoEngineImpl* vie_impl = reinterpret_cast<VideoEngineImpl*>(video_engine);
36 ViECodecImpl* vie_codec_impl = vie_impl;
37 // Increase ref count.
38 (*vie_codec_impl)++;
39 return vie_codec_impl;
40#else
41 return NULL;
42#endif
43}
44
45int ViECodecImpl::Release() {
46 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, shared_data_->instance_id(),
47 "ViECodecImpl::Release()");
48 // Decrease ref count.
49 (*this)--;
50
51 WebRtc_Word32 ref_count = GetCount();
52 if (ref_count < 0) {
53 WEBRTC_TRACE(kTraceWarning, kTraceVideo, shared_data_->instance_id(),
54 "ViECodec released too many times");
55 shared_data_->SetLastError(kViEAPIDoesNotExist);
56 return -1;
57 }
58 WEBRTC_TRACE(kTraceInfo, kTraceVideo, shared_data_->instance_id(),
59 "ViECodec reference count: %d", ref_count);
60 return ref_count;
61}
62
63ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
64 : shared_data_(shared_data) {
65 WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
66 "ViECodecImpl::ViECodecImpl() Ctor");
67}
68
69ViECodecImpl::~ViECodecImpl() {
70 WEBRTC_TRACE(kTraceMemory, kTraceVideo, shared_data_->instance_id(),
71 "ViECodecImpl::~ViECodecImpl() Dtor");
72}
73
74int ViECodecImpl::NumberOfCodecs() const {
75 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
76 "%s", __FUNCTION__);
77 // +2 because of FEC(RED and ULPFEC)
78 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
79}
80
81int ViECodecImpl::GetCodec(const unsigned char list_number,
82 VideoCodec& video_codec) const {
83 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
84 "%s(list_number: %d, codec_type: %d)", __FUNCTION__,
85 list_number, video_codec.codecType);
86 if (list_number == VideoCodingModule::NumberOfCodecs()) {
87 memset(&video_codec, 0, sizeof(VideoCodec));
88 strncpy(video_codec.plName, "red", 3);
89 video_codec.codecType = kVideoCodecRED;
90 video_codec.plType = VCM_RED_PAYLOAD_TYPE;
91 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
92 memset(&video_codec, 0, sizeof(VideoCodec));
93 strncpy(video_codec.plName, "ulpfec", 6);
94 video_codec.codecType = kVideoCodecULPFEC;
95 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
96 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
97 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
98 "%s: Could not get codec for list_number: %u", __FUNCTION__,
99 list_number);
100 shared_data_->SetLastError(kViECodecInvalidArgument);
101 return -1;
102 }
103 return 0;
104}
105
106int ViECodecImpl::SetSendCodec(const int video_channel,
107 const VideoCodec& video_codec) {
108 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
109 ViEId(shared_data_->instance_id(), video_channel),
110 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
111 video_channel, video_codec.codecType);
112 WEBRTC_TRACE(kTraceInfo, kTraceVideo,
113 ViEId(shared_data_->instance_id(), video_channel),
114 "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d"
115 "maxBr: %d, min_br: %d, frame_rate: %d, qpMax: %u,"
116 "numberOfSimulcastStreams: %u )", __FUNCTION__,
117 video_codec.codecType, video_codec.plType, video_codec.width,
118 video_codec.height, video_codec.startBitrate,
119 video_codec.maxBitrate, video_codec.minBitrate,
120 video_codec.maxFramerate, video_codec.qpMax,
121 video_codec.numberOfSimulcastStreams);
122 if (video_codec.codecType == kVideoCodecVP8) {
123 WEBRTC_TRACE(kTraceInfo, kTraceVideo,
124 ViEId(shared_data_->instance_id(), video_channel),
125 "pictureLossIndicationOn: %d, feedbackModeOn: %d, "
126 "complexity: %d, resilience: %d, numberOfTemporalLayers: %u",
127 video_codec.codecSpecific.VP8.pictureLossIndicationOn,
128 video_codec.codecSpecific.VP8.feedbackModeOn,
129 video_codec.codecSpecific.VP8.complexity,
130 video_codec.codecSpecific.VP8.resilience,
131 video_codec.codecSpecific.VP8.numberOfTemporalLayers);
132 }
133 if (!CodecValid(video_codec)) {
134 // Error logged.
135 shared_data_->SetLastError(kViECodecInvalidCodec);
136 return -1;
137 }
138
139 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
140 ViEChannel* vie_channel = cs.Channel(video_channel);
141 if (!vie_channel) {
142 WEBRTC_TRACE(kTraceError, kTraceVideo,
143 ViEId(shared_data_->instance_id(), video_channel),
144 "%s: No channel %d", __FUNCTION__, video_channel);
145 shared_data_->SetLastError(kViECodecInvalidChannelId);
146 return -1;
147 }
148
149 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
150 assert(vie_encoder);
151 if (vie_encoder->Owner() != video_channel) {
152 WEBRTC_TRACE(kTraceError, kTraceVideo,
153 ViEId(shared_data_->instance_id(), video_channel),
154 "%s: Receive only channel %d", __FUNCTION__, video_channel);
155 shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
156 return -1;
157 }
158
159 // Set a max_bitrate if the user hasn't set one.
160 VideoCodec video_codec_internal;
161 memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
162 if (video_codec_internal.maxBitrate == 0) {
163 // Max is one bit per pixel.
164 video_codec_internal.maxBitrate = (video_codec_internal.width *
165 video_codec_internal.height *
166 video_codec_internal.maxFramerate)
167 / 1000;
168 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
169 // Don't limit the set start bitrate.
170 video_codec_internal.maxBitrate = video_codec_internal.startBitrate;
171 }
172 WEBRTC_TRACE(kTraceInfo, kTraceVideo,
173 ViEId(shared_data_->instance_id(), video_channel),
174 "%s: New max bitrate set to %d kbps", __FUNCTION__,
175 video_codec_internal.maxBitrate);
176 }
177
178 VideoCodec encoder;
179 vie_encoder->GetEncoder(&encoder);
180
181 // Make sure to generate a new SSRC if the codec type and/or resolution has
182 // changed. This won't have any effect if the user has set an SSRC.
183 bool new_rtp_stream = false;
184 if (encoder.codecType != video_codec_internal.codecType) {
185 new_rtp_stream = true;
186 }
187
188 ViEInputManagerScoped is(*(shared_data_->input_manager()));
189 ViEFrameProviderBase* frame_provider = NULL;
190
191 // Stop the media flow while reconfiguring.
192 vie_encoder->Pause();
193
194 // Check if we have a frame provider that is a camera and can provide this
195 // codec for us.
196 bool use_capture_device_as_encoder = false;
197 frame_provider = is.FrameProvider(vie_encoder);
198 if (frame_provider) {
199 if (frame_provider->Id() >= kViECaptureIdBase &&
200 frame_provider->Id() <= kViECaptureIdMax) {
201 ViECapturer* vie_capture = static_cast<ViECapturer*>(frame_provider);
202 // Try to get preencoded. Nothing to do if it is not supported.
203 if (vie_capture && vie_capture->PreEncodeToViEEncoder(
204 video_codec_internal,
205 *vie_encoder,
206 video_channel) == 0) {
207 use_capture_device_as_encoder = true;
208 }
209 }
210 }
211
212 // Update the encoder settings if we are not using a capture device capable
213 // of this codec.
214 if (!use_capture_device_as_encoder &&
215 vie_encoder->SetEncoder(video_codec_internal) != 0) {
216 WEBRTC_TRACE(kTraceError, kTraceVideo,
217 ViEId(shared_data_->instance_id(), video_channel),
218 "%s: Could not change encoder for channel %d", __FUNCTION__,
219 video_channel);
220 shared_data_->SetLastError(kViECodecUnknownError);
221 return -1;
222 }
223
224 // Give the channel(s) the new information.
225 ChannelList channels;
226 cs.ChannelsUsingViEEncoder(video_channel, &channels);
227 for (ChannelList::iterator it = channels.begin(); it != channels.end();
228 ++it) {
229 bool ret = true;
230 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
231 WEBRTC_TRACE(kTraceError, kTraceVideo,
232 ViEId(shared_data_->instance_id(), video_channel),
233 "%s: Could not set send codec for channel %d", __FUNCTION__,
234 video_channel);
235 ret = false;
236 }
237 if (!ret) {
238 shared_data_->SetLastError(kViECodecUnknownError);
239 return -1;
240 }
241 }
242
243 // TODO(mflodman) Break out this part in GetLocalSsrcListi().
244 // Update all SSRCs to ViEEncoder.
245 std::list<unsigned int> ssrcs;
246 if (video_codec_internal.numberOfSimulcastStreams == 0) {
247 unsigned int ssrc = 0;
248 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
249 WEBRTC_TRACE(kTraceError, kTraceVideo,
250 ViEId(shared_data_->instance_id(), video_channel),
251 "%s: Could not get ssrc", __FUNCTION__);
252 }
253 ssrcs.push_back(ssrc);
254 } else {
255 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
256 ++idx) {
257 unsigned int ssrc = 0;
258 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
259 WEBRTC_TRACE(kTraceError, kTraceVideo,
260 ViEId(shared_data_->instance_id(), video_channel),
261 "%s: Could not get ssrc for idx %d", __FUNCTION__, idx);
262 }
263 ssrcs.push_back(ssrc);
264 }
265 }
266 vie_encoder->SetSsrcs(ssrcs);
267 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
268
269 // Update the protection mode, we might be switching NACK/FEC.
270 vie_encoder->UpdateProtectionMethod();
271
272 // Get new best format for frame provider.
273 if (frame_provider) {
274 frame_provider->FrameCallbackChanged();
275 }
276 // Restart the media flow
277 if (new_rtp_stream) {
278 // Stream settings changed, make sure we get a key frame.
279 vie_encoder->SendKeyFrame();
280 }
281 vie_encoder->Restart();
282 return 0;
283}
284
285int ViECodecImpl::GetSendCodec(const int video_channel,
286 VideoCodec& video_codec) const {
287 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
288 ViEId(shared_data_->instance_id(), video_channel),
289 "%s(video_channel: %d)", __FUNCTION__, video_channel);
290
291 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
292 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
293 if (!vie_encoder) {
294 WEBRTC_TRACE(kTraceError, kTraceVideo,
295 ViEId(shared_data_->instance_id(), video_channel),
296 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
297 shared_data_->SetLastError(kViECodecInvalidChannelId);
298 return -1;
299 }
300 return vie_encoder->GetEncoder(&video_codec);
301}
302
303int ViECodecImpl::SetReceiveCodec(const int video_channel,
304 const VideoCodec& video_codec) {
305 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
306 ViEId(shared_data_->instance_id(), video_channel),
307 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
308 video_channel, video_codec.codecType);
309 WEBRTC_TRACE(kTraceInfo, kTraceVideo,
310 ViEId(shared_data_->instance_id(), video_channel),
311 "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d,"
312 "maxBr: %d, min_br: %d, frame_rate: %d", __FUNCTION__,
313 video_codec.codecType, video_codec.plType, video_codec.width,
314 video_codec.height, video_codec.startBitrate,
315 video_codec.maxBitrate, video_codec.minBitrate,
316 video_codec.maxFramerate);
317
318 if (CodecValid(video_codec) == false) {
319 // Error logged.
320 shared_data_->SetLastError(kViECodecInvalidCodec);
321 return -1;
322 }
323
324 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
325 ViEChannel* vie_channel = cs.Channel(video_channel);
326 if (!vie_channel) {
327 WEBRTC_TRACE(kTraceError, kTraceVideo,
328 ViEId(shared_data_->instance_id(), video_channel),
329 "%s: No channel %d", __FUNCTION__, video_channel);
330 shared_data_->SetLastError(kViECodecInvalidChannelId);
331 return -1;
332 }
333
334 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
335 WEBRTC_TRACE(kTraceError, kTraceVideo,
336 ViEId(shared_data_->instance_id(), video_channel),
337 "%s: Could not set receive codec for channel %d",
338 __FUNCTION__, video_channel);
339 shared_data_->SetLastError(kViECodecUnknownError);
340 return -1;
341 }
342 return 0;
343}
344
345int ViECodecImpl::GetReceiveCodec(const int video_channel,
346 VideoCodec& video_codec) const {
347 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
348 ViEId(shared_data_->instance_id(), video_channel),
349 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
350 video_channel, video_codec.codecType);
351
352 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
353 ViEChannel* vie_channel = cs.Channel(video_channel);
354 if (!vie_channel) {
355 WEBRTC_TRACE(kTraceError, kTraceVideo,
356 ViEId(shared_data_->instance_id(), video_channel),
357 "%s: No channel %d", __FUNCTION__, video_channel);
358 shared_data_->SetLastError(kViECodecInvalidChannelId);
359 return -1;
360 }
361
362 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
363 shared_data_->SetLastError(kViECodecUnknownError);
364 return -1;
365 }
366 return 0;
367}
368
369int ViECodecImpl::GetCodecConfigParameters(
370 const int video_channel,
371 unsigned char config_parameters[kConfigParameterSize],
372 unsigned char& config_parameters_size) const {
373 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
374 ViEId(shared_data_->instance_id(), video_channel),
375 "%s(video_channel: %d)", __FUNCTION__, video_channel);
376
377 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
378 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
379 if (!vie_encoder) {
380 WEBRTC_TRACE(kTraceError, kTraceVideo,
381 ViEId(shared_data_->instance_id(), video_channel),
382 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
383 shared_data_->SetLastError(kViECodecInvalidChannelId);
384 return -1;
385 }
386
387 if (vie_encoder->GetCodecConfigParameters(config_parameters,
388 config_parameters_size) != 0) {
389 shared_data_->SetLastError(kViECodecUnknownError);
390 return -1;
391 }
392 return 0;
393}
394
395int ViECodecImpl::SetImageScaleStatus(const int video_channel,
396 const bool enable) {
397 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
398 ViEId(shared_data_->instance_id(), video_channel),
399 "%s(video_channel: %d, enable: %d)", __FUNCTION__, video_channel,
400 enable);
401
402 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
403 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
404 if (!vie_encoder) {
405 WEBRTC_TRACE(kTraceError, kTraceVideo,
406 ViEId(shared_data_->instance_id(), video_channel),
407 "%s: No channel %d", __FUNCTION__, video_channel);
408 shared_data_->SetLastError(kViECodecInvalidChannelId);
409 return -1;
410 }
411
412 if (vie_encoder->ScaleInputImage(enable) != 0) {
413 shared_data_->SetLastError(kViECodecUnknownError);
414 return -1;
415 }
416 return 0;
417}
418
419int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
420 unsigned int& key_frames,
421 unsigned int& delta_frames) const {
422 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
423 ViEId(shared_data_->instance_id(), video_channel),
424 "%s(video_channel %d)", __FUNCTION__, video_channel);
425
426 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
427 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
428 if (!vie_encoder) {
429 WEBRTC_TRACE(kTraceError, kTraceVideo,
430 ViEId(shared_data_->instance_id(), video_channel),
431 "%s: No send codec for channel %d", __FUNCTION__,
432 video_channel);
433 shared_data_->SetLastError(kViECodecInvalidChannelId);
434 return -1;
435 }
436
437 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
438 shared_data_->SetLastError(kViECodecUnknownError);
439 return -1;
440 }
441 return 0;
442}
443
444int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
445 unsigned int& key_frames,
446 unsigned int& delta_frames) const {
447 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
448 ViEId(shared_data_->instance_id(), video_channel),
449 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
450 video_channel);
451
452 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
453 ViEChannel* vie_channel = cs.Channel(video_channel);
454 if (!vie_channel) {
455 WEBRTC_TRACE(kTraceError, kTraceVideo,
456 ViEId(shared_data_->instance_id(), video_channel),
457 "%s: No channel %d", __FUNCTION__, video_channel);
458 shared_data_->SetLastError(kViECodecInvalidChannelId);
459 return -1;
460 }
461 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
462 shared_data_->SetLastError(kViECodecUnknownError);
463 return -1;
464 }
465 return 0;
466}
467
468int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
469 unsigned int* bitrate) const {
470 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
471 ViEId(shared_data_->instance_id(), video_channel),
472 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
473 video_channel);
474
475 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
476 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
477 if (!vie_encoder) {
478 WEBRTC_TRACE(kTraceError, kTraceVideo,
479 ViEId(shared_data_->instance_id(), video_channel),
480 "%s: No send codec for channel %d", __FUNCTION__,
481 video_channel);
482 shared_data_->SetLastError(kViECodecInvalidChannelId);
483 return -1;
484 }
485 return vie_encoder->CodecTargetBitrate(static_cast<WebRtc_UWord32*>(bitrate));
486}
487
488unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
489 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
490 ViEId(shared_data_->instance_id(), video_channel),
491 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
492 video_channel);
493
494 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
495 ViEChannel* vie_channel = cs.Channel(video_channel);
496 if (!vie_channel) {
497 WEBRTC_TRACE(kTraceError, kTraceVideo,
498 ViEId(shared_data_->instance_id(), video_channel),
499 "%s: No channel %d", __FUNCTION__, video_channel);
500 shared_data_->SetLastError(kViECodecInvalidChannelId);
501 return -1;
502 }
503 return vie_channel->DiscardedPackets();
504}
505
506int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
507 const bool enable) {
508 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
509 ViEId(shared_data_->instance_id(), video_channel),
510 "%s(video_channel: %d)", __FUNCTION__, video_channel);
511
512 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
513 ViEChannel* vie_channel = cs.Channel(video_channel);
514 if (!vie_channel) {
515 WEBRTC_TRACE(kTraceError, kTraceVideo,
516 ViEId(shared_data_->instance_id(), video_channel),
517 "%s: No channel %d", __FUNCTION__, video_channel);
518 shared_data_->SetLastError(kViECodecInvalidChannelId);
519 return -1;
520 }
521 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
522 shared_data_->SetLastError(kViECodecUnknownError);
523 return -1;
524 }
525 return 0;
526}
527
528int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
529 const bool enable,
530 const bool only_key_frames) {
531 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
532 ViEId(shared_data_->instance_id(), video_channel),
533 "%s(video_channel: %d, enable: %d, only_key_frames: %d)",
534 __FUNCTION__, video_channel, enable);
535
536 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
537 ViEChannel* vie_channel = cs.Channel(video_channel);
538 if (!vie_channel) {
539 WEBRTC_TRACE(kTraceError, kTraceVideo,
540 ViEId(shared_data_->instance_id(), video_channel),
541 "%s: No channel %d", __FUNCTION__, video_channel);
542 shared_data_->SetLastError(kViECodecInvalidChannelId);
543 return -1;
544 }
545 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
546 shared_data_->SetLastError(kViECodecUnknownError);
547 return -1;
548 }
549 return 0;
550}
551
552int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
553 ViEEncoderObserver& observer) {
554 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
555 "%s", __FUNCTION__);
556
557 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
558 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
559 if (!vie_encoder) {
560 WEBRTC_TRACE(kTraceError, kTraceVideo,
561 ViEId(shared_data_->instance_id(), video_channel),
562 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
563 shared_data_->SetLastError(kViECodecInvalidChannelId);
564 return -1;
565 }
566 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
567 WEBRTC_TRACE(kTraceError, kTraceVideo,
568 ViEId(shared_data_->instance_id(), video_channel),
569 "%s: Could not register codec observer at channel",
570 __FUNCTION__);
571 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
572 return -1;
573 }
574 return 0;
575}
576
577int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
578 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
579 "%s", __FUNCTION__);
580
581 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
582 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
583 if (!vie_encoder) {
584 WEBRTC_TRACE(kTraceError, kTraceVideo,
585 ViEId(shared_data_->instance_id(), video_channel),
586 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
587 shared_data_->SetLastError(kViECodecInvalidChannelId);
588 return -1;
589 }
590 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
591 shared_data_->SetLastError(kViECodecObserverNotRegistered);
592 return -1;
593 }
594 return 0;
595}
596
597int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
598 ViEDecoderObserver& observer) {
599 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
600 "%s", __FUNCTION__);
601
602 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
603 ViEChannel* vie_channel = cs.Channel(video_channel);
604 if (!vie_channel) {
605 WEBRTC_TRACE(kTraceError, kTraceVideo,
606 ViEId(shared_data_->instance_id(), video_channel),
607 "%s: No channel %d", __FUNCTION__, video_channel);
608 shared_data_->SetLastError(kViECodecInvalidChannelId);
609 return -1;
610 }
611 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
612 WEBRTC_TRACE(kTraceError, kTraceVideo,
613 ViEId(shared_data_->instance_id(), video_channel),
614 "%s: Could not register codec observer at channel",
615 __FUNCTION__);
616 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
617 return -1;
618 }
619 return 0;
620}
621
622int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
623 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
624 ViEId(shared_data_->instance_id()), "%s",
625 __FUNCTION__);
626
627 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
628 ViEChannel* vie_channel = cs.Channel(video_channel);
629 if (!vie_channel) {
630 WEBRTC_TRACE(kTraceError, kTraceVideo,
631 ViEId(shared_data_->instance_id(), video_channel),
632 "%s: No channel %d", __FUNCTION__, video_channel);
633 shared_data_->SetLastError(kViECodecInvalidChannelId);
634 return -1;
635 }
636 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
637 shared_data_->SetLastError(kViECodecObserverNotRegistered);
638 return -1;
639 }
640 return 0;
641}
642
643int ViECodecImpl::SendKeyFrame(const int video_channel) {
644 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
645 "%s(video_channel: %d)", __FUNCTION__, video_channel);
646
647 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
648 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
649 if (!vie_encoder) {
650 WEBRTC_TRACE(kTraceError, kTraceVideo,
651 ViEId(shared_data_->instance_id(), video_channel),
652 "%s: No channel %d", __FUNCTION__, video_channel);
653 shared_data_->SetLastError(kViECodecInvalidChannelId);
654 return -1;
655 }
656 if (vie_encoder->SendKeyFrame() != 0) {
657 shared_data_->SetLastError(kViECodecUnknownError);
658 return -1;
659 }
660 return 0;
661}
662
663int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
664 const bool wait) {
665 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
666 ViEId(shared_data_->instance_id()),
667 "%s(video_channel: %d, wait: %d)", __FUNCTION__, video_channel,
668 wait);
669
670 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
671 ViEChannel* vie_channel = cs.Channel(video_channel);
672 if (!vie_channel) {
673 WEBRTC_TRACE(kTraceError, kTraceVideo,
674 ViEId(shared_data_->instance_id(), video_channel),
675 "%s: No channel %d", __FUNCTION__, video_channel);
676 shared_data_->SetLastError(kViECodecInvalidChannelId);
677 return -1;
678 }
679 if (vie_channel->WaitForKeyFrame(wait) != 0) {
680 shared_data_->SetLastError(kViECodecUnknownError);
681 return -1;
682 }
683 return 0;
684}
685
686bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
687 // Check pl_name matches codec_type.
688 if (video_codec.codecType == kVideoCodecRED) {
689#if defined(WIN32)
690 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
691#else
692 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
693#endif
694 // We only care about the type and name for red.
695 return true;
696 }
697 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
698 "Codec type doesn't match pl_name", video_codec.plType);
699 return false;
700 } else if (video_codec.codecType == kVideoCodecULPFEC) {
701#if defined(WIN32)
702 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
703#else
704 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
705#endif
706 // We only care about the type and name for ULPFEC.
707 return true;
708 }
709 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
710 "Codec type doesn't match pl_name", video_codec.plType);
711 return false;
712 } else if ((video_codec.codecType == kVideoCodecVP8 &&
713 strncmp(video_codec.plName, "VP8", 4) == 0) ||
714 (video_codec.codecType == kVideoCodecI420 &&
715 strncmp(video_codec.plName, "I420", 4) == 0)) {
716 // OK.
717 } else {
718 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
719 "Codec type doesn't match pl_name", video_codec.plType);
720 return false;
721 }
722
723 if (video_codec.plType == 0 && video_codec.plType > 127) {
724 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
725 "Invalid codec payload type: %d", video_codec.plType);
726 return false;
727 }
728
729 if (video_codec.width > kViEMaxCodecWidth ||
730 video_codec.height > kViEMaxCodecHeight) {
731 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid codec size: %u x %u",
732 video_codec.width, video_codec.height);
733 return false;
734 }
735
736 if (video_codec.startBitrate < kViEMinCodecBitrate) {
737 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid start_bitrate: %u",
738 video_codec.startBitrate);
739 return false;
740 }
741 if (video_codec.minBitrate < kViEMinCodecBitrate) {
742 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid min_bitrate: %u",
743 video_codec.minBitrate);
744 return false;
745 }
746 return true;
747}
748
749} // namespace webrtc