Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(934)

Side by Side Diff: webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.cc

Issue 2830793005: Reuse allocated encoders in SimulcastEncoderAdapter. (Closed)
Patch Set: Forgot to upload change that detaches sequenced task checker. Also deregister callbacks when Releas… Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 for (int i = 0; i < num_streams; ++i) { 55 for (int i = 0; i < num_streams; ++i) {
56 if (codec.width * codec.simulcastStream[i].height != 56 if (codec.width * codec.simulcastStream[i].height !=
57 codec.height * codec.simulcastStream[i].width) { 57 codec.height * codec.simulcastStream[i].width) {
58 return false; 58 return false;
59 } 59 }
60 } 60 }
61 return true; 61 return true;
62 } 62 }
63 63
64 int VerifyCodec(const webrtc::VideoCodec* inst) { 64 int VerifyCodec(const webrtc::VideoCodec* inst) {
65 if (inst == NULL) { 65 if (inst == nullptr) {
66 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 66 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
67 } 67 }
68 if (inst->maxFramerate < 1) { 68 if (inst->maxFramerate < 1) {
69 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 69 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
70 } 70 }
71 // allow zero to represent an unspecified maxBitRate 71 // allow zero to represent an unspecified maxBitRate
72 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) { 72 if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) {
73 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 73 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
74 } 74 }
75 if (inst->width <= 1 || inst->height <= 1) { 75 if (inst->width <= 1 || inst->height <= 1) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 120
121 const int adapted_simulcast_id_; 121 const int adapted_simulcast_id_;
122 const TemporalLayersFactory& tl_factory_; 122 const TemporalLayersFactory& tl_factory_;
123 }; 123 };
124 124
125 } // namespace 125 } // namespace
126 126
127 namespace webrtc { 127 namespace webrtc {
128 128
129 SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory) 129 SimulcastEncoderAdapter::SimulcastEncoderAdapter(VideoEncoderFactory* factory)
130 : factory_(factory), 130 : inited_(false),
131 factory_(factory),
131 encoded_complete_callback_(nullptr), 132 encoded_complete_callback_(nullptr),
132 implementation_name_("SimulcastEncoderAdapter") { 133 implementation_name_("SimulcastEncoderAdapter") {
134 // The adapter is typically created on the worker thread, but operated on
135 // the encoder task queue.
136 encoder_queue_.Detach();
137
133 memset(&codec_, 0, sizeof(webrtc::VideoCodec)); 138 memset(&codec_, 0, sizeof(webrtc::VideoCodec));
134 } 139 }
135 140
136 SimulcastEncoderAdapter::~SimulcastEncoderAdapter() { 141 SimulcastEncoderAdapter::~SimulcastEncoderAdapter() {
137 Release(); 142 RTC_DCHECK(!Initialized());
143 DestroyStoredEncoders();
138 } 144 }
139 145
140 int SimulcastEncoderAdapter::Release() { 146 int SimulcastEncoderAdapter::Release() {
141 // TODO(pbos): Keep the last encoder instance but call ::Release() on it, then 147 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
142 // re-use this instance in ::InitEncode(). This means that changing 148
143 // resolutions doesn't require reallocation of the first encoder, but only
144 // reinitialization, which makes sense. Then Destroy this instance instead in
145 // ~SimulcastEncoderAdapter().
146 while (!streaminfos_.empty()) { 149 while (!streaminfos_.empty()) {
147 VideoEncoder* encoder = streaminfos_.back().encoder; 150 VideoEncoder* encoder = streaminfos_.back().encoder;
148 EncodedImageCallback* callback = streaminfos_.back().callback; 151 streaminfos_.pop_back();
149 encoder->Release(); 152 encoder->Release();
150 factory_->Destroy(encoder); 153 // Even though it seems very unlikely, there are no guarantees that the
151 delete callback; 154 // encoder will not call back after being Release()'d. Therefore, we disable
152 streaminfos_.pop_back(); 155 // the callbacks here.
156 encoder->RegisterEncodeCompleteCallback(nullptr);
brandtr 2017/05/15 10:20:20 As discussed offline with sprang@.
sprang_webrtc 2017/05/15 12:03:39 Acknowledged.
157 stored_encoders_.push(encoder);
153 } 158 }
159 #if RTC_DCHECK_IS_ON
160 rtc::CritScope cs(&inited_crit_);
161 #endif
162 inited_ = false;
163 // It's legal to move the encoder to another queue now.
164 encoder_queue_.Detach();
165
154 return WEBRTC_VIDEO_CODEC_OK; 166 return WEBRTC_VIDEO_CODEC_OK;
155 } 167 }
156 168
157 int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, 169 int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
158 int number_of_cores, 170 int number_of_cores,
159 size_t max_payload_size) { 171 size_t max_payload_size) {
172 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
173
160 if (number_of_cores < 1) { 174 if (number_of_cores < 1) {
161 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 175 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
162 } 176 }
163 177
164 int ret = VerifyCodec(inst); 178 int ret = VerifyCodec(inst);
165 if (ret < 0) { 179 if (ret < 0) {
166 return ret; 180 return ret;
167 } 181 }
168 182
169 ret = Release(); 183 ret = Release();
170 if (ret < 0) { 184 if (ret < 0) {
171 return ret; 185 return ret;
172 } 186 }
173 187
174 int number_of_streams = NumberOfStreams(*inst); 188 int number_of_streams = NumberOfStreams(*inst);
189 RTC_DCHECK_LE(number_of_streams, kMaxSimulcastStreams);
175 const bool doing_simulcast = (number_of_streams > 1); 190 const bool doing_simulcast = (number_of_streams > 1);
176 191
177 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) { 192 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) {
178 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 193 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
179 } 194 }
180 195
181 codec_ = *inst; 196 codec_ = *inst;
182 SimulcastRateAllocator rate_allocator(codec_, nullptr); 197 SimulcastRateAllocator rate_allocator(codec_, nullptr);
183 BitrateAllocation allocation = rate_allocator.GetAllocation( 198 BitrateAllocation allocation = rate_allocator.GetAllocation(
184 codec_.startBitrate * 1000, codec_.maxFramerate); 199 codec_.startBitrate * 1000, codec_.maxFramerate);
(...skipping 10 matching lines...) Expand all
195 uint32_t start_bitrate_kbps = start_bitrates[i]; 210 uint32_t start_bitrate_kbps = start_bitrates[i];
196 if (!doing_simulcast) { 211 if (!doing_simulcast) {
197 stream_codec = codec_; 212 stream_codec = codec_;
198 stream_codec.numberOfSimulcastStreams = 1; 213 stream_codec.numberOfSimulcastStreams = 1;
199 } else { 214 } else {
200 // Cap start bitrate to the min bitrate in order to avoid strange codec 215 // Cap start bitrate to the min bitrate in order to avoid strange codec
201 // behavior. Since sending sending will be false, this should not matter. 216 // behavior. Since sending sending will be false, this should not matter.
202 start_bitrate_kbps = 217 start_bitrate_kbps =
203 std::max(codec_.simulcastStream[i].minBitrate, start_bitrate_kbps); 218 std::max(codec_.simulcastStream[i].minBitrate, start_bitrate_kbps);
204 bool highest_resolution_stream = (i == (number_of_streams - 1)); 219 bool highest_resolution_stream = (i == (number_of_streams - 1));
205 PopulateStreamCodec(&codec_, i, start_bitrate_kbps, 220 PopulateStreamCodec(codec_, i, start_bitrate_kbps,
206 highest_resolution_stream, &stream_codec); 221 highest_resolution_stream, &stream_codec);
207 } 222 }
208 TemporalLayersFactoryAdapter tl_factory_adapter(i, 223 TemporalLayersFactoryAdapter tl_factory_adapter(i,
209 *codec_.VP8()->tl_factory); 224 *codec_.VP8()->tl_factory);
210 stream_codec.VP8()->tl_factory = &tl_factory_adapter; 225 stream_codec.VP8()->tl_factory = &tl_factory_adapter;
211 226
212 // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl. 227 // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl.
213 if (stream_codec.qpMax < kDefaultMinQp) { 228 if (stream_codec.qpMax < kDefaultMinQp) {
214 stream_codec.qpMax = kDefaultMaxQp; 229 stream_codec.qpMax = kDefaultMaxQp;
215 } 230 }
216 231
217 VideoEncoder* encoder = factory_->Create(); 232 // If an existing encoder instance exists, reuse it.
233 // TODO(brandtr): Set initial RTP state (e.g., picture_id/tl0_pic_idx) here,
234 // when we start storing that state outside the encoder wrappers.
235 VideoEncoder* encoder;
236 if (!stored_encoders_.empty()) {
237 encoder = stored_encoders_.top();
238 stored_encoders_.pop();
239 } else {
240 encoder = factory_->Create();
241 }
242
218 ret = encoder->InitEncode(&stream_codec, number_of_cores, max_payload_size); 243 ret = encoder->InitEncode(&stream_codec, number_of_cores, max_payload_size);
219 if (ret < 0) { 244 if (ret < 0) {
220 // Explicitly destroy the current encoder; because we haven't registered a 245 // Explicitly destroy the current encoder; because we haven't registered a
221 // StreamInfo for it yet, Release won't do anything about it. 246 // StreamInfo for it yet, Release won't do anything about it.
222 factory_->Destroy(encoder); 247 factory_->Destroy(encoder);
223 Release(); 248 Release();
224 return ret; 249 return ret;
225 } 250 }
226 EncodedImageCallback* callback = new AdapterEncodedImageCallback(this, i); 251 std::unique_ptr<EncodedImageCallback> callback(
227 encoder->RegisterEncodeCompleteCallback(callback); 252 new AdapterEncodedImageCallback(this, i));
228 streaminfos_.push_back(StreamInfo(encoder, callback, stream_codec.width, 253 encoder->RegisterEncodeCompleteCallback(callback.get());
229 stream_codec.height, 254 streaminfos_.emplace_back(encoder, std::move(callback), stream_codec.width,
230 start_bitrate_kbps > 0)); 255 stream_codec.height, start_bitrate_kbps > 0);
231 if (i != 0) 256
257 if (i != 0) {
232 implementation_name += ", "; 258 implementation_name += ", ";
259 }
233 implementation_name += streaminfos_[i].encoder->ImplementationName(); 260 implementation_name += streaminfos_[i].encoder->ImplementationName();
234 } 261 }
262
235 if (doing_simulcast) { 263 if (doing_simulcast) {
236 implementation_name_ = 264 implementation_name_ =
237 "SimulcastEncoderAdapter (" + implementation_name + ")"; 265 "SimulcastEncoderAdapter (" + implementation_name + ")";
238 } else { 266 } else {
239 implementation_name_ = implementation_name; 267 implementation_name_ = implementation_name;
240 } 268 }
269
270 // To save memory, don't store encoders that we don't use.
271 DestroyStoredEncoders();
272
273 #if RTC_DCHECK_IS_ON
274 rtc::CritScope cs(&inited_crit_);
275 #endif
276 inited_ = true;
277
241 return WEBRTC_VIDEO_CODEC_OK; 278 return WEBRTC_VIDEO_CODEC_OK;
242 } 279 }
243 280
244 int SimulcastEncoderAdapter::Encode( 281 int SimulcastEncoderAdapter::Encode(
245 const VideoFrame& input_image, 282 const VideoFrame& input_image,
246 const CodecSpecificInfo* codec_specific_info, 283 const CodecSpecificInfo* codec_specific_info,
247 const std::vector<FrameType>* frame_types) { 284 const std::vector<FrameType>* frame_types) {
285 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
286
248 if (!Initialized()) { 287 if (!Initialized()) {
249 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 288 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
250 } 289 }
251 if (encoded_complete_callback_ == NULL) { 290 if (encoded_complete_callback_ == nullptr) {
252 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 291 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
253 } 292 }
254 293
255 // All active streams should generate a key frame if 294 // All active streams should generate a key frame if
256 // a key frame is requested by any stream. 295 // a key frame is requested by any stream.
257 bool send_key_frame = false; 296 bool send_key_frame = false;
258 if (frame_types) { 297 if (frame_types) {
259 for (size_t i = 0; i < frame_types->size(); ++i) { 298 for (size_t i = 0; i < frame_types->size(); ++i) {
260 if (frame_types->at(i) == kVideoFrameKey) { 299 if (frame_types->at(i) == kVideoFrameKey) {
261 send_key_frame = true; 300 send_key_frame = true;
262 break; 301 break;
263 } 302 }
264 } 303 }
265 } 304 }
266 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 305 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
267 if (streaminfos_[stream_idx].key_frame_request && 306 if (streaminfos_[stream_idx].key_frame_request &&
268 streaminfos_[stream_idx].send_stream) { 307 streaminfos_[stream_idx].send_stream) {
269 send_key_frame = true; 308 send_key_frame = true;
270 break; 309 break;
271 } 310 }
272 } 311 }
273 312
274 int src_width = input_image.width(); 313 int src_width = input_image.width();
275 int src_height = input_image.height(); 314 int src_height = input_image.height();
276 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 315 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
277 // Don't encode frames in resolutions that we don't intend to send. 316 // Don't encode frames in resolutions that we don't intend to send.
278 if (!streaminfos_[stream_idx].send_stream) 317 if (!streaminfos_[stream_idx].send_stream) {
279 continue; 318 continue;
319 }
280 320
281 std::vector<FrameType> stream_frame_types; 321 std::vector<FrameType> stream_frame_types;
282 if (send_key_frame) { 322 if (send_key_frame) {
283 stream_frame_types.push_back(kVideoFrameKey); 323 stream_frame_types.push_back(kVideoFrameKey);
284 streaminfos_[stream_idx].key_frame_request = false; 324 streaminfos_[stream_idx].key_frame_request = false;
285 } else { 325 } else {
286 stream_frame_types.push_back(kVideoFrameDelta); 326 stream_frame_types.push_back(kVideoFrameDelta);
287 } 327 }
288 328
289 int dst_width = streaminfos_[stream_idx].width; 329 int dst_width = streaminfos_[stream_idx].width;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 return ret; 371 return ret;
332 } 372 }
333 } 373 }
334 } 374 }
335 375
336 return WEBRTC_VIDEO_CODEC_OK; 376 return WEBRTC_VIDEO_CODEC_OK;
337 } 377 }
338 378
339 int SimulcastEncoderAdapter::RegisterEncodeCompleteCallback( 379 int SimulcastEncoderAdapter::RegisterEncodeCompleteCallback(
340 EncodedImageCallback* callback) { 380 EncodedImageCallback* callback) {
381 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
341 encoded_complete_callback_ = callback; 382 encoded_complete_callback_ = callback;
342 return WEBRTC_VIDEO_CODEC_OK; 383 return WEBRTC_VIDEO_CODEC_OK;
343 } 384 }
344 385
345 int SimulcastEncoderAdapter::SetChannelParameters(uint32_t packet_loss, 386 int SimulcastEncoderAdapter::SetChannelParameters(uint32_t packet_loss,
346 int64_t rtt) { 387 int64_t rtt) {
388 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
347 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 389 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
348 streaminfos_[stream_idx].encoder->SetChannelParameters(packet_loss, rtt); 390 streaminfos_[stream_idx].encoder->SetChannelParameters(packet_loss, rtt);
349 } 391 }
350 return WEBRTC_VIDEO_CODEC_OK; 392 return WEBRTC_VIDEO_CODEC_OK;
351 } 393 }
352 394
353 int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate, 395 int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate,
354 uint32_t new_framerate) { 396 uint32_t new_framerate) {
355 if (!Initialized()) 397 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
398
399 if (!Initialized()) {
356 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 400 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
401 }
357 402
358 if (new_framerate < 1) 403 if (new_framerate < 1) {
359 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 404 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
405 }
360 406
361 if (codec_.maxBitrate > 0 && bitrate.get_sum_kbps() > codec_.maxBitrate) 407 if (codec_.maxBitrate > 0 && bitrate.get_sum_kbps() > codec_.maxBitrate) {
362 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 408 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
409 }
363 410
364 if (bitrate.get_sum_bps() > 0) { 411 if (bitrate.get_sum_bps() > 0) {
365 // Make sure the bitrate fits the configured min bitrates. 0 is a special 412 // Make sure the bitrate fits the configured min bitrates. 0 is a special
366 // value that means paused, though, so leave it alone. 413 // value that means paused, though, so leave it alone.
367 if (bitrate.get_sum_kbps() < codec_.minBitrate) 414 if (bitrate.get_sum_kbps() < codec_.minBitrate) {
368 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 415 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
416 }
369 417
370 if (codec_.numberOfSimulcastStreams > 0 && 418 if (codec_.numberOfSimulcastStreams > 0 &&
371 bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) { 419 bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) {
372 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 420 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
373 } 421 }
374 } 422 }
375 423
376 codec_.maxFramerate = new_framerate; 424 codec_.maxFramerate = new_framerate;
377 425
378 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 426 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
379 uint32_t stream_bitrate_kbps = 427 uint32_t stream_bitrate_kbps =
380 bitrate.GetSpatialLayerSum(stream_idx) / 1000; 428 bitrate.GetSpatialLayerSum(stream_idx) / 1000;
381 429
382 // Need a key frame if we have not sent this stream before. 430 // Need a key frame if we have not sent this stream before.
383 if (stream_bitrate_kbps > 0 && !streaminfos_[stream_idx].send_stream) { 431 if (stream_bitrate_kbps > 0 && !streaminfos_[stream_idx].send_stream) {
384 streaminfos_[stream_idx].key_frame_request = true; 432 streaminfos_[stream_idx].key_frame_request = true;
385 } 433 }
386 streaminfos_[stream_idx].send_stream = stream_bitrate_kbps > 0; 434 streaminfos_[stream_idx].send_stream = stream_bitrate_kbps > 0;
387 435
388 // Slice the temporal layers out of the full allocation and pass it on to 436 // Slice the temporal layers out of the full allocation and pass it on to
389 // the encoder handling the current simulcast stream. 437 // the encoder handling the current simulcast stream.
390 BitrateAllocation stream_allocation; 438 BitrateAllocation stream_allocation;
391 for (int i = 0; i < kMaxTemporalStreams; ++i) 439 for (int i = 0; i < kMaxTemporalStreams; ++i) {
392 stream_allocation.SetBitrate(0, i, bitrate.GetBitrate(stream_idx, i)); 440 stream_allocation.SetBitrate(0, i, bitrate.GetBitrate(stream_idx, i));
441 }
393 streaminfos_[stream_idx].encoder->SetRateAllocation(stream_allocation, 442 streaminfos_[stream_idx].encoder->SetRateAllocation(stream_allocation,
394 new_framerate); 443 new_framerate);
395 } 444 }
396 445
397 return WEBRTC_VIDEO_CODEC_OK; 446 return WEBRTC_VIDEO_CODEC_OK;
398 } 447 }
399 448
449 // TODO(brandtr): Add task checker to this member function, when all encoder
450 // callbacks are coming in on the encoder queue.
400 EncodedImageCallback::Result SimulcastEncoderAdapter::OnEncodedImage( 451 EncodedImageCallback::Result SimulcastEncoderAdapter::OnEncodedImage(
401 size_t stream_idx, 452 size_t stream_idx,
402 const EncodedImage& encodedImage, 453 const EncodedImage& encodedImage,
403 const CodecSpecificInfo* codecSpecificInfo, 454 const CodecSpecificInfo* codecSpecificInfo,
404 const RTPFragmentationHeader* fragmentation) { 455 const RTPFragmentationHeader* fragmentation) {
405 CodecSpecificInfo stream_codec_specific = *codecSpecificInfo; 456 CodecSpecificInfo stream_codec_specific = *codecSpecificInfo;
406 stream_codec_specific.codec_name = implementation_name_.c_str(); 457 stream_codec_specific.codec_name = implementation_name_.c_str();
407 CodecSpecificInfoVP8* vp8Info = &(stream_codec_specific.codecSpecific.VP8); 458 CodecSpecificInfoVP8* vp8Info = &(stream_codec_specific.codecSpecific.VP8);
408 vp8Info->simulcastIdx = stream_idx; 459 vp8Info->simulcastIdx = stream_idx;
409 460
410 return encoded_complete_callback_->OnEncodedImage( 461 return encoded_complete_callback_->OnEncodedImage(
411 encodedImage, &stream_codec_specific, fragmentation); 462 encodedImage, &stream_codec_specific, fragmentation);
412 } 463 }
413 464
414 void SimulcastEncoderAdapter::PopulateStreamCodec( 465 void SimulcastEncoderAdapter::PopulateStreamCodec(
415 const webrtc::VideoCodec* inst, 466 const webrtc::VideoCodec& inst,
416 int stream_index, 467 int stream_index,
417 uint32_t start_bitrate_kbps, 468 uint32_t start_bitrate_kbps,
418 bool highest_resolution_stream, 469 bool highest_resolution_stream,
419 webrtc::VideoCodec* stream_codec) { 470 webrtc::VideoCodec* stream_codec) {
420 *stream_codec = *inst; 471 *stream_codec = inst;
421 472
422 // Stream specific settings. 473 // Stream specific settings.
423 stream_codec->VP8()->numberOfTemporalLayers = 474 stream_codec->VP8()->numberOfTemporalLayers =
424 inst->simulcastStream[stream_index].numberOfTemporalLayers; 475 inst.simulcastStream[stream_index].numberOfTemporalLayers;
425 stream_codec->numberOfSimulcastStreams = 0; 476 stream_codec->numberOfSimulcastStreams = 0;
426 stream_codec->width = inst->simulcastStream[stream_index].width; 477 stream_codec->width = inst.simulcastStream[stream_index].width;
427 stream_codec->height = inst->simulcastStream[stream_index].height; 478 stream_codec->height = inst.simulcastStream[stream_index].height;
428 stream_codec->maxBitrate = inst->simulcastStream[stream_index].maxBitrate; 479 stream_codec->maxBitrate = inst.simulcastStream[stream_index].maxBitrate;
429 stream_codec->minBitrate = inst->simulcastStream[stream_index].minBitrate; 480 stream_codec->minBitrate = inst.simulcastStream[stream_index].minBitrate;
430 stream_codec->qpMax = inst->simulcastStream[stream_index].qpMax; 481 stream_codec->qpMax = inst.simulcastStream[stream_index].qpMax;
431 // Settings that are based on stream/resolution. 482 // Settings that are based on stream/resolution.
432 if (stream_index == 0) { 483 const bool lowest_resolution_stream = (stream_index == 0);
484 if (lowest_resolution_stream) {
433 // Settings for lowest spatial resolutions. 485 // Settings for lowest spatial resolutions.
434 stream_codec->qpMax = kLowestResMaxQp; 486 stream_codec->qpMax = kLowestResMaxQp;
435 } 487 }
436 if (!highest_resolution_stream) { 488 if (!highest_resolution_stream) {
437 // For resolutions below CIF, set the codec |complexity| parameter to 489 // For resolutions below CIF, set the codec |complexity| parameter to
438 // kComplexityHigher, which maps to cpu_used = -4. 490 // kComplexityHigher, which maps to cpu_used = -4.
439 int pixels_per_frame = stream_codec->width * stream_codec->height; 491 int pixels_per_frame = stream_codec->width * stream_codec->height;
440 if (pixels_per_frame < 352 * 288) { 492 if (pixels_per_frame < 352 * 288) {
441 stream_codec->VP8()->complexity = webrtc::kComplexityHigher; 493 stream_codec->VP8()->complexity = webrtc::kComplexityHigher;
442 } 494 }
443 // Turn off denoising for all streams but the highest resolution. 495 // Turn off denoising for all streams but the highest resolution.
444 stream_codec->VP8()->denoisingOn = false; 496 stream_codec->VP8()->denoisingOn = false;
445 } 497 }
446 // TODO(ronghuawu): what to do with targetBitrate. 498 // TODO(ronghuawu): what to do with targetBitrate.
447 499
448 stream_codec->startBitrate = start_bitrate_kbps; 500 stream_codec->startBitrate = start_bitrate_kbps;
449 } 501 }
450 502
451 bool SimulcastEncoderAdapter::Initialized() const { 503 bool SimulcastEncoderAdapter::Initialized() const {
452 return !streaminfos_.empty(); 504 #if RTC_DCHECK_IS_ON
505 rtc::CritScope cs(&inited_crit_);
506 #endif
507 return inited_;
508 }
509
510 void SimulcastEncoderAdapter::DestroyStoredEncoders() {
511 while (!stored_encoders_.empty()) {
512 VideoEncoder* encoder = stored_encoders_.top();
513 factory_->Destroy(encoder);
514 stored_encoders_.pop();
515 }
453 } 516 }
454 517
455 bool SimulcastEncoderAdapter::SupportsNativeHandle() const { 518 bool SimulcastEncoderAdapter::SupportsNativeHandle() const {
519 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
456 // We should not be calling this method before streaminfos_ are configured. 520 // We should not be calling this method before streaminfos_ are configured.
457 RTC_DCHECK(!streaminfos_.empty()); 521 RTC_DCHECK(!streaminfos_.empty());
458 for (const auto& streaminfo : streaminfos_) { 522 for (const auto& streaminfo : streaminfos_) {
459 if (!streaminfo.encoder->SupportsNativeHandle()) 523 if (!streaminfo.encoder->SupportsNativeHandle()) {
460 return false; 524 return false;
525 }
461 } 526 }
462 return true; 527 return true;
463 } 528 }
464 529
465 VideoEncoder::ScalingSettings SimulcastEncoderAdapter::GetScalingSettings() 530 VideoEncoder::ScalingSettings SimulcastEncoderAdapter::GetScalingSettings()
466 const { 531 const {
532 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
467 // Turn off quality scaling for simulcast. 533 // Turn off quality scaling for simulcast.
468 if (!Initialized() || NumberOfStreams(codec_) != 1) 534 if (!Initialized() || NumberOfStreams(codec_) != 1) {
469 return VideoEncoder::ScalingSettings(false); 535 return VideoEncoder::ScalingSettings(false);
536 }
470 return streaminfos_[0].encoder->GetScalingSettings(); 537 return streaminfos_[0].encoder->GetScalingSettings();
471 } 538 }
472 539
473 const char* SimulcastEncoderAdapter::ImplementationName() const { 540 const char* SimulcastEncoderAdapter::ImplementationName() const {
541 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
474 return implementation_name_.c_str(); 542 return implementation_name_.c_str();
475 } 543 }
476 544
477 } // namespace webrtc 545 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698