| 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() {
|
|
|