Commit 5749f28d authored by Alexandre Courbot's avatar Alexandre Courbot Committed by Commit Bot

media/gpu: use 0x1000 alignment for user buffers passed to V4L2 devices

User-allocated memory can be passed to some hardware (like video
encoder). Such hardware is generally not happy if the memory is not
page-aligned. This patch adds a new member to VideoFrameLayout that
specifies the desired alignment of the buffer, and make VideoFrame
comply to it when allocating memory. It also makes use of it by
specifying a page-alignment to formats returned by V4L2Device.

Other users of VideoFrame/VideoFrameLayout are not affected by this
CL.

BUG=b:80274650
TEST=Made sure the VEA unittest was working on Hana and Cheza.

Change-Id: Id615ca1ba3f9b253ba774573146a3428c144f57f
Reviewed-on: https://chromium-review.googlesource.com/c/1154769
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#608280}
parent 2540a648
...@@ -1242,7 +1242,7 @@ void VideoFrame::AllocateMemory(bool zero_initialize_memory) { ...@@ -1242,7 +1242,7 @@ void VideoFrame::AllocateMemory(bool zero_initialize_memory) {
} }
uint8_t* data = reinterpret_cast<uint8_t*>( uint8_t* data = reinterpret_cast<uint8_t*>(
base::AlignedAlloc(total_buffer_size, kFrameAddressAlignment)); base::AlignedAlloc(total_buffer_size, layout_.buffer_addr_align()));
if (zero_initialize_memory) { if (zero_initialize_memory) {
memset(data, 0, total_buffer_size); memset(data, 0, total_buffer_size);
} }
......
...@@ -46,9 +46,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { ...@@ -46,9 +46,7 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
kFrameSizeAlignment = 16, kFrameSizeAlignment = 16,
kFrameSizePadding = 16, kFrameSizePadding = 16,
// Note: This value is dependent on what's used by ffmpeg, do not change kFrameAddressAlignment = VideoFrameLayout::kBufferAddressAlignment
// without inspecting av_frame_get_buffer() first.
kFrameAddressAlignment = 32
}; };
enum { enum {
......
...@@ -105,7 +105,8 @@ base::Optional<VideoFrameLayout> VideoFrameLayout::CreateWithPlanes( ...@@ -105,7 +105,8 @@ base::Optional<VideoFrameLayout> VideoFrameLayout::CreateWithPlanes(
VideoPixelFormat format, VideoPixelFormat format,
const gfx::Size& coded_size, const gfx::Size& coded_size,
std::vector<Plane> planes, std::vector<Plane> planes,
std::vector<size_t> buffer_sizes) { std::vector<size_t> buffer_sizes,
size_t buffer_addr_align) {
// NOTE: Even if format is UNKNOWN, it is valid if coded_sizes is not Empty(). // NOTE: Even if format is UNKNOWN, it is valid if coded_sizes is not Empty().
// TODO(crbug.com/896135): Return base::nullopt, // TODO(crbug.com/896135): Return base::nullopt,
// if (format != PIXEL_FORMAT_UNKNOWN || !coded_sizes.IsEmpty()) // if (format != PIXEL_FORMAT_UNKNOWN || !coded_sizes.IsEmpty())
...@@ -114,17 +115,19 @@ base::Optional<VideoFrameLayout> VideoFrameLayout::CreateWithPlanes( ...@@ -114,17 +115,19 @@ base::Optional<VideoFrameLayout> VideoFrameLayout::CreateWithPlanes(
// TODO(crbug.com/896135): Return base::nullopt, // TODO(crbug.com/896135): Return base::nullopt,
// if (buffer_sizes.size() > planes.size()) // if (buffer_sizes.size() > planes.size())
return VideoFrameLayout(format, coded_size, std::move(planes), return VideoFrameLayout(format, coded_size, std::move(planes),
std::move(buffer_sizes)); std::move(buffer_sizes), buffer_addr_align);
} }
VideoFrameLayout::VideoFrameLayout(VideoPixelFormat format, VideoFrameLayout::VideoFrameLayout(VideoPixelFormat format,
const gfx::Size& coded_size, const gfx::Size& coded_size,
std::vector<Plane> planes, std::vector<Plane> planes,
std::vector<size_t> buffer_sizes) std::vector<size_t> buffer_sizes,
size_t buffer_addr_align)
: format_(format), : format_(format),
coded_size_(coded_size), coded_size_(coded_size),
planes_(std::move(planes)), planes_(std::move(planes)),
buffer_sizes_(std::move(buffer_sizes)) {} buffer_sizes_(std::move(buffer_sizes)),
buffer_addr_align_(buffer_addr_align) {}
VideoFrameLayout::~VideoFrameLayout() = default; VideoFrameLayout::~VideoFrameLayout() = default;
VideoFrameLayout::VideoFrameLayout(const VideoFrameLayout&) = default; VideoFrameLayout::VideoFrameLayout(const VideoFrameLayout&) = default;
......
...@@ -30,6 +30,11 @@ namespace media { ...@@ -30,6 +30,11 @@ namespace media {
// Note that it is copyable. // Note that it is copyable.
class MEDIA_EXPORT VideoFrameLayout { class MEDIA_EXPORT VideoFrameLayout {
public: public:
// Default alignment for buffers.
// Note: This value is dependent on what's used by ffmpeg, do not change
// without inspecting av_frame_get_buffer() first.
static constexpr size_t kBufferAddressAlignment = 32;
struct Plane { struct Plane {
Plane() = default; Plane() = default;
Plane(int32_t stride, size_t offset) : stride(stride), offset(offset) {} Plane(int32_t stride, size_t offset) : stride(stride), offset(offset) {}
...@@ -55,6 +60,8 @@ class MEDIA_EXPORT VideoFrameLayout { ...@@ -55,6 +60,8 @@ class MEDIA_EXPORT VideoFrameLayout {
// The size of |buffer_sizes| must be less than or equal to |planes|. // The size of |buffer_sizes| must be less than or equal to |planes|.
// Unless they are specified, num_planes() is NumPlanes(|format|) and // Unless they are specified, num_planes() is NumPlanes(|format|) and
// num_buffers() is 0. // num_buffers() is 0.
// |buffer_addr_align| can be specified to request a specific buffer memory
// alignment.
// The returned base::Optional will be base::nullopt if the configured values // The returned base::Optional will be base::nullopt if the configured values
// are invalid. // are invalid.
static base::Optional<VideoFrameLayout> Create(VideoPixelFormat format, static base::Optional<VideoFrameLayout> Create(VideoPixelFormat format,
...@@ -73,7 +80,8 @@ class MEDIA_EXPORT VideoFrameLayout { ...@@ -73,7 +80,8 @@ class MEDIA_EXPORT VideoFrameLayout {
VideoPixelFormat format, VideoPixelFormat format,
const gfx::Size& coded_size, const gfx::Size& coded_size,
std::vector<Plane> planes, std::vector<Plane> planes,
std::vector<size_t> buffer_sizes = {}); std::vector<size_t> buffer_sizes = {},
size_t buffer_addr_align = kBufferAddressAlignment);
VideoFrameLayout() = delete; VideoFrameLayout() = delete;
VideoFrameLayout(const VideoFrameLayout&); VideoFrameLayout(const VideoFrameLayout&);
...@@ -101,11 +109,17 @@ class MEDIA_EXPORT VideoFrameLayout { ...@@ -101,11 +109,17 @@ class MEDIA_EXPORT VideoFrameLayout {
// Composes VideoFrameLayout as human readable string. // Composes VideoFrameLayout as human readable string.
std::string ToString() const; std::string ToString() const;
// Returns the required memory alignment for buffers.
size_t buffer_addr_align() const {
return buffer_addr_align_;
}
private: private:
VideoFrameLayout(VideoPixelFormat format, VideoFrameLayout(VideoPixelFormat format,
const gfx::Size& coded_size, const gfx::Size& coded_size,
std::vector<Plane> planes, std::vector<Plane> planes,
std::vector<size_t> buffer_sizes); std::vector<size_t> buffer_sizes,
size_t buffer_addr_align);
VideoPixelFormat format_; VideoPixelFormat format_;
...@@ -122,6 +136,11 @@ class MEDIA_EXPORT VideoFrameLayout { ...@@ -122,6 +136,11 @@ class MEDIA_EXPORT VideoFrameLayout {
// Vector of sizes for each buffer, typically greater or equal to the area of // Vector of sizes for each buffer, typically greater or equal to the area of
// |coded_size_|. // |coded_size_|.
std::vector<size_t> buffer_sizes_; std::vector<size_t> buffer_sizes_;
// Memory address alignment of the buffers. This is only relevant when
// allocating physical memory for the buffer, so it doesn't need to be
// serialized when frames are passed through Mojo.
size_t buffer_addr_align_;
}; };
// Outputs VideoFrameLayout::Plane to stream. // Outputs VideoFrameLayout::Plane to stream.
......
...@@ -1288,9 +1288,14 @@ base::Optional<VideoFrameLayout> V4L2Device::V4L2FormatToVideoFrameLayout( ...@@ -1288,9 +1288,14 @@ base::Optional<VideoFrameLayout> V4L2Device::V4L2FormatToVideoFrameLayout(
return base::nullopt; return base::nullopt;
} }
} }
// Some V4L2 devices expect buffers to be page-aligned. We cannot detect
// such devices individually, so set this as a video frame layout property.
constexpr size_t buffer_alignment = 0x1000;
return VideoFrameLayout::CreateWithPlanes( return VideoFrameLayout::CreateWithPlanes(
video_format, gfx::Size(pix_mp.width, pix_mp.height), std::move(planes), video_format, gfx::Size(pix_mp.width, pix_mp.height), std::move(planes),
std::move(buffer_sizes)); std::move(buffer_sizes), buffer_alignment);
} }
void V4L2Device::GetSupportedResolution(uint32_t pixelformat, void V4L2Device::GetSupportedResolution(uint32_t pixelformat,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment