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

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

Issue 2351633002: Let ViEEncoder handle resolution changes. (Closed)
Patch Set: fix line ending. 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
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 switch (video_codec.codecType) { 71 switch (video_codec.codecType) {
71 case kVideoCodecVP8: { 72 case kVideoCodecVP8: {
72 if (config.encoder_specific_settings) { 73 if (config.encoder_specific_settings) {
73 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>( 74 video_codec.codecSpecific.VP8 = *reinterpret_cast<const VideoCodecVP8*>(
74 config.encoder_specific_settings); 75 config.encoder_specific_settings);
75 } else { 76 } else {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 // Unset max bitrate -> cap to one bit per pixel. 173 // Unset max bitrate -> cap to one bit per pixel.
173 video_codec.maxBitrate = 174 video_codec.maxBitrate =
174 (video_codec.width * video_codec.height * video_codec.maxFramerate) / 175 (video_codec.width * video_codec.height * video_codec.maxFramerate) /
175 1000; 176 1000;
176 } 177 }
177 if (video_codec.maxBitrate < kEncoderMinBitrateKbps) 178 if (video_codec.maxBitrate < kEncoderMinBitrateKbps)
178 video_codec.maxBitrate = kEncoderMinBitrateKbps; 179 video_codec.maxBitrate = kEncoderMinBitrateKbps;
179 180
180 RTC_DCHECK_GT(streams[0].max_framerate, 0); 181 RTC_DCHECK_GT(streams[0].max_framerate, 0);
181 video_codec.maxFramerate = streams[0].max_framerate; 182 video_codec.maxFramerate = streams[0].max_framerate;
182 video_codec.expect_encode_from_texture = config.expect_encode_from_texture;
183
184 return video_codec; 183 return video_codec;
185 } 184 }
186 185
187 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle 186 // TODO(pbos): Lower these thresholds (to closer to 100%) when we handle
188 // pipelining encoders better (multiple input frames before something comes 187 // pipelining encoders better (multiple input frames before something comes
189 // out). This should effectively turn off CPU adaptations for systems that 188 // out). This should effectively turn off CPU adaptations for systems that
190 // remotely cope with the load right now. 189 // remotely cope with the load right now.
191 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) { 190 CpuOveruseOptions GetCpuOveruseOptions(bool full_overuse_time) {
192 CpuOveruseOptions options; 191 CpuOveruseOptions options;
193 if (full_overuse_time) { 192 if (full_overuse_time) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 const VideoSendStream::Config::EncoderSettings& settings, 308 const VideoSendStream::Config::EncoderSettings& settings,
310 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, 309 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback,
311 LoadObserver* overuse_callback, 310 LoadObserver* overuse_callback,
312 EncodedFrameObserver* encoder_timing) 311 EncodedFrameObserver* encoder_timing)
313 : shutdown_event_(true /* manual_reset */, false), 312 : shutdown_event_(true /* manual_reset */, false),
314 number_of_cores_(number_of_cores), 313 number_of_cores_(number_of_cores),
315 source_proxy_(new VideoSourceProxy(this)), 314 source_proxy_(new VideoSourceProxy(this)),
316 sink_(nullptr), 315 sink_(nullptr),
317 settings_(settings), 316 settings_(settings),
318 codec_type_(PayloadNameToCodecType(settings.payload_name)), 317 codec_type_(PayloadNameToCodecType(settings.payload_name)),
319 vp_(VideoProcessing::Create()),
320 video_sender_(Clock::GetRealTimeClock(), this, this), 318 video_sender_(Clock::GetRealTimeClock(), this, this),
321 overuse_detector_(Clock::GetRealTimeClock(), 319 overuse_detector_(Clock::GetRealTimeClock(),
322 GetCpuOveruseOptions(settings.full_overuse_time), 320 GetCpuOveruseOptions(settings.full_overuse_time),
323 this, 321 this,
324 encoder_timing, 322 encoder_timing,
325 stats_proxy), 323 stats_proxy),
326 load_observer_(overuse_callback), 324 load_observer_(overuse_callback),
327 stats_proxy_(stats_proxy), 325 stats_proxy_(stats_proxy),
328 pre_encode_callback_(pre_encode_callback), 326 pre_encode_callback_(pre_encode_callback),
329 module_process_thread_(nullptr), 327 module_process_thread_(nullptr),
330 encoder_config_(), 328 pending_encoder_reconfiguration_(false),
331 encoder_start_bitrate_bps_(0), 329 encoder_start_bitrate_bps_(0),
332 max_data_payload_length_(0), 330 max_data_payload_length_(0),
333 last_observed_bitrate_bps_(0), 331 last_observed_bitrate_bps_(0),
334 encoder_paused_and_dropped_frame_(false), 332 encoder_paused_and_dropped_frame_(false),
335 has_received_sli_(false), 333 has_received_sli_(false),
336 picture_id_sli_(0), 334 picture_id_sli_(0),
337 has_received_rpsi_(false), 335 has_received_rpsi_(false),
338 picture_id_rpsi_(0), 336 picture_id_rpsi_(0),
339 clock_(Clock::GetRealTimeClock()), 337 clock_(Clock::GetRealTimeClock()),
340 last_captured_timestamp_(0), 338 last_captured_timestamp_(0),
341 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() - 339 delta_ntp_internal_ms_(clock_->CurrentNtpInMilliseconds() -
342 clock_->TimeInMilliseconds()), 340 clock_->TimeInMilliseconds()),
343 last_frame_log_ms_(clock_->TimeInMilliseconds()), 341 last_frame_log_ms_(clock_->TimeInMilliseconds()),
344 captured_frame_count_(0), 342 captured_frame_count_(0),
345 dropped_frame_count_(0), 343 dropped_frame_count_(0),
346 encoder_queue_("EncoderQueue") { 344 encoder_queue_("EncoderQueue") {
347 vp_->EnableTemporalDecimation(false);
348
349 encoder_queue_.PostTask([this, encoder_timing] { 345 encoder_queue_.PostTask([this, encoder_timing] {
350 RTC_DCHECK_RUN_ON(&encoder_queue_); 346 RTC_DCHECK_RUN_ON(&encoder_queue_);
351 video_sender_.RegisterExternalEncoder( 347 video_sender_.RegisterExternalEncoder(
352 settings_.encoder, settings_.payload_type, settings_.internal_source); 348 settings_.encoder, settings_.payload_type, settings_.internal_source);
353 overuse_detector_.StartCheckForOveruse(); 349 overuse_detector_.StartCheckForOveruse();
354 }); 350 });
355 } 351 }
356 352
357 ViEEncoder::~ViEEncoder() { 353 ViEEncoder::~ViEEncoder() {
358 RTC_DCHECK_RUN_ON(&thread_checker_); 354 RTC_DCHECK_RUN_ON(&thread_checker_);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
410 size_t max_data_payload_length) { 406 size_t max_data_payload_length) {
411 encoder_queue_.PostTask( 407 encoder_queue_.PostTask(
412 std::unique_ptr<rtc::QueuedTask>(new ConfigureEncoderTask( 408 std::unique_ptr<rtc::QueuedTask>(new ConfigureEncoderTask(
413 this, std::move(config), max_data_payload_length))); 409 this, std::move(config), max_data_payload_length)));
414 } 410 }
415 411
416 void ViEEncoder::ConfigureEncoderOnTaskQueue(VideoEncoderConfig config, 412 void ViEEncoder::ConfigureEncoderOnTaskQueue(VideoEncoderConfig config,
417 size_t max_data_payload_length) { 413 size_t max_data_payload_length) {
418 RTC_DCHECK_RUN_ON(&encoder_queue_); 414 RTC_DCHECK_RUN_ON(&encoder_queue_);
419 RTC_DCHECK(sink_); 415 RTC_DCHECK(sink_);
420 LOG(LS_INFO) << "ConfigureEncoderOnTaskQueue"; 416 LOG(LS_INFO) << "ConfigureEncoder requested.";
421 417
422 max_data_payload_length_ = max_data_payload_length; 418 max_data_payload_length_ = max_data_payload_length;
423 encoder_config_ = std::move(config); 419 encoder_config_ = std::move(config);
420 pending_encoder_reconfiguration_ = true;
424 421
425 VideoCodec video_codec = VideoEncoderConfigToVideoCodec( 422 // Reconfigure the encoder now if the encoder has an internal source or
mflodman 2016/09/27 11:28:01 Great to get this comment here!
426 encoder_config_, settings_.payload_name, settings_.payload_type); 423 // if this is the first time the encoder is configured.
424 // Otherwise, the reconfiguration is deferred until the next frame to minimize
425 // the number of reconfigurations. The codec configuration depends on incoming
426 // video frame size.
427 if (!last_frame_info_ || settings_.internal_source) {
428 if (!last_frame_info_) {
429 last_frame_info_ = rtc::Optional<VideoFrameInfo>(
430 VideoFrameInfo(176, 144, kVideoRotation_0, false));
431 }
432 ReconfigureEncoder();
433 }
434 }
427 435
428 // Setting target width and height for VPM. 436 void ViEEncoder::ReconfigureEncoder() {
429 RTC_CHECK_EQ(VPM_OK, 437 RTC_DCHECK_RUN_ON(&encoder_queue_);
430 vp_->SetTargetResolution(video_codec.width, video_codec.height, 438 RTC_DCHECK(pending_encoder_reconfiguration_);
431 video_codec.maxFramerate)); 439 std::vector<VideoStream> streams =
440 encoder_config_.encoder_stream_factory->CreateEncoderStreams(
441 last_frame_info_->width, last_frame_info_->height, encoder_config_);
432 442
433 video_codec.startBitrate = 443 VideoCodec codec = VideoEncoderConfigToVideoCodec(
434 std::max(encoder_start_bitrate_bps_ / 1000, video_codec.minBitrate); 444 encoder_config_, streams, settings_.payload_name, settings_.payload_type);
435 video_codec.startBitrate =
436 std::min(video_codec.startBitrate, video_codec.maxBitrate);
437 445
438 bool success = video_sender_.RegisterSendCodec( 446 codec.startBitrate =
439 &video_codec, number_of_cores_, 447 std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate);
440 static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; 448 codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate);
441 449
450 codec.expect_encode_from_texture = last_frame_info_->is_texture;
451
452 bool success =
453 video_sender_.RegisterSendCodec(&codec, number_of_cores_,
454 max_data_payload_length_) == VCM_OK;
442 if (!success) { 455 if (!success) {
443 LOG(LS_ERROR) << "Failed to configure encoder."; 456 LOG(LS_ERROR) << "Failed to configure encoder.";
444 RTC_DCHECK(success); 457 RTC_DCHECK(success);
445 } 458 }
459 pending_encoder_reconfiguration_ = false;
446 460
447 if (stats_proxy_) { 461 if (stats_proxy_) {
448 stats_proxy_->OnEncoderReconfigured(encoder_config_, 462 stats_proxy_->OnEncoderReconfigured(encoder_config_, streams);
449 encoder_config_.streams);
450 } 463 }
451
452 sink_->OnEncoderConfigurationChanged( 464 sink_->OnEncoderConfigurationChanged(
453 encoder_config_.streams, encoder_config_.min_transmit_bitrate_bps); 465 std::move(streams), encoder_config_.min_transmit_bitrate_bps);
454 } 466 }
455 467
456 void ViEEncoder::OnFrame(const VideoFrame& video_frame) { 468 void ViEEncoder::OnFrame(const VideoFrame& video_frame) {
457 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_); 469 RTC_DCHECK_RUNS_SERIALIZED(&incoming_frame_race_checker_);
458 stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height()); 470 stats_proxy_->OnIncomingFrame(video_frame.width(), video_frame.height());
459 471
460 VideoFrame incoming_frame = video_frame; 472 VideoFrame incoming_frame = video_frame;
461 473
462 // Local time in webrtc time base. 474 // Local time in webrtc time base.
463 int64_t current_time = clock_->TimeInMilliseconds(); 475 int64_t current_time = clock_->TimeInMilliseconds();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 } 538 }
527 encoder_paused_and_dropped_frame_ = false; 539 encoder_paused_and_dropped_frame_ = false;
528 } 540 }
529 541
530 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, 542 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame,
531 int64_t time_when_posted_in_ms) { 543 int64_t time_when_posted_in_ms) {
532 RTC_DCHECK_RUN_ON(&encoder_queue_); 544 RTC_DCHECK_RUN_ON(&encoder_queue_);
533 if (pre_encode_callback_) 545 if (pre_encode_callback_)
534 pre_encode_callback_->OnFrame(video_frame); 546 pre_encode_callback_->OnFrame(video_frame);
535 547
548 if (video_frame.width() != last_frame_info_->width ||
549 video_frame.height() != last_frame_info_->height ||
550 video_frame.rotation() != last_frame_info_->rotation ||
551 video_frame.is_texture() != last_frame_info_->is_texture) {
552 pending_encoder_reconfiguration_ = true;
553 last_frame_info_ = rtc::Optional<VideoFrameInfo>(
554 VideoFrameInfo(video_frame.width(), video_frame.height(),
555 video_frame.rotation(), video_frame.is_texture()));
556 LOG(LS_INFO) << "Video frame parameters changed: dimensions="
557 << last_frame_info_->width << "x" << last_frame_info_->height
558 << ", rotation=" << last_frame_info_->rotation
559 << ", texture=" << last_frame_info_->is_texture;
560 }
561
562 if (pending_encoder_reconfiguration_) {
563 ReconfigureEncoder();
564 }
565
536 if (EncoderPaused()) { 566 if (EncoderPaused()) {
537 TraceFrameDropStart(); 567 TraceFrameDropStart();
538 return; 568 return;
539 } 569 }
540 TraceFrameDropEnd(); 570 TraceFrameDropEnd();
541 571
542 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), 572 TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
543 "Encode"); 573 "Encode");
544 const VideoFrame* frame_to_send = &video_frame;
545 // TODO(wuchengli): support texture frames.
546 if (!video_frame.video_frame_buffer()->native_handle()) {
547 // Pass frame via preprocessor.
548 frame_to_send = vp_->PreprocessFrame(video_frame);
549 if (!frame_to_send) {
550 // Drop this frame, or there was an error processing it.
551 return;
552 }
553 }
554 574
555 overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms); 575 overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms);
556 576
557 if (codec_type_ == webrtc::kVideoCodecVP8) { 577 if (codec_type_ == webrtc::kVideoCodecVP8) {
558 webrtc::CodecSpecificInfo codec_specific_info; 578 webrtc::CodecSpecificInfo codec_specific_info;
559 codec_specific_info.codecType = webrtc::kVideoCodecVP8; 579 codec_specific_info.codecType = webrtc::kVideoCodecVP8;
560 580
561 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI = 581 codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
562 has_received_rpsi_; 582 has_received_rpsi_;
563 codec_specific_info.codecSpecific.VP8.hasReceivedSLI = 583 codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
564 has_received_sli_; 584 has_received_sli_;
565 codec_specific_info.codecSpecific.VP8.pictureIdRPSI = 585 codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
566 picture_id_rpsi_; 586 picture_id_rpsi_;
567 codec_specific_info.codecSpecific.VP8.pictureIdSLI = 587 codec_specific_info.codecSpecific.VP8.pictureIdSLI =
568 picture_id_sli_; 588 picture_id_sli_;
569 has_received_sli_ = false; 589 has_received_sli_ = false;
570 has_received_rpsi_ = false; 590 has_received_rpsi_ = false;
571 591
572 video_sender_.AddVideoFrame(*frame_to_send, &codec_specific_info); 592 video_sender_.AddVideoFrame(video_frame, &codec_specific_info);
573 return; 593 return;
574 } 594 }
575 video_sender_.AddVideoFrame(*frame_to_send, nullptr); 595 video_sender_.AddVideoFrame(video_frame, nullptr);
576 } 596 }
577 597
578 void ViEEncoder::SendKeyFrame() { 598 void ViEEncoder::SendKeyFrame() {
579 if (!encoder_queue_.IsCurrent()) { 599 if (!encoder_queue_.IsCurrent()) {
580 encoder_queue_.PostTask([this] { SendKeyFrame(); }); 600 encoder_queue_.PostTask([this] { SendKeyFrame(); });
581 return; 601 return;
582 } 602 }
583 RTC_DCHECK_RUN_ON(&encoder_queue_); 603 RTC_DCHECK_RUN_ON(&encoder_queue_);
584 video_sender_.IntraFrameRequest(0); 604 video_sender_.IntraFrameRequest(0);
585 } 605 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 load_observer_->OnLoadUpdate(LoadObserver::kOveruse); 708 load_observer_->OnLoadUpdate(LoadObserver::kOveruse);
689 } 709 }
690 710
691 void ViEEncoder::NormalUsage() { 711 void ViEEncoder::NormalUsage() {
692 RTC_DCHECK_RUN_ON(&encoder_queue_); 712 RTC_DCHECK_RUN_ON(&encoder_queue_);
693 if (load_observer_) 713 if (load_observer_)
694 load_observer_->OnLoadUpdate(LoadObserver::kUnderuse); 714 load_observer_->OnLoadUpdate(LoadObserver::kUnderuse);
695 } 715 }
696 716
697 } // namespace webrtc 717 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698