blob: 6c76d7e8e7fa9a70b5c89e6a0ed5d08e43349195 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 <lib/media/test/codec_buffer.h>
#include <lib/fxl/logging.h>
#include <zx/vmar.h>
#include <zx/vmo.h>
#include <stdio.h>
CodecBuffer::CodecBuffer(uint32_t buffer_index, size_t size_bytes)
: buffer_index_(buffer_index), size_bytes_(size_bytes) {}
uint32_t CodecBuffer::buffer_index() { return buffer_index_; }
void CodecBuffer::SetPhysicallyContiguousRequired(
const ::zx::handle& very_temp_kludge_bti_handle) {
is_physically_contiguous_required_ = true;
zx_status_t status =
::zx::unowned_bti(very_temp_kludge_bti_handle.get())
->duplicate(ZX_RIGHT_SAME_RIGHTS, &very_temp_kludge_bti_handle_);
FXL_CHECK(status == ZX_OK);
}
bool CodecBuffer::Init() {
zx::vmo local_vmo;
zx_status_t res;
// Create the VMO.
if (is_physically_contiguous_required_) {
res = zx_vmo_create_contiguous(very_temp_kludge_bti_handle_.get(),
size_bytes_, 0,
local_vmo.reset_and_get_address());
if (res != ZX_OK) {
printf(
"Failed to create _physically contiguous_ %zu byte buffer vmo (res "
"%d)\n",
size_bytes_, res);
return false;
}
} else {
res = zx::vmo::create(size_bytes_, 0, &local_vmo);
if (res != ZX_OK) {
printf("Failed to create %zu byte buffer vmo (res %d)\n", size_bytes_,
res);
return false;
}
}
// Map the VMO in the local address space.
uintptr_t tmp;
res = zx::vmar::root_self()->map(0, local_vmo, 0, size_bytes_,
ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, &tmp);
if (res != ZX_OK) {
printf("Failed to map %zu byte buffer vmo (res %d)\n", size_bytes_, res);
return false;
}
base_ = reinterpret_cast<uint8_t*>(tmp);
// If we don't make it to here, then local_vmo takes care of freeing the
// zx::vmo as needed.
vmo_ = std::move(local_vmo);
return true;
}
CodecBuffer::~CodecBuffer() {
if (base_) {
zx_status_t res = zx::vmar::root_self()->unmap(
reinterpret_cast<uintptr_t>(base_), size_bytes_);
if (res != ZX_OK) {
FXL_LOG(FATAL) << "Failed to unmap " << size_bytes_
<< " byte buffer vmo (res " << res << ") - exiting";
}
base_ = nullptr;
}
}
bool CodecBuffer::GetDupVmo(bool is_for_write, zx::vmo* out_vmo) {
zx_rights_t rights = ZX_RIGHTS_BASIC | ZX_RIGHT_READ | ZX_RIGHT_MAP;
if (is_for_write) {
rights |= ZX_RIGHT_WRITE;
}
zx_status_t res = vmo_.duplicate(rights, out_vmo);
if (res != ZX_OK) {
printf("Failed to duplicate buffer vmo handle (res %d)\n", res);
return false;
}
return true;
}
// A real client would want to enforce a max allocation size before size_bytes
// gets here.
std::unique_ptr<CodecBuffer> CodecBuffer::Allocate(
uint32_t buffer_index,
const fuchsia::media::StreamBufferConstraints& constraints) {
std::unique_ptr<CodecBuffer> result(new CodecBuffer(
buffer_index, constraints.per_packet_buffer_bytes_recommended));
if (constraints.is_physically_contiguous_required) {
result->SetPhysicallyContiguousRequired(
constraints.very_temp_kludge_bti_handle);
}
if (!result->Init()) {
return nullptr;
}
return result;
}