• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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