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