| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/media/engine/videodecodersoftwarefallbackwrapper.h" | 11 #include "webrtc/media/engine/videodecodersoftwarefallbackwrapper.h" |
| 12 | 12 |
| 13 #include <string> | 13 #include <string> |
| 14 | 14 |
| 15 #include "webrtc/base/checks.h" |
| 15 #include "webrtc/base/logging.h" | 16 #include "webrtc/base/logging.h" |
| 16 #include "webrtc/media/engine/internaldecoderfactory.h" | 17 #include "webrtc/media/engine/internaldecoderfactory.h" |
| 17 #include "webrtc/modules/video_coding/include/video_error_codes.h" | 18 #include "webrtc/modules/video_coding/include/video_error_codes.h" |
| 18 | 19 |
| 19 namespace webrtc { | 20 namespace webrtc { |
| 20 | 21 |
| 21 VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper( | 22 VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper( |
| 22 VideoCodecType codec_type, | 23 VideoCodecType codec_type, |
| 23 VideoDecoder* decoder) | 24 VideoDecoder* decoder) |
| 24 : codec_type_(codec_type), decoder_(decoder), callback_(nullptr) {} | 25 : codec_type_(codec_type), |
| 26 decoder_(decoder), |
| 27 decoder_initialized_(false), |
| 28 callback_(nullptr) {} |
| 25 | 29 |
| 26 int32_t VideoDecoderSoftwareFallbackWrapper::InitDecode( | 30 int32_t VideoDecoderSoftwareFallbackWrapper::InitDecode( |
| 27 const VideoCodec* codec_settings, | 31 const VideoCodec* codec_settings, |
| 28 int32_t number_of_cores) { | 32 int32_t number_of_cores) { |
| 33 RTC_DCHECK(!fallback_decoder_) << "Fallback decoder should never be " |
| 34 "initialized here, it should've been " |
| 35 "released."; |
| 29 codec_settings_ = *codec_settings; | 36 codec_settings_ = *codec_settings; |
| 30 number_of_cores_ = number_of_cores; | 37 number_of_cores_ = number_of_cores; |
| 31 return decoder_->InitDecode(codec_settings, number_of_cores); | 38 int32_t ret = decoder_->InitDecode(codec_settings, number_of_cores); |
| 39 if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) { |
| 40 decoder_initialized_ = (ret == WEBRTC_VIDEO_CODEC_OK); |
| 41 return ret; |
| 42 } |
| 43 decoder_initialized_ = false; |
| 44 |
| 45 // Try to initialize fallback decoder. |
| 46 if (InitFallbackDecoder()) |
| 47 return WEBRTC_VIDEO_CODEC_OK; |
| 48 return ret; |
| 32 } | 49 } |
| 33 | 50 |
| 34 bool VideoDecoderSoftwareFallbackWrapper::InitFallbackDecoder() { | 51 bool VideoDecoderSoftwareFallbackWrapper::InitFallbackDecoder() { |
| 35 RTC_CHECK(codec_type_ != kVideoCodecUnknown) | 52 RTC_CHECK(codec_type_ != kVideoCodecUnknown) |
| 36 << "Decoder requesting fallback to codec not supported in software."; | 53 << "Decoder requesting fallback to codec not supported in software."; |
| 37 LOG(LS_WARNING) << "Decoder falling back to software decoding."; | 54 LOG(LS_WARNING) << "Decoder falling back to software decoding."; |
| 38 cricket::InternalDecoderFactory internal_decoder_factory; | 55 cricket::InternalDecoderFactory internal_decoder_factory; |
| 39 fallback_decoder_.reset( | 56 fallback_decoder_.reset( |
| 40 internal_decoder_factory.CreateVideoDecoder(codec_type_)); | 57 internal_decoder_factory.CreateVideoDecoder(codec_type_)); |
| 41 if (fallback_decoder_->InitDecode(&codec_settings_, number_of_cores_) != | 58 if (fallback_decoder_->InitDecode(&codec_settings_, number_of_cores_) != |
| 42 WEBRTC_VIDEO_CODEC_OK) { | 59 WEBRTC_VIDEO_CODEC_OK) { |
| 43 LOG(LS_ERROR) << "Failed to initialize software-decoder fallback."; | 60 LOG(LS_ERROR) << "Failed to initialize software-decoder fallback."; |
| 44 fallback_decoder_.reset(); | 61 fallback_decoder_.reset(); |
| 45 return false; | 62 return false; |
| 46 } | 63 } |
| 47 if (callback_) | 64 if (callback_) |
| 48 fallback_decoder_->RegisterDecodeCompleteCallback(callback_); | 65 fallback_decoder_->RegisterDecodeCompleteCallback(callback_); |
| 49 fallback_implementation_name_ = | 66 fallback_implementation_name_ = |
| 50 std::string(fallback_decoder_->ImplementationName()) + | 67 std::string(fallback_decoder_->ImplementationName()) + |
| 51 " (fallback from: " + decoder_->ImplementationName() + ")"; | 68 " (fallback from: " + decoder_->ImplementationName() + ")"; |
| 52 return true; | 69 return true; |
| 53 } | 70 } |
| 54 | 71 |
| 55 int32_t VideoDecoderSoftwareFallbackWrapper::Decode( | 72 int32_t VideoDecoderSoftwareFallbackWrapper::Decode( |
| 56 const EncodedImage& input_image, | 73 const EncodedImage& input_image, |
| 57 bool missing_frames, | 74 bool missing_frames, |
| 58 const RTPFragmentationHeader* fragmentation, | 75 const RTPFragmentationHeader* fragmentation, |
| 59 const CodecSpecificInfo* codec_specific_info, | 76 const CodecSpecificInfo* codec_specific_info, |
| 60 int64_t render_time_ms) { | 77 int64_t render_time_ms) { |
| 61 // Try decoding with the provided decoder on every keyframe or when there's no | 78 // Try initializing and decoding with the provided decoder on every keyframe |
| 62 // fallback decoder. This is the normal case. | 79 // or when there's no fallback decoder. This is the normal case. |
| 63 if (!fallback_decoder_ || input_image._frameType == kVideoFrameKey) { | 80 if (!fallback_decoder_ || input_image._frameType == kVideoFrameKey) { |
| 64 int32_t ret = decoder_->Decode(input_image, missing_frames, fragmentation, | 81 int32_t ret = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE; |
| 65 codec_specific_info, render_time_ms); | 82 // Try reinitializing the decoder if it had failed before. |
| 83 if (!decoder_initialized_) { |
| 84 decoder_initialized_ = |
| 85 decoder_->InitDecode(&codec_settings_, number_of_cores_) == |
| 86 WEBRTC_VIDEO_CODEC_OK; |
| 87 } |
| 88 if (decoder_initialized_) { |
| 89 ret = decoder_->Decode(input_image, missing_frames, fragmentation, |
| 90 codec_specific_info, render_time_ms); |
| 91 } |
| 66 if (ret == WEBRTC_VIDEO_CODEC_OK) { | 92 if (ret == WEBRTC_VIDEO_CODEC_OK) { |
| 67 if (fallback_decoder_) { | 93 if (fallback_decoder_) { |
| 68 // Decode OK -> stop using fallback decoder. | 94 // Decode OK -> stop using fallback decoder. |
| 95 LOG(LS_INFO) |
| 96 << "Decode OK, no longer using the software fallback decoder."; |
| 69 fallback_decoder_->Release(); | 97 fallback_decoder_->Release(); |
| 70 fallback_decoder_.reset(); | 98 fallback_decoder_.reset(); |
| 71 return WEBRTC_VIDEO_CODEC_OK; | 99 return WEBRTC_VIDEO_CODEC_OK; |
| 72 } | 100 } |
| 73 } | 101 } |
| 74 if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) | 102 if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) |
| 75 return ret; | 103 return ret; |
| 76 if (!fallback_decoder_) { | 104 if (!fallback_decoder_) { |
| 77 // Try to initialize fallback decoder. | 105 // Try to initialize fallback decoder. |
| 78 if (!InitFallbackDecoder()) | 106 if (!InitFallbackDecoder()) |
| 79 return ret; | 107 return ret; |
| 80 } | 108 } |
| 81 } | 109 } |
| 82 return fallback_decoder_->Decode(input_image, missing_frames, fragmentation, | 110 return fallback_decoder_->Decode(input_image, missing_frames, fragmentation, |
| 83 codec_specific_info, render_time_ms); | 111 codec_specific_info, render_time_ms); |
| 84 } | 112 } |
| 85 | 113 |
| 86 int32_t VideoDecoderSoftwareFallbackWrapper::RegisterDecodeCompleteCallback( | 114 int32_t VideoDecoderSoftwareFallbackWrapper::RegisterDecodeCompleteCallback( |
| 87 DecodedImageCallback* callback) { | 115 DecodedImageCallback* callback) { |
| 88 callback_ = callback; | 116 callback_ = callback; |
| 89 int32_t ret = decoder_->RegisterDecodeCompleteCallback(callback); | 117 int32_t ret = decoder_->RegisterDecodeCompleteCallback(callback); |
| 90 if (fallback_decoder_) | 118 if (fallback_decoder_) |
| 91 return fallback_decoder_->RegisterDecodeCompleteCallback(callback); | 119 return fallback_decoder_->RegisterDecodeCompleteCallback(callback); |
| 92 return ret; | 120 return ret; |
| 93 } | 121 } |
| 94 | 122 |
| 95 int32_t VideoDecoderSoftwareFallbackWrapper::Release() { | 123 int32_t VideoDecoderSoftwareFallbackWrapper::Release() { |
| 96 if (fallback_decoder_) | 124 if (fallback_decoder_) { |
| 125 LOG(LS_INFO) << "Releasing software fallback decoder."; |
| 97 fallback_decoder_->Release(); | 126 fallback_decoder_->Release(); |
| 127 fallback_decoder_.reset(); |
| 128 } |
| 129 decoder_initialized_ = false; |
| 98 return decoder_->Release(); | 130 return decoder_->Release(); |
| 99 } | 131 } |
| 100 | 132 |
| 101 bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const { | 133 bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const { |
| 102 if (fallback_decoder_) | 134 if (fallback_decoder_) |
| 103 return fallback_decoder_->PrefersLateDecoding(); | 135 return fallback_decoder_->PrefersLateDecoding(); |
| 104 return decoder_->PrefersLateDecoding(); | 136 return decoder_->PrefersLateDecoding(); |
| 105 } | 137 } |
| 106 | 138 |
| 107 const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const { | 139 const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const { |
| 108 if (fallback_decoder_) | 140 if (fallback_decoder_) |
| 109 return fallback_implementation_name_.c_str(); | 141 return fallback_implementation_name_.c_str(); |
| 110 return decoder_->ImplementationName(); | 142 return decoder_->ImplementationName(); |
| 111 } | 143 } |
| 112 | 144 |
| 113 } // namespace webrtc | 145 } // namespace webrtc |
| OLD | NEW |