OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 VP8Encoder* VP8Encoder::Create() { | 106 VP8Encoder* VP8Encoder::Create() { |
107 return new VP8EncoderImpl(); | 107 return new VP8EncoderImpl(); |
108 } | 108 } |
109 | 109 |
110 VP8Decoder* VP8Decoder::Create() { | 110 VP8Decoder* VP8Decoder::Create() { |
111 return new VP8DecoderImpl(); | 111 return new VP8DecoderImpl(); |
112 } | 112 } |
113 | 113 |
114 VP8EncoderImpl::VP8EncoderImpl() | 114 VP8EncoderImpl::VP8EncoderImpl() |
115 : encoded_complete_callback_(nullptr), | 115 : encoded_complete_callback_(nullptr), |
| 116 rate_allocator_(new SimulcastRateAllocator(codec_)), |
116 inited_(false), | 117 inited_(false), |
117 timestamp_(0), | 118 timestamp_(0), |
118 feedback_mode_(false), | 119 feedback_mode_(false), |
119 qp_max_(56), // Setting for max quantizer. | 120 qp_max_(56), // Setting for max quantizer. |
120 cpu_speed_default_(-6), | 121 cpu_speed_default_(-6), |
121 number_of_cores_(0), | 122 number_of_cores_(0), |
122 rc_max_intra_target_(0), | 123 rc_max_intra_target_(0), |
123 token_partitions_(VP8_ONE_TOKENPARTITION), | 124 token_partitions_(VP8_ONE_TOKENPARTITION), |
124 down_scale_requested_(false), | 125 down_scale_requested_(false), |
125 down_scale_bitrate_(0), | 126 down_scale_bitrate_(0), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 raw_images_.pop_back(); | 168 raw_images_.pop_back(); |
168 } | 169 } |
169 while (!temporal_layers_.empty()) { | 170 while (!temporal_layers_.empty()) { |
170 delete temporal_layers_.back(); | 171 delete temporal_layers_.back(); |
171 temporal_layers_.pop_back(); | 172 temporal_layers_.pop_back(); |
172 } | 173 } |
173 inited_ = false; | 174 inited_ = false; |
174 return ret_val; | 175 return ret_val; |
175 } | 176 } |
176 | 177 |
177 int VP8EncoderImpl::SetRateAllocation(const BitrateAllocation& bitrate, | 178 int VP8EncoderImpl::SetRates(uint32_t new_bitrate_kbit, |
178 uint32_t new_framerate) { | 179 uint32_t new_framerate) { |
179 if (!inited_) | 180 if (!inited_) { |
180 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; | 181 return WEBRTC_VIDEO_CODEC_UNINITIALIZED; |
181 | 182 } |
182 if (encoders_[0].err) | 183 if (encoders_[0].err) { |
183 return WEBRTC_VIDEO_CODEC_ERROR; | 184 return WEBRTC_VIDEO_CODEC_ERROR; |
184 | 185 } |
185 if (new_framerate < 1) | 186 if (new_framerate < 1) { |
186 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 187 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
187 | |
188 if (bitrate.get_sum_bps() == 0) { | |
189 // Encoder paused, turn off all encoding. | |
190 const int num_streams = static_cast<size_t>(encoders_.size()); | |
191 for (int i = 0; i < num_streams; ++i) | |
192 SetStreamState(false, i); | |
193 return WEBRTC_VIDEO_CODEC_OK; | |
194 } | 188 } |
195 | 189 if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) { |
196 // At this point, bitrate allocation should already match codec settings. | 190 new_bitrate_kbit = codec_.maxBitrate; |
197 if (codec_.maxBitrate > 0) | 191 } |
198 RTC_DCHECK_LE(bitrate.get_sum_kbps(), codec_.maxBitrate); | 192 if (new_bitrate_kbit < codec_.minBitrate) { |
199 RTC_DCHECK_GE(bitrate.get_sum_kbps(), codec_.minBitrate); | 193 new_bitrate_kbit = codec_.minBitrate; |
200 if (codec_.numberOfSimulcastStreams > 0) | 194 } |
201 RTC_DCHECK_GE(bitrate.get_sum_kbps(), codec_.simulcastStream[0].minBitrate); | 195 if (codec_.numberOfSimulcastStreams > 0 && |
202 | 196 new_bitrate_kbit < codec_.simulcastStream[0].minBitrate) { |
| 197 new_bitrate_kbit = codec_.simulcastStream[0].minBitrate; |
| 198 } |
203 codec_.maxFramerate = new_framerate; | 199 codec_.maxFramerate = new_framerate; |
204 | 200 |
205 if (encoders_.size() == 1) { | 201 if (encoders_.size() == 1) { |
206 // 1:1. | 202 // 1:1. |
207 // Calculate a rough limit for when to trigger a potental down scale. | 203 // Calculate a rough limit for when to trigger a potental down scale. |
208 uint32_t k_pixels_per_frame = codec_.width * codec_.height / 1000; | 204 uint32_t k_pixels_per_frame = codec_.width * codec_.height / 1000; |
209 // TODO(pwestin): we currently lack CAMA, this is a temporary fix to work | 205 // TODO(pwestin): we currently lack CAMA, this is a temporary fix to work |
210 // around the current limitations. | 206 // around the current limitations. |
211 // Only trigger keyframes if we are allowed to scale down. | 207 // Only trigger keyframes if we are allowed to scale down. |
212 if (configurations_[0].rc_resize_allowed) { | 208 if (configurations_[0].rc_resize_allowed) { |
213 if (!down_scale_requested_) { | 209 if (!down_scale_requested_) { |
214 if (k_pixels_per_frame > bitrate.get_sum_kbps()) { | 210 if (k_pixels_per_frame > new_bitrate_kbit) { |
215 down_scale_requested_ = true; | 211 down_scale_requested_ = true; |
216 down_scale_bitrate_ = bitrate.get_sum_kbps(); | 212 down_scale_bitrate_ = new_bitrate_kbit; |
217 key_frame_request_[0] = true; | 213 key_frame_request_[0] = true; |
218 } | 214 } |
219 } else { | 215 } else { |
220 if (bitrate.get_sum_kbps() > (2 * down_scale_bitrate_) || | 216 if (new_bitrate_kbit > (2 * down_scale_bitrate_) || |
221 bitrate.get_sum_kbps() < (down_scale_bitrate_ / 2)) { | 217 new_bitrate_kbit < (down_scale_bitrate_ / 2)) { |
222 down_scale_requested_ = false; | 218 down_scale_requested_ = false; |
223 } | 219 } |
224 } | 220 } |
225 } | 221 } |
226 } else { | 222 } else { |
227 // If we have more than 1 stream, reduce the qp_max for the low resolution | 223 // If we have more than 1 stream, reduce the qp_max for the low resolution |
228 // stream if frame rate is not too low. The trade-off with lower qp_max is | 224 // stream if frame rate is not too low. The trade-off with lower qp_max is |
229 // possibly more dropped frames, so we only do this if the frame rate is | 225 // possibly more dropped frames, so we only do this if the frame rate is |
230 // above some threshold (base temporal layer is down to 1/4 for 3 layers). | 226 // above some threshold (base temporal layer is down to 1/4 for 3 layers). |
231 // We may want to condition this on bitrate later. | 227 // We may want to condition this on bitrate later. |
232 if (new_framerate > 20) { | 228 if (new_framerate > 20) { |
233 configurations_[encoders_.size() - 1].rc_max_quantizer = 45; | 229 configurations_[encoders_.size() - 1].rc_max_quantizer = 45; |
234 } else { | 230 } else { |
235 // Go back to default value set in InitEncode. | 231 // Go back to default value set in InitEncode. |
236 configurations_[encoders_.size() - 1].rc_max_quantizer = qp_max_; | 232 configurations_[encoders_.size() - 1].rc_max_quantizer = qp_max_; |
237 } | 233 } |
238 } | 234 } |
239 | 235 |
| 236 std::vector<uint32_t> stream_bitrates = |
| 237 rate_allocator_->GetAllocation(new_bitrate_kbit); |
240 size_t stream_idx = encoders_.size() - 1; | 238 size_t stream_idx = encoders_.size() - 1; |
241 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { | 239 for (size_t i = 0; i < encoders_.size(); ++i, --stream_idx) { |
242 unsigned int target_bitrate_kbps = | 240 if (encoders_.size() > 1) |
243 bitrate.GetSpatialLayerSum(stream_idx) / 1000; | 241 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
244 | 242 |
245 bool send_stream = target_bitrate_kbps > 0; | 243 unsigned int target_bitrate = stream_bitrates[stream_idx]; |
246 if (send_stream || encoders_.size() > 1) | 244 unsigned int max_bitrate = codec_.maxBitrate; |
247 SetStreamState(send_stream, stream_idx); | 245 int framerate = new_framerate; |
248 | 246 // TODO(holmer): This is a temporary hack for screensharing, where we |
249 configurations_[i].rc_target_bitrate = target_bitrate_kbps; | 247 // interpret the startBitrate as the encoder target bitrate. This is |
250 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); | 248 // to allow for a different max bitrate, so if the codec can't meet |
251 | 249 // the target we still allow it to overshoot up to the max before dropping |
| 250 // frames. This hack should be improved. |
| 251 if (codec_.targetBitrate > 0 && |
| 252 (codec_.VP8()->numberOfTemporalLayers == 2 || |
| 253 codec_.simulcastStream[0].numberOfTemporalLayers == 2)) { |
| 254 int tl0_bitrate = std::min(codec_.targetBitrate, target_bitrate); |
| 255 max_bitrate = std::min(codec_.maxBitrate, target_bitrate); |
| 256 target_bitrate = tl0_bitrate; |
| 257 } |
| 258 configurations_[i].rc_target_bitrate = target_bitrate; |
| 259 temporal_layers_[stream_idx]->ConfigureBitrates( |
| 260 target_bitrate, max_bitrate, framerate, &configurations_[i]); |
252 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { | 261 if (vpx_codec_enc_config_set(&encoders_[i], &configurations_[i])) { |
253 return WEBRTC_VIDEO_CODEC_ERROR; | 262 return WEBRTC_VIDEO_CODEC_ERROR; |
254 } | 263 } |
255 } | 264 } |
256 quality_scaler_.ReportFramerate(new_framerate); | 265 quality_scaler_.ReportFramerate(new_framerate); |
257 return WEBRTC_VIDEO_CODEC_OK; | 266 return WEBRTC_VIDEO_CODEC_OK; |
258 } | 267 } |
259 | 268 |
260 void VP8EncoderImpl::OnDroppedFrame() { | 269 void VP8EncoderImpl::OnDroppedFrame() { |
261 if (quality_scaler_enabled_) | 270 if (quality_scaler_enabled_) |
262 quality_scaler_.ReportDroppedFrame(); | 271 quality_scaler_.ReportDroppedFrame(); |
263 } | 272 } |
264 | 273 |
265 const char* VP8EncoderImpl::ImplementationName() const { | 274 const char* VP8EncoderImpl::ImplementationName() const { |
266 return "libvpx"; | 275 return "libvpx"; |
267 } | 276 } |
268 | 277 |
269 void VP8EncoderImpl::SetStreamState(bool send_stream, | 278 void VP8EncoderImpl::SetStreamState(bool send_stream, |
270 int stream_idx) { | 279 int stream_idx) { |
271 if (send_stream && !send_stream_[stream_idx]) { | 280 if (send_stream && !send_stream_[stream_idx]) { |
272 // Need a key frame if we have not sent this stream before. | 281 // Need a key frame if we have not sent this stream before. |
273 key_frame_request_[stream_idx] = true; | 282 key_frame_request_[stream_idx] = true; |
274 } | 283 } |
275 send_stream_[stream_idx] = send_stream; | 284 send_stream_[stream_idx] = send_stream; |
276 } | 285 } |
277 | 286 |
278 void VP8EncoderImpl::SetupTemporalLayers(int num_streams, | 287 void VP8EncoderImpl::SetupTemporalLayers(int num_streams, |
279 int num_temporal_layers, | 288 int num_temporal_layers, |
280 const VideoCodec& codec) { | 289 const VideoCodec& codec) { |
281 RTC_DCHECK(codec.codecSpecific.VP8.tl_factory != nullptr); | 290 TemporalLayersFactory default_factory; |
282 const TemporalLayersFactory* tl_factory = codec.codecSpecific.VP8.tl_factory; | 291 const TemporalLayersFactory* tl_factory = codec.VP8().tl_factory; |
| 292 if (!tl_factory) |
| 293 tl_factory = &default_factory; |
283 if (num_streams == 1) { | 294 if (num_streams == 1) { |
284 temporal_layers_.push_back( | 295 if (codec.mode == kScreensharing) { |
285 tl_factory->Create(0, num_temporal_layers, rand())); | 296 // Special mode when screensharing on a single stream. |
| 297 temporal_layers_.push_back(new ScreenshareLayers( |
| 298 num_temporal_layers, rand(), webrtc::Clock::GetRealTimeClock())); |
| 299 } else { |
| 300 temporal_layers_.push_back( |
| 301 tl_factory->Create(num_temporal_layers, rand())); |
| 302 } |
286 } else { | 303 } else { |
287 for (int i = 0; i < num_streams; ++i) { | 304 for (int i = 0; i < num_streams; ++i) { |
288 RTC_CHECK_GT(num_temporal_layers, 0); | 305 // TODO(andresp): crash if layers is invalid. |
289 int layers = std::max(static_cast<uint8_t>(1), | 306 int layers = codec.simulcastStream[i].numberOfTemporalLayers; |
290 codec.simulcastStream[i].numberOfTemporalLayers); | 307 if (layers < 1) |
291 temporal_layers_.push_back(tl_factory->Create(i, layers, rand())); | 308 layers = 1; |
| 309 temporal_layers_.push_back(tl_factory->Create(layers, rand())); |
292 } | 310 } |
293 } | 311 } |
294 } | 312 } |
295 | 313 |
296 int VP8EncoderImpl::InitEncode(const VideoCodec* inst, | 314 int VP8EncoderImpl::InitEncode(const VideoCodec* inst, |
297 int number_of_cores, | 315 int number_of_cores, |
298 size_t /*maxPayloadSize */) { | 316 size_t /*maxPayloadSize */) { |
299 if (inst == NULL) { | 317 if (inst == NULL) { |
300 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 318 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
301 } | 319 } |
(...skipping 24 matching lines...) Expand all Loading... |
326 int number_of_streams = NumberOfStreams(*inst); | 344 int number_of_streams = NumberOfStreams(*inst); |
327 bool doing_simulcast = (number_of_streams > 1); | 345 bool doing_simulcast = (number_of_streams > 1); |
328 | 346 |
329 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) { | 347 if (doing_simulcast && !ValidSimulcastResolutions(*inst, number_of_streams)) { |
330 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; | 348 return WEBRTC_VIDEO_CODEC_ERR_PARAMETER; |
331 } | 349 } |
332 | 350 |
333 int num_temporal_layers = | 351 int num_temporal_layers = |
334 doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers | 352 doing_simulcast ? inst->simulcastStream[0].numberOfTemporalLayers |
335 : inst->VP8().numberOfTemporalLayers; | 353 : inst->VP8().numberOfTemporalLayers; |
336 RTC_DCHECK_GT(num_temporal_layers, 0); | |
337 | 354 |
| 355 // TODO(andresp): crash if num temporal layers is bananas. |
| 356 if (num_temporal_layers < 1) |
| 357 num_temporal_layers = 1; |
338 SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst); | 358 SetupTemporalLayers(number_of_streams, num_temporal_layers, *inst); |
339 | 359 |
340 feedback_mode_ = inst->VP8().feedbackModeOn; | 360 feedback_mode_ = inst->VP8().feedbackModeOn; |
341 | 361 |
342 number_of_cores_ = number_of_cores; | 362 number_of_cores_ = number_of_cores; |
343 timestamp_ = 0; | 363 timestamp_ = 0; |
344 codec_ = *inst; | 364 codec_ = *inst; |
| 365 rate_allocator_.reset(new SimulcastRateAllocator(codec_)); |
345 | 366 |
346 // Code expects simulcastStream resolutions to be correct, make sure they are | 367 // Code expects simulcastStream resolutions to be correct, make sure they are |
347 // filled even when there are no simulcast layers. | 368 // filled even when there are no simulcast layers. |
348 if (codec_.numberOfSimulcastStreams == 0) { | 369 if (codec_.numberOfSimulcastStreams == 0) { |
349 codec_.simulcastStream[0].width = codec_.width; | 370 codec_.simulcastStream[0].width = codec_.width; |
350 codec_.simulcastStream[0].height = codec_.height; | 371 codec_.simulcastStream[0].height = codec_.height; |
351 } | 372 } |
352 | 373 |
353 picture_id_.resize(number_of_streams); | 374 picture_id_.resize(number_of_streams); |
354 last_key_frame_picture_id_.resize(number_of_streams); | 375 last_key_frame_picture_id_.resize(number_of_streams); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 // TODO(fbarchard): Consider number of Simulcast layers. | 507 // TODO(fbarchard): Consider number of Simulcast layers. |
487 configurations_[0].g_threads = NumberOfThreads( | 508 configurations_[0].g_threads = NumberOfThreads( |
488 configurations_[0].g_w, configurations_[0].g_h, number_of_cores); | 509 configurations_[0].g_w, configurations_[0].g_h, number_of_cores); |
489 | 510 |
490 // Creating a wrapper to the image - setting image data to NULL. | 511 // Creating a wrapper to the image - setting image data to NULL. |
491 // Actual pointer will be set in encode. Setting align to 1, as it | 512 // Actual pointer will be set in encode. Setting align to 1, as it |
492 // is meaningless (no memory allocation is done here). | 513 // is meaningless (no memory allocation is done here). |
493 vpx_img_wrap(&raw_images_[0], VPX_IMG_FMT_I420, inst->width, inst->height, 1, | 514 vpx_img_wrap(&raw_images_[0], VPX_IMG_FMT_I420, inst->width, inst->height, 1, |
494 NULL); | 515 NULL); |
495 | 516 |
496 // Note the order we use is different from webm, we have lowest resolution | 517 if (encoders_.size() == 1) { |
497 // at position 0 and they have highest resolution at position 0. | 518 configurations_[0].rc_target_bitrate = inst->startBitrate; |
498 int stream_idx = encoders_.size() - 1; | 519 temporal_layers_[0]->ConfigureBitrates(inst->startBitrate, inst->maxBitrate, |
499 SimulcastRateAllocator init_allocator(codec_, nullptr); | 520 inst->maxFramerate, |
500 BitrateAllocation allocation = init_allocator.GetAllocation( | 521 &configurations_[0]); |
501 inst->startBitrate * 1000, inst->maxFramerate); | 522 } else { |
502 std::vector<uint32_t> stream_bitrates; | 523 // Note the order we use is different from webm, we have lowest resolution |
503 for (int i = 0; i == 0 || i < inst->numberOfSimulcastStreams; ++i) { | 524 // at position 0 and they have highest resolution at position 0. |
504 uint32_t bitrate = allocation.GetSpatialLayerSum(i) / 1000; | 525 int stream_idx = encoders_.size() - 1; |
505 stream_bitrates.push_back(bitrate); | 526 std::vector<uint32_t> stream_bitrates = |
506 } | 527 rate_allocator_->GetAllocation(inst->startBitrate); |
| 528 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
| 529 configurations_[0].rc_target_bitrate = stream_bitrates[stream_idx]; |
| 530 temporal_layers_[stream_idx]->ConfigureBitrates( |
| 531 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, |
| 532 &configurations_[0]); |
| 533 --stream_idx; |
| 534 for (size_t i = 1; i < encoders_.size(); ++i, --stream_idx) { |
| 535 memcpy(&configurations_[i], &configurations_[0], |
| 536 sizeof(configurations_[0])); |
507 | 537 |
508 configurations_[0].rc_target_bitrate = stream_bitrates[stream_idx]; | 538 configurations_[i].g_w = inst->simulcastStream[stream_idx].width; |
509 temporal_layers_[stream_idx]->OnRatesUpdated( | 539 configurations_[i].g_h = inst->simulcastStream[stream_idx].height; |
510 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); | |
511 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[0]); | |
512 --stream_idx; | |
513 for (size_t i = 1; i < encoders_.size(); ++i, --stream_idx) { | |
514 memcpy(&configurations_[i], &configurations_[0], | |
515 sizeof(configurations_[0])); | |
516 | 540 |
517 configurations_[i].g_w = inst->simulcastStream[stream_idx].width; | 541 // Use 1 thread for lower resolutions. |
518 configurations_[i].g_h = inst->simulcastStream[stream_idx].height; | 542 configurations_[i].g_threads = 1; |
519 | 543 |
520 // Use 1 thread for lower resolutions. | 544 // Setting alignment to 32 - as that ensures at least 16 for all |
521 configurations_[i].g_threads = 1; | 545 // planes (32 for Y, 16 for U,V). Libvpx sets the requested stride for |
522 | 546 // the y plane, but only half of it to the u and v planes. |
523 // Setting alignment to 32 - as that ensures at least 16 for all | 547 vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420, |
524 // planes (32 for Y, 16 for U,V). Libvpx sets the requested stride for | 548 inst->simulcastStream[stream_idx].width, |
525 // the y plane, but only half of it to the u and v planes. | 549 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); |
526 vpx_img_alloc(&raw_images_[i], VPX_IMG_FMT_I420, | 550 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); |
527 inst->simulcastStream[stream_idx].width, | 551 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; |
528 inst->simulcastStream[stream_idx].height, kVp832ByteAlign); | 552 temporal_layers_[stream_idx]->ConfigureBitrates( |
529 SetStreamState(stream_bitrates[stream_idx] > 0, stream_idx); | 553 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate, |
530 configurations_[i].rc_target_bitrate = stream_bitrates[stream_idx]; | 554 &configurations_[i]); |
531 temporal_layers_[stream_idx]->OnRatesUpdated( | 555 } |
532 stream_bitrates[stream_idx], inst->maxBitrate, inst->maxFramerate); | |
533 temporal_layers_[stream_idx]->UpdateConfiguration(&configurations_[i]); | |
534 } | 556 } |
535 | 557 |
536 rps_.Init(); | 558 rps_.Init(); |
537 quality_scaler_.Init(codec_.codecType, codec_.startBitrate, codec_.width, | 559 quality_scaler_.Init(codec_.codecType, codec_.startBitrate, codec_.width, |
538 codec_.height, codec_.maxFramerate); | 560 codec_.height, codec_.maxFramerate); |
539 | 561 |
540 // Only apply scaling to improve for single-layer streams. The scaling metrics | 562 // Only apply scaling to improve for single-layer streams. The scaling metrics |
541 // use frame drops as a signal and is only applicable when we drop frames. | 563 // use frame drops as a signal and is only applicable when we drop frames. |
542 quality_scaler_enabled_ = encoders_.size() == 1 && | 564 quality_scaler_enabled_ = encoders_.size() == 1 && |
543 configurations_[0].rc_dropframe_thresh > 0 && | 565 configurations_[0].rc_dropframe_thresh > 0 && |
(...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1312 return -1; | 1334 return -1; |
1313 } | 1335 } |
1314 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != | 1336 if (vpx_codec_control(copy->decoder_, VP8_SET_REFERENCE, ref_frame_) != |
1315 VPX_CODEC_OK) { | 1337 VPX_CODEC_OK) { |
1316 return -1; | 1338 return -1; |
1317 } | 1339 } |
1318 return 0; | 1340 return 0; |
1319 } | 1341 } |
1320 | 1342 |
1321 } // namespace webrtc | 1343 } // namespace webrtc |
OLD | NEW |