// 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 #include #include #include #include #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(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(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(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 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 new_data( static_cast(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_private_data); buffer->in_use = false; } } // namespace libgav1