Home | History | Annotate | Download | only in video
      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 {
     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 
     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 
     50 VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper(
     51     VideoCodecType codec_type,
     52     VideoDecoder* decoder)
     53     : decoder_type_(CodecTypeToDecoderType(codec_type)),
     54       decoder_(decoder),
     55       callback_(nullptr) {
     56 }
     57 
     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 
     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 
     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 
    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 
    125 int32_t VideoDecoderSoftwareFallbackWrapper::Release() {
    126   if (fallback_decoder_)
    127     fallback_decoder_->Release();
    128   return decoder_->Release();
    129 }
    130 
    131 int32_t VideoDecoderSoftwareFallbackWrapper::Reset() {
    132   if (fallback_decoder_)
    133     fallback_decoder_->Reset();
    134   return decoder_->Reset();
    135 }
    136 
    137 bool VideoDecoderSoftwareFallbackWrapper::PrefersLateDecoding() const {
    138   if (fallback_decoder_)
    139     return fallback_decoder_->PrefersLateDecoding();
    140   return decoder_->PrefersLateDecoding();
    141 }
    142 
    143 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