| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * 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. |
| */ |
| #define LOG_TAG "CachedStreamBuffer" |
| #include "cached_stream_buffer.h" |
| #include <hardware/gralloc.h> |
| #include <log/log.h> |
| #include <sync/sync.h> |
| |
| namespace android::hardware::camera::device::V3_4::implementation { |
| |
| namespace { |
| HandleImporter g_importer; |
| } |
| |
| ReleaseFence::ReleaseFence(int fence_fd) : handle_(nullptr) { |
| if (fence_fd >= 0) { |
| handle_ = native_handle_create(/*numFds*/ 1, /*numInts*/ 0); |
| handle_->data[0] = fence_fd; |
| } |
| } |
| |
| ReleaseFence::~ReleaseFence() { |
| if (handle_ != nullptr) { |
| native_handle_close(handle_); |
| native_handle_delete(handle_); |
| } |
| } |
| |
| CachedStreamBuffer::CachedStreamBuffer() |
| : buffer_(nullptr), buffer_id_(0), stream_id_(0), acquire_fence_(-1) {} |
| |
| CachedStreamBuffer::CachedStreamBuffer(const StreamBuffer& buffer) |
| : buffer_(buffer.buffer.getNativeHandle()), |
| buffer_id_(buffer.bufferId), |
| stream_id_(buffer.streamId), |
| acquire_fence_(-1) { |
| g_importer.importBuffer(buffer_); |
| g_importer.importFence(buffer.acquireFence, acquire_fence_); |
| } |
| |
| CachedStreamBuffer::CachedStreamBuffer(CachedStreamBuffer&& from) noexcept { |
| buffer_ = from.buffer_; |
| buffer_id_ = from.buffer_id_; |
| stream_id_ = from.stream_id_; |
| acquire_fence_ = from.acquire_fence_; |
| from.acquire_fence_ = -1; |
| from.buffer_ = nullptr; |
| } |
| |
| CachedStreamBuffer& CachedStreamBuffer::operator=( |
| CachedStreamBuffer&& from) noexcept { |
| if (this != &from) { |
| buffer_ = from.buffer_; |
| buffer_id_ = from.buffer_id_; |
| stream_id_ = from.stream_id_; |
| acquire_fence_ = from.acquire_fence_; |
| from.acquire_fence_ = -1; |
| from.buffer_ = nullptr; |
| } |
| return *this; |
| } |
| |
| CachedStreamBuffer::~CachedStreamBuffer() { |
| if (buffer_ != nullptr) { |
| g_importer.freeBuffer(buffer_); |
| } |
| g_importer.closeFence(acquire_fence_); |
| } |
| |
| void CachedStreamBuffer::importFence(const native_handle_t* fence_handle) { |
| g_importer.closeFence(acquire_fence_); |
| g_importer.importFence(fence_handle, acquire_fence_); |
| } |
| |
| YCbCrLayout CachedStreamBuffer::acquireAsYUV(int32_t width, int32_t height, |
| int timeout_ms) { |
| if (acquire_fence_ >= 0) { |
| if (sync_wait(acquire_fence_, timeout_ms)) { |
| ALOGW("%s: timeout while waiting acquire fence", __FUNCTION__); |
| return {}; |
| } else { |
| ::close(acquire_fence_); |
| acquire_fence_ = -1; |
| } |
| } |
| IMapper::Rect region{0, 0, width, height}; |
| return g_importer.lockYCbCr(buffer_, GRALLOC_USAGE_SW_WRITE_OFTEN, region); |
| } |
| |
| void* CachedStreamBuffer::acquireAsBlob(int32_t size, int timeout_ms) { |
| if (acquire_fence_ >= 0) { |
| if (sync_wait(acquire_fence_, timeout_ms)) { |
| return nullptr; |
| } else { |
| ::close(acquire_fence_); |
| acquire_fence_ = -1; |
| } |
| } |
| return g_importer.lock(buffer_, GRALLOC_USAGE_SW_WRITE_OFTEN, size); |
| } |
| |
| int CachedStreamBuffer::release() { return g_importer.unlock(buffer_); } |
| |
| } // namespace android::hardware::camera::device::V3_4::implementation |