/* * 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 * \date 2014/05/12 * * Revision History: * - 2014.05.12 : Cho KyongHo (pullip.cho@samsung.com) \n * Create */ #ifndef _LIBSCALER_V4L2_H_ #define _LIBSCALER_V4L2_H_ #include #include #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(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_