[go: nahoru, domu]

blob: 6e541f64d558b369ec633f63ceea5e231482fc49 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/gpu/chromeos/chromeos_compressed_gpu_memory_buffer_video_frame_utils.h"
#include <drm_fourcc.h>
#include <stdint.h>
#include "base/logging.h"
#include "base/time/time.h"
#include "media/base/color_plane_layout.h"
#include "media/base/format_utils.h"
#include "media/base/video_frame.h"
#include "media/base/video_types.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace media {
scoped_refptr<VideoFrame> WrapChromeOSCompressedGpuMemoryBufferAsVideoFrame(
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
std::unique_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer,
base::TimeDelta timestamp) {
const absl::optional<VideoPixelFormat> format =
GfxBufferFormatToVideoPixelFormat(gpu_memory_buffer->GetFormat());
if (!format ||
(*format != PIXEL_FORMAT_NV12 && *format != PIXEL_FORMAT_P016LE)) {
return nullptr;
}
constexpr VideoFrame::StorageType storage =
VideoFrame::STORAGE_GPU_MEMORY_BUFFER;
const gfx::Size& coded_size = gpu_memory_buffer->GetSize();
if (!VideoFrame::IsValidConfig(*format, storage, coded_size, visible_rect,
natural_size)) {
DLOG(ERROR) << __func__ << " Invalid config"
<< VideoFrame::ConfigToString(*format, storage, coded_size,
visible_rect, natural_size);
return nullptr;
}
CHECK_EQ(gpu_memory_buffer->GetType(), gfx::NATIVE_PIXMAP);
gfx::GpuMemoryBufferHandle gmb_handle = gpu_memory_buffer->CloneHandle();
if (gmb_handle.is_null() || gmb_handle.native_pixmap_handle.planes.empty()) {
DLOG(ERROR) << "Failed to clone the GpuMemoryBufferHandle";
return nullptr;
}
const uint64_t modifier = gmb_handle.native_pixmap_handle.modifier;
if (!IsIntelMediaCompressedModifier(modifier)) {
return nullptr;
}
constexpr size_t kExpectedNumberOfPlanes = 4u;
if (gmb_handle.native_pixmap_handle.planes.size() !=
kExpectedNumberOfPlanes) {
DLOG(ERROR) << "Invalid number of planes="
<< gmb_handle.native_pixmap_handle.planes.size()
<< ", expected num_planes=" << kExpectedNumberOfPlanes;
return nullptr;
}
std::vector<ColorPlaneLayout> planes(kExpectedNumberOfPlanes);
for (size_t i = 0; i < kExpectedNumberOfPlanes; ++i) {
const auto& plane = gmb_handle.native_pixmap_handle.planes[i];
planes[i].stride = plane.stride;
planes[i].offset = plane.offset;
planes[i].size = plane.size;
}
const auto layout = VideoFrameLayout::CreateWithPlanes(
*format, coded_size, std::move(planes),
VideoFrameLayout::kBufferAddressAlignment, modifier);
if (!layout) {
DLOG(ERROR) << __func__ << " Invalid layout";
return nullptr;
}
scoped_refptr<VideoFrame> frame =
new VideoFrame(*layout, storage, visible_rect, natural_size, timestamp);
if (!frame) {
DLOG(ERROR) << __func__ << " Couldn't create ChromeOS VideoFrame instance";
return nullptr;
}
frame->gpu_memory_buffer_ = std::move(gpu_memory_buffer);
return frame;
}
bool IsIntelMediaCompressedModifier(uint64_t modifier) {
return modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
modifier == I915_FORMAT_MOD_4_TILED_MTL_MC_CCS;
}
std::string IntelMediaCompressedModifierToString(uint64_t modifier) {
switch (modifier) {
case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS:
return "I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS";
case I915_FORMAT_MOD_4_TILED_MTL_MC_CCS:
return "I915_FORMAT_MOD_4_TILED_MTL_MC_CCS";
}
NOTREACHED() << "Invalid Intel Media Compressed modifier provided: "
<< modifier;
return "";
}
} // namespace media