blob: a8ab5d33768899f36a7fa349dfb70c3d04ed98ab [file] [log] [blame]
/*
* Copyright (C) 2015-2020 Intel Corporation.
*
* 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.
*/
#pragma once
#include <map>
#include <vector>
#include "iutils/Thread.h"
#include "iutils/Errors.h"
#include "CameraEvent.h"
#include "CameraBuffer.h"
/**
* These are the abstract Classes for buffer communication between different class of HAL
*/
namespace icamera {
class BufferProducer;
/**
* BufferConsumer listens on the onFrameAvailable event from the producer by
* calling setBufferProducer
*/
class BufferConsumer {
public:
virtual ~BufferConsumer() {};
virtual int onFrameAvailable(Port port, const std::shared_ptr<CameraBuffer> &camBuffer) = 0;
virtual void setBufferProducer(BufferProducer *producer) = 0;
};
/**
* BufferProcuder get the buffers from consumer by "qbuf".
* Notfiy the consumer by calling the onFramAvaible interface of consumer.
* The consumer must be registered by "addFrameAvailableListener" before getting
* any buffer done notification.
*/
class BufferProducer : public EventSource {
public:
BufferProducer(int memType = V4L2_MEMORY_USERPTR);
virtual ~BufferProducer() {};
virtual int qbuf(Port port, const std::shared_ptr<CameraBuffer> &camBuffer) = 0;
virtual int allocateMemory(Port port, const std::shared_ptr<CameraBuffer> &camBuffer) = 0;
virtual void addFrameAvailableListener(BufferConsumer *listener) = 0;
virtual void removeFrameAvailableListener(BufferConsumer *listener) = 0;
int getMemoryType(void) const {return mMemType;}
private:
int mMemType;
};
class BufferQueue: public BufferConsumer, public BufferProducer, public EventListener {
public:
BufferQueue();
virtual ~BufferQueue();
/**
* \brief the notify when poll one frame buffer
*
* Push the CameraBuffer to InputQueue and send a signal if needed
*/
virtual int onFrameAvailable(Port port, const std::shared_ptr<CameraBuffer> &camBuffer);
/**
* \brief Register the BufferProducer
*
* Register the BufferProducer: Psys, software, or captureUnit
*/
virtual void setBufferProducer(BufferProducer *producer);
/**
* \brief Queue one buffer to producer
*
* Push this buffer to output queue
*/
virtual int qbuf(Port port, const std::shared_ptr<CameraBuffer> &camBuffer);
/**
* \brief allocate memory
*
* Not support this function in Psys and SWProcessor
*/
virtual int allocateMemory(Port port,
const std::shared_ptr<CameraBuffer> &camBuffer) { return -1; }
/**
* \brief Add the get frame listener
*/
virtual void addFrameAvailableListener(BufferConsumer *listener);
/**
* \brief Remove the get frame listener
*/
virtual void removeFrameAvailableListener(BufferConsumer *listener);
/**
* \brief Set all frames configuration
*
* Must be called before configure which needs use frame configuration.
*/
virtual void setFrameInfo(const std::map<Port, stream_t>& inputInfo,
const std::map<Port, stream_t>& outputInfo);
/*
* \brief Get all frames configuration
*/
virtual void getFrameInfo(std::map<Port, stream_t>& inputInfo,
std::map<Port, stream_t>& outputInfo) const;
/**
* \brief Register user buffers to processor(PSys)
*/
virtual int registerUserOutputBufs(Port port,
const std::shared_ptr<CameraBuffer> &camBuffer) { return OK; }
/**
* \brief Common Interface
*/
virtual int start() = 0;
virtual void stop() = 0;
virtual int setParameters(const Parameters& param) { return OK; }
virtual int getParameters(Parameters& param) { return OK; }
virtual int configure(const std::vector<ConfigMode>& configModes) { return OK; }
protected:
virtual int processNewFrame() = 0;
/**
* \brief Clear and initialize input and output buffer queues.
*/
void clearBufferQueues();
/**
* \brief Wait for available input and output buffers.
*
* Only fetch buffer from the buffer queue, need pop buffer from
* the queue after the buffer is used, and need to be protected by mBufferQueueLock.
*/
int waitFreeBuffersInQueue(ConditionLock& lock,
std::map<Port, std::shared_ptr<CameraBuffer> > &cInBuffer,
std::map<Port, std::shared_ptr<CameraBuffer> > &cOutBuffer,
int64_t timeout = 0);
/**
* \brief Buffers allocation for producer
*/
int allocProducerBuffers(int camId, int bufNum);
protected:
/**
* \brief The process new frame buffer thread
*
* Use this thread listen to the input queue and output queue.
* And do process if these two queues are not empty
*/
class ProcessThread: public Thread {
BufferQueue *mProcessor;
public:
ProcessThread(BufferQueue *p)
: mProcessor(p) { }
virtual bool threadLoop() {
int ret = mProcessor->processNewFrame();
return (ret == 0);
}
};
static const nsecs_t kWaitDuration = 10000000000; //10000ms
BufferProducer *mBufferProducer;
std::vector<BufferConsumer*> mBufferConsumerList;
std::map<Port, stream_t> mInputFrameInfo;
std::map<Port, stream_t> mOutputFrameInfo;
std::map<Port, CameraBufQ> mInputQueue;
std::map<Port, CameraBufQ> mOutputQueue;
// For internal buffers allocation for producer
std::map<Port, CameraBufVector> mInternalBuffers;
// Guard for BufferQueue public API
Mutex mBufferQueueLock;
Condition mFrameAvailableSignal;
Condition mOutputAvailableSignal;
//for the thread loop
ProcessThread* mProcessThread;
bool mThreadRunning; //state of the processor. true after start and false after stop
private:
int queueInputBuffer(Port port, const std::shared_ptr<CameraBuffer> &camBuffer);
};
} //namespace icamera