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

Unified Diff: content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.cc

Issue 1549473002: Add ArcGpuVideoDecodeAccelerator. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years 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/common/gpu/media/arc/arc_gpu_video_decode_accelerator.cc
diff --git a/content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.cc b/content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..16c6a2916baa2b2dc3bc12d28f89b98caf83bce8
--- /dev/null
+++ b/content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.cc
@@ -0,0 +1,339 @@
+// 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 "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "content/common/gpu/media/arc/arc_gpu_video_decode_accelerator.h"
+
+namespace content {
+namespace arc {
+
+ArcGpuVideoDecodeAccelerator::BufferInfo::BufferInfo()
+ : state(OWNED_BY_CLIENT), offset(0), length(0) {}
+
+ArcGpuVideoDecodeAccelerator::PortInfo::PortInfo()
+ : memory_type(MEMORY_DMABUF) {}
+
+ArcGpuVideoDecodeAccelerator::InputRecord::InputRecord(
+ int32_t bitstream_buffer_id,
+ uint32_t index,
+ int64_t timestamp)
+ : bitstream_buffer_id(bitstream_buffer_id),
+ index(index),
+ timestamp(timestamp) {}
+
+ArcGpuVideoDecodeAccelerator::ArcGpuVideoDecodeAccelerator()
+ : arc_client_(nullptr) {}
+
+status_t ArcGpuVideoDecodeAccelerator::initialize(
+ DeviceType device,
+ ArcVideoAccelerator::Client* client) {
+ if (device != DEVICE_DECODER)
+ return EINVAL;
+ DCHECK(client);
+ DCHECK(!arc_client_);
+ arc_client_ = client;
+ return 0;
+}
+
+status_t ArcGpuVideoDecodeAccelerator::setBufferCount(PortType port,
+ size_t* count) {
+ if (arc_vda_ == nullptr) {
+ DVLOG(1) << "Must call setBufferFormat before setBufferCount";
+ return EINVAL;
+ }
+ if (port == PORT_OUTPUT) {
+ size_t try_count = *count;
+ for (; try_count > 0; --try_count) {
+ if (arc_vda_->SetPictureCount(*count)) {
+ *count = try_count;
+ break;
+ }
+ }
+ if (try_count == 0) {
+ DVLOG(1) << "Failed to find valid buffer count";
+ return EIO;
+ }
+ }
+ PortInfo* port_info = &port_info_[port];
kcwu 2015/12/23 06:25:43 validate value of |port|
Owen Lin 2015/12/31 07:22:14 Done.
+ port_info->buffers.clear();
+ port_info->buffers.resize(*count);
+ return 0;
+}
+
+status_t ArcGpuVideoDecodeAccelerator::setBufferFormat(
+ PortType port,
+ const BufferFormat& format) {
+ PortInfo* port_info = &port_info_[port];
+ switch (port) {
+ case PORT_INPUT:
+ if (format.memory_type != MEMORY_SHARED_MEMORY) {
+ DVLOG(1) << "Only SharedMemory is supported for input buffers";
+ return EINVAL;
+ }
+ port_info->memory_type = format.memory_type;
+ switch (format.pixel_format) {
+ case HAL_PIXEL_FORMAT_H264:
+ case HAL_PIXEL_FORMAT_VP8:
+ arc_vda_ = nullptr; // TODO(owenlin): Change to real implementation.
+ break;
+ default:
+ DVLOG(1) << "Unsupported input format: " << format.pixel_format;
+ return EINVAL;
+ }
+ break;
+ case PORT_OUTPUT:
+ if (format.memory_type != MEMORY_DMABUF) {
+ DVLOG(1) << "Only DMA buffer is supported for output buffers";
+ return EINVAL;
+ }
+ port_info->memory_type = format.memory_type;
+ break;
+ default:
+ NOTREACHED();
kcwu 2015/12/23 06:25:43 return EINVAL; |port| may come from less trusted c
Owen Lin 2015/12/31 07:22:14 Done.
+ }
+ return 0;
+}
+
+ArcGpuVideoDecodeAccelerator::BufferInfo*
+ArcGpuVideoDecodeAccelerator::GetBufferInfo(PortType port, uint32_t index) {
+ if (port < 0 || port >= PORT_COUNT)
+ return nullptr;
+ std::vector<BufferInfo>* buffers = &port_info_[port].buffers;
kcwu 2015/12/23 06:25:43 How about: auto& buffers = port_info_[port].buffer
Owen Lin 2015/12/31 07:22:14 Done.
+ return index >= buffers->size() ? nullptr : &buffers->at(index);
+}
+
+status_t ArcGpuVideoDecodeAccelerator::bindSharedBuffer(PortType port,
+ uint32_t index,
+ int ashmem_fd,
+ size_t offset,
+ size_t length) {
+ // Make sure we will close the file descriptor.
+ base::ScopedFD handle(ashmem_fd);
+ PortInfo* port_info = &port_info_[port];
kcwu 2015/12/23 06:25:43 Value of |port| need to validate. Please either 1.
Owen Lin 2015/12/31 07:22:14 Done.
+ if (port_info->memory_type != MEMORY_SHARED_MEMORY) {
+ DVLOG(1) << "Unmatched memory type: " << port_info->memory_type;
+ return EINVAL;
+ }
+ BufferInfo* buffer_info = GetBufferInfo(port, index);
+ if (buffer_info == nullptr) {
+ DVLOG(1) << "Invalid buffer port: " << port << " index: " << index;
+ return EINVAL;
+ }
+ if (buffer_info->state != OWNED_BY_CLIENT) {
+ DVLOG(1) << "Cannot bind a buffer while in use";
+ return EINVAL;
+ }
+ buffer_info->handle = std::move(handle);
+ buffer_info->offset = offset;
+ buffer_info->length = length;
+ return 0;
+}
+
+status_t ArcGpuVideoDecodeAccelerator::bindGraphicBuffer(PortType port,
+ uint32_t index,
+ int dmabuf_fd) {
+ // Make sure we will close the file descriptor.
+ base::ScopedFD handle(dmabuf_fd);
+ PortInfo* port_info = &port_info_[port];
kcwu 2015/12/23 06:25:43 Ditto, check value of |port|
Owen Lin 2015/12/31 07:22:14 Done.
+ if (port_info->memory_type != MEMORY_DMABUF) {
+ DVLOG(1) << "Unmatched memory type: " << port_info->memory_type;
+ return EINVAL;
+ }
+ BufferInfo* buffer_info = GetBufferInfo(port, index);
+ if (buffer_info == nullptr) {
+ DVLOG(1) << "Invalid buffer port: " << port << " index: " << index;
+ return EINVAL;
+ }
+ if (buffer_info->state != OWNED_BY_CLIENT) {
+ DVLOG(1) << "Cannot bind a buffer while in use";
+ return EINVAL;
+ }
+ return arc_vda_->AssignPictureBuffer(index, std::move(handle)) ? 0 : EIO;
+}
+
+void ArcGpuVideoDecodeAccelerator::useBuffer(PortType port,
+ uint32_t index,
+ const BufferMetadata& metadata) {
+ BufferInfo* buffer_info = GetBufferInfo(port, index);
+ if (buffer_info == nullptr) {
+ DVLOG(1) << "Invalid buffer port: " << port << ", index: " << index;
+ arc_client_->onError(INVALID_ARGUMENT);
+ return;
+ }
+ if (!buffer_info->handle.is_valid()) {
+ DVLOG(1) << "Must bind a buffer before using it, port: " << port
+ << ", index: " << index;
+ arc_client_->onError(ILLEGAL_STATE);
+ return;
+ }
+ buffer_info->state = OWNED_BY_US;
+ switch (port) {
+ case PORT_INPUT: {
+ if (metadata.flags & BUFFER_FLAG_EOS) {
+ // Ask VDA to return all output pictures so that we can output an EOS
+ // picture when Flush() is done.
+ arc_vda_->Flush(true);
+ }
+ if (metadata.bytes_used > 0) {
+ int32_t bitstream_buffer_id = bitstream_buffer_serial_++;
+ if (bitstream_buffer_serial_ < 0)
+ bitstream_buffer_serial_ = 0;
+ SetInputRecord(bitstream_buffer_id, index, metadata.timestamp);
+ base::SharedMemoryHandle shared_memory_handle(buffer_info->handle.get(),
kcwu 2015/12/23 06:25:43 when will the handle be closed?
Owen Lin 2015/12/31 07:22:14 For now, it will be close when this ArcGVDA destro
+ false);
+ // TODO(owenlin): Make BitstreamBuffer surpport offset and use here.
+ media::BitstreamBuffer bitstream_buffer(
+ bitstream_buffer_id, shared_memory_handle, buffer_info->length);
+ buffer_info->state = OWNED_BY_VDA;
+ arc_vda_->Decode(bitstream_buffer);
+ } else {
+ buffer_info->state = OWNED_BY_CLIENT;
+ arc_client_->onBufferDone(PORT_INPUT, index, BufferMetadata());
+ }
+ break;
+ }
+ case PORT_OUTPUT: {
+ SendEosIfNeededOrReusePicture(index, buffer_info);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+void ArcGpuVideoDecodeAccelerator::reset() {
+ base::RunLoop loop;
+ reset_done_callback_ = loop.QuitClosure();
+ arc_vda_->Reset();
+ base::MessageLoop::ScopedNestableTaskAllower allow(
+ base::MessageLoop::current());
+ // Wait for the ResetDone callback.
+ loop.Run();
+}
+
+void ArcGpuVideoDecodeAccelerator::RequestPictureBuffers(
+ size_t requested_num_of_buffers,
+ const gfx::Size& coded_size,
+ const gfx::Rect& crop_rect) {
+ // TODO(owenlin): Think if we need to handle the pixel format.
+ // It looks like the flexible pixel format is good enough.
+ VideoFormat video_format;
+ video_format.min_num_buffers = requested_num_of_buffers;
+ video_format.coded_width = coded_size.width();
+ video_format.coded_height = coded_size.height();
+ video_format.crop_left = crop_rect.x();
+ video_format.crop_top = crop_rect.y();
+ video_format.crop_width = crop_rect.width();
+ video_format.crop_height = crop_rect.height();
+ arc_client_->onOutputFormatChanged(video_format);
+}
+
+void ArcGpuVideoDecodeAccelerator::PictureReady(const media::Picture& picture) {
+ BufferInfo* output_buffer =
+ GetBufferInfo(PORT_OUTPUT, picture.picture_buffer_id());
+ CHECK_NE(output_buffer, nullptr);
+
+ // Empty buffer, returned in Flushing.
+ if (picture.bitstream_buffer_id() == -1) {
+ output_buffer->state = OWNED_BY_US;
+ } else {
+ BufferMetadata metadata;
+ uint32_t index = 0;
+ GetInputRecord(picture.bitstream_buffer_id(), &index, &metadata.timestamp);
+ output_buffer->state = OWNED_BY_CLIENT;
+ arc_client_->onBufferDone(PORT_OUTPUT, picture.picture_buffer_id(),
+ metadata);
+ }
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer(
+ int32_t bitstream_buffer_id) {
+ int64_t timestamp = 0;
+ uint32_t index = 0;
+ GetInputRecord(bitstream_buffer_id, &index, &timestamp);
+ BufferInfo* buffer_info = GetBufferInfo(PORT_OUTPUT, index);
+ CHECK(buffer_info);
+ buffer_info->state = OWNED_BY_CLIENT;
+ arc_client_->onBufferDone(PORT_INPUT, bitstream_buffer_id, BufferMetadata());
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyFlushDone() {
+ pending_eos_output_buffer_ = true;
+ std::vector<BufferInfo>* buffers = &port_info_[PORT_OUTPUT].buffers;
+ for (size_t i = 0, n = buffers->size(); i < n; ++i) {
+ BufferInfo* info = &buffers->at(i);
+ if (info->state == OWNED_BY_US)
+ SendEosIfNeededOrReusePicture(i, info);
+ }
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyResetDone() {
+ base::ResetAndReturn(&reset_done_callback_).Run();
+}
+
+static ArcVideoAccelerator::Error convertErrorCode(
kcwu 2015/12/23 06:25:43 s/convert/Convert/
Owen Lin 2015/12/31 07:22:14 Done.
+ ArcVideoDecodeAccelerator::Error error) {
+#define CASE(t) \
+ case ArcVideoDecodeAccelerator::t: \
+ return ArcVideoAccelerator::t
+ switch (error) {
+ CASE(ILLEGAL_STATE);
+ CASE(INVALID_ARGUMENT);
+ CASE(UNREADABLE_INPUT);
+ CASE(PLATFORM_FAILURE);
+ default:
+ NOTREACHED() << "Unknown error: " << error;
+ }
+#undef CASE
+ return static_cast<ArcVideoAccelerator::Error>(error);
+}
+
+void ArcGpuVideoDecodeAccelerator::NotifyError(
+ ArcVideoDecodeAccelerator::Error error) {
+ arc_client_->onError(convertErrorCode(error));
+}
+
+void ArcGpuVideoDecodeAccelerator::SendEosIfNeededOrReusePicture(
+ uint32_t index,
+ BufferInfo* info) {
+ DCHECK_EQ(info->state, OWNED_BY_US);
+ if (pending_eos_output_buffer_) {
+ BufferMetadata metadata;
+ metadata.flags = BUFFER_FLAG_EOS;
+ info->state = OWNED_BY_CLIENT;
+ arc_client_->onBufferDone(PORT_OUTPUT, index, metadata);
+ pending_eos_output_buffer_ = false;
+ } else {
+ info->state = OWNED_BY_VDA;
+ arc_vda_->ReusePictureBuffer(index);
+ }
+}
+
+void ArcGpuVideoDecodeAccelerator::SetInputRecord(int32_t bitstream_buffer_id,
+ uint32_t index,
+ int64_t timestamp) {
+ input_records_.push_front(InputRecord(bitstream_buffer_id, index, timestamp));
+ // The value is copied from media::GpuVideoDecoder.
+ static const size_t kMaxInputBufferDataSize = 128;
kcwu 2015/12/23 06:25:43 s/static// local constant doesn't need static stor
Owen Lin 2015/12/31 07:22:14 Done.
+ if (input_records_.size() > kMaxInputBufferDataSize)
+ input_records_.pop_back();
+}
+
+void ArcGpuVideoDecodeAccelerator::GetInputRecord(int32_t bitstream_buffer_id,
+ uint32_t* index,
+ int64_t* timestamp) {
+ for (auto& data : input_records_) {
+ if (data.bitstream_buffer_id == bitstream_buffer_id) {
+ *index = data.index;
+ *timestamp = data.timestamp;
+ return;
+ }
+ }
+ NOTREACHED() << "Missing bitstream_buffer_id: " << bitstream_buffer_id;
+}
+
+} // arc
+} // content

Powered by Google App Engine
This is Rietveld 408576698