2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/video_engine/vie_codec_impl.h"
15 #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/video_engine/include/vie_errors.h"
19 #include "webrtc/video_engine/vie_capturer.h"
20 #include "webrtc/video_engine/vie_channel.h"
21 #include "webrtc/video_engine/vie_channel_manager.h"
22 #include "webrtc/video_engine/vie_defines.h"
23 #include "webrtc/video_engine/vie_encoder.h"
24 #include "webrtc/video_engine/vie_impl.h"
25 #include "webrtc/video_engine/vie_input_manager.h"
26 #include "webrtc/video_engine/vie_shared_data.h"
30 static void LogCodec(const VideoCodec& codec) {
31 LOG(LS_INFO) << "CodecType " << codec.codecType
32 << ", pl_type " << static_cast<int>(codec.plType)
33 << ", resolution " << codec.width
34 << " x " << codec.height
35 << ", start br " << codec.startBitrate
36 << ", min br " << codec.minBitrate
37 << ", max br " << codec.maxBitrate
38 << ", max fps " << static_cast<int>(codec.maxFramerate)
39 << ", max qp " << codec.qpMax
40 << ", number of streams "
41 << static_cast<int>(codec.numberOfSimulcastStreams);
42 if (codec.codecType == kVideoCodecVP8) {
43 LOG(LS_INFO) << "VP8 specific settings";
44 LOG(LS_INFO) << "pictureLossIndicationOn "
45 << codec.codecSpecific.VP8.pictureLossIndicationOn
46 << ", feedbackModeOn "
47 << codec.codecSpecific.VP8.feedbackModeOn
49 << codec.codecSpecific.VP8.complexity
51 << codec.codecSpecific.VP8.resilience
52 << ", numberOfTemporalLayers "
54 codec.codecSpecific.VP8.numberOfTemporalLayers)
55 << ", keyFrameinterval "
56 << codec.codecSpecific.VP8.keyFrameInterval;
57 for (int idx = 0; idx < codec.numberOfSimulcastStreams; ++idx) {
58 LOG(LS_INFO) << "Stream " << codec.simulcastStream[idx].width
59 << " x " << codec.simulcastStream[idx].height;
60 LOG(LS_INFO) << "Temporal layers "
62 codec.simulcastStream[idx].numberOfTemporalLayers)
64 << codec.simulcastStream[idx].minBitrate
66 << codec.simulcastStream[idx].targetBitrate
68 << codec.simulcastStream[idx].maxBitrate
70 << codec.simulcastStream[idx].qpMax;
76 ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
77 #ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
81 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
82 ViECodecImpl* vie_codec_impl = vie_impl;
83 // Increase ref count.
85 return vie_codec_impl;
91 int ViECodecImpl::Release() {
92 LOG(LS_INFO) << "ViECodec::Release.";
93 // Decrease ref count.
96 int32_t ref_count = GetCount();
98 LOG(LS_WARNING) << "ViECodec released too many times.";
99 shared_data_->SetLastError(kViEAPIDoesNotExist);
105 ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
106 : shared_data_(shared_data) {
109 ViECodecImpl::~ViECodecImpl() {
112 int ViECodecImpl::NumberOfCodecs() const {
113 // +2 because of FEC(RED and ULPFEC)
114 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
117 int ViECodecImpl::GetCodec(const unsigned char list_number,
118 VideoCodec& video_codec) const {
119 if (list_number == VideoCodingModule::NumberOfCodecs()) {
120 memset(&video_codec, 0, sizeof(VideoCodec));
121 strcpy(video_codec.plName, "red");
122 video_codec.codecType = kVideoCodecRED;
123 video_codec.plType = VCM_RED_PAYLOAD_TYPE;
124 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
125 memset(&video_codec, 0, sizeof(VideoCodec));
126 strcpy(video_codec.plName, "ulpfec");
127 video_codec.codecType = kVideoCodecULPFEC;
128 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
129 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
130 shared_data_->SetLastError(kViECodecInvalidArgument);
136 int ViECodecImpl::SetSendCodec(const int video_channel,
137 const VideoCodec& video_codec) {
138 LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
139 LogCodec(video_codec);
140 if (!CodecValid(video_codec)) {
142 shared_data_->SetLastError(kViECodecInvalidCodec);
146 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
147 ViEChannel* vie_channel = cs.Channel(video_channel);
149 shared_data_->SetLastError(kViECodecInvalidChannelId);
153 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
155 if (vie_encoder->Owner() != video_channel) {
156 LOG_F(LS_ERROR) << "Receive only channel.";
157 shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
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)
169 LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
172 if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) {
173 video_codec_internal.startBitrate = video_codec_internal.minBitrate;
175 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
176 video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
180 vie_encoder->GetEncoder(&encoder);
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;
189 ViEInputManagerScoped is(*(shared_data_->input_manager()));
191 // Stop the media flow while reconfiguring.
192 vie_encoder->Pause();
194 if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
195 shared_data_->SetLastError(kViECodecUnknownError);
199 // Give the channel(s) the new information.
200 ChannelList channels;
201 cs.ChannelsUsingViEEncoder(video_channel, &channels);
202 for (ChannelList::iterator it = channels.begin(); it != channels.end();
205 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
209 shared_data_->SetLastError(kViECodecUnknownError);
214 // TODO(mflodman) Break out this part in GetLocalSsrcList().
215 // Update all SSRCs to ViEEncoder.
216 std::list<unsigned int> ssrcs;
217 if (video_codec_internal.numberOfSimulcastStreams == 0) {
218 unsigned int ssrc = 0;
219 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
220 LOG_F(LS_ERROR) << "Could not get ssrc.";
222 ssrcs.push_back(ssrc);
224 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
226 unsigned int ssrc = 0;
227 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
228 LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
230 ssrcs.push_back(ssrc);
233 vie_encoder->SetSsrcs(ssrcs);
234 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
236 // Update the protection mode, we might be switching NACK/FEC.
237 vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled());
239 // Get new best format for frame provider.
240 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
241 if (frame_provider) {
242 frame_provider->FrameCallbackChanged();
244 // Restart the media flow
245 if (new_rtp_stream) {
246 // Stream settings changed, make sure we get a key frame.
247 vie_encoder->SendKeyFrame();
249 vie_encoder->Restart();
253 int ViECodecImpl::GetSendCodec(const int video_channel,
254 VideoCodec& video_codec) const {
255 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
256 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
258 shared_data_->SetLastError(kViECodecInvalidChannelId);
261 return vie_encoder->GetEncoder(&video_codec);
264 int ViECodecImpl::SetReceiveCodec(const int video_channel,
265 const VideoCodec& video_codec) {
266 LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
267 LOG(LS_INFO) << "Codec type " << video_codec.codecType
268 << ", payload type " << video_codec.plType;
270 if (CodecValid(video_codec) == false) {
271 shared_data_->SetLastError(kViECodecInvalidCodec);
275 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
276 ViEChannel* vie_channel = cs.Channel(video_channel);
278 shared_data_->SetLastError(kViECodecInvalidChannelId);
282 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
283 shared_data_->SetLastError(kViECodecUnknownError);
289 int ViECodecImpl::GetReceiveCodec(const int video_channel,
290 VideoCodec& video_codec) const {
291 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
292 ViEChannel* vie_channel = cs.Channel(video_channel);
294 shared_data_->SetLastError(kViECodecInvalidChannelId);
298 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
299 shared_data_->SetLastError(kViECodecUnknownError);
305 int ViECodecImpl::GetCodecConfigParameters(
306 const int video_channel,
307 unsigned char config_parameters[kConfigParameterSize],
308 unsigned char& config_parameters_size) const {
309 LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;
311 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
312 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
314 shared_data_->SetLastError(kViECodecInvalidChannelId);
318 if (vie_encoder->GetCodecConfigParameters(config_parameters,
319 config_parameters_size) != 0) {
320 shared_data_->SetLastError(kViECodecUnknownError);
326 int ViECodecImpl::SetImageScaleStatus(const int video_channel,
328 LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
329 << ", enable: " << enable;
331 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
332 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
334 shared_data_->SetLastError(kViECodecInvalidChannelId);
338 if (vie_encoder->ScaleInputImage(enable) != 0) {
339 shared_data_->SetLastError(kViECodecUnknownError);
345 int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
346 unsigned int& key_frames,
347 unsigned int& delta_frames) const {
348 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
349 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
351 shared_data_->SetLastError(kViECodecInvalidChannelId);
355 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
356 shared_data_->SetLastError(kViECodecUnknownError);
362 int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
363 unsigned int& key_frames,
364 unsigned int& delta_frames) const {
365 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
366 ViEChannel* vie_channel = cs.Channel(video_channel);
368 shared_data_->SetLastError(kViECodecInvalidChannelId);
371 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
372 shared_data_->SetLastError(kViECodecUnknownError);
378 int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
379 int* delay_ms) const {
380 assert(delay_ms != NULL);
382 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
383 ViEChannel* vie_channel = cs.Channel(video_channel);
385 shared_data_->SetLastError(kViECodecInvalidChannelId);
388 *delay_ms = vie_channel->ReceiveDelay();
396 int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
397 unsigned int* bitrate) const {
398 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
399 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
401 shared_data_->SetLastError(kViECodecInvalidChannelId);
404 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
407 unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
408 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
409 ViEChannel* vie_channel = cs.Channel(video_channel);
411 shared_data_->SetLastError(kViECodecInvalidChannelId);
414 return vie_channel->DiscardedPackets();
417 int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
419 LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
420 << ", enacle " << enable;
422 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
423 ViEChannel* vie_channel = cs.Channel(video_channel);
425 shared_data_->SetLastError(kViECodecInvalidChannelId);
428 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
429 shared_data_->SetLastError(kViECodecUnknownError);
435 int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
437 const bool only_key_frames) {
438 LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
439 << "enable, " << enable
440 << ", only key frames " << only_key_frames;
442 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
443 ViEChannel* vie_channel = cs.Channel(video_channel);
445 shared_data_->SetLastError(kViECodecInvalidChannelId);
448 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
449 shared_data_->SetLastError(kViECodecUnknownError);
455 int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
456 ViEEncoderObserver& observer) {
457 LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;
459 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
460 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
462 shared_data_->SetLastError(kViECodecInvalidChannelId);
465 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
466 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
472 int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
473 LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;
475 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
476 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
478 shared_data_->SetLastError(kViECodecInvalidChannelId);
481 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
482 shared_data_->SetLastError(kViECodecObserverNotRegistered);
488 int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
489 ViEDecoderObserver& observer) {
490 LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;
492 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
493 ViEChannel* vie_channel = cs.Channel(video_channel);
495 shared_data_->SetLastError(kViECodecInvalidChannelId);
498 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
499 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
505 int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
506 LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;
508 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
509 ViEChannel* vie_channel = cs.Channel(video_channel);
511 shared_data_->SetLastError(kViECodecInvalidChannelId);
514 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
515 shared_data_->SetLastError(kViECodecObserverNotRegistered);
521 int ViECodecImpl::SendKeyFrame(const int video_channel) {
522 LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;
524 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
525 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
527 shared_data_->SetLastError(kViECodecInvalidChannelId);
530 if (vie_encoder->SendKeyFrame() != 0) {
531 shared_data_->SetLastError(kViECodecUnknownError);
537 int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
539 LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
540 << ", wait " << wait;
542 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
543 ViEChannel* vie_channel = cs.Channel(video_channel);
545 shared_data_->SetLastError(kViECodecInvalidChannelId);
548 if (vie_channel->WaitForKeyFrame(wait) != 0) {
549 shared_data_->SetLastError(kViECodecUnknownError);
555 int ViECodecImpl::StartDebugRecording(int video_channel,
556 const char* file_name_utf8) {
557 LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
558 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
559 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
563 return vie_encoder->StartDebugRecording(file_name_utf8);
566 int ViECodecImpl::StopDebugRecording(int video_channel) {
567 LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
568 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
569 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
573 return vie_encoder->StopDebugRecording();
576 void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
577 LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
578 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
579 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
583 vie_encoder->SuspendBelowMinBitrate();
584 ViEChannel* vie_channel = cs.Channel(video_channel);
588 // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no
589 // padding will be sent when the video is suspended so the video will be
590 // unable to recover.
591 vie_channel->SetTransmissionSmoothingStatus(true);
594 bool ViECodecImpl::GetSendSideDelay(int video_channel, int* avg_delay_ms,
595 int* max_delay_ms) const {
596 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
597 ViEChannel* vie_channel = cs.Channel(video_channel);
599 shared_data_->SetLastError(kViECodecInvalidChannelId);
602 return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
605 bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
606 // Check pl_name matches codec_type.
607 if (video_codec.codecType == kVideoCodecRED) {
609 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
611 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
613 // We only care about the type and name for red.
616 LOG_F(LS_ERROR) << "Invalid RED configuration.";
618 } else if (video_codec.codecType == kVideoCodecULPFEC) {
620 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
622 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
624 // We only care about the type and name for ULPFEC.
627 LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
629 } else if ((video_codec.codecType == kVideoCodecVP8 &&
630 strncmp(video_codec.plName, "VP8", 4) == 0) ||
631 (video_codec.codecType == kVideoCodecI420 &&
632 strncmp(video_codec.plName, "I420", 4) == 0)) {
634 } else if (video_codec.codecType != kVideoCodecGeneric) {
635 LOG(LS_ERROR) << "Codec type and name mismatch.";
639 if (video_codec.plType == 0 || video_codec.plType > 127) {
640 LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType;
644 if (video_codec.width > kViEMaxCodecWidth ||
645 video_codec.height > kViEMaxCodecHeight) {
646 LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
647 << " x " << video_codec.height;
651 if (video_codec.startBitrate < kViEMinCodecBitrate) {
652 LOG(LS_ERROR) << "Invalid start bitrate.";
655 if (video_codec.minBitrate < kViEMinCodecBitrate) {
656 LOG(LS_ERROR) << "Invalid min bitrate.";
662 } // namespace webrtc