In practice, we never want to go back to HW decoding after deciding to start decoding with SW codecs. This allows simplifying the code in the fallback wrapper and makes it easier to implement HW codecs. HW decoder is also now released when software fallback is activated because it will not be used again. This could free up some resources. Bug: b/73498933 Change-Id: Ibea4e32fce0c605179b649c8ac2744031799f3ee Reviewed-on: https://webrtc-review.googlesource.com/55263 Commit-Queue: Sami Kalliomäki <sakal@webrtc.org> Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Reviewed-by: Alex Glaznev <glaznev@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22168}
169 lines
5.4 KiB
C++
169 lines
5.4 KiB
C++
/*
|
|
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "media/engine/videodecodersoftwarefallbackwrapper.h"
|
|
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "modules/video_coding/include/video_error_codes.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/logging.h"
|
|
#include "rtc_base/system/fallthrough.h"
|
|
#include "rtc_base/trace_event.h"
|
|
|
|
namespace webrtc {
|
|
|
|
VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper(
|
|
std::unique_ptr<VideoDecoder> sw_fallback_decoder,
|
|
std::unique_ptr<VideoDecoder> hw_decoder)
|
|
: decoder_type_(DecoderType::kNone),
|
|
hw_decoder_(std::move(hw_decoder)),
|
|
fallback_decoder_(std::move(sw_fallback_decoder)),
|
|
fallback_implementation_name_(
|
|
std::string(fallback_decoder_->ImplementationName()) +
|
|
" (fallback from: " + hw_decoder_->ImplementationName() + ")"),
|
|
callback_(nullptr) {}
|
|
|
|
int32_t VideoDecoderSoftwareFallbackWrapper::InitDecode(
|
|
const VideoCodec* codec_settings,
|
|
int32_t number_of_cores) {
|
|
codec_settings_ = *codec_settings;
|
|
number_of_cores_ = number_of_cores;
|
|
|
|
int32_t status = InitHwDecoder();
|
|
if (status == WEBRTC_VIDEO_CODEC_OK) {
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
|
}
|
|
|
|
RTC_DCHECK(decoder_type_ == DecoderType::kNone);
|
|
if (InitFallbackDecoder()) {
|
|
return WEBRTC_VIDEO_CODEC_OK;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
int32_t VideoDecoderSoftwareFallbackWrapper::InitHwDecoder() {
|
|
RTC_DCHECK(decoder_type_ == DecoderType::kNone);
|
|
int32_t status = hw_decoder_->InitDecode(&codec_settings_, number_of_cores_);
|
|
if (status != WEBRTC_VIDEO_CODEC_OK) {
|
|
return status;
|
|
}
|
|
|
|
decoder_type_ = DecoderType::kHardware;
|
|
if (callback_)
|
|
hw_decoder_->RegisterDecodeCompleteCallback(callback_);
|
|
return status;
|
|
}
|
|
|
|
bool VideoDecoderSoftwareFallbackWrapper::InitFallbackDecoder() {
|
|
RTC_DCHECK(decoder_type_ == DecoderType::kNone ||
|
|
decoder_type_ == DecoderType::kHardware);
|
|
RTC_LOG(LS_WARNING) << "Decoder falling back to software decoding.";
|
|
int32_t status =
|
|
fallback_decoder_->InitDecode(&codec_settings_, number_of_cores_);
|
|
if (status != WEBRTC_VIDEO_CODEC_OK) {
|
|
RTC_LOG(LS_ERROR) << "Failed to initialize software-decoder fallback.";
|
|
return false;
|
|
}
|
|
|
|
if (decoder_type_ == DecoderType::kHardware) {
|
|
hw_decoder_->Release();
|
|
}
|
|
decoder_type_ = DecoderType::kFallback;
|
|
|
|
if (callback_)
|
|
fallback_decoder_->RegisterDecodeCompleteCallback(callback_);
|
|
return true;
|
|
}
|
|
|
|
int32_t VideoDecoderSoftwareFallbackWrapper::Decode(
|
|
const EncodedImage& input_image,
|
|
bool missing_frames,
|
|
const RTPFragmentationHeader* fragmentation,
|
|
const CodecSpecificInfo* codec_specific_info,
|
|
int64_t render_time_ms) {
|
|
TRACE_EVENT0("webrtc", "VideoDecoderSoftwareFallbackWrapper::Decode");
|
|
switch (decoder_type_) {
|
|
case DecoderType::kNone:
|
|
return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
|
|
case DecoderType::kHardware: {
|
|
int32_t ret = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
|
|
ret = hw_decoder_->Decode(input_image, missing_frames, fragmentation,
|
|
codec_specific_info, render_time_ms);
|
|
if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) {
|
|
return ret;
|
|
}
|
|
|
|
// HW decoder returned WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE or
|
|
// initialization failed, fallback to software.
|
|
if (!InitFallbackDecoder()) {
|
|
return ret;
|
|
}
|
|
|
|
// Fallback decoder initialized, fall-through.
|
|
RTC_FALLTHROUGH();
|
|
}
|
|
case DecoderType::kFallback:
|
|
return fallback_decoder_->Decode(input_image, missing_frames,
|
|
fragmentation, codec_specific_info,
|
|
render_time_ms);
|
|
default:
|
|
RTC_NOTREACHED();
|
|
return WEBRTC_VIDEO_CODEC_ERROR;
|
|
}
|
|
}
|
|
|
|
int32_t VideoDecoderSoftwareFallbackWrapper::RegisterDecodeCompleteCallback(
|
|
DecodedImageCallback* callback) {
|
|
callback_ = callback;
|
|
return active_decoder().RegisterDecodeCompleteCallback(callback);
|
|
}
|
|
|
|
int32_t VideoDecoderSoftwareFallbackWrapper::Release() {
|
|
int32_t status;
|
|
switch (decoder_type_) {
|
|
case DecoderType::kHardware:
|
|
status = hw_decoder_->Release();
|
|
break;
|
|
case DecoderType::kFallback:
|
|
RTC_LOG(LS_INFO) << "Releasing software fallback decoder.";
|
|
status = fallback_decoder_->Release();
|
|
break;
|
|
case DecoderType::kNone:
|
|
status = WEBRTC_VIDEO_CODEC_OK;
|
|
break;
|
|
default:
|
|
RTC_NOTREACHED();
|
|
status = WEBRTC_VIDEO_CODEC_ERROR;
|
|
}
|
|
|
|
decoder_type_ = DecoderType::kNone;
|
|
return status;
|
|
}
|
|
|
|
bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const {
|
|
return active_decoder().PrefersLateDecoding();
|
|
}
|
|
|
|
const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const {
|
|
return decoder_type_ == DecoderType::kFallback
|
|
? fallback_implementation_name_.c_str()
|
|
: hw_decoder_->ImplementationName();
|
|
}
|
|
|
|
VideoDecoder& VideoDecoderSoftwareFallbackWrapper::active_decoder() const {
|
|
return decoder_type_ == DecoderType::kFallback ? *fallback_decoder_
|
|
: *hw_decoder_;
|
|
}
|
|
|
|
} // namespace webrtc
|