blob: d2aaab9ef8e04d9017cc670662a750a17390ed67 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
stefan@webrtc.org439be292012-02-16 14:45:37 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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.orgf5d4cb12013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_codec_impl.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +000013#include <list>
14
pbos@webrtc.orgf5d4cb12013-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"
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000018#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"
niklase@google.com470e71d2011-07-07 08:21:25 +000027
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000028namespace webrtc {
niklase@google.com470e71d2011-07-07 08:21:25 +000029
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000030static void LogCodec(const VideoCodec& codec) {
31 LOG(LS_INFO) << "CodecType " << codec.codecType
32 << ", pl_type " << 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 fpr " << codec.maxFramerate
39 << ", max qp " << codec.qpMax
40 << ", number of streams "
41 << codec.numberOfSimulcastStreams;
42 if (codec.codecType == kVideoCodecVP8) {
43 LOG(LS_INFO) << "VP8 specific settings";
44 LOG(LS_INFO) << "pivtureLossIndicationOn "
45 << codec.codecSpecific.VP8.pictureLossIndicationOn
46 << ", feedbackModeOn "
47 << codec.codecSpecific.VP8.feedbackModeOn
48 << ", complexity "
49 << codec.codecSpecific.VP8.complexity
50 << ", resilience "
51 << codec.codecSpecific.VP8.resilience
52 << ", numberOfTeporalLayers "
53 << codec.codecSpecific.VP8.numberOfTemporalLayers
54 << ", keyFrameinterval "
55 << codec.codecSpecific.VP8.keyFrameInterval;
56 for (int idx = 0; idx < codec.numberOfSimulcastStreams; ++idx) {
57 LOG(LS_INFO) << "Stream " << codec.simulcastStream[idx].width
58 << " x " << codec.simulcastStream[idx].height;
59 LOG(LS_INFO) << "Temporal layers "
60 << codec.simulcastStream[idx].numberOfTemporalLayers
61 << ", min br "
62 << codec.simulcastStream[idx].minBitrate
63 << ", target br "
64 << codec.simulcastStream[idx].targetBitrate
65 << ", max br "
66 << codec.simulcastStream[idx].maxBitrate
67 << ", qp max "
68 << codec.simulcastStream[idx].qpMax;
69
70 }
71 }
72}
73
74
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000075ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000076#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000077 if (!video_engine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000078 return NULL;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000079 }
andrew@webrtc.orgd72262d2013-05-09 02:12:07 +000080 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000081 ViECodecImpl* vie_codec_impl = vie_impl;
82 // Increase ref count.
83 (*vie_codec_impl)++;
84 return vie_codec_impl;
85#else
86 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000087#endif
88}
89
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000090int ViECodecImpl::Release() {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000091 LOG(LS_INFO) << "ViECodec::Release.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000092 // Decrease ref count.
93 (*this)--;
niklase@google.com470e71d2011-07-07 08:21:25 +000094
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000095 int32_t ref_count = GetCount();
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000096 if (ref_count < 0) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000097 LOG(LS_WARNING) << "ViECodec released too many times.";
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +000098 shared_data_->SetLastError(kViEAPIDoesNotExist);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000099 return -1;
100 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000101 return ref_count;
niklase@google.com470e71d2011-07-07 08:21:25 +0000102}
103
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000104ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
105 : shared_data_(shared_data) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000106}
107
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000108ViECodecImpl::~ViECodecImpl() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000109}
110
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000111int ViECodecImpl::NumberOfCodecs() const {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000112 // +2 because of FEC(RED and ULPFEC)
113 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
niklase@google.com470e71d2011-07-07 08:21:25 +0000114}
115
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000116int ViECodecImpl::GetCodec(const unsigned char list_number,
117 VideoCodec& video_codec) const {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000118 if (list_number == VideoCodingModule::NumberOfCodecs()) {
119 memset(&video_codec, 0, sizeof(VideoCodec));
mflodman@webrtc.orgaeff4f32013-04-22 12:41:57 +0000120 strcpy(video_codec.plName, "red");
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000121 video_codec.codecType = kVideoCodecRED;
122 video_codec.plType = VCM_RED_PAYLOAD_TYPE;
123 } else if (list_number == VideoCodingModule::NumberOfCodecs() + 1) {
124 memset(&video_codec, 0, sizeof(VideoCodec));
mflodman@webrtc.orgaeff4f32013-04-22 12:41:57 +0000125 strcpy(video_codec.plName, "ulpfec");
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000126 video_codec.codecType = kVideoCodecULPFEC;
127 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
128 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000129 shared_data_->SetLastError(kViECodecInvalidArgument);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000130 return -1;
131 }
132 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000133}
134
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000135int ViECodecImpl::SetSendCodec(const int video_channel,
136 const VideoCodec& video_codec) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000137 LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
138 LogCodec(video_codec);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000139 if (!CodecValid(video_codec)) {
140 // Error logged.
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000141 shared_data_->SetLastError(kViECodecInvalidCodec);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000142 return -1;
143 }
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000144
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000145 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000146 ViEChannel* vie_channel = cs.Channel(video_channel);
147 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000148 shared_data_->SetLastError(kViECodecInvalidChannelId);
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000149 return -1;
150 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000151
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000152 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
153 assert(vie_encoder);
154 if (vie_encoder->Owner() != video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000155 LOG_F(LS_ERROR) << "Receive only channel.";
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000156 shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
157 return -1;
158 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000159 // Set a max_bitrate if the user hasn't set one.
160 VideoCodec video_codec_internal;
161 memcpy(&video_codec_internal, &video_codec, sizeof(VideoCodec));
162 if (video_codec_internal.maxBitrate == 0) {
163 // Max is one bit per pixel.
164 video_codec_internal.maxBitrate = (video_codec_internal.width *
165 video_codec_internal.height *
166 video_codec_internal.maxFramerate)
167 / 1000;
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000168 LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000169 }
170
mflodman@webrtc.org60310012013-12-20 15:07:12 +0000171 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
172 video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
173 }
174
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000175 VideoCodec encoder;
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000176 vie_encoder->GetEncoder(&encoder);
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000177
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000178 // Make sure to generate a new SSRC if the codec type and/or resolution has
179 // changed. This won't have any effect if the user has set an SSRC.
180 bool new_rtp_stream = false;
stefan@webrtc.org4e8eaba2012-08-20 14:29:52 +0000181 if (encoder.codecType != video_codec_internal.codecType) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000182 new_rtp_stream = true;
183 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000184
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000185 ViEInputManagerScoped is(*(shared_data_->input_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000186
187 // Stop the media flow while reconfiguring.
188 vie_encoder->Pause();
189
mflodman@webrtc.org3ba883f2013-06-07 13:57:57 +0000190 if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000191 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000192 return -1;
193 }
194
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000195 // Give the channel(s) the new information.
196 ChannelList channels;
197 cs.ChannelsUsingViEEncoder(video_channel, &channels);
198 for (ChannelList::iterator it = channels.begin(); it != channels.end();
199 ++it) {
200 bool ret = true;
201 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000202 ret = false;
203 }
204 if (!ret) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000205 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000206 return -1;
207 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000208 }
209
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000210 // TODO(mflodman) Break out this part in GetLocalSsrcList().
211 // Update all SSRCs to ViEEncoder.
212 std::list<unsigned int> ssrcs;
213 if (video_codec_internal.numberOfSimulcastStreams == 0) {
214 unsigned int ssrc = 0;
215 if (vie_channel->GetLocalSSRC(0, &ssrc) != 0) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000216 LOG_F(LS_ERROR) << "Could not get ssrc.";
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000217 }
218 ssrcs.push_back(ssrc);
219 } else {
220 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
221 ++idx) {
222 unsigned int ssrc = 0;
223 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000224 LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000225 }
226 ssrcs.push_back(ssrc);
227 }
228 }
229 vie_encoder->SetSsrcs(ssrcs);
230 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
231
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000232 // Update the protection mode, we might be switching NACK/FEC.
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000233 vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled());
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000234
235 // Get new best format for frame provider.
pbos@webrtc.org735a7c82013-08-05 09:03:03 +0000236 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000237 if (frame_provider) {
238 frame_provider->FrameCallbackChanged();
239 }
240 // Restart the media flow
241 if (new_rtp_stream) {
242 // Stream settings changed, make sure we get a key frame.
243 vie_encoder->SendKeyFrame();
244 }
245 vie_encoder->Restart();
246 return 0;
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000247}
248
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000249int ViECodecImpl::GetSendCodec(const int video_channel,
250 VideoCodec& video_codec) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000251 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000252 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
253 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000254 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000255 return -1;
256 }
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000257 return vie_encoder->GetEncoder(&video_codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000258}
259
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000260int ViECodecImpl::SetReceiveCodec(const int video_channel,
261 const VideoCodec& video_codec) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000262 LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
263 LOG(LS_INFO) << "Codec type " << video_codec.codecType
264 << ", payload type " << video_codec.plType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000265
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000266 if (CodecValid(video_codec) == false) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000267 shared_data_->SetLastError(kViECodecInvalidCodec);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000268 return -1;
269 }
270
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000271 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000272 ViEChannel* vie_channel = cs.Channel(video_channel);
273 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000274 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000275 return -1;
276 }
277
278 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000279 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000280 return -1;
281 }
282 return 0;
283}
284
285int ViECodecImpl::GetReceiveCodec(const int video_channel,
286 VideoCodec& video_codec) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000287 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000288 ViEChannel* vie_channel = cs.Channel(video_channel);
289 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000290 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000291 return -1;
292 }
293
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000294 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000295 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000296 return -1;
297 }
298 return 0;
299}
300
301int ViECodecImpl::GetCodecConfigParameters(
302 const int video_channel,
303 unsigned char config_parameters[kConfigParameterSize],
304 unsigned char& config_parameters_size) const {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000305 LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000306
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000307 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000308 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
309 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000310 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000311 return -1;
312 }
313
314 if (vie_encoder->GetCodecConfigParameters(config_parameters,
315 config_parameters_size) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000316 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000317 return -1;
318 }
319 return 0;
320}
321
322int ViECodecImpl::SetImageScaleStatus(const int video_channel,
323 const bool enable) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000324 LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
325 << ", enable: " << enable;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000326
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000327 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000328 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
329 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000330 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000331 return -1;
332 }
333
334 if (vie_encoder->ScaleInputImage(enable) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000335 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000336 return -1;
337 }
338 return 0;
339}
340
341int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
342 unsigned int& key_frames,
343 unsigned int& delta_frames) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000344 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000345 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
346 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000347 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000348 return -1;
349 }
350
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000351 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000352 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000353 return -1;
354 }
355 return 0;
356}
357
358int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
359 unsigned int& key_frames,
360 unsigned int& delta_frames) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000361 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000362 ViEChannel* vie_channel = cs.Channel(video_channel);
363 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000364 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000365 return -1;
366 }
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000367 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000368 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000369 return -1;
370 }
371 return 0;
372}
373
mflodman@webrtc.org4aee6b62012-12-14 14:02:10 +0000374int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
375 int* delay_ms) const {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000376 assert(delay_ms != NULL);
mflodman@webrtc.org4aee6b62012-12-14 14:02:10 +0000377
378 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
379 ViEChannel* vie_channel = cs.Channel(video_channel);
380 if (!vie_channel) {
mflodman@webrtc.org4aee6b62012-12-14 14:02:10 +0000381 shared_data_->SetLastError(kViECodecInvalidChannelId);
382 return -1;
383 }
384 *delay_ms = vie_channel->ReceiveDelay();
385 if (*delay_ms < 0) {
386 return -1;
387 }
388 return 0;
389}
390
391
stefan@webrtc.org439be292012-02-16 14:45:37 +0000392int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
393 unsigned int* bitrate) const {
stefan@webrtc.org439be292012-02-16 14:45:37 +0000394 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
395 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
396 if (!vie_encoder) {
stefan@webrtc.org439be292012-02-16 14:45:37 +0000397 shared_data_->SetLastError(kViECodecInvalidChannelId);
398 return -1;
399 }
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000400 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
stefan@webrtc.org439be292012-02-16 14:45:37 +0000401}
402
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000403unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000404 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000405 ViEChannel* vie_channel = cs.Channel(video_channel);
406 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000407 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000408 return -1;
409 }
410 return vie_channel->DiscardedPackets();
411}
412
413int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
414 const bool enable) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000415 LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
416 << ", enacle " << enable;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000417
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000418 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000419 ViEChannel* vie_channel = cs.Channel(video_channel);
420 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000421 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000422 return -1;
423 }
424 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000425 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000426 return -1;
427 }
428 return 0;
429}
430
431int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
niklase@google.com470e71d2011-07-07 08:21:25 +0000432 const bool enable,
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000433 const bool only_key_frames) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000434 LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
435 << "enable, " << enable
436 << ", only key frames " << only_key_frames;
niklase@google.com470e71d2011-07-07 08:21:25 +0000437
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000438 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000439 ViEChannel* vie_channel = cs.Channel(video_channel);
440 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000441 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000442 return -1;
443 }
444 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000445 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000446 return -1;
447 }
448 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000449}
450
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000451int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
452 ViEEncoderObserver& observer) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000453 LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000454
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000455 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000456 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
457 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000458 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000459 return -1;
460 }
461 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000462 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000463 return -1;
464 }
465 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000466}
467
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000468int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000469 LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000470
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000471 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000472 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
473 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000474 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000475 return -1;
476 }
477 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000478 shared_data_->SetLastError(kViECodecObserverNotRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000479 return -1;
480 }
481 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000482}
483
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000484int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
485 ViEDecoderObserver& observer) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000486 LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000487
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000488 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000489 ViEChannel* vie_channel = cs.Channel(video_channel);
490 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000491 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000492 return -1;
493 }
494 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000495 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000496 return -1;
497 }
498 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000499}
500
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000501int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000502 LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000503
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000504 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000505 ViEChannel* vie_channel = cs.Channel(video_channel);
506 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000507 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000508 return -1;
509 }
510 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000511 shared_data_->SetLastError(kViECodecObserverNotRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000512 return -1;
513 }
514 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000515}
516
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000517int ViECodecImpl::SendKeyFrame(const int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000518 LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000519
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000520 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000521 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
522 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000523 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000524 return -1;
525 }
526 if (vie_encoder->SendKeyFrame() != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000527 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000528 return -1;
529 }
530 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000531}
532
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000533int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
534 const bool wait) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000535 LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
536 << ", wait " << wait;
niklase@google.com470e71d2011-07-07 08:21:25 +0000537
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000538 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000539 ViEChannel* vie_channel = cs.Channel(video_channel);
540 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000541 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000542 return -1;
543 }
544 if (vie_channel->WaitForKeyFrame(wait) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000545 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000546 return -1;
547 }
548 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000549}
550
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000551int ViECodecImpl::StartDebugRecording(int video_channel,
552 const char* file_name_utf8) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000553 LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000554 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
555 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
556 if (!vie_encoder) {
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000557 return -1;
558 }
559 return vie_encoder->StartDebugRecording(file_name_utf8);
560}
561
562int ViECodecImpl::StopDebugRecording(int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000563 LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000564 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
565 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
566 if (!vie_encoder) {
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000567 return -1;
568 }
569 return vie_encoder->StopDebugRecording();
570}
571
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000572void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000573 LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
henrik.lundin@webrtc.org7ea4f242013-10-02 13:34:26 +0000574 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
575 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
576 if (!vie_encoder) {
henrik.lundin@webrtc.org7ea4f242013-10-02 13:34:26 +0000577 return;
578 }
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000579 vie_encoder->SuspendBelowMinBitrate();
580 ViEChannel* vie_channel = cs.Channel(video_channel);
581 if (!vie_channel) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000582 return;
583 }
584 // Must enable pacing when enabling SuspendBelowMinBitrate. Otherwise, no
585 // padding will be sent when the video is suspended so the video will be
586 // unable to recover.
587 vie_channel->SetTransmissionSmoothingStatus(true);
henrik.lundin@webrtc.org7ea4f242013-10-02 13:34:26 +0000588}
589
stefan@webrtc.org0a3c1472013-12-05 14:05:07 +0000590bool ViECodecImpl::GetSendSideDelay(int video_channel, int* avg_delay_ms,
591 int* max_delay_ms) const {
592 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
593 ViEChannel* vie_channel = cs.Channel(video_channel);
594 if (!vie_channel) {
stefan@webrtc.org0a3c1472013-12-05 14:05:07 +0000595 shared_data_->SetLastError(kViECodecInvalidChannelId);
596 return false;
597 }
598 return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
599}
600
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000601bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
602 // Check pl_name matches codec_type.
603 if (video_codec.codecType == kVideoCodecRED) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000604#if defined(WIN32)
mflodman@webrtc.org1fe2ada2011-12-21 12:23:15 +0000605 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000606#else
607 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000608#endif
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000609 // We only care about the type and name for red.
610 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000611 }
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000612 LOG_F(LS_ERROR) << "Invalid RED configuration.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000613 return false;
614 } else if (video_codec.codecType == kVideoCodecULPFEC) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000615#if defined(WIN32)
mflodman@webrtc.org1fe2ada2011-12-21 12:23:15 +0000616 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000617#else
618 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000619#endif
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000620 // We only care about the type and name for ULPFEC.
621 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000622 }
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000623 LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000624 return false;
pwestin@webrtc.org56210572012-01-17 12:45:47 +0000625 } else if ((video_codec.codecType == kVideoCodecVP8 &&
pbos@webrtc.org8911ce42013-03-18 16:39:03 +0000626 strncmp(video_codec.plName, "VP8", 4) == 0) ||
627 (video_codec.codecType == kVideoCodecI420 &&
pbos@webrtc.orgb5bf54c2013-04-05 13:27:38 +0000628 strncmp(video_codec.plName, "I420", 4) == 0)) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000629 // OK.
pbos@webrtc.orgb5bf54c2013-04-05 13:27:38 +0000630 } else if (video_codec.codecType != kVideoCodecGeneric) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000631 LOG(LS_ERROR) << "Codec type and name mismatch.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000632 return false;
633 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000634
braveyao@webrtc.org49273ff2013-01-14 01:52:26 +0000635 if (video_codec.plType == 0 || video_codec.plType > 127) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000636 LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000637 return false;
638 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000640 if (video_codec.width > kViEMaxCodecWidth ||
641 video_codec.height > kViEMaxCodecHeight) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000642 LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
643 << " x " << video_codec.height;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000644 return false;
645 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000647 if (video_codec.startBitrate < kViEMinCodecBitrate) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000648 LOG(LS_ERROR) << "Invalid start bitrate.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000649 return false;
650 }
651 if (video_codec.minBitrate < kViEMinCodecBitrate) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000652 LOG(LS_ERROR) << "Invalid min bitrate.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000653 return false;
654 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000655 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000656}
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000657
658} // namespace webrtc