blob: 0cf34ce74b8d7a42f6dce5f17d8f3f058036d010 [file] [log] [blame] [edit]
// Copyright 2023 The Chromium Authors
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif
#include "fake_image.h"
#include "base/ptr_util.h"
#include "fake_buffer.h"
#include "fake_driver.h"
namespace libvafake {
std::unique_ptr<FakeImage> FakeImage::Create(IdType id,
const VAImageFormat& format,
int width,
int height,
FakeDriver& fake_driver,
VAImage* va_image) {
// Chrome should only request NV12 images from the fake driver.
CHECK_EQ(format.fourcc, static_cast<uint32_t>(VA_FOURCC_NV12));
// Validate the |format|. Chrome should request VA_LSB_FIRST images only.
CHECK_EQ(format.byte_order, static_cast<uint32_t>(VA_LSB_FIRST));
CHECK_EQ(format.bits_per_pixel, 12u);
std::vector<Plane> planes;
planes.emplace_back(/*stride=*/static_cast<uint32_t>(width),
/*offset=*/0);
// TODO(b/358445928): bring back safe math.
// UV stride = ceil(width / 2) * 2.
uint32_t uv_stride = static_cast<uint32_t>(width);
uv_stride += 1;
uv_stride /= 2;
uv_stride *= 2;
// UV offset = Y plane size = width * height.
uint32_t uv_offset = static_cast<uint32_t>(width);
uv_offset *= static_cast<uint32_t>(height);
planes.emplace_back(/*stride=*/uv_stride,
/*offset=*/uv_offset);
// UV plane size = ceil(height / 2) * UV stride.
uint32_t uv_size = static_cast<uint32_t>(height);
uv_size += 1;
uv_size /= 2;
uv_size *= uv_stride;
// Total size = UV offset + UV plane size.
const unsigned int data_size = uv_offset + uv_size;
memset(va_image, 0, sizeof(VAImage));
va_image->image_id = id;
va_image->format = format;
FakeBuffer::IdType buf = fake_driver.CreateBuffer(
/*context=*/VA_INVALID_ID, VAImageBufferType,
/*size_per_element=*/1, data_size, /*data=*/nullptr);
va_image->buf = buf;
va_image->width = static_cast<uint16_t>(width);
va_image->height = static_cast<uint16_t>(height);
va_image->data_size = data_size;
va_image->num_planes = 2;
va_image->pitches[0] = static_cast<uint32_t>(width);
va_image->pitches[1] = uv_stride;
va_image->offsets[0] = 0;
va_image->offsets[1] = uv_offset;
return base::WrapUnique(
new FakeImage(id, format, width, height, std::move(planes),
fake_driver.GetBuffer(buf), fake_driver));
}
FakeImage::FakeImage(FakeImage::IdType id,
const VAImageFormat& format,
int width,
int height,
std::vector<Plane> planes,
const FakeBuffer& buffer,
FakeDriver& driver)
: id_(id),
format_(format),
width_(width),
height_(height),
planes_(std::move(planes)),
buffer_(buffer),
driver_(driver) {}
FakeImage::~FakeImage() {
driver_.DestroyBuffer(buffer_.GetID());
}
FakeImage::IdType FakeImage::GetID() const {
return id_;
}
const VAImageFormat& FakeImage::GetFormat() const {
return format_;
}
int FakeImage::GetWidth() const {
return width_;
}
int FakeImage::GetHeight() const {
return height_;
}
const FakeBuffer& FakeImage::GetBuffer() const {
return buffer_;
}
uint32_t FakeImage::GetPlaneStride(size_t plane) const {
CHECK_LT(plane, planes_.size());
return planes_[plane].stride;
}
uint32_t FakeImage::GetPlaneOffset(size_t plane) const {
CHECK_LT(plane, planes_.size());
return planes_[plane].offset;
}
FakeImage::Plane::Plane(uint32_t stride, uint32_t offset)
: stride(stride), offset(offset) {}
} // namespace libvafake