1/* 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11#include "webrtc/video_decoder.h" 12 13#include "webrtc/base/checks.h" 14#include "webrtc/base/logging.h" 15#include "webrtc/modules/video_coding/codecs/h264/include/h264.h" 16#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h" 17#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h" 18 19namespace webrtc { 20VideoDecoder* VideoDecoder::Create(VideoDecoder::DecoderType codec_type) { 21 switch (codec_type) { 22 case kH264: 23 RTC_DCHECK(H264Decoder::IsSupported()); 24 return H264Decoder::Create(); 25 case kVp8: 26 return VP8Decoder::Create(); 27 case kVp9: 28 return VP9Decoder::Create(); 29 case kUnsupportedCodec: 30 RTC_NOTREACHED(); 31 return nullptr; 32 } 33 RTC_NOTREACHED(); 34 return nullptr; 35} 36 37VideoDecoder::DecoderType CodecTypeToDecoderType(VideoCodecType codec_type) { 38 switch (codec_type) { 39 case kVideoCodecH264: 40 return VideoDecoder::kH264; 41 case kVideoCodecVP8: 42 return VideoDecoder::kVp8; 43 case kVideoCodecVP9: 44 return VideoDecoder::kVp9; 45 default: 46 return VideoDecoder::kUnsupportedCodec; 47 } 48} 49 50VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper( 51 VideoCodecType codec_type, 52 VideoDecoder* decoder) 53 : decoder_type_(CodecTypeToDecoderType(codec_type)), 54 decoder_(decoder), 55 callback_(nullptr) { 56} 57 58int32_t VideoDecoderSoftwareFallbackWrapper::InitDecode( 59 const VideoCodec* codec_settings, 60 int32_t number_of_cores) { 61 codec_settings_ = *codec_settings; 62 number_of_cores_ = number_of_cores; 63 return decoder_->InitDecode(codec_settings, number_of_cores); 64} 65 66bool VideoDecoderSoftwareFallbackWrapper::InitFallbackDecoder() { 67 RTC_CHECK(decoder_type_ != kUnsupportedCodec) 68 << "Decoder requesting fallback to codec not supported in software."; 69 LOG(LS_WARNING) << "Decoder falling back to software decoding."; 70 fallback_decoder_.reset(VideoDecoder::Create(decoder_type_)); 71 if (fallback_decoder_->InitDecode(&codec_settings_, number_of_cores_) != 72 WEBRTC_VIDEO_CODEC_OK) { 73 LOG(LS_ERROR) << "Failed to initialize software-decoder fallback."; 74 fallback_decoder_.reset(); 75 return false; 76 } 77 if (callback_ != nullptr) 78 fallback_decoder_->RegisterDecodeCompleteCallback(callback_); 79 fallback_implementation_name_ = 80 std::string(fallback_decoder_->ImplementationName()) + 81 " (fallback from: " + decoder_->ImplementationName() + ")"; 82 return true; 83} 84 85int32_t VideoDecoderSoftwareFallbackWrapper::Decode( 86 const EncodedImage& input_image, 87 bool missing_frames, 88 const RTPFragmentationHeader* fragmentation, 89 const CodecSpecificInfo* codec_specific_info, 90 int64_t render_time_ms) { 91 // Try decoding with the provided decoder on every keyframe or when there's no 92 // fallback decoder. This is the normal case. 93 if (!fallback_decoder_ || input_image._frameType == kVideoFrameKey) { 94 int32_t ret = decoder_->Decode(input_image, missing_frames, fragmentation, 95 codec_specific_info, render_time_ms); 96 if (ret == WEBRTC_VIDEO_CODEC_OK) { 97 if (fallback_decoder_) { 98 // Decode OK -> stop using fallback decoder. 99 fallback_decoder_->Release(); 100 fallback_decoder_.reset(); 101 return WEBRTC_VIDEO_CODEC_OK; 102 } 103 } 104 if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) 105 return ret; 106 if (!fallback_decoder_) { 107 // Try to initialize fallback decoder. 108 if (!InitFallbackDecoder()) 109 return ret; 110 } 111 } 112 return fallback_decoder_->Decode(input_image, missing_frames, fragmentation, 113 codec_specific_info, render_time_ms); 114} 115 116int32_t VideoDecoderSoftwareFallbackWrapper::RegisterDecodeCompleteCallback( 117 DecodedImageCallback* callback) { 118 callback_ = callback; 119 int32_t ret = decoder_->RegisterDecodeCompleteCallback(callback); 120 if (fallback_decoder_) 121 return fallback_decoder_->RegisterDecodeCompleteCallback(callback); 122 return ret; 123} 124 125int32_t VideoDecoderSoftwareFallbackWrapper::Release() { 126 if (fallback_decoder_) 127 fallback_decoder_->Release(); 128 return decoder_->Release(); 129} 130 131int32_t VideoDecoderSoftwareFallbackWrapper::Reset() { 132 if (fallback_decoder_) 133 fallback_decoder_->Reset(); 134 return decoder_->Reset(); 135} 136 137bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const { 138 if (fallback_decoder_) 139 return fallback_decoder_->PrefersLateDecoding(); 140 return decoder_->PrefersLateDecoding(); 141} 142 143const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const { 144 if (fallback_decoder_) 145 return fallback_implementation_name_.c_str(); 146 return decoder_->ImplementationName(); 147} 148 149} // namespace webrtc 150