Files
Linux_Drivers/u-boot-2021.10/drivers/jpeg/jpuhelper.c
forum_service ebdd1dbfcf u-boot: weekly update 2023-09-06
Update mipi_tx
Update Jpeg driver

Change-Id: I5e1f2e64befbd52cbb45e2c235945effef136d91
2023-12-21 16:52:04 +08:00

2018 lines
51 KiB
C

#include <linux/string.h>
#include <malloc.h>
#include <common.h>
#include "jpuapi.h"
#include "jpuapifunc.h"
#include "jpuhelper.h"
#include "jpulog.h"
#include "jputable.h"
#include "regdefine.h"
extern int sscanf(const char *str, const char *format, ...);
extern int __must_check kstrtoint(const char *s, unsigned int base, int *res);
static int FillSdramBurst(BufInfo *pBufInfo, Uint64 targetAddr,
PhysicalAddress bsBufStartAddr,
PhysicalAddress bsBufEndAddr, Uint32 size,
int checkeos, int *streameos, int endian);
static int StoreYuvImageBurstFormat(Uint8 *dst, int picWidth, int picHeight,
unsigned long addrY, unsigned long addrCb,
unsigned long addrCr, int stride,
int interLeave, int format, int endian,
int packed);
static void ProcessEncodedBitstreamBurst(osal_file_t *fp,
unsigned long targetAddr,
PhysicalAddress bsBufStartAddr,
PhysicalAddress bsBufEndAddr, int size,
int endian);
static int LoadYuvImageBurstFormat(unsigned char *src, int picWidth,
int picHeight, unsigned long addrY,
unsigned long addrCb, unsigned long addrCr,
int stride, int interLeave, int format,
int endian, int packed);
// Figure A.6 - Zig-zag sequence of quantized DCT coefficients
const int InvScanTable[64] = {
0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42,
3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53,
10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60,
21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63
};
const int ScanTable[64] = {
0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18,
11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20,
13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43,
36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45,
38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
};
JpgRet WriteJpgBsBufHelperStream(JpgDecHandle handle, BufInfo *pBufInfo,
PhysicalAddress paBsBufStart,
PhysicalAddress paBsBufEnd, int defaultsize,
int checkeos, int *pstreameos, int endian)
{
JpgRet ret = JPG_RET_SUCCESS;
int size = 0;
int fillSize = 0;
PhysicalAddress paRdPtr, paWrPtr;
ret = JPU_DecGetBitstreamBuffer(handle, &paRdPtr, &paWrPtr, &size);
JLOG(INFO, "rdPtr: 0x%lx, wrPtr: 0x%lx, size: %d\n", paRdPtr, paWrPtr, size);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecGetBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
if (size <= 0)
return JPG_RET_SUCCESS;
if (defaultsize) {
if (size < defaultsize)
fillSize = size;
else
fillSize = defaultsize;
} else {
fillSize = size;
}
JLOG(INFO, "Before fillSize: %d\n", fillSize);
fillSize = FillSdramBurst(pBufInfo, paWrPtr, paBsBufStart, paBsBufEnd,
fillSize, checkeos, pstreameos, endian);
if (fillSize == 0 && pBufInfo->fillendbs != 1)
return ret;
JLOG(INFO, "After fillSize :%d\n", fillSize);
if (*pstreameos == 0) {
ret = JPU_DecUpdateBitstreamBuffer(handle, fillSize);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
if (pBufInfo->fillendbs == 1) {
ret = JPU_DecUpdateBitstreamBuffer(handle, STREAM_END_SIZE);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
// pBufInfo->fillendbs = 1;
}
} else {
if (!pBufInfo->fillendbs) {
ret = JPU_DecUpdateBitstreamBuffer(handle, STREAM_END_SIZE);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
pBufInfo->fillendbs = 1;
}
}
FILL_BS_ERROR:
return ret;
}
JpgRet WriteJpgBsBufHelper(JpgDecHandle handle, BufInfo *pBufInfo,
PhysicalAddress paBsBufStart,
PhysicalAddress paBsBufEnd, int defaultsize,
int checkeos, int *pstreameos, int endian)
{
JpgRet ret = JPG_RET_SUCCESS;
int size = 0;
int fillSize = 0;
PhysicalAddress paRdPtr, paWrPtr;
ret = JPU_DecGetBitstreamBuffer(handle, &paRdPtr, &paWrPtr, &size);
JLOG(INFO, "rdPtr: 0x%lx, wrPtr: 0x%lx, size: %d\n", paRdPtr, paWrPtr, size);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecGetBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
if (size <= 0)
return JPG_RET_SUCCESS;
if (defaultsize) {
if (size < defaultsize)
fillSize = size;
else
fillSize = defaultsize;
} else {
fillSize = size;
}
fillSize = FillSdramBurst(pBufInfo, paWrPtr, paBsBufStart, paBsBufEnd,
fillSize, checkeos, pstreameos, endian);
JLOG(INFO, "fillSize :%d\n", fillSize);
if (*pstreameos == 0) {
ret = JPU_DecUpdateBitstreamBuffer(handle, fillSize);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
if ((pBufInfo->size - pBufInfo->point) <= 0) {
ret = JPU_DecUpdateBitstreamBuffer(handle, STREAM_END_SIZE);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
pBufInfo->fillendbs = 1;
}
} else {
if (!pBufInfo->fillendbs) {
ret = JPU_DecUpdateBitstreamBuffer(handle, STREAM_END_SIZE);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_DecUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto FILL_BS_ERROR;
}
pBufInfo->fillendbs = 1;
}
}
FILL_BS_ERROR:
return ret;
}
/**
* Bitstream Read for encoders
*/
JpgRet ReadJpgBsBufHelper(JpgEncHandle handle, osal_file_t *bsFp,
PhysicalAddress paBsBufStart,
PhysicalAddress paBsBufEnd, int encHeaderSize,
int endian)
{
JpgRet ret = JPG_RET_SUCCESS;
int loadSize = 0;
int stuffSize;
PhysicalAddress paRdPtr, paWrPtr;
int size = 0;
ret = JPU_EncGetBitstreamBuffer(handle, &paRdPtr, &paWrPtr, &size);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "JPU_EncGetBitstreamBuffer failed Error code is 0x%x\n", ret);
goto LOAD_BS_ERROR;
}
if (size > 0) {
stuffSize = 0;
if (encHeaderSize && (size + encHeaderSize) % 8) {
stuffSize = (size + encHeaderSize) - ((size + encHeaderSize) / 8) * 8;
stuffSize = 8 - stuffSize;
}
loadSize = size;
if (loadSize > 0) {
ProcessEncodedBitstreamBurst(bsFp, paRdPtr, paBsBufStart, paBsBufEnd, loadSize, endian);
ret = JPU_EncUpdateBitstreamBuffer(handle, loadSize);
if (ret != JPG_RET_SUCCESS) {
JLOG(ERR, "VPU_EncUpdateBitstreamBuffer failed Error code is 0x%x\n", ret);
goto LOAD_BS_ERROR;
}
}
}
LOAD_BS_ERROR:
return ret;
}
/******************************************************************************
* DPB Image Data Control
******************************************************************************/
int LoadYuvImageHelperFormat(osal_file_t *yuvFp, Uint8 *pYuv,
PhysicalAddress addrY, PhysicalAddress addrCb,
PhysicalAddress addrCr, int picWidth,
int picHeight, int stride, int interleave,
int format, int endian, int packed)
{
int frameSize = 0;
switch (format) {
case FORMAT_420:
frameSize = picWidth * picHeight * 3 / 2;
break;
case FORMAT_224:
frameSize = picWidth * picHeight * 4 / 2;
break;
case FORMAT_422:
frameSize = picWidth * picHeight * 4 / 2;
break;
case FORMAT_444:
frameSize = picWidth * picHeight * 6 / 2;
break;
case FORMAT_400:
frameSize = picWidth * picHeight;
break;
}
if (packed == PACKED_FORMAT_NONE) {
frameSize = frameSize;
} else if (packed == PACKED_FORMAT_444) {
frameSize = picWidth * 3 * picHeight;
} else { // PACKED_FORMAT_422_XXXX
frameSize = picWidth * 2 * picHeight;
}
// Load source one picture image to encode to SDRAM frame buffer.
if (!OSAL_FREAD(pYuv, 1, frameSize, yuvFp)) {
if (!OSAL_FEOF(yuvFp))
JLOG(ERR, "Yuv Data fread failed file handle is 0x%p\n", yuvFp);
return 0;
}
LoadYuvImageBurstFormat(pYuv, picWidth, picHeight, addrY, addrCb,
addrCr, stride, interleave, format, endian,
packed);
return 1;
}
int LoadYuvPartialImageHelperFormat(osal_file_t *yuvFp, Uint8 *pYuv, PhysicalAddress addrY,
PhysicalAddress addrCb, PhysicalAddress addrCr, int picWidth, int picHeight,
int picHeightPartial, int stride, int interleave, int format, int endian,
int partPosIdx, int frameIdx, int packed)
{
int LumaPicSize;
int ChromaPicSize;
int LumaPartialSize;
int ChromaPartialSize;
int pos;
int divX, divY;
int frameSize = 0;
divX = format == FORMAT_420 || format == FORMAT_422 ? 2 : 1;
divY = format == FORMAT_420 || format == FORMAT_224 ? 2 : 1;
LumaPicSize = picWidth * picHeight;
ChromaPicSize = LumaPicSize / divX / divY;
LumaPartialSize = picWidth * picHeightPartial;
ChromaPartialSize = LumaPartialSize / divX / divY;
if (format == FORMAT_400)
frameSize = LumaPicSize;
else
frameSize = LumaPicSize + ChromaPicSize * 2;
// Load source one picture image to encode to SDRAM frame buffer.
if (packed) {
if (packed == PACKED_FORMAT_444) {
LumaPicSize = picWidth * 3 * picHeight;
LumaPartialSize = picWidth * 3 * picHeightPartial;
} else {
LumaPicSize = picWidth * 2 * picHeight;
LumaPartialSize = picWidth * 2 * picHeightPartial;
}
frameSize = LumaPicSize;
ChromaPicSize = 0;
ChromaPartialSize = 0;
}
// Y
OSAL_FSEEK(yuvFp, (frameIdx * frameSize), SEEK_SET);
pos = LumaPartialSize * partPosIdx;
OSAL_FSEEK(yuvFp, pos, SEEK_CUR);
if (!OSAL_FREAD(pYuv, 1, LumaPartialSize, yuvFp)) {
if (!OSAL_FEOF(yuvFp))
JLOG(ERR, "Yuv Data fread failed file handle is 0x%p\n", yuvFp);
return 0;
}
if (format != FORMAT_400 && packed == 0) {
// Cb
OSAL_FSEEK(yuvFp, (frameIdx * frameSize), SEEK_SET);
pos = LumaPicSize + ChromaPartialSize * partPosIdx;
OSAL_FSEEK(yuvFp, pos, SEEK_CUR);
if (!OSAL_FREAD(pYuv + LumaPartialSize, 1, ChromaPartialSize,
yuvFp)) {
if (!OSAL_FEOF(yuvFp))
JLOG(ERR, "Yuv Data fread failed file handle is 0x%p\n", yuvFp);
return 0;
}
// Cr
OSAL_FSEEK(yuvFp, (frameIdx * frameSize), SEEK_SET);
pos = LumaPicSize + ChromaPicSize + ChromaPartialSize * partPosIdx;
OSAL_FSEEK(yuvFp, pos, SEEK_CUR);
if (!OSAL_FREAD(pYuv + LumaPartialSize + ChromaPartialSize, 1, ChromaPartialSize, yuvFp)) {
if (!OSAL_FEOF(yuvFp))
JLOG(ERR, "Yuv Data fread failed file handle is 0x%p\n", yuvFp);
return 0;
}
}
LoadYuvImageBurstFormat(pYuv, picWidth, picHeightPartial, addrY, addrCb,
addrCr, stride, interleave, format, endian,
packed);
return 1;
}
int SaveYuvImageHelperFormat(osal_file_t *yuvFp, Uint8 *pYuv,
PhysicalAddress addrY, PhysicalAddress addrCb,
PhysicalAddress addrCr, int picWidth,
int picHeight, int stride, int interLeave,
int format, int endian, int packed)
{
int frameSize;
frameSize = StoreYuvImageBurstFormat(pYuv, picWidth, picHeight, addrY,
addrCb, addrCr, stride, interLeave,
format, endian, packed);
if (yuvFp) {
if (!OSAL_FWRITE(pYuv, sizeof(Uint8), frameSize, yuvFp)) {
JLOG(ERR, "Frame Data fwrite failed file handle is 0x%p\n", yuvFp);
return 0;
}
OSAL_FFLUSH(yuvFp);
}
return 1;
}
int SaveYuvPartialImageHelperFormat(osal_file_t *yuvFp, Uint8 *pYuv, PhysicalAddress addrY,
PhysicalAddress addrCb, PhysicalAddress addrCr, int picWidth, int picHeight,
int picHeightPartial, int stride, int interLeave, int format, int endian,
int partPosIdx, int frameIdx, int packed)
{
int LumaPicSize = 0;
int ChromaPicSize = 0;
int frameSize = 0;
int LumaPartialSize = 0;
int ChromaPartialSize = 0;
int pos = 0;
// int divX, divY;
// divX = format == FORMAT_420 || format == FORMAT_422 ? 2 : 1;
// divY = format == FORMAT_420 || format == FORMAT_224 ? 2 : 1;
switch (format) {
case FORMAT_420:
LumaPicSize = picWidth * ((picHeight + 1) / 2 * 2);
ChromaPicSize = ((picWidth + 1) / 2) * ((picHeight + 1) / 2);
frameSize = LumaPicSize + ChromaPicSize * 2;
LumaPartialSize = picWidth * ((picHeightPartial + 1) / 2 * 2);
ChromaPartialSize = ((picWidth + 1) / 2) * ((picHeightPartial + 1) / 2);
if (interLeave)
ChromaPartialSize = (((picWidth + 1) / 2) * 2) * ((picHeightPartial + 1) / 2);
break;
case FORMAT_224:
LumaPicSize = picWidth * ((picHeight + 1) / 2 * 2);
ChromaPicSize = picWidth * ((picHeight + 1) / 2);
frameSize = LumaPicSize + ChromaPicSize * 2;
LumaPartialSize = picWidth * ((picHeightPartial + 1) / 2 * 2);
ChromaPartialSize = picWidth * ((picHeightPartial + 1) / 2);
if (interLeave)
ChromaPartialSize = picWidth * 2 * ((picHeightPartial + 1) / 2);
break;
case FORMAT_422:
LumaPicSize = picWidth * picHeight;
ChromaPicSize = ((picWidth + 1) / 2) * picHeight;
frameSize = LumaPicSize + ChromaPicSize * 2;
LumaPartialSize = picWidth * picHeightPartial;
ChromaPartialSize = ((picWidth + 1) / 2) * picHeightPartial;
if (interLeave)
ChromaPartialSize = (((picWidth + 1) / 2) * 2) * picHeightPartial;
break;
case FORMAT_444:
LumaPicSize = picWidth * picHeight;
ChromaPicSize = picWidth * picHeight;
frameSize = LumaPicSize + ChromaPicSize * 2;
LumaPartialSize = picWidth * picHeightPartial;
ChromaPartialSize = picWidth * picHeightPartial;
if (interLeave)
ChromaPartialSize = picWidth * 2 * picHeightPartial;
break;
case FORMAT_400:
LumaPicSize = picWidth * picHeight;
ChromaPicSize = 0;
frameSize = LumaPicSize + ChromaPicSize * 2;
LumaPartialSize = picWidth * picHeightPartial;
ChromaPartialSize = 0;
break;
}
if (packed) {
if (packed == PACKED_FORMAT_444)
picWidth *= 3;
else
picWidth *= 2;
LumaPicSize = picWidth * picHeight;
ChromaPicSize = 0;
frameSize = LumaPicSize;
LumaPartialSize = picWidth * picHeightPartial;
ChromaPartialSize = 0;
}
StoreYuvImageBurstFormat(pYuv, picWidth, picHeightPartial, addrY,
addrCb, addrCr, stride, interLeave, format,
endian, packed);
if (yuvFp) {
// Y
OSAL_FSEEK(yuvFp, (frameIdx * frameSize), SEEK_SET);
pos = LumaPartialSize * partPosIdx;
OSAL_FSEEK(yuvFp, pos, SEEK_CUR);
if (!OSAL_FWRITE(pYuv, sizeof(Uint8), LumaPartialSize, yuvFp)) {
JLOG(ERR, "Frame Data fwrite failed file handle is 0x%p\n", yuvFp);
return 0;
}
if (packed) {
OSAL_FFLUSH(yuvFp);
return 1;
}
if (format != FORMAT_400) {
// Cb
OSAL_FSEEK(yuvFp, (frameIdx * frameSize), SEEK_SET);
pos = LumaPicSize + ChromaPartialSize * partPosIdx;
OSAL_FSEEK(yuvFp, pos, SEEK_CUR);
if (!OSAL_FWRITE(pYuv + LumaPartialSize, sizeof(Uint8), ChromaPartialSize, yuvFp)) {
JLOG(ERR, "Frame Data fwrite failed file handle is 0x%p\n", yuvFp);
return 0;
}
if (interLeave) {
OSAL_FFLUSH(yuvFp);
return 1;
}
// Cr
OSAL_FSEEK(yuvFp, (frameIdx * frameSize), SEEK_SET);
pos = LumaPicSize + ChromaPicSize + ChromaPartialSize * partPosIdx;
OSAL_FSEEK(yuvFp, pos, SEEK_CUR);
if (!OSAL_FWRITE(pYuv + LumaPartialSize + ChromaPartialSize, sizeof(Uint8),
ChromaPartialSize, yuvFp)) {
JLOG(ERR, "Frame Data fwrite failed file handle is 0x%p\n", yuvFp);
return 0;
}
}
OSAL_FFLUSH(yuvFp);
}
return 1;
}
/******************************************************************************
* JPEG specific Helper
******************************************************************************/
static int getTblElement(osal_file_t *fp, char *str)
{
static int LineNum = 1;
while (1) {
if (!OSAL_FGETS(str, 256, fp))
return 0;
if ((str[0] != ';') && (str[0] != '/'))
break;
LineNum++;
}
return 1;
}
static int parseHuffmanTable(osal_file_t *fp, EncMjpgParam *param)
{
int ret = 0;
char sLine[256] = {
0,
};
unsigned int h[8] = {
0,
};
BYTE *huffBit;
BYTE *huffVal;
int i, j;
huffBit = param->huffBits[DC_TABLE_INDEX0];
huffVal = param->huffVal[DC_TABLE_INDEX0];
for (i = 0; i < 2; i++) { // Luma DC BitLength
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffBit++ = (BYTE)h[j];
}
for (i = 0; i < (16 / 8); i++) { // Luma DC HuffValue
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffVal++ = (BYTE)h[j];
}
huffBit = param->huffBits[AC_TABLE_INDEX0];
huffVal = param->huffVal[AC_TABLE_INDEX0];
for (i = 0; i < (16 / 8); i++) { // Luma AC BitLength
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffBit++ = (BYTE)h[j];
}
for (i = 0; i < (162 / 8); i++) { // Luma DC HuffValue
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffVal++ = (BYTE)h[j];
}
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2], &h[3],
&h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 2; j++)
*huffVal++ = (BYTE)h[j];
huffBit = param->huffBits[DC_TABLE_INDEX1];
huffVal = param->huffVal[DC_TABLE_INDEX1];
for (i = 0; i < (16 / 8); i++) { // Chroma DC BitLength
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffBit++ = (BYTE)h[j];
}
for (i = 0; i < (16 / 8); i++) { // Chroma DC HuffValue
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffVal++ = (BYTE)h[j];
}
huffBit = param->huffBits[AC_TABLE_INDEX1];
huffVal = param->huffVal[AC_TABLE_INDEX1];
for (i = 0; i < (16 / 8); i++) { // Chroma DC BitLength
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffBit++ = (BYTE)h[j];
}
for (i = 0; i < (162 / 8); i++) {// Luma DC HuffValue
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*huffVal++ = (BYTE)h[j];
}
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2], &h[3],
&h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 2; j++)
*huffVal++ = (BYTE)h[j];
(void)ret;
return 1;
}
static int parseQMatrix(osal_file_t *fp, EncMjpgParam *param)
{
int ret = 0;
char sLine[256] = {
0,
};
int i, j;
unsigned int h[8] = {
0,
};
BYTE temp_dc[64], temp_ac[64];
BYTE *qTable_dc, *qTable_ac, *qTable;
qTable = temp_dc;
for (i = 0; i < (64 / 8); i++) {
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*qTable++ = (BYTE)h[j];
}
qTable = temp_ac;
for (i = 0; i < (64 / 8); i++) {
if (getTblElement(fp, sLine) == 0)
return 0;
memset(h, 0x00, 8 * sizeof(unsigned int));
ret = sscanf(sLine, "%x %x %x %x %x %x %x %x", &h[0], &h[1], &h[2],
&h[3], &h[4], &h[5], &h[6], &h[7]);
for (j = 0; j < 8; j++)
*qTable++ = (BYTE)h[j];
}
qTable_dc = param->qMatTab[DC_TABLE_INDEX0];
qTable_ac = param->qMatTab[AC_TABLE_INDEX0];
for (i = 0; i < 64; i++) {
qTable_dc[InvScanTable[i]] = temp_dc[i];
qTable_ac[InvScanTable[i]] = temp_ac[i];
}
memcpy(param->qMatTab[DC_TABLE_INDEX1], param->qMatTab[DC_TABLE_INDEX0], 64);
memcpy(param->qMatTab[AC_TABLE_INDEX1], param->qMatTab[AC_TABLE_INDEX0], 64);
(void)ret;
return 1;
}
int jpgGetHuffTable(char *huffFileName, EncMjpgParam *param)
{
char huffFilePath[256];
osal_file_t *huffFp = NULL;
if (huffFileName && huffFileName[0] != 0) {
// strcpy(huffFilePath, huffFileName);
huffFp = OSAL_FOPEN(huffFilePath, "rt");
if (!huffFp) {
JLOG(ERR, "Can't open Huffman Table file %s\n", huffFilePath);
return 0;
}
parseHuffmanTable(huffFp, param);
OSAL_FCLOSE(huffFp);
} else {
// Rearrange and insert pre-defined Huffman table to deticated
// variable.
memcpy(param->huffBits[DC_TABLE_INDEX0], lumaDcBits, 16); // Luma DC BitLength
memcpy(param->huffVal[DC_TABLE_INDEX0], lumaDcValue, 16); // Luma DC HuffValue
memcpy(param->huffBits[AC_TABLE_INDEX0], lumaAcBits, 16); // Luma DC BitLength
memcpy(param->huffVal[AC_TABLE_INDEX0], lumaAcValue, 162); // Luma DC HuffValue
memcpy(param->huffBits[DC_TABLE_INDEX1], chromaDcBits, 16); // Chroma DC BitLength
memcpy(param->huffVal[DC_TABLE_INDEX1], chromaDcValue, 16); // Chroma DC HuffValue
memcpy(param->huffBits[AC_TABLE_INDEX1], chromaAcBits, 16); // Chroma AC BitLength
memcpy(param->huffVal[AC_TABLE_INDEX1], chromaAcValue, 162); // Chorma AC HuffValue
}
return 1;
}
int jpgGetQMatrix(char *qMatFileName, EncMjpgParam *param)
{
char qMatFilePath[256];
osal_file_t *qMatFp = NULL;
if (qMatFileName && qMatFileName[0] != 0) {
// strcpy(qMatFilePath, qMatFileName);
qMatFp = OSAL_FOPEN(qMatFilePath, "rt");
if (!qMatFp) {
JLOG(ERR, "Can't open Q Matrix file %s\n", qMatFilePath);
return 0;
}
parseQMatrix(qMatFp, param);
OSAL_FCLOSE(qMatFp);
} else {
// Rearrange and insert pre-defined Q-matrix to deticated
// variable.
memcpy(param->qMatTab[DC_TABLE_INDEX0], lumaQ2, 64);
memcpy(param->qMatTab[AC_TABLE_INDEX0], chromaBQ2, 64);
memcpy(param->qMatTab[DC_TABLE_INDEX1], param->qMatTab[DC_TABLE_INDEX0], 64);
memcpy(param->qMatTab[AC_TABLE_INDEX1], param->qMatTab[AC_TABLE_INDEX0], 64);
}
return 1;
}
/******************************************************************************
* EncOpenParam Initialization
******************************************************************************/
int getJpgEncOpenParamDefault(JpgEncOpenParam *pEncOP,
EncConfigParam *pEncConfig)
{
int ret;
EncMjpgParam mjpgParam;
memset(&mjpgParam, 0x00, sizeof(EncMjpgParam));
pEncOP->picWidth = pEncConfig->picWidth;
pEncOP->picHeight = pEncConfig->picHeight;
pEncOP->sourceFormat = pEncConfig->mjpgChromaFormat;
pEncOP->restartInterval = 0;
pEncOP->chroma_interleave = pEncConfig->chroma_interleave;
pEncOP->packedFormat = pEncConfig->packedFormat;
mjpgParam.sourceFormat = pEncConfig->mjpgChromaFormat;
ret = jpgGetHuffTable(pEncConfig->huffFileName, &mjpgParam);
if (ret == 0)
return ret;
ret = jpgGetQMatrix(pEncConfig->qMatFileName, &mjpgParam);
if (ret == 0)
return ret;
memcpy(pEncOP->huffVal, mjpgParam.huffVal, 4 * 162);
memcpy(pEncOP->huffBits, mjpgParam.huffBits, 4 * 256);
memcpy(pEncOP->qMatTab, mjpgParam.qMatTab, 4 * 64);
return 1;
}
/**
* To init EncOpenParam by CFG file
* IN
* EncConfigParam *pEncConfig
* OUT
* EncOpenParam *pEncOP
* char *srcYuvFileName
*/
int getJpgEncOpenParam(JpgEncOpenParam *pEncOP, EncConfigParam *pEncConfig, char *srcYuvFileName)
{
ENC_CFG encCfg;
int ret;
EncMjpgParam mjpgParam;
char cfgFileName[MAX_FILE_PATH];
// Source YUV Image File to load
// strcpy(srcYuvFileName, encCfg.SrcFileName);
memset(&encCfg, 0x00, sizeof(ENC_CFG));
memset(&mjpgParam, 0x00, sizeof(EncMjpgParam));
if (strlen(pEncConfig->strCfgDir))
sprintf(cfgFileName, "%s%s", pEncConfig->strCfgDir, pEncConfig->cfgFileName);
// else
// strcpy(cfgFileName, pEncConfig->cfgFileName);
parseJpgCfgFile(&encCfg, cfgFileName);
if (srcYuvFileName) {
if (strlen(pEncConfig->strStmDir))
sprintf(srcYuvFileName, "%s%s", pEncConfig->strStmDir, encCfg.SrcFileName);
// else
// strcpy(srcYuvFileName, encCfg.SrcFileName);
}
if (encCfg.FrmFormat == 0)
pEncConfig->chroma_interleave = CBCR_SEPARATED;
else if (encCfg.FrmFormat == 1)
pEncConfig->chroma_interleave = CBCR_INTERLEAVE;
else if (encCfg.FrmFormat == 2)
pEncConfig->chroma_interleave = CRCB_INTERLEAVE;
else
pEncConfig->chroma_interleave = CBCR_SEPARATED;
pEncConfig->packedFormat = (encCfg.FrmFormat - 2);
if (pEncConfig->packedFormat < 0)
pEncConfig->packedFormat = 0;
pEncConfig->outNum = encCfg.NumFrame;
if (pEncOP) {
pEncOP->picWidth = encCfg.PicX;
pEncOP->picHeight = encCfg.PicY;
pEncOP->chroma_interleave = pEncConfig->chroma_interleave;
pEncOP->packedFormat = pEncConfig->packedFormat;
pEncOP->sourceFormat = encCfg.SrcFormat;
pEncOP->restartInterval = encCfg.RstIntval;
mjpgParam.sourceFormat = encCfg.SrcFormat;
ret = jpgGetHuffTable(encCfg.HuffTabName, &mjpgParam);
if (ret == 0)
return ret;
ret = jpgGetQMatrix(encCfg.QMatTabName, &mjpgParam);
if (ret == 0)
return ret;
memcpy(pEncOP->huffVal, mjpgParam.huffVal, 4 * 162);
memcpy(pEncOP->huffBits, mjpgParam.huffBits, 4 * 256);
memcpy(pEncOP->qMatTab, mjpgParam.qMatTab, 4 * 64);
}
return 1;
}
//------------------------------------------------------------------------------
// ENCODE PARAMETER PARSE FUNCSIONS
//------------------------------------------------------------------------------
// Parameter parsing helper
static int GetValue(osal_file_t *fp, char *para, char *value)
{
static int LineNum = 1;
char lineStr[256];
char paraStr[256];
int ret = 0;
OSAL_FSEEK(fp, 0, SEEK_SET);
while (1) {
if (!OSAL_FGETS(lineStr, 256, fp))
return 0;
ret = sscanf(lineStr, "%s %s", paraStr, value);
if (paraStr[0] != ';') {
if (strcmp(para, paraStr) == 0)
return 1;
}
LineNum++;
}
(void)ret;
return 1;
}
int parseJpgCfgFile(ENC_CFG *pEncCfg, char *FileName)
{
osal_file_t *Fp;
int ret = 0;
char sLine[256] = {
0,
};
Fp = OSAL_FOPEN(FileName, "rt");
if (!Fp) {
BM_DBG_ERR(" > ERROR: File not exist <%s>\n", FileName);
return 0;
}
// source file name
if (GetValue(Fp, "YUV_SRC_IMG", sLine) == 0)
return 0;
ret = sscanf(sLine, "%s", (char *)&pEncCfg->SrcFileName);
// frame format
// ; 0-planar, 1-NV12,NV16(CbCr interleave) 2-NV21,NV61(CbCr
// alternative) ; 3-YUYV, 4-UYVY, 5-YVYU, 6-VYUY, 7-YUV packed
// (444 only)
if (GetValue(Fp, "FRAME_FORMAT", sLine) == 0)
return 0;
pEncCfg->FrmFormat = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->FrmFormat);
// width
if (GetValue(Fp, "PICTURE_WIDTH", sLine) == 0)
return 0;
pEncCfg->PicX = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->PicX);
// height
if (GetValue(Fp, "PICTURE_HEIGHT", sLine) == 0)
return 0;
pEncCfg->PicY = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->PicY);
// frame_rate
if (GetValue(Fp, "FRAME_RATE", sLine) == 0)
return 0;
{
double frameRate = 0.0;
int timeRes, timeInc;
// frameRate = (double)(int)atoi(sLine);
timeInc = 1;
while ((int)frameRate != frameRate) {
timeInc *= 10;
frameRate *= 10;
}
timeRes = (int)frameRate;
// divide 2 or 5
if (timeInc % 2 == 0 && timeRes % 2 == 0)
timeInc /= 2, timeRes /= 2;
if (timeInc % 5 == 0 && timeRes % 5 == 0)
timeInc /= 5, timeRes /= 5;
if (timeRes == 2997 && timeInc == 100)
timeRes = 30000, timeInc = 1001;
pEncCfg->FrameRate = (timeInc - 1) << 16;
pEncCfg->FrameRate |= timeRes;
}
// frame count
if (GetValue(Fp, "FRAME_NUMBER_ENCODED", sLine) == 0)
return 0;
pEncCfg->NumFrame = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->NumFrame);
if (GetValue(Fp, "VERSION_ID", sLine) == 0)
return 0;
pEncCfg->VersionID = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->VersionID);
if (GetValue(Fp, "RESTART_INTERVAL", sLine) == 0)
return 0;
pEncCfg->RstIntval = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->RstIntval);
if (GetValue(Fp, "IMG_FORMAT", sLine) == 0)
return 0;
pEncCfg->SrcFormat = (int)simple_strtol(sLine, NULL, 10);//sscanf(sLine, "%d", &pEncCfg->SrcFormat);
if (GetValue(Fp, "QMATRIX_TABLE", sLine) == 0)
return 0;
ret = sscanf(sLine, "%s", (char *)&pEncCfg->QMatTabName);
if (GetValue(Fp, "HUFFMAN_TABLE", sLine) == 0)
return 0;
ret = sscanf(sLine, "%s", (char *)&pEncCfg->HuffTabName);
(void)ret;
OSAL_FCLOSE(Fp);
return 1;
}
int FillSdramBurst(BufInfo *pBufInfo, Uint64 targetAddr,
PhysicalAddress bsBufStartAddr, PhysicalAddress bsBufEndAddr,
Uint32 size, int checkeos, int *streameos, int endian)
{
Uint8 *pBuf;
int room;
pBufInfo->count = 0;
if (checkeos == 1 && pBufInfo->point >= pBufInfo->size) {
*streameos = 1;
return 0;
}
if ((pBufInfo->size - pBufInfo->point) < (int)size)
pBufInfo->count = (pBufInfo->size - pBufInfo->point);
else
pBufInfo->count = size;
pBuf = pBufInfo->buf + pBufInfo->point;
if ((targetAddr + pBufInfo->count) > bsBufEndAddr) {
room = bsBufEndAddr - targetAddr;
JpuWriteMem(targetAddr, pBuf, room, endian);
JpuWriteMem(bsBufStartAddr, pBuf + room, (pBufInfo->count - room), endian);
} else {
JpuWriteMem(targetAddr, pBuf, pBufInfo->count, endian);
}
pBufInfo->point += pBufInfo->count;
return pBufInfo->count;
}
int StoreYuvImageBurstFormat(Uint8 *dst, int picWidth, int picHeight,
unsigned long addrY, unsigned long addrCb,
unsigned long addrCr, int stride, int interLeave,
int format, int endian, int packed)
{
int size = 0;
int y = 0, nY = 0, nCb = 0, nCr = 0;
unsigned long addr = 0;
int lumaSize = 0, chromaSize = 0, chromaStride = 0, chromaWidth = 0, chromaHeight = 0;
Uint8 *puc;
switch (format) {
case FORMAT_420:
nY = (picHeight + 1) / 2 * 2;
nCb = (picHeight + 1) / 2;
nCr = (picHeight + 1) / 2;
chromaSize = ((picWidth + 1) / 2) * ((picHeight + 1) / 2);
chromaStride = stride / 2;
chromaWidth = (picWidth + 1) / 2;
chromaHeight = nY;
break;
case FORMAT_224:
nY = (picHeight + 1) / 2 * 2;
nCb = (picHeight + 1) / 2;
nCr = (picHeight + 1) / 2;
chromaSize = (picWidth) * ((picHeight + 1) / 2);
chromaStride = stride;
chromaWidth = picWidth;
chromaHeight = nY;
break;
case FORMAT_422:
nY = picHeight;
nCb = picHeight;
nCr = picHeight;
chromaSize = ((picWidth + 1) / 2) * picHeight;
chromaStride = stride / 2;
chromaWidth = (picWidth + 1) / 2;
chromaHeight = nY * 2;
break;
case FORMAT_444:
nY = picHeight;
nCb = picHeight;
nCr = picHeight;
chromaSize = picWidth * picHeight;
chromaStride = stride;
chromaWidth = picWidth;
chromaHeight = nY * 2;
break;
case FORMAT_400:
nY = picHeight;
nCb = 0;
nCr = 0;
chromaSize = 0;
chromaStride = 0;
chromaWidth = 0;
chromaHeight = 0;
break;
}
puc = dst;
addr = addrY;
if (packed) {
if (packed == PACKED_FORMAT_444)
picWidth *= 3;
else
picWidth *= 2;
chromaSize = 0;
}
lumaSize = picWidth * nY;
size = lumaSize + chromaSize * 2;
if (picWidth == stride) {
JpuReadMem(addr, (Uint8 *)(puc), lumaSize, endian);
if (packed)
return size;
if (interLeave) {
puc = dst + lumaSize;
addr = addrCb;
JpuReadMem(addr, (Uint8 *)(puc), chromaSize * 2,
endian);
} else {
puc = dst + lumaSize;
addr = addrCb;
JpuReadMem(addr, (Uint8 *)(puc), chromaSize, endian);
puc = dst + lumaSize + chromaSize;
addr = addrCr;
JpuReadMem(addr, (Uint8 *)(puc), chromaSize, endian);
}
} else {
for (y = 0; y < nY; ++y) {
JpuReadMem(addr + stride * y, (Uint8 *)(puc + y * picWidth), picWidth, endian);
}
if (packed)
return size;
if (interLeave) {
puc = dst + lumaSize;
addr = addrCb;
for (y = 0; y < (chromaHeight / 2); ++y) {
JpuReadMem(addr + (chromaStride * 2) * y,
(Uint8 *)(puc + y * (chromaWidth * 2)),
(chromaWidth * 2), endian);
}
} else {
puc = dst + lumaSize;
addr = addrCb;
for (y = 0; y < nCb; ++y) {
JpuReadMem(addr + chromaStride * y,
(Uint8 *)(puc + y * chromaWidth),
chromaWidth, endian);
}
puc = dst + lumaSize + chromaSize;
addr = addrCr;
for (y = 0; y < nCr; ++y) {
JpuReadMem(addr + chromaStride * y,
(Uint8 *)(puc + y * chromaWidth),
chromaWidth, endian);
}
}
}
return size;
}
void ProcessEncodedBitstreamBurst(osal_file_t *fp, unsigned long targetAddr,
PhysicalAddress bsBufStartAddr,
PhysicalAddress bsBufEndAddr, int size,
int endian)
{
Uint8 *val = 0;
int room = 0;
BM_DBG_TRACE("target addr :%lx\n", targetAddr);
BM_DBG_TRACE("start :%lx, end:%lx, size:%d\n", bsBufStartAddr, bsBufEndAddr, size);
val = (Uint8 *)OSAL_MALLOC(size);
if ((targetAddr + size) > (unsigned long)bsBufEndAddr) {
room = bsBufEndAddr - targetAddr;
JpuReadMem(targetAddr, val, room, endian);
JpuReadMem(bsBufStartAddr, val + room, (size - room), endian);
} else {
BM_DBG_TRACE("read target addr :%lx\n", targetAddr);
JpuReadMem(targetAddr, val, size, endian);
}
if (fp) {
OSAL_FWRITE(val, sizeof(Uint8), size, fp);
OSAL_FFLUSH(fp);
}
OSAL_FREE(val);
}
int LoadYuvImageBurstFormat(Uint8 *src, int picWidth, int picHeight,
unsigned long addrY, unsigned long addrCb,
unsigned long addrCr, int stride, int interLeave,
int format, int endian, int packed)
{
int y = 0, nY = 0, nCb = 0, nCr = 0;
unsigned long addr = 0;
int size = 0;
int lumaSize = 0, chromaSize = 0, chromaStride = 0, chromaWidth = 0;
Uint8 *puc = NULL;
switch (format) {
case FORMAT_420:
nY = picHeight;
nCb = picHeight / 2;
nCr = picHeight / 2;
chromaSize = picWidth * picHeight / 4;
chromaStride = stride / 2;
chromaWidth = picWidth / 2;
break;
case FORMAT_224:
nY = picHeight;
nCb = picHeight / 2;
nCr = picHeight / 2;
chromaSize = picWidth * picHeight / 2;
chromaStride = stride;
chromaWidth = picWidth;
break;
case FORMAT_422:
nY = picHeight;
nCb = picHeight;
nCr = picHeight;
chromaSize = picWidth * picHeight / 2;
chromaStride = stride / 2;
chromaWidth = picWidth / 2;
break;
case FORMAT_444:
nY = picHeight;
nCb = picHeight;
nCr = picHeight;
chromaSize = picWidth * picHeight;
chromaStride = stride;
chromaWidth = picWidth;
break;
case FORMAT_400:
nY = picHeight;
nCb = 0;
nCr = 0;
chromaSize = picWidth * picHeight / 4;
chromaStride = stride / 2;
chromaWidth = picWidth / 2;
break;
}
puc = src;
addr = addrY;
if (packed) {
if (packed == PACKED_FORMAT_444)
picWidth *= 3;
else
picWidth *= 2;
chromaSize = 0;
}
lumaSize = picWidth * nY;
size = lumaSize + chromaSize * 2;
if (picWidth == stride) { // for fast write
JpuWriteMem(addr, (Uint8 *)(puc), lumaSize, endian);
if (format == FORMAT_400)
return size;
if (packed)
return size;
if (interLeave) {
Uint8 t0, t1, t2, t3, t4, t5, t6, t7;
int i, height, width;
int stride;
Uint8 *pTemp;
Uint8 *dstAddrCb;
Uint8 *dstAddrCr;
addr = addrCb;
stride = chromaStride * 2;
height = nCb;
width = chromaWidth * 2;
dstAddrCb = (Uint8 *)(puc + picWidth * nY);
dstAddrCr = (Uint8 *)(dstAddrCb + chromaSize);
pTemp = OSAL_MALLOC(width);
if (!pTemp) {
return 0;
}
for (y = 0; y < height; ++y) {
for (i = 0; i < width; i += 8) {
t0 = *dstAddrCb++;
t2 = *dstAddrCb++;
t4 = *dstAddrCb++;
t6 = *dstAddrCb++;
t1 = *dstAddrCr++;
t3 = *dstAddrCr++;
t5 = *dstAddrCr++;
t7 = *dstAddrCr++;
if (interLeave == CBCR_INTERLEAVE) {
pTemp[i] = t0;
pTemp[i + 1] = t1;
pTemp[i + 2] = t2;
pTemp[i + 3] = t3;
pTemp[i + 4] = t4;
pTemp[i + 5] = t5;
pTemp[i + 6] = t6;
pTemp[i + 7] = t7;
} else { // CRCB_INTERLEAVE
pTemp[i] = t1;
pTemp[i + 1] = t0;
pTemp[i + 2] = t3;
pTemp[i + 3] = t2;
pTemp[i + 4] = t5;
pTemp[i + 5] = t4;
pTemp[i + 6] = t7;
pTemp[i + 7] = t6;
}
}
JpuWriteMem(addr + stride * y, (unsigned char *)pTemp, width, endian);
}
OSAL_FREE(pTemp);
} else {
puc = src + lumaSize;
addr = addrCb;
JpuWriteMem(addr, (Uint8 *)puc, chromaSize, endian);
puc = src + lumaSize + chromaSize;
addr = addrCr;
JpuWriteMem(addr, (Uint8 *)puc, chromaSize, endian);
}
} else {
for (y = 0; y < nY; ++y) {
JpuWriteMem(addr + stride * y, (Uint8 *)(puc + y * picWidth), picWidth, endian);
}
if (format == FORMAT_400)
return size;
if (packed)
return size;
if (interLeave == 1) {
Uint8 t0, t1, t2, t3, t4, t5, t6, t7;
int i, width, height, stride;
Uint8 *pTemp;
Uint8 *dstAddrCb;
Uint8 *dstAddrCr;
addr = addrCb;
stride = chromaStride * 2;
height = nCb / 2;
width = chromaWidth * 2;
dstAddrCb = (Uint8 *)(puc + picWidth * nY);
dstAddrCr = (Uint8 *)(dstAddrCb + chromaSize);
pTemp = OSAL_MALLOC((width + 7) & ~7);
if (!pTemp) {
return 0;
}
// it may be not occur that pic_width in not 8byte
// alined.
for (y = 0; y < height; ++y) {
for (i = 0; i < width; i += 8) {
t0 = *dstAddrCb++;
t2 = *dstAddrCb++;
t4 = *dstAddrCb++;
t6 = *dstAddrCb++;
t1 = *dstAddrCr++;
t3 = *dstAddrCr++;
t5 = *dstAddrCr++;
t7 = *dstAddrCr++;
if (interLeave == CBCR_INTERLEAVE) {
pTemp[i] = t0;
pTemp[i + 1] = t1;
pTemp[i + 2] = t2;
pTemp[i + 3] = t3;
pTemp[i + 4] = t4;
pTemp[i + 5] = t5;
pTemp[i + 6] = t6;
pTemp[i + 7] = t7;
} else { // CRCB_INTERLEAVE
pTemp[i] = t1;
pTemp[i + 1] = t0;
pTemp[i + 2] = t3;
pTemp[i + 3] = t2;
pTemp[i + 4] = t5;
pTemp[i + 5] = t3;
pTemp[i + 6] = t7;
pTemp[i + 7] = t6;
}
JpuWriteMem(addr + stride * y, (unsigned char *)pTemp, stride, endian);
}
}
} else {
puc = src + lumaSize;
addr = addrCb;
for (y = 0; y < nCb; ++y) {
JpuWriteMem(addr + chromaStride * y,
(Uint8 *)(puc + y * chromaWidth),
chromaWidth, endian);
}
puc = src + lumaSize + chromaSize;
addr = addrCr;
for (y = 0; y < nCr; ++y) {
JpuWriteMem(addr + chromaStride * y,
(Uint8 *)(puc + y * chromaWidth),
chromaWidth, endian);
}
}
}
return size;
}
void GetMcuUnitSize(int format, int *mcuWidth, int *mcuHeight)
{
switch (format) {
case FORMAT_420:
*mcuWidth = 16;
*mcuHeight = 16;
break;
case FORMAT_422:
*mcuWidth = 16;
*mcuHeight = 8;
break;
case FORMAT_224:
*mcuWidth = 8;
*mcuHeight = 16;
break;
default: // FORMAT_444,400
*mcuWidth = 8;
*mcuHeight = 8;
break;
}
}
unsigned int GetFrameBufSize(int framebufFormat, int picWidth, int picHeight)
{
unsigned int framebufSize = 0;
unsigned int framebufWidth, framebufHeight;
if (framebufFormat == FORMAT_420 || framebufFormat == FORMAT_422)
framebufWidth = ((picWidth + 15) / 16) * 16;
else
framebufWidth = ((picWidth + 7) / 8) * 8;
if (framebufFormat == FORMAT_420 || framebufFormat == FORMAT_224)
framebufHeight = ((picHeight + 15) / 16) * 16;
else
framebufHeight = ((picHeight + 7) / 8) * 8;
switch (framebufFormat) {
case FORMAT_420:
framebufSize =
framebufWidth * ((framebufHeight + 1) / 2 * 2) +
((framebufWidth + 1) / 2) * ((framebufHeight + 1) / 2) * 2;
break;
case FORMAT_224:
framebufSize = framebufWidth * ((framebufHeight + 1) / 2 * 2) +
framebufWidth * ((framebufHeight + 1) / 2) * 2;
break;
case FORMAT_422:
framebufSize = framebufWidth * framebufHeight +
((framebufWidth + 1) / 2) * framebufHeight * 2;
break;
case FORMAT_444:
framebufSize = framebufWidth * framebufHeight * 3;
break;
case FORMAT_400:
framebufSize = framebufWidth * framebufHeight;
break;
}
framebufSize = ((framebufSize + 7) & ~7);
return framebufSize;
}
// inteleave : 0 (chroma separate mode), 1 (cbcr interleave mode), 2 (crcb
// interleave mode)
yuv2rgb_color_format
convert_jpuapi_format_to_yuv2rgb_color_format(int planar_format,
int pack_format, int interleave)
{
yuv2rgb_color_format format = 0;
if (!pack_format) {
switch (planar_format) {
case FORMAT_400:
format = YUV400;
break;
case FORMAT_444:
format = YUV444;
break;
case FORMAT_224:
case FORMAT_422:
format = YUV422;
break;
case FORMAT_420:
if (interleave == 0)
format = YUV420;
else if (interleave == 1)
format = NV12;
else
format = NV21;
break;
}
} else {
switch (pack_format) {
case PACKED_FORMAT_422_YUYV:
format = YUYV;
break;
case PACKED_FORMAT_422_UYVY:
format = UYVY;
break;
case PACKED_FORMAT_422_YVYU:
format = YVYU;
break;
case PACKED_FORMAT_422_VYUY:
format = VYUY;
break;
case PACKED_FORMAT_444:
format = YYY;
break;
}
}
return format;
}
void jpu_yuv2rgb(int width, int height, yuv2rgb_color_format format,
unsigned char *src, unsigned char *rgba, int cbcr_reverse)
{
#define jpu_clip(var) (((var) >= 255) ? 255 : ((var) <= 0) ? 0 : (var))
int j, i;
int c, d, e;
unsigned char *line = rgba;
unsigned char *cur = NULL;
unsigned char *y = NULL;
unsigned char *u = NULL;
unsigned char *v = NULL;
unsigned char *misc = NULL;
int frame_size_y;
int frame_size_uv;
int t_width;
frame_size_y = width * height;
if (format == YUV444 || format == RGB_PLANAR)
frame_size_uv = width * height;
else if (format == YUV422)
frame_size_uv = (width * height) >> 1;
else if (format == YUV420 || format == NV12 || format == NV21)
frame_size_uv = (width * height) >> 2;
else
frame_size_uv = 0;
t_width = width;
if (format == YUYV || format == YVYU || format == UYVY || format == VYUY) {
misc = src;
} else if (format == NV12 || format == NV21) {
y = src;
misc = src + frame_size_y;
} else if (format == RGB32 || format == RGB24 || format == RGB16) {
misc = src;
} else {
y = src;
u = src + frame_size_y;
v = src + frame_size_y + frame_size_uv;
}
if (format == YUV444) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
c = y[j * width + i] - 16;
d = u[j * width + i] - 128;
e = v[j * width + i] - 128;
if (!cbcr_reverse) {
d = u[j * width + i] - 128;
e = v[j * width + i] - 128;
} else {
e = u[j * width + i] - 128;
e = v[j * width + i] - 128;
}
(*cur) = jpu_clip((298 * c + 409 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c - 100 * d - 208 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c + 516 * d + 128) >> 8);
cur++;
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
} else if (format == YUV422) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
c = y[j * width + i] - 16;
d = u[j * (width >> 1) + (i >> 1)] - 128;
e = v[j * (width >> 1) + (i >> 1)] - 128;
if (!cbcr_reverse) {
d = u[j * (width >> 1) + (i >> 1)] - 128;
e = v[j * (width >> 1) + (i >> 1)] - 128;
} else {
e = u[j * (width >> 1) + (i >> 1)] - 128;
d = v[j * (width >> 1) + (i >> 1)] - 128;
}
(*cur) = jpu_clip((298 * c + 409 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c - 100 * d - 208 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c + 516 * d + 128) >> 8);
cur++;
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
} else if (format == YUYV || format == YVYU || format == UYVY || format == VYUY) {
unsigned char *t = misc;
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i += 2) {
switch (format) {
case YUYV:
c = *(t) - 16;
if (!cbcr_reverse) {
d = *(t + 1) - 128;
e = *(t + 3) - 128;
} else {
e = *(t + 1) - 128;
d = *(t + 3) - 128;
}
break;
case YVYU:
c = *(t) - 16;
if (!cbcr_reverse) {
d = *(t + 3) - 128;
e = *(t + 1) - 128;
} else {
e = *(t + 3) - 128;
d = *(t + 1) - 128;
}
break;
case UYVY:
c = *(t + 1) - 16;
if (!cbcr_reverse) {
d = *(t) - 128;
e = *(t + 2) - 128;
} else {
e = *(t) - 128;
d = *(t + 2) - 128;
}
break;
case VYUY:
c = *(t + 1) - 16;
if (!cbcr_reverse) {
d = *(t + 2) - 128;
e = *(t) - 128;
} else {
e = *(t + 2) - 128;
d = *(t) - 128;
}
break;
default: // like YUYV
c = *(t) - 16;
if (!cbcr_reverse) {
d = *(t + 1) - 128;
e = *(t + 3) - 128;
} else {
e = *(t + 1) - 128;
d = *(t + 3) - 128;
}
break;
}
(*cur) = jpu_clip((298 * c + 409 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c - 100 * d - 208 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c + 516 * d + 128) >> 8);
cur++;
(*cur) = 0;
cur++;
switch (format) {
case YUYV:
case YVYU:
c = *(t + 2) - 16;
break;
case VYUY:
case UYVY:
c = *(t + 3) - 16;
break;
default: // like YUYV
c = *(t + 2) - 16;
break;
}
(*cur) = jpu_clip((298 * c + 409 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c - 100 * d - 208 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c + 516 * d + 128) >> 8);
cur++;
(*cur) = 0;
cur++;
t += 4;
}
line += t_width << 2;
}
} else if (format == YUV420 || format == NV12 || format == NV21) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
c = y[j * width + i] - 16;
if (format == YUV420) {
if (!cbcr_reverse) {
d = u[(j >> 1) * (width >> 1) + (i >> 1)] - 128;
e = v[(j >> 1) * (width >> 1) + (i >> 1)] - 128;
} else {
e = u[(j >> 1) * (width >> 1) + (i >> 1)] - 128;
d = v[(j >> 1) * (width >> 1) + (i >> 1)] - 128;
}
} else if (format == NV12) {
if (!cbcr_reverse) {
d = misc[(j >> 1) * width + (i >> 1 << 1)] - 128;
e = misc[(j >> 1) * width + (i >> 1 << 1) + 1] - 128;
} else {
e = misc[(j >> 1) * width + (i >> 1 << 1)] - 128;
d = misc[(j >> 1) * width + (i >> 1 << 1) + 1] - 128;
}
} else { // if (m_color == NV21)
if (!cbcr_reverse) {
d = misc[(j >> 1) * width + (i >> 1 << 1) + 1] - 128;
e = misc[(j >> 1) * width + (i >> 1 << 1)] - 128;
} else {
e = misc[(j >> 1) * width + (i >> 1 << 1) + 1] - 128;
d = misc[(j >> 1) * width + (i >> 1 << 1)] - 128;
}
}
(*cur) = jpu_clip((298 * c + 409 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c - 100 * d - 208 * e + 128) >> 8);
cur++;
(*cur) = jpu_clip((298 * c + 516 * d + 128) >> 8);
cur++;
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
} else if (format == RGB_PLANAR) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
(*cur) = y[j * width + i];
cur++;
(*cur) = u[j * width + i];
cur++;
(*cur) = v[j * width + i];
cur++;
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
} else if (format == RGB32) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
(*cur) = misc[j * width * 4 + i];
cur++; // R
(*cur) = misc[j * width * 4 + i + 1];
cur++; // G
(*cur) = misc[j * width * 4 + i + 2];
cur++; // B
(*cur) = misc[j * width * 4 + i + 3];
cur++; // A
}
line += t_width << 2;
}
} else if (format == RGB24) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
(*cur) = misc[j * width * 3 + i];
cur++; // R
(*cur) = misc[j * width * 3 + i + 1];
cur++; // G
(*cur) = misc[j * width * 3 + i + 2];
cur++; // B
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
} else if (format == RGB16) {
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
int tmp = misc[j * width * 2 + i] << 8 | misc[j * width * 2 + i + 1];
(*cur) = ((tmp >> 11) & 0x1F << 3);
cur++; // R(5bit)
(*cur) = ((tmp >> 5) & 0x3F << 2);
cur++; // G(6bit)
(*cur) = ((tmp) & 0x1F << 3);
cur++; // B(5bit)
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
} else { // YYY
for (j = 0; j < height; j++) {
cur = line;
for (i = 0; i < width; i++) {
(*cur) = y[j * width + i];
cur++;
(*cur) = y[j * width + i];
cur++;
(*cur) = y[j * width + i];
cur++;
(*cur) = 0;
cur++;
}
line += t_width << 2;
}
}
}
int comparateYuv(Uint8 *pYuv, Uint8 *pRefYuv, int picWidth, int picHeight,
int stride, int interleave, int format, int endian, int packed)
{
int size = 0;
int y = 0, nY = 0, nCb = 0, nCr = 0;
Uint8 *pRef = NULL;
int lumaSize = 0, chromaSize = 0, chromaStride = 0, chromaWidth = 0, chromaHeight = 0;
Uint8 *pOrg = NULL;
switch (format) {
case FORMAT_420:
nY = (picHeight + 1) / 2 * 2;
nCb = (picHeight + 1) / 2;
nCr = (picHeight + 1) / 2;
chromaSize = ((picWidth + 1) / 2) * ((picHeight + 1) / 2);
chromaStride = stride / 2;
chromaWidth = (picWidth + 1) / 2;
chromaHeight = nY;
break;
case FORMAT_224:
nY = (picHeight + 1) / 2 * 2;
nCb = (picHeight + 1) / 2;
nCr = (picHeight + 1) / 2;
chromaSize = (picWidth) * ((picHeight + 1) / 2);
chromaStride = stride;
chromaWidth = picWidth;
chromaHeight = nY;
break;
case FORMAT_422:
nY = picHeight;
nCb = picHeight;
nCr = picHeight;
chromaSize = ((picWidth + 1) / 2) * picHeight;
chromaStride = stride / 2;
chromaWidth = (picWidth + 1) / 2;
chromaHeight = nY * 2;
break;
case FORMAT_444:
nY = picHeight;
nCb = picHeight;
nCr = picHeight;
chromaSize = picWidth * picHeight;
chromaStride = stride;
chromaWidth = picWidth;
chromaHeight = nY * 2;
break;
case FORMAT_400:
nY = picHeight;
nCb = 0;
nCr = 0;
chromaSize = 0;
chromaStride = 0;
chromaWidth = 0;
chromaHeight = 0;
break;
}
pRef = pRefYuv;
pOrg = pYuv;
if (packed) {
if (packed == PACKED_FORMAT_444)
picWidth *= 3;
else
picWidth *= 2;
chromaSize = 0;
}
lumaSize = picWidth * nY;
size = lumaSize + chromaSize * 2;
if (picWidth == stride) {
if (OSAL_MEMCMP(pRef, pOrg, size)) {
JLOG(INFO, "pRef = 0x%lx, pOrg = 0x%lx, size:%d\n",
(unsigned long)pRef, (unsigned long)pOrg, size);
return 1;
} else
return 0;
} else {
for (y = 0; y < nY; ++y) {
if (OSAL_MEMCMP(pOrg + stride * y, pRef + y * picWidth, picWidth)) {
JLOG(INFO, "pRef1 = 0x%lx, pOrg1 = 0x%lx\n",
(unsigned long)(pRef + y * picWidth),
(unsigned long)(pOrg + stride * y));
return 1;
}
}
if (packed)
return 0;
pRef = pRef + lumaSize;
pOrg = pOrg + nY * stride;
if (interleave) {
for (y = 0; y < (chromaHeight / 2); ++y) {
if (OSAL_MEMCMP(pOrg + (chromaStride * 2) * y,
pRef + y * (chromaWidth * 2),
(chromaWidth * 2))) {
JLOG(INFO, "pRef1 = 0x%lx\n", (unsigned long)(pOrg + (chromaStride * 2) * y));
JLOG(INFO, "pOrg2 = 0x%lx\n", (unsigned long)(pRef + y * (chromaWidth * 2)));
return 1;
}
}
} else {
for (y = 0; y < nCb; ++y) {
if (OSAL_MEMCMP(pOrg + chromaStride * y, pRef + y * chromaWidth, chromaWidth)) {
JLOG(INFO,
"pRef3 = 0x%lx, pOrg3 = 0x%lx\n",
(unsigned long)(pOrg + chromaStride * y),
(unsigned long)(pRef + y * chromaWidth));
return 1;
}
}
pRef = pRef + chromaSize;
pOrg = pOrg + nCb * chromaStride;
for (y = 0; y < nCr; ++y) {
if (OSAL_MEMCMP(pOrg + chromaStride * y, pRef + y * chromaWidth, chromaWidth)) {
JLOG(INFO,
"pRef4 = 0x%lx, pOrg4 = 0x%lx\n",
(unsigned long)(pOrg + chromaStride * y),
(unsigned long)(pRef + y * chromaWidth));
return 1;
}
}
}
}
return 0;
}