You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
6.7 KiB
184 lines
6.7 KiB
/*
|
|
* Copyright 2019 The libgav1 Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef LIBGAV1_SRC_YUV_BUFFER_H_
|
|
#define LIBGAV1_SRC_YUV_BUFFER_H_
|
|
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
#include <type_traits>
|
|
|
|
#include "src/gav1/frame_buffer.h"
|
|
#include "src/utils/constants.h"
|
|
|
|
namespace libgav1 {
|
|
|
|
class YuvBuffer {
|
|
public:
|
|
// Allocates the buffer. Returns true on success. Returns false on failure.
|
|
//
|
|
// * |width| and |height| are the image dimensions in pixels.
|
|
// * |subsampling_x| and |subsampling_y| (either 0 or 1) specify the
|
|
// subsampling of the width and height of the chroma planes, respectively.
|
|
// * |left_border|, |right_border|, |top_border|, and |bottom_border| are
|
|
// the sizes (in pixels) of the borders on the left, right, top, and
|
|
// bottom sides, respectively. The four border sizes must all be a
|
|
// multiple of 2.
|
|
// * If |get_frame_buffer| is not null, it is invoked to allocate the memory.
|
|
// If |get_frame_buffer| is null, YuvBuffer allocates the memory directly
|
|
// and ignores the |callback_private_data| and |buffer_private_data|
|
|
// parameters, which should be null.
|
|
//
|
|
// NOTE: The strides are a multiple of 16. Since the first row in each plane
|
|
// is 16-byte aligned, subsequent rows are also 16-byte aligned.
|
|
//
|
|
// Example: bitdepth=8 width=20 height=6 left/right/top/bottom_border=2. The
|
|
// diagram below shows how Realloc() allocates the data buffer for the Y
|
|
// plane.
|
|
//
|
|
// 16-byte aligned
|
|
// |
|
|
// v
|
|
// ++++++++++++++++++++++++pppppppp
|
|
// ++++++++++++++++++++++++pppppppp
|
|
// ++01234567890123456789++pppppppp
|
|
// ++11234567890123456789++pppppppp
|
|
// ++21234567890123456789++pppppppp
|
|
// ++31234567890123456789++pppppppp
|
|
// ++41234567890123456789++pppppppp
|
|
// ++51234567890123456789++pppppppp
|
|
// ++++++++++++++++++++++++pppppppp
|
|
// ++++++++++++++++++++++++pppppppp
|
|
// | |
|
|
// |<-- stride (multiple of 16) ->|
|
|
//
|
|
// The video frame has 6 rows of 20 pixels each. Each row is shown as the
|
|
// pattern r1234567890123456789, where |r| is 0, 1, 2, 3, 4, 5.
|
|
//
|
|
// Realloc() first adds a border of 2 pixels around the video frame. The
|
|
// border pixels are shown as '+'.
|
|
//
|
|
// Each row is then padded to a multiple of the default alignment in bytes,
|
|
// which is 16. The padding bytes are shown as lowercase 'p'. (Since
|
|
// |bitdepth| is 8 in this example, each pixel is one byte.) The padded size
|
|
// in bytes is the stride. In this example, the stride is 32 bytes.
|
|
//
|
|
// Finally, Realloc() aligns the first byte of frame data, which is the '0'
|
|
// pixel/byte in the upper left corner of the frame, to the default (16-byte)
|
|
// alignment boundary.
|
|
//
|
|
// TODO(wtc): Add a check for width and height limits to defend against
|
|
// invalid bitstreams.
|
|
bool Realloc(int bitdepth, bool is_monochrome, int width, int height,
|
|
int8_t subsampling_x, int8_t subsampling_y, int left_border,
|
|
int right_border, int top_border, int bottom_border,
|
|
GetFrameBufferCallback get_frame_buffer,
|
|
void* callback_private_data, void** buffer_private_data);
|
|
|
|
int bitdepth() const { return bitdepth_; }
|
|
|
|
bool is_monochrome() const { return is_monochrome_; }
|
|
|
|
int8_t subsampling_x() const { return subsampling_x_; }
|
|
int8_t subsampling_y() const { return subsampling_y_; }
|
|
|
|
int width(int plane) const {
|
|
return (plane == kPlaneY) ? y_width_ : uv_width_;
|
|
}
|
|
int height(int plane) const {
|
|
return (plane == kPlaneY) ? y_height_ : uv_height_;
|
|
}
|
|
|
|
// Returns border sizes in pixels.
|
|
int left_border(int plane) const { return left_border_[plane]; }
|
|
int right_border(int plane) const { return right_border_[plane]; }
|
|
int top_border(int plane) const { return top_border_[plane]; }
|
|
int bottom_border(int plane) const { return bottom_border_[plane]; }
|
|
|
|
// Returns the alignment of frame buffer row in bytes.
|
|
int alignment() const { return kFrameBufferRowAlignment; }
|
|
|
|
// Backup the current set of warnings and disable -Warray-bounds for the
|
|
// following three functions as the compiler cannot, in all cases, determine
|
|
// whether |plane| is within [0, kMaxPlanes), e.g., with a variable based for
|
|
// loop.
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Warray-bounds"
|
|
#endif
|
|
// Returns the data buffer for |plane|.
|
|
uint8_t* data(int plane) {
|
|
assert(plane >= 0);
|
|
assert(static_cast<size_t>(plane) < std::extent<decltype(buffer_)>::value);
|
|
return buffer_[plane];
|
|
}
|
|
const uint8_t* data(int plane) const {
|
|
assert(plane >= 0);
|
|
assert(static_cast<size_t>(plane) < std::extent<decltype(buffer_)>::value);
|
|
return buffer_[plane];
|
|
}
|
|
|
|
// Returns the stride in bytes for |plane|.
|
|
int stride(int plane) const {
|
|
assert(plane >= 0);
|
|
assert(static_cast<size_t>(plane) < std::extent<decltype(stride_)>::value);
|
|
return stride_[plane];
|
|
}
|
|
// Restore the previous set of compiler warnings.
|
|
#ifdef __GNUC__
|
|
#pragma GCC diagnostic pop
|
|
#endif
|
|
|
|
private:
|
|
static constexpr int kFrameBufferRowAlignment = 16;
|
|
int bitdepth_ = 0;
|
|
bool is_monochrome_ = false;
|
|
|
|
// y_width_ and y_height_ are the |width| and |height| arguments passed to the
|
|
// Realloc() method.
|
|
//
|
|
// uv_width_ and uv_height_ are computed from y_width_ and y_height_ as
|
|
// follows:
|
|
// uv_width_ = (y_width_ + subsampling_x_) >> subsampling_x_
|
|
// uv_height_ = (y_height_ + subsampling_y_) >> subsampling_y_
|
|
int y_width_ = 0;
|
|
int uv_width_ = 0;
|
|
int y_height_ = 0;
|
|
int uv_height_ = 0;
|
|
|
|
int left_border_[kMaxPlanes] = {};
|
|
int right_border_[kMaxPlanes] = {};
|
|
int top_border_[kMaxPlanes] = {};
|
|
int bottom_border_[kMaxPlanes] = {};
|
|
|
|
int stride_[kMaxPlanes] = {};
|
|
uint8_t* buffer_[kMaxPlanes] = {};
|
|
|
|
// buffer_alloc_ and buffer_alloc_size_ are only used if the
|
|
// get_frame_buffer callback is null and we allocate the buffer ourselves.
|
|
std::unique_ptr<uint8_t[]> buffer_alloc_;
|
|
size_t buffer_alloc_size_ = 0;
|
|
|
|
int8_t subsampling_x_ = 0; // 0 or 1.
|
|
int8_t subsampling_y_ = 0; // 0 or 1.
|
|
};
|
|
|
|
} // namespace libgav1
|
|
|
|
#endif // LIBGAV1_SRC_YUV_BUFFER_H_
|