blob: 452a9080c7af68a7d580db7cab6b1ab20681e455 [file] [log] [blame]
/*
* 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 ANDROID_SERVERS_CAMERA3_BUFFER_UTILS_H
#define ANDROID_SERVERS_CAMERA3_BUFFER_UTILS_H
#include <unordered_map>
#include <mutex>
#include <set>
#include <cutils/native_handle.h>
#include <android/hardware/camera/device/3.2/ICameraDevice.h>
// TODO: remove legacy camera3.h references
#include "hardware/camera3.h"
#include <device3/Camera3OutputInterface.h>
namespace android {
namespace camera3 {
struct BufferHasher {
size_t operator()(const buffer_handle_t& buf) const {
if (buf == nullptr)
return 0;
size_t result = 1;
result = 31 * result + buf->numFds;
for (int i = 0; i < buf->numFds; i++) {
result = 31 * result + buf->data[i];
}
return result;
}
};
struct BufferComparator {
bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
if (buf1->numFds == buf2->numFds) {
for (int i = 0; i < buf1->numFds; i++) {
if (buf1->data[i] != buf2->data[i]) {
return false;
}
}
return true;
}
return false;
}
};
// Per stream buffer native handle -> bufId map
typedef std::unordered_map<const buffer_handle_t, uint64_t,
BufferHasher, BufferComparator> BufferIdMap;
// streamId -> BufferIdMap
typedef std::unordered_map<int, BufferIdMap> BufferIdMaps;
// Map of inflight buffers sent along in capture requests.
// Key is composed by (frameNumber << 32 | streamId)
typedef std::unordered_map<uint64_t, buffer_handle_t*> InflightBufferMap;
// Map of inflight buffers dealt by requestStreamBuffers API
typedef std::unordered_map<uint64_t, std::pair<int32_t, buffer_handle_t*>> RequestedBufferMap;
// A struct containing all buffer tracking information like inflight buffers
// and buffer ID caches
class BufferRecords : public BufferRecordsInterface {
public:
BufferRecords() {}
BufferRecords(BufferRecords&& other) :
mBufferIdMaps(other.mBufferIdMaps),
mNextBufferId(other.mNextBufferId),
mInflightBufferMap(other.mInflightBufferMap),
mRequestedBufferMap(other.mRequestedBufferMap) {}
virtual ~BufferRecords() {}
// Helper methods to help moving buffer records
void takeInflightBufferMap(BufferRecords& other);
void takeRequestedBufferMap(BufferRecords& other);
void takeBufferCaches(BufferRecords& other, const std::vector<int32_t>& streams);
// method to extract buffer's unique ID
// return pair of (newlySeenBuffer?, bufferId)
virtual std::pair<bool, uint64_t> getBufferId(
const buffer_handle_t& buf, int streamId) override;
void tryCreateBufferCache(int streamId);
void removeInactiveBufferCaches(const std::set<int32_t>& activeStreams);
// Return the removed buffer ID if input cache is found.
// Otherwise return BUFFER_ID_NO_BUFFER
uint64_t removeOneBufferCache(int streamId, const native_handle_t* handle);
// Clear all caches for input stream, but do not remove the stream
// Removed buffers' ID are returned
std::vector<uint64_t> clearBufferCaches(int streamId);
bool isStreamCached(int streamId);
// Return true if the input caches match what we have; otherwise false
bool verifyBufferIds(int32_t streamId, std::vector<uint64_t>& inBufIds);
// Get a vector of (frameNumber, streamId) pair of currently inflight
// buffers
void getInflightBufferKeys(std::vector<std::pair<int32_t, int32_t>>* out);
status_t pushInflightBuffer(int32_t frameNumber, int32_t streamId,
buffer_handle_t *buffer);
// Find a buffer_handle_t based on frame number and stream ID
virtual status_t popInflightBuffer(int32_t frameNumber, int32_t streamId,
/*out*/ buffer_handle_t **buffer) override;
// Pop inflight buffers based on pairs of (frameNumber,streamId)
void popInflightBuffers(const std::vector<std::pair<int32_t, int32_t>>& buffers);
// Get a vector of bufferId of currently inflight buffers
void getInflightRequestBufferKeys(std::vector<uint64_t>* out);
// Register a bufId (streamId, buffer_handle_t) to inflight request buffer
virtual status_t pushInflightRequestBuffer(
uint64_t bufferId, buffer_handle_t* buf, int32_t streamId) override;
// Find a buffer_handle_t based on bufferId
virtual status_t popInflightRequestBuffer(uint64_t bufferId,
/*out*/ buffer_handle_t** buffer,
/*optional out*/ int32_t* streamId = nullptr) override;
private:
std::mutex mBufferIdMapLock;
BufferIdMaps mBufferIdMaps;
uint64_t mNextBufferId = 1; // 0 means no buffer
std::mutex mInflightLock;
InflightBufferMap mInflightBufferMap;
std::mutex mRequestedBuffersLock;
RequestedBufferMap mRequestedBufferMap;
}; // class BufferRecords
static const uint64_t BUFFER_ID_NO_BUFFER = 0;
camera3_buffer_status_t mapHidlBufferStatus(
hardware::camera::device::V3_2::BufferStatus status);
} // namespace camera3
} // namespace android
#endif