Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Unified Diff: content/renderer/media/rtc_video_decoder_bridge_tv.cc

Issue 14247018: Implement WebRTC in Chrome for TV (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: nits Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/rtc_video_decoder_bridge_tv.cc
diff --git a/content/renderer/media/rtc_video_decoder_bridge_tv.cc b/content/renderer/media/rtc_video_decoder_bridge_tv.cc
new file mode 100644
index 0000000000000000000000000000000000000000..999e0bc7adc52a17bf4fcf85a0dbc2f2bdc4fc28
--- /dev/null
+++ b/content/renderer/media/rtc_video_decoder_bridge_tv.cc
@@ -0,0 +1,141 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/rtc_video_decoder_bridge_tv.h"
+
+#include <queue>
+
+#include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "base/message_loop_proxy.h"
+#include "base/time.h"
+#include "content/renderer/media/rtc_video_decoder_factory_tv.h"
+#include "media/base/bind_to_loop.h"
+#include "media/base/decoder_buffer.h"
+#include "third_party/libjingle/source/talk/base/ratetracker.h"
+
+namespace content {
+
+RTCVideoDecoderBridgeTv::RTCVideoDecoderBridgeTv(
+ RTCVideoDecoderFactoryTv* factory)
+ : factory_(factory),
+ is_initialized_(false),
+ first_frame_(true),
+ decode_complete_callback_(NULL) {}
+
+RTCVideoDecoderBridgeTv::~RTCVideoDecoderBridgeTv() {}
+
+int32_t RTCVideoDecoderBridgeTv::InitDecode(
+ const webrtc::VideoCodec* codecSettings,
+ int32_t numberOfCores) {
+ if (codecSettings->codecType != webrtc::kVideoCodecVP8)
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ // We don't support feedback mode.
+ if (codecSettings->codecSpecific.VP8.feedbackModeOn)
+ return WEBRTC_VIDEO_CODEC_ERROR;
+
+ if (is_initialized_)
+ return WEBRTC_VIDEO_CODEC_ERROR;
+ size_ = gfx::Size(codecSettings->width, codecSettings->height);
+ is_initialized_ = true;
+ first_frame_ = true;
+ factory_->InitializeStream(size_);
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderBridgeTv::Decode(
+ const webrtc::EncodedImage& inputImage,
+ bool missingFrames,
+ const webrtc::RTPFragmentationHeader* /* fragmentation */,
+ const webrtc::CodecSpecificInfo* /* codecSpecificInfo */,
+ int64_t renderTimeMs) {
+ // Unlike the SW decoder in libvpx, hw decoder can not handle broken frames.
+ // Here, we return an error in order to request a key frame.
+ if (missingFrames || !inputImage._completeFrame)
+ return WEBRTC_VIDEO_CODEC_ERROR;
+
+ if (!is_initialized_ || decode_complete_callback_ == NULL)
+ return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+
+ if (first_frame_) {
+ // If the first frame is not a key frame, return an error to request a key
+ // frame.
+ if (inputImage._frameType != webrtc::kKeyFrame)
+ return WEBRTC_VIDEO_CODEC_ERROR;
+
+ // Google TV expects timestamp from 0, so we store the initial timestamp as
+ // an offset and subtract the value from every timestamps to meet the
+ // expectation.
+ timestamp_offset_millis_ = renderTimeMs;
+ }
+ first_frame_ = false;
+ gfx::Size new_size;
+ if (inputImage._frameType == webrtc::kKeyFrame &&
+ inputImage._encodedWidth != 0 &&
+ inputImage._encodedHeight != 0) {
+ // Only a key frame has a meaningful size.
+ new_size.SetSize(inputImage._encodedWidth, inputImage._encodedHeight);
+ if (size_ == new_size)
+ new_size = gfx::Size();
+ else
+ size_ = new_size;
+ }
+ // |inputImage_| may be destroyed after this call, so we make a copy of the
+ // buffer so that we can queue the buffer asynchronously.
+ scoped_refptr<media::DecoderBuffer> buffer =
+ media::DecoderBuffer::CopyFrom(inputImage._buffer, inputImage._length);
+ if (renderTimeMs != -1) {
+ buffer->SetTimestamp(base::TimeDelta::FromMilliseconds(
+ renderTimeMs - timestamp_offset_millis_));
+ }
+
+ factory_->QueueBuffer(
+ buffer,
+ base::Bind(&RTCVideoDecoderBridgeTv::RunDecodeCompleteCallback,
+ decode_complete_callback_,
+ inputImage._timeStamp),
+ new_size);
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderBridgeTv::RegisterDecodeCompleteCallback(
+ webrtc::DecodedImageCallback* callback) {
+ decode_complete_callback_ = callback;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderBridgeTv::Release() {
+ is_initialized_ = false;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t RTCVideoDecoderBridgeTv::Reset() {
+ first_frame_ = true;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+// static
+void RTCVideoDecoderBridgeTv::RunDecodeCompleteCallback(
+ webrtc::DecodedImageCallback* callback,
+ int64_t timestamp) {
+ // We call the decode complete callback function to notify libjingle that
+ // decoding is finished. In addition, this also reports back to libjingle that
+ // the particular video frame with |timestamp| is correctly rendered to
+ // libjingle, so that it can generate proper stats.
+ webrtc::I420VideoFrame dummy_video_frame;
+ // Smallest possible non-zero I420 image is 2x2 square, with stride_y being 2
+ // and stride_u & stride_v being 1. In other words, this dummy frame contains
+ // 2x2 y values and 1x1 u & v values each.
+ dummy_video_frame.CreateEmptyFrame(2, 2, 2, 1, 1);
+ dummy_video_frame.set_timestamp(timestamp);
+ callback->Decoded(dummy_video_frame);
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698