Home | History | Annotate | Download | only in media
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/renderer/media/rtc_video_decoder_bridge_tv.h"
      6 
      7 #include <queue>
      8 
      9 #include "base/bind.h"
     10 #include "base/callback_helpers.h"
     11 #include "base/location.h"
     12 #include "base/logging.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/singleton.h"
     15 #include "base/message_loop/message_loop_proxy.h"
     16 #include "base/time/time.h"
     17 #include "content/renderer/media/rtc_video_decoder_factory_tv.h"
     18 #include "media/base/bind_to_loop.h"
     19 #include "media/base/decoder_buffer.h"
     20 #include "third_party/libjingle/source/talk/base/ratetracker.h"
     21 
     22 namespace content {
     23 
     24 RTCVideoDecoderBridgeTv::RTCVideoDecoderBridgeTv(
     25     RTCVideoDecoderFactoryTv* factory)
     26     : factory_(factory),
     27       is_initialized_(false),
     28       first_frame_(true) {}
     29 
     30 RTCVideoDecoderBridgeTv::~RTCVideoDecoderBridgeTv() {}
     31 
     32 int32_t RTCVideoDecoderBridgeTv::InitDecode(
     33     const webrtc::VideoCodec* codec_settings,
     34     int32_t number_of_cores) {
     35   // We don't support non-VP8 codec, feedback mode, nor double-initialization
     36   if (codec_settings->codecType != webrtc::kVideoCodecVP8 ||
     37       codec_settings->codecSpecific.VP8.feedbackModeOn || is_initialized_)
     38     return WEBRTC_VIDEO_CODEC_ERROR;
     39   size_ = gfx::Size(codec_settings->width, codec_settings->height);
     40 
     41   is_initialized_ = true;
     42   first_frame_ = true;
     43   factory_->InitializeStream(size_);
     44 
     45   return WEBRTC_VIDEO_CODEC_OK;
     46 }
     47 
     48 int32_t RTCVideoDecoderBridgeTv::Decode(
     49     const webrtc::EncodedImage& input_image,
     50     bool missing_frames,
     51     const webrtc::RTPFragmentationHeader* fragmentation,
     52     const webrtc::CodecSpecificInfo* codec_specific_info,
     53     int64_t render_time_ms) {
     54   // Unlike the SW decoder in libvpx, hw decoder can not handle broken frames.
     55   // Here, we return an error in order to request a key frame.
     56   if (missing_frames || !input_image._completeFrame)
     57     return WEBRTC_VIDEO_CODEC_ERROR;
     58 
     59   if (!is_initialized_)
     60     return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
     61 
     62   if (first_frame_) {
     63     // If the first frame is not a key frame, return an error to request a key
     64     // frame.
     65     if (input_image._frameType != webrtc::kKeyFrame)
     66       return WEBRTC_VIDEO_CODEC_ERROR;
     67 
     68     // Google TV expects timestamp from 0, so we store the initial timestamp as
     69     // an offset and subtract the value from every timestamps to meet the
     70     // expectation.
     71     timestamp_offset_millis_ = render_time_ms;
     72   }
     73   first_frame_ = false;
     74   gfx::Size new_size;
     75   if (input_image._frameType == webrtc::kKeyFrame &&
     76       input_image._encodedWidth != 0 && input_image._encodedHeight != 0) {
     77     // Only a key frame has a meaningful size.
     78     new_size.SetSize(input_image._encodedWidth, input_image._encodedHeight);
     79     if (size_ == new_size)
     80       new_size = gfx::Size();
     81     else
     82       size_ = new_size;
     83   }
     84   // |input_image_| may be destroyed after this call, so we make a copy of the
     85   // buffer so that we can queue the buffer asynchronously.
     86   scoped_refptr<media::DecoderBuffer> buffer =
     87       media::DecoderBuffer::CopyFrom(input_image._buffer, input_image._length);
     88   if (render_time_ms != -1) {
     89     buffer->set_timestamp(base::TimeDelta::FromMilliseconds(
     90         render_time_ms - timestamp_offset_millis_));
     91   }
     92 
     93   factory_->QueueBuffer(buffer, new_size);
     94 
     95   return WEBRTC_VIDEO_CODEC_OK;
     96 }
     97 
     98 int32_t RTCVideoDecoderBridgeTv::RegisterDecodeCompleteCallback(
     99     webrtc::DecodedImageCallback* callback) {
    100   return WEBRTC_VIDEO_CODEC_OK;
    101 }
    102 
    103 int32_t RTCVideoDecoderBridgeTv::Release() {
    104   is_initialized_ = false;
    105   return WEBRTC_VIDEO_CODEC_OK;
    106 }
    107 
    108 int32_t RTCVideoDecoderBridgeTv::Reset() {
    109   first_frame_ = true;
    110   return WEBRTC_VIDEO_CODEC_OK;
    111 }
    112 
    113 }  // namespace content
    114