Chromium Code Reviews| Index: webrtc/video/vie_encoder.cc |
| diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc |
| index ff5f916ed6184abdb3d6aa60ca03517c5591b12d..915859da3eb270625f77ddb37435c2f45eb466e6 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; |
| } |
| @@ -316,7 +315,6 @@ ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
| sink_(nullptr), |
| settings_(settings), |
| codec_type_(PayloadNameToCodecType(settings.payload_name)), |
| - vp_(VideoProcessing::Create()), |
| video_sender_(Clock::GetRealTimeClock(), this, this), |
| overuse_detector_(Clock::GetRealTimeClock(), |
| GetCpuOveruseOptions(settings.full_overuse_time), |
| @@ -327,7 +325,7 @@ 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), |
| @@ -344,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( |
| @@ -417,40 +413,56 @@ void ViEEncoder::ConfigureEncoderOnTaskQueue(VideoEncoderConfig config, |
| size_t max_data_payload_length) { |
| RTC_DCHECK_RUN_ON(&encoder_queue_); |
| RTC_DCHECK(sink_); |
| - LOG(LS_INFO) << "ConfigureEncoderOnTaskQueue"; |
| + 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 |
|
mflodman
2016/09/27 11:28:01
Great to get this comment here!
|
| + // 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(); |
| + } |
| +} |
| - VideoCodec video_codec = VideoEncoderConfigToVideoCodec( |
| - encoder_config_, settings_.payload_name, settings_.payload_type); |
| +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); |
| - video_codec.startBitrate = |
| - std::max(encoder_start_bitrate_bps_ / 1000, video_codec.minBitrate); |
| - video_codec.startBitrate = |
| - std::min(video_codec.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( |
| - &video_codec, 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_) { |
| - stats_proxy_->OnEncoderReconfigured(encoder_config_, |
| - encoder_config_.streams); |
| + stats_proxy_->OnEncoderReconfigured(encoder_config_, streams); |
| } |
| - |
| sink_->OnEncoderConfigurationChanged( |
| - encoder_config_.streams, encoder_config_.min_transmit_bitrate_bps); |
| + std::move(streams), encoder_config_.min_transmit_bitrate_bps); |
| } |
| void ViEEncoder::OnFrame(const VideoFrame& video_frame) { |
| @@ -533,6 +545,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; |
| @@ -541,16 +571,6 @@ 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); |
| @@ -569,10 +589,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() { |