/**************************************************************************//** * @file jpegDec.c * @brief JPEG Decode function shows the decode control flow * * SPDX-License-Identifier: Apache-2.0 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. *****************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include "N9H20.h" #include "jpegSample.h" extern LCDFORMATEX lcdInfo; extern CHAR g_u8String[100]; extern UINT32 g_u32StringIndex; UINT32 g_u32DecFormat = JPEG_DEC_PRIMARY_PACKET_RGB565; /* Decode Output format */ PUINT8 g_pu8JpegBuffer; /* The source bit stream data for decoding */ UINT32 g_u32JpegBuffer; PUINT8 g_pu8DecFrameBuffer; /* The buffer for decoding output */ /*-----------------------------------------------------------------------*/ /* Decode Input Wait parameter */ /*-----------------------------------------------------------------------*/ UINT8 g_au8DecInputWaitBuffer[DEC_IPW_BUFFERSIZE] __attribute__((aligned(32))); /* Buffer for Decode Input Wait */ UINT32 g_u32IpwUsedSize = 0; /* Buffer Control parameter for Decode Input Wait (bitstream size put to Bitstream Buffer )*/ UINT32 g_u32BitstreamSize = 0; /* JPEG Bitstream Size for Decode Input Wait */ /*-----------------------------------------------------------------------*/ /* Decode Output Wait parameter */ /*-----------------------------------------------------------------------*/ PUINT8 apBuffer[100]; /* Decode Output buffer pointer array */ UINT32 g_u32OpwUsedSize; /* JPEG Bitstream Size for Decode Input Wait */ UINT32 u32MCU_Line; /* One MCU Line data size */ UINT32 u32TotalSize; /* Total size for JPEG Decode Ouput */ UINT32 g_u32OpwBufferIndex = 0; /* Decode output Buffer index */ /*-----------------------------------------------------------------------*/ /* Decode Function */ /*-----------------------------------------------------------------------*/ VOID JpegDecTest (void) { INT len; UINT32 u32BitstreamSize; JPEG_INFO_T jpegInfo; INT nWriteLen, nStatus, nReadLen; INT hFile; CHAR suFileName[100]; /* Decode Output Wait */ UINT32 u32Width,u32Height,u32Format; /*******************************************************************/ /* Read JPEG file */ /*******************************************************************/ sysprintf("Input Jpeg File name\n"); GetString(); strcpy(decodePath, g_u8String); fsAsciiToUnicode(decodePath, suFileName, TRUE); hFile = fsOpenFile(suFileName, NULL, O_RDONLY); if (hFile > 0) sysprintf("\tOpen file:[%s], file handle:%d\n", decodePath, hFile); else { sysprintf("\tFailed to open file: %s (%x)\n", decodePath, hFile); return; } u32BitstreamSize = fsGetFileSize(hFile); sysprintf("\tBit stream size for Decode is %d\n", u32BitstreamSize); /* Allocate the Bitstream Data Buffer for Decode Operation */ g_pu8JpegBuffer = (PUINT8)malloc(sizeof(CHAR) * (u32BitstreamSize + 0x03)); g_u32JpegBuffer = (((UINT32)g_pu8JpegBuffer + 0x03) & ~0x03) | 0x80000000; nStatus = fsReadFile(hFile, (UINT8 *)g_u32JpegBuffer, u32BitstreamSize, &nReadLen); if (nStatus < 0) sysprintf("\tRead error!!\n"); fsCloseFile(hFile); if(ParsingJPEG((UINT8 *)(UINT32)g_u32JpegBuffer, nReadLen, &u32Width, &u32Height, &u32Format, TRUE) == ERR_MODE) { sysprintf("\tNot Support the JPEG sampling\n"); goto END_ERROR_FORMAT; } /*******************************************************************/ /* Decode JPEG Bitstream */ /*******************************************************************/ /* JPEG Init */ jpegInit(); if(g_bDecIpwTest) { /*******************************************************************/ /* Decode Input Setting */ /*******************************************************************/ sysprintf ("\tDecode Input Test - %d KB Bitstream Buffer\n",DEC_IPW_BUFFERSIZE / 1024); sysprintf ("\tBitstream Buffer 0 0x%x \n",(UINT32)g_au8DecInputWaitBuffer | 0x80000000); sysprintf ("\tBitstream Buffer 1 0x%x \n",(UINT32)g_au8DecInputWaitBuffer | 0x80000000 + DEC_IPW_BUFFERSIZE/2); /* Reset the Buffer control parameter for Decode Input Wait function */ g_u32IpwUsedSize = 0; /* Set Bit stream Address (g_au8DecInputWaitBuffer -> 8KB Buffer) */ jpegIoctl(JPEG_IOCTL_SET_BITSTREAM_ADDR,(UINT32) g_au8DecInputWaitBuffer, 0); g_u32BitstreamSize = u32BitstreamSize; /* Set Decode Input Wait mode (Maximum size for the buffer is 2046 KB) */ jpegIoctl(JPEG_IOCTL_SET_DECINPUTWAIT_CALBACKFUN, (UINT32) JpegDecInputWait, DEC_IPW_BUFFERSIZE); if(u32BitstreamSize < DEC_IPW_BUFFERSIZE) len = u32BitstreamSize; else len = DEC_IPW_BUFFERSIZE; /* Prepare the data for first decode operation (Fill Buffer 0 & 1) */ /* Copy bitstream from the temp buffer (g_pu8JpegBuffer) to the buffer engine used (g_au8DecInputWaitBuffer) */ memcpy((char *)((UINT32)g_au8DecInputWaitBuffer | 0x80000000),(char *)g_u32JpegBuffer, len); /* The bitstream size put to Bitstream Buffer */ g_u32IpwUsedSize += len; } else { /* Set Bit stream Address */ jpegIoctl(JPEG_IOCTL_SET_BITSTREAM_ADDR,g_u32JpegBuffer, 0); } if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) { UINT32 u32FrameBuffer; /* Allocate Raw Data Buffer for Decode Operation (Prepare 1MB for Planar output) */ /* Or user needs to get image size to allocate buffer before Decode Trigger for Planar */ g_pu8DecFrameBuffer = (PUINT8)malloc(sizeof(CHAR) * (PLANAR_DEC_BUFFER_SIZE + 0x03)); if(g_pu8DecFrameBuffer == NULL) { sysprintf("\tCan't allocate the buffer for decode (size 0x%X)\n",PLANAR_DEC_BUFFER_SIZE); return; } u32FrameBuffer = (((UINT32) g_pu8DecFrameBuffer + 0x03) & ~0x03) | 0x80000000; sysprintf("\tThe Buffer prepared for Planar format starts from 0x%X, Size is 0x%X\n", u32FrameBuffer, PLANAR_DEC_BUFFER_SIZE); /* Set Decoded Image Address (Only Can be set before Decode Trigger for Planar;The address can set any time before existing Header Decode Complete Callback function) */ jpegIoctl(JPEG_IOCTL_SET_YADDR, u32FrameBuffer, 0); } /* Decode mode */ jpegIoctl(JPEG_IOCTL_SET_DECODE_MODE, g_u32DecFormat, 0); /* Set JPEG Header Decode End Call Back Function */ jpegIoctl(JPEG_IOCTL_SET_HEADERDECODE_CALBACKFUN, (UINT32) JpegDecHeaderComplete, 0); /* Trigger JPEG decoder */ jpegIoctl(JPEG_IOCTL_DECODE_TRIGGER, 0, 0); /* Wait for complete */ if(jpegWait()) { /*******************************************************************/ /* Prepare Output file name */ /*******************************************************************/ g_u8String[g_u32StringIndex] = '_'; g_u8String[g_u32StringIndex + 1] = 0x00; strcpy(decodePath, g_u8String); if(g_bDecIpwTest) strcat(decodePath, "IPW_"); if(g_bDecPanelTest) strcat(decodePath, "Panel_"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "PLANAR_"); else { switch(g_u32DecFormat) { case JPEG_DEC_PRIMARY_PACKET_YUV422: strcat(decodePath, "PACKET_YUV422_"); break; case JPEG_DEC_PRIMARY_PACKET_RGB555: strcat(decodePath, "PACKET_RGB555_"); break; case JPEG_DEC_PRIMARY_PACKET_RGB565: strcat(decodePath, "PACKET_RGB565_"); break; case JPEG_DEC_PRIMARY_PACKET_RGB888: strcat(decodePath, "PACKET_RGB888_"); break; } } jpegGetInfo(&jpegInfo); sysprintf("\tJPEG Decode Complete!!\n"); sysprintf("\t\tJpeg YuvFormat "); switch(jpegInfo.yuvformat) { case JPEG_DEC_YUV420: sysprintf("YUV420\n"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "YUV420_"); break; case JPEG_DEC_YUV422: sysprintf("YUV422\n"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "YUV422_"); break; case JPEG_DEC_YUV444: sysprintf("YUV444\n"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "YUV444_"); break; case JPEG_DEC_YUV411: sysprintf("YUV411\n"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "YUV411_"); break; case JPEG_DEC_GRAY: sysprintf("GRAY\n"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "GRAY_"); break; case JPEG_DEC_YUV422T: sysprintf("YUV422T\n"); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PLANAR_YUV) strcat(decodePath, "YUV422T_"); break; } sysprintf("\t\tJpeg Width = %d\n",jpegInfo.jpeg_width); /* JPEG width in Bitstream header */ sysprintf("\t\tJpeg Height = %d\n",jpegInfo.jpeg_height); /* JPEG width in Bitstream header */ strcat(decodePath, "size"); if(g_bDecPanelTest) { strcat(decodePath, intToStr(PANEL_WIDTH)); strcat(decodePath, "x"); strcat(decodePath, intToStr(PANEL_HEIGHT)); } else { strcat(decodePath, intToStr(jpegInfo.width)); strcat(decodePath, "x"); strcat(decodePath, intToStr(jpegInfo.height)); } strcat(decodePath, ".dat"); sysprintf("\t\tOutput Image Width = %d\n",jpegInfo.width); /* Decode image width */ sysprintf("\t\tOutput Image Height = %d\n",jpegInfo.height); /* Decode image height */ if(jpegInfo.stride) sysprintf("\t\tJpeg Decode Image Stride = %d\n",jpegInfo.stride); /*******************************************************************/ /* Get Output file size */ /*******************************************************************/ len = jpegInfo.image_size[0]; if(g_bDecPanelTest) { sysprintf ("\t\tOutput Raw data size from JPEG engine %d x %d\n", PANEL_WIDTH, TARGET_HEIGHT); if(g_u32DecFormat == JPEG_DEC_PRIMARY_PACKET_RGB888) len = PANEL_WIDTH * PANEL_HEIGHT * 4; else len = PANEL_WIDTH * PANEL_HEIGHT * 2; sysprintf ("\t\tOutput Raw data size (file) %d x %d\n", PANEL_WIDTH, PANEL_HEIGHT); vpostLCMInit(&lcdInfo, (UINT32*)((UINT32)g_pu8DecFrameBuffer | 0x80000000)); /* If backlight control signal is different from nuvoton's demo board, please don't call this function and must implement another similar one to enable LCD backlight. */ vpostEnaBacklight(); } else { sysprintf ("\t\tOuput Raw data size (file) %d\n", len); } } else { sysprintf("\tJPEG Decode Error!!\n"); len = 0; goto END; } /*******************************************************************/ /* Write to Disk */ /*******************************************************************/ fsAsciiToUnicode(decodePath, suFileName, TRUE); hFile = fsOpenFile(suFileName, NULL, O_CREATE | O_TRUNC); if (hFile > 0) sysprintf("\tOpen file:[%s], file handle:%d\n", decodePath, hFile); else { sysprintf("\tFailed to open file: %s (%x)\n", decodePath, hFile); } nStatus = fsWriteFile(hFile, (UINT8 *)((UINT32)g_pu8DecFrameBuffer | 0x80000000), len, &nWriteLen); if (nStatus < 0) sysprintf("\tWrite error!!\n"); fsCloseFile(hFile); END: free(g_pu8DecFrameBuffer); END_ERROR_FORMAT: free(g_pu8JpegBuffer); sysprintf ("\tDecode test completed!\n"); return; }