blob: 3ba56de54d836c45ccf789aba18444f3ab0100df [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
asapersson@webrtc.org46106f22014-04-25 07:02:52 +000032 << ", pl_type " << static_cast<int>(codec.plType)
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000033 << ", resolution " << codec.width
34 << " x " << codec.height
35 << ", start br " << codec.startBitrate
36 << ", min br " << codec.minBitrate
37 << ", max br " << codec.maxBitrate
asapersson@webrtc.org46106f22014-04-25 07:02:52 +000038 << ", max fps " << static_cast<int>(codec.maxFramerate)
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000039 << ", max qp " << codec.qpMax
40 << ", number of streams "
asapersson@webrtc.org46106f22014-04-25 07:02:52 +000041 << static_cast<int>(codec.numberOfSimulcastStreams);
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000042 if (codec.codecType == kVideoCodecVP8) {
43 LOG(LS_INFO) << "VP8 specific settings";
asapersson@webrtc.org46106f22014-04-25 07:02:52 +000044 LOG(LS_INFO) << "pictureLossIndicationOn "
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000045 << 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
asapersson@webrtc.org46106f22014-04-25 07:02:52 +000052 << ", numberOfTemporalLayers "
53 << static_cast<int>(
54 codec.codecSpecific.VP8.numberOfTemporalLayers)
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000055 << ", 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 "
asapersson@webrtc.org46106f22014-04-25 07:02:52 +000061 << static_cast<int>(
62 codec.simulcastStream[idx].numberOfTemporalLayers)
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000063 << ", min br "
64 << codec.simulcastStream[idx].minBitrate
65 << ", target br "
66 << codec.simulcastStream[idx].targetBitrate
67 << ", max br "
68 << codec.simulcastStream[idx].maxBitrate
69 << ", qp max "
70 << codec.simulcastStream[idx].qpMax;
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000071 }
72 }
73}
74
75
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000076ViECodec* ViECodec::GetInterface(VideoEngine* video_engine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000077#ifdef WEBRTC_VIDEO_ENGINE_CODEC_API
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000078 if (!video_engine) {
niklase@google.com470e71d2011-07-07 08:21:25 +000079 return NULL;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000080 }
andrew@webrtc.orgd72262d2013-05-09 02:12:07 +000081 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000082 ViECodecImpl* vie_codec_impl = vie_impl;
83 // Increase ref count.
84 (*vie_codec_impl)++;
85 return vie_codec_impl;
86#else
87 return NULL;
niklase@google.com470e71d2011-07-07 08:21:25 +000088#endif
89}
90
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000091int ViECodecImpl::Release() {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000092 LOG(LS_INFO) << "ViECodec::Release.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000093 // Decrease ref count.
94 (*this)--;
niklase@google.com470e71d2011-07-07 08:21:25 +000095
pbos@webrtc.orgb238d122013-04-09 13:41:51 +000096 int32_t ref_count = GetCount();
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +000097 if (ref_count < 0) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +000098 LOG(LS_WARNING) << "ViECodec released too many times.";
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +000099 shared_data_->SetLastError(kViEAPIDoesNotExist);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000100 return -1;
101 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000102 return ref_count;
niklase@google.com470e71d2011-07-07 08:21:25 +0000103}
104
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000105ViECodecImpl::ViECodecImpl(ViESharedData* shared_data)
106 : shared_data_(shared_data) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000107}
108
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000109ViECodecImpl::~ViECodecImpl() {
niklase@google.com470e71d2011-07-07 08:21:25 +0000110}
111
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000112int ViECodecImpl::NumberOfCodecs() const {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000113 // +2 because of FEC(RED and ULPFEC)
114 return static_cast<int>((VideoCodingModule::NumberOfCodecs() + 2));
niklase@google.com470e71d2011-07-07 08:21:25 +0000115}
116
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000117int ViECodecImpl::GetCodec(const unsigned char list_number,
118 VideoCodec& video_codec) const {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000119 if (list_number == VideoCodingModule::NumberOfCodecs()) {
120 memset(&video_codec, 0, sizeof(VideoCodec));
mflodman@webrtc.orgaeff4f32013-04-22 12:41:57 +0000121 strcpy(video_codec.plName, "red");
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000122 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));
mflodman@webrtc.orgaeff4f32013-04-22 12:41:57 +0000126 strcpy(video_codec.plName, "ulpfec");
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000127 video_codec.codecType = kVideoCodecULPFEC;
128 video_codec.plType = VCM_ULPFEC_PAYLOAD_TYPE;
129 } else if (VideoCodingModule::Codec(list_number, &video_codec) != VCM_OK) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000130 shared_data_->SetLastError(kViECodecInvalidArgument);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000131 return -1;
132 }
133 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000134}
135
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000136int ViECodecImpl::SetSendCodec(const int video_channel,
137 const VideoCodec& video_codec) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000138 LOG(LS_INFO) << "SetSendCodec for channel " << video_channel;
139 LogCodec(video_codec);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000140 if (!CodecValid(video_codec)) {
141 // Error logged.
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000142 shared_data_->SetLastError(kViECodecInvalidCodec);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000143 return -1;
144 }
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000145
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000146 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000147 ViEChannel* vie_channel = cs.Channel(video_channel);
148 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000149 shared_data_->SetLastError(kViECodecInvalidChannelId);
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000150 return -1;
151 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000152
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000153 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
154 assert(vie_encoder);
155 if (vie_encoder->Owner() != video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000156 LOG_F(LS_ERROR) << "Receive only channel.";
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000157 shared_data_->SetLastError(kViECodecReceiveOnlyChannel);
158 return -1;
159 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +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;
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000169 LOG(LS_INFO) << "New max bitrate set " << video_codec_internal.maxBitrate;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000170 }
171
mflodman@webrtc.orgf2237462014-04-29 12:38:42 +0000172 if (video_codec_internal.startBitrate < video_codec_internal.minBitrate) {
173 video_codec_internal.startBitrate = video_codec_internal.minBitrate;
174 }
mflodman@webrtc.org60310012013-12-20 15:07:12 +0000175 if (video_codec_internal.startBitrate > video_codec_internal.maxBitrate) {
176 video_codec_internal.startBitrate = video_codec_internal.maxBitrate;
177 }
178
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000179 VideoCodec encoder;
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000180 vie_encoder->GetEncoder(&encoder);
mflodman@webrtc.org9ec883e2012-03-05 17:12:41 +0000181
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000182 // 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;
stefan@webrtc.org4e8eaba2012-08-20 14:29:52 +0000185 if (encoder.codecType != video_codec_internal.codecType) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000186 new_rtp_stream = true;
187 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000188
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000189 ViEInputManagerScoped is(*(shared_data_->input_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000190
191 // Stop the media flow while reconfiguring.
192 vie_encoder->Pause();
193
mflodman@webrtc.org3ba883f2013-06-07 13:57:57 +0000194 if (vie_encoder->SetEncoder(video_codec_internal) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000195 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000196 return -1;
197 }
198
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000199 // 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();
203 ++it) {
204 bool ret = true;
205 if ((*it)->SetSendCodec(video_codec_internal, new_rtp_stream) != 0) {
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000206 ret = false;
207 }
208 if (!ret) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000209 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.org9c0aedc2012-01-03 13:46:49 +0000210 return -1;
211 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000212 }
213
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000214 // 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) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000220 LOG_F(LS_ERROR) << "Could not get ssrc.";
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000221 }
222 ssrcs.push_back(ssrc);
223 } else {
224 for (int idx = 0; idx < video_codec_internal.numberOfSimulcastStreams;
225 ++idx) {
226 unsigned int ssrc = 0;
227 if (vie_channel->GetLocalSSRC(idx, &ssrc) != 0) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000228 LOG_F(LS_ERROR) << "Could not get ssrc for stream " << idx;
mflodman@webrtc.orgd6ec3862012-10-25 11:30:29 +0000229 }
230 ssrcs.push_back(ssrc);
231 }
232 }
233 vie_encoder->SetSsrcs(ssrcs);
234 shared_data_->channel_manager()->UpdateSsrcs(video_channel, ssrcs);
235
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000236 // Update the protection mode, we might be switching NACK/FEC.
wu@webrtc.org822fbd82013-08-15 23:38:54 +0000237 vie_encoder->UpdateProtectionMethod(vie_encoder->nack_enabled());
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000238
239 // Get new best format for frame provider.
pbos@webrtc.org735a7c82013-08-05 09:03:03 +0000240 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000241 if (frame_provider) {
242 frame_provider->FrameCallbackChanged();
243 }
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();
248 }
249 vie_encoder->Restart();
250 return 0;
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000251}
252
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000253int ViECodecImpl::GetSendCodec(const int video_channel,
254 VideoCodec& video_codec) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000255 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000256 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
257 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000258 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000259 return -1;
260 }
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000261 return vie_encoder->GetEncoder(&video_codec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000262}
263
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000264int ViECodecImpl::SetReceiveCodec(const int video_channel,
265 const VideoCodec& video_codec) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000266 LOG(LS_INFO) << "SetReceiveCodec for channel " << video_channel;
267 LOG(LS_INFO) << "Codec type " << video_codec.codecType
268 << ", payload type " << video_codec.plType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000269
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000270 if (CodecValid(video_codec) == false) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000271 shared_data_->SetLastError(kViECodecInvalidCodec);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000272 return -1;
273 }
274
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000275 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000276 ViEChannel* vie_channel = cs.Channel(video_channel);
277 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000278 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000279 return -1;
280 }
281
282 if (vie_channel->SetReceiveCodec(video_codec) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000283 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000284 return -1;
285 }
286 return 0;
287}
288
289int ViECodecImpl::GetReceiveCodec(const int video_channel,
290 VideoCodec& video_codec) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000291 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000292 ViEChannel* vie_channel = cs.Channel(video_channel);
293 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000294 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000295 return -1;
296 }
297
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000298 if (vie_channel->GetReceiveCodec(&video_codec) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000299 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000300 return -1;
301 }
302 return 0;
303}
304
305int ViECodecImpl::GetCodecConfigParameters(
306 const int video_channel,
307 unsigned char config_parameters[kConfigParameterSize],
308 unsigned char& config_parameters_size) const {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000309 LOG(LS_INFO) << "GetCodecConfigParameters " << video_channel;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000310
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000311 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000312 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
313 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000314 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000315 return -1;
316 }
317
318 if (vie_encoder->GetCodecConfigParameters(config_parameters,
319 config_parameters_size) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000320 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000321 return -1;
322 }
323 return 0;
324}
325
326int ViECodecImpl::SetImageScaleStatus(const int video_channel,
327 const bool enable) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000328 LOG(LS_INFO) << "SetImageScaleStates for channel " << video_channel
329 << ", enable: " << enable;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000330
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000331 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000332 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
333 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000334 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000335 return -1;
336 }
337
338 if (vie_encoder->ScaleInputImage(enable) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000339 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000340 return -1;
341 }
342 return 0;
343}
344
345int ViECodecImpl::GetSendCodecStastistics(const int video_channel,
346 unsigned int& key_frames,
347 unsigned int& delta_frames) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000348 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000349 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
350 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000351 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000352 return -1;
353 }
354
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000355 if (vie_encoder->SendCodecStatistics(&key_frames, &delta_frames) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000356 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000357 return -1;
358 }
359 return 0;
360}
361
362int ViECodecImpl::GetReceiveCodecStastistics(const int video_channel,
363 unsigned int& key_frames,
364 unsigned int& delta_frames) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000365 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000366 ViEChannel* vie_channel = cs.Channel(video_channel);
367 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000368 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000369 return -1;
370 }
mflodman@webrtc.orgf5e99db2012-06-27 09:49:37 +0000371 if (vie_channel->ReceiveCodecStatistics(&key_frames, &delta_frames) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000372 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000373 return -1;
374 }
375 return 0;
376}
377
mflodman@webrtc.org4aee6b62012-12-14 14:02:10 +0000378int ViECodecImpl::GetReceiveSideDelay(const int video_channel,
379 int* delay_ms) const {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000380 assert(delay_ms != NULL);
mflodman@webrtc.org4aee6b62012-12-14 14:02:10 +0000381
382 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
383 ViEChannel* vie_channel = cs.Channel(video_channel);
384 if (!vie_channel) {
mflodman@webrtc.org4aee6b62012-12-14 14:02:10 +0000385 shared_data_->SetLastError(kViECodecInvalidChannelId);
386 return -1;
387 }
388 *delay_ms = vie_channel->ReceiveDelay();
389 if (*delay_ms < 0) {
390 return -1;
391 }
392 return 0;
393}
394
395
stefan@webrtc.org439be292012-02-16 14:45:37 +0000396int ViECodecImpl::GetCodecTargetBitrate(const int video_channel,
397 unsigned int* bitrate) const {
stefan@webrtc.org439be292012-02-16 14:45:37 +0000398 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
399 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
400 if (!vie_encoder) {
stefan@webrtc.org439be292012-02-16 14:45:37 +0000401 shared_data_->SetLastError(kViECodecInvalidChannelId);
402 return -1;
403 }
pbos@webrtc.orgb238d122013-04-09 13:41:51 +0000404 return vie_encoder->CodecTargetBitrate(static_cast<uint32_t*>(bitrate));
stefan@webrtc.org439be292012-02-16 14:45:37 +0000405}
406
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000407unsigned int ViECodecImpl::GetDiscardedPackets(const int video_channel) const {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000408 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000409 ViEChannel* vie_channel = cs.Channel(video_channel);
410 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000411 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000412 return -1;
413 }
414 return vie_channel->DiscardedPackets();
415}
416
417int ViECodecImpl::SetKeyFrameRequestCallbackStatus(const int video_channel,
418 const bool enable) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000419 LOG(LS_INFO) << "SetKeyFrameRequestCallbackStatus for " << video_channel
420 << ", enacle " << enable;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000421
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000422 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000423 ViEChannel* vie_channel = cs.Channel(video_channel);
424 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000425 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000426 return -1;
427 }
428 if (vie_channel->EnableKeyFrameRequestCallback(enable) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000429 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000430 return -1;
431 }
432 return 0;
433}
434
435int ViECodecImpl::SetSignalKeyPacketLossStatus(const int video_channel,
niklase@google.com470e71d2011-07-07 08:21:25 +0000436 const bool enable,
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000437 const bool only_key_frames) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000438 LOG(LS_INFO) << "SetSignalKeyPacketLossStatus for " << video_channel
439 << "enable, " << enable
440 << ", only key frames " << only_key_frames;
niklase@google.com470e71d2011-07-07 08:21:25 +0000441
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000442 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000443 ViEChannel* vie_channel = cs.Channel(video_channel);
444 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000445 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000446 return -1;
447 }
448 if (vie_channel->SetSignalPacketLossStatus(enable, only_key_frames) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000449 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000450 return -1;
451 }
452 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000453}
454
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000455int ViECodecImpl::RegisterEncoderObserver(const int video_channel,
456 ViEEncoderObserver& observer) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000457 LOG(LS_INFO) << "RegisterEncoderObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000458
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000459 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000460 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
461 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000462 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000463 return -1;
464 }
465 if (vie_encoder->RegisterCodecObserver(&observer) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000466 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000467 return -1;
468 }
469 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000470}
471
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000472int ViECodecImpl::DeregisterEncoderObserver(const int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000473 LOG(LS_INFO) << "DeregisterEncoderObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000474
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000475 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000476 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
477 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000478 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000479 return -1;
480 }
481 if (vie_encoder->RegisterCodecObserver(NULL) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000482 shared_data_->SetLastError(kViECodecObserverNotRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000483 return -1;
484 }
485 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000486}
487
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000488int ViECodecImpl::RegisterDecoderObserver(const int video_channel,
489 ViEDecoderObserver& observer) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000490 LOG(LS_INFO) << "RegisterDecoderObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000491
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000492 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000493 ViEChannel* vie_channel = cs.Channel(video_channel);
494 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000495 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000496 return -1;
497 }
498 if (vie_channel->RegisterCodecObserver(&observer) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000499 shared_data_->SetLastError(kViECodecObserverAlreadyRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000500 return -1;
501 }
502 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000503}
504
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000505int ViECodecImpl::DeregisterDecoderObserver(const int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000506 LOG(LS_INFO) << "DeregisterDecodeObserver for channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000507
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000508 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000509 ViEChannel* vie_channel = cs.Channel(video_channel);
510 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000511 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000512 return -1;
513 }
514 if (vie_channel->RegisterCodecObserver(NULL) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000515 shared_data_->SetLastError(kViECodecObserverNotRegistered);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000516 return -1;
517 }
518 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000519}
520
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000521int ViECodecImpl::SendKeyFrame(const int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000522 LOG(LS_INFO) << "SendKeyFrame on channel " << video_channel;
niklase@google.com470e71d2011-07-07 08:21:25 +0000523
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000524 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000525 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
526 if (!vie_encoder) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000527 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000528 return -1;
529 }
530 if (vie_encoder->SendKeyFrame() != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000531 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000532 return -1;
533 }
534 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000535}
536
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000537int ViECodecImpl::WaitForFirstKeyFrame(const int video_channel,
538 const bool wait) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000539 LOG(LS_INFO) << "WaitForFirstKeyFrame for channel " << video_channel
540 << ", wait " << wait;
niklase@google.com470e71d2011-07-07 08:21:25 +0000541
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000542 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000543 ViEChannel* vie_channel = cs.Channel(video_channel);
544 if (!vie_channel) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000545 shared_data_->SetLastError(kViECodecInvalidChannelId);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000546 return -1;
547 }
548 if (vie_channel->WaitForKeyFrame(wait) != 0) {
mflodman@webrtc.orgb11424b2012-01-25 13:42:03 +0000549 shared_data_->SetLastError(kViECodecUnknownError);
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000550 return -1;
551 }
552 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000553}
554
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000555int ViECodecImpl::StartDebugRecording(int video_channel,
556 const char* file_name_utf8) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000557 LOG(LS_INFO) << "StartDebugRecording for channel " << video_channel;
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000558 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
559 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
560 if (!vie_encoder) {
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000561 return -1;
562 }
563 return vie_encoder->StartDebugRecording(file_name_utf8);
564}
565
566int ViECodecImpl::StopDebugRecording(int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000567 LOG(LS_INFO) << "StopDebugRecording for channel " << video_channel;
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000568 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
569 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
570 if (!vie_encoder) {
mflodman@webrtc.org1c986e72013-06-26 09:12:49 +0000571 return -1;
572 }
573 return vie_encoder->StopDebugRecording();
574}
575
henrik.lundin@webrtc.orgce8e0932013-11-18 12:18:43 +0000576void ViECodecImpl::SuspendBelowMinBitrate(int video_channel) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000577 LOG(LS_INFO) << "SuspendBelowMinBitrate for channel " << video_channel;
henrik.lundin@webrtc.org7ea4f242013-10-02 13:34:26 +0000578 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
579 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
580 if (!vie_encoder) {
henrik.lundin@webrtc.org7ea4f242013-10-02 13:34:26 +0000581 return;
582 }
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000583 vie_encoder->SuspendBelowMinBitrate();
584 ViEChannel* vie_channel = cs.Channel(video_channel);
585 if (!vie_channel) {
henrik.lundin@webrtc.org331d4402013-11-21 14:05:40 +0000586 return;
587 }
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);
henrik.lundin@webrtc.org7ea4f242013-10-02 13:34:26 +0000592}
593
stefan@webrtc.org0a3c1472013-12-05 14:05:07 +0000594bool 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);
598 if (!vie_channel) {
stefan@webrtc.org0a3c1472013-12-05 14:05:07 +0000599 shared_data_->SetLastError(kViECodecInvalidChannelId);
600 return false;
601 }
602 return vie_channel->GetSendSideDelay(avg_delay_ms, max_delay_ms);
603}
604
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000605bool ViECodecImpl::CodecValid(const VideoCodec& video_codec) {
606 // Check pl_name matches codec_type.
607 if (video_codec.codecType == kVideoCodecRED) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000608#if defined(WIN32)
mflodman@webrtc.org1fe2ada2011-12-21 12:23:15 +0000609 if (_strnicmp(video_codec.plName, "red", 3) == 0) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000610#else
611 if (strncasecmp(video_codec.plName, "red", 3) == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000612#endif
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000613 // We only care about the type and name for red.
614 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000615 }
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000616 LOG_F(LS_ERROR) << "Invalid RED configuration.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000617 return false;
618 } else if (video_codec.codecType == kVideoCodecULPFEC) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000619#if defined(WIN32)
mflodman@webrtc.org1fe2ada2011-12-21 12:23:15 +0000620 if (_strnicmp(video_codec.plName, "ULPFEC", 6) == 0) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000621#else
622 if (strncasecmp(video_codec.plName, "ULPFEC", 6) == 0) {
niklase@google.com470e71d2011-07-07 08:21:25 +0000623#endif
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000624 // We only care about the type and name for ULPFEC.
625 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000626 }
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000627 LOG_F(LS_ERROR) << "Invalid ULPFEC configuration.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000628 return false;
pwestin@webrtc.org56210572012-01-17 12:45:47 +0000629 } else if ((video_codec.codecType == kVideoCodecVP8 &&
pbos@webrtc.org8911ce42013-03-18 16:39:03 +0000630 strncmp(video_codec.plName, "VP8", 4) == 0) ||
631 (video_codec.codecType == kVideoCodecI420 &&
pbos@webrtc.orgb5bf54c2013-04-05 13:27:38 +0000632 strncmp(video_codec.plName, "I420", 4) == 0)) {
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000633 // OK.
pbos@webrtc.orgb5bf54c2013-04-05 13:27:38 +0000634 } else if (video_codec.codecType != kVideoCodecGeneric) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000635 LOG(LS_ERROR) << "Codec type and name mismatch.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000636 return false;
637 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000638
braveyao@webrtc.org49273ff2013-01-14 01:52:26 +0000639 if (video_codec.plType == 0 || video_codec.plType > 127) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000640 LOG(LS_ERROR) << "Invalif payload type: " << video_codec.plType;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000641 return false;
642 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000643
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000644 if (video_codec.width > kViEMaxCodecWidth ||
645 video_codec.height > kViEMaxCodecHeight) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000646 LOG(LS_ERROR) << "Invalid codec resolution " << video_codec.width
647 << " x " << video_codec.height;
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000648 return false;
649 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000650
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000651 if (video_codec.startBitrate < kViEMinCodecBitrate) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000652 LOG(LS_ERROR) << "Invalid start bitrate.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000653 return false;
654 }
655 if (video_codec.minBitrate < kViEMinCodecBitrate) {
mflodman@webrtc.org5574dac2014-04-07 10:56:31 +0000656 LOG(LS_ERROR) << "Invalid min bitrate.";
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000657 return false;
658 }
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000659 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000660}
mflodman@webrtc.orgc12686c2011-12-21 09:29:28 +0000661
662} // namespace webrtc