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