android13/hardware/rockchip/tv_input/HinDev.h

346 lines
12 KiB
C++

/*
* Copyright (c) 2021 Rockchip Electronics Co., Ltd
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/select.h>
#include <linux/videodev2.h>
#include <sys/time.h>
#include <unordered_map>
#include <utils/KeyedVector.h>
#include <cutils/properties.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <utils/threads.h>
#include <hardware/gralloc.h>
#include <hardware/tv_input.h>
#include <map>
#include "TvDeviceV4L2Event.h"
#include "sideband/RTSidebandWindow.h"
#include "common/RgaCropScale.h"
#include "common/HandleImporter.h"
#include "common/rk_hdmirx_config.h"
#include "common/rk-camera-module.h"
#include <rkpq.h>
#include "rkiep.h"
#include "MppEncodeServer.h"
#include "RKMppEncApi.h"
#ifdef LOG_TAG
#undef LOG_TAG
#define LOG_TAG "tv_input"
#endif
using namespace android;
using ::android::tvinput::RgaCropScale;
typedef struct source_buffer_info {
buffer_handle_t source_buffer_handle_t;
int reserved_data;
long tv_sec;
long tv_usec;
} source_buffer_info_t;
struct HinNodeInfo {
struct v4l2_capability cap;
struct v4l2_format format;
struct v4l2_plane planes[SIDEBAND_WINDOW_BUFF_CNT];
struct v4l2_buffer onceBuff;
struct v4l2_requestbuffers reqBuf;
struct v4l2_buffer bufferArray[SIDEBAND_WINDOW_BUFF_CNT];
buffer_handle_t buffer_handle_poll[SIDEBAND_WINDOW_BUFF_CNT];
vt_buffer_t *vt_buffers[SIDEBAND_WINDOW_BUFF_CNT];
// long *mem[SIDEBAND_WINDOW_BUFF_CNT];
// unsigned reservedData[SIDEBAND_WINDOW_BUFF_CNT];
// unsigned refcount[SIDEBAND_WINDOW_BUFF_CNT];
int currBufferHandleFd;
int currBufferHandleIndex;
bool isStreaming;
int width;
int height;
int formatIn;
int framesizeIn;
int displaymode;
};
typedef struct tv_record_buffer_info {
buffer_handle_t outHandle;
int width;
int height;
int verStride;
int horStride;
bool isCoding;
} tv_record_buffer_info_t;
typedef struct tv_pq_buffer_info {
buffer_handle_t srcHandle = NULL;
buffer_handle_t outHandle = NULL;
int src_vt_fd = -1;
vt_buffer_t *out_vt_buffer = nullptr;
bool isFilled;
} tv_pq_buffer_info_t;
enum State {
START,
PAUSE,
STOPING,
STOPED,
};
typedef struct tv_preview_buff_app {
int bufferFd;
uint64_t bufferId;
// buffer_handle_t rawHandle;
buffer_handle_t outHandle;
bool isRendering;
bool isFilled;
} tv_preview_buff_app_t;
// typedef struct tv_input_preview_buff {
// uint64_t bufferId;
// buffer_handle_t* buffPtr;
// bool isRendering;
// bool isFilled;
// } tv_input_preview_buff_t;
typedef struct tv_input_command{
int command_id;
} tv_input_command_t;
typedef void (*NotifyQueueDataCallback)(tv_input_capture_result_t result, uint64_t buff_id);
typedef void (*app_data_callback)(void *user, source_buffer_info_t *buff_info);
typedef void (*NotifyCommandCallback)(tv_input_command command);
#define HIN_GRALLOC_USAGE GRALLOC_USAGE_HW_TEXTURE | \
GRALLOC_USAGE_HW_RENDER | \
GRALLOC_USAGE_SW_READ_RARELY | \
GRALLOC_USAGE_SW_WRITE_NEVER
#ifndef container_of
#define container_of(ptr, type, member) \
(type *)((char*)(ptr) - offsetof(type, member))
#endif
static std::vector<tv_record_buffer_info_t> mRecordHandle;
//static std::mutex mRecordMutex;
class HinDevImpl {
public:
HinDevImpl();
~HinDevImpl();
int init(int id,int type, int& initWidth, int& initHeight,int& initFormat);
int findDevice(int id, int& initWidth, int& initHeight,int& initFormat);
int start();
int stop();
int pause();
int get_csi_format(int fd, int &hdmi_in_width, int &hdmi_in_height,int& initFormat);
int get_format(int fd, int &hdmi_in_width, int &hdmi_in_height,int& initFormat);
int set_format(int width = 640, int height = 480, int color_format = V4L2_PIX_FMT_NV21);
int get_HdmiIn(bool enforce);
int set_crop(int x, int y, int width, int height);
int set_preview_info(int top, int left, int width, int height);
int set_preview_buffer(buffer_handle_t rawHandle, uint64_t bufferId);
int aquire_buffer();
// int inc_buffer_refcount(int* ptr);
int release_buffer();
int set_preview_callback(NotifyQueueDataCallback callback);
int set_data_callback(V4L2EventCallBack callback);
int set_command_callback(NotifyCommandCallback callback);
int set_frame_rate(int frameRate);
int get_current_sourcesize(int& width,int& height,int& format);
int start_device();
int stop_device();
int set_mode(int display_mode);
buffer_handle_t getSindebandBufferHandle();
buffer_handle_t getSindebandCancelBufferHandle();
int deal_priv_message(const string action, const map<string, string> data);
int request_capture(buffer_handle_t rawHandle, uint64_t bufferId);
bool check_zme(int src_width, int src_height, int* dst_width, int* dst_height);
int check_interlaced();
void set_interlaced(int interlaced);
const tv_input_callback_ops_t* mTvInputCB;
//Just for first start encoding thread control
bool mEncodeThreadRunning = false;
MppEncodeServer *gMppEnCodeServer=nullptr;
private:
int workThread();
int pqBufferThread();
int iepBufferThread();
int getPqFmt(int V4L2Fmt);
void initPqInfo(int pqMode, int hdmi_range_mode);
// int previewBuffThread();
int makeHwcSidebandHandle();
void wrapCaptureResultAndNotify(uint64_t buffId, buffer_handle_t handle, bool forceNotify);
void doRecordCmd(const map<string, string> data);
void doPQCmd(const map<string, string> data);
int getRecordBufferFd(int previewHandlerIndex);
int init_encodeserver(MppEncodeServer::MetaInfo* info);
void deinit_encodeserver();
void stopRecord();
void buffDataTransfer(buffer_handle_t srcHandle, int srcFmt, int srcWidth, int srcHeight,
buffer_handle_t dstHandle, int dstFmt, int dstWidth, int dstHeight, int dstWStride, int dstHStride);
int getOutRange(char* value);
int get_extfmt_info();
void showVTunnel(vt_buffer_t* vt_buffer);
bool needShowPqFrame(int pqMode);
bool qBuf(int fd, bool noFoundLog);
private:
class WorkThread : public Thread {
HinDevImpl* mSource;
public:
WorkThread(HinDevImpl* source) :
Thread(false), mSource(source) { }
virtual void onFirstRef() {
run("tif work thread", PRIORITY_URGENT_DISPLAY);
}
virtual bool threadLoop() {
mSource->workThread();
// loop until we need to quit
return true;
}
};
class PqBufferThread : public Thread {
HinDevImpl* mSource;
public:
PqBufferThread(HinDevImpl* source) :
Thread(false), mSource(source) { }
virtual void onFirstRef() {
run("tif pq buffer thread", PRIORITY_URGENT_DISPLAY);
}
virtual bool threadLoop() {
mSource->pqBufferThread();
// loop until we need to quit
return true;
}
};
class IepBufferThread : public Thread {
HinDevImpl* mSource;
public:
IepBufferThread(HinDevImpl* source) :
Thread(false), mSource(source) { }
virtual void onFirstRef() {
run("tif iep buffer thread", PRIORITY_URGENT_DISPLAY);
}
virtual bool threadLoop() {
mSource->iepBufferThread();
// loop until we need to quit
return true;
}
};
// class PreviewBuffThread : public Thread {
// HinDevImpl* mSource;
// public:
// PreviewBuffThread(HinDevImpl* source) :
// Thread(false), mSource(source) { }
// virtual void onFirstRef() {
// run("hdmi_input_source preview buff work thread", PRIORITY_URGENT_DISPLAY);
// }
// virtual bool threadLoop() {
// mSource->previewBuffThread();
// // loop until we need to quit
// return true;
// }
// };
private:
//int mCurrentIndex;
//KeyedVector<long *, long> mBufs;
//KeyedVector<long *, long> mTemp_Bufs;
int mBufferCount;
int mSrcFrameWidth;
int mSrcFrameHeight;
int mDstFrameWidth;
int mDstFrameHeight;
int mFrameFps;
int mFrameColorRange = HDMIRX_DEFAULT_RANGE;
int mFrameColorSpace = HDMIRX_XVYCC709;
int mBufferSize;
bool mIsHdmiIn;
unsigned int flex_ratio;
unsigned int flex_original;
int m_FrameHeight = 0;
int m_FrameWidth = 0;
int m_rest = 0;
int m_displaymode;
volatile int mState;
NotifyQueueDataCallback mNotifyQueueCb;
NotifyCommandCallback mNotifyCommandCb = NULL;
int mPixelFormat;
int mNativeWindowPixelFormat;
sp<ANativeWindow> mANativeWindow;
sp<WorkThread> mWorkThread;
sp<PqBufferThread> mPqBufferThread;
sp<IepBufferThread> mIepBufferThread;
// sp<PreviewBuffThread> mPreviewBuffThread;
mutable Mutex mLock;
Mutex mBufferLock;
int mHinDevHandle;
int mHinDevEventHandle = -1;
struct HinNodeInfo *mHinNodeInfo;
sp<V4L2DeviceEvent> mV4l2Event;
sp<V4L2DeviceEvent> mCsiV4l2Event;
buffer_handle_t mSignalPreviewHandle = NULL;
buffer_handle_t mSignalHandle = NULL;
vt_buffer_t *mSignalVTBuffer = nullptr;
buffer_handle_t mSidebandHandle;
buffer_handle_t mSidebandCancelHandle = NULL;
sp<RTSidebandWindow> mSidebandWindow;
int mFrameType;
bool mOpen;
int mDebugLevel;
int mSkipFrame;
int mDumpFrameCount;
void *mUser;
bool mV4L2DataFormatConvert;
int mPreviewBuffIndex = 0;
bool mFirstRequestCapture;
int mRequestCaptureCount = 0;
std::vector<tv_preview_buff_app_t> mPreviewRawHandle;
std::vector<tv_pq_buffer_info_t> mIepBufferHandle;
tv_pq_buffer_info_t mIepTempHandle;
std::vector<int> mIepPrepareList;
std::vector<int> mIepDoneList;
int mRecordCodingBuffIndex = 0;
int mDisplayRatio = FULL_SCREEN;
int mPqMode = PQ_OFF;
bool mIsLastPqShowFrameMode = false;
int mOutRange = HDMIRX_DEFAULT_RANGE;
int mLastOutRange = mOutRange;
std::vector<tv_pq_buffer_info_t> mPqBufferHandle;
std::vector<int> mPqPrepareList;
std::vector<int> mPqDoneList;
int mPqBuffIndex = 0;
int mPqBuffOutIndex = 0;
rkpq *mRkpq=nullptr;
bool mUseZme = false;
bool mLastZmeStatus = false;
rkiep *mRkiep=nullptr;
int mIepBuffIndex = 0;
int mIepBuffOutIndex = 0;
bool mUseIep = false;
bool mPqIniting = false;
int mLastPqStatus = -1;
int mEnableDump = 0;
int mHdmiInType = HDMIIN_TYPE_HDMIRX;//0 hdmirx, 1 mipicsi
int mQbufCount = 0;
int mDstColorSpace = 0;
bool mUpdateColorSpace = false;
struct v4l2_plane mCurrentPlanes;
struct v4l2_buffer mCurrentBufferArray;
// std::vector<tv_input_preview_buff_t> mPreviewBuff;
};