354 lines
13 KiB
C++
354 lines
13 KiB
C++
/*
|
|
* Copyright (C) 2013-2017 Intel Corporation
|
|
* Copyright (c) 2017, Fuzhou Rockchip 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 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 _CAMERA3_HAL_V4L2DEVICE_H_
|
|
#define _CAMERA3_HAL_V4L2DEVICE_H_
|
|
|
|
#include <memory>
|
|
#include <atomic>
|
|
#include <sys/ioctl.h>
|
|
#include <linux/videodev2.h>
|
|
#include <linux/v4l2-subdev.h>
|
|
#include <poll.h>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include "PerformanceTraces.h"
|
|
#include "FrameInfo.h"
|
|
#include "SysCall.h"
|
|
#include <map>
|
|
|
|
#include "arc/camera_buffer_manager.h"
|
|
|
|
NAMESPACE_DECLARATION {
|
|
#define pioctl(fd, ctrlId, attr, name) \
|
|
SysCall::ioctl(fd, ctrlId, attr)
|
|
|
|
#define perfopen(name, attr, fd) \
|
|
fd = SysCall::open(name, attr)
|
|
|
|
#define perfclose(name, fd) \
|
|
SysCall::close(fd)
|
|
|
|
#define pbxioctl(ctrlId, attr) \
|
|
V4L2DeviceBase::xioctl(ctrlId, attr)
|
|
|
|
#define perfpoll(fd, value, timeout) \
|
|
SysCall::poll(fd, value, timeout)
|
|
|
|
/*
|
|
* Wrapper for v4l2_buffer to provide compatible
|
|
* interfaces for multi-plane buffers.
|
|
*/
|
|
class V4L2Buffer
|
|
{
|
|
public:
|
|
V4L2Buffer();
|
|
V4L2Buffer(const struct v4l2_buffer &buf);
|
|
uint32_t index() const {return vbuf.index;}
|
|
void setIndex(uint32_t index) {vbuf.index = index;}
|
|
uint32_t type() {return vbuf.type;}
|
|
void setType(uint32_t type);
|
|
uint32_t flags() {return vbuf.flags;}
|
|
void setFlags(uint32_t flags) {vbuf.flags = flags;}
|
|
uint32_t field() {return vbuf.field;}
|
|
void setField(uint32_t field) {vbuf.field = field;}
|
|
struct timeval timestamp() {return vbuf.timestamp;}
|
|
void setTimestamp(struct timeval timestamp) {vbuf.timestamp = timestamp;}
|
|
struct v4l2_timecode timecode() {return vbuf.timecode;}
|
|
void setTimecode(struct v4l2_timecode timecode) {vbuf.timecode = timecode;}
|
|
uint32_t sequence() {return vbuf.sequence;}
|
|
void setSequence(uint32_t sequence) {vbuf.sequence = sequence;}
|
|
uint32_t memory() {return vbuf.memory;}
|
|
void setMemory(uint32_t memory) {vbuf.memory = memory;}
|
|
uint32_t offset(int plane = 0);
|
|
void setOffset(uint32_t offset, int plane = 0);
|
|
unsigned long userptr(int plane = 0);
|
|
void setUserptr(unsigned long userptr, int plane = 0);
|
|
int fd(int plane = 0);
|
|
void setFd(int fd, int plane = 0);
|
|
uint32_t bytesused(int plane = 0);
|
|
void setBytesused(uint32_t bytesused, int plane = 0);
|
|
uint32_t length(int plane = 0);
|
|
void setLength(uint32_t length, int plane = 0);
|
|
uint32_t getNumPlanes();
|
|
void setNumPlanes(int numPlanes);
|
|
struct v4l2_buffer *get() {return &vbuf;}
|
|
const V4L2Buffer &operator=(const V4L2Buffer &buf);
|
|
|
|
private:
|
|
struct v4l2_buffer vbuf;
|
|
std::vector<struct v4l2_plane> planes; // For multi-planar buffers.
|
|
};
|
|
|
|
/**
|
|
* v4l2 buffer descriptor.
|
|
*
|
|
* This information is stored in the pool
|
|
*/
|
|
class V4L2BufferInfo {
|
|
public:
|
|
V4L2BufferInfo();
|
|
void *data;
|
|
size_t length;
|
|
int width;
|
|
int height;
|
|
int format;
|
|
int cache_flags; /*!< initial flags used when creating buffers */
|
|
V4L2Buffer vbuffer;
|
|
};
|
|
|
|
/*
|
|
* Wrapper for v4l2_format to provide compatible
|
|
* interfaces for multi-plane buffers.
|
|
*/
|
|
class V4L2Format
|
|
{
|
|
public:
|
|
V4L2Format() {CLEAR(vfmt);}
|
|
V4L2Format(const struct v4l2_format &fmt) {vfmt = fmt;}
|
|
uint32_t type() {return vfmt.type;}
|
|
void setType(uint32_t type);
|
|
uint32_t width();
|
|
void setWidth(uint32_t width);
|
|
uint32_t height();
|
|
void setHeight(uint32_t height);
|
|
uint32_t pixelformat();
|
|
void setPixelformat(uint32_t format);
|
|
uint32_t field();
|
|
void setField(uint32_t field);
|
|
uint32_t bytesperline(int plane = 0);
|
|
void setBytesperline(uint32_t bytesperline, int plane = 0);
|
|
uint32_t sizeimage(int plane = 0);
|
|
void setSizeimage(uint32_t size, int plane = 0);
|
|
struct v4l2_format *get() {return &vfmt;}
|
|
const V4L2Format &operator=(const V4L2Format &fmt);
|
|
|
|
private:
|
|
struct v4l2_format vfmt;
|
|
};
|
|
|
|
struct v4l2_sensor_mode {
|
|
struct v4l2_fmtdesc fmt;
|
|
struct v4l2_frmsizeenum size;
|
|
struct v4l2_frmivalenum ival;
|
|
};
|
|
|
|
/**
|
|
* A class encapsulating simple V4L2 device operations
|
|
*
|
|
* Base class that contains common V4L2 operations used by video nodes and
|
|
* subdevices. It provides a slightly higher interface than IOCTLS to access
|
|
* the devices. It also stores:
|
|
* - State of the device to protect from invalid usage sequence
|
|
* - Name
|
|
* - File descriptor
|
|
*/
|
|
class V4L2DeviceBase {
|
|
public:
|
|
explicit V4L2DeviceBase(const char *name);
|
|
virtual ~V4L2DeviceBase();
|
|
|
|
virtual status_t open();
|
|
virtual status_t close();
|
|
|
|
virtual int xioctl(int request, void *arg, int *errnoCopy = nullptr) const;
|
|
virtual int poll(int timeout);
|
|
|
|
virtual status_t setControl(int aControlNum, const int value, const char *name);
|
|
virtual status_t getControl(int aControlNum, int *value);
|
|
virtual status_t queryMenu(v4l2_querymenu &menu);
|
|
virtual status_t queryControl(v4l2_queryctrl &control);
|
|
|
|
virtual int subscribeEvent(int event);
|
|
virtual int unsubscribeEvent(int event);
|
|
virtual int dequeueEvent(struct v4l2_event *event);
|
|
|
|
bool isOpen() { return mFd != -1; }
|
|
int getFd() { return mFd; }
|
|
|
|
const char* name() { return mName.c_str(); }
|
|
|
|
static int pollDevices(const std::vector<std::shared_ptr<V4L2DeviceBase>> &devices,
|
|
std::vector<std::shared_ptr<V4L2DeviceBase>> &activeDevices,
|
|
std::vector<std::shared_ptr<V4L2DeviceBase>> &inactiveDevices,
|
|
int timeOut, int flushFd = -1,
|
|
int events = POLLPRI | POLLIN | POLLERR);
|
|
|
|
static int frmsizeWidth(struct v4l2_frmsizeenum &size);
|
|
static int frmsizeHeight(struct v4l2_frmsizeenum &size);
|
|
static void frmivalIval(struct v4l2_frmivalenum &frmival, struct v4l2_fract &ival);
|
|
static int cmpFract(struct v4l2_fract &f1, struct v4l2_fract &f2);
|
|
static int cmpIval(struct v4l2_frmivalenum &i1, struct v4l2_frmivalenum &i2);
|
|
|
|
protected:
|
|
std::string mName; /*!< path to device in file system, ex: /dev/video0 */
|
|
int mFd; /*!< file descriptor obtained when device is open */
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* A class encapsulating simple V4L2 video device node operations
|
|
*
|
|
* This class extends V4L2DeviceBase and adds extra internal state
|
|
* and more convenience methods to manage an associated buffer pool
|
|
* with the device.
|
|
* This class introduces new methods specifics to control video device nodes
|
|
*
|
|
*/
|
|
class V4L2VideoNode: public V4L2DeviceBase {
|
|
public:
|
|
explicit V4L2VideoNode(const char *name);
|
|
virtual ~V4L2VideoNode();
|
|
|
|
virtual status_t open();
|
|
virtual status_t close();
|
|
|
|
virtual status_t setBlock(bool block);
|
|
|
|
virtual status_t setInput(int index);
|
|
virtual status_t queryCap(struct v4l2_capability *cap);
|
|
virtual status_t enumerateInputs(struct v4l2_input *anInput);
|
|
|
|
// Video node configuration
|
|
virtual int getFramerate(float * framerate, int width, int height, int pix_fmt);
|
|
virtual status_t setParameter (struct v4l2_streamparm *aParam);
|
|
virtual status_t getMaxCropRectangle(struct v4l2_rect *crop);
|
|
virtual status_t setCropRectangle (struct v4l2_rect *crop);
|
|
virtual status_t getCropRectangle (struct v4l2_rect *crop);
|
|
virtual status_t setFormat(FrameInfo &aConfig);
|
|
virtual status_t getFormat(V4L2Format &aFormat);
|
|
virtual status_t setSelection(const struct v4l2_selection &aSelection);
|
|
virtual status_t queryCapturePixelFormats(std::vector<v4l2_fmtdesc> &formats);
|
|
virtual int getMemoryType();
|
|
|
|
// Buffer pool management -- DEPRECATED!
|
|
virtual status_t setBufferPool(void **pool, unsigned int poolSize,
|
|
FrameInfo *aFrameInfo, bool cached);
|
|
virtual void destroyBufferPool();
|
|
virtual int createBufferPool(unsigned int buffer_count);
|
|
|
|
// New Buffer pool management
|
|
virtual status_t setBufferPool(std::vector<V4L2Buffer> &pool,
|
|
bool cached,
|
|
int memType = V4L2_MEMORY_USERPTR);
|
|
|
|
// Buffer flow control
|
|
virtual int stop(bool keepBuffers = false);
|
|
virtual int start(int initialSkips);
|
|
|
|
virtual int grabFrame(V4L2BufferInfo *buf);
|
|
virtual int putFrame(const V4L2Buffer &buf);
|
|
virtual int putFrame(unsigned int index);
|
|
virtual int exportFrame(unsigned int index);
|
|
|
|
// Convenience accessors
|
|
virtual bool isStarted() const { return mState == DEVICE_STARTED; }
|
|
virtual unsigned int getFrameCount() const { return mFrameCounter; }
|
|
virtual unsigned int getBufsInDeviceCount() const { return mBuffersInDevice; }
|
|
virtual unsigned int getInitialFrameSkips() const { return mInitialSkips; }
|
|
virtual void getConfig(FrameInfo &config) const { config = mConfig; }
|
|
|
|
virtual status_t enumModes(std::vector<struct v4l2_sensor_mode> &modes);
|
|
std::atomic<int32_t> mBuffersInDevice; /*!< Tracks the amount of buffers inside the driver. Goes from 0 to the size of the pool*/
|
|
|
|
private:
|
|
virtual status_t setPixFormat(V4L2Format &aFormat);
|
|
virtual status_t setMetaFormat(V4L2Format &aFormat);
|
|
|
|
protected:
|
|
virtual int qbuf(V4L2BufferInfo *buf);
|
|
virtual int dqbuf(V4L2BufferInfo *buf);
|
|
virtual int newBuffer(int index, V4L2BufferInfo &buf,
|
|
int memType = V4L2_MEMORY_USERPTR);
|
|
virtual int freeBuffer(V4L2BufferInfo *buf_info);
|
|
virtual int requestBuffers(size_t num_buffers,
|
|
int memType = V4L2_MEMORY_USERPTR);
|
|
virtual void printBufferInfo(const char *func, V4L2Buffer &buf);
|
|
|
|
protected:
|
|
|
|
enum VideoNodeState {
|
|
DEVICE_CLOSED = 0, /*!< kernel device closed */
|
|
DEVICE_OPEN, /*!< device node opened */
|
|
DEVICE_CONFIGURED, /*!< device format set, IOC_S_FMT */
|
|
DEVICE_PREPARED, /*!< device has requested buffers (set_buffer_pool)*/
|
|
DEVICE_STARTED, /*!< stream started, IOC_STREAMON */
|
|
DEVICE_ERROR /*!< undefined state */
|
|
};
|
|
|
|
VideoNodeState mState;
|
|
// Device capture configuration
|
|
FrameInfo mConfig;
|
|
|
|
unsigned int mFrameCounter; /*!< Tracks the number of output buffers produced by the device. Running counter. It is reset when we start the device*/
|
|
unsigned int mInitialSkips;
|
|
|
|
std::vector<V4L2BufferInfo> mSetBufferPool; /*!< DEPRECATED:This is the buffer pool set before the device is prepared*/
|
|
std::vector<V4L2BufferInfo> mBufferPool; /*!< This is the active buffer pool */
|
|
std::vector<buffer_handle_t> mDmaBufferPool;
|
|
|
|
enum v4l2_buf_type mBufType;
|
|
int mMemoryType;
|
|
};
|
|
|
|
/**
|
|
* A class encapsulating simple V4L2 sub device node operations
|
|
*
|
|
* Sub-devices are control points to the new media controller architecture
|
|
* in V4L2
|
|
*
|
|
*/
|
|
class V4L2Subdevice: public V4L2DeviceBase {
|
|
public:
|
|
explicit V4L2Subdevice(const char *name);
|
|
virtual ~V4L2Subdevice();
|
|
|
|
virtual status_t open();
|
|
virtual status_t close();
|
|
|
|
status_t queryDvTimings(struct v4l2_dv_timings &timings);
|
|
status_t queryFormats(int pad, std::vector<uint32_t> &formats);
|
|
status_t getFormat(struct v4l2_subdev_format &aFormat);
|
|
status_t setFormat(int pad, int width, int height, int formatCode, int field, int quantization);
|
|
status_t getSelection(struct v4l2_subdev_selection &aSelection);
|
|
status_t setSelection(int pad, int target, int top, int left, int width, int height);
|
|
status_t getPadFormat(int padIndex, int &width, int &height, int &code);
|
|
status_t setFramerate(int pad, int fps);
|
|
status_t getSensorFrameDuration(int32_t &duration);
|
|
status_t getSensorFormats(int pad, uint32_t code, std::vector<struct v4l2_subdev_frame_size_enum> &fse);
|
|
private:
|
|
status_t setFormat(struct v4l2_subdev_format &aFormat);
|
|
status_t setSelection(struct v4l2_subdev_selection &aSelection);
|
|
status_t setFrameInterval(struct v4l2_subdev_frame_interval &finterval);
|
|
private:
|
|
enum SubdevState {
|
|
DEVICE_CLOSED = 0, /*!< kernel device closed */
|
|
DEVICE_OPEN, /*!< device node opened */
|
|
DEVICE_CONFIGURED, /*!< device format set, IOC_S_FMT */
|
|
DEVICE_ERROR /*!< undefined state */
|
|
};
|
|
|
|
SubdevState mState;
|
|
FrameInfo mConfig;
|
|
std::map<uint32_t, char> codeIndex;
|
|
};
|
|
|
|
} NAMESPACE_DECLARATION_END
|
|
#endif // _CAMERA3_HAL_V4L2DEVICE_H_
|