1835 lines
43 KiB
C
1835 lines
43 KiB
C
|
|
#include "jpuapi.h"
|
|
#include "jpuapifunc.h"
|
|
|
|
#include "jpulog.h"
|
|
#include "dm/device.h"
|
|
#include "timer.h"
|
|
|
|
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
|
|
};
|
|
|
|
int JPU_IsBusy(void)
|
|
{
|
|
Uint32 val;
|
|
|
|
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
if ((val & (1 << INT_JPU_DONE)) || (val & (1 << INT_JPU_ERROR)))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
void JPU_ClrStatus(Uint32 val)
|
|
{
|
|
if (val != 0)
|
|
JpuWriteReg(MJPEG_PIC_STATUS_REG, val);
|
|
}
|
|
|
|
Uint32 JPU_GetStatus(void)
|
|
{
|
|
return JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
}
|
|
|
|
Uint32 JPU_IsInit(void)
|
|
{
|
|
jpu_instance_pool_t *pjip;
|
|
|
|
pjip = (jpu_instance_pool_t *)jdi_get_instance_pool();
|
|
|
|
if (!pjip)
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
Uint32 JPU_WaitInterrupt(int timeout)
|
|
{
|
|
Uint32 reason = 0;
|
|
#ifdef SUPPORT_INTERRUPT
|
|
reason = jdi_wait_interrupt(timeout);
|
|
BM_DBG_TRACE("reason = 0x%X\n", reason);
|
|
#else
|
|
|
|
reason = jdi_wait_interrupt(timeout);
|
|
BM_DBG_TRACE("reason = 0x%X\n", reason);
|
|
|
|
JpgSetClockGate(1);
|
|
|
|
if (reason != (Uint32)-1)
|
|
reason = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
JpgSetClockGate(0);
|
|
#endif
|
|
return reason;
|
|
}
|
|
|
|
int JPU_GetOpenInstanceNum(void)
|
|
{
|
|
jpu_instance_pool_t *pjip;
|
|
|
|
pjip = (jpu_instance_pool_t *)jdi_get_instance_pool();
|
|
if (!pjip)
|
|
return -1;
|
|
|
|
return pjip->jpu_instance_num;
|
|
}
|
|
|
|
JpgRet JPU_Init(void)
|
|
{
|
|
jpu_instance_pool_t *pjip;
|
|
|
|
if (jdi_init() < 0)
|
|
return JPG_RET_FAILURE;
|
|
|
|
pjip = (jpu_instance_pool_t *)jdi_get_instance_pool();
|
|
if (!pjip)
|
|
return JPG_RET_FAILURE;
|
|
|
|
InitJpgInstancePool();
|
|
JPU_SWReset();
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
void JPU_DeInit(void)
|
|
{
|
|
jdi_release();
|
|
}
|
|
|
|
JpgRet JPU_GetVersionInfo(Uint32 *versionInfo)
|
|
{
|
|
|
|
if (JPU_IsInit() == 0) {
|
|
return JPG_RET_NOT_INITIALIZED;
|
|
}
|
|
|
|
*versionInfo = API_VERSION;
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecOpen(JpgDecHandle *pHandle, JpgDecOpenParam *pop)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgDecOpenParam(pop);
|
|
if (ret != JPG_RET_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
ret = GetJpgInstance(&pJpgInst);
|
|
if (ret == JPG_RET_FAILURE) {
|
|
*pHandle = 0;
|
|
JpgLeaveLock();
|
|
return JPG_RET_FAILURE;
|
|
}
|
|
|
|
*pHandle = pJpgInst;
|
|
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
memset(pDecInfo, 0x00, sizeof(JpgDecInfo));
|
|
|
|
pDecInfo->streamWrPtr = pop->bitstreamBuffer;
|
|
pDecInfo->streamRdPtr = pop->bitstreamBuffer;
|
|
|
|
pDecInfo->streamBufStartAddr = pop->bitstreamBuffer;
|
|
pDecInfo->streamBufSize = pop->bitstreamBufferSize;
|
|
pDecInfo->streamBufEndAddr =
|
|
pop->bitstreamBuffer + pop->bitstreamBufferSize;
|
|
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pDecInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamBufEndAddr);
|
|
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pDecInfo->streamRdPtr);
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pDecInfo->streamWrPtr);
|
|
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0);
|
|
|
|
pDecInfo->pBitStream = pop->pBitStream;
|
|
pDecInfo->streamEndian = pop->streamEndian;
|
|
pDecInfo->frameEndian = pop->frameEndian;
|
|
pDecInfo->chroma_interleave = pop->chroma_interleave;
|
|
pDecInfo->packedFormat = pop->packedFormat;
|
|
pDecInfo->roiEnable = pop->roiEnable;
|
|
pDecInfo->roiWidth = pop->roiWidth;
|
|
pDecInfo->roiHeight = pop->roiHeight;
|
|
pDecInfo->roiOffsetX = pop->roiOffsetX;
|
|
pDecInfo->roiOffsetY = pop->roiOffsetY;
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecClose(JpgDecHandle handle)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
|
|
JpgEnterLock();
|
|
FreeJpgInstance(pJpgInst);
|
|
JpgLeaveLock();
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecGetInitialInfo(JpgDecHandle handle, JpgDecInitialInfo *info)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS) {
|
|
BM_DBG_ERR("CheckJpgInstValidity\n");
|
|
return ret;
|
|
}
|
|
|
|
if (info == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
if (JpegDecodeHeader(pDecInfo) <= 0) {
|
|
BM_DBG_ERR("JpegDecodeHeader\n");
|
|
return JPG_RET_FAILURE;
|
|
}
|
|
|
|
info->picWidth = pDecInfo->picWidth;
|
|
info->picHeight = pDecInfo->picHeight;
|
|
info->minFrameBufferCount = 1;
|
|
info->sourceFormat = pDecInfo->format;
|
|
info->ecsPtr = pDecInfo->ecsPtr;
|
|
|
|
JLOG(ERR, "pDecInfo->format %d\n", pDecInfo->format);
|
|
|
|
pDecInfo->initialInfoObtained = 1;
|
|
pDecInfo->minFrameBufferNum = 1;
|
|
|
|
#ifdef MJPEG_ERROR_CONCEAL
|
|
pDecInfo->curRstIdx = 0;
|
|
pDecInfo->nextRstIdx = -1;
|
|
#endif
|
|
|
|
if (pDecInfo->packedFormat == PACKED_FORMAT_444 &&
|
|
pDecInfo->format != FORMAT_444) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
if (pDecInfo->roiEnable) {
|
|
pDecInfo->roiMcuWidth = pDecInfo->roiWidth / pDecInfo->mcuWidth;
|
|
pDecInfo->roiMcuHeight = pDecInfo->roiHeight / pDecInfo->mcuHeight;
|
|
pDecInfo->roiMcuOffsetX = pDecInfo->roiOffsetX / pDecInfo->mcuWidth;
|
|
pDecInfo->roiMcuOffsetY = pDecInfo->roiOffsetY / pDecInfo->mcuHeight;
|
|
|
|
if (pDecInfo->roiOffsetX > pDecInfo->alignedWidth ||
|
|
pDecInfo->roiOffsetY > pDecInfo->alignedHeight ||
|
|
pDecInfo->roiOffsetX + pDecInfo->roiWidth > pDecInfo->alignedWidth ||
|
|
pDecInfo->roiOffsetY + pDecInfo->roiHeight > pDecInfo->alignedHeight)
|
|
return JPG_RET_INVALID_PARAM;
|
|
|
|
if (((pDecInfo->roiOffsetX + pDecInfo->roiWidth) < pDecInfo->mcuWidth) ||
|
|
((pDecInfo->roiOffsetY + pDecInfo->roiHeight) < pDecInfo->mcuHeight))
|
|
return JPG_RET_INVALID_PARAM;
|
|
|
|
info->roiFrameWidth = pDecInfo->roiMcuWidth * pDecInfo->mcuWidth;
|
|
info->roiFrameHeight = pDecInfo->roiMcuHeight * pDecInfo->mcuHeight;
|
|
info->roiFrameOffsetX = pDecInfo->roiMcuOffsetX * pDecInfo->mcuWidth;
|
|
info->roiFrameOffsetY = pDecInfo->roiMcuOffsetY * pDecInfo->mcuHeight;
|
|
info->roiMCUSize = pDecInfo->mcuWidth;
|
|
}
|
|
info->colorComponents = pDecInfo->compNum;
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecRegisterFrameBuffer(JpgDecHandle handle, FrameBuffer *bufArray,
|
|
int num, int strideY, int strideC)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
if (!pDecInfo->initialInfoObtained) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
if (bufArray == 0) {
|
|
return JPG_RET_INVALID_FRAME_BUFFER;
|
|
}
|
|
|
|
if (num < pDecInfo->minFrameBufferNum) {
|
|
return JPG_RET_INSUFFICIENT_FRAME_BUFFERS;
|
|
}
|
|
if (pDecInfo->usePartial && pDecInfo->bufNum == 0) {
|
|
return JPG_RET_INSUFFICIENT_FRAME_BUFFERS;
|
|
}
|
|
if (pDecInfo->usePartial && num < pDecInfo->bufNum) {
|
|
return JPG_RET_INSUFFICIENT_FRAME_BUFFERS;
|
|
}
|
|
|
|
if (!pDecInfo->roiEnable) {
|
|
if (strideY < pDecInfo->picWidth >> 3 || strideY % 8 != 0)
|
|
return JPG_RET_INVALID_STRIDE;
|
|
}
|
|
|
|
pDecInfo->frameBufPool = bufArray;
|
|
pDecInfo->numFrameBuffers = num;
|
|
pDecInfo->stride = strideY;
|
|
pDecInfo->strideY = strideY;
|
|
pDecInfo->strideC = strideC;
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecGetBitstreamBuffer(JpgDecHandle handle, PhysicalAddress *prdPrt,
|
|
PhysicalAddress *pwrPtr, int *size)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
PhysicalAddress rdPtr;
|
|
PhysicalAddress wrPtr;
|
|
int room;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
if (prdPrt == 0 || pwrPtr == 0 || size == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
if (GetJpgPendingInst() == pJpgInst) {
|
|
rdPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
|
|
} else {
|
|
rdPtr = pDecInfo->streamRdPtr;
|
|
}
|
|
|
|
wrPtr = pDecInfo->streamWrPtr;
|
|
|
|
if (wrPtr == pDecInfo->streamBufStartAddr) {
|
|
if (pDecInfo->frameOffset == 0) {
|
|
room = (pDecInfo->streamBufEndAddr -= pDecInfo->streamBufStartAddr);
|
|
} else {
|
|
room = (pDecInfo->frameOffset);
|
|
}
|
|
} else {
|
|
room = (pDecInfo->streamBufEndAddr - wrPtr);
|
|
}
|
|
|
|
room = ((room >> 9) << 9); // multiple of 512
|
|
|
|
*prdPrt = rdPtr;
|
|
*pwrPtr = wrPtr;
|
|
|
|
*size = room;
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecUpdateBitstreamBuffer(JpgDecHandle handle, int size)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
PhysicalAddress wrPtr;
|
|
PhysicalAddress rdPtr;
|
|
JpgRet ret;
|
|
int val = 0;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
wrPtr = pDecInfo->streamWrPtr;
|
|
|
|
if (size == 0) {
|
|
val = (wrPtr - pDecInfo->streamBufStartAddr) / 256;
|
|
if ((wrPtr - pDecInfo->streamBufStartAddr) % 256)
|
|
val = val + 1;
|
|
if (GetJpgPendingInst() == pJpgInst)
|
|
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, (1 << 31 | val));
|
|
pDecInfo->streamEndflag = 1;
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgSetClockGate(1);
|
|
|
|
wrPtr = pDecInfo->streamWrPtr;
|
|
wrPtr += size;
|
|
|
|
if (wrPtr == pDecInfo->streamBufEndAddr) {
|
|
wrPtr = pDecInfo->streamBufStartAddr;
|
|
}
|
|
|
|
pDecInfo->streamWrPtr = wrPtr;
|
|
|
|
if (GetJpgPendingInst() == pJpgInst) {
|
|
rdPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
|
|
|
|
if (rdPtr == (pDecInfo->streamBufEndAddr & 0xffffffff)) {
|
|
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
|
|
}
|
|
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, wrPtr);
|
|
if (wrPtr == pDecInfo->streamBufStartAddr) {
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamBufEndAddr);
|
|
} else {
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, wrPtr);
|
|
}
|
|
} else {
|
|
rdPtr = pDecInfo->streamRdPtr;
|
|
}
|
|
|
|
pDecInfo->streamRdPtr = rdPtr;
|
|
|
|
JpgSetClockGate(0);
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_SWReset(void)
|
|
{
|
|
Uint32 val;
|
|
PhysicalAddress streamBufStartAddr;
|
|
PhysicalAddress streamBufEndAddr;
|
|
PhysicalAddress streamWrPtr;
|
|
PhysicalAddress streamRdPtr;
|
|
|
|
JpgEnterLock();
|
|
|
|
streamBufStartAddr = JpuReadReg(MJPEG_BBC_BAS_ADDR_REG);
|
|
streamBufEndAddr = JpuReadReg(MJPEG_BBC_END_ADDR_REG);
|
|
streamWrPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
|
|
streamRdPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
|
|
|
|
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_INIT));
|
|
|
|
do {
|
|
val = JpuReadReg(MJPEG_PIC_START_REG);
|
|
} while ((val & (1 << JPG_START_INIT)) == (1 << JPG_START_INIT));
|
|
|
|
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, streamBufEndAddr);
|
|
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, streamRdPtr);
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, streamWrPtr);
|
|
|
|
JpgLeaveLock();
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_HWReset(void)
|
|
{
|
|
if (jdi_hw_reset() < 0)
|
|
return JPG_RET_FAILURE;
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecIssueStop(JpgDecHandle handle)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
// JpgDecInfo * pDecInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
// pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
if (pJpgInst != GetJpgPendingInst()) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
JpgSetClockGate(1);
|
|
JpuWriteReg(MJPEG_PIC_START_REG, 1 << JPG_START_STOP);
|
|
JpgSetClockGate(0);
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecCompleteStop(JpgDecHandle handle)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
// JpgDecInfo * pDecInfo;
|
|
JpgRet ret;
|
|
Uint32 val;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
// pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
if (pJpgInst != GetJpgPendingInst()) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
JpgSetClockGate(1);
|
|
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
if (val & (1 << INT_JPU_BIT_BUF_STOP)) {
|
|
SetJpgPendingInst(0);
|
|
JpgSetClockGate(0);
|
|
} else {
|
|
JpgSetClockGate(0);
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecSetRdPtr(JpgDecHandle handle, PhysicalAddress addr, int updateWrPtr)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
JpgEnterLock();
|
|
|
|
if (GetJpgPendingInst()) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FRAME_NOT_COMPLETE;
|
|
}
|
|
|
|
pDecInfo->streamRdPtr = addr;
|
|
if (updateWrPtr)
|
|
pDecInfo->streamWrPtr = addr;
|
|
|
|
pDecInfo->frameOffset = addr - pDecInfo->streamBufStartAddr;
|
|
pDecInfo->consumeByte = 0;
|
|
|
|
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pDecInfo->streamRdPtr);
|
|
|
|
JpgLeaveLock();
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecStartOneFrame(JpgDecHandle handle, JpgDecParam *param)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
Uint32 rotMir;
|
|
JpgRet ret;
|
|
Uint32 val;
|
|
int i;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
if (pDecInfo->frameBufPool == 0) { // This means frame buffers have not been registered.
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
rotMir = 0;
|
|
if (pDecInfo->rotationEnable) {
|
|
rotMir |= 0x10; // Enable rotator
|
|
switch (pDecInfo->rotationAngle) {
|
|
case 0:
|
|
rotMir |= 0x0;
|
|
break;
|
|
|
|
case 90:
|
|
rotMir |= 0x1;
|
|
break;
|
|
|
|
case 180:
|
|
rotMir |= 0x2;
|
|
break;
|
|
|
|
case 270:
|
|
rotMir |= 0x3;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pDecInfo->mirrorEnable) {
|
|
rotMir |= 0x10; // Enable rotator
|
|
switch (pDecInfo->mirrorDirection) {
|
|
case MIRDIR_NONE:
|
|
rotMir |= 0x0;
|
|
break;
|
|
|
|
case MIRDIR_VER:
|
|
rotMir |= 0x4;
|
|
break;
|
|
|
|
case MIRDIR_HOR:
|
|
rotMir |= 0x8;
|
|
break;
|
|
|
|
case MIRDIR_HOR_VER:
|
|
rotMir |= 0xc;
|
|
break;
|
|
}
|
|
}
|
|
JpgEnterLock();
|
|
|
|
if (GetJpgPendingInst()) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FRAME_NOT_COMPLETE;
|
|
}
|
|
|
|
#ifdef MJPEG_ERROR_CONCEAL
|
|
// Error Concealment
|
|
if (pDecInfo->errInfo.bError) {
|
|
// error conceal main function
|
|
val = JpegDecodeConcealError(pDecInfo);
|
|
if (val == -1) {
|
|
// stream buffer wrap around in error cases.
|
|
pDecInfo->frameOffset = 0;
|
|
pDecInfo->nextOffset = 0;
|
|
|
|
// end of stream
|
|
if (pDecInfo->streamEndflag == 1) {
|
|
pDecInfo->frameOffset = -1;
|
|
SetJpgPendingInst(pJpgInst);
|
|
return JPG_RET_EOS;
|
|
}
|
|
// request data
|
|
JpgLeaveLock();
|
|
return JPG_RET_BIT_EMPTY;
|
|
}
|
|
|
|
// init GBU
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
|
|
|
|
val = pDecInfo->huffAcIdx << 10 | pDecInfo->huffDcIdx << 7 | pDecInfo->userHuffTab << 6;
|
|
val |= (JPU_CHECK_WRITE_RESPONSE_BVALID_SIGNAL << 2) | 0;
|
|
JpuWriteReg(MJPEG_PIC_CTRL_REG, val);
|
|
val = pDecInfo->mcuBlockNum << 16 | pDecInfo->compNum << 12;
|
|
val |= pDecInfo->compInfo[0] << 8 | pDecInfo->compInfo[1] << 4 | pDecInfo->compInfo[2];
|
|
JpuWriteReg(MJPEG_MCU_INFO_REG, val);
|
|
JpuWriteReg(MJPEG_RST_INTVAL_REG, pDecInfo->rstIntval);
|
|
|
|
JpgDecGramSetup(pDecInfo);
|
|
|
|
JpuWriteReg(MJPEG_DPCM_DIFF_Y_REG, 0);
|
|
JpuWriteReg(MJPEG_DPCM_DIFF_CB_REG, 0);
|
|
JpuWriteReg(MJPEG_DPCM_DIFF_CR_REG, 0);
|
|
|
|
JpuWriteReg(MJPEG_GBU_FF_RPTR_REG, pDecInfo->bitPtr);
|
|
JpuWriteReg(MJPEG_GBU_CTRL_REG, 3);
|
|
|
|
val = (pDecInfo->setPosX << 16) | (pDecInfo->setPosY);
|
|
JpuWriteReg(MJPEG_PIC_SETMB_REG, val);
|
|
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC));
|
|
|
|
SetJpgPendingInst(pJpgInst);
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
if (pDecInfo->frameOffset < 0) {
|
|
SetJpgPendingInst(pJpgInst);
|
|
return JPG_RET_EOS;
|
|
}
|
|
|
|
val = JpegDecodeHeader(pDecInfo);
|
|
if (val == 0) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FAILURE;
|
|
}
|
|
|
|
if (val == -2) { // wrap around case
|
|
pDecInfo->frameOffset = 0;
|
|
pDecInfo->ecsPtr = 0;
|
|
#ifdef MJPEG_ERROR_CONCEAL
|
|
pDecInfo->nextOffset = 0;
|
|
#endif
|
|
val = JpegDecodeHeader(pDecInfo);
|
|
if (val == 0) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FAILURE;
|
|
}
|
|
}
|
|
|
|
if (val == -1) { // stream empty case
|
|
if (pDecInfo->streamEndflag == 1) {
|
|
SetJpgPendingInst(pJpgInst);
|
|
pDecInfo->frameOffset = -1;
|
|
return JPG_RET_EOS;
|
|
}
|
|
JpgLeaveLock();
|
|
return JPG_RET_BIT_EMPTY;
|
|
}
|
|
|
|
if (pDecInfo->streamRdPtr == pDecInfo->streamBufEndAddr) {
|
|
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
|
|
}
|
|
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pDecInfo->streamWrPtr);
|
|
if (pDecInfo->streamWrPtr == pDecInfo->streamBufStartAddr) {
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamBufEndAddr);
|
|
} else {
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pDecInfo->streamWrPtr);
|
|
}
|
|
|
|
JLOG(INFO, "pDecInfo->streamBufStartAddr %p\n",
|
|
(void *)pDecInfo->streamBufStartAddr);
|
|
|
|
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pDecInfo->streamBufStartAddr);
|
|
|
|
if (pDecInfo->streamEndflag == 1) {
|
|
val = JpuReadReg(MJPEG_BBC_STRM_CTRL_REG);
|
|
if ((val & (1 << 31)) == 0) {
|
|
val = (pDecInfo->streamWrPtr -
|
|
pDecInfo->streamBufStartAddr) /
|
|
256;
|
|
if ((pDecInfo->streamWrPtr -
|
|
pDecInfo->streamBufStartAddr) %
|
|
256)
|
|
val = val + 1;
|
|
|
|
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, (1 << 31 | val));
|
|
}
|
|
} else {
|
|
JpuWriteReg(MJPEG_BBC_STRM_CTRL_REG, 0);
|
|
}
|
|
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_TT_CNT_REG + 4, 0);
|
|
JpuWriteReg(MJPEG_PIC_ERRMB_REG, 0);
|
|
val = pDecInfo->huffAcIdx << 10 | pDecInfo->huffDcIdx << 7 | pDecInfo->userHuffTab << 6;
|
|
val |= ((JPU_CHECK_WRITE_RESPONSE_BVALID_SIGNAL << 2) | pDecInfo->usePartial);
|
|
JpuWriteReg(MJPEG_PIC_CTRL_REG, val);
|
|
|
|
JpuWriteReg(MJPEG_PIC_SIZE_REG, (pDecInfo->alignedWidth << 16) | pDecInfo->alignedHeight);
|
|
JpuWriteReg(MJPEG_ROT_INFO_REG, 0);
|
|
JpuWriteReg(MJPEG_OP_INFO_REG, pDecInfo->lineNum << 16 | pDecInfo->bufNum << 3 | pDecInfo->busReqNum);
|
|
val = pDecInfo->mcuBlockNum << 16 | pDecInfo->compNum << 12;
|
|
val |= pDecInfo->compInfo[0] << 8 | pDecInfo->compInfo[1] << 4 | pDecInfo->compInfo[2];
|
|
JpuWriteReg(MJPEG_MCU_INFO_REG, val);
|
|
|
|
if (pDecInfo->chroma_interleave == 0)
|
|
val = 0;
|
|
else if (pDecInfo->chroma_interleave == 1)
|
|
val = 2;
|
|
else
|
|
val = 3;
|
|
if (pDecInfo->packedFormat == PACKED_FORMAT_NONE) {
|
|
val |= (pDecInfo->frameEndian << 6) | (0 << 5) | (0 << 4);
|
|
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
|
|
} else if (pDecInfo->packedFormat == PACKED_FORMAT_444) {
|
|
val |= (pDecInfo->frameEndian << 6) | (1 << 5) | (0 << 4) | (0 << 2);
|
|
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
|
|
} else {
|
|
val |= (pDecInfo->frameEndian << 6) | (0 << 5) | (1 << 4) | ((pDecInfo->packedFormat - 1) << 2);
|
|
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
|
|
}
|
|
JpuWriteReg(MJPEG_RST_INTVAL_REG, pDecInfo->rstIntval);
|
|
if (param) {
|
|
if (param->scaleDownRatioWidth > 0)
|
|
pDecInfo->iHorScaleMode = param->scaleDownRatioWidth;
|
|
if (param->scaleDownRatioHeight > 0)
|
|
pDecInfo->iVerScaleMode = param->scaleDownRatioHeight;
|
|
}
|
|
if (pDecInfo->iHorScaleMode | pDecInfo->iVerScaleMode)
|
|
val = ((pDecInfo->iHorScaleMode & 0x3) << 2) |
|
|
((pDecInfo->iVerScaleMode & 0x3)) | 0x10;
|
|
else {
|
|
val = 0;
|
|
}
|
|
JpuWriteReg(MJPEG_SCL_INFO_REG, val);
|
|
|
|
if (pDecInfo->userHuffTab) {
|
|
if (!JpgDecHuffTabSetUp(pDecInfo)) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
}
|
|
|
|
if (!JpgDecQMatTabSetUp(pDecInfo)) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
JpgDecGramSetup(pDecInfo);
|
|
|
|
JpuWriteReg(MJPEG_RST_INDEX_REG, 0); // RST index at the beginning.
|
|
JpuWriteReg(MJPEG_RST_COUNT_REG, 0);
|
|
|
|
JpuWriteReg(MJPEG_DPCM_DIFF_Y_REG, 0);
|
|
JpuWriteReg(MJPEG_DPCM_DIFF_CB_REG, 0);
|
|
JpuWriteReg(MJPEG_DPCM_DIFF_CR_REG, 0);
|
|
|
|
JpuWriteReg(MJPEG_GBU_FF_RPTR_REG, pDecInfo->bitPtr);
|
|
JpuWriteReg(MJPEG_GBU_CTRL_REG, 3);
|
|
|
|
JpuWriteReg(MJPEG_ROT_INFO_REG, rotMir);
|
|
|
|
if (rotMir & 1) {
|
|
pDecInfo->format = (pDecInfo->format == FORMAT_422)
|
|
? FORMAT_224
|
|
: (pDecInfo->format == FORMAT_224)
|
|
? FORMAT_422
|
|
: pDecInfo->format;
|
|
}
|
|
|
|
if (rotMir & 0x10) {
|
|
JpuWriteReg(MJPEG_DPB_BASE00_REG, pDecInfo->rotatorOutput.bufY);
|
|
JpuWriteReg(MJPEG_DPB_BASE01_REG,
|
|
pDecInfo->rotatorOutput.bufCb);
|
|
JpuWriteReg(MJPEG_DPB_BASE02_REG,
|
|
pDecInfo->rotatorOutput.bufCr);
|
|
} else if (pDecInfo->usePartial) {
|
|
PhysicalAddress addr;
|
|
|
|
val = (pDecInfo->frameIdx % (pDecInfo->numFrameBuffers / pDecInfo->bufNum));
|
|
for (i = 0; i < pDecInfo->bufNum; i++) {
|
|
addr = pDecInfo->frameBufPool[(val * pDecInfo->bufNum) + i].bufY;
|
|
JpuWriteReg(MJPEG_DPB_BASE00_REG + (i * 12), addr);
|
|
addr = pDecInfo->frameBufPool[(val * pDecInfo->bufNum) + i].bufCb;
|
|
JpuWriteReg(MJPEG_DPB_BASE01_REG + (i * 12), addr);
|
|
addr = pDecInfo->frameBufPool[(val * pDecInfo->bufNum) + i].bufCr;
|
|
JpuWriteReg(MJPEG_DPB_BASE02_REG + (i * 12), addr);
|
|
}
|
|
} else {
|
|
val = (pDecInfo->frameIdx % pDecInfo->numFrameBuffers);
|
|
JpuWriteReg(MJPEG_DPB_BASE00_REG, pDecInfo->frameBufPool[val].bufY);
|
|
JpuWriteReg(MJPEG_DPB_BASE01_REG, pDecInfo->frameBufPool[val].bufCb);
|
|
JpuWriteReg(MJPEG_DPB_BASE02_REG, pDecInfo->frameBufPool[val].bufCr);
|
|
}
|
|
|
|
if (pDecInfo->rotationEnable) {
|
|
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pDecInfo->rotatorStride);
|
|
val = (pDecInfo->format == FORMAT_420 ||
|
|
pDecInfo->format == FORMAT_422 ||
|
|
pDecInfo->format == FORMAT_400)
|
|
? 2
|
|
: 1;
|
|
if (pDecInfo->chroma_interleave)
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, (pDecInfo->rotatorStride / (int)val) * 2);
|
|
else
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pDecInfo->rotatorStride / (int)val);
|
|
} else {
|
|
|
|
CVI_JPG_DBG("packedFormat = %d\n", pDecInfo->packedFormat);
|
|
if (pDecInfo->packedFormat == PACKED_FORMAT_NONE && pDecInfo->format == FORMAT_420) {
|
|
CVI_JPG_DBG("strideY = %d, strideC = %d\n", pDecInfo->strideY, pDecInfo->strideC);
|
|
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pDecInfo->strideY);
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pDecInfo->strideC);
|
|
} else {
|
|
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pDecInfo->stride);
|
|
if (pDecInfo->chroma_interleave)
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, (pDecInfo->stride / (int)val) * 2);
|
|
else
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pDecInfo->stride / (int)val);
|
|
}
|
|
}
|
|
if (pDecInfo->roiEnable) {
|
|
JpuWriteReg(MJPEG_CLP_INFO_REG, 1);
|
|
JpuWriteReg(MJPEG_CLP_BASE_REG, pDecInfo->roiOffsetX << 16 | pDecInfo->roiOffsetY); // pixel unit
|
|
val = (pDecInfo->roiMcuWidth * pDecInfo->mcuWidth) << 16;
|
|
val |= pDecInfo->roiMcuHeight * pDecInfo->mcuHeight;
|
|
JpuWriteReg(MJPEG_CLP_SIZE_REG, val); // pixel Unit
|
|
} else {
|
|
JpuWriteReg(MJPEG_CLP_INFO_REG, 0);
|
|
}
|
|
|
|
if (pJpgInst->loggingEnable)
|
|
jdi_log(JDI_LOG_CMD_PICRUN, 1);
|
|
|
|
BM_DBG_FLOW("JPG_START_PIC\n");
|
|
|
|
#ifdef PROFILE_PERFORMANCE
|
|
timer_meter_start();
|
|
#endif
|
|
|
|
JpuWriteReg(MJPEG_PIC_STATUS_REG, JpuReadReg(MJPEG_PIC_STATUS_REG));
|
|
|
|
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC));
|
|
|
|
SetJpgPendingInst(pJpgInst);
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecGetOutputInfo(JpgDecHandle handle, JpgDecOutputInfo *info)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
Uint32 val = 0;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return ret;
|
|
}
|
|
|
|
if (info == 0) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
|
|
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
if (pJpgInst != GetJpgPendingInst()) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
if (pDecInfo->frameOffset < 0) {
|
|
info->numOfErrMBs = 0;
|
|
info->decodingSuccess = 1;
|
|
info->indexFrameDisplay = -1;
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
if (pDecInfo->roiEnable) {
|
|
info->decPicWidth = pDecInfo->roiMcuWidth * pDecInfo->mcuWidth;
|
|
info->decPicHeight =
|
|
pDecInfo->roiMcuHeight * pDecInfo->mcuHeight;
|
|
} else {
|
|
info->decPicWidth = pDecInfo->alignedWidth;
|
|
info->decPicHeight = pDecInfo->alignedHeight;
|
|
}
|
|
|
|
info->decPicWidth >>= pDecInfo->iHorScaleMode;
|
|
info->decPicHeight >>= pDecInfo->iVerScaleMode;
|
|
|
|
info->indexFrameDisplay =
|
|
(pDecInfo->frameIdx % pDecInfo->numFrameBuffers);
|
|
#ifdef MJPEG_ERROR_CONCEAL
|
|
info->consumedByte =
|
|
pDecInfo->gbuStartPtr + (JpuReadReg(MJPEG_GBU_TT_CNT_REG)) / 8;
|
|
#else
|
|
info->consumedByte = (JpuReadReg(MJPEG_GBU_TT_CNT_REG)) / 8;
|
|
#endif
|
|
pDecInfo->streamRdPtr = JpuReadReg(MJPEG_BBC_RD_PTR_REG);
|
|
pDecInfo->consumeByte = info->consumedByte - 16 - pDecInfo->ecsPtr;
|
|
info->bytePosFrameStart = pDecInfo->frameOffset;
|
|
info->ecsPtr = pDecInfo->ecsPtr;
|
|
|
|
pDecInfo->ecsPtr = 0;
|
|
pDecInfo->frameIdx++;
|
|
|
|
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
if (val & (1 << INT_JPU_DONE)) {
|
|
info->decodingSuccess = 1;
|
|
info->numOfErrMBs = 0;
|
|
|
|
#ifdef MJPEG_ERROR_CONCEAL
|
|
pDecInfo->errInfo.bError = 0;
|
|
pDecInfo->nextOffset = 0;
|
|
pDecInfo->gbuStartPtr = 0;
|
|
#endif
|
|
} else if (val & (1 << INT_JPU_ERROR)) {
|
|
|
|
info->numOfErrMBs = JpuReadReg(MJPEG_PIC_ERRMB_REG);
|
|
info->decodingSuccess = 0;
|
|
|
|
#ifdef MJPEG_ERROR_CONCEAL
|
|
// info->numOfErrMBs =
|
|
// JpuReadReg(MJPEG_PIC_ERRMB_REG);
|
|
pDecInfo->errInfo.bError = 1;
|
|
pDecInfo->errInfo.errPosY = info->numOfErrMBs & 0xFFF;
|
|
pDecInfo->errInfo.errPosX = (info->numOfErrMBs >> 12) & 0xFFF;
|
|
|
|
// set search point to find next rstMarker from origin of frame
|
|
// buffer by host
|
|
pDecInfo->nextOffset = (info->consumedByte) & (~7);
|
|
|
|
// prevent to find same position.
|
|
if (pDecInfo->currOffset == pDecInfo->nextOffset)
|
|
pDecInfo->nextOffset += JPU_GBU_SIZE;
|
|
#endif
|
|
}
|
|
|
|
if (val != 0)
|
|
JpuWriteReg(MJPEG_PIC_STATUS_REG, val);
|
|
|
|
if (pJpgInst->loggingEnable) {
|
|
jdi_log(JDI_LOG_CMD_PICRUN, 0);
|
|
}
|
|
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_DecGiveCommand(JpgDecHandle handle, JpgCommand cmd, void *param)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgDecInfo *pDecInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pDecInfo = &pJpgInst->JpgInfo.decInfo;
|
|
switch (cmd) {
|
|
case ENABLE_JPG_ROTATION: {
|
|
if (pDecInfo->roiEnable) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
if (pDecInfo->rotatorStride == 0) {
|
|
return JPG_RET_ROTATOR_STRIDE_NOT_SET;
|
|
}
|
|
pDecInfo->rotationEnable = 1;
|
|
break;
|
|
}
|
|
|
|
case DISABLE_JPG_ROTATION: {
|
|
pDecInfo->rotationEnable = 0;
|
|
break;
|
|
}
|
|
|
|
case ENABLE_JPG_MIRRORING: {
|
|
if (pDecInfo->rotatorStride == 0) {
|
|
return JPG_RET_ROTATOR_STRIDE_NOT_SET;
|
|
}
|
|
pDecInfo->mirrorEnable = 1;
|
|
break;
|
|
}
|
|
case DISABLE_JPG_MIRRORING: {
|
|
pDecInfo->mirrorEnable = 0;
|
|
break;
|
|
}
|
|
case SET_JPG_MIRROR_DIRECTION: {
|
|
|
|
JpgMirrorDirection mirDir;
|
|
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
mirDir = *(JpgMirrorDirection *)param;
|
|
if (!(mirDir >= MIRDIR_NONE && mirDir <= MIRDIR_HOR_VER)) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
pDecInfo->mirrorDirection = mirDir;
|
|
|
|
break;
|
|
}
|
|
case SET_JPG_ROTATION_ANGLE: {
|
|
int angle;
|
|
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
angle = *(int *)param;
|
|
if (angle != 0 && angle != 90 && angle != 180 && angle != 270) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pDecInfo->rotationAngle = angle;
|
|
break;
|
|
}
|
|
|
|
case SET_JPG_ROTATOR_OUTPUT: {
|
|
FrameBuffer *frame;
|
|
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
frame = (FrameBuffer *)param;
|
|
pDecInfo->rotatorOutput = *frame;
|
|
pDecInfo->rotatorOutputValid = 1;
|
|
break;
|
|
}
|
|
|
|
case SET_JPG_ROTATOR_STRIDE: {
|
|
int stride;
|
|
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
stride = *(int *)param;
|
|
if (stride % 8 != 0 || stride == 0) {
|
|
return JPG_RET_INVALID_STRIDE;
|
|
}
|
|
|
|
if (pDecInfo->rotationAngle == 90 ||
|
|
pDecInfo->rotationAngle == 270) {
|
|
if (pDecInfo->alignedHeight > stride) {
|
|
return JPG_RET_INVALID_STRIDE;
|
|
}
|
|
} else {
|
|
if (pDecInfo->alignedWidth > stride) {
|
|
return JPG_RET_INVALID_STRIDE;
|
|
}
|
|
}
|
|
|
|
pDecInfo->rotatorStride = stride;
|
|
break;
|
|
}
|
|
case SET_JPG_SCALE_HOR: {
|
|
int scale;
|
|
|
|
scale = *(int *)param;
|
|
if (pDecInfo->alignedWidth < 128 ||
|
|
pDecInfo->alignedHeight < 128) {
|
|
if (scale) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
}
|
|
|
|
pDecInfo->iHorScaleMode = scale;
|
|
break;
|
|
}
|
|
case SET_JPG_SCALE_VER: {
|
|
int scale;
|
|
|
|
scale = *(int *)param;
|
|
if (pDecInfo->alignedWidth < 128 ||
|
|
pDecInfo->alignedHeight < 128) {
|
|
if (scale) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
}
|
|
pDecInfo->iVerScaleMode = scale;
|
|
break;
|
|
}
|
|
case SET_JPG_USE_PARTIAL_MODE: {
|
|
int enable;
|
|
|
|
enable = *(int *)param;
|
|
pDecInfo->usePartial = enable;
|
|
|
|
break;
|
|
}
|
|
case SET_JPG_PARTIAL_FRAME_NUM: {
|
|
int frame;
|
|
|
|
if (pDecInfo->stride != 0) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
frame = *(int *)param;
|
|
pDecInfo->bufNum = frame;
|
|
|
|
break;
|
|
}
|
|
case SET_JPG_PARTIAL_LINE_NUM: {
|
|
int line;
|
|
|
|
if (pDecInfo->stride != 0) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
line = *(int *)param;
|
|
pDecInfo->lineNum = line;
|
|
|
|
break;
|
|
}
|
|
case ENABLE_LOGGING: {
|
|
pJpgInst->loggingEnable = 1;
|
|
} break;
|
|
case DISABLE_LOGGING: {
|
|
pJpgInst->loggingEnable = 0;
|
|
} break;
|
|
default:
|
|
return JPG_RET_INVALID_COMMAND;
|
|
}
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncOpen(JpgEncHandle *pHandle, JpgEncOpenParam *pop)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
JpgRet ret;
|
|
int i;
|
|
|
|
ret = CheckJpgEncOpenParam(pop);
|
|
if (ret != JPG_RET_SUCCESS) {
|
|
BM_DBG_ERR("CheckJpgEncOpenParam\n");
|
|
return ret;
|
|
}
|
|
|
|
JpgEnterLock();
|
|
ret = GetJpgInstance(&pJpgInst);
|
|
if (ret == JPG_RET_FAILURE) {
|
|
BM_DBG_ERR("GetJpgInstance\n");
|
|
*pHandle = 0;
|
|
JpgLeaveLock();
|
|
return JPG_RET_FAILURE;
|
|
}
|
|
|
|
*pHandle = pJpgInst;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
memset(pEncInfo, 0x00, sizeof(JpgEncInfo));
|
|
pEncInfo->openParam = *pop;
|
|
pEncInfo->streamRdPtr = pop->bitstreamBuffer;
|
|
pEncInfo->streamWrPtr = pop->bitstreamBuffer;
|
|
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pEncInfo->streamWrPtr);
|
|
pEncInfo->streamBufStartAddr = pop->bitstreamBuffer;
|
|
pEncInfo->streamBufSize = pop->bitstreamBufferSize;
|
|
pEncInfo->streamBufEndAddr =
|
|
pop->bitstreamBuffer + pop->bitstreamBufferSize;
|
|
pEncInfo->streamEndian = pop->streamEndian;
|
|
pEncInfo->frameEndian = pop->frameEndian;
|
|
pEncInfo->chroma_interleave = pop->chroma_interleave;
|
|
|
|
pEncInfo->format = pEncInfo->openParam.sourceFormat;
|
|
pEncInfo->picWidth = pEncInfo->openParam.picWidth;
|
|
pEncInfo->picHeight = pEncInfo->openParam.picHeight;
|
|
// Picture size alignment
|
|
if (pEncInfo->format == FORMAT_420 || pEncInfo->format == FORMAT_422)
|
|
pEncInfo->alignedWidth = ((pEncInfo->picWidth + 15) / 16) * 16;
|
|
else
|
|
pEncInfo->alignedWidth = ((pEncInfo->picWidth + 7) / 8) * 8;
|
|
|
|
if (pEncInfo->format == FORMAT_420 || pEncInfo->format == FORMAT_224)
|
|
pEncInfo->alignedHeight =
|
|
((pEncInfo->picHeight + 15) / 16) * 16;
|
|
else
|
|
pEncInfo->alignedHeight = ((pEncInfo->picHeight + 7) / 8) * 8;
|
|
pEncInfo->rstIntval = pEncInfo->openParam.restartInterval;
|
|
|
|
for (i = 0; i < 4; i++)
|
|
pEncInfo->pHuffVal[i] = pEncInfo->openParam.huffVal[i];
|
|
for (i = 0; i < 4; i++)
|
|
pEncInfo->pHuffBits[i] = pEncInfo->openParam.huffBits[i];
|
|
for (i = 0; i < 4; i++)
|
|
pEncInfo->pQMatTab[i] = pEncInfo->openParam.qMatTab[i];
|
|
|
|
pEncInfo->pCInfoTab[0] = sJpuCompInfoTable[/*2*/ pEncInfo->format];
|
|
pEncInfo->pCInfoTab[1] = pEncInfo->pCInfoTab[0] + 6;
|
|
pEncInfo->pCInfoTab[2] = pEncInfo->pCInfoTab[1] + 6;
|
|
pEncInfo->pCInfoTab[3] = pEncInfo->pCInfoTab[2] + 6;
|
|
|
|
if (pop->packedFormat == PACKED_FORMAT_444 &&
|
|
pEncInfo->format != FORMAT_444) {
|
|
BM_DBG_ERR("PACKED_FORMAT_444\n");
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
pEncInfo->packedFormat = pop->packedFormat;
|
|
|
|
JpgLeaveLock();
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncClose(JpgEncHandle handle)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
JpgEnterLock();
|
|
|
|
if (GetJpgPendingInst()) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FRAME_NOT_COMPLETE;
|
|
}
|
|
|
|
pJpgInst = handle;
|
|
JpuWriteReg(MJPEG_BBC_FLUSH_CMD_REG, 0);
|
|
FreeJpgInstance(pJpgInst);
|
|
JpgLeaveLock();
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncGetInitialInfo(JpgEncHandle handle, JpgEncInitialInfo *info)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
if (info == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pJpgInst = handle;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
if (pEncInfo->initialInfoObtained) {
|
|
return JPG_RET_CALLED_BEFORE;
|
|
}
|
|
|
|
JpgEnterLock();
|
|
|
|
if (GetJpgPendingInst()) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FRAME_NOT_COMPLETE;
|
|
}
|
|
|
|
if (pEncInfo->format == FORMAT_400) {
|
|
pEncInfo->compInfo[1] = 0;
|
|
pEncInfo->compInfo[2] = 0;
|
|
} else {
|
|
pEncInfo->compInfo[1] = 5;
|
|
pEncInfo->compInfo[2] = 5;
|
|
}
|
|
|
|
if (pEncInfo->format == FORMAT_400)
|
|
pEncInfo->compNum = 1;
|
|
else
|
|
pEncInfo->compNum = 3;
|
|
|
|
if (pEncInfo->format == FORMAT_420) {
|
|
pEncInfo->mcuBlockNum = 6;
|
|
pEncInfo->compInfo[0] = 10;
|
|
pEncInfo->busReqNum = 2;
|
|
} else if (pEncInfo->format == FORMAT_422) {
|
|
pEncInfo->mcuBlockNum = 4;
|
|
pEncInfo->busReqNum = 3;
|
|
pEncInfo->compInfo[0] = 9;
|
|
} else if (pEncInfo->format == FORMAT_224) {
|
|
pEncInfo->mcuBlockNum = 4;
|
|
pEncInfo->busReqNum = 3;
|
|
pEncInfo->compInfo[0] = 6;
|
|
} else if (pEncInfo->format == FORMAT_444) {
|
|
pEncInfo->mcuBlockNum = 3;
|
|
pEncInfo->compInfo[0] = 5;
|
|
pEncInfo->busReqNum = 4;
|
|
} else if (pEncInfo->format == FORMAT_400) {
|
|
pEncInfo->mcuBlockNum = 1;
|
|
pEncInfo->busReqNum = 4;
|
|
pEncInfo->compInfo[0] = 5;
|
|
}
|
|
|
|
info->minFrameBufferCount = 0;
|
|
info->colorComponents = pEncInfo->compNum;
|
|
|
|
pEncInfo->initialInfo = *info;
|
|
pEncInfo->initialInfoObtained = 1;
|
|
|
|
JpgLeaveLock();
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncGetBitstreamBuffer(JpgEncHandle handle, PhysicalAddress *prdPrt,
|
|
PhysicalAddress *pwrPtr, int *size)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
if (prdPrt == 0 || pwrPtr == 0 || size == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pJpgInst = handle;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
JpgSetClockGate(1);
|
|
*prdPrt = pEncInfo->streamRdPtr;
|
|
|
|
if (GetJpgPendingInst() == pJpgInst) {
|
|
*pwrPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
|
|
} else {
|
|
*pwrPtr = pEncInfo->streamWrPtr;
|
|
}
|
|
*size = *pwrPtr - *prdPrt;
|
|
JpgSetClockGate(0);
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncUpdateBitstreamBuffer(JpgEncHandle handle, int size)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
PhysicalAddress rdPtr;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
JpgSetClockGate(1);
|
|
rdPtr = pEncInfo->streamRdPtr;
|
|
rdPtr += size;
|
|
|
|
if (rdPtr == pEncInfo->streamBufEndAddr) {
|
|
rdPtr = pEncInfo->streamBufStartAddr;
|
|
}
|
|
|
|
pEncInfo->streamRdPtr = pEncInfo->streamBufStartAddr;
|
|
|
|
if (GetJpgPendingInst() == pJpgInst) {
|
|
pEncInfo->streamWrPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
|
|
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
|
|
JpuWriteReg(MJPEG_BBC_EXT_ADDR_REG,
|
|
pEncInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pEncInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pEncInfo->streamBufStartAddr);
|
|
}
|
|
JpgSetClockGate(0);
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncIssueStop(JpgEncHandle handle)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
// JpgEncInfo *pEncInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
// pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
if (pJpgInst != GetJpgPendingInst()) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
JpgSetClockGate(1);
|
|
JpuWriteReg(MJPEG_PIC_START_REG, 1 << JPG_START_STOP);
|
|
JpgSetClockGate(0);
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncCompleteStop(JpgEncHandle handle)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
// JpgEncInfo *pEncInfo;
|
|
JpgRet ret;
|
|
Uint32 val;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
// pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
if (pJpgInst != GetJpgPendingInst()) {
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
JpgSetClockGate(1);
|
|
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
if (val & (1 << INT_JPU_BIT_BUF_STOP)) {
|
|
SetJpgPendingInst(0);
|
|
JpgSetClockGate(0);
|
|
} else {
|
|
JpgSetClockGate(0);
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncStartOneFrame(JpgEncHandle handle, JpgEncParam *param)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
FrameBuffer *pBasFrame;
|
|
Uint32 rotMirEnable;
|
|
Uint32 rotMirMode;
|
|
JpgRet ret;
|
|
Uint32 val;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
ret = CheckJpgEncParam(handle, param);
|
|
if (ret != JPG_RET_SUCCESS) {
|
|
return ret;
|
|
}
|
|
|
|
pBasFrame = param->sourceFrame;
|
|
rotMirEnable = 0;
|
|
rotMirMode = 0;
|
|
if (pEncInfo->rotationEnable) {
|
|
rotMirEnable = 0x10; // Enable rotator
|
|
switch (pEncInfo->rotationAngle) {
|
|
case 0:
|
|
rotMirMode |= 0x0;
|
|
break;
|
|
|
|
case 90:
|
|
rotMirMode |= 0x1;
|
|
break;
|
|
|
|
case 180:
|
|
rotMirMode |= 0x2;
|
|
break;
|
|
|
|
case 270:
|
|
rotMirMode |= 0x3;
|
|
break;
|
|
}
|
|
}
|
|
if (pEncInfo->mirrorEnable) {
|
|
rotMirEnable = 0x10; // Enable rotator
|
|
|
|
switch (pEncInfo->mirrorDirection) {
|
|
case MIRDIR_NONE:
|
|
rotMirMode |= 0x0;
|
|
break;
|
|
|
|
case MIRDIR_VER:
|
|
rotMirMode |= 0x4;
|
|
break;
|
|
|
|
case MIRDIR_HOR:
|
|
rotMirMode |= 0x8;
|
|
break;
|
|
|
|
case MIRDIR_HOR_VER:
|
|
rotMirMode |= 0xc;
|
|
break;
|
|
}
|
|
}
|
|
|
|
JpgEnterLock();
|
|
|
|
if (GetJpgPendingInst()) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_FRAME_NOT_COMPLETE;
|
|
}
|
|
|
|
// off ROI enable due to not supported feature for encoder.
|
|
JpuWriteReg(MJPEG_CLP_INFO_REG, 0);
|
|
|
|
JpuWriteReg(MJPEG_BBC_BAS_ADDR_REG, pEncInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_END_ADDR_REG, pEncInfo->streamBufEndAddr);
|
|
JpuWriteReg(MJPEG_BBC_WR_PTR_REG, pEncInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_RD_PTR_REG, pEncInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_CUR_POS_REG, 0);
|
|
JpuWriteReg(MJPEG_BBC_DATA_CNT_REG, 256 / 4); // 64 * 4 byte == 32 * 8 byte
|
|
JpuWriteReg(MJPEG_BBC_EXT_ADDR_REG, pEncInfo->streamBufStartAddr);
|
|
JpuWriteReg(MJPEG_BBC_INT_ADDR_REG, 0);
|
|
|
|
JpuWriteReg(MJPEG_GBU_BT_PTR_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_WD_PTR_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_BBSR_REG, 0);
|
|
JpuWriteReg(MJPEG_GBU_CTRL_REG, 0);
|
|
|
|
JpuWriteReg(MJPEG_GBU_BBER_REG, ((256 / 4) * 2) - 1);
|
|
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
|
|
val = 0x18 | pEncInfo->usePartial | (JPU_CHECK_WRITE_RESPONSE_BVALID_SIGNAL << 2);
|
|
JpuWriteReg(MJPEG_PIC_CTRL_REG, val);
|
|
JpuWriteReg(MJPEG_SCL_INFO_REG, 0);
|
|
if (pEncInfo->chroma_interleave == 0)
|
|
val = 0;
|
|
else if (pEncInfo->chroma_interleave == 1)
|
|
val = 2;
|
|
else
|
|
val = 3;
|
|
if (pEncInfo->packedFormat == PACKED_FORMAT_NONE) {
|
|
val |= (pEncInfo->frameEndian << 6) | (0 << 5) | (0 << 4) | (0 << 2);
|
|
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
|
|
} else if (pEncInfo->packedFormat == PACKED_FORMAT_444) {
|
|
val |= (pEncInfo->frameEndian << 6) | (1 << 5) | (0 << 4) | (0 << 2);
|
|
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
|
|
} else {
|
|
val |= (pEncInfo->frameEndian << 6) | (0 << 5) | (1 << 4) | ((pEncInfo->packedFormat - 1) << 2);
|
|
JpuWriteReg(MJPEG_DPB_CONFIG_REG, val);
|
|
}
|
|
|
|
JpuWriteReg(MJPEG_RST_INTVAL_REG, pEncInfo->rstIntval);
|
|
JpuWriteReg(MJPEG_BBC_CTRL_REG, (pEncInfo->streamEndian << 1) | 1);
|
|
val = pEncInfo->partiallineNum << 16 | pEncInfo->partialBufNum << 3 | pEncInfo->busReqNum;
|
|
JpuWriteReg(MJPEG_OP_INFO_REG, val);
|
|
|
|
// Load HUFFTab
|
|
if (!JpgEncLoadHuffTab(pEncInfo)) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
// Load QMATTab
|
|
if (!JpgEncLoadQMatTab(pEncInfo)) {
|
|
JpgLeaveLock();
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
JpgEncEncodeHeader(handle, pEncInfo->paraSet);
|
|
// although rotator is enable, this picture size must not be changed
|
|
// from widh to height.
|
|
JpuWriteReg(MJPEG_PIC_SIZE_REG, pEncInfo->alignedWidth << 16 | pEncInfo->alignedHeight);
|
|
JpuWriteReg(MJPEG_ROT_INFO_REG, (rotMirEnable | rotMirMode));
|
|
|
|
val = pEncInfo->mcuBlockNum << 16 | pEncInfo->compNum << 12;
|
|
val |= pEncInfo->compInfo[0] << 8 | pEncInfo->compInfo[1] << 4 | pEncInfo->compInfo[2];
|
|
JpuWriteReg(MJPEG_MCU_INFO_REG, val);
|
|
|
|
// JpgEncGbuResetReg
|
|
JpuWriteReg(MJPEG_GBU_CTRL_REG, pEncInfo->stuffByteEnable << 3); // stuffing "FF" data where frame end
|
|
|
|
if (pEncInfo->usePartial) {
|
|
int i;
|
|
|
|
for (i = 0; i < pEncInfo->partialBufNum; i++) {
|
|
JpuWriteReg(MJPEG_DPB_BASE00_REG + (i * 12), pBasFrame[i].bufY);
|
|
JpuWriteReg(MJPEG_DPB_BASE01_REG + (i * 12), pBasFrame[i].bufCb);
|
|
JpuWriteReg(MJPEG_DPB_BASE02_REG + (i * 12), pBasFrame[i].bufCr);
|
|
}
|
|
|
|
} else {
|
|
JpuWriteReg(MJPEG_DPB_BASE00_REG, pBasFrame->bufY);
|
|
JpuWriteReg(MJPEG_DPB_BASE01_REG, pBasFrame->bufCb);
|
|
JpuWriteReg(MJPEG_DPB_BASE02_REG, pBasFrame->bufCr);
|
|
}
|
|
|
|
JpuWriteReg(MJPEG_DPB_YSTRIDE_REG, pBasFrame->stride);
|
|
|
|
if (pEncInfo->format == FORMAT_420 || pEncInfo->format == FORMAT_422 || pEncInfo->format == FORMAT_400)
|
|
val = 2;
|
|
else
|
|
val = 1;
|
|
|
|
if (pEncInfo->chroma_interleave)
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, (pBasFrame->stride / (int)val) * 2);
|
|
else
|
|
JpuWriteReg(MJPEG_DPB_CSTRIDE_REG, pBasFrame->stride / (int)val);
|
|
|
|
if (pJpgInst->loggingEnable)
|
|
jdi_log(JDI_LOG_CMD_PICRUN, 1);
|
|
|
|
#ifdef PROFILE_PERFORMANCE
|
|
timer_meter_start();
|
|
#endif
|
|
|
|
JpuWriteReg(MJPEG_PIC_STATUS_REG, JpuReadReg(MJPEG_PIC_STATUS_REG));
|
|
if (pEncInfo->usePartial)
|
|
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC) | (1 << JPG_START_PARTIAL));
|
|
else
|
|
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PIC));
|
|
|
|
SetJpgPendingInst(pJpgInst);
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncGetOutputInfo(JpgEncHandle handle, JpgEncOutputInfo *info)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
Uint32 val;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return ret;
|
|
}
|
|
|
|
if (info == 0) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pJpgInst = handle;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
|
|
if (pJpgInst != GetJpgPendingInst()) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
val = JpuReadReg(MJPEG_PIC_STATUS_REG);
|
|
|
|
if ((val & 0x4) >> 2) {
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_WRONG_CALL_SEQUENCE;
|
|
}
|
|
|
|
if (val != 0)
|
|
JpuWriteReg(MJPEG_PIC_STATUS_REG, val);
|
|
|
|
info->bitstreamBuffer = pEncInfo->streamBufStartAddr;
|
|
info->bitstreamSize = JpuReadReg(MJPEG_BBC_WR_PTR_REG) - pEncInfo->streamBufStartAddr;
|
|
pEncInfo->streamWrPtr = JpuReadReg(MJPEG_BBC_WR_PTR_REG);
|
|
|
|
JpuWriteReg(MJPEG_BBC_FLUSH_CMD_REG, 0);
|
|
|
|
if (pJpgInst->loggingEnable)
|
|
jdi_log(JDI_LOG_CMD_PICRUN, 0);
|
|
|
|
SetJpgPendingInst(0);
|
|
JpgLeaveLock();
|
|
return JPG_RET_SUCCESS;
|
|
}
|
|
|
|
JpgRet JPU_EncGiveCommand(JpgEncHandle handle, JpgCommand cmd, void *param)
|
|
{
|
|
JpgInst *pJpgInst;
|
|
JpgEncInfo *pEncInfo;
|
|
JpgRet ret;
|
|
|
|
ret = CheckJpgInstValidity(handle);
|
|
if (ret != JPG_RET_SUCCESS)
|
|
return ret;
|
|
|
|
pJpgInst = handle;
|
|
pEncInfo = &pJpgInst->JpgInfo.encInfo;
|
|
switch (cmd) {
|
|
case ENABLE_JPG_ROTATION: {
|
|
pEncInfo->rotationEnable = 1;
|
|
} break;
|
|
case DISABLE_JPG_ROTATION: {
|
|
pEncInfo->rotationEnable = 0;
|
|
} break;
|
|
case ENABLE_JPG_MIRRORING: {
|
|
pEncInfo->mirrorEnable = 1;
|
|
} break;
|
|
case DISABLE_JPG_MIRRORING: {
|
|
pEncInfo->mirrorEnable = 0;
|
|
} break;
|
|
case SET_JPG_MIRROR_DIRECTION: {
|
|
JpgMirrorDirection mirDir;
|
|
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
mirDir = *(JpgMirrorDirection *)param;
|
|
if (!(mirDir >= MIRDIR_NONE && mirDir <= MIRDIR_HOR_VER)) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
pEncInfo->mirrorDirection = mirDir;
|
|
} break;
|
|
case SET_JPG_ROTATION_ANGLE: {
|
|
int angle;
|
|
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
angle = *(int *)param;
|
|
if (angle != 0 && angle != 90 && angle != 180 && angle != 270) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
if (pEncInfo->initialInfoObtained && (angle == 90 || angle == 270)) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
pEncInfo->rotationAngle = angle;
|
|
} break;
|
|
case ENC_JPG_GET_HEADER: {
|
|
if (param == 0) {
|
|
return JPG_RET_INVALID_PARAM;
|
|
}
|
|
|
|
pEncInfo->paraSet = (JpgEncParamSet *)param;
|
|
break;
|
|
}
|
|
case SET_JPG_USE_PARTIAL_MODE: {
|
|
int enable;
|
|
|
|
enable = *(int *)param;
|
|
pEncInfo->usePartial = enable;
|
|
|
|
break;
|
|
}
|
|
case SET_JPG_PARTIAL_FRAME_NUM: {
|
|
int frame;
|
|
|
|
frame = *(int *)param;
|
|
pEncInfo->partialBufNum = frame;
|
|
|
|
break;
|
|
}
|
|
case SET_JPG_PARTIAL_LINE_NUM: {
|
|
int line;
|
|
|
|
line = *(int *)param;
|
|
pEncInfo->partiallineNum = line;
|
|
|
|
break;
|
|
}
|
|
case SET_JPG_ENCODE_NEXT_LINE: {
|
|
JpuWriteReg(MJPEG_PIC_START_REG, (1 << JPG_START_PARTIAL));
|
|
break;
|
|
}
|
|
case SET_JPG_USE_STUFFING_BYTE_FF: {
|
|
int enable;
|
|
|
|
enable = *(int *)param;
|
|
pEncInfo->stuffByteEnable = enable;
|
|
break;
|
|
}
|
|
case ENABLE_LOGGING: {
|
|
pJpgInst->loggingEnable = 1;
|
|
break;
|
|
}
|
|
case DISABLE_LOGGING: {
|
|
pJpgInst->loggingEnable = 0;
|
|
break;
|
|
}
|
|
default:
|
|
return JPG_RET_INVALID_COMMAND;
|
|
}
|
|
|
|
return JPG_RET_SUCCESS;
|
|
}
|