blob: 7df8cafc1079d65e81249e149d255f985d1ca425 [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
pbos@webrtc.org281cff82013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_codec_impl.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +000013#include <list>
14
pbos@webrtc.org281cff82013-05-17 13:44:48 +000015#include "webrtc/engine_configurations.h"
16#include "webrtc/modules/video_coding/main/interface/video_coding.h"
17#include "webrtc/system_wrappers/interface/logging.h"
18#include "webrtc/system_wrappers/interface/trace.h"
19#include "webrtc/video_engine/include/vie_errors.h"
20#include "webrtc/video_engine/vie_capturer.h"
21#include "webrtc/video_engine/vie_channel.h"
22#include "webrtc/video_engine/vie_channel_manager.h"
23#include "webrtc/video_engine/vie_defines.h"
24#include "webrtc/video_engine/vie_encoder.h"
25#include "webrtc/video_engine/vie_impl.h"
26#include "webrtc/video_engine/vie_input_manager.h"
27#include "webrtc/video_engine/vie_shared_data.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000028
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
mflodman@webrtc.orga18c6e52013-06-07 13:57:57 +0000196 if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000197 WEBRTC_TRACE(kTraceError, kTraceVideo,
198 ViEId(shared_data_->instance_id(), video_channel),
199 "%s: Could not change encoder for channel %d", __FUNCTION__,
200 video_channel);
201 shared_data_->SetLastError(kViECodecUnknownError);
202 return -1;
203 }
204
205 // Give the channel(s) the new information.
206 ChannelList channels;
207 cs.ChannelsUsingViEEncoder(video_channel, &channels);
208 for (ChannelList::iterator it = channels.begin(); it != channels.end();
209 ++it) {
210 bool ret = true;
211 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
212 WEBRTC_TRACE(kTraceError, kTraceVideo,
213 ViEId(shared_data_->instance_id(), video_channel),
214 "%s: Could not set send codec for channel %d", __FUNCTION__,
215 video_channel);
216 ret = false;
217 }
218 if (!ret) {
219 shared_data_->SetLastError(kViECodecUnknownError);
220 return -1;
221 }
222 }
223
mflodman@webrtc.orgb6d9cfc2012-10-25 11:30:29 +0000224 // TODO(mflodman) Break out this part in GetLocalSsrcList().
225 // Update all SSRCs to ViEEncoder.
226 std::list<unsigned int> ssrcs;
227 if (video_codec_internal.numberOfSimulcastStreams == 0) {
228 unsigned int ssrc = 0;
229 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
230 WEBRTC_TRACE(kTraceError, kTraceVideo,
231 ViEId(shared_data_->instance_id(), video_channel),
232 "%s: Could not get ssrc", __FUNCTION__);
233 }
234 ssrcs.push_back(ssrc);
235 } else {
236 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
237 ++idx) {
238 unsigned int ssrc = 0;
239 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
240 WEBRTC_TRACE(kTraceError, kTraceVideo,
241 ViEId(shared_data_->instance_id(), video_channel),
242 "%s: Could not get ssrc for idx %d", __FUNCTION__, idx);
243 }
244 ssrcs.push_back(ssrc);
245 }
246 }
247 vie_encoder->SetSsrcs(ssrcs);
248 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
249
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000250 // Update the protection mode, we might be switching NACK/FEC.
251 vie_encoder->UpdateProtectionMethod();
252
253 // Get new best format for frame provider.
254 if (frame_provider) {
255 frame_provider->FrameCallbackChanged();
256 }
257 // Restart the media flow
258 if (new_rtp_stream) {
259 // Stream settings changed, make sure we get a key frame.
260 vie_encoder->SendKeyFrame();
261 }
262 vie_encoder->Restart();
263 return 0;
264}
265
266int ViECodecImpl::GetSendCodec(const int video_channel,
267 VideoCodec& video_codec) const {
268 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
269 ViEId(shared_data_->instance_id(), video_channel),
270 "%s(video_channel: %d)", __FUNCTION__, video_channel);
271
272 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
273 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
274 if (!vie_encoder) {
275 WEBRTC_TRACE(kTraceError, kTraceVideo,
276 ViEId(shared_data_->instance_id(), video_channel),
277 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
278 shared_data_->SetLastError(kViECodecInvalidChannelId);
279 return -1;
280 }
281 return vie_encoder->GetEncoder(&video_codec);
282}
283
284int ViECodecImpl::SetReceiveCodec(const int video_channel,
285 const VideoCodec& video_codec) {
286 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
287 ViEId(shared_data_->instance_id(), video_channel),
288 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
289 video_channel, video_codec.codecType);
290 WEBRTC_TRACE(kTraceInfo, kTraceVideo,
291 ViEId(shared_data_->instance_id(), video_channel),
292 "%s: codec: %d, pl_type: %d, width: %d, height: %d, bitrate: %d,"
293 "maxBr: %d, min_br: %d, frame_rate: %d", __FUNCTION__,
294 video_codec.codecType, video_codec.plType, video_codec.width,
295 video_codec.height, video_codec.startBitrate,
296 video_codec.maxBitrate, video_codec.minBitrate,
297 video_codec.maxFramerate);
298
299 if (CodecValid(video_codec) == false) {
300 // Error logged.
301 shared_data_->SetLastError(kViECodecInvalidCodec);
302 return -1;
303 }
304
305 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
306 ViEChannel* vie_channel = cs.Channel(video_channel);
307 if (!vie_channel) {
308 WEBRTC_TRACE(kTraceError, kTraceVideo,
309 ViEId(shared_data_->instance_id(), video_channel),
310 "%s: No channel %d", __FUNCTION__, video_channel);
311 shared_data_->SetLastError(kViECodecInvalidChannelId);
312 return -1;
313 }
314
315 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
316 WEBRTC_TRACE(kTraceError, kTraceVideo,
317 ViEId(shared_data_->instance_id(), video_channel),
318 "%s: Could not set receive codec for channel %d",
319 __FUNCTION__, video_channel);
320 shared_data_->SetLastError(kViECodecUnknownError);
321 return -1;
322 }
323 return 0;
324}
325
326int ViECodecImpl::GetReceiveCodec(const int video_channel,
327 VideoCodec& video_codec) const {
328 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
329 ViEId(shared_data_->instance_id(), video_channel),
330 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
331 video_channel, video_codec.codecType);
332
333 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
334 ViEChannel* vie_channel = cs.Channel(video_channel);
335 if (!vie_channel) {
336 WEBRTC_TRACE(kTraceError, kTraceVideo,
337 ViEId(shared_data_->instance_id(), video_channel),
338 "%s: No channel %d", __FUNCTION__, video_channel);
339 shared_data_->SetLastError(kViECodecInvalidChannelId);
340 return -1;
341 }
342
343 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
344 shared_data_->SetLastError(kViECodecUnknownError);
345 return -1;
346 }
347 return 0;
348}
349
350int ViECodecImpl::GetCodecConfigParameters(
351 const int video_channel,
352 unsigned char config_parameters[kConfigParameterSize],
353 unsigned char& config_parameters_size) const {
354 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
355 ViEId(shared_data_->instance_id(), video_channel),
356 "%s(video_channel: %d)", __FUNCTION__, video_channel);
357
358 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
359 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
360 if (!vie_encoder) {
361 WEBRTC_TRACE(kTraceError, kTraceVideo,
362 ViEId(shared_data_->instance_id(), video_channel),
363 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
364 shared_data_->SetLastError(kViECodecInvalidChannelId);
365 return -1;
366 }
367
368 if (vie_encoder->GetCodecConfigParameters(config_parameters,
369 config_parameters_size) != 0) {
370 shared_data_->SetLastError(kViECodecUnknownError);
371 return -1;
372 }
373 return 0;
374}
375
376int ViECodecImpl::SetImageScaleStatus(const int video_channel,
377 const bool enable) {
378 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
379 ViEId(shared_data_->instance_id(), video_channel),
380 "%s(video_channel: %d, enable: %d)", __FUNCTION__, video_channel,
381 enable);
382
383 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
384 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
385 if (!vie_encoder) {
386 WEBRTC_TRACE(kTraceError, kTraceVideo,
387 ViEId(shared_data_->instance_id(), video_channel),
388 "%s: No channel %d", __FUNCTION__, video_channel);
389 shared_data_->SetLastError(kViECodecInvalidChannelId);
390 return -1;
391 }
392
393 if (vie_encoder->ScaleInputImage(enable) != 0) {
394 shared_data_->SetLastError(kViECodecUnknownError);
395 return -1;
396 }
397 return 0;
398}
399
400int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
401 unsigned int& key_frames,
402 unsigned int& delta_frames) const {
403 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
404 ViEId(shared_data_->instance_id(), video_channel),
405 "%s(video_channel %d)", __FUNCTION__, video_channel);
406
407 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
408 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
409 if (!vie_encoder) {
410 WEBRTC_TRACE(kTraceError, kTraceVideo,
411 ViEId(shared_data_->instance_id(), video_channel),
412 "%s: No send codec for channel %d", __FUNCTION__,
413 video_channel);
414 shared_data_->SetLastError(kViECodecInvalidChannelId);
415 return -1;
416 }
417
418 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
419 shared_data_->SetLastError(kViECodecUnknownError);
420 return -1;
421 }
422 return 0;
423}
424
425int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
426 unsigned int& key_frames,
427 unsigned int& delta_frames) const {
428 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
429 ViEId(shared_data_->instance_id(), video_channel),
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000430 "%s(video_channel: %d)", __FUNCTION__,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000431 video_channel);
432
433 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
434 ViEChannel* vie_channel = cs.Channel(video_channel);
435 if (!vie_channel) {
436 WEBRTC_TRACE(kTraceError, kTraceVideo,
437 ViEId(shared_data_->instance_id(), video_channel),
438 "%s: No channel %d", __FUNCTION__, video_channel);
439 shared_data_->SetLastError(kViECodecInvalidChannelId);
440 return -1;
441 }
442 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
443 shared_data_->SetLastError(kViECodecUnknownError);
444 return -1;
445 }
446 return 0;
447}
448
mflodman@webrtc.orgf314c802012-12-14 14:02:10 +0000449int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
450 int* delay_ms) const {
451 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
452 ViEId(shared_data_->instance_id(), video_channel),
453 "%s(video_channel: %d)", __FUNCTION__, video_channel);
454 if (delay_ms == NULL) {
455 LOG_F(LS_ERROR) << "NULL pointer argument.";
456 return -1;
457 }
458
459 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
460 ViEChannel* vie_channel = cs.Channel(video_channel);
461 if (!vie_channel) {
462 WEBRTC_TRACE(kTraceError, kTraceVideo,
463 ViEId(shared_data_->instance_id(), video_channel),
464 "%s: No channel %d", __FUNCTION__, video_channel);
465 shared_data_->SetLastError(kViECodecInvalidChannelId);
466 return -1;
467 }
468 *delay_ms = vie_channel->ReceiveDelay();
469 if (*delay_ms < 0) {
470 return -1;
471 }
472 return 0;
473}
474
475
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000476int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
477 unsigned int* bitrate) const {
478 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
479 ViEId(shared_data_->instance_id(), video_channel),
480 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
481 video_channel);
482
483 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
484 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
485 if (!vie_encoder) {
486 WEBRTC_TRACE(kTraceError, kTraceVideo,
487 ViEId(shared_data_->instance_id(), video_channel),
488 "%s: No send codec for channel %d", __FUNCTION__,
489 video_channel);
490 shared_data_->SetLastError(kViECodecInvalidChannelId);
491 return -1;
492 }
pbos@webrtc.org67879bc2013-04-09 13:41:51 +0000493 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000494}
495
496unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
497 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
498 ViEId(shared_data_->instance_id(), video_channel),
499 "%s(video_channel: %d, codec_type: %d)", __FUNCTION__,
500 video_channel);
501
502 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
503 ViEChannel* vie_channel = cs.Channel(video_channel);
504 if (!vie_channel) {
505 WEBRTC_TRACE(kTraceError, kTraceVideo,
506 ViEId(shared_data_->instance_id(), video_channel),
507 "%s: No channel %d", __FUNCTION__, video_channel);
508 shared_data_->SetLastError(kViECodecInvalidChannelId);
509 return -1;
510 }
511 return vie_channel->DiscardedPackets();
512}
513
514int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
515 const bool enable) {
516 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
517 ViEId(shared_data_->instance_id(), video_channel),
518 "%s(video_channel: %d)", __FUNCTION__, video_channel);
519
520 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
521 ViEChannel* vie_channel = cs.Channel(video_channel);
522 if (!vie_channel) {
523 WEBRTC_TRACE(kTraceError, kTraceVideo,
524 ViEId(shared_data_->instance_id(), video_channel),
525 "%s: No channel %d", __FUNCTION__, video_channel);
526 shared_data_->SetLastError(kViECodecInvalidChannelId);
527 return -1;
528 }
529 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
530 shared_data_->SetLastError(kViECodecUnknownError);
531 return -1;
532 }
533 return 0;
534}
535
536int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
537 const bool enable,
538 const bool only_key_frames) {
539 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
540 ViEId(shared_data_->instance_id(), video_channel),
541 "%s(video_channel: %d, enable: %d, only_key_frames: %d)",
542 __FUNCTION__, video_channel, enable);
543
544 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
545 ViEChannel* vie_channel = cs.Channel(video_channel);
546 if (!vie_channel) {
547 WEBRTC_TRACE(kTraceError, kTraceVideo,
548 ViEId(shared_data_->instance_id(), video_channel),
549 "%s: No channel %d", __FUNCTION__, video_channel);
550 shared_data_->SetLastError(kViECodecInvalidChannelId);
551 return -1;
552 }
553 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
554 shared_data_->SetLastError(kViECodecUnknownError);
555 return -1;
556 }
557 return 0;
558}
559
560int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
561 ViEEncoderObserver& observer) {
562 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
563 "%s", __FUNCTION__);
564
565 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
566 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
567 if (!vie_encoder) {
568 WEBRTC_TRACE(kTraceError, kTraceVideo,
569 ViEId(shared_data_->instance_id(), video_channel),
570 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
571 shared_data_->SetLastError(kViECodecInvalidChannelId);
572 return -1;
573 }
574 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
575 WEBRTC_TRACE(kTraceError, kTraceVideo,
576 ViEId(shared_data_->instance_id(), video_channel),
577 "%s: Could not register codec observer at channel",
578 __FUNCTION__);
579 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
580 return -1;
581 }
582 return 0;
583}
584
585int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
586 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
587 "%s", __FUNCTION__);
588
589 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
590 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
591 if (!vie_encoder) {
592 WEBRTC_TRACE(kTraceError, kTraceVideo,
593 ViEId(shared_data_->instance_id(), video_channel),
594 "%s: No encoder for channel %d", __FUNCTION__, video_channel);
595 shared_data_->SetLastError(kViECodecInvalidChannelId);
596 return -1;
597 }
598 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
599 shared_data_->SetLastError(kViECodecObserverNotRegistered);
600 return -1;
601 }
602 return 0;
603}
604
605int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
606 ViEDecoderObserver& observer) {
607 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
608 "%s", __FUNCTION__);
609
610 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
611 ViEChannel* vie_channel = cs.Channel(video_channel);
612 if (!vie_channel) {
613 WEBRTC_TRACE(kTraceError, kTraceVideo,
614 ViEId(shared_data_->instance_id(), video_channel),
615 "%s: No channel %d", __FUNCTION__, video_channel);
616 shared_data_->SetLastError(kViECodecInvalidChannelId);
617 return -1;
618 }
619 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
620 WEBRTC_TRACE(kTraceError, kTraceVideo,
621 ViEId(shared_data_->instance_id(), video_channel),
622 "%s: Could not register codec observer at channel",
623 __FUNCTION__);
624 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
625 return -1;
626 }
627 return 0;
628}
629
630int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
631 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
632 ViEId(shared_data_->instance_id()), "%s",
633 __FUNCTION__);
634
635 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
636 ViEChannel* vie_channel = cs.Channel(video_channel);
637 if (!vie_channel) {
638 WEBRTC_TRACE(kTraceError, kTraceVideo,
639 ViEId(shared_data_->instance_id(), video_channel),
640 "%s: No channel %d", __FUNCTION__, video_channel);
641 shared_data_->SetLastError(kViECodecInvalidChannelId);
642 return -1;
643 }
644 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
645 shared_data_->SetLastError(kViECodecObserverNotRegistered);
646 return -1;
647 }
648 return 0;
649}
650
651int ViECodecImpl::SendKeyFrame(const int video_channel) {
652 WEBRTC_TRACE(kTraceApiCall, kTraceVideo, ViEId(shared_data_->instance_id()),
653 "%s(video_channel: %d)", __FUNCTION__, video_channel);
654
655 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
656 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
657 if (!vie_encoder) {
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_encoder->SendKeyFrame() != 0) {
665 shared_data_->SetLastError(kViECodecUnknownError);
666 return -1;
667 }
668 return 0;
669}
670
671int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
672 const bool wait) {
673 WEBRTC_TRACE(kTraceApiCall, kTraceVideo,
674 ViEId(shared_data_->instance_id()),
675 "%s(video_channel: %d, wait: %d)", __FUNCTION__, video_channel,
676 wait);
677
678 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
679 ViEChannel* vie_channel = cs.Channel(video_channel);
680 if (!vie_channel) {
681 WEBRTC_TRACE(kTraceError, kTraceVideo,
682 ViEId(shared_data_->instance_id(), video_channel),
683 "%s: No channel %d", __FUNCTION__, video_channel);
684 shared_data_->SetLastError(kViECodecInvalidChannelId);
685 return -1;
686 }
687 if (vie_channel->WaitForKeyFrame(wait) != 0) {
688 shared_data_->SetLastError(kViECodecUnknownError);
689 return -1;
690 }
691 return 0;
692}
693
mflodman@webrtc.org0291c802013-06-26 09:12:49 +0000694int ViECodecImpl::StartDebugRecording(int video_channel,
695 const char* file_name_utf8) {
696 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
697 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
698 if (!vie_encoder) {
699 WEBRTC_TRACE(kTraceError, kTraceVideo,
700 ViEId(shared_data_->instance_id(), video_channel),
701 "%s: No encoder %d", __FUNCTION__, video_channel);
702 return -1;
703 }
704 return vie_encoder->StartDebugRecording(file_name_utf8);
705}
706
707int ViECodecImpl::StopDebugRecording(int video_channel) {
708 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
709 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
710 if (!vie_encoder) {
711 WEBRTC_TRACE(kTraceError, kTraceVideo,
712 ViEId(shared_data_->instance_id(), video_channel),
713 "%s: No encoder %d", __FUNCTION__, video_channel);
714 return -1;
715 }
716 return vie_encoder->StopDebugRecording();
717}
718
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000719bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
720 // Check pl_name matches codec_type.
721 if (video_codec.codecType == kVideoCodecRED) {
722#if defined(WIN32)
723 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
724#else
725 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
726#endif
727 // We only care about the type and name for red.
728 return true;
729 }
730 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
731 "Codec type doesn't match pl_name", video_codec.plType);
732 return false;
733 } else if (video_codec.codecType == kVideoCodecULPFEC) {
734#if defined(WIN32)
735 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
736#else
737 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
738#endif
739 // We only care about the type and name for ULPFEC.
740 return true;
741 }
742 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
743 "Codec type doesn't match pl_name", video_codec.plType);
744 return false;
745 } else if ((video_codec.codecType == kVideoCodecVP8 &&
pbos@webrtc.orge3339fc2013-03-18 16:39:03 +0000746 strncmp(video_codec.plName, "VP8", 4) == 0) ||
747 (video_codec.codecType == kVideoCodecI420 &&
pbos@webrtc.org2ed1cd92013-04-05 13:27:38 +0000748 strncmp(video_codec.plName, "I420", 4) == 0)) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000749 // OK.
pbos@webrtc.org2ed1cd92013-04-05 13:27:38 +0000750 } else if (video_codec.codecType != kVideoCodecGeneric) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000751 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
752 "Codec type doesn't match pl_name", video_codec.plType);
753 return false;
754 }
755
braveyao@webrtc.orge7a9bd42013-01-14 01:52:26 +0000756 if (video_codec.plType == 0 || video_codec.plType > 127) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000757 WEBRTC_TRACE(kTraceError, kTraceVideo, -1,
758 "Invalid codec payload type: %d", video_codec.plType);
759 return false;
760 }
761
762 if (video_codec.width > kViEMaxCodecWidth ||
763 video_codec.height > kViEMaxCodecHeight) {
764 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid codec size: %u x %u",
765 video_codec.width, video_codec.height);
766 return false;
767 }
768
769 if (video_codec.startBitrate < kViEMinCodecBitrate) {
770 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid start_bitrate: %u",
771 video_codec.startBitrate);
772 return false;
773 }
774 if (video_codec.minBitrate < kViEMinCodecBitrate) {
775 WEBRTC_TRACE(kTraceError, kTraceVideo, -1, "Invalid min_bitrate: %u",
776 video_codec.minBitrate);
777 return false;
778 }
779 return true;
780}
781
782} // namespace webrtc