Commit 5a5ed1d0 authored by Dean Liao's avatar Dean Liao Committed by Commit Bot

media: Add VideoFrameLayout class.

As current VideoFrame cannot represent real buffer layout, I
propose to add a new class, VideoFrameLayout, to store size
of physical buffers codec needs as well as format and
coded_size of a frame. Also, it stores stride (bytesperline)
per buffer to calculate each color plane's size.

BUG=b:110815424
TEST=pass media_unittests --gtest_filter=VideoFrameLayout.*

Change-Id: Idf96adff1a5d28d4b60bfb208bb51e197d3292ae
Reviewed-on: https://chromium-review.googlesource.com/1114568
Commit-Queue: Shuo-Peng Liao <deanliao@google.com>
Reviewed-by: default avatarDale Curtis <dalecurtis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#575569}
parent f1d37f3e
...@@ -266,6 +266,8 @@ source_set("base") { ...@@ -266,6 +266,8 @@ source_set("base") {
"video_decoder_config.h", "video_decoder_config.h",
"video_frame.cc", "video_frame.cc",
"video_frame.h", "video_frame.h",
"video_frame_layout.cc",
"video_frame_layout.h",
"video_frame_metadata.cc", "video_frame_metadata.cc",
"video_frame_metadata.h", "video_frame_metadata.h",
"video_frame_pool.cc", "video_frame_pool.cc",
...@@ -514,6 +516,7 @@ source_set("unit_tests") { ...@@ -514,6 +516,7 @@ source_set("unit_tests") {
"video_codecs_unittest.cc", "video_codecs_unittest.cc",
"video_color_space_unittest.cc", "video_color_space_unittest.cc",
"video_decoder_config_unittest.cc", "video_decoder_config_unittest.cc",
"video_frame_layout_unittest.cc",
"video_frame_pool_unittest.cc", "video_frame_pool_unittest.cc",
"video_frame_unittest.cc", "video_frame_unittest.cc",
"video_util_unittest.cc", "video_util_unittest.cc",
......
// Copyright 2018 The Chromium 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 "media/base/video_frame_layout.h"
#include <numeric>
#include <sstream>
namespace {
template <class T>
std::string VectorToString(const std::vector<T>& vec) {
std::ostringstream result;
std::string delim;
result << "[";
for (auto v : vec) {
result << delim << v;
if (delim.size() == 0)
delim = ", ";
}
result << "]";
return result.str();
}
} // namespace
namespace media {
VideoFrameLayout::VideoFrameLayout(VideoPixelFormat format,
const gfx::Size& coded_size,
std::vector<int32_t> strides,
std::vector<size_t> buffer_sizes)
: format_(format),
coded_size_(coded_size),
strides_(std::move(strides)),
buffer_sizes_(std::move(buffer_sizes)) {}
VideoFrameLayout::VideoFrameLayout(const VideoFrameLayout& layout) = default;
VideoFrameLayout::~VideoFrameLayout() = default;
size_t VideoFrameLayout::GetTotalBufferSize() const {
return std::accumulate(buffer_sizes_.begin(), buffer_sizes_.end(), 0u);
}
std::string VideoFrameLayout::ToString() const {
std::ostringstream s;
s << "VideoFrameLayout format:" << VideoPixelFormatToString(format_)
<< " coded_size:" << coded_size_.ToString()
<< " num_buffers:" << num_buffers()
<< " buffer_sizes:" << VectorToString(buffer_sizes_)
<< " num_strides:" << num_strides()
<< " strides:" << VectorToString(strides_);
return s.str();
}
} // namespace media
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_BASE_VIDEO_FRAME_LAYOUT_H_
#define MEDIA_BASE_VIDEO_FRAME_LAYOUT_H_
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "media/base/media_export.h"
#include "media/base/video_types.h"
#include "ui/gfx/geometry/size.h"
namespace media {
// A class to describes how physical buffer is allocated for video frame.
// In stores format, coded size of the frame and size of physical buffers
// which can be used to allocate buffer(s) hardware expected.
// Also, it stores stride (bytes per line) per color plane to calculate each
// color plane's size (note that a buffer may contains multiple color planes.)
class MEDIA_EXPORT VideoFrameLayout {
public:
// Constructor with strides and buffers' size.
VideoFrameLayout(VideoPixelFormat format,
const gfx::Size& coded_size,
std::vector<int32_t> strides = std::vector<int32_t>(),
std::vector<size_t> buffer_sizes = std::vector<size_t>());
VideoFrameLayout(const VideoFrameLayout& layout);
~VideoFrameLayout();
VideoPixelFormat format() const { return format_; }
const gfx::Size& coded_size() const { return coded_size_; }
// Return number of buffers. Note that num_strides >= num_buffers.
size_t num_buffers() const { return buffer_sizes_.size(); }
// Returns number of strides. Note that num_strides >= num_buffers.
size_t num_strides() const { return strides_.size(); }
const std::vector<int32_t>& strides() const { return strides_; }
const std::vector<size_t>& buffer_sizes() const { return buffer_sizes_; }
// Sets strides.
void set_strides(std::vector<int32_t> strides) {
strides_ = std::move(strides);
}
// Sets buffer_sizes.
void set_buffer_sizes(std::vector<size_t> buffer_sizes) {
buffer_sizes_ = std::move(buffer_sizes);
}
// Returns sum of bytes of all buffers.
size_t GetTotalBufferSize() const;
// Composes VideoFrameLayout as human readable string.
std::string ToString() const;
private:
const VideoPixelFormat format_;
// Width and height of the video frame in pixels. This must include pixel
// data for the whole image; i.e. for YUV formats with subsampled chroma
// planes, in the case that the visible portion of the image does not line up
// on a sample boundary, |coded_size_| must be rounded up appropriately and
// the pixel data provided for the odd pixels.
const gfx::Size coded_size_;
// Vector of strides for each buffer, typically greater or equal to the
// width of the surface divided by the horizontal sampling period. Note that
// strides can be negative if the image layout is bottom-up.
std::vector<int32_t> strides_;
// Vector of sizes for each buffer, typically greater or equal to the area of
// |coded_size_|.
std::vector<size_t> buffer_sizes_;
};
} // namespace media
#endif // MEDIA_BASE_VIDEO_FRAME_LAYOUT_H_
// Copyright (c) 2018 The Chromium 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 "media/base/video_frame_layout.h"
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <utility>
#include "media/base/video_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/size.h"
namespace media {
TEST(VideoFrameLayout, Constructor) {
gfx::Size coded_size = gfx::Size(320, 180);
std::vector<int32_t> strides = {384, 192, 192};
std::vector<size_t> buffer_sizes = {73728, 18432, 18432};
VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size, strides, buffer_sizes);
EXPECT_EQ(layout.format(), PIXEL_FORMAT_I420);
EXPECT_EQ(layout.coded_size(), coded_size);
EXPECT_EQ(layout.num_strides(), 3u);
EXPECT_EQ(layout.num_buffers(), 3u);
EXPECT_EQ(layout.GetTotalBufferSize(), 110592u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(layout.strides()[i], strides[i]);
EXPECT_EQ(layout.buffer_sizes()[i], buffer_sizes[i]);
}
}
TEST(VideoFrameLayout, ConstructorNoStrideBufferSize) {
gfx::Size coded_size = gfx::Size(320, 180);
VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size);
EXPECT_EQ(layout.format(), PIXEL_FORMAT_I420);
EXPECT_EQ(layout.coded_size(), coded_size);
EXPECT_EQ(layout.GetTotalBufferSize(), 0u);
EXPECT_EQ(layout.num_strides(), 0u);
EXPECT_EQ(layout.num_buffers(), 0u);
}
TEST(VideoFrameLayout, CopyConstructor) {
gfx::Size coded_size = gfx::Size(320, 180);
std::vector<int32_t> strides = {384, 192, 192};
std::vector<size_t> buffer_sizes = {73728, 18432, 18432};
VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size, strides, buffer_sizes);
VideoFrameLayout layout_copy(layout);
EXPECT_EQ(layout_copy.format(), PIXEL_FORMAT_I420);
EXPECT_EQ(layout_copy.coded_size(), coded_size);
EXPECT_EQ(layout_copy.num_strides(), 3u);
EXPECT_EQ(layout_copy.num_buffers(), 3u);
EXPECT_EQ(layout_copy.GetTotalBufferSize(), 110592u);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(layout_copy.strides()[i], strides[i]);
EXPECT_EQ(layout_copy.buffer_sizes()[i], buffer_sizes[i]);
}
}
TEST(VideoFrameLayout, ToString) {
gfx::Size coded_size = gfx::Size(320, 180);
std::vector<int32_t> strides = {384, 192, 192};
std::vector<size_t> buffer_sizes = {73728, 18432, 18432};
VideoFrameLayout layout(PIXEL_FORMAT_I420, coded_size, strides, buffer_sizes);
EXPECT_EQ(layout.ToString(),
"VideoFrameLayout format:PIXEL_FORMAT_I420 coded_size:320x180 "
"num_buffers:3 buffer_sizes:[73728, 18432, 18432] num_strides:3 "
"strides:[384, 192, 192]");
}
TEST(VideoFrameLayout, ToStringOneBuffer) {
gfx::Size coded_size = gfx::Size(320, 180);
std::vector<int32_t> strides = {384};
std::vector<size_t> buffer_sizes = {122880};
VideoFrameLayout layout(PIXEL_FORMAT_NV12, coded_size, strides, buffer_sizes);
EXPECT_EQ(layout.ToString(),
"VideoFrameLayout format:PIXEL_FORMAT_NV12 coded_size:320x180 "
"num_buffers:1 buffer_sizes:[122880] num_strides:1 strides:[384]");
}
TEST(VideoFrameLayout, ToStringNoBufferInfo) {
gfx::Size coded_size = gfx::Size(320, 180);
VideoFrameLayout layout(PIXEL_FORMAT_NV12, coded_size);
EXPECT_EQ(layout.ToString(),
"VideoFrameLayout format:PIXEL_FORMAT_NV12 coded_size:320x180 "
"num_buffers:0 buffer_sizes:[] num_strides:0 strides:[]");
}
TEST(VideoFrameLayout, SetStrideBufferSize) {
gfx::Size coded_size = gfx::Size(320, 180);
VideoFrameLayout layout(PIXEL_FORMAT_NV12, coded_size);
std::vector<int32_t> strides = {384, 192, 192};
layout.set_strides(std::move(strides));
std::vector<size_t> buffer_sizes = {122880};
layout.set_buffer_sizes(std::move(buffer_sizes));
EXPECT_EQ(layout.ToString(),
"VideoFrameLayout format:PIXEL_FORMAT_NV12 coded_size:320x180 "
"num_buffers:1 buffer_sizes:[122880] num_strides:3 "
"strides:[384, 192, 192]");
}
} // namespace media
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