blob: a3d016f02220c01de9b8e2f2585dbede74225164 [file] [log] [blame]
/*
* Copyright 2013, Samsung Electronics Co. LTD
*
* 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 toggle 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.
*/
/*!
* \file ExynosCameraBufferManager.h
* \brief header file for ExynosCameraBufferManager
* \author Sunmi Lee(carrotsm.lee@samsung.com)
* \date 2013/07/17
*
*/
#ifndef EXYNOS_CAMERA_BUFFER_MANAGER_H__
#define EXYNOS_CAMERA_BUFFER_MANAGER_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <utils/List.h>
#include <utils/threads.h>
#include <cutils/properties.h>
#include <binder/MemoryHeapBase.h>
#include <ui/Fence.h>
#include <videodev2.h>
#include <videodev2_exynos_camera.h>
#include <ion/ion.h>
#include "gralloc1_priv.h"
#include "ExynosCameraConfig.h"
#include "fimc-is-metadata.h"
#include "ExynosCameraList.h"
#include "ExynosCameraAutoTimer.h"
#include "ExynosCameraBuffer.h"
#include "ExynosCameraMemory.h"
#include "ExynosCameraThread.h"
namespace android {
/* #define DUMP_2_FILE */
/* #define EXYNOS_CAMERA_BUFFER_TRACE */
#ifdef EXYNOS_CAMERA_BUFFER_TRACE
#define EXYNOS_CAMERA_BUFFER_IN() CLOGD("IN..")
#define EXYNOS_CAMERA_BUFFER_OUT() CLOGD("OUT..")
#else
#define EXYNOS_CAMERA_BUFFER_IN() ((void *)0)
#define EXYNOS_CAMERA_BUFFER_OUT() ((void *)0)
#endif
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
#define BUFFER_COLLECT_MARGIN (1)
#define BUFFER_COLLECTOR_WAITING_TIME (10000) /* 10 msec */
#endif
// Hack: Close Fence FD if the fd is larger than specified number
// Currently, Joon's fence FD is not closed properly
#define FORCE_CLOSE_ACQUIRE_FD
#define FORCE_CLOSE_ACQUIRE_FD_THRESHOLD 700
typedef enum buffer_manager_type {
BUFFER_MANAGER_ION_TYPE = 0,
BUFFER_MANAGER_HEAP_BASE_TYPE = 1,
BUFFER_MANAGER_GRALLOC_TYPE = 2,
BUFFER_MANAGER_SERVICE_GRALLOC_TYPE = 3,
BUFFER_MANAGER_INVALID_TYPE,
} buffer_manager_type_t;
typedef enum buffer_manager_allocation_mode {
BUFFER_MANAGER_ALLOCATION_ATONCE = 0, /* alloc() : allocation all buffers */
BUFFER_MANAGER_ALLOCATION_ONDEMAND = 1, /* alloc() : allocation the number of reqCount buffers, getBuffer() : increase buffers within limits */
BUFFER_MANAGER_ALLOCATION_SILENT = 2, /* alloc() : same as ONDEMAND, increase buffers in background */
BUFFER_MANAGER_ALLOCATION_INVALID_MODE,
} buffer_manager_allocation_mode_t;
typedef ExynosCameraList<int32_t> reuseBufList_t;
class ExynosCameraBufferManager {
protected:
ExynosCameraBufferManager();
public:
static ExynosCameraBufferManager *createBufferManager(buffer_manager_type_t type);
virtual ~ExynosCameraBufferManager();
status_t create(const char *name, void *defaultAllocator);
status_t create(const char *name, int cameraId, void *defaultAllocator);
void init(void);
virtual void deinit(void);
virtual status_t resetBuffers(void);
status_t setAllocator(void *allocator);
status_t alloc(void);
void setContigBufCount(int reservedMemoryCount);
int getContigBufCount(void);
status_t setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int reqBufCount,
bool createMetaPlane,
bool needMmap = false);
status_t setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int reqBufCount,
int allowedMaxBufCount,
exynos_camera_buffer_type_t type,
bool createMetaPlane,
bool needMmap = false);
status_t setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
bool createMetaPlane,
bool needMmap = false);
status_t setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
int allowedMaxBufCount,
exynos_camera_buffer_type_t type,
buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
bool needMmap = false);
status_t setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
int allowedMaxBufCount,
int batchSize,
exynos_camera_buffer_type_t type,
buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
bool needMmap = false);
status_t setInfo(
int planeCount,
unsigned int size[],
unsigned int bytePerLine[],
int startBufIndex,
int reqBufCount,
int allowedMaxBufCount,
exynos_camera_buffer_type_t type,
buffer_manager_allocation_mode_t allocMode,
bool createMetaPlane,
int width,
int height,
int stride,
int pixelFormat,
bool needMmap = false);
status_t putBuffer(
int bufIndex,
enum EXYNOS_CAMERA_BUFFER_POSITION position);
status_t getBuffer(
int *reqBufIndex,
enum EXYNOS_CAMERA_BUFFER_POSITION position,
struct ExynosCameraBuffer *buffer);
status_t updateStatus(
int bufIndex,
int driverValue,
enum EXYNOS_CAMERA_BUFFER_POSITION position,
enum EXYNOS_CAMERA_BUFFER_PERMISSION permission);
status_t getStatus(
int bufIndex,
struct ExynosCameraBufferStatus *bufStatus);
virtual status_t getIndexByHandle(buffer_handle_t *handle, int *index);
virtual status_t getHandleByIndex(buffer_handle_t **handle, int index);
virtual sp<GraphicBuffer> getGraphicBuffer(int index);
virtual status_t getIndexByFd(int fd, int *index);
virtual status_t registerBuffer(
int frameCount,
buffer_handle_t *handle,
int acquireFence,
int releaseFence,
enum EXYNOS_CAMERA_BUFFER_POSITION position);
bool isAllocated(void);
bool isAvaliable(int bufIndex);
void dump(void);
void dumpBufferInfo(void);
int getAllocatedBufferCount(void);
int getAvailableIncreaseBufferCount(void);
int getNumOfAvailableBuffer(void);
int getNumOfAvailableAndNoneBuffer(void);
int getNumOfAllowedMaxBuffer(void);
void printBufferInfo(
const char *funcName,
const int lineNum,
int bufIndex,
int planeIndex);
void printBufferQState(void);
virtual void printBufferState(void);
virtual void printBufferState(int bufIndex, int planeIndex);
virtual status_t increase(int increaseCount);
#ifdef USE_GRALLOC_REUSE_SUPPORT
virtual status_t cancelBuffer(int bufIndex, bool isReuse = false);
#else
virtual status_t cancelBuffer(int bufIndex);
#endif
virtual status_t setBufferCount(int bufferCount);
virtual int getBufferCount(void);
virtual int getBufStride(void);
protected:
status_t m_free(void);
status_t m_setDefaultAllocator(void *allocator);
status_t m_defaultAlloc(int bIndex, int eIndex, bool isMetaPlane);
status_t m_defaultFree(int bIndex, int eIndex, bool isMetaPlane);
bool m_checkInfoForAlloc(void);
status_t m_createDefaultAllocator(bool isCached = false);
int m_getTotalPlaneCount(int planeCount, int batchSize, bool hasMetaPlane);
virtual void m_resetSequenceQ(void);
virtual status_t m_setAllocator(void *allocator) = 0;
virtual status_t m_alloc(int bIndex, int eIndex) = 0;
virtual status_t m_free(int bIndex, int eIndex) = 0;
virtual status_t m_increase(int increaseCount) = 0;
virtual status_t m_decrease(void) = 0;
virtual status_t m_putBuffer(int bufIndex) = 0;
virtual status_t m_getBuffer(int *bufIndex, int *acquireFence, int *releaseFence) = 0;
virtual status_t m_constructBatchBuffer(int bufIndex);
virtual status_t m_destructBatchBuffer(int bufIndex);
virtual bool m_isValidBatchBuffer(int bufIndex);
protected:
bool m_flagAllocated;
int m_reservedMemoryCount;
int m_reqBufCount;
int m_allocatedBufCount;
int m_allowedMaxBufCount;
bool m_flagSkipAllocation;
bool m_isDestructor;
mutable Mutex m_lock;
bool m_flagNeedMmap;
bool m_hasMetaPlane;
/* using internal allocator (ION) for MetaData plane */
ExynosCameraIonAllocator *m_defaultAllocator;
bool m_isCreateDefaultAllocator;
struct ExynosCameraBuffer m_buffer[VIDEO_MAX_FRAME];
char m_name[EXYNOS_CAMERA_NAME_STR_SIZE];
int m_cameraId;
List<int> m_availableBufferIndexQ;
mutable Mutex m_availableBufferIndexQLock;
buffer_manager_allocation_mode_t m_allocMode;
int m_indexOffset;
ExynosCameraGraphicBufferAllocator m_graphicBufferAllocator;
private:
typedef ExynosCameraThread<ExynosCameraBufferManager> allocThread;
sp<allocThread> m_allocationThread;
bool m_allocationThreadFunc(void);
};
class InternalExynosCameraBufferManager : public ExynosCameraBufferManager {
public:
InternalExynosCameraBufferManager();
virtual ~InternalExynosCameraBufferManager();
status_t increase(int increaseCount);
protected:
status_t m_setAllocator(void *allocator);
status_t m_alloc(int bIndex, int eIndex);
status_t m_free(int bIndex, int eIndex);
status_t m_increase(int increaseCount);
status_t m_decrease(void);
status_t m_putBuffer(int bufIndex);
status_t m_getBuffer(int *bufIndex, int *acquireFence, int *releaseFence);
};
class MHBExynosCameraBufferManager : public ExynosCameraBufferManager {
/* do not use! deprecated class */
public:
MHBExynosCameraBufferManager();
virtual ~MHBExynosCameraBufferManager();
status_t allocMulti();
status_t getHeapMemory(
int bufIndex,
int planeIndex,
camera_memory_t **heap);
protected:
status_t m_setAllocator(void *allocator);
status_t m_alloc(int bIndex, int eIndex);
status_t m_free(int bIndex, int eIndex);
status_t m_increase(int increaseCount);
status_t m_decrease(void);
status_t m_putBuffer(int bufIndex);
status_t m_getBuffer(int *bufIndex, int *acquireFence, int *releaseFence);
private:
ExynosCameraMHBAllocator *m_allocator;
camera_memory_t *m_heap[VIDEO_MAX_FRAME][EXYNOS_CAMERA_BUFFER_MAX_PLANES];
int m_numBufsHeap;
};
class GrallocExynosCameraBufferManager : public ExynosCameraBufferManager {
public:
GrallocExynosCameraBufferManager();
virtual ~GrallocExynosCameraBufferManager();
void deinit(void);
status_t resetBuffers(void);
#ifdef USE_GRALLOC_REUSE_SUPPORT
status_t cancelBuffer(int bufIndex, bool isReuse = false);
#else
status_t cancelBuffer(int bufIndex);
#endif
status_t setBufferCount(int bufferCount);
int getBufferCount(void);
int getBufStride(void);
void printBufferState(void);
void printBufferState(int bufIndex, int planeIndex);
sp<GraphicBuffer> getGraphicBuffer(int index);
protected:
status_t m_setAllocator(void *allocator);
status_t m_alloc(int bIndex, int eIndex);
status_t m_free(int bIndex, int eIndex);
status_t m_increase(int increaseCount);
status_t m_decrease(void);
status_t m_putBuffer(int bufIndex);
status_t m_getBuffer(int *bufIndex, int *acquireFence, int *releaseFence);
#ifdef USE_GRALLOC_REUSE_SUPPORT
bool m_cancelReuseBuffer(int bufIndex, bool isReuse);
#endif
status_t m_constructBatchBuffer(int bufIndex);
status_t m_destructBatchBuffer(int bufIndex);
private:
ExynosCameraGrallocAllocator *m_allocator;
buffer_handle_t *m_handle[VIDEO_MAX_FRAME];
bool m_handleIsLocked[VIDEO_MAX_FRAME];
int m_dequeuedBufCount;
int m_minUndequeuedBufCount;
int m_bufferCount;
int m_bufStride;
#ifdef USE_GRALLOC_BUFFER_COLLECTOR
typedef ExynosCameraThread<GrallocExynosCameraBufferManager> grallocBufferThread;
int m_collectedBufferCount;
bool m_stopBufferCollector;
sp<grallocBufferThread> m_bufferCollector;
bool m_bufferCollectorThreadFunc(void);
status_t m_getCollectedBuffer(int *bufIndex);
bool m_isCollectedBuffer(int bufferIndex);
#endif
#ifdef USE_GRALLOC_REUSE_SUPPORT
status_t m_cancelBuffer(int bufIndex, bool isReuse = false);
#else
status_t m_cancelBuffer(int bufIndex);
#endif
};
class ExynosCameraFence {
public:
enum EXYNOS_CAMERA_FENCE_TYPE {
EXYNOS_CAMERA_FENCE_TYPE_BASE = 0,
EXYNOS_CAMERA_FENCE_TYPE_ACQUIRE,
EXYNOS_CAMERA_FENCE_TYPE_RELEASE,
EXYNOS_CAMERA_FENCE_TYPE_MAX,
};
private:
ExynosCameraFence();
public:
ExynosCameraFence(
enum EXYNOS_CAMERA_FENCE_TYPE fenceType,
int frameCount,
int index,
int acquireFence,
int releaseFence);
virtual ~ExynosCameraFence();
int getFenceType(void);
int getFrameCount(void);
int getIndex(void);
int getAcquireFence(void);
int getReleaseFence(void);
bool isValid(void);
status_t wait(int time = -1);
private:
enum EXYNOS_CAMERA_FENCE_TYPE m_fenceType;
int m_frameCount;
int m_index;
int m_acquireFence;
int m_releaseFence;
sp<Fence> m_fence;
bool m_flagSwfence;
};
class ServiceExynosCameraBufferManager : public ExynosCameraBufferManager {
public:
ServiceExynosCameraBufferManager();
virtual ~ServiceExynosCameraBufferManager();
status_t getIndexByHandle(buffer_handle_t *handle, int *index);
status_t getHandleByIndex(buffer_handle_t **handle, int index);
/*
* The H/W fence sequence is
* 1. On putBuffer (call by processCaptureRequest()),
* And, save acquire_fence, release_fence value.
* S/W fence : Make Fence class with acquire_fence on output_buffer.
*
* 2. when getBuffer,
* H/W fence : save acquire_fence, release_fence to ExynosCameraBuffer.
* S/W fence : wait Fence class that allocated at step 1.
*
* (step 3 ~ step 4 is on ExynosCameraNode::m_qBuf())
* 3. During H/W qBuf,
* give ExynosCameraBuffer.acquireFence (gotten step2) to v4l2
* v4l2_buffer.flags = V4L2_BUF_FLAG_USE_SYNC;
* v4l2_buffer.reserved = ExynosCameraBuffer.acquireFence;
* 4. after H/W qBuf
* v4l2_buffer.reserved is changed to release_fence value.
* So,
* ExynosCameraBuffer.releaseFence = static_cast<int>(v4l2_buffer.reserved)
*
* 5. (step5 is on ExynosCamera3::m_setResultBufferInfo())
* after H/W dqBuf, we meet handlePreview().
* we can set final value.
* result_buffer_info_t.acquire_fence = -1. (NOT original ExynosCameraBuffer.acquireFence)
* result_buffer_info_t.release_fence = ExynosCameraBuffer.releaseFence. (gotten by driver at step3)
* (service will look this release_fence.)
*
* 6 skip bufferManger::putBuffer().
* (we don't need to call putBuffer. because, buffer came from service.)
*
* 7. repeat from 1.
*/
status_t registerBuffer(
int frameCount,
buffer_handle_t *handle,
int acquireFence,
int releaseFence,
enum EXYNOS_CAMERA_BUFFER_POSITION position);
protected:
virtual void m_resetSequenceQ(void);
status_t m_setAllocator(void *allocator);
status_t m_alloc(int bIndex, int eIndex);
status_t m_free(int bIndex, int eIndex);
status_t m_increase(int increaseCount);
status_t m_decrease(void);
status_t m_registerBuffer(buffer_handle_t **handle, int index);
status_t m_putBuffer(int bufIndex);
status_t m_getBuffer(int *bufIndex, int *acquireFence, int *releaseFence);
virtual status_t m_waitFence(ExynosCameraFence *fence);
virtual void m_pushFence(List<ExynosCameraFence *> *list, ExynosCameraFence *fence);
virtual ExynosCameraFence *m_popFence(List<ExynosCameraFence *> *list);
virtual status_t m_removeFence(List<ExynosCameraFence *> *list, int index);
virtual status_t m_compareFdOfBufferHandle(const buffer_handle_t* handle, const ExynosCameraBuffer* exynosBuf);
private:
ExynosCameraStreamAllocator *m_allocator;
buffer_handle_t *m_handle[VIDEO_MAX_FRAME];
bool m_handleIsLocked[VIDEO_MAX_FRAME];
List<ExynosCameraFence *> m_fenceList;
mutable Mutex m_fenceListLock;
};
}
#endif