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