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

Unified Diff: content/common/gpu/media/vp8_decoder.cc

Issue 813693006: Add accelerated video decoder interface, VP8 and H.264 implementations and hook up to V4L2SVDA (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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
« no previous file with comments | « content/common/gpu/media/vp8_decoder.h ('k') | content/common/gpu/media/vp8_picture.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/common/gpu/media/vp8_decoder.cc
diff --git a/content/common/gpu/media/vp8_decoder.cc b/content/common/gpu/media/vp8_decoder.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fc3793c752719199f5ac19e5230d56c0ae9cdbe6
--- /dev/null
+++ b/content/common/gpu/media/vp8_decoder.cc
@@ -0,0 +1,186 @@
+// Copyright 2015 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/common/gpu/media/vp8_decoder.h"
+#include "media/base/limits.h"
+
+namespace content {
+
+VP8Decoder::VP8Accelerator::VP8Accelerator() {
+}
+
+VP8Decoder::VP8Accelerator::~VP8Accelerator() {
+}
+
+VP8Decoder::VP8Decoder(VP8Accelerator* accelerator)
+ : state_(kNeedStreamMetadata),
+ curr_frame_start_(nullptr),
+ frame_size_(0),
+ accelerator_(accelerator) {
+ DCHECK(accelerator_);
+}
+
+VP8Decoder::~VP8Decoder() {
+}
+
+bool VP8Decoder::Flush() {
+ DVLOG(2) << "Decoder flush";
+ Reset();
+ return true;
+}
+
+void VP8Decoder::SetStream(const uint8_t* ptr, size_t size) {
+ DCHECK(ptr);
+ DCHECK(size);
+
+ curr_frame_start_ = ptr;
+ frame_size_ = size;
+ DVLOG(4) << "New input stream at: " << (void*)ptr << " size: " << size;
+}
+
+void VP8Decoder::Reset() {
+ curr_pic_ = nullptr;
+ curr_frame_hdr_ = nullptr;
+ curr_frame_start_ = nullptr;
+ frame_size_ = 0;
+
+ last_frame_ = nullptr;
+ golden_frame_ = nullptr;
+ alt_frame_ = nullptr;
+
+ if (state_ == kDecoding)
+ state_ = kAfterReset;
+}
+
+VP8Decoder::DecodeResult VP8Decoder::Decode() {
+ if (!curr_frame_start_ || frame_size_ == 0)
+ return kRanOutOfStreamData;
+
+ if (!curr_frame_hdr_) {
+ curr_frame_hdr_.reset(new media::Vp8FrameHeader());
+ if (!parser_.ParseFrame(curr_frame_start_, frame_size_,
+ curr_frame_hdr_.get())) {
+ DVLOG(1) << "Error during decode";
+ state_ = kError;
+ return kDecodeError;
+ }
+ }
+
+ if (curr_frame_hdr_->IsKeyframe()) {
+ gfx::Size new_pic_size(curr_frame_hdr_->width, curr_frame_hdr_->height);
+ if (new_pic_size.IsEmpty())
+ return kDecodeError;
+
+ if (new_pic_size != pic_size_) {
+ DVLOG(2) << "New resolution: " << new_pic_size.ToString();
+ pic_size_ = new_pic_size;
+ return kAllocateNewSurfaces;
+ }
+
+ state_ = kDecoding;
+ } else {
+ if (state_ != kDecoding) {
+ // Need a resume point.
+ curr_frame_hdr_.reset();
+ return kRanOutOfStreamData;
+ }
+ }
+
+ curr_pic_ = accelerator_->CreateVP8Picture();
+ if (!curr_pic_)
+ return kRanOutOfSurfaces;
+
+ if (!DecodeAndOutputCurrentFrame())
+ return kDecodeError;
+
+ return kRanOutOfStreamData;
+}
+
+void VP8Decoder::RefreshReferenceFrames() {
+ if (curr_frame_hdr_->IsKeyframe()) {
+ last_frame_ = curr_pic_;
+ golden_frame_ = curr_pic_;
+ alt_frame_ = curr_pic_;
+ return;
+ }
+
+ // Save current golden since we overwrite it here,
+ // but may have to use it to update alt below.
+ scoped_refptr<VP8Picture> curr_golden = golden_frame_;
+
+ if (curr_frame_hdr_->refresh_golden_frame) {
+ golden_frame_ = curr_pic_;
+ } else {
+ switch (curr_frame_hdr_->copy_buffer_to_golden) {
+ case media::Vp8FrameHeader::COPY_LAST_TO_GOLDEN:
+ DCHECK(last_frame_);
+ golden_frame_ = last_frame_;
+ break;
+
+ case media::Vp8FrameHeader::COPY_ALT_TO_GOLDEN:
+ DCHECK(alt_frame_);
+ golden_frame_ = alt_frame_;
+ break;
+ }
+ }
+
+ if (curr_frame_hdr_->refresh_alternate_frame) {
+ alt_frame_ = curr_pic_;
+ } else {
+ switch (curr_frame_hdr_->copy_buffer_to_alternate) {
+ case media::Vp8FrameHeader::COPY_LAST_TO_ALT:
+ DCHECK(last_frame_);
+ alt_frame_ = last_frame_;
+ break;
+
+ case media::Vp8FrameHeader::COPY_GOLDEN_TO_ALT:
+ DCHECK(curr_golden);
+ alt_frame_ = curr_golden;
+ break;
+ }
+ }
+
+ if (curr_frame_hdr_->refresh_last)
+ last_frame_ = curr_pic_;
+}
+
+bool VP8Decoder::DecodeAndOutputCurrentFrame() {
+ DCHECK(!pic_size_.IsEmpty());
+ DCHECK(curr_pic_);
+ DCHECK(curr_frame_hdr_);
+
+ if (curr_frame_hdr_->IsKeyframe()) {
+ horizontal_scale_ = curr_frame_hdr_->horizontal_scale;
+ vertical_scale_ = curr_frame_hdr_->vertical_scale;
+ } else {
+ // Populate fields from decoder state instead.
+ curr_frame_hdr_->width = pic_size_.width();
+ curr_frame_hdr_->height = pic_size_.height();
+ curr_frame_hdr_->horizontal_scale = horizontal_scale_;
+ curr_frame_hdr_->vertical_scale = vertical_scale_;
+ }
+
+ if (!accelerator_->SubmitDecode(curr_pic_, curr_frame_hdr_.get(), last_frame_,
+ golden_frame_, alt_frame_))
+ return false;
+
+ if (!accelerator_->OutputPicture(curr_pic_))
+ return false;
+
+ RefreshReferenceFrames();
+
+ curr_pic_ = nullptr;
+ curr_frame_hdr_ = nullptr;
+ curr_frame_start_ = nullptr;
+ frame_size_ = 0;
+ return true;
+}
+
+size_t VP8Decoder::GetRequiredNumOfPictures() const {
+ const size_t kVP8NumFramesActive = 4;
+ const size_t kPicsInPipeline = media::limits::kMaxVideoFrames + 2;
+ return kVP8NumFramesActive + kPicsInPipeline;
+}
+
+} // namespace content
« no previous file with comments | « content/common/gpu/media/vp8_decoder.h ('k') | content/common/gpu/media/vp8_picture.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698