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

Side by Side Diff: webrtc/video/vie_encoder.cc

Issue 2351633002: Let ViEEncoder handle resolution changes. (Closed)
Patch Set: rebased Created 4 years, 2 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
« no previous file with comments | « webrtc/video/vie_encoder.h ('k') | webrtc/video/vie_encoder_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 23 matching lines...) Expand all
34 VideoCodecType PayloadNameToCodecType(const std::string& payload_name) { 34 VideoCodecType PayloadNameToCodecType(const std::string& payload_name) {
35 if (payload_name == "VP8") 35 if (payload_name == "VP8")
36 return kVideoCodecVP8; 36 return kVideoCodecVP8;
37 if (payload_name == "VP9") 37 if (payload_name == "VP9")
38 return kVideoCodecVP9; 38 return kVideoCodecVP9;
39 if (payload_name == "H264") 39 if (payload_name == "H264")
40 return kVideoCodecH264; 40 return kVideoCodecH264;
41 return kVideoCodecGeneric; 41 return kVideoCodecGeneric;
42 } 42 }
43 43
44 VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, 44 VideoCodec VideoEncoderConfigToVideoCodec(
45 const std::string& payload_name, 45 const VideoEncoderConfig& config,
46 int payload_type) { 46 const std::vector<VideoStream>& streams,
47 const std::vector<VideoStream>& streams = config.streams; 47 const std::string& payload_name,
48 int payload_type) {
48 static const int kEncoderMinBitrateKbps = 30; 49 static const int kEncoderMinBitrateKbps = 30;
49 RTC_DCHECK(!streams.empty()); 50 RTC_DCHECK(!streams.empty());
50 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); 51 RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0);
51 52
52 VideoCodec video_codec; 53 VideoCodec video_codec;
53 memset(&video_codec, 0, sizeof(video_codec)); 54 memset(&video_codec, 0, sizeof(video_codec));
54 video_codec.codecType = PayloadNameToCodecType(payload_name); 55 video_codec.codecType = PayloadNameToCodecType(payload_name);
55 56
56 switch (config.content_type) { 57 switch (config.content_type) {
57 case VideoEncoderConfig::ContentType::kRealtimeVideo: 58 case VideoEncoderConfig::ContentType::kRealtimeVideo:
58 video_codec.mode = kRealtimeVideo; 59 video_codec.mode = kRealtimeVideo;
59 break; 60 break;
60 case VideoEncoderConfig::ContentType::kScreen: 61 case VideoEncoderConfig::ContentType::kScreen:
61 video_codec.mode = kScreensharing; 62 video_codec.mode = kScreensharing;
62 if (config.streams.size() == 1 && 63 if (streams.size() == 1 &&
63 config.streams[0].temporal_layer_thresholds_bps.size() == 1) { 64 streams[0].temporal_layer_thresholds_bps.size() == 1) {
64 video_codec.targetBitrate = 65 video_codec.targetBitrate =
65 config.streams[0].temporal_layer_thresholds_bps[0] / 1000; 66 streams[0].temporal_layer_thresholds_bps[0] / 1000;
66 } 67 }
67 break; 68 break;
68 } 69 }
69 70
70 if (config.encoder_specific_settings) 71 if (config.encoder_specific_settings)
71 config.encoder_specific_settings->FillEncoderSpecificSettings(&video_codec); 72 config.encoder_specific_settings->FillEncoderSpecificSettings(&video_codec);
72 73
73 switch (video_codec.codecType) { 74 switch (video_codec.codecType) {
74 case kVideoCodecVP8: { 75 case kVideoCodecVP8: {
75 if (!config.encoder_specific_settings) 76 if (!config.encoder_specific_settings)
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 // Unset max bitrate -> cap to one bit per pixel. 163 // Unset max bitrate -> cap to one bit per pixel.
163 video_codec.maxBitrate = 164 video_codec.maxBitrate =
164 (video_codec.width * video_codec.height * video_codec.maxFramerate) / 165 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
165 1000; 166 1000;
166 } 167 }
167 if (video_codec.maxBitrate < kEncoderMinBitrateKbps) 168 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
168 video_codec.maxBitrate = kEncoderMinBitrateKbps; 169 video_codec.maxBitrate = kEncoderMinBitrateKbps;
169 170
170 RTC_DCHECK_GT(streams[0].max_framerate, 0); 171 RTC_DCHECK_GT(streams[0].max_framerate, 0);
171 video_codec.maxFramerate = streams[0].max_framerate; 172 video_codec.maxFramerate = streams[0].max_framerate;
172 video_codec.expect_encode_from_texture = config.expect_encode_from_texture;
173
174 return video_codec; 173 return video_codec;
175 } 174 }
176 175
177 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle 176 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle
178 // pipelining encoders better (multiple input frames before something comes 177 // pipelining encoders better (multiple input frames before something comes
179 // out). This should effectively turn off CPU adaptations for systems that 178 // out). This should effectively turn off CPU adaptations for systems that
180 // remotely cope with the load right now. 179 // remotely cope with the load right now.
181 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { 180 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) {
182 CpuOveruseOptions options; 181 CpuOveruseOptions options;
183 if (full_overuse_time) { 182 if (full_overuse_time) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 const VideoSendStream::Config::EncoderSettings& settings, 298 const VideoSendStream::Config::EncoderSettings& settings,
300 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, 299 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback,
301 LoadObserver* overuse_callback, 300 LoadObserver* overuse_callback,
302 EncodedFrameObserver* encoder_timing) 301 EncodedFrameObserver* encoder_timing)
303 : shutdown_event_(true /* manual_reset */, false), 302 : shutdown_event_(true /* manual_reset */, false),
304 number_of_cores_(number_of_cores), 303 number_of_cores_(number_of_cores),
305 source_proxy_(new VideoSourceProxy(this)), 304 source_proxy_(new VideoSourceProxy(this)),
306 sink_(nullptr), 305 sink_(nullptr),
307 settings_(settings), 306 settings_(settings),
308 codec_type_(PayloadNameToCodecType(settings.payload_name)), 307 codec_type_(PayloadNameToCodecType(settings.payload_name)),
309 vp_(VideoProcessing::Create()),
310 video_sender_(Clock::GetRealTimeClock(), this, this), 308 video_sender_(Clock::GetRealTimeClock(), this, this),
311 overuse_detector_(Clock::GetRealTimeClock(), 309 overuse_detector_(Clock::GetRealTimeClock(),
312 GetCpuOveruseOptions(settings.full_overuse_time), 310 GetCpuOveruseOptions(settings.full_overuse_time),
313 this, 311 this,
314 encoder_timing, 312 encoder_timing,
315 stats_proxy), 313 stats_proxy),
316 load_observer_(overuse_callback), 314 load_observer_(overuse_callback),
317 stats_proxy_(stats_proxy), 315 stats_proxy_(stats_proxy),
318 pre_encode_callback_(pre_encode_callback), 316 pre_encode_callback_(pre_encode_callback),
319 module_process_thread_(nullptr), 317 module_process_thread_(nullptr),
320 encoder_config_(), 318 pending_encoder_reconfiguration_(false),
321 encoder_start_bitrate_bps_(0), 319 encoder_start_bitrate_bps_(0),
322 max_data_payload_length_(0), 320 max_data_payload_length_(0),
323 last_observed_bitrate_bps_(0), 321 last_observed_bitrate_bps_(0),
324 encoder_paused_and_dropped_frame_(false), 322 encoder_paused_and_dropped_frame_(false),
325 has_received_sli_(false), 323 has_received_sli_(false),
326 picture_id_sli_(0), 324 picture_id_sli_(0),
327 has_received_rpsi_(false), 325 has_received_rpsi_(false),
328 picture_id_rpsi_(0), 326 picture_id_rpsi_(0),
329 clock_(Clock::GetRealTimeClock()), 327 clock_(Clock::GetRealTimeClock()),
330 last_captured_timestamp_(0), 328 last_captured_timestamp_(0),
331 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - 329 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
332 clock_->TimeInMilliseconds()), 330 clock_->TimeInMilliseconds()),
333 last_frame_log_ms_(clock_->TimeInMilliseconds()), 331 last_frame_log_ms_(clock_->TimeInMilliseconds()),
334 captured_frame_count_(0), 332 captured_frame_count_(0),
335 dropped_frame_count_(0), 333 dropped_frame_count_(0),
336 encoder_queue_("EncoderQueue") { 334 encoder_queue_("EncoderQueue") {
337 vp_->EnableTemporalDecimation(false);
338
339 encoder_queue_.PostTask([this, encoder_timing] { 335 encoder_queue_.PostTask([this, encoder_timing] {
340 RTC_DCHECK_RUN_ON(&encoder_queue_); 336 RTC_DCHECK_RUN_ON(&encoder_queue_);
341 video_sender_.RegisterExternalEncoder( 337 video_sender_.RegisterExternalEncoder(
342 settings_.encoder, settings_.payload_type, settings_.internal_source); 338 settings_.encoder, settings_.payload_type, settings_.internal_source);
343 overuse_detector_.StartCheckForOveruse(); 339 overuse_detector_.StartCheckForOveruse();
344 }); 340 });
345 } 341 }
346 342
347 ViEEncoder::~ViEEncoder() { 343 ViEEncoder::~ViEEncoder() {
348 RTC_DCHECK_RUN_ON(&thread_checker_); 344 RTC_DCHECK_RUN_ON(&thread_checker_);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 size_t max_data_payload_length) { 396 size_t max_data_payload_length) {
401 encoder_queue_.PostTask( 397 encoder_queue_.PostTask(
402 std::unique_ptr<rtc::QueuedTask>(new ConfigureEncoderTask( 398 std::unique_ptr<rtc::QueuedTask>(new ConfigureEncoderTask(
403 this, std::move(config), max_data_payload_length))); 399 this, std::move(config), max_data_payload_length)));
404 } 400 }
405 401
406 void ViEEncoder::ConfigureEncoderOnTaskQueue(VideoEncoderConfig config, 402 void ViEEncoder::ConfigureEncoderOnTaskQueue(VideoEncoderConfig config,
407 size_t max_data_payload_length) { 403 size_t max_data_payload_length) {
408 RTC_DCHECK_RUN_ON(&encoder_queue_); 404 RTC_DCHECK_RUN_ON(&encoder_queue_);
409 RTC_DCHECK(sink_); 405 RTC_DCHECK(sink_);
410 LOG(LS_INFO) << "ConfigureEncoderOnTaskQueue"; 406 LOG(LS_INFO) << "ConfigureEncoder requested.";
411 407
412 max_data_payload_length_ = max_data_payload_length; 408 max_data_payload_length_ = max_data_payload_length;
413 encoder_config_ = std::move(config); 409 encoder_config_ = std::move(config);
410 pending_encoder_reconfiguration_ = true;
414 411
415 VideoCodec video_codec = VideoEncoderConfigToVideoCodec( 412 // Reconfigure the encoder now if the encoder has an internal source or
416 encoder_config_, settings_.payload_name, settings_.payload_type); 413 // if this is the first time the encoder is configured.
414 // Otherwise, the reconfiguration is deferred until the next frame to minimize
415 // the number of reconfigurations. The codec configuration depends on incoming
416 // video frame size.
417 if (!last_frame_info_ || settings_.internal_source) {
418 if (!last_frame_info_) {
419 last_frame_info_ = rtc::Optional<VideoFrameInfo>(
420 VideoFrameInfo(176, 144, kVideoRotation_0, false));
421 }
422 ReconfigureEncoder();
423 }
424 }
417 425
418 // Setting target width and height for VPM. 426 void ViEEncoder::ReconfigureEncoder() {
419 RTC_CHECK_EQ(VPM_OK, 427 RTC_DCHECK_RUN_ON(&encoder_queue_);
420 vp_->SetTargetResolution(video_codec.width, video_codec.height, 428 RTC_DCHECK(pending_encoder_reconfiguration_);
421 video_codec.maxFramerate)); 429 std::vector<VideoStream> streams =
430 encoder_config_.video_stream_factory->CreateEncoderStreams(
431 last_frame_info_->width, last_frame_info_->height, encoder_config_);
422 432
423 video_codec.startBitrate = 433 VideoCodec codec = VideoEncoderConfigToVideoCodec(
424 std::max(encoder_start_bitrate_bps_ / 1000, video_codec.minBitrate); 434 encoder_config_, streams, settings_.payload_name, settings_.payload_type);
425 video_codec.startBitrate = 435
426 std::min(video_codec.startBitrate, video_codec.maxBitrate); 436 codec.startBitrate =
437 std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate);
438 codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate);
439 codec.expect_encode_from_texture = last_frame_info_->is_texture;
427 440
428 bool success = video_sender_.RegisterSendCodec( 441 bool success = video_sender_.RegisterSendCodec(
429 &video_codec, number_of_cores_, 442 &codec, number_of_cores_,
430 static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; 443 static_cast<uint32_t>(max_data_payload_length_)) == VCM_OK;
431
432 if (!success) { 444 if (!success) {
433 LOG(LS_ERROR) << "Failed to configure encoder."; 445 LOG(LS_ERROR) << "Failed to configure encoder.";
434 RTC_DCHECK(success); 446 RTC_DCHECK(success);
435 } 447 }
436 448
437 rate_allocator_.reset(new SimulcastRateAllocator(video_codec)); 449 rate_allocator_.reset(new SimulcastRateAllocator(codec));
438 if (stats_proxy_) { 450 if (stats_proxy_) {
439 stats_proxy_->OnEncoderReconfigured(encoder_config_, 451 stats_proxy_->OnEncoderReconfigured(encoder_config_,
440 rate_allocator_->GetPreferedBitrate()); 452 rate_allocator_->GetPreferedBitrate());
441 } 453 }
442 454
455 pending_encoder_reconfiguration_ = false;
456 if (stats_proxy_) {
457 stats_proxy_->OnEncoderReconfigured(encoder_config_,
458 rate_allocator_->GetPreferedBitrate());
459 }
443 sink_->OnEncoderConfigurationChanged( 460 sink_->OnEncoderConfigurationChanged(
444 encoder_config_.streams, encoder_config_.min_transmit_bitrate_bps); 461 std::move(streams), encoder_config_.min_transmit_bitrate_bps);
445 } 462 }
446 463
447 void ViEEncoder::OnFrame(const VideoFrame& video_frame) { 464 void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
448 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_); 465 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_);
449 stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height()); 466 stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height());
450 467
451 VideoFrame incoming_frame = video_frame; 468 VideoFrame incoming_frame = video_frame;
452 469
453 // Local time in webrtc time base. 470 // Local time in webrtc time base.
454 int64_t current_time = clock_->TimeInMilliseconds(); 471 int64_t current_time = clock_->TimeInMilliseconds();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 } 534 }
518 encoder_paused_and_dropped_frame_ = false; 535 encoder_paused_and_dropped_frame_ = false;
519 } 536 }
520 537
521 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, 538 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
522 int64_t time_when_posted_in_ms) { 539 int64_t time_when_posted_in_ms) {
523 RTC_DCHECK_RUN_ON(&encoder_queue_); 540 RTC_DCHECK_RUN_ON(&encoder_queue_);
524 if (pre_encode_callback_) 541 if (pre_encode_callback_)
525 pre_encode_callback_->OnFrame(video_frame); 542 pre_encode_callback_->OnFrame(video_frame);
526 543
544 if (video_frame.width() != last_frame_info_->width ||
545 video_frame.height() != last_frame_info_->height ||
546 video_frame.rotation() != last_frame_info_->rotation ||
547 video_frame.is_texture() != last_frame_info_->is_texture) {
548 pending_encoder_reconfiguration_ = true;
549 last_frame_info_ = rtc::Optional<VideoFrameInfo>(
550 VideoFrameInfo(video_frame.width(), video_frame.height(),
551 video_frame.rotation(), video_frame.is_texture()));
552 LOG(LS_INFO) << "Video frame parameters changed: dimensions="
553 << last_frame_info_->width << "x" << last_frame_info_->height
554 << ", rotation=" << last_frame_info_->rotation
555 << ", texture=" << last_frame_info_->is_texture;
556 }
557
558 if (pending_encoder_reconfiguration_) {
559 ReconfigureEncoder();
560 }
561
527 if (EncoderPaused()) { 562 if (EncoderPaused()) {
528 TraceFrameDropStart(); 563 TraceFrameDropStart();
529 return; 564 return;
530 } 565 }
531 TraceFrameDropEnd(); 566 TraceFrameDropEnd();
532 567
533 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), 568 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
534 "Encode"); 569 "Encode");
535 const VideoFrame* frame_to_send = &video_frame;
536 // TODO(wuchengli): support texture frames.
537 if (!video_frame.video_frame_buffer()->native_handle()) {
538 // Pass frame via preprocessor.
539 frame_to_send = vp_->PreprocessFrame(video_frame);
540 if (!frame_to_send) {
541 // Drop this frame, or there was an error processing it.
542 return;
543 }
544 }
545 570
546 overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms); 571 overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms);
547 572
548 if (codec_type_ == webrtc::kVideoCodecVP8) { 573 if (codec_type_ == webrtc::kVideoCodecVP8) {
549 webrtc::CodecSpecificInfo codec_specific_info; 574 webrtc::CodecSpecificInfo codec_specific_info;
550 codec_specific_info.codecType = webrtc::kVideoCodecVP8; 575 codec_specific_info.codecType = webrtc::kVideoCodecVP8;
551 576
552 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI = 577 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
553 has_received_rpsi_; 578 has_received_rpsi_;
554 codec_specific_info.codecSpecific.VP8.hasReceivedSLI = 579 codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
555 has_received_sli_; 580 has_received_sli_;
556 codec_specific_info.codecSpecific.VP8.pictureIdRPSI = 581 codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
557 picture_id_rpsi_; 582 picture_id_rpsi_;
558 codec_specific_info.codecSpecific.VP8.pictureIdSLI = 583 codec_specific_info.codecSpecific.VP8.pictureIdSLI =
559 picture_id_sli_; 584 picture_id_sli_;
560 has_received_sli_ = false; 585 has_received_sli_ = false;
561 has_received_rpsi_ = false; 586 has_received_rpsi_ = false;
562 587
563 video_sender_.AddVideoFrame(*frame_to_send, &codec_specific_info); 588 video_sender_.AddVideoFrame(video_frame, &codec_specific_info);
564 return; 589 return;
565 } 590 }
566 video_sender_.AddVideoFrame(*frame_to_send, nullptr); 591 video_sender_.AddVideoFrame(video_frame, nullptr);
567 } 592 }
568 593
569 void ViEEncoder::SendKeyFrame() { 594 void ViEEncoder::SendKeyFrame() {
570 if (!encoder_queue_.IsCurrent()) { 595 if (!encoder_queue_.IsCurrent()) {
571 encoder_queue_.PostTask([this] { SendKeyFrame(); }); 596 encoder_queue_.PostTask([this] { SendKeyFrame(); });
572 return; 597 return;
573 } 598 }
574 RTC_DCHECK_RUN_ON(&encoder_queue_); 599 RTC_DCHECK_RUN_ON(&encoder_queue_);
575 video_sender_.IntraFrameRequest(0); 600 video_sender_.IntraFrameRequest(0);
576 } 601 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 load_observer_->OnLoadUpdate(LoadObserver::kOveruse); 704 load_observer_->OnLoadUpdate(LoadObserver::kOveruse);
680 } 705 }
681 706
682 void ViEEncoder::NormalUsage() { 707 void ViEEncoder::NormalUsage() {
683 RTC_DCHECK_RUN_ON(&encoder_queue_); 708 RTC_DCHECK_RUN_ON(&encoder_queue_);
684 if (load_observer_) 709 if (load_observer_)
685 load_observer_->OnLoadUpdate(LoadObserver::kUnderuse); 710 load_observer_->OnLoadUpdate(LoadObserver::kUnderuse);
686 } 711 }
687 712
688 } // namespace webrtc 713 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/video/vie_encoder.h ('k') | webrtc/video/vie_encoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698