Index: webrtc/video/vie_encoder.cc |
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
index 5e1d294dda675dda384b68aecc901197b3f6b8ad..ddc492bb5f84939d1aa848f8dafc34f000b92222 100644 |
--- a/webrtc/video/vie_encoder.cc |
+++ b/webrtc/video/vie_encoder.cc |
@@ -41,10 +41,11 @@ VideoCodecType PayloadNameToCodecType(const std::string& payload_name) { |
return kVideoCodecGeneric; |
} |
-VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, |
- const std::string& payload_name, |
- int payload_type) { |
- const std::vector<VideoStream>& streams = config.streams; |
+VideoCodec VideoEncoderConfigToVideoCodec( |
+ const VideoEncoderConfig& config, |
+ const std::vector<VideoStream>& streams, |
+ const std::string& payload_name, |
+ int payload_type) { |
static const int kEncoderMinBitrateKbps = 30; |
RTC_DCHECK(!streams.empty()); |
RTC_DCHECK_GE(config.min_transmit_bitrate_bps, 0); |
@@ -59,10 +60,10 @@ VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, |
break; |
case VideoEncoderConfig::ContentType::kScreen: |
video_codec.mode = kScreensharing; |
- if (config.streams.size() == 1 && |
- config.streams[0].temporal_layer_thresholds_bps.size() == 1) { |
+ if (streams.size() == 1 && |
+ streams[0].temporal_layer_thresholds_bps.size() == 1) { |
video_codec.targetBitrate = |
- config.streams[0].temporal_layer_thresholds_bps[0] / 1000; |
+ streams[0].temporal_layer_thresholds_bps[0] / 1000; |
} |
break; |
} |
@@ -179,8 +180,6 @@ VideoCodec VideoEncoderConfigToVideoCodec(const VideoEncoderConfig& config, |
RTC_DCHECK_GT(streams[0].max_framerate, 0); |
video_codec.maxFramerate = streams[0].max_framerate; |
- video_codec.expect_encode_from_texture = config.expect_encode_from_texture; |
- |
return video_codec; |
} |
@@ -283,6 +282,27 @@ class ViEEncoder::VideoSourceProxy { |
RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy); |
}; |
+class ViEEncoder::ConfigureEncoderTask : public rtc::QueuedTask { |
+ public: |
+ ConfigureEncoderTask(ViEEncoder* vie_encoder, |
+ VideoEncoderConfig config, |
+ size_t max_data_payload_length) |
+ : vie_encoder_(vie_encoder), |
+ config_(std::move(config)), |
+ max_data_payload_length_(max_data_payload_length) {} |
+ |
+ private: |
+ bool Run() override { |
+ vie_encoder_->ConfigureEncoderOnTaskQueue(std::move(config_), |
+ max_data_payload_length_); |
+ return true; |
+ } |
+ |
+ ViEEncoder* const vie_encoder_; |
+ VideoEncoderConfig config_; |
+ size_t max_data_payload_length_; |
+}; |
+ |
ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
SendStatisticsProxy* stats_proxy, |
const VideoSendStream::Config::EncoderSettings& settings, |
@@ -292,8 +312,9 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
: shutdown_event_(true /* manual_reset */, false), |
number_of_cores_(number_of_cores), |
source_proxy_(new VideoSourceProxy(this)), |
+ sink_(nullptr), |
settings_(settings), |
- vp_(VideoProcessing::Create()), |
+ codec_type_(PayloadNameToCodecType(settings.payload_name)), |
video_sender_(Clock::GetRealTimeClock(), this, this), |
overuse_detector_(Clock::GetRealTimeClock(), |
GetCpuOveruseOptions(settings.full_overuse_time), |
@@ -304,8 +325,9 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
stats_proxy_(stats_proxy), |
pre_encode_callback_(pre_encode_callback), |
module_process_thread_(nullptr), |
- encoder_config_(), |
+ pending_encoder_reconfiguration_(false), |
encoder_start_bitrate_bps_(0), |
+ max_data_payload_length_(0), |
last_observed_bitrate_bps_(0), |
encoder_paused_and_dropped_frame_(false), |
has_received_sli_(false), |
@@ -320,8 +342,6 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
captured_frame_count_(0), |
dropped_frame_count_(0), |
encoder_queue_("EncoderQueue") { |
- vp_->EnableTemporalDecimation(false); |
- |
encoder_queue_.PostTask([this, encoder_timing] { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
video_sender_.RegisterExternalEncoder( |
@@ -384,66 +404,66 @@ void ViEEncoder::SetStartBitrate(int start_bitrate_bps) { |
void ViEEncoder::ConfigureEncoder(VideoEncoderConfig config, |
size_t max_data_payload_length) { |
- VideoCodec video_codec = VideoEncoderConfigToVideoCodec( |
- config, settings_.payload_name, settings_.payload_type); |
- LOG(LS_INFO) << "ConfigureEncoder: " << config.ToString(); |
- std::vector<VideoStream> stream = std::move(config.streams); |
- int min_transmit_bitrate = config.min_transmit_bitrate_bps; |
- encoder_queue_.PostTask([this, video_codec, max_data_payload_length, stream, |
- min_transmit_bitrate] { |
- ConfigureEncoderInternal(video_codec, max_data_payload_length, stream, |
- min_transmit_bitrate); |
- }); |
- return; |
+ encoder_queue_.PostTask( |
+ std::unique_ptr<rtc::QueuedTask>(new ConfigureEncoderTask( |
+ this, std::move(config), max_data_payload_length))); |
} |
-void ViEEncoder::ConfigureEncoderInternal(const VideoCodec& video_codec, |
- size_t max_data_payload_length, |
- std::vector<VideoStream> stream, |
- int min_transmit_bitrate) { |
+void ViEEncoder::ConfigureEncoderOnTaskQueue(VideoEncoderConfig config, |
+ size_t max_data_payload_length) { |
RTC_DCHECK_RUN_ON(&encoder_queue_); |
- RTC_DCHECK_GE(encoder_start_bitrate_bps_, 0); |
+ RTC_DCHECK_GE(encoder_start_bitrate_bps_, 0u); |
RTC_DCHECK(sink_); |
+ LOG(LS_INFO) << "ConfigureEncoder requested."; |
+ |
+ max_data_payload_length_ = max_data_payload_length; |
+ encoder_config_ = std::move(config); |
+ pending_encoder_reconfiguration_ = true; |
+ |
+ // Reconfigure the encoder now if the encoder has an internal source or |
+ // if this is the first time the encoder is configured. |
+ // Otherwise, the reconfiguration is deferred until the next frame to minimize |
+ // the number of reconfigurations. The codec configuration depends on incoming |
+ // video frame size. |
+ if (!last_frame_info_ || settings_.internal_source) { |
+ if (!last_frame_info_) { |
+ last_frame_info_ = rtc::Optional<VideoFrameInfo>( |
+ VideoFrameInfo(176, 144, kVideoRotation_0, false)); |
+ } |
+ ReconfigureEncoder(); |
+ } |
+} |
+ |
+void ViEEncoder::ReconfigureEncoder() { |
+ RTC_DCHECK_RUN_ON(&encoder_queue_); |
+ RTC_DCHECK(pending_encoder_reconfiguration_); |
+ std::vector<VideoStream> streams = |
+ encoder_config_.encoder_stream_factory->CreateEncoderStreams( |
+ last_frame_info_->width, last_frame_info_->height, encoder_config_); |
- // Setting target width and height for VPM. |
- RTC_CHECK_EQ(VPM_OK, |
- vp_->SetTargetResolution(video_codec.width, video_codec.height, |
- video_codec.maxFramerate)); |
+ VideoCodec codec = VideoEncoderConfigToVideoCodec( |
+ encoder_config_, streams, settings_.payload_name, settings_.payload_type); |
- encoder_config_ = video_codec; |
- encoder_config_.startBitrate = encoder_start_bitrate_bps_ / 1000; |
- encoder_config_.startBitrate = |
- std::max(encoder_config_.startBitrate, video_codec.minBitrate); |
- encoder_config_.startBitrate = |
- std::min(encoder_config_.startBitrate, video_codec.maxBitrate); |
+ codec.startBitrate = |
+ std::max(encoder_start_bitrate_bps_ / 1000, codec.minBitrate); |
+ codec.startBitrate = std::min(codec.startBitrate, codec.maxBitrate); |
- bool success = video_sender_.RegisterSendCodec( |
- &encoder_config_, number_of_cores_, |
- static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; |
+ codec.expect_encode_from_texture = last_frame_info_->is_texture; |
+ bool success = |
+ video_sender_.RegisterSendCodec(&codec, number_of_cores_, |
+ max_data_payload_length_) == VCM_OK; |
if (!success) { |
LOG(LS_ERROR) << "Failed to configure encoder."; |
RTC_DCHECK(success); |
} |
+ pending_encoder_reconfiguration_ = false; |
if (stats_proxy_) { |
- VideoEncoderConfig::ContentType content_type = |
- VideoEncoderConfig::ContentType::kRealtimeVideo; |
- switch (video_codec.mode) { |
- case kRealtimeVideo: |
- content_type = VideoEncoderConfig::ContentType::kRealtimeVideo; |
- break; |
- case kScreensharing: |
- content_type = VideoEncoderConfig::ContentType::kScreen; |
- break; |
- default: |
- RTC_NOTREACHED(); |
- break; |
- } |
- stats_proxy_->SetContentType(content_type); |
+ stats_proxy_->OnEncoderReconfigured(encoder_config_, streams); |
} |
- |
- sink_->OnEncoderConfigurationChanged(stream, min_transmit_bitrate); |
+ sink_->OnEncoderConfigurationChanged( |
+ std::move(streams), encoder_config_.min_transmit_bitrate_bps); |
} |
void ViEEncoder::OnFrame(const VideoFrame& video_frame) { |
@@ -526,6 +546,24 @@ void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, |
if (pre_encode_callback_) |
pre_encode_callback_->OnFrame(video_frame); |
+ if (video_frame.width() != last_frame_info_->width || |
+ video_frame.height() != last_frame_info_->height || |
+ video_frame.rotation() != last_frame_info_->rotation || |
+ video_frame.is_texture() != last_frame_info_->is_texture) { |
+ pending_encoder_reconfiguration_ = true; |
+ last_frame_info_ = rtc::Optional<VideoFrameInfo>( |
+ VideoFrameInfo(video_frame.width(), video_frame.height(), |
+ video_frame.rotation(), video_frame.is_texture())); |
+ LOG(LS_INFO) << "Video frame parameters changed: dimensions=" |
+ << last_frame_info_->width << "x" << last_frame_info_->height |
+ << ", rotation=" << last_frame_info_->rotation |
+ << ", texture=" << last_frame_info_->is_texture; |
+ } |
+ |
+ if (pending_encoder_reconfiguration_) { |
+ ReconfigureEncoder(); |
+ } |
+ |
if (EncoderPaused()) { |
TraceFrameDropStart(); |
return; |
@@ -534,20 +572,10 @@ void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, |
TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(), |
"Encode"); |
- const VideoFrame* frame_to_send = &video_frame; |
- // TODO(wuchengli): support texture frames. |
- if (!video_frame.video_frame_buffer()->native_handle()) { |
- // Pass frame via preprocessor. |
- frame_to_send = vp_->PreprocessFrame(video_frame); |
- if (!frame_to_send) { |
- // Drop this frame, or there was an error processing it. |
- return; |
- } |
- } |
overuse_detector_.FrameCaptured(video_frame, time_when_posted_in_ms); |
- if (encoder_config_.codecType == webrtc::kVideoCodecVP8) { |
+ if (codec_type_ == webrtc::kVideoCodecVP8) { |
webrtc::CodecSpecificInfo codec_specific_info; |
codec_specific_info.codecType = webrtc::kVideoCodecVP8; |
@@ -562,10 +590,10 @@ void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame, |
has_received_sli_ = false; |
has_received_rpsi_ = false; |
- video_sender_.AddVideoFrame(*frame_to_send, &codec_specific_info); |
- return; |
+ video_sender_.AddVideoFrame(video_frame, &codec_specific_info); |
+ return; |
} |
- video_sender_.AddVideoFrame(*frame_to_send, nullptr); |
+ video_sender_.AddVideoFrame(video_frame, nullptr); |
} |
void ViEEncoder::SendKeyFrame() { |