/* * Copyright (C) 2019 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. */ #ifndef HARDWARE_GOOGLE_CAMERA_HAL_UTILS_ZSL_BUFFER_MANAGER_H #define HARDWARE_GOOGLE_CAMERA_HAL_UTILS_ZSL_BUFFER_MANAGER_H #include #include #include #include #include #include #include #include #include "gralloc_buffer_allocator.h" #include "hal_buffer_allocator.h" #include "hal_types.h" namespace android { namespace google_camera_hal { // ZslBufferManager creates and manages ZSL buffers. class ZslBufferManager { public: // allocator will be used to allocate buffers. If allocator is nullptr, // GrallocBufferAllocator will be used to allocate buffers. ZslBufferManager(IHalBufferAllocator* allocator = nullptr, int partial_result_count = 1); virtual ~ZslBufferManager(); // Defines a ZSL buffer. struct ZslBuffer { // Original frame number of this ZSL buffer captured by HAL. uint32_t frame_number = 0; // Buffer StreamBuffer buffer; // Original result metadata of this ZSL buffer captured by HAL. std::unique_ptr metadata; // Last partial result received int partial_result = 0; }; // Allocate buffers. This can only be called once. // The second call will return ALREADY_EXISTS. status_t AllocateBuffers(const HalBufferDescriptor& buffer_descriptor); // Get an empty buffer for capture. The caller can modify the buffer data // but the buffer is owned by ZslBufferManager and // must not be freed by the caller. buffer_handle_t GetEmptyBuffer(); // Return an empty buffer that was previously obtained by GetEmptyBuffer(). status_t ReturnEmptyBuffer(buffer_handle_t buffer); // Return the buffer part of a filled buffer // that was previously obtained by GetEmptyBuffer(). status_t ReturnFilledBuffer(uint32_t frame_number, const StreamBuffer& buffer); // Return the metadata part of a filled buffer // that was previously obtained by GetEmptyBuffer(). // ZSL buffer manager will make a copy of metadata. // The caller still owns metadata. status_t ReturnMetadata(uint32_t frame_number, const HalCameraMetadata* metadata, int partial_result); // Get a number of the most recent ZSL buffers. // If numBuffers is larger than available ZSL buffers, // zslBuffers will contain all available ZSL buffers, // i.e. zslBuffers.size() may be smaller than numBuffers. // The buffer and metadata are owned by ZslBufferManager and // must not be freed by the caller. // minBuffers is the minimum number of buffers the // zsl buffer manager should return. If this can not be satisfied // (i.e. not enough ZSL buffers exist), // this GetMostRecentZslBuffers returns an empty vector. void GetMostRecentZslBuffers(std::vector* zsl_buffers, uint32_t num_buffers, uint32_t min_buffers); // Return a ZSL buffer that was previously obtained by // GetMostRecentZslBuffers(). void ReturnZslBuffer(ZslBuffer zsl_buffer); // Return a vector of ZSL buffers that were previously obtained by // GetMostRecentZslBuffers(). void ReturnZslBuffers(std::vector zsl_buffers); // Check ZslBuffers are allocated or not. bool IsBufferAllocated() { return allocated_; }; // Check pending_zsl_buffers_ is empty or not. bool IsPendingBufferEmpty(); // Add buffer map to pending_zsl_buffers_ void AddPendingBuffers(const std::vector& buffers); // Clean buffer map from pending_zsl_buffers_ status_t CleanPendingBuffers(std::vector* buffers); private: static const uint32_t kMaxPartialZslBuffers = 100; // Max timestamp difference of the ZSL buffer and current time. Used // to discard old ZSL buffers. static const int64_t kMaxBufferTimestampDiff = 1000000000; // 1 second // Maximum number of unused buffers. When the number of unused buffers > // kMaxUnusedBuffers, it will try to free excessive buffers. static const uint32_t kMaxUnusedBuffers = 2; // Maximum number of frames with enough unused buffers. When the number of // counter > kMaxIdelBufferFrameCounter, it will try to free excessive // buffers. static const uint32_t kMaxIdelBufferFrameCounter = 300; const bool kMemoryProfilingEnabled; // Remove the oldest metadata. status_t RemoveOldestMetadataLocked(); // Get current BOOT_TIME timestamp in nanoseconds status_t GetCurrentTimestampNs(int64_t* current_timestamp); // Allocate a number of buffers. Must be protected by zsl_buffers_lock_. status_t AllocateBuffersLocked(uint32_t buffer_number); // Get an empty buffer. Must be protected by zsl_buffers_lock_. buffer_handle_t GetEmptyBufferLocked(); // Try to free unused buffers. Must be protected by zsl_buffers_lock_. void FreeUnusedBuffersLocked(); bool allocated_ = false; std::mutex zsl_buffers_lock_; // Buffer manager for allocating the buffers. Protected by mZslBuffersLock. std::unique_ptr internal_buffer_allocator_; // external buffer allocator IHalBufferAllocator* buffer_allocator_ = nullptr; // Empty ZSL buffer queue. Protected by mZslBuffersLock. std::deque empty_zsl_buffers_; // Filled ZSL buffers. Map from frameNumber to ZslBuffer. // Ordered from the oldest to the newest buffers. // Protected by mZslBuffersLock. std::map filled_zsl_buffers_; // Partially filled ZSL buffers. Either the metadata or // the buffer is returned. Once the metadata and the buffer are both ready, // the ZslBuffer will be moved to the filled_zsl_buffers_. // Map from frameNumber to ZslBuffer. Ordered from the oldest to the newest // buffers. filled_zsl_buffers_ protected by zsl_buffers_lock_. std::map partially_filled_zsl_buffers_; // Store all allocated buffers return from GrallocBufferAllocator std::vector buffers_; std::mutex pending_zsl_buffers_mutex; // Map from buffer handle to ZSL buffer. Protected by pending_zsl_buffers_mutex. std::unordered_map pending_zsl_buffers_; // Store the buffer descriptor when call AllocateBuffers() // Use it for AllocateExtraBuffers() HalBufferDescriptor buffer_descriptor_; // Count the number when there are enough unused buffers. uint32_t idle_buffer_frame_counter_ = 0; // Partial result count reported by camera HAL int partial_result_count_ = 1; }; } // namespace google_camera_hal } // namespace android #endif // HARDWARE_GOOGLE_CAMERA_HAL_UTILS_ZSL_BUFFER_MANAGER_H