Index: webrtc/video/video_encoder.cc |
diff --git a/webrtc/video/video_encoder.cc b/webrtc/video/video_encoder.cc |
index 3e6ce634f8e9022442bab86e15250119e4639e35..d116a1ea6728c30391fceaaae931633c5eea0154 100644 |
--- a/webrtc/video/video_encoder.cc |
+++ b/webrtc/video/video_encoder.cc |
@@ -50,34 +50,67 @@ VideoEncoder::EncoderType CodecToEncoderType(VideoCodecType codec_type) { |
VideoEncoderSoftwareFallbackWrapper::VideoEncoderSoftwareFallbackWrapper( |
VideoCodecType codec_type, |
webrtc::VideoEncoder* encoder) |
- : encoder_type_(CodecToEncoderType(codec_type)), |
+ : rates_set_(false), |
+ channel_parameters_set_(false), |
+ encoder_type_(CodecToEncoderType(codec_type)), |
encoder_(encoder), |
- callback_(nullptr) { |
+ callback_(nullptr) {} |
+ |
+bool VideoEncoderSoftwareFallbackWrapper::InitFallbackEncoder() { |
+ RTC_CHECK(encoder_type_ != kUnsupportedCodec) |
+ << "Encoder requesting fallback to codec not supported in software."; |
+ fallback_encoder_.reset(VideoEncoder::Create(encoder_type_)); |
+ if (fallback_encoder_->InitEncode(&codec_settings_, number_of_cores_, |
+ max_payload_size_) != |
+ WEBRTC_VIDEO_CODEC_OK) { |
+ LOG(LS_ERROR) << "Failed to initialize software-encoder fallback."; |
+ fallback_encoder_->Release(); |
+ fallback_encoder_.reset(); |
+ return false; |
+ } |
+ // Replay callback, rates, and channel parameters. |
+ if (callback_) |
+ fallback_encoder_->RegisterEncodeCompleteCallback(callback_); |
+ if (rates_set_) |
+ fallback_encoder_->SetRates(bitrate_, framerate_); |
+ if (channel_parameters_set_) |
+ fallback_encoder_->SetChannelParameters(packet_loss_, rtt_); |
+ |
+ // Since we're switching to the fallback encoder, Release the real encoder. It |
+ // may be re-initialized via InitEncode later, and it will continue to get |
+ // Set calls for rates and channel parameters in the meantime. |
+ encoder_->Release(); |
+ return true; |
} |
int32_t VideoEncoderSoftwareFallbackWrapper::InitEncode( |
const VideoCodec* codec_settings, |
int32_t number_of_cores, |
size_t max_payload_size) { |
+ // Store settings, in case we need to dynamically switch to the fallback |
+ // encoder after a failed Encode call. |
+ codec_settings_ = *codec_settings; |
+ number_of_cores_ = number_of_cores; |
+ max_payload_size_ = max_payload_size; |
+ // Clear stored rate/channel parameters. |
+ rates_set_ = false; |
+ channel_parameters_set_ = false; |
+ |
int32_t ret = |
encoder_->InitEncode(codec_settings, number_of_cores, max_payload_size); |
if (ret == WEBRTC_VIDEO_CODEC_OK || encoder_type_ == kUnsupportedCodec) { |
+ if (fallback_encoder_) |
+ fallback_encoder_->Release(); |
fallback_encoder_.reset(); |
if (callback_) |
encoder_->RegisterEncodeCompleteCallback(callback_); |
return ret; |
} |
// Try to instantiate software codec. |
- fallback_encoder_.reset(VideoEncoder::Create(encoder_type_)); |
- if (fallback_encoder_->InitEncode(codec_settings, number_of_cores, |
- max_payload_size) == |
- WEBRTC_VIDEO_CODEC_OK) { |
- if (callback_) |
- fallback_encoder_->RegisterEncodeCompleteCallback(callback_); |
+ if (InitFallbackEncoder()) { |
return WEBRTC_VIDEO_CODEC_OK; |
} |
- // Software encoder failed, reset and use original return code. |
- fallback_encoder_.reset(); |
+ // Software encoder failed, use original return code. |
return ret; |
} |
@@ -91,6 +124,9 @@ int32_t VideoEncoderSoftwareFallbackWrapper::RegisterEncodeCompleteCallback( |
} |
int32_t VideoEncoderSoftwareFallbackWrapper::Release() { |
+ // If the fallback_encoder_ is non-null, it means it was created via |
+ // InitFallbackEncoder which has Release()d encoder_, so we should only ever |
+ // need to Release() whichever one is active. |
if (fallback_encoder_) |
return fallback_encoder_->Release(); |
return encoder_->Release(); |
@@ -102,12 +138,21 @@ int32_t VideoEncoderSoftwareFallbackWrapper::Encode( |
const std::vector<FrameType>* frame_types) { |
if (fallback_encoder_) |
return fallback_encoder_->Encode(frame, codec_specific_info, frame_types); |
- return encoder_->Encode(frame, codec_specific_info, frame_types); |
+ int32_t ret = encoder_->Encode(frame, codec_specific_info, frame_types); |
+ // If requested, try a software fallback. |
+ if (ret == WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE && InitFallbackEncoder()) { |
+ // Fallback was successful, so start using it with this frame. |
+ return fallback_encoder_->Encode(frame, codec_specific_info, frame_types); |
+ } |
+ return ret; |
} |
int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters( |
uint32_t packet_loss, |
int64_t rtt) { |
+ channel_parameters_set_ = true; |
+ packet_loss_ = packet_loss; |
+ rtt_ = rtt; |
int32_t ret = encoder_->SetChannelParameters(packet_loss, rtt); |
if (fallback_encoder_) |
return fallback_encoder_->SetChannelParameters(packet_loss, rtt); |
@@ -116,6 +161,9 @@ int32_t VideoEncoderSoftwareFallbackWrapper::SetChannelParameters( |
int32_t VideoEncoderSoftwareFallbackWrapper::SetRates(uint32_t bitrate, |
uint32_t framerate) { |
+ rates_set_ = true; |
+ bitrate_ = bitrate; |
+ framerate_ = framerate; |
int32_t ret = encoder_->SetRates(bitrate, framerate); |
if (fallback_encoder_) |
return fallback_encoder_->SetRates(bitrate, framerate); |