Files
MAX_CARLINK_A270S/MXC_A27-PCB4.5-270T/lib/hx170dec/src/mfcapi.c
2025-01-21 16:49:37 +08:00

434 lines
11 KiB
C

#include <string.h>
#include <stdio.h>
#include "FreeRTOS.h"
#include "dwl.h"
#include "h264decapi.h"
#include "jpegdecapi.h"
#include "jpegdeccontainer.h"
#include "mfcapi.h"
#include "mmu.h"
#include "include/amt630hv100.h"
#include "sysctl.h"
#include "semphr.h"
#define JPEG_BUF_COUNTS 2
static u32 g_picDecodeNumber = 0;
static u32 g_JpegYBusAddress = 0;
static u32 g_JpegCbCrBusAddress = 0;
static DWLLinearMem_t g_JpegYMemInfo[JPEG_BUF_COUNTS] = {0};
static u32 g_JpegMemIndex = 0;
static void MFCSwitchIramMode(int en)
{
#if 0
static SemaphoreHandle_t MfcIramMutex = NULL;
if(!MfcIramMutex)
MfcIramMutex = xSemaphoreCreateMutex();
if(MfcIramMutex)
xSemaphoreTake(MfcIramMutex, portMAX_DELAY);
//0 MFC ram use as iram; 1 MFC ram use MFC REF buffer
u32 val = readl(REGS_SYSCTL_BASE + 0x78);
if(en)
val |= (1<<0);
else
val &= ~(1<<0);
writel(val, REGS_SYSCTL_BASE + 0x78);
if(MfcIramMutex)
xSemaphoreGive(MfcIramMutex);
#else
portENTER_CRITICAL();
//0 MFC ram use as iram; 1 MFC ram use MFC REF buffer
u32 val = readl(REGS_SYSCTL_BASE + 0x78);
if(en)
val |= (1<<0);
else
val &= ~(1<<0);
writel(val, REGS_SYSCTL_BASE + 0x78);
portEXIT_CRITICAL();
#endif
}
int MFCH264Decode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *outBuffer)
{
H264DecRet ret;
H264DecRet picRet;
H264DecInput decIn;
H264DecOutput decOut;
static H264DecInfo decInfo;
H264DecPicture decPic;
decIn.dataLen = inBuffer->size;
decIn.pStream = (u8*)inBuffer->virtualAddress;
decIn.streamBusAddress = inBuffer->busAddress;
do
{
/* Picture ID is the picture number in decoding order */
decIn.picId = g_picDecodeNumber;
/* decode the stream data */
ret = H264DecDecode(handle->decInst, &decIn, &decOut);
switch(ret)
{
case H264DEC_HDRS_RDY:
/* read stream info */
H264DecGetInfo(handle->decInst, &decInfo);
outBuffer->codedWidth = decInfo.picWidth;
outBuffer->codedHeight = decInfo.picHeight;
break;
case H264DEC_ADVANCED_TOOLS:
/* Arbitrary Slice Order/multiple slice groups noticed */
/* in the stream. The decoder has to reallocate resources */
break;
case H264DEC_PIC_DECODED: /* a picture was decoded */
case H264DEC_PENDING_FLUSH:
g_picDecodeNumber++;
do {
if(outBuffer->num >= MAX_OUTFRAME_NUM)
return 0;
picRet = H264DecNextPicture(handle->decInst, &decPic, 0);
if (picRet != H264DEC_PIC_RDY) {
break;
}
outBuffer->buffer[outBuffer->num].keyPicture =
decPic.isIdrPicture;
outBuffer->buffer[outBuffer->num].yBusAddress =
decPic.outputPictureBusAddress;
outBuffer->buffer[outBuffer->num].pyVirAddress =
decPic.pOutputPicture;
outBuffer->frameWidth = decInfo.picWidth;
outBuffer->frameHeight = decInfo.picHeight;
outBuffer->num++;
} while (picRet == H264DEC_PIC_RDY);
break;
case H264DEC_STRM_PROCESSED:
/* Input stream was processed but no picture is ready */
break;
case H264DEC_MEMFAIL:
return -1;
default:
/* all other cases are errors where decoding cannot continue */
return -1;
}
if(decOut.dataLeft == 0)
{
break;
}
else
{
/* data left undecoded */
decIn.dataLen = decOut.dataLeft;
decIn.pStream = decOut.pStrmCurrPos;
decIn.streamBusAddress = decOut.strmCurrBusAddress;
}
}while ((ret != H264DEC_STRM_PROCESSED) && (decOut.dataLeft > 0));
return 0;
}
int MFCJpegDecode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *outBuffer)
{
JpegDecInst decoder;
JpegDecRet infoRet;
JpegDecInput DecIn;
JpegDecImageInfo DecImgInf;
JpegDecOutput DecOut;
int ret = 0;
int i;
infoRet = JpegDecInit(&decoder);
if(infoRet !=JPEGDEC_OK) {
printf("JpegDecInit failure %d.\n", infoRet);
return -1;
}
handle->decInst = (void*)decoder;
DecIn.decImageType = JPEGDEC_IMAGE;
DecIn.sliceMbSet = 0;
DecIn.bufferSize = 0;
DecIn.streamLength = inBuffer->size;
DecIn.streamBuffer.busAddress= inBuffer->busAddress;
DecIn.streamBuffer.pVirtualAddress = inBuffer->virtualAddress;
g_JpegYBusAddress = 0;
for (i = 0; i < JPEG_BUF_COUNTS; i++) {
if(g_JpegYMemInfo[i].busAddress == 0)
{
if(DWLMallocLinear(((JpegDecContainer*)handle->decInst)->dwl, MAX_OUTFRAME_WIDTH*MAX_OUTFRAME_HEIGHT*2,
&g_JpegYMemInfo[i]) == DWL_ERROR)
{
printf("Jpeg DWLMallocLinear y failure.\n");
goto end;
}
}
}
/* Get image information of the JFIF */
infoRet = JpegDecGetImageInfo(handle->decInst,
&DecIn,
&DecImgInf);
if(infoRet !=JPEGDEC_OK)
{
printf("\rJpegDecGetImageInfo failure.\n");
goto end;
}
DecIn.pictureBufferY.busAddress = g_JpegYMemInfo[g_JpegMemIndex].busAddress;
DecIn.pictureBufferY.pVirtualAddress = g_JpegYMemInfo[g_JpegMemIndex].virtualAddress;
DecIn.pictureBufferCbCr.busAddress = g_JpegYMemInfo[g_JpegMemIndex].busAddress + DecImgInf.outputWidth * DecImgInf.outputHeight;
DecIn.pictureBufferCbCr.pVirtualAddress = (u32*)((u32)g_JpegYMemInfo[g_JpegMemIndex].virtualAddress +
DecImgInf.outputWidth * DecImgInf.outputHeight);
DecIn.pictureBufferCr.busAddress = 0;
DecIn.pictureBufferCr.pVirtualAddress = 0;
g_JpegMemIndex = !g_JpegMemIndex;
/* Decode JFIF */
infoRet = JpegDecDecode(handle->decInst, &DecIn, &DecOut);
if(infoRet != JPEGDEC_FRAME_READY)
{
printf("\rJpegDecDecode failure, ret=%d\n", infoRet);
if (infoRet == JPEGDEC_MEMFAIL)
ret = -1;
goto end;
}
ret = 0;
outBuffer->outputFormat = DecImgInf.outputFormat;
outBuffer->codedWidth = DecImgInf.displayWidth;
outBuffer->codedHeight = DecImgInf.displayHeight;
outBuffer->buffer[0].keyPicture = 1;
g_JpegYBusAddress = DecOut.outputPictureY.busAddress;
g_JpegCbCrBusAddress = DecOut.outputPictureCbCr.busAddress;
if (g_JpegYBusAddress) {
outBuffer->num = 1;
outBuffer->buffer[0].yBusAddress = g_JpegYBusAddress;
outBuffer->buffer[0].cbcrBusAddress = g_JpegCbCrBusAddress;
outBuffer->buffer[0].pyVirAddress = DecOut.outputPictureY.pVirtualAddress;
outBuffer->buffer[0].pcbcrVirAddress = DecOut.outputPictureCbCr.pVirtualAddress;
outBuffer->frameWidth = DecImgInf.outputWidth;
outBuffer->frameHeight = DecImgInf.outputHeight;
}
end:
JpegDecRelease((JpegDecInst)handle->decInst);
return ret;
}
void JpegReleaseBuffer(void)
{
int i;
for(i = 0; i < JPEG_BUF_COUNTS; i++) {
if(g_JpegYMemInfo[i].virtualAddress != NULL)
//vPortFree(g_JpegYMemInfo[i].virtualAddress - 0x10000000/4);
vPortFree((u32 *)UNCACHED_VIRT_TO_PHT(g_JpegYMemInfo[i].virtualAddress));
memset(&g_JpegYMemInfo[i], 0, sizeof(g_JpegYMemInfo[i]));
}
}
int mfc_jpegdec(JpegHeaderInfo *jpegInfo)
{
JpegDecInst decoder;
JpegDecRet infoRet;
JpegDecInput DecIn;
JpegDecImageInfo DecImgInf;
JpegDecOutput DecOut;
int ret = -1;
MFCSwitchIramMode(1);
infoRet = JpegDecInit(&decoder);
if(infoRet !=JPEGDEC_OK) {
printf("JpegDecInit failure %d.\n", infoRet);
goto exit;
}
jpegInfo->handle->decInst = (void*)decoder;
DecIn.decImageType = JPEGDEC_IMAGE;
DecIn.sliceMbSet = 0;
DecIn.bufferSize = 0;
DecIn.streamLength = jpegInfo->jpg_size;
DecIn.streamBuffer.busAddress= jpegInfo->jpg_addr;
DecIn.streamBuffer.pVirtualAddress = (u32 *)PHY_TO_UNCACHED_VIRT(jpegInfo->jpg_addr);
/* Get image information of the JFIF */
infoRet = JpegDecGetImageInfo(jpegInfo->handle->decInst,
&DecIn,
&DecImgInf);
if(infoRet !=JPEGDEC_OK)
{
printf("\rJpegDecGetImageInfo failure.\n");
goto end;
}
DecIn.pictureBufferY.busAddress = jpegInfo->dec_addry;
DecIn.pictureBufferY.pVirtualAddress = (u32 *)PHY_TO_UNCACHED_VIRT(jpegInfo->dec_addry);
DecIn.pictureBufferCbCr.busAddress = DecIn.pictureBufferY.busAddress +
DecImgInf.outputWidth * DecImgInf.outputHeight;
DecIn.pictureBufferCbCr.pVirtualAddress = (u32*)((u32)DecIn.pictureBufferY.pVirtualAddress +
DecImgInf.outputWidth * DecImgInf.outputHeight);
DecIn.pictureBufferCr.busAddress = 0;
DecIn.pictureBufferCr.pVirtualAddress = 0;
/* Decode JFIF */
infoRet = JpegDecDecode(jpegInfo->handle->decInst, &DecIn, &DecOut);
if(infoRet != JPEGDEC_FRAME_READY)
{
printf("\rJpegDecDecode failure, ret=%d\n", infoRet);
if (infoRet == JPEGDEC_MEMFAIL)
ret = -1;
goto end;
}
ret = 0;
jpegInfo->dec_format = DecImgInf.outputFormat;
jpegInfo->jpg_width = DecImgInf.displayWidth;
jpegInfo->jpg_height = DecImgInf.displayHeight;
if((jpegInfo->dec_format == JPEGDEC_YCbCr420_SEMIPLANAR) || (jpegInfo->dec_format == JPEGDEC_YCbCr422_SEMIPLANAR)) {
jpegInfo->dec_width = (jpegInfo->jpg_width + 0xF) & (~0xF);
jpegInfo->dec_height = (jpegInfo->jpg_height + 0xF) & (~0xF);
} else {
jpegInfo->dec_width = (jpegInfo->jpg_width + 0x7) & (~0x7);
jpegInfo->dec_height = (jpegInfo->jpg_height + 0x7) & (~0x7);
}
jpegInfo->dec_addry = DecOut.outputPictureY.busAddress;
jpegInfo->dec_addru = DecOut.outputPictureCbCr.busAddress;
jpegInfo->dec_addrv = 0;
end:
JpegDecRelease((JpegDecInst)jpegInfo->handle->decInst);
exit:
MFCSwitchIramMode(0);
return ret;
}
MFCHandle* mfc_init(int streamType)
{
MFCHandle *handle = NULL;
void *decInst = NULL;
switch(streamType) {
case RAW_STRM_TYPE_H264: {
H264DecInst decoder;
H264DecRet infoRet;
g_picDecodeNumber = 0;
infoRet = H264DecInit(&decoder, 0, 0, 1);
if(infoRet != H264DEC_OK) {
printf("H264DecInit failure.\n");
return NULL;
}
decInst = (void*)decoder;
break;
}
case RAW_STRM_TYPE_H264_NOREORDER: {
H264DecInst decoder;
H264DecRet infoRet;
g_picDecodeNumber = 0;
infoRet = H264DecInit(&decoder, 1, 0, 1);
if(infoRet != H264DEC_OK) {
printf("H264DecInit failure.\n");
return NULL;
}
decInst = (void*)decoder;
break;
}
case RAW_STRM_TYPE_JPEG:
break;
default:
printf("MFCDecode unsupported format.\n");
return NULL;
}
handle = (MFCHandle*)pvPortMalloc(sizeof(MFCHandle));
if (!handle)
return NULL;
memset(handle, 0, sizeof(MFCHandle));
handle->decInst = decInst;
handle->streamType = streamType;
return handle;
}
int mfc_decode(MFCHandle *handle, DWLLinearMem_t *inBuffer, OutFrameBuffer *outBuffer)
{
int ret = 0;
if (handle == NULL) {
printf("Invalid handle.\n");
return -1;
}
MFCSwitchIramMode(1);
outBuffer->num = 0;
switch(handle->streamType) {
case RAW_STRM_TYPE_H264:
case RAW_STRM_TYPE_H264_NOREORDER:
ret= MFCH264Decode(handle, inBuffer, outBuffer);
break;
case RAW_STRM_TYPE_JPEG:
ret= MFCJpegDecode(handle, inBuffer, outBuffer);
break;
default:
printf("MFCDecode unsupported format.\n");
ret = -1;
break;
}
MFCSwitchIramMode(0);
return ret;
}
void mfc_uninit(MFCHandle *handle)
{
if (handle == NULL) {
printf("Invalid handle.\n");
return ;
}
switch(handle->streamType)
{
case RAW_STRM_TYPE_H264:
case RAW_STRM_TYPE_H264_NOREORDER:
if(handle->decInst)
H264DecRelease((H264DecInst)handle->decInst);
break;
case RAW_STRM_TYPE_JPEG:
JpegReleaseBuffer();
break;
default:
printf("MFCRelease unsupported format.\n");
break;
}
vPortFree(handle);
}