Qualcomm Camera HAL3: Dump YUV and RAW implemented in CAMX

During the CMAX development process, it is often necessary to dump yuv or raw images at the HAL layer for analysis.

How to implement Dump YUV and RAW functions in CAMX?

Without further ado, let’s get into the code.

1. Dump YUV function implementation code

1. Add the following code to the header file:

typedef long                   MLong;
typedef float                  MFloat;
typedef double                 MDouble;
typedef unsigned char          MByte;
typedef unsigned short         MWord;
typedef unsigned int           MDWord;
typedef void*                  MHandle;
typedef char                   MChar;
typedef long                   MBool;
typedef void                   MVoid;
typedef void*                  MPVoid;
typedef char*                  MPChar;
typedef short                  MShort;
typedef const    char*         MPCChar;
typedef MLong                  MRESULT;
typedef MDWord                 MCOLORREF;
typedef signed   char          MInt8;
typedef unsigned char          MUInt8;
typedef signed   short         MInt16;
typedef unsigned short         MUInt16;
typedef signed   int           MInt32;
typedef unsigned int           MUInt32;
/*Define the image format space*/
typedef struct __tag_ASVL_OFFSCREEN{
	MUInt32	u32PixelArrayFormat;
	MInt32	i32Width;
	MInt32	i32Height;
	MUInt8*	ppu8Plane[4];
	MInt32	pi32Pitch[4];
}ASVLOFFSCREEN, *LPASVLOFFSCREEN;
// used for performance
static long long __attribute__((unused))  gettime(){
    struct timeval time;
    gettimeofday(&time, NULL);
    return ((long long)time.tv_sec * 1000 + time.tv_usec / 1000);
}
VOID DumpYUVData(ASVLOFFSCREEN* pASLIn, UINT index, const CHAR* namePrefix, long long timestamp);  //放到具体node类的private 中

2. In the .cpp file of the specific node, add the following code:

#define DUMP_FILE_PATH "/data/vendor/camera/"
VOID XXXNode::DumpYUVData(ASVLOFFSCREEN* pASLIn, UINT index, const CHAR* namePrefix, long long timestamp){
    CHAR filename[256];
    memset(filename, 0, sizeof(CHAR) * 256);
    snprintf(filename, sizeof(filename), "%s%s_%llu_%d_%dx%d_%d.nv12",DUMP_FILE_PATH,namePrefix,timestamp,index,pASLIn->pi32Pitch[0],pASLIn->i32Height, 0);

    int file_fd = open(filename,O_RDWR|O_CREAT,0777);
    if(file_fd){
        UINT bytes_write;
	    //存储第一个plane, Y, 长度是 所有像素的总个数,即像素图像的宽x高
        bytes_write = write(file_fd,pASLIn->ppu8Plane[0],pASLIn->pi32Pitch[0] * pASLIn->i32Height);
	    //存储第二个plane, UV, UV长度是Y的长度的一半,所以是 像素图像的宽x高/2
        bytes_write = write(file_fd,pASLIn->ppu8Plane[1],pASLIn->pi32Pitch[0] * (pASLIn->i32Height >> 1) );
        close(file_fd);
    }else{
        ALOGE("fileopen  error");
    }
}
CDKResult XXXNode::ProcessRequest(CHINODEPROCESSREQUESTINFO* pProcessRequestInfo){
    CHINODEBUFFERHANDLE hOutput = pProcessRequestInfo->phOutputBuffer[0];
    CHINODEBUFFERHANDLE hInput = pProcessRequestInfo->phInputBuffer[0];
    ASVLOFFSCREEN inputFrame, outputFrame;

    long long t0 = gettime();
    inputFrame.i32Width = hInput->format.width;
    inputFrame.i32Height = hInput->format.height;
    for(UINT j = 0; j < hInput->numberOfPlanes; j++) {
        //nv12就两个plane,第个plane 是Y; 第二个plane 是UV
        inputFrame.pi32Pitch[j] = hInput->format.formatParams.yuvFormat[0].planeStride;      //每个plane的宽
        inputFrame.ppu8Plane[j] = hInput->pImageList[0].pAddr[j];      //每个plane的数据首地址
    }

    outputFrame.i32Width = hOutput->format.width;
    outputFrame.i32Height = hOutput->format.height;
    for(UINT j = 0; j < hOutput->numberOfPlanes; j++) {
        outputFrame.pi32Pitch[j] = hOutput->format.formatParams.yuvFormat[0].planeStride;
        outputFrame.ppu8Plane[j] = hOutput->pImageList[0].pAddr[j];
    }

    DumpYUVData(&inputFrame, 0, "IMG", t0);
    //CopyImage(pProcessRequestInfo->phOutputBuffer[i], pProcessRequestInfo->phInputBuffer[i]);
    DumpYUVData(&outputFrame, 1, "IMG", t0);
}

2. Dump RAW function implementation code

1. Add functions in camxchixxxxxnode.cpp code:

VOID ChiAWRawHdrNode::DumpRAWData(CHINODEBUFFERHANDLE hRAWIn, const CHAR* namePrefix)
{
    if (hRAWIn == NULL) {
        LOG_INFO(CamxLogGroupChi, "[AW_RAWNS]  hRAWIn is NULL");
        return;
    }
    CHAR filename[128];
    int written_len = 0;
    memset(filename, 0 , sizeof(CHAR) * 128);
    snprintf(filename, sizeof(filename), "/data/vendor/camera/%s_%dx%d.RAW", namePrefix, hRAWIn->format.formatParams.rawFormat.stride, hRAWIn->format.formatParams.rawFormat.sliceHeight);
    LOG_INFO(CamxLogGroupChi, "[AW_RAWNS] try to open file : %s", filename);


    int file_fd = open(filename, O_RDWR | O_CREAT | O_APPEND, 0777);
    if(file_fd)
{
        if (hRAWIn->planeSize[0] != 0) {
            uint32_t index = 0;
            void *data = NULL;
            data = (void *)((uint8_t *)hRAWIn->pImageList[0].pAddr[0]);
            written_len += write(file_fd, data, hRAWIn->planeSize[0]);
            LOG_INFO(CamxLogGroupChi, "[AW_RAWNS] written number of bytes %zu\n", hRAWIn->planeSize[0]);
        }

        close(file_fd);
    }
else
{
        LOG_ERROR(CamxLogGroupChi, "[AW_RAWNS] fileopen  error: %d", file_fd);
    }
}

The parameter CHINODEBUFFERHANDLE is defined in chinode.h. It comes with Qualcomm code and does not need to be added.

2. Add where Dump is required (for example, in the ProcessRequest() function:

CDKResult ChiAWRawHdrNode::ProcessRequest(CHINODEPROCESSREQUESTINFO* pProcessRequestInfo)
{
        if(property_get_int32("debug.vendor.camera.dumpawraw", 0))
        {
		CHAR filename[256];
		long long timestamp = gettime();
		memset(filename, 0 , sizeof(CHAR) * 256);
		snprintf(filename, sizeof(filename), "rawhdr_frame_%llu_input%d", timestamp,i);
		DumpRAWData(pProcessRequestInfo->phInputBuffer[i],filename);
	}
}

3. End 

Guess you like

Origin blog.csdn.net/geyichongchujianghu/article/details/131140588