/*
* Copyright (C) Texas Instruments - http://www.ti.com/
*
* 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 BUFFER_SOURCE_ADAPTER_H
#define BUFFER_SOURCE_ADAPTER_H
#ifdef OMAP_ENHANCEMENT_CPCAM
#include "CameraHal.h"
#include <ui/GraphicBufferMapper.h>
#include <hal_public.h>
namespace Ti {
namespace Camera {
/**
* Handles enqueueing/dequeing buffers to tap-in/tap-out points
* TODO(XXX): this class implements DisplayAdapter for now
* but this will most likely change once tap-in/tap-out points
* are better defined
*/
class BufferSourceAdapter : public DisplayAdapter
{
// private types
private:
///Constant declarations
static const int NO_BUFFERS_IMAGE_CAPTURE_SYSTEM_HEAP;
// helper class to return frame in different thread context
class ReturnFrame : public android::Thread {
public:
ReturnFrame(BufferSourceAdapter* __this) : mBufferSourceAdapter(__this) {
android::AutoMutex lock(mReturnFrameMutex);
mDestroying = false;
mFrameCount = 0;
}
~ReturnFrame() {
android::AutoMutex lock(mReturnFrameMutex);
}
void signal() {
android::AutoMutex lock(mReturnFrameMutex);
mFrameCount++;
mReturnFrameCondition.signal();
}
virtual void requestExit() {
Thread::requestExit();
android::AutoMutex lock(mReturnFrameMutex);
mDestroying = true;
mReturnFrameCondition.signal();
}
virtual bool threadLoop() {
android::AutoMutex lock(mReturnFrameMutex);
if ( 0 >= mFrameCount ) {
mReturnFrameCondition.wait(mReturnFrameMutex);
}
if (!mDestroying) {
mBufferSourceAdapter->handleFrameReturn();
mFrameCount--;
}
return true;
}
private:
BufferSourceAdapter* mBufferSourceAdapter;
android::Condition mReturnFrameCondition;
android::Mutex mReturnFrameMutex;
int mFrameCount;
bool mDestroying;
};
// helper class to queue frame in different thread context
class QueueFrame : public android::Thread {
public:
QueueFrame(BufferSourceAdapter* __this) : mBufferSourceAdapter(__this) {
mDestroying = false;
}
~QueueFrame() {
}
void addFrame(CameraFrame *frame) {
android::AutoMutex lock(mFramesMutex);
mFrames.add(new CameraFrame(*frame));
mFramesCondition.signal();
}
virtual void requestExit() {
Thread::requestExit();
mDestroying = true;
android::AutoMutex lock(mFramesMutex);
while (!mFrames.empty()) {
CameraFrame *frame = mFrames.itemAt(0);
mFrames.removeAt(0);
frame->mMetaData.clear();
delete frame;
}
mFramesCondition.signal();
}
virtual bool threadLoop() {
CameraFrame *frame = NULL;
{
android::AutoMutex lock(mFramesMutex);
while (mFrames.empty() && !mDestroying) mFramesCondition.wait(mFramesMutex);
if (!mDestroying) {
frame = mFrames.itemAt(0);
mFrames.removeAt(0);
}
}
if (frame) {
mBufferSourceAdapter->handleFrameCallback(frame);
frame->mMetaData.clear();
// signal return frame thread that it can dequeue a buffer now
mBufferSourceAdapter->mReturnFrame->signal();
delete frame;
}
return true;
}
private:
BufferSourceAdapter* mBufferSourceAdapter;
android::Vector<CameraFrame *> mFrames;
android::Condition mFramesCondition;
android::Mutex mFramesMutex;
bool mDestroying;
};
enum {
BUFFER_SOURCE_TAP_IN,
BUFFER_SOURCE_TAP_OUT
};
// public member functions
public:
BufferSourceAdapter();
virtual ~BufferSourceAdapter();
virtual status_t initialize();
virtual int setPreviewWindow(struct preview_stream_ops *source);
virtual int setFrameProvider(FrameNotifier *frameProvider);
virtual int setErrorHandler(ErrorNotifier *errorNotifier);
virtual int enableDisplay(int width, int height, struct timeval *refTime = NULL);
virtual int disableDisplay(bool cancel_buffer = true);
virtual status_t pauseDisplay(bool pause);
#if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS
// Not implemented in this class
virtual status_t setSnapshotTimeRef(struct timeval *refTime = NULL) { return NO_ERROR; }
#endif
virtual bool supportsExternalBuffering();
virtual CameraBuffer * allocateBufferList(int width, int dummyHeight, const char* format, int &bytes, int numBufs);
virtual CameraBuffer *getBufferList(int *numBufs);
virtual uint32_t * getOffsets() ;
virtual int getFd() ;
virtual int freeBufferList(CameraBuffer * buflist);
virtual int maxQueueableBuffers(unsigned int& queueable);
virtual int minUndequeueableBuffers(int& unqueueable);
virtual bool match(const char * str);
virtual CameraBuffer * getBuffers(bool reset = false);
virtual unsigned int getSize();
virtual int getBufferCount();
static void frameCallback(CameraFrame* caFrame);
void addFrame(CameraFrame* caFrame);
void handleFrameCallback(CameraFrame* caFrame);
bool handleFrameReturn();
private:
void destroy();
status_t returnBuffersToWindow();
private:
preview_stream_ops_t* mBufferSource;
FrameProvider *mFrameProvider; // Pointer to the frame provider interface
mutable android::Mutex mLock;
int mBufferCount;
CameraBuffer *mBuffers;
android::KeyedVector<buffer_handle_t *, int> mFramesWithCameraAdapterMap;
android::sp<ErrorNotifier> mErrorNotifier;
android::sp<ReturnFrame> mReturnFrame;
android::sp<QueueFrame> mQueueFrame;
uint32_t mFrameWidth;
uint32_t mFrameHeight;
uint32_t mPreviewWidth;
uint32_t mPreviewHeight;
int mBufferSourceDirection;
const char *mPixelFormat;
};
} // namespace Camera
} // namespace Ti
#endif
#endif