#include "media/capture/video/shared_memory_buffer_tracker.h"
#include "base/check.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_span.h"
#include "base/notreached.h"
#include "media/base/video_frame.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "ui/gfx/geometry/size.h"
namespace {
class SharedMemoryBufferTrackerHandle : public media::VideoCaptureBufferHandle {
public:
explicit SharedMemoryBufferTrackerHandle(
base::WritableSharedMemoryMapping& mapping)
: span_(mapping.GetMemoryAsSpan<uint8_t>()) {}
size_t mapped_size() const final { return span_.size(); }
base::span<uint8_t> data() final { return span_; }
base::span<const uint8_t> const_data() const final { return span_; }
private:
base::raw_span<uint8_t> span_;
};
size_t CalculateRequiredBufferSize(
const gfx::Size& dimensions,
media::VideoPixelFormat format,
const media::mojom::PlaneStridesPtr& strides) {
if (strides) {
size_t result = 0u;
for (size_t plane_index = 0;
plane_index < media::VideoFrame::NumPlanes(format); plane_index++) {
result +=
strides->stride_by_plane[plane_index] *
media::VideoFrame::Rows(plane_index, format, dimensions.height());
}
return result;
} else {
const auto& frame_format =
media::VideoCaptureFormat(dimensions, 0.0f, format);
return media::VideoFrame::AllocationSize(frame_format.pixel_format,
frame_format.frame_size);
}
}
}
namespace media {
SharedMemoryBufferTracker::SharedMemoryBufferTracker(bool strict_pixel_format)
: strict_pixel_format_(strict_pixel_format) {}
SharedMemoryBufferTracker::~SharedMemoryBufferTracker() = default;
bool SharedMemoryBufferTracker::Init(const gfx::Size& dimensions,
VideoPixelFormat format,
const mojom::PlaneStridesPtr& strides) {
DCHECK(!region_.IsValid());
const size_t buffer_size =
CalculateRequiredBufferSize(dimensions, format, strides);
region_ = base::UnsafeSharedMemoryRegion::Create(buffer_size);
mapping_ = {};
format_ = format;
return region_.IsValid();
}
bool SharedMemoryBufferTracker::IsReusableForFormat(
const gfx::Size& dimensions,
VideoPixelFormat format,
const mojom::PlaneStridesPtr& strides) {
return (!strict_pixel_format_ || format == format_) &&
GetMemorySizeInBytes() >=
CalculateRequiredBufferSize(dimensions, format, strides);
}
std::unique_ptr<VideoCaptureBufferHandle>
SharedMemoryBufferTracker::GetMemoryMappedAccess() {
DCHECK(region_.IsValid());
if (!mapping_.IsValid()) {
mapping_ = region_.Map();
}
DCHECK(mapping_.IsValid());
return std::make_unique<SharedMemoryBufferTrackerHandle>(mapping_);
}
base::UnsafeSharedMemoryRegion
SharedMemoryBufferTracker::DuplicateAsUnsafeRegion() {
DCHECK(region_.IsValid());
return region_.Duplicate();
}
gfx::GpuMemoryBufferHandle
SharedMemoryBufferTracker::GetGpuMemoryBufferHandle() {
NOTREACHED() << "Unsupported operation";
}
VideoCaptureBufferType SharedMemoryBufferTracker::GetBufferType() {
return VideoCaptureBufferType::kSharedMemory;
}
uint32_t SharedMemoryBufferTracker::GetMemorySizeInBytes() {
DCHECK(region_.IsValid());
return region_.GetSize();
}
}