diff options
Diffstat (limited to 'src/internal_frame_buffer_list.cc')
-rw-r--r-- | src/internal_frame_buffer_list.cc | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/internal_frame_buffer_list.cc b/src/internal_frame_buffer_list.cc new file mode 100644 index 0000000..e2d2273 --- /dev/null +++ b/src/internal_frame_buffer_list.cc @@ -0,0 +1,122 @@ +// 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. + +#include "src/internal_frame_buffer_list.h" + +#include <cassert> +#include <cstdint> +#include <memory> +#include <new> +#include <utility> + +#include "src/utils/common.h" + +namespace libgav1 { +extern "C" { + +Libgav1StatusCode OnInternalFrameBufferSizeChanged( + void* callback_private_data, int bitdepth, Libgav1ImageFormat image_format, + int width, int height, int left_border, int right_border, int top_border, + int bottom_border, int stride_alignment) { + auto* buffer_list = + static_cast<InternalFrameBufferList*>(callback_private_data); + return buffer_list->OnFrameBufferSizeChanged( + bitdepth, image_format, width, height, left_border, right_border, + top_border, bottom_border, stride_alignment); +} + +Libgav1StatusCode GetInternalFrameBuffer( + void* callback_private_data, int bitdepth, Libgav1ImageFormat image_format, + int width, int height, int left_border, int right_border, int top_border, + int bottom_border, int stride_alignment, Libgav1FrameBuffer* frame_buffer) { + auto* buffer_list = + static_cast<InternalFrameBufferList*>(callback_private_data); + return buffer_list->GetFrameBuffer( + bitdepth, image_format, width, height, left_border, right_border, + top_border, bottom_border, stride_alignment, frame_buffer); +} + +void ReleaseInternalFrameBuffer(void* callback_private_data, + void* buffer_private_data) { + auto* buffer_list = + static_cast<InternalFrameBufferList*>(callback_private_data); + buffer_list->ReleaseFrameBuffer(buffer_private_data); +} + +} // extern "C" + +StatusCode InternalFrameBufferList::OnFrameBufferSizeChanged( + int /*bitdepth*/, Libgav1ImageFormat /*image_format*/, int /*width*/, + int /*height*/, int /*left_border*/, int /*right_border*/, + int /*top_border*/, int /*bottom_border*/, int /*stride_alignment*/) { + return kStatusOk; +} + +StatusCode InternalFrameBufferList::GetFrameBuffer( + int bitdepth, Libgav1ImageFormat image_format, int width, int height, + int left_border, int right_border, int top_border, int bottom_border, + int stride_alignment, Libgav1FrameBuffer* frame_buffer) { + FrameBufferInfo info; + StatusCode status = ComputeFrameBufferInfo( + bitdepth, image_format, width, height, left_border, right_border, + top_border, bottom_border, stride_alignment, &info); + if (status != kStatusOk) return status; + + if (info.uv_buffer_size > SIZE_MAX / 2 || + info.y_buffer_size > SIZE_MAX - 2 * info.uv_buffer_size) { + return kStatusInvalidArgument; + } + const size_t min_size = info.y_buffer_size + 2 * info.uv_buffer_size; + + Buffer* buffer = nullptr; + for (auto& buffer_ptr : buffers_) { + if (!buffer_ptr->in_use) { + buffer = buffer_ptr.get(); + break; + } + } + if (buffer == nullptr) { + std::unique_ptr<Buffer> new_buffer(new (std::nothrow) Buffer); + if (new_buffer == nullptr || !buffers_.push_back(std::move(new_buffer))) { + return kStatusOutOfMemory; + } + buffer = buffers_.back().get(); + } + + if (buffer->size < min_size) { + std::unique_ptr<uint8_t[], MallocDeleter> new_data( + static_cast<uint8_t*>(malloc(min_size))); + if (new_data == nullptr) return kStatusOutOfMemory; + buffer->data = std::move(new_data); + buffer->size = min_size; + } + + uint8_t* const y_buffer = buffer->data.get(); + uint8_t* const u_buffer = + (info.uv_buffer_size == 0) ? nullptr : y_buffer + info.y_buffer_size; + uint8_t* const v_buffer = + (info.uv_buffer_size == 0) ? nullptr : u_buffer + info.uv_buffer_size; + status = Libgav1SetFrameBuffer(&info, y_buffer, u_buffer, v_buffer, buffer, + frame_buffer); + if (status != kStatusOk) return status; + buffer->in_use = true; + return kStatusOk; +} + +void InternalFrameBufferList::ReleaseFrameBuffer(void* buffer_private_data) { + auto* const buffer = static_cast<Buffer*>(buffer_private_data); + buffer->in_use = false; +} + +} // namespace libgav1 |