blob: 8dd0f841ea204c875a99322c05115ed0521397a1 [file] [log] [blame]
magjedf6acc2a2016-11-22 01:43:03 -08001/*
2 * Copyright (c) 2016 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/media/engine/videodecodersoftwarefallbackwrapper.h"
12
13#include <string>
14
15#include "webrtc/base/logging.h"
16#include "webrtc/modules/video_coding/include/video_error_codes.h"
17
18namespace webrtc {
19
20namespace {
21
22VideoDecoder::DecoderType CodecTypeToDecoderType(VideoCodecType codec_type) {
23 switch (codec_type) {
24 case kVideoCodecH264:
25 return VideoDecoder::kH264;
26 case kVideoCodecVP8:
27 return VideoDecoder::kVp8;
28 case kVideoCodecVP9:
29 return VideoDecoder::kVp9;
30 default:
31 return VideoDecoder::kUnsupportedCodec;
32 }
33}
34
35} // anonymous namespace
36
37VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper(
38 VideoCodecType codec_type,
39 VideoDecoder* decoder)
40 : decoder_type_(CodecTypeToDecoderType(codec_type)),
41 decoder_(decoder),
42 callback_(nullptr) {
43}
44
45int32_t VideoDecoderSoftwareFallbackWrapper::InitDecode(
46 const VideoCodec* codec_settings,
47 int32_t number_of_cores) {
48 codec_settings_ = *codec_settings;
49 number_of_cores_ = number_of_cores;
50 return decoder_->InitDecode(codec_settings, number_of_cores);
51}
52
53bool VideoDecoderSoftwareFallbackWrapper::InitFallbackDecoder() {
54 RTC_CHECK(decoder_type_ != kUnsupportedCodec)
55 << "Decoder requesting fallback to codec not supported in software.";
56 LOG(LS_WARNING) << "Decoder falling back to software decoding.";
57 fallback_decoder_.reset(VideoDecoder::Create(decoder_type_));
58 if (fallback_decoder_->InitDecode(&codec_settings_, number_of_cores_) !=
59 WEBRTC_VIDEO_CODEC_OK) {
60 LOG(LS_ERROR) << "Failed to initialize software-decoder fallback.";
61 fallback_decoder_.reset();
62 return false;
63 }
64 if (callback_)
65 fallback_decoder_->RegisterDecodeCompleteCallback(callback_);
66 fallback_implementation_name_ =
67 std::string(fallback_decoder_->ImplementationName()) +
68 " (fallback from: " + decoder_->ImplementationName() + ")";
69 return true;
70}
71
72int32_t VideoDecoderSoftwareFallbackWrapper::Decode(
73 const EncodedImage& input_image,
74 bool missing_frames,
75 const RTPFragmentationHeader* fragmentation,
76 const CodecSpecificInfo* codec_specific_info,
77 int64_t render_time_ms) {
78 // Try decoding with the provided decoder on every keyframe or when there's no
79 // fallback decoder. This is the normal case.
80 if (!fallback_decoder_ || input_image._frameType == kVideoFrameKey) {
81 int32_t ret = decoder_->Decode(input_image, missing_frames, fragmentation,
82 codec_specific_info, render_time_ms);
83 if (ret == WEBRTC_VIDEO_CODEC_OK) {
84 if (fallback_decoder_) {
85 // Decode OK -> stop using fallback decoder.
86 fallback_decoder_->Release();
87 fallback_decoder_.reset();
88 return WEBRTC_VIDEO_CODEC_OK;
89 }
90 }
91 if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE)
92 return ret;
93 if (!fallback_decoder_) {
94 // Try to initialize fallback decoder.
95 if (!InitFallbackDecoder())
96 return ret;
97 }
98 }
99 return fallback_decoder_->Decode(input_image, missing_frames, fragmentation,
100 codec_specific_info, render_time_ms);
101}
102
103int32_t VideoDecoderSoftwareFallbackWrapper::RegisterDecodeCompleteCallback(
104 DecodedImageCallback* callback) {
105 callback_ = callback;
106 int32_t ret = decoder_->RegisterDecodeCompleteCallback(callback);
107 if (fallback_decoder_)
108 return fallback_decoder_->RegisterDecodeCompleteCallback(callback);
109 return ret;
110}
111
112int32_t VideoDecoderSoftwareFallbackWrapper::Release() {
113 if (fallback_decoder_)
114 fallback_decoder_->Release();
115 return decoder_->Release();
116}
117
118bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const {
119 if (fallback_decoder_)
120 return fallback_decoder_->PrefersLateDecoding();
121 return decoder_->PrefersLateDecoding();
122}
123
124const char* VideoDecoderSoftwareFallbackWrapper::ImplementationName() const {
125 if (fallback_decoder_)
126 return fallback_implementation_name_.c_str();
127 return decoder_->ImplementationName();
128}
129
130} // namespace webrtc