blob: 98d45e2089c2e26796f3237a7f76c43281b8a8eb [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
* Copyright@ 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 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.
*/
/*!
* \file libscaler-v4l2.h
* \brief source file for Scaler HAL
* \author Cho KyongHo <pullip.cho@samsung.com>
* \date 2014/05/12
*
* <b>Revision History: </b>
* - 2014.05.12 : Cho KyongHo (pullip.cho@samsung.com) \n
* Create
*/
#ifndef _LIBSCALER_V4L2_H_
#define _LIBSCALER_V4L2_H_
#include <fcntl.h>
#include <exynos_scaler.h>
#include "libscaler-common.h"
#define V4L2_CID_EXYNOS_BASE (V4L2_CTRL_CLASS_USER | 0x2000)
#define V4L2_CID_CSC_EQ_MODE (V4L2_CID_EXYNOS_BASE + 100)
#define V4L2_CID_CSC_EQ (V4L2_CID_EXYNOS_BASE + 101)
#define V4L2_CID_CSC_RANGE (V4L2_CID_EXYNOS_BASE + 102)
#define V4L2_CID_CONTENT_PROTECTION (V4L2_CID_EXYNOS_BASE + 201)
#define V4L2_PIX_FMT_NV12N v4l2_fourcc('N', 'N', '1', '2')
#define V4L2_PIX_FMT_NV12NT v4l2_fourcc('T', 'N', '1', '2')
#define V4L2_PIX_FMT_YUV420N v4l2_fourcc('Y', 'N', '1', '2')
#define V4L2_PIX_FMT_NV12N_10B v4l2_fourcc('B', 'N', '1', '2')
#define V4L2_BUF_FLAG_USE_SYNC 0x00008000
class CScalerV4L2 {
public:
enum { SC_MAX_PLANES = SC_NUM_OF_PLANES };
enum { SC_MAX_NODENAME = 14 };
enum { SC_V4L2_FMT_PREMULTI_FLAG = 10 };
enum SC_FRAME_FLAG {
// frame status
SCFF_BUF_FRESH = 0,
// h/w setting
SCFF_CACHEABLE,
SCFF_PREMULTIPLIED,
// v4l2 status
SCFF_REQBUFS,
SCFF_QBUF,
SCFF_STREAMING,
};
enum SC_FLAG {
SCF_RESERVED = 0,
// session status
SCF_ROTATION_FRESH,
SCF_CSC_FRESH,
SCF_DRM_FRESH,
// h/w setting setting
SCF_HFLIP,
SCF_VFLIP,
SCF_DRM,
SCF_ALLOW_DRM,
SCF_CSC_WIDE,
SCF_SRC_BLEND,
SCF_FRAMERATE,
};
struct FrameInfo {
const char *name;
v4l2_buf_type type;
unsigned int width, height;
v4l2_rect crop;
unsigned int color_format;
void *addr[SC_MAX_PLANES];
int fdAcquireFence;
enum v4l2_memory memory;
int out_num_planes;
unsigned long out_plane_size[SC_MAX_PLANES];
unsigned long flags; // enum SC_FRAME_FLAG
};
private:
FrameInfo m_frmSrc;
FrameInfo m_frmDst;
unsigned int m_nRotDegree;
unsigned int m_frameRate;
char m_cszNode[SC_MAX_NODENAME]; // /dev/videoXX
int m_iInstance;
int m_fdValidate;
unsigned int m_filter;
unsigned int m_colorspace;
void Initialize(int instance);
bool ResetDevice(FrameInfo &frm);
inline void SetRotDegree(int rot) {
rot = rot % 360;
if (rot < 0)
rot = 360 + rot;
m_nRotDegree = rot;
SetFlag(m_fStatus, SCF_ROTATION_FRESH);
}
bool DevSetFormat(FrameInfo &frm);
bool ReqBufs(FrameInfo &frm);
bool QBuf(FrameInfo &frm, int *pfdReleaseFence);
bool StreamOn(FrameInfo &frm);
bool DQBuf(FrameInfo &frm);
inline bool SetFormat(FrameInfo &frm, unsigned int width, unsigned int height,
unsigned int v4l2_colorformat) {
frm.color_format = v4l2_colorformat;
frm.width = width;
frm.height = height;
SetFlag(frm.flags, SCFF_BUF_FRESH);
return true;
}
inline bool SetCrop(FrameInfo &frm, unsigned int left, unsigned int top,
unsigned int width, unsigned int height) {
frm.crop.left = left;
frm.crop.top = top;
frm.crop.width = width;
frm.crop.height = height;
SetFlag(frm.flags, SCFF_BUF_FRESH);
return true;
}
inline void SetPremultiplied(FrameInfo &frm, unsigned int premultiplied) {
if (premultiplied)
SetFlag(frm.flags, SCFF_PREMULTIPLIED);
else
ClearFlag(frm.flags, SCFF_PREMULTIPLIED);
}
inline void SetCacheable(FrameInfo &frm, bool __UNUSED__ cacheable) {
SetFlag(frm.flags, SCFF_CACHEABLE);
}
inline void SetAddr(FrameInfo &frm, void *addr[SC_NUM_OF_PLANES], int mem_type, int fence)
{
for (int i = 0; i < SC_MAX_PLANES; i++)
frm.addr[i] = addr[i];
frm.memory = static_cast<v4l2_memory>(mem_type);
frm.fdAcquireFence = fence;
}
bool RunSWScaling();
protected:
unsigned long m_fStatus; // enum SC_FLAG
int m_fdScaler;
inline void SetFlag(unsigned long &flags, unsigned long flag) {
flags |= (1 << flag);
}
inline void ClearFlag(unsigned long &flags, unsigned long flag) {
flags &= ~(1 << flag);
}
inline bool TestFlag(unsigned long &flags, unsigned long flag) {
return (flags & (1 << flag)) != 0;
}
public:
inline bool Valid() { return (m_fdScaler >= 0) && (m_fdScaler == -m_fdValidate); }
CScalerV4L2(int instance, int allow_drm = 0);
virtual ~CScalerV4L2();
bool SetCtrl();
inline bool IsDRMAllowed() { return TestFlag(m_fStatus, SCF_ALLOW_DRM); }
inline int GetScalerID() { return m_iInstance; }
bool Stop();
bool Run(); // Blocking mode
// H/W Control
virtual bool DevSetCtrl();
bool DevSetFormat();
inline bool ReqBufs() {
if (!ReqBufs(m_frmSrc))
return false;
return ReqBufs(m_frmDst);
}
inline bool QBuf(int *pfdSrcReleaseFence = NULL, int *pfdDstReleaseFence = NULL) {
if (!QBuf(m_frmSrc, pfdSrcReleaseFence))
return false;
if (!QBuf(m_frmDst, pfdDstReleaseFence)) {
ClearFlag(m_frmSrc.flags, SCFF_QBUF);
return false;
}
return true;
}
inline bool StreamOn() {
if (!StreamOn(m_frmSrc))
return false;
return StreamOn(m_frmDst);
}
inline bool DQBuf() {
if (!DQBuf(m_frmSrc))
return false;
return DQBuf(m_frmDst);
}
inline bool SetSrcFormat(unsigned int width, unsigned int height,
unsigned int v4l2_colorformat) {
return SetFormat(m_frmSrc, width, height, v4l2_colorformat);
}
inline bool SetDstFormat(unsigned int width, unsigned int height,
unsigned int v4l2_colorformat) {
return SetFormat(m_frmDst, width, height, v4l2_colorformat);
}
inline bool SetSrcCrop(unsigned int left, unsigned int top,
unsigned int width, unsigned int height) {
return SetCrop(m_frmSrc, left, top, width, height);
}
inline bool SetDstCrop(unsigned int left, unsigned int top,
unsigned int width, unsigned int height) {
return SetCrop(m_frmDst, left, top, width, height);
}
inline void SetDRM(bool drm) {
if (drm != TestFlag(m_fStatus, SCF_DRM)) {
if (drm)
SetFlag(m_fStatus, SCF_DRM);
else
ClearFlag(m_fStatus, SCF_DRM);
SetFlag(m_fStatus, SCF_DRM_FRESH);
}
}
inline void SetCSCWide(bool wide) {
if (wide)
SetFlag(m_fStatus, SCF_CSC_WIDE);
else
ClearFlag(m_fStatus, SCF_CSC_WIDE);
SetFlag(m_fStatus, SCF_CSC_FRESH);
}
inline void SetCSCEq(unsigned int v4l2_colorspace) {
if (v4l2_colorspace == V4L2_COLORSPACE_SMPTE170M)
m_colorspace = V4L2_COLORSPACE_DEFAULT;
else
m_colorspace = v4l2_colorspace;
SetFlag(m_fStatus, SCF_CSC_FRESH);
}
inline void SetFilter(unsigned int filter) {
m_filter = filter;
}
inline void SetSrcCacheable(bool cacheable) {
return SetCacheable(m_frmSrc, cacheable);
}
inline void SetDstCacheable(bool cacheable) {
return SetCacheable(m_frmDst, cacheable);
}
inline void SetSrcPremultiplied(bool premultiplied) {
return SetPremultiplied(m_frmSrc, premultiplied);
}
inline void SetDstPremultiplied(bool premultiplied) {
return SetPremultiplied(m_frmDst, premultiplied);
}
// Parameter Extraction
bool SetRotate(int rot, int flip_h, int flip_v);
inline bool SetSrcAddr(void *addr[SC_NUM_OF_PLANES], int mem_type, int fence = -1) {
SetAddr(m_frmSrc, addr, mem_type, fence);
return true;
}
inline bool SetDstAddr(void *addr[SC_NUM_OF_PLANES], int mem_type, int fence = -1) {
SetAddr(m_frmDst, addr, mem_type, fence);
return true;
}
inline void SetFrameRate(int framerate) {
m_frameRate = framerate;
SetFlag(m_fStatus, SCF_FRAMERATE);
}
};
#endif //_LIBSCALER_V4L2_H_