Files
Linux_Drivers/u-boot-2021.10/drivers/jpeg/jpuapifunc.c
wangliang.wang 607778300c [uboot] Upgrade the MMF SDK from V4.0.0 to V4.1.0
1. add cv181x functions
	2. Delete some useless files and add .gitignore

Change-Id: Iea2b2fa43b5a1152e5e99fb32b88f8d2c249251a
2023-03-10 20:42:30 +08:00

2113 lines
54 KiB
C

#include "jdi.h"
#include "jpuapifunc.h"
#include "jpulog.h"
#include "regdefine.h"
/******************************************************************************
* Codec Instance Slot Management
******************************************************************************/
// static UINT tGetBits(JpgDecInfo *jpg, int endian, int byteCnt);
const char lendian[4] = {0x49, 0x49, 0x2A, 0x00};
const char bendian[4] = {0x4D, 0x4D, 0x00, 0x2A};
const char *jfif = "JFIF";
const char *jfxx = "JFXX";
const char *exif = "Exif";
static unsigned char sJpuCompInfoTable[5][24] = {
{00, 02, 02, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 420
{00, 02, 01, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 422H
{00, 01, 02, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 422V
{00, 01, 01, 00, 00, 00, 01, 01, 01, 01, 01, 01,
02, 01, 01, 01, 01, 01, 03, 00, 00, 00, 00, 00}, // 444
{00, 01, 01, 00, 00, 00, 01, 00, 00, 00, 00, 00,
02, 00, 00, 00, 00, 00, 03, 00, 00, 00, 00, 00}, // 400
};
JpgRet InitJpgInstancePool(void)
{
int i;
JpgInst *pJpgInst;
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip)
return JPG_RET_INVALID_HANDLE;
if (jip->instance_pool_inited == 0) {
for (i = 0; i < MAX_NUM_INSTANCE; i++) {
pJpgInst = (JpgInst *)jip->jpgInstPool[i];
pJpgInst->instIndex = i;
pJpgInst->inUse = 0;
}
jip->instance_pool_inited = 1;
}
return JPG_RET_SUCCESS;
}
/*
* GetJpgInstance() obtains a instance.
* It stores a pointer to the allocated instance in *ppInst
* and returns JPG_RET_SUCCESS on success.
* Failure results in 0(null pointer) in *ppInst and JPG_RET_FAILURE.
*/
JpgRet GetJpgInstance(JpgInst **ppInst)
{
int i;
JpgInst *pJpgInst = 0;
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip)
return JPG_RET_INVALID_HANDLE;
for (i = 0; i < MAX_NUM_INSTANCE; ++i, ++pJpgInst) {
pJpgInst = (JpgInst *)jip->jpgInstPool[i];
if (!pJpgInst) {
return JPG_RET_FAILURE;
}
if (!pJpgInst->inUse)
break;
}
if (i == MAX_NUM_INSTANCE) {
*ppInst = 0;
return JPG_RET_FAILURE;
}
pJpgInst->inUse = 1;
*ppInst = pJpgInst;
if (jdi_open_instance(pJpgInst->instIndex) < 0)
return JPG_RET_FAILURE;
return JPG_RET_SUCCESS;
}
void FreeJpgInstance(JpgInst *pJpgInst)
{
pJpgInst->inUse = 0;
jdi_close_instance(pJpgInst->instIndex);
}
JpgRet CheckJpgInstValidity(JpgInst *pci)
{
JpgInst *pJpgInst = 0;
int i;
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip) {
BM_DBG_ERR("jdi_get_instance_pool\n");
return JPG_RET_FAILURE;
}
for (i = 0; i < MAX_NUM_INSTANCE; ++i, ++pJpgInst) {
if ((JpgInst *)jip->jpgInstPool[i] == pci)
return JPG_RET_SUCCESS;
}
return JPG_RET_INVALID_HANDLE;
}
/******************************************************************************
* API Subroutines
******************************************************************************/
JpgRet CheckJpgDecOpenParam(JpgDecOpenParam *pop)
{
if (pop == 0) {
return JPG_RET_INVALID_PARAM;
}
if (pop->bitstreamBuffer % 8) {
return JPG_RET_INVALID_PARAM;
}
if (pop->bitstreamBufferSize % 1024 ||
pop->bitstreamBufferSize < 1024) {
return JPG_RET_INVALID_PARAM;
}
if (pop->chroma_interleave != CBCR_SEPARATED &&
pop->chroma_interleave != CBCR_INTERLEAVE &&
pop->chroma_interleave != CRCB_INTERLEAVE) {
return JPG_RET_INVALID_PARAM;
}
if (pop->packedFormat > PACKED_FORMAT_444) {
return JPG_RET_INVALID_PARAM;
}
if (pop->packedFormat != PACKED_FORMAT_NONE) {
if (pop->chroma_interleave != CBCR_SEPARATED) {
return JPG_RET_INVALID_PARAM;
}
}
return JPG_RET_SUCCESS;
}
int JpgDecHuffTabSetUp(JpgDecInfo *jpg)
{
int i, j;
int HuffData; // 16BITS
int HuffLength;
int temp;
// MIN Tables
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0x003);
// DC Luma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMin[0][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG,
(((temp & 0xFFFF) << 16) | HuffData)); // 32-bit
}
// DC Chroma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMin[2][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData)); // 32-bit
}
// AC Luma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMin[1][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData)); // 32-bit
}
// AC Chroma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMin[3][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData)); // 32-bit
}
// MAX Tables
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0x403);
JpuWriteReg(MJPEG_HUFF_ADDR_REG, 0x440);
// DC Luma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMax[0][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData));
}
// DC Chroma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMax[2][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData));
}
// AC Luma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMax[1][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData));
}
// AC Chroma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffMax[3][j];
temp = (HuffData & 0x8000) >> 15;
temp = (temp << 15) | (temp << 14) | (temp << 13) |
(temp << 12) | (temp << 11) | (temp << 10) |
(temp << 9) | (temp << 8) | (temp << 7) | (temp << 6) |
(temp << 5) | (temp << 4) | (temp << 3) | (temp << 2) |
(temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFF) << 16) | HuffData));
}
// PTR Tables
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0x803);
JpuWriteReg(MJPEG_HUFF_ADDR_REG, 0x880);
// DC Luma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffPtr[0][j];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
// DC Chroma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffPtr[2][j];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
// AC Luma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffPtr[1][j];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
// AC Chroma
for (j = 0; j < 16; j++) {
HuffData = jpg->huffPtr[3][j];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
// VAL Tables
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0xC03);
// VAL DC Luma
HuffLength = 0;
for (i = 0; i < 12; i++)
HuffLength += jpg->huffBits[0][i];
for (i = 0; i < HuffLength;
i++) { // 8-bit, 12 row, 1 category (DC Luma)
HuffData = jpg->huffVal[0][i];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
for (i = 0; i < 12 - HuffLength; i++) {
JpuWriteReg(MJPEG_HUFF_DATA_REG, 0xFFFFFFFF);
}
// VAL DC Chroma
HuffLength = 0;
for (i = 0; i < 12; i++)
HuffLength += jpg->huffBits[2][i];
for (i = 0; i < HuffLength; i++) { // 8-bit, 12 row, 1 category (DC Chroma)
HuffData = jpg->huffVal[2][i];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
for (i = 0; i < 12 - HuffLength; i++) {
JpuWriteReg(MJPEG_HUFF_DATA_REG, 0xFFFFFFFF);
}
// VAL AC Luma
HuffLength = 0;
for (i = 0; i < 162; i++)
HuffLength += jpg->huffBits[1][i];
for (i = 0; i < HuffLength; i++) { // 8-bit, 162 row, 1 category (AC Luma)
HuffData = jpg->huffVal[1][i];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
for (i = 0; i < 162 - HuffLength; i++) {
JpuWriteReg(MJPEG_HUFF_DATA_REG, 0xFFFFFFFF);
}
// VAL AC Chroma
HuffLength = 0;
for (i = 0; i < 162; i++)
HuffLength += jpg->huffBits[3][i];
for (i = 0; i < HuffLength; i++) { // 8-bit, 162 row, 1 category (AC Chroma)
HuffData = jpg->huffVal[3][i];
temp = (HuffData & 0x80) >> 7;
temp = (temp << 23) | (temp << 22) | (temp << 21) |
(temp << 20) | (temp << 19) | (temp << 18) |
(temp << 17) | (temp << 16) | (temp << 15) |
(temp << 14) | (temp << 13) | (temp << 12) |
(temp << 11) | (temp << 10) | (temp << 9) | (temp << 8) |
(temp << 7) | (temp << 6) | (temp << 5) | (temp << 4) |
(temp << 3) | (temp << 2) | (temp << 1) | (temp);
JpuWriteReg(MJPEG_HUFF_DATA_REG, (((temp & 0xFFFFFF) << 8) | HuffData));
}
for (i = 0; i < 162 - HuffLength; i++) {
JpuWriteReg(MJPEG_HUFF_DATA_REG, 0xFFFFFFFF);
}
// end SerPeriHuffTab
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0x000);
return 1;
}
int JpgDecQMatTabSetUp(JpgDecInfo *jpg)
{
int i;
int table;
int val;
// SetPeriQMatTab
// Comp 0
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x03);
table = jpg->cInfoTab[0][3];
for (i = 0; i < 64; i++) {
val = jpg->qMatTab[table][i];
JpuWriteReg(MJPEG_QMAT_DATA_REG, val);
}
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x00);
// Comp 1
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x43);
table = jpg->cInfoTab[1][3];
for (i = 0; i < 64; i++) {
val = jpg->qMatTab[table][i];
JpuWriteReg(MJPEG_QMAT_DATA_REG, val);
}
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x00);
// Comp 2
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x83);
table = jpg->cInfoTab[2][3];
for (i = 0; i < 64; i++) {
val = jpg->qMatTab[table][i];
JpuWriteReg(MJPEG_QMAT_DATA_REG, val);
}
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x00);
return 1;
}
void JpgDecGramSetup(JpgDecInfo *jpg)
{
int dExtBitBufCurPos;
int dExtBitBufBaseAddr;
int dMibStatus;
dMibStatus = 1;
dExtBitBufCurPos = jpg->pagePtr;
dExtBitBufBaseAddr = jpg->streamBufStartAddr;
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, dExtBitBufCurPos);
JpuWriteReg(MJPEG_BBC_EXT_ADDR_REG, dExtBitBufBaseAddr + (dExtBitBufCurPos << 8));
JpuWriteReg(MJPEG_BBC_INT_ADDR_REG, (dExtBitBufCurPos & 1) << 6);
JpuWriteReg(MJPEG_BBC_DATA_CNT_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
JpuWriteReg(MJPEG_BBC_COMMAND_REG, (jpg->streamEndian << 1) | 0);
while (dMibStatus == 1) {
dMibStatus = JpuReadReg(MJPEG_BBC_BUSY_REG);
}
dMibStatus = 1;
dExtBitBufCurPos = dExtBitBufCurPos + 1;
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, dExtBitBufCurPos);
JpuWriteReg(MJPEG_BBC_EXT_ADDR_REG, dExtBitBufBaseAddr + (dExtBitBufCurPos << 8));
JpuWriteReg(MJPEG_BBC_INT_ADDR_REG, (dExtBitBufCurPos & 1) << 6);
JpuWriteReg(MJPEG_BBC_DATA_CNT_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
JpuWriteReg(MJPEG_BBC_COMMAND_REG, (jpg->streamEndian << 1) | 0);
while (dMibStatus == 1) {
dMibStatus = JpuReadReg(MJPEG_BBC_BUSY_REG);
}
dMibStatus = 1;
dExtBitBufCurPos = dExtBitBufCurPos + 1;
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, dExtBitBufCurPos); // next unit page pointer
JpuWriteReg(MJPEG_BBC_CTRL_REG, (jpg->streamEndian << 1) | 1);
JpuWriteReg(MJPEG_GBU_WD_PTR_REG, jpg->wordPtr);
JpuWriteReg(MJPEG_GBU_BBSR_REG, 0);
JpuWriteReg(MJPEG_GBU_BBER_REG, ((256 / 4) * 2) - 1);
if (jpg->pagePtr & 1) {
JpuWriteReg(MJPEG_GBU_BBIR_REG, 0);
JpuWriteReg(MJPEG_GBU_BBHR_REG, 0);
} else {
JpuWriteReg(MJPEG_GBU_BBIR_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
JpuWriteReg(MJPEG_GBU_BBHR_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
}
JpuWriteReg(MJPEG_GBU_CTRL_REG, 4);
JpuWriteReg(MJPEG_GBU_FF_RPTR_REG, jpg->bitPtr);
}
enum {
SAMPLE_420 = 0xA,
SAMPLE_H422 = 0x9,
SAMPLE_V422 = 0x6,
SAMPLE_444 = 0x5,
SAMPLE_400 = 0x1
};
const BYTE cDefHuffBits[4][16] = {
{// DC index 0 (Luminance DC)
0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00},
{// AC index 0 (Luminance AC)
0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04,
0x00, 0x00, 0x01, 0x7D},
{// DC index 1 (Chrominance DC)
0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00},
{// AC index 1 (Chrominance AC)
0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
0x00, 0x01, 0x02, 0x77}
};
const BYTE cDefHuffVal[4][162] = {
{// DC index 0 (Luminance DC)
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B},
{// AC index 0 (Luminance AC)
0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06,
0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08,
0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72,
0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28,
0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45,
0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75,
0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3,
0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9,
0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2,
0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4,
0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA},
{// DC index 1 (Chrominance DC)
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B},
{// AC index 1 (Chrominance AC)
0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41,
0x51, 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1,
0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26,
0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44,
0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74,
0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A,
0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4,
0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA,
0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4,
0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA}
};
enum {
Marker = 0xFF,
FF_Marker = 0x00,
SOI_Marker = 0xFFD8, // Start of image
EOI_Marker = 0xFFD9, // End of image
JFIF_CODE = 0xFFE0, // Application
EXIF_CODE = 0xFFE1,
DRI_Marker = 0xFFDD, // Define restart interval
RST_Marker = 0xD, // 0xD0 ~0xD7
DQT_Marker = 0xFFDB, // Define quantization table(s)
DHT_Marker = 0xFFC4, // Define Huffman table(s)
SOF_Marker = 0xFFC0, // Start of frame : Baseline DCT
SOS_Marker = 0xFFDA, // Start of scan
};
int check_start_code(JpgDecInfo *jpg)
{
if (show_bits(&jpg->gbc, 8) == 0xFF)
return 1;
else
return 0;
}
int find_start_code(JpgDecInfo *jpg)
{
int word;
for (;;) {
if (get_bits_left(&jpg->gbc) <= 16) {
////printf("hit end of stream\n");
return 0;
}
word = show_bits(&jpg->gbc, 16);
if (word > 0xFF00 && word < 0xFFFF)
break;
get_bits(&jpg->gbc, 8);
}
return word;
}
int find_start_soi_code(JpgDecInfo *jpg)
{
int word;
for (;;) {
if (get_bits_left(&jpg->gbc) <= 16) {
////printf("hit end of stream\n");
return 0;
}
word = show_bits(&jpg->gbc, 16);
if (word > 0xFF00 && word < 0xFFFF) {
if (word != SOI_Marker)
get_bits(&jpg->gbc, 8);
break;
}
get_bits(&jpg->gbc, 8);
}
return word;
}
#ifdef MJPEG_ERROR_CONCEAL
int find_restart_marker(JpgDecInfo *jpg)
{
int word;
for (;;) {
if (get_bits_left(&jpg->gbc) <= 16) {
////printf("hit end of stream\n");
return -1;
}
word = show_bits(&jpg->gbc, 16);
if ((word >= 0xFFD0 && word <= 0xFFD7) || word == 0xFFD8 || word == 0xFFD9)
break;
get_bits(&jpg->gbc, 8);
}
return word;
}
#endif
int decode_app_header(JpgDecInfo *jpg)
{
int length;
if (get_bits_left(&jpg->gbc) < 16)
return 0;
length = get_bits(&jpg->gbc, 16);
length -= 2;
while (length-- > 0) {
if (get_bits_left(&jpg->gbc) < 8)
return 0;
get_bits(&jpg->gbc, 8);
}
return 1;
}
int decode_dri_header(JpgDecInfo *jpg)
{
// Length, Lr
if (get_bits_left(&jpg->gbc) < 16 * 2)
return 0;
get_bits(&jpg->gbc, 16);
jpg->rstIntval = get_bits(&jpg->gbc, 16);
return 1;
}
int decode_dqt_header(JpgDecInfo *jpg)
{
int Pq;
int Tq;
int i;
int tmp;
if (get_bits_left(&jpg->gbc) < 16)
return 0;
// Lq, Length of DQT
get_bits(&jpg->gbc, 16);
do {
if (get_bits_left(&jpg->gbc) < 4 + 4 + 8 * 64)
return 0;
// Pq, Quantization Precision
tmp = get_bits(&jpg->gbc, 8);
// Tq, Quantization table destination identifier
Pq = (tmp >> 4) & 0xf;
Tq = tmp & 0xf;
for (i = 0; i < 64; i++)
jpg->qMatTab[Tq][i] = (BYTE)get_bits(&jpg->gbc, 8);
} while (!check_start_code(jpg));
if (Pq != 0) {// not 8-bit
////printf("pq is not set to zero\n");
return 0;
}
return 1;
}
int decode_dth_header(JpgDecInfo *jpg)
{
int Tc;
int Th;
int ThTc;
int bitCnt;
int i;
int tmp;
// Length, Lh
if (get_bits_left(&jpg->gbc) < 16)
return 0;
get_bits(&jpg->gbc, 16);
do {
if (get_bits_left(&jpg->gbc) < 8 + 8 * 16)
return 0;
// Table class - DC, AC
tmp = get_bits(&jpg->gbc, 8);
// Table destination identifier
Tc = (tmp >> 4) & 0xf;
Th = tmp & 0xf;
// DC_ID0 (0x00) -> 0
// AC_ID0 (0x10) -> 1
// DC_ID1 (0x01) -> 2
// AC_ID1 (0x11) -> 3
ThTc = ((Th & 1) << 1) | (Tc & 1);
// Get Huff Bits list
bitCnt = 0;
for (i = 0; i < 16; i++) {
jpg->huffBits[ThTc][i] = (BYTE)get_bits(&jpg->gbc, 8);
bitCnt += jpg->huffBits[ThTc][i];
if (cDefHuffBits[ThTc][i] != jpg->huffBits[ThTc][i])
jpg->userHuffTab = 1;
}
if (get_bits_left(&jpg->gbc) < 8 * bitCnt)
return 0;
// Get Huff Val list
for (i = 0; i < bitCnt; i++) {
jpg->huffVal[ThTc][i] = (BYTE)get_bits(&jpg->gbc, 8);
if (cDefHuffVal[ThTc][i] != jpg->huffVal[ThTc][i])
jpg->userHuffTab = 1;
}
} while (!check_start_code(jpg));
return 1;
}
int decode_sof_header(JpgDecInfo *jpg)
{
int samplePrecision;
int sampleFactor;
int i;
int Tqi;
BYTE compID;
int hSampFact[3] = {
0,
};
int vSampFact[3] = {
0,
};
int picX, picY;
int numComp;
int tmp;
if (get_bits_left(&jpg->gbc) < 16 + 8 + 16 + 16 + 8)
return 0;
// LF, Length of SOF
get_bits(&jpg->gbc, 16);
// Sample Precision: Baseline(8), P
samplePrecision = get_bits(&jpg->gbc, 8);
if (samplePrecision != 8) {
// printf("Sample Precision is not 8\n");
return 0;
}
picY = get_bits(&jpg->gbc, 16);
if (picY > MAX_MJPG_PIC_WIDTH) {
// printf("Picture Vertical Size limits Maximum size\n");
return 0;
}
picX = get_bits(&jpg->gbc, 16);
if (picX > MAX_MJPG_PIC_HEIGHT) {
// printf("Picture Horizontal Size limits Maximum size\n");
return 0;
}
// Number of Components in Frame: Nf
numComp = get_bits(&jpg->gbc, 8);
if (numComp > 3) {
// printf("Picture Horizontal Size limits Maximum size\n");
}
if (get_bits_left(&jpg->gbc) < numComp * (8 + 4 + 4 + 8))
return 0;
for (i = 0; i < numComp; i++) {
// Component ID, Ci 0 ~ 255
compID = (BYTE)get_bits(&jpg->gbc, 8);
tmp = get_bits(&jpg->gbc, 8);
// Horizontal Sampling Factor, Hi
hSampFact[i] = (tmp >> 4) & 0xf;
// Vertical Sampling Factor, Vi
vSampFact[i] = tmp & 0xf;
// Quantization Table Selector, Tqi
Tqi = get_bits(&jpg->gbc, 8);
jpg->cInfoTab[i][0] = compID;
jpg->cInfoTab[i][1] = (BYTE)hSampFact[i];
jpg->cInfoTab[i][2] = (BYTE)vSampFact[i];
jpg->cInfoTab[i][3] = (BYTE)Tqi;
}
// if ( hSampFact[0]>2 || vSampFact[0]>2 || ( numComp == 3 && (
// hSampFact[1]!=1 || hSampFact[2]!=1 || vSampFact[1]!=1 ||
// vSampFact[2]!=1) ) ) printf("Not Supported Sampling Factor\n");
if (numComp == 1)
sampleFactor = SAMPLE_400;
else
sampleFactor = ((hSampFact[0] & 3) << 2) | (vSampFact[0] & 3);
switch (sampleFactor) {
case SAMPLE_420:
jpg->format = FORMAT_420;
break;
case SAMPLE_H422:
jpg->format = FORMAT_422;
break;
case SAMPLE_V422:
jpg->format = FORMAT_224;
break;
case SAMPLE_444:
jpg->format = FORMAT_444;
break;
default: // 4:0:0
jpg->format = FORMAT_400;
}
jpg->picWidth = picX;
jpg->picHeight = picY;
return 1;
}
int decode_sos_header(JpgDecInfo *jpg)
{
int i, j;
int len;
int numComp;
int compID;
int ecsPtr;
int ss, se, ah, al;
int dcHufTblIdx[3] = {
0,
};
int acHufTblIdx[3] = {
0,
};
int tmp;
if (get_bits_left(&jpg->gbc) < 8)
return 0;
// Length, Ls
len = get_bits(&jpg->gbc, 16);
jpg->ecsPtr = get_bits_count(&jpg->gbc) / 8 + len - 2;
ecsPtr = jpg->ecsPtr + jpg->frameOffset;
// printf("ecsPtr=0x%x frameOffset=0x%x, ecsOffset=0x%x, wrPtr=0x%x,
// rdPtr0x%x\n", jpg->ecsPtr, jpg->frameOffset, ecsPtr,
// jpg->streamWrPtr, jpg->streamRdPtr);
jpg->pagePtr = ecsPtr >> 8; // page unit ecsPtr/256;
jpg->wordPtr = (ecsPtr & 0xF0) >> 2; // word unit ((ecsPtr % 256) & 0xF0) / 4;
if (jpg->pagePtr & 1)
jpg->wordPtr += 64;
if (jpg->wordPtr & 1)
jpg->wordPtr -= 1; // to make even.
jpg->bitPtr = (ecsPtr & 0xF) << 3; // bit unit (ecsPtr & 0xF) * 8;
if (get_bits_left(&jpg->gbc) < 8)
return 0;
// Number of Components in Scan: Ns
numComp = get_bits(&jpg->gbc, 8);
if (get_bits_left(&jpg->gbc) < numComp * (8 + 4 + 4))
return 0;
for (i = 0; i < numComp; i++) {
// Component ID, Csj 0 ~ 255
compID = get_bits(&jpg->gbc, 8);
tmp = get_bits(&jpg->gbc, 8);
// dc entropy coding table selector, Tdj
dcHufTblIdx[i] = (tmp >> 4) & 0xf;
// ac entropy coding table selector, Taj
acHufTblIdx[i] = tmp & 0xf;
for (j = 0; j < numComp; j++) {
if (compID == jpg->cInfoTab[j][0]) {
jpg->cInfoTab[j][4] = (BYTE)dcHufTblIdx[i];
jpg->cInfoTab[j][5] = (BYTE)acHufTblIdx[i];
}
}
}
if (get_bits_left(&jpg->gbc) < 8 + 8 + 4 + 4)
return 0;
// Ss 0
ss = get_bits(&jpg->gbc, 8);
// Se 3F
se = get_bits(&jpg->gbc, 8);
tmp = get_bits(&jpg->gbc, 8);
// Ah 0
ah = (i >> 4) & 0xf;
// Al 0
al = tmp & 0xf;
if (ss != 0 || se != 0x3F || ah != 0 || al != 0) {
// printf("The Jpeg Image must be another profile\n");
return 0;
}
return 1;
}
static void genDecHuffTab(JpgDecInfo *jpg, int tabNum)
{
unsigned char *huffPtr, *huffBits;
unsigned int *huffMax, *huffMin;
int ptrCnt = 0;
int huffCode = 0;
int zeroFlag = 0;
int dataFlag = 0;
int i;
huffBits = jpg->huffBits[tabNum];
huffPtr = jpg->huffPtr[tabNum];
huffMax = jpg->huffMax[tabNum];
huffMin = jpg->huffMin[tabNum];
for (i = 0; i < 16; i++) {
if (huffBits[i]) { // if there is bit cnt value
huffPtr[i] = (BYTE)ptrCnt;
ptrCnt += huffBits[i];
huffMin[i] = huffCode;
huffMax[i] = huffCode + (huffBits[i] - 1);
dataFlag = 1;
zeroFlag = 0;
} else {
huffPtr[i] = 0xFF;
huffMin[i] = 0xFFFF;
huffMax[i] = 0xFFFF;
zeroFlag = 1;
}
if (dataFlag == 1) {
if (zeroFlag == 1)
huffCode <<= 1;
else
huffCode = (huffMax[i] + 1) << 1;
}
}
}
int JpuGbuInit(vpu_getbit_context_t *ctx, BYTE *buffer, int size)
{
ctx->buffer = buffer;
ctx->index = 0;
ctx->size = size / 8;
return 1;
}
int JpuGbuGetUsedBitCount(vpu_getbit_context_t *ctx) { return ctx->index * 8; }
int JpuGbuGetLeftBitCount(vpu_getbit_context_t *ctx)
{
return (ctx->size * 8) - JpuGbuGetUsedBitCount(ctx);
}
unsigned int JpuGbuGetBit(vpu_getbit_context_t *ctx, int bit_num)
{
BYTE *p;
unsigned int b = 0x0;
if (bit_num > JpuGbuGetLeftBitCount(ctx))
return (unsigned int)-1;
p = ctx->buffer + ctx->index;
if (bit_num == 8) {
b = *p;
ctx->index++;
} else if (bit_num == 16) {
b = *p++ << 8;
b |= *p++;
ctx->index += 2;
} else if (bit_num == 32) {
b = *p++ << 24;
b |= (*p++ << 16);
b |= (*p++ << 8);
b |= (*p++ << 0);
ctx->index += 4;
}
return b;
}
unsigned int JpuGguShowBit(vpu_getbit_context_t *ctx, int bit_num)
{
BYTE *p;
unsigned int b = 0x0;
if (bit_num > JpuGbuGetLeftBitCount(ctx))
return (unsigned int)-1;
p = ctx->buffer + ctx->index;
if (bit_num == 8) {
b = *p;
} else if (bit_num == 16) {
b = *p++ << 8;
b |= *p++;
} else if (bit_num == 32) {
b = *p++ << 24;
b |= (*p++ << 16);
b |= (*p++ << 8);
b |= (*p++ << 0);
}
return b;
}
static int wraparound_bistream_data(JpgDecInfo *jpg, int return_type)
{
BYTE *dst;
BYTE *src;
BYTE *data;
int data_size;
int src_size;
int dst_size;
data_size = jpg->streamWrPtr - jpg->streamBufStartAddr;
data = (BYTE *)OSAL_MALLOC(data_size);
if (data_size && data)
JpuReadMem(jpg->streamBufStartAddr, data, data_size,
jpg->streamEndian);
src_size = jpg->streamBufSize - jpg->frameOffset;
src = (BYTE *)OSAL_MALLOC(src_size);
dst_size = ((src_size + (JPU_GBU_SIZE - 1)) & ~(JPU_GBU_SIZE - 1));
dst = (BYTE *)OSAL_MALLOC(dst_size);
if (dst && src) {
memset(dst, 0x00, dst_size);
JpuReadMem(jpg->streamBufStartAddr + jpg->frameOffset, src, src_size, jpg->streamEndian);
memcpy(dst + (dst_size - src_size), src, src_size);
JpuWriteMem(jpg->streamBufStartAddr, dst, dst_size, jpg->streamEndian);
if (data_size && data)
JpuWriteMem(jpg->streamBufStartAddr + dst_size, data, data_size, jpg->streamEndian);
OSAL_FREE(src);
OSAL_FREE(dst);
}
if (data_size && data)
OSAL_FREE(data);
if (return_type == -2) { // header wraparound
jpg->streamWrPtr = jpg->streamBufStartAddr + dst_size + data_size;
jpg->consumeByte = 0;
return -2;
} else if (return_type == -1) { // ecsPtr wraparound
jpg->streamWrPtr = jpg->streamBufStartAddr + dst_size + data_size;
jpg->frameOffset = 0;
return -1;
}
return 0; // error
}
#ifdef MJPEG_ERROR_CONCEAL
int JpegDecodeConcealError(JpgDecInfo *jpg)
{
unsigned int code;
int ret, foced_stop = 0;
BYTE *b;
Uint32 ecsPtr = 0;
Uint32 size, wrOffset;
Uint32 nextMarkerPtr;
Uint32 iRstIdx;
int numMcu = 0, numMcuCol = 0;
// "nextOffset" is distance between frameOffset and next_restart_index
// that exist.
nextMarkerPtr = jpg->nextOffset + jpg->frameOffset;
if (jpg->streamWrPtr == jpg->streamBufStartAddr) {
size = jpg->streamBufSize - nextMarkerPtr;
wrOffset = jpg->streamBufSize;
} else {
size = jpg->streamWrPtr - nextMarkerPtr;
wrOffset = (jpg->streamWrPtr - jpg->streamBufStartAddr);
}
// pointing to find next_restart_marker
b = jpg->pBitStream + nextMarkerPtr;
init_get_bits(&jpg->gbc, b, size * 8);
for (;;) {
ret = find_restart_marker(jpg);
if (ret < 0) {
break;
}
code = get_bits(&jpg->gbc, 16);
if (code == 0xFFD8 || code == 0xFFD9) {
// if next_start_maker meet EOI(end of picture) or next
// SOI(start of image) but decoding is not completed
// yet, To prevent over picture boundary in ringbuffer
// mode, finding previous maker and make decoding forced
// to stop.
b = jpg->pBitStream + jpg->currOffset + jpg->frameOffset;
init_get_bits(&jpg->gbc, b, size * 8);
nextMarkerPtr = jpg->currOffset + jpg->frameOffset;
foced_stop = 1;
continue;
}
iRstIdx = (code & 0xF);
// you can find next restart marker which will be.
if (iRstIdx >= 0 && iRstIdx <= 7) {
int numMcuRow;
if (get_bits_left(&jpg->gbc) < 8)
return (-1);
jpg->ecsPtr = get_bits_count(&jpg->gbc) / 8;
// set ecsPtr that restart marker is founded.
ecsPtr = jpg->ecsPtr + nextMarkerPtr;
jpg->pagePtr = ecsPtr >> 8;
jpg->wordPtr = (ecsPtr & 0xF0) >> 2; // word unit
if (jpg->pagePtr & 1)
jpg->wordPtr += 64;
if (jpg->wordPtr & 1)
jpg->wordPtr -= 1; // to make even.
jpg->bitPtr = (ecsPtr & 0xF) << 3; // bit unit
numMcuRow = (jpg->alignedWidth / jpg->mcuWidth);
numMcuCol = (jpg->alignedHeight / jpg->mcuHeight);
// num of restart marker that is rounded can be
// calculated from error position.
// numRstMakerRounding =
// ((jpg->errInfo.errPosY*numMcuRow +
// jpg->errInfo.errPosX) / (jpg->rstIntval*8));
jpg->curRstIdx = iRstIdx;
if (jpg->curRstIdx < jpg->nextRstIdx)
jpg->numRstMakerRounding++;
// find mcu position to restart.
numMcu =
(jpg->numRstMakerRounding * jpg->rstIntval * 8) +
(jpg->curRstIdx + 1) * jpg->rstIntval;
// numMcu = jpg->rstIntval;
jpg->setPosX = (numMcu % numMcuRow);
jpg->setPosY = (numMcu / numMcuRow);
jpg->gbuStartPtr = ((ecsPtr - jpg->frameOffset) / 256) * 256;
// if setPosY is greater than Picture Height, set mcu
// position to last mcu of picture to finish decoding.
if (jpg->setPosY > numMcuCol || foced_stop) {
jpg->setPosX = numMcuRow - 1;
jpg->setPosY = numMcuCol - 1;
}
// update restart_index to find next.
jpg->nextRstIdx = iRstIdx++;
ret = 0;
break;
}
}
// prevent to find same position.
jpg->currOffset = jpg->nextOffset;
// if the distance between ecsPtr and streamBufEndAddr is less than
// 512byte, that rdPtr run over than streamBufEndAddr without interrupt.
// bellow is workaround to avoid this case.
if (jpg->streamBufSize - (jpg->frameOffset + ecsPtr) < JPU_GBU_SIZE)
// if((jpg->streamBufEndAddr - ecsPtr < JPU_GBU_SIZE) )
{
ret = wraparound_bistream_data(jpg, -1);
}
if (wrOffset - (jpg->frameOffset + jpg->ecsPtr) < JPU_GBU_SIZE && jpg->streamEndflag == 0) {
return -1;
}
return ret;
}
#endif
int JpegDecodeHeader(JpgDecInfo *jpg)
{
unsigned int code;
int ret;
int i;
int temp;
int wrOffset;
BYTE *b = jpg->pBitStream + jpg->frameOffset;
int size;
ret = 1;
if (jpg->streamWrPtr == jpg->streamBufStartAddr) {
size = jpg->streamBufSize - jpg->frameOffset;
wrOffset = jpg->streamBufSize;
} else {
if (jpg->frameOffset >= (int)(jpg->streamWrPtr - jpg->streamBufStartAddr))
size = jpg->streamBufSize - jpg->frameOffset;
else
size = (jpg->streamWrPtr - jpg->streamBufStartAddr) - jpg->frameOffset;
wrOffset = (jpg->streamWrPtr - jpg->streamBufStartAddr);
}
if (!b || !size) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
// find start code of next frame
if (!jpg->ecsPtr) {
int nextOffset = 0;
int soiOffset = 0;
if (jpg->consumeByte != 0) { // meaning is frameIdx > 0
nextOffset = jpg->consumeByte;
if (nextOffset <= 0)
nextOffset = 2; // in order to consume start code.
}
// consume to find the start code of next frame.
b += nextOffset;
size -= nextOffset;
if (size < 0) {
jpg->consumeByte -= (b - (jpg->pBitStream + jpg->streamBufSize));
if (jpg->consumeByte < 0) {
ret = 0;
goto DONE_DEC_HEADER;
}
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
init_get_bits(&jpg->gbc, b, size * 8);
for (;;) {
code = find_start_soi_code(jpg);
if (code == 0) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
if (code == SOI_Marker)
break;
}
soiOffset = get_bits_count(&jpg->gbc) / 8;
b += soiOffset;
size -= soiOffset;
jpg->frameOffset += (soiOffset + nextOffset);
}
if (jpg->headerSize > 0 && (jpg->headerSize > (jpg->streamBufSize - jpg->frameOffset))) {
// if header size is smaller than room of stream end. copy the buffer to bistream start.
BM_DBG_ERR("\n");
return wraparound_bistream_data(jpg, -2);
}
init_get_bits(&jpg->gbc, b, size * 8);
// Initialize component information table
for (i = 0; i < 4; i++) {
jpg->cInfoTab[i][0] = 0;
jpg->cInfoTab[i][1] = 0;
jpg->cInfoTab[i][2] = 0;
jpg->cInfoTab[i][3] = 0;
jpg->cInfoTab[i][4] = 0;
jpg->cInfoTab[i][5] = 0;
}
for (;;) {
if (find_start_code(jpg) == 0) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
code = get_bits(&jpg->gbc, 16); // getbit 2byte
switch (code) {
case SOI_Marker:
break;
case JFIF_CODE:
case EXIF_CODE: {
if (!decode_app_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
}
break;
case DRI_Marker:
if (!decode_dri_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
break;
case DQT_Marker:
if (!decode_dqt_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
break;
case DHT_Marker:
if (!decode_dth_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
break;
case SOF_Marker:
if (!decode_sof_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
break;
case SOS_Marker:
if (!decode_sos_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
// we assume header size of all frame is same for mjpeg case
if (!jpg->headerSize)
jpg->headerSize = jpg->ecsPtr;
goto DONE_DEC_HEADER;
// break;
case EOI_Marker:
goto DONE_DEC_HEADER;
default:
switch (code & 0xFFF0) {
case 0xFFE0: // 0xFFEX
case 0xFFF0: // 0xFFFX
if (get_bits_left(&jpg->gbc) <= 0) {
{
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
} else {
if (!decode_app_header(jpg)) {
ret = -1;
BM_DBG_ERR("DONE_DEC_HEADER\n");
goto DONE_DEC_HEADER;
}
break;
}
default:
// in case, restart marker is founded.
if ((code & 0xFFF0) >= 0xFFD0 && (code & 0xFFF0) <= 0xFFD7)
break;
return 0;
}
break;
}
}
DONE_DEC_HEADER:
if (ret == -1) {
if (wrOffset < jpg->frameOffset) {
BM_DBG_ERR("fail\n");
return -2;
}
BM_DBG_ERR("fail\n");
return -1;
}
if (!jpg->ecsPtr) {
BM_DBG_ERR("fail\n");
return 0;
}
if (wrOffset - (jpg->frameOffset + jpg->ecsPtr) < JPU_GBU_SIZE && jpg->streamEndflag == 0) {
BM_DBG_ERR("fail\n");
return -1;
}
// this bellow is workaround to avoid the case that JPU is run over
// without interrupt.
if (jpg->streamBufSize - (jpg->frameOffset + jpg->ecsPtr) < JPU_GBU_SIZE) {
BM_DBG_ERR("fail\n");
return wraparound_bistream_data(jpg, -1);
}
// Generate Huffman table information
for (i = 0; i < 4; i++)
genDecHuffTab(jpg, i);
// Q Idx
temp = jpg->cInfoTab[0][3];
temp = temp << 1 | jpg->cInfoTab[1][3];
temp = temp << 1 | jpg->cInfoTab[2][3];
jpg->Qidx = temp;
// Huff Idx[DC, AC]
temp = jpg->cInfoTab[0][4];
temp = temp << 1 | jpg->cInfoTab[1][4];
temp = temp << 1 | jpg->cInfoTab[2][4];
jpg->huffDcIdx = temp;
temp = jpg->cInfoTab[0][5];
temp = temp << 1 | jpg->cInfoTab[1][5];
temp = temp << 1 | jpg->cInfoTab[2][5];
jpg->huffAcIdx = temp;
switch (jpg->format) {
case FORMAT_420:
jpg->busReqNum = 2;
jpg->mcuBlockNum = 6;
jpg->compNum = 3;
jpg->compInfo[0] = 10;
jpg->compInfo[1] = 5;
jpg->compInfo[2] = 5;
jpg->alignedWidth = ((jpg->picWidth + 15) & ~15);
jpg->alignedHeight = ((jpg->picHeight + 15) & ~15);
jpg->mcuWidth = 16;
jpg->mcuHeight = 16;
break;
case FORMAT_422:
jpg->busReqNum = 3;
jpg->mcuBlockNum = 4;
jpg->compNum = 3;
jpg->compInfo[0] = 9;
jpg->compInfo[1] = 5;
jpg->compInfo[2] = 5;
jpg->alignedWidth = ((jpg->picWidth + 15) & ~15);
jpg->alignedHeight = ((jpg->picHeight + 7) & ~7);
jpg->mcuWidth = 16;
jpg->mcuHeight = 8;
break;
case FORMAT_224:
jpg->busReqNum = 3;
jpg->mcuBlockNum = 4;
jpg->compNum = 3;
jpg->compInfo[0] = 6;
jpg->compInfo[1] = 5;
jpg->compInfo[2] = 5;
jpg->alignedWidth = ((jpg->picWidth + 7) & ~7);
jpg->alignedHeight = ((jpg->picHeight + 15) & ~15);
jpg->mcuWidth = 8;
jpg->mcuHeight = 16;
break;
case FORMAT_444:
jpg->busReqNum = 4;
jpg->mcuBlockNum = 3;
jpg->compNum = 3;
jpg->compInfo[0] = 5;
jpg->compInfo[1] = 5;
jpg->compInfo[2] = 5;
jpg->alignedWidth = ((jpg->picWidth + 7) & ~7);
jpg->alignedHeight = ((jpg->picHeight + 7) & ~7);
jpg->mcuWidth = 8;
jpg->mcuHeight = 8;
break;
case FORMAT_400:
jpg->busReqNum = 4;
jpg->mcuBlockNum = 1;
jpg->compNum = 1;
jpg->compInfo[0] = 5;
jpg->compInfo[1] = 0;
jpg->compInfo[2] = 0;
jpg->alignedWidth = ((jpg->picWidth + 7) & ~7);
jpg->alignedHeight = ((jpg->picHeight + 7) & ~7);
jpg->mcuWidth = 8;
jpg->mcuHeight = 8;
break;
}
return 1;
}
JpgRet CheckJpgEncOpenParam(JpgEncOpenParam *pop)
{
int picWidth;
int picHeight;
if (pop == 0) {
BM_DBG_ERR("JPG_RET_INVALID_PARAM\n");
return JPG_RET_INVALID_PARAM;
}
picWidth = pop->picWidth;
picHeight = pop->picHeight;
if (pop->bitstreamBuffer % 8) {
BM_DBG_ERR("bitstreamBuffer, JPG_RET_INVALID_PARAM\n");
return JPG_RET_INVALID_PARAM;
}
if (pop->bitstreamBufferSize % 1024 ||
pop->bitstreamBufferSize < 1024 ||
pop->bitstreamBufferSize > 16383 * 1024) {
BM_DBG_ERR("JPG_RET_INVALID_PARAM\n");
return JPG_RET_INVALID_PARAM;
}
if (picWidth < 16 || picWidth > MAX_MJPG_PIC_WIDTH) {
BM_DBG_ERR("JPG_RET_INVALID_PARAM, picWidth = %d\n", picWidth);
return JPG_RET_INVALID_PARAM;
}
if (picHeight < 16 || picHeight > MAX_MJPG_PIC_HEIGHT) {
BM_DBG_ERR("JPG_RET_INVALID_PARAM, picHeight = %d\n",
picHeight);
return JPG_RET_INVALID_PARAM;
}
return JPG_RET_SUCCESS;
}
JpgRet CheckJpgEncParam(JpgEncHandle handle, JpgEncParam *param)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
if (param == 0) {
return JPG_RET_INVALID_PARAM;
}
if (pEncInfo->packedFormat != PACKED_FORMAT_NONE) {
if (pEncInfo->packedFormat == PACKED_FORMAT_444) {
if (param->sourceFrame->stride < pEncInfo->openParam.picWidth * 2) {
return JPG_RET_INVALID_PARAM;
}
}
if (pEncInfo->packedFormat == PACKED_FORMAT_444) {
if (param->sourceFrame->stride < pEncInfo->openParam.picWidth * 3) {
return JPG_RET_INVALID_PARAM;
}
}
}
return JPG_RET_SUCCESS;
}
int JpgEncGenHuffTab(JpgEncInfo *pEncInfo, int tabNum)
{
int p, i, l, lastp, si, maxsymbol;
int huffsize[256] = {
0,
};
int huffcode[256] = {
0,
};
int code;
BYTE *bitleng, *huffval;
unsigned int *ehufco, *ehufsi;
bitleng = pEncInfo->pHuffBits[tabNum];
huffval = pEncInfo->pHuffVal[tabNum];
ehufco = pEncInfo->huffCode[tabNum];
ehufsi = pEncInfo->huffSize[tabNum];
maxsymbol = tabNum & 1 ? 256 : 16;
/* Figure C.1: make table of Huffman code length for each symbol */
p = 0;
for (l = 1; l <= 16; l++) {
i = bitleng[l - 1];
if (i < 0 || p + i > maxsymbol)
return 0;
while (i--)
huffsize[p++] = l;
}
lastp = p;
/* Figure C.2: generate the codes themselves */
/* We also validate that the counts represent a legal Huffman code tree.
*/
code = 0;
si = huffsize[0];
p = 0;
while (huffsize[p] != 0) {
while (huffsize[p] == si) {
huffcode[p++] = code;
code++;
}
if (code >= (1 << si))
return 0;
code <<= 1;
si++;
}
/* Figure C.3: generate encoding tables */
/* These are code and size indexed by symbol value */
for (i = 0; i < 256; i++)
ehufsi[i] = 0x00;
for (i = 0; i < 256; i++)
ehufco[i] = 0x00;
for (p = 0; p < lastp; p++) {
i = huffval[p];
if (i < 0 || i >= maxsymbol || ehufsi[i])
return 0;
ehufco[i] = huffcode[p];
ehufsi[i] = huffsize[p];
}
return 1;
}
int JpgEncLoadHuffTab(JpgEncInfo *pEncInfo)
{
int i, j, t;
int huffData;
for (i = 0; i < 4; i++)
JpgEncGenHuffTab(pEncInfo, i);
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0x3);
for (j = 0; j < 4; j++) {
t = (j == 0) ? AC_TABLE_INDEX0
: (j == 1) ? AC_TABLE_INDEX1
: (j == 2) ? DC_TABLE_INDEX0
: DC_TABLE_INDEX1;
for (i = 0; i < 256; i++) {
if ((t == DC_TABLE_INDEX0 || t == DC_TABLE_INDEX1) && i > 15) // DC
break;
if (pEncInfo->huffSize[t][i] == 0 && pEncInfo->huffCode[t][i] == 0)
huffData = 0;
else {
huffData = (pEncInfo->huffSize[t][i] - 1); // Code length (1 ~ 16), 4-bit
huffData = (huffData << 16) | (pEncInfo->huffCode[t][i]); // Code word, 16-bit
}
JpuWriteReg(MJPEG_HUFF_DATA_REG, huffData);
}
}
JpuWriteReg(MJPEG_HUFF_CTRL_REG, 0x0);
return 1;
}
int JpgEncLoadQMatTab(JpgEncInfo *pEncInfo)
{
#ifdef WIN32
__int64 dividend = 0x80000;
__int64 quotient;
#else
long long dividend = 0x80000;
long long quotient;
#endif
int quantID;
int divisor;
int comp;
int i, t;
for (comp = 0; comp < 3; comp++) {
quantID = pEncInfo->pCInfoTab[comp][3];
if (quantID >= 4)
return 0;
t = (comp == 0) ? Q_COMPONENT0
: (comp == 1) ? Q_COMPONENT1 : Q_COMPONENT2;
JpuWriteReg(MJPEG_QMAT_CTRL_REG, 0x3 + t);
for (i = 0; i < 64; i++) {
divisor = pEncInfo->pQMatTab[quantID][i];
quotient = dividend / divisor;
// enhace bit precision & rounding Q
JpuWriteReg(MJPEG_QMAT_DATA_REG, (int)(divisor << 20) | (int)(quotient & 0xFFFFF));
}
JpuWriteReg(MJPEG_QMAT_CTRL_REG, t);
}
return 1;
}
int JpgEncEncodeHeader(JpgEncHandle handle, JpgEncParamSet *para)
{
JpgInst *pJpgInst;
JpgEncInfo *pEncInfo;
// BYTE *p;
int i;
BYTE *pCInfoTab[4];
int frameFormat;
Uint32 val;
pJpgInst = handle;
pEncInfo = &pJpgInst->JpgInfo.encInfo;
if (!para)
return 0;
// p = para->pParaSet;
// len = para->size;
// SOI Header
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, 0xFFD8);
if (!para->disableAPPMarker) {
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, 0xFFE90004);
// APP9 Header
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, pEncInfo->frameIdx);
}
// DRI header
if (pEncInfo->rstIntval) {
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, 0xFFDD0004);
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, pEncInfo->rstIntval);
}
// DQT Header
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, 0xFFDB);
if (para->quantMode == JPG_TBL_NORMAL) {
JpuWriteReg(MJPEG_GBU_PBIT_24_REG, 0x004300);
for (i = 0; i < 64; i += 4) {
val = pEncInfo->pQMatTab[0][i] << 24;
val |= pEncInfo->pQMatTab[0][i + 1] << 16;
val |= pEncInfo->pQMatTab[0][i + 2] << 8;
val |= pEncInfo->pQMatTab[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
if (pEncInfo->format != FORMAT_400) {
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, 0xFFDB0043);
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x01);
for (i = 0; i < 64; i += 4) {
val = pEncInfo->pQMatTab[1][i] << 24;
val |= pEncInfo->pQMatTab[1][i + 1] << 16;
val |= pEncInfo->pQMatTab[1][i + 2] << 8;
val |= pEncInfo->pQMatTab[1][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
}
} else { // if (para->quantMode == JPG_TBL_MERGE)
if (pEncInfo->format != FORMAT_400) {
JpuWriteReg(MJPEG_GBU_PBIT_24_REG, 0x008400);
} else {
JpuWriteReg(MJPEG_GBU_PBIT_24_REG, 0x004300);
}
for (i = 0; i < 64; i += 4) {
val = pEncInfo->pQMatTab[0][i] << 24;
val |= pEncInfo->pQMatTab[0][i + 1] << 16;
val |= pEncInfo->pQMatTab[0][i + 2] << 8;
val |= pEncInfo->pQMatTab[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
if (pEncInfo->format != FORMAT_400) {
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x01);
for (i = 0; i < 64; i += 4) {
val = pEncInfo->pQMatTab[0][i] << 24;
val |= pEncInfo->pQMatTab[0][i + 1] << 16;
val |= pEncInfo->pQMatTab[0][i + 2] << 8;
val |= pEncInfo->pQMatTab[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
}
}
// DHT Header
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, 0xFFC4);
if (para->huffMode == JPG_TBL_NORMAL) {
JpuWriteReg(MJPEG_GBU_PBIT_24_REG, 0x001F00);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[0][i] << 24;
val |= pEncInfo->pHuffBits[0][i + 1] << 16;
val |= pEncInfo->pHuffBits[0][i + 2] << 8;
val |= pEncInfo->pHuffBits[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 12; i += 4) {
val = pEncInfo->pHuffVal[0][i] << 24;
val |= pEncInfo->pHuffVal[0][i + 1] << 16;
val |= pEncInfo->pHuffVal[0][i + 2] << 8;
val |= pEncInfo->pHuffVal[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, 0xFFC400B5);
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x10);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[1][i] << 24;
val |= pEncInfo->pHuffBits[1][i + 1] << 16;
val |= pEncInfo->pHuffBits[1][i + 2] << 8;
val |= pEncInfo->pHuffBits[1][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 160; i += 4) {
val = pEncInfo->pHuffVal[1][i] << 24;
val |= pEncInfo->pHuffVal[1][i + 1] << 16;
val |= pEncInfo->pHuffVal[1][i + 2] << 8;
val |= pEncInfo->pHuffVal[1][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, pEncInfo->pHuffVal[1][160] << 8 | pEncInfo->pHuffVal[1][161]);
if (pEncInfo->format != FORMAT_400) {
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, 0xFFC4001F);
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x01);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[2][i] << 24;
val |= pEncInfo->pHuffBits[2][i + 1] << 16;
val |= pEncInfo->pHuffBits[2][i + 2] << 8;
val |= pEncInfo->pHuffBits[2][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 12; i += 4) {
val = pEncInfo->pHuffVal[2][i] << 24;
val |= pEncInfo->pHuffVal[2][i + 1] << 16;
val |= pEncInfo->pHuffVal[2][i + 2] << 8;
val |= pEncInfo->pHuffVal[2][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, 0xFFC400B5);
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x11);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[3][i] << 24;
val |= pEncInfo->pHuffBits[3][i + 1] << 16;
val |= pEncInfo->pHuffBits[3][i + 2] << 8;
val |= pEncInfo->pHuffBits[3][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 160; i += 4) {
val = pEncInfo->pHuffVal[3][i] << 24;
val |= pEncInfo->pHuffVal[3][i + 1] << 16;
val |= pEncInfo->pHuffVal[3][i + 2] << 8;
val |= pEncInfo->pHuffVal[3][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
val = pEncInfo->pHuffVal[3][160] << 8 | pEncInfo->pHuffVal[3][161];
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, val);
}
} else { // if (para->huffMode == JPG_TBL_MERGE)
if (pEncInfo->format != FORMAT_400) {
JpuWriteReg(MJPEG_GBU_PBIT_24_REG, 0x01A200);
} else {
JpuWriteReg(MJPEG_GBU_PBIT_24_REG, 0x00D400);
}
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[0][i] << 24;
val |= pEncInfo->pHuffBits[0][i + 1] << 16;
val |= pEncInfo->pHuffBits[0][i + 2] << 8;
val |= pEncInfo->pHuffBits[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 12; i += 4) {
val = pEncInfo->pHuffVal[0][i] << 24;
val |= pEncInfo->pHuffVal[0][i + 1] << 16;
val |= pEncInfo->pHuffVal[0][i + 2] << 8;
val |= pEncInfo->pHuffVal[0][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x10);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[1][i] << 24;
val |= pEncInfo->pHuffBits[1][i + 1] << 16;
val |= pEncInfo->pHuffBits[1][i + 2] << 8;
val |= pEncInfo->pHuffBits[1][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 160; i += 4) {
val = pEncInfo->pHuffVal[1][i] << 24;
val |= pEncInfo->pHuffVal[1][i + 1] << 16;
val |= pEncInfo->pHuffVal[1][i + 2] << 8;
val |= pEncInfo->pHuffVal[1][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, pEncInfo->pHuffVal[1][160] << 8 | pEncInfo->pHuffVal[1][161]);
if (pEncInfo->format != FORMAT_400) {
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x01);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[2][i] << 24;
val |= pEncInfo->pHuffBits[2][i + 1] << 16;
val |= pEncInfo->pHuffBits[2][i + 2] << 8;
val |= pEncInfo->pHuffBits[2][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 12; i += 4) {
val = pEncInfo->pHuffVal[2][i] << 24;
val |= pEncInfo->pHuffVal[2][i + 1] << 16;
val |= pEncInfo->pHuffVal[2][i + 2] << 8;
val |= pEncInfo->pHuffVal[2][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x11);
for (i = 0; i < 16; i += 4) {
val = pEncInfo->pHuffBits[3][i] << 24;
val |= pEncInfo->pHuffBits[3][i + 1] << 16;
val |= pEncInfo->pHuffBits[3][i + 2] << 8;
val |= pEncInfo->pHuffBits[3][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
for (i = 0; i < 160; i += 4) {
val = pEncInfo->pHuffVal[3][i] << 24;
val |= pEncInfo->pHuffVal[3][i + 1] << 16;
val |= pEncInfo->pHuffVal[3][i + 2] << 8;
val |= pEncInfo->pHuffVal[3][i + 3];
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, val);
}
val = pEncInfo->pHuffVal[3][160] << 8 | pEncInfo->pHuffVal[3][161];
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, val);
}
}
// SOF header
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, 0xFFC0);
JpuWriteReg(MJPEG_GBU_PBIT_16_REG, (8 + (pEncInfo->compNum * 3)));
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, 0x08);
if (pEncInfo->rotationAngle == 90 || pEncInfo->rotationAngle == 270) {
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, pEncInfo->picWidth << 16 | pEncInfo->picHeight);
} else {
JpuWriteReg(MJPEG_GBU_PBIT_32_REG, pEncInfo->picHeight << 16 | pEncInfo->picWidth);
}
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, pEncInfo->compNum);
frameFormat = pEncInfo->format;
if (pEncInfo->rotationEnable &&
(pEncInfo->rotationAngle == 90 || pEncInfo->rotationAngle == 270)) {
frameFormat = (frameFormat == FORMAT_422)
? FORMAT_224
: (frameFormat == FORMAT_224) ? FORMAT_422
: frameFormat;
}
pCInfoTab[0] = sJpuCompInfoTable[frameFormat];
pCInfoTab[1] = pCInfoTab[0] + 6;
pCInfoTab[2] = pCInfoTab[1] + 6;
pCInfoTab[3] = pCInfoTab[2] + 6;
for (i = 0; i < pEncInfo->compNum; i++) {
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, (i + 1));
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, ((pCInfoTab[i][1] << 4) & 0xF0) + (pCInfoTab[i][2] & 0x0F));
JpuWriteReg(MJPEG_GBU_PBIT_08_REG, pCInfoTab[i][3]);
}
pEncInfo->frameIdx++;
return 1;
}
JpgRet JpgEnterLock(void)
{
jdi_lock();
JpgSetClockGate(1);
return JPG_RET_SUCCESS;
}
JpgRet JpgLeaveLock(void)
{
JpgSetClockGate(0);
jdi_unlock();
return JPG_RET_SUCCESS;
}
JpgRet JpgSetClockGate(Uint32 on)
{
JpgInst *inst;
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip)
return JPG_RET_FAILURE;
inst = jip->pendingInst;
if (inst && !on)
return JPG_RET_SUCCESS;
jdi_set_clock_gate(on);
return JPG_RET_SUCCESS;
}
void SetJpgPendingInst(JpgInst *inst)
{
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip)
return;
jip->pendingInst = inst;
}
void ClearJpgPendingInst(void)
{
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip)
return;
if (jip->pendingInst)
jip->pendingInst = 0;
}
JpgInst *GetJpgPendingInst(void)
{
jpu_instance_pool_t *jip;
jip = (jpu_instance_pool_t *)jdi_get_instance_pool();
if (!jip)
return NULL;
return jip->pendingInst;
}