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);
}
}