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