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
19 namespace webrtc {
Create(VideoDecoder::DecoderType codec_type)20 VideoDecoder* 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
CodecTypeToDecoderType(VideoCodecType codec_type)37 VideoDecoder::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
VideoDecoderSoftwareFallbackWrapper(VideoCodecType codec_type,VideoDecoder * decoder)50 VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper(
51 VideoCodecType codec_type,
52 VideoDecoder* decoder)
53 : decoder_type_(CodecTypeToDecoderType(codec_type)),
54 decoder_(decoder),
55 callback_(nullptr) {
56 }
57
InitDecode(const VideoCodec * codec_settings,int32_t number_of_cores)58 int32_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
InitFallbackDecoder()66 bool 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
Decode(const EncodedImage & input_image,bool missing_frames,const RTPFragmentationHeader * fragmentation,const CodecSpecificInfo * codec_specific_info,int64_t render_time_ms)85 int32_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
RegisterDecodeCompleteCallback(DecodedImageCallback * callback)116 int32_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
Release()125 int32_t VideoDecoderSoftwareFallbackWrapper::Release() {
126 if (fallback_decoder_)
127 fallback_decoder_->Release();
128 return decoder_->Release();
129 }
130
Reset()131 int32_t VideoDecoderSoftwareFallbackWrapper::Reset() {
132 if (fallback_decoder_)
133 fallback_decoder_->Reset();
134 return decoder_->Reset();
135 }
136
PrefersLateDecoding() const137 bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const {
138 if (fallback_decoder_)
139 return fallback_decoder_->PrefersLateDecoding();
140 return decoder_->PrefersLateDecoding();
141 }
142
ImplementationName() const143 const 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