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