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 |