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

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

Issue 2901493002: Reland of use allocated encoders in SimulcastEncoderAdapter. (Closed)
Patch Set: 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_(0),
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;
149 encoder->Release(); 151 encoder->Release();
150 factory_->Destroy(encoder); 152 // Even though it seems very unlikely, there are no guarantees that the
151 delete callback; 153 // encoder will not call back after being Release()'d. Therefore, we disable
152 streaminfos_.pop_back(); 154 // the callbacks here.
155 encoder->RegisterEncodeCompleteCallback(nullptr);
156 streaminfos_.pop_back(); // Deletes callback adapter.
157 stored_encoders_.push(encoder);
153 } 158 }
159
160 // It's legal to move the encoder to another queue now.
161 encoder_queue_.Detach();
162
163 rtc::AtomicOps::ReleaseStore(&inited_, 0);
164
154 return WEBRTC_VIDEO_CODEC_OK; 165 return WEBRTC_VIDEO_CODEC_OK;
155 } 166 }
156 167
157 int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst, 168 int SimulcastEncoderAdapter::InitEncode(const VideoCodec* inst,
158 int number_of_cores, 169 int number_of_cores,
159 size_t max_payload_size) { 170 size_t max_payload_size) {
171 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
172
160 if (number_of_cores < 1) { 173 if (number_of_cores < 1) {
161 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 174 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
162 } 175 }
163 176
164 int ret = VerifyCodec(inst); 177 int ret = VerifyCodec(inst);
165 if (ret < 0) { 178 if (ret < 0) {
166 return ret; 179 return ret;
167 } 180 }
168 181
169 ret = Release(); 182 ret = Release();
170 if (ret < 0) { 183 if (ret < 0) {
171 return ret; 184 return ret;
172 } 185 }
173 186
174 int number_of_streams = NumberOfStreams(*inst); 187 int number_of_streams = NumberOfStreams(*inst);
188 RTC_DCHECK_LE(number_of_streams, kMaxSimulcastStreams);
175 const bool doing_simulcast = (number_of_streams > 1); 189 const bool doing_simulcast = (number_of_streams > 1);
176 190
177 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) { 191 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) {
178 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 192 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
179 } 193 }
180 194
181 codec_ = *inst; 195 codec_ = *inst;
182 SimulcastRateAllocator rate_allocator(codec_, nullptr); 196 SimulcastRateAllocator rate_allocator(codec_, nullptr);
183 BitrateAllocation allocation = rate_allocator.GetAllocation( 197 BitrateAllocation allocation = rate_allocator.GetAllocation(
184 codec_.startBitrate * 1000, codec_.maxFramerate); 198 codec_.startBitrate * 1000, codec_.maxFramerate);
(...skipping 10 matching lines...) Expand all
195 uint32_t start_bitrate_kbps = start_bitrates[i]; 209 uint32_t start_bitrate_kbps = start_bitrates[i];
196 if (!doing_simulcast) { 210 if (!doing_simulcast) {
197 stream_codec = codec_; 211 stream_codec = codec_;
198 stream_codec.numberOfSimulcastStreams = 1; 212 stream_codec.numberOfSimulcastStreams = 1;
199 } else { 213 } else {
200 // Cap start bitrate to the min bitrate in order to avoid strange codec 214 // 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. 215 // behavior. Since sending sending will be false, this should not matter.
202 start_bitrate_kbps = 216 start_bitrate_kbps =
203 std::max(codec_.simulcastStream[i].minBitrate, start_bitrate_kbps); 217 std::max(codec_.simulcastStream[i].minBitrate, start_bitrate_kbps);
204 bool highest_resolution_stream = (i == (number_of_streams - 1)); 218 bool highest_resolution_stream = (i == (number_of_streams - 1));
205 PopulateStreamCodec(&codec_, i, start_bitrate_kbps, 219 PopulateStreamCodec(codec_, i, start_bitrate_kbps,
206 highest_resolution_stream, &stream_codec); 220 highest_resolution_stream, &stream_codec);
207 } 221 }
208 TemporalLayersFactoryAdapter tl_factory_adapter(i, 222 TemporalLayersFactoryAdapter tl_factory_adapter(i,
209 *codec_.VP8()->tl_factory); 223 *codec_.VP8()->tl_factory);
210 stream_codec.VP8()->tl_factory = &tl_factory_adapter; 224 stream_codec.VP8()->tl_factory = &tl_factory_adapter;
211 225
212 // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl. 226 // TODO(ronghuawu): Remove once this is handled in VP8EncoderImpl.
213 if (stream_codec.qpMax < kDefaultMinQp) { 227 if (stream_codec.qpMax < kDefaultMinQp) {
214 stream_codec.qpMax = kDefaultMaxQp; 228 stream_codec.qpMax = kDefaultMaxQp;
215 } 229 }
216 230
217 VideoEncoder* encoder = factory_->Create(); 231 // If an existing encoder instance exists, reuse it.
232 // TODO(brandtr): Set initial RTP state (e.g., picture_id/tl0_pic_idx) here,
233 // when we start storing that state outside the encoder wrappers.
234 VideoEncoder* encoder;
235 if (!stored_encoders_.empty()) {
236 encoder = stored_encoders_.top();
237 stored_encoders_.pop();
238 } else {
239 encoder = factory_->Create();
240 }
241
218 ret = encoder->InitEncode(&stream_codec, number_of_cores, max_payload_size); 242 ret = encoder->InitEncode(&stream_codec, number_of_cores, max_payload_size);
219 if (ret < 0) { 243 if (ret < 0) {
220 // Explicitly destroy the current encoder; because we haven't registered a 244 // Explicitly destroy the current encoder; because we haven't registered a
221 // StreamInfo for it yet, Release won't do anything about it. 245 // StreamInfo for it yet, Release won't do anything about it.
222 factory_->Destroy(encoder); 246 factory_->Destroy(encoder);
223 Release(); 247 Release();
224 return ret; 248 return ret;
225 } 249 }
226 EncodedImageCallback* callback = new AdapterEncodedImageCallback(this, i); 250 std::unique_ptr<EncodedImageCallback> callback(
227 encoder->RegisterEncodeCompleteCallback(callback); 251 new AdapterEncodedImageCallback(this, i));
228 streaminfos_.push_back(StreamInfo(encoder, callback, stream_codec.width, 252 encoder->RegisterEncodeCompleteCallback(callback.get());
229 stream_codec.height, 253 streaminfos_.emplace_back(encoder, std::move(callback), stream_codec.width,
230 start_bitrate_kbps > 0)); 254 stream_codec.height, start_bitrate_kbps > 0);
231 if (i != 0) 255
256 if (i != 0) {
232 implementation_name += ", "; 257 implementation_name += ", ";
258 }
233 implementation_name += streaminfos_[i].encoder->ImplementationName(); 259 implementation_name += streaminfos_[i].encoder->ImplementationName();
234 } 260 }
261
235 if (doing_simulcast) { 262 if (doing_simulcast) {
236 implementation_name_ = 263 implementation_name_ =
237 "SimulcastEncoderAdapter (" + implementation_name + ")"; 264 "SimulcastEncoderAdapter (" + implementation_name + ")";
238 } else { 265 } else {
239 implementation_name_ = implementation_name; 266 implementation_name_ = implementation_name;
240 } 267 }
268
269 // To save memory, don't store encoders that we don't use.
270 DestroyStoredEncoders();
271
272 rtc::AtomicOps::ReleaseStore(&inited_, 1);
273
241 return WEBRTC_VIDEO_CODEC_OK; 274 return WEBRTC_VIDEO_CODEC_OK;
242 } 275 }
243 276
244 int SimulcastEncoderAdapter::Encode( 277 int SimulcastEncoderAdapter::Encode(
245 const VideoFrame& input_image, 278 const VideoFrame& input_image,
246 const CodecSpecificInfo* codec_specific_info, 279 const CodecSpecificInfo* codec_specific_info,
247 const std::vector<FrameType>* frame_types) { 280 const std::vector<FrameType>* frame_types) {
281 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
282
248 if (!Initialized()) { 283 if (!Initialized()) {
249 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 284 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
250 } 285 }
251 if (encoded_complete_callback_ == NULL) { 286 if (encoded_complete_callback_ == nullptr) {
252 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 287 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
253 } 288 }
254 289
255 // All active streams should generate a key frame if 290 // All active streams should generate a key frame if
256 // a key frame is requested by any stream. 291 // a key frame is requested by any stream.
257 bool send_key_frame = false; 292 bool send_key_frame = false;
258 if (frame_types) { 293 if (frame_types) {
259 for (size_t i = 0; i < frame_types->size(); ++i) { 294 for (size_t i = 0; i < frame_types->size(); ++i) {
260 if (frame_types->at(i) == kVideoFrameKey) { 295 if (frame_types->at(i) == kVideoFrameKey) {
261 send_key_frame = true; 296 send_key_frame = true;
262 break; 297 break;
263 } 298 }
264 } 299 }
265 } 300 }
266 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 301 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
267 if (streaminfos_[stream_idx].key_frame_request && 302 if (streaminfos_[stream_idx].key_frame_request &&
268 streaminfos_[stream_idx].send_stream) { 303 streaminfos_[stream_idx].send_stream) {
269 send_key_frame = true; 304 send_key_frame = true;
270 break; 305 break;
271 } 306 }
272 } 307 }
273 308
274 int src_width = input_image.width(); 309 int src_width = input_image.width();
275 int src_height = input_image.height(); 310 int src_height = input_image.height();
276 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 311 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. 312 // Don't encode frames in resolutions that we don't intend to send.
278 if (!streaminfos_[stream_idx].send_stream) 313 if (!streaminfos_[stream_idx].send_stream) {
279 continue; 314 continue;
315 }
280 316
281 std::vector<FrameType> stream_frame_types; 317 std::vector<FrameType> stream_frame_types;
282 if (send_key_frame) { 318 if (send_key_frame) {
283 stream_frame_types.push_back(kVideoFrameKey); 319 stream_frame_types.push_back(kVideoFrameKey);
284 streaminfos_[stream_idx].key_frame_request = false; 320 streaminfos_[stream_idx].key_frame_request = false;
285 } else { 321 } else {
286 stream_frame_types.push_back(kVideoFrameDelta); 322 stream_frame_types.push_back(kVideoFrameDelta);
287 } 323 }
288 324
289 int dst_width = streaminfos_[stream_idx].width; 325 int dst_width = streaminfos_[stream_idx].width;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 return ret; 367 return ret;
332 } 368 }
333 } 369 }
334 } 370 }
335 371
336 return WEBRTC_VIDEO_CODEC_OK; 372 return WEBRTC_VIDEO_CODEC_OK;
337 } 373 }
338 374
339 int SimulcastEncoderAdapter::RegisterEncodeCompleteCallback( 375 int SimulcastEncoderAdapter::RegisterEncodeCompleteCallback(
340 EncodedImageCallback* callback) { 376 EncodedImageCallback* callback) {
377 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
341 encoded_complete_callback_ = callback; 378 encoded_complete_callback_ = callback;
342 return WEBRTC_VIDEO_CODEC_OK; 379 return WEBRTC_VIDEO_CODEC_OK;
343 } 380 }
344 381
345 int SimulcastEncoderAdapter::SetChannelParameters(uint32_t packet_loss, 382 int SimulcastEncoderAdapter::SetChannelParameters(uint32_t packet_loss,
346 int64_t rtt) { 383 int64_t rtt) {
384 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
347 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 385 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
348 streaminfos_[stream_idx].encoder->SetChannelParameters(packet_loss, rtt); 386 streaminfos_[stream_idx].encoder->SetChannelParameters(packet_loss, rtt);
349 } 387 }
350 return WEBRTC_VIDEO_CODEC_OK; 388 return WEBRTC_VIDEO_CODEC_OK;
351 } 389 }
352 390
353 int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate, 391 int SimulcastEncoderAdapter::SetRateAllocation(const BitrateAllocation& bitrate,
354 uint32_t new_framerate) { 392 uint32_t new_framerate) {
355 if (!Initialized()) 393 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
394
395 if (!Initialized()) {
356 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; 396 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
397 }
357 398
358 if (new_framerate < 1) 399 if (new_framerate < 1) {
359 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 400 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
401 }
360 402
361 if (codec_.maxBitrate > 0 && bitrate.get_sum_kbps() > codec_.maxBitrate) 403 if (codec_.maxBitrate > 0 && bitrate.get_sum_kbps() > codec_.maxBitrate) {
362 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 404 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
405 }
363 406
364 if (bitrate.get_sum_bps() > 0) { 407 if (bitrate.get_sum_bps() > 0) {
365 // Make sure the bitrate fits the configured min bitrates. 0 is a special 408 // Make sure the bitrate fits the configured min bitrates. 0 is a special
366 // value that means paused, though, so leave it alone. 409 // value that means paused, though, so leave it alone.
367 if (bitrate.get_sum_kbps() < codec_.minBitrate) 410 if (bitrate.get_sum_kbps() < codec_.minBitrate) {
368 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 411 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
412 }
369 413
370 if (codec_.numberOfSimulcastStreams > 0 && 414 if (codec_.numberOfSimulcastStreams > 0 &&
371 bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) { 415 bitrate.get_sum_kbps() < codec_.simulcastStream[0].minBitrate) {
372 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; 416 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
373 } 417 }
374 } 418 }
375 419
376 codec_.maxFramerate = new_framerate; 420 codec_.maxFramerate = new_framerate;
377 421
378 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) { 422 for (size_t stream_idx = 0; stream_idx < streaminfos_.size(); ++stream_idx) {
379 uint32_t stream_bitrate_kbps = 423 uint32_t stream_bitrate_kbps =
380 bitrate.GetSpatialLayerSum(stream_idx) / 1000; 424 bitrate.GetSpatialLayerSum(stream_idx) / 1000;
381 425
382 // Need a key frame if we have not sent this stream before. 426 // Need a key frame if we have not sent this stream before.
383 if (stream_bitrate_kbps > 0 && !streaminfos_[stream_idx].send_stream) { 427 if (stream_bitrate_kbps > 0 && !streaminfos_[stream_idx].send_stream) {
384 streaminfos_[stream_idx].key_frame_request = true; 428 streaminfos_[stream_idx].key_frame_request = true;
385 } 429 }
386 streaminfos_[stream_idx].send_stream = stream_bitrate_kbps > 0; 430 streaminfos_[stream_idx].send_stream = stream_bitrate_kbps > 0;
387 431
388 // Slice the temporal layers out of the full allocation and pass it on to 432 // Slice the temporal layers out of the full allocation and pass it on to
389 // the encoder handling the current simulcast stream. 433 // the encoder handling the current simulcast stream.
390 BitrateAllocation stream_allocation; 434 BitrateAllocation stream_allocation;
391 for (int i = 0; i < kMaxTemporalStreams; ++i) 435 for (int i = 0; i < kMaxTemporalStreams; ++i) {
392 stream_allocation.SetBitrate(0, i, bitrate.GetBitrate(stream_idx, i)); 436 stream_allocation.SetBitrate(0, i, bitrate.GetBitrate(stream_idx, i));
437 }
393 streaminfos_[stream_idx].encoder->SetRateAllocation(stream_allocation, 438 streaminfos_[stream_idx].encoder->SetRateAllocation(stream_allocation,
394 new_framerate); 439 new_framerate);
395 } 440 }
396 441
397 return WEBRTC_VIDEO_CODEC_OK; 442 return WEBRTC_VIDEO_CODEC_OK;
398 } 443 }
399 444
445 // TODO(brandtr): Add task checker to this member function, when all encoder
446 // callbacks are coming in on the encoder queue.
400 EncodedImageCallback::Result SimulcastEncoderAdapter::OnEncodedImage( 447 EncodedImageCallback::Result SimulcastEncoderAdapter::OnEncodedImage(
401 size_t stream_idx, 448 size_t stream_idx,
402 const EncodedImage& encodedImage, 449 const EncodedImage& encodedImage,
403 const CodecSpecificInfo* codecSpecificInfo, 450 const CodecSpecificInfo* codecSpecificInfo,
404 const RTPFragmentationHeader* fragmentation) { 451 const RTPFragmentationHeader* fragmentation) {
405 CodecSpecificInfo stream_codec_specific = *codecSpecificInfo; 452 CodecSpecificInfo stream_codec_specific = *codecSpecificInfo;
406 stream_codec_specific.codec_name = implementation_name_.c_str(); 453 stream_codec_specific.codec_name = implementation_name_.c_str();
407 CodecSpecificInfoVP8* vp8Info = &(stream_codec_specific.codecSpecific.VP8); 454 CodecSpecificInfoVP8* vp8Info = &(stream_codec_specific.codecSpecific.VP8);
408 vp8Info->simulcastIdx = stream_idx; 455 vp8Info->simulcastIdx = stream_idx;
409 456
410 return encoded_complete_callback_->OnEncodedImage( 457 return encoded_complete_callback_->OnEncodedImage(
411 encodedImage, &stream_codec_specific, fragmentation); 458 encodedImage, &stream_codec_specific, fragmentation);
412 } 459 }
413 460
414 void SimulcastEncoderAdapter::PopulateStreamCodec( 461 void SimulcastEncoderAdapter::PopulateStreamCodec(
415 const webrtc::VideoCodec* inst, 462 const webrtc::VideoCodec& inst,
416 int stream_index, 463 int stream_index,
417 uint32_t start_bitrate_kbps, 464 uint32_t start_bitrate_kbps,
418 bool highest_resolution_stream, 465 bool highest_resolution_stream,
419 webrtc::VideoCodec* stream_codec) { 466 webrtc::VideoCodec* stream_codec) {
420 *stream_codec = *inst; 467 *stream_codec = inst;
421 468
422 // Stream specific settings. 469 // Stream specific settings.
423 stream_codec->VP8()->numberOfTemporalLayers = 470 stream_codec->VP8()->numberOfTemporalLayers =
424 inst->simulcastStream[stream_index].numberOfTemporalLayers; 471 inst.simulcastStream[stream_index].numberOfTemporalLayers;
425 stream_codec->numberOfSimulcastStreams = 0; 472 stream_codec->numberOfSimulcastStreams = 0;
426 stream_codec->width = inst->simulcastStream[stream_index].width; 473 stream_codec->width = inst.simulcastStream[stream_index].width;
427 stream_codec->height = inst->simulcastStream[stream_index].height; 474 stream_codec->height = inst.simulcastStream[stream_index].height;
428 stream_codec->maxBitrate = inst->simulcastStream[stream_index].maxBitrate; 475 stream_codec->maxBitrate = inst.simulcastStream[stream_index].maxBitrate;
429 stream_codec->minBitrate = inst->simulcastStream[stream_index].minBitrate; 476 stream_codec->minBitrate = inst.simulcastStream[stream_index].minBitrate;
430 stream_codec->qpMax = inst->simulcastStream[stream_index].qpMax; 477 stream_codec->qpMax = inst.simulcastStream[stream_index].qpMax;
431 // Settings that are based on stream/resolution. 478 // Settings that are based on stream/resolution.
432 if (stream_index == 0) { 479 const bool lowest_resolution_stream = (stream_index == 0);
480 if (lowest_resolution_stream) {
433 // Settings for lowest spatial resolutions. 481 // Settings for lowest spatial resolutions.
434 stream_codec->qpMax = kLowestResMaxQp; 482 stream_codec->qpMax = kLowestResMaxQp;
435 } 483 }
436 if (!highest_resolution_stream) { 484 if (!highest_resolution_stream) {
437 // For resolutions below CIF, set the codec |complexity| parameter to 485 // For resolutions below CIF, set the codec |complexity| parameter to
438 // kComplexityHigher, which maps to cpu_used = -4. 486 // kComplexityHigher, which maps to cpu_used = -4.
439 int pixels_per_frame = stream_codec->width * stream_codec->height; 487 int pixels_per_frame = stream_codec->width * stream_codec->height;
440 if (pixels_per_frame < 352 * 288) { 488 if (pixels_per_frame < 352 * 288) {
441 stream_codec->VP8()->complexity = webrtc::kComplexityHigher; 489 stream_codec->VP8()->complexity = webrtc::kComplexityHigher;
442 } 490 }
443 // Turn off denoising for all streams but the highest resolution. 491 // Turn off denoising for all streams but the highest resolution.
444 stream_codec->VP8()->denoisingOn = false; 492 stream_codec->VP8()->denoisingOn = false;
445 } 493 }
446 // TODO(ronghuawu): what to do with targetBitrate. 494 // TODO(ronghuawu): what to do with targetBitrate.
447 495
448 stream_codec->startBitrate = start_bitrate_kbps; 496 stream_codec->startBitrate = start_bitrate_kbps;
449 } 497 }
450 498
451 bool SimulcastEncoderAdapter::Initialized() const { 499 bool SimulcastEncoderAdapter::Initialized() const {
452 return !streaminfos_.empty(); 500 return rtc::AtomicOps::AcquireLoad(&inited_) == 1;
501 }
502
503 void SimulcastEncoderAdapter::DestroyStoredEncoders() {
504 while (!stored_encoders_.empty()) {
505 VideoEncoder* encoder = stored_encoders_.top();
506 factory_->Destroy(encoder);
507 stored_encoders_.pop();
508 }
453 } 509 }
454 510
455 bool SimulcastEncoderAdapter::SupportsNativeHandle() const { 511 bool SimulcastEncoderAdapter::SupportsNativeHandle() const {
512 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
456 // We should not be calling this method before streaminfos_ are configured. 513 // We should not be calling this method before streaminfos_ are configured.
457 RTC_DCHECK(!streaminfos_.empty()); 514 RTC_DCHECK(!streaminfos_.empty());
458 for (const auto& streaminfo : streaminfos_) { 515 for (const auto& streaminfo : streaminfos_) {
459 if (!streaminfo.encoder->SupportsNativeHandle()) 516 if (!streaminfo.encoder->SupportsNativeHandle()) {
460 return false; 517 return false;
518 }
461 } 519 }
462 return true; 520 return true;
463 } 521 }
464 522
465 VideoEncoder::ScalingSettings SimulcastEncoderAdapter::GetScalingSettings() 523 VideoEncoder::ScalingSettings SimulcastEncoderAdapter::GetScalingSettings()
466 const { 524 const {
525 // TODO(brandtr): Investigate why the sequence checker below fails on mac.
526 // RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
467 // Turn off quality scaling for simulcast. 527 // Turn off quality scaling for simulcast.
468 if (!Initialized() || NumberOfStreams(codec_) != 1) 528 if (!Initialized() || NumberOfStreams(codec_) != 1) {
469 return VideoEncoder::ScalingSettings(false); 529 return VideoEncoder::ScalingSettings(false);
530 }
470 return streaminfos_[0].encoder->GetScalingSettings(); 531 return streaminfos_[0].encoder->GetScalingSettings();
471 } 532 }
472 533
473 const char* SimulcastEncoderAdapter::ImplementationName() const { 534 const char* SimulcastEncoderAdapter::ImplementationName() const {
535 RTC_DCHECK_CALLED_SEQUENTIALLY(&encoder_queue_);
474 return implementation_name_.c_str(); 536 return implementation_name_.c_str();
475 } 537 }
476 538
477 } // namespace webrtc 539 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698