三星已经对JPEG解码做好了驱动,应用通过调用JPEG解码的API函数,从而调用JPEG驱动,驱动通过6410的内部硬件解码,将JPEG格式的数据解码成YUV格式的数据,然后将YUV格式转化成RGB,通过LCD显示出来。
在三星提供的BSP包中,有文件S3C6410_WinCE6.0_WM6.0_JPEG_API.pdf,里面详细介绍了JPEG的使用方法。另外,三星还做了个JPEG的例子,在BSP包中路径为:E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG,直接在PB6.0中编译生成*.exe文件,即可在6410的平台上运行。
JPEG的解码测试代码如下:
- void TestDecoder()
- {
- char *InBuf = NULL;
- char *OutBuf = NULL;
- char *OutPhyBuf = NULL;
- char *OutRGBBuf = NULL;
- char *OutRGBPhyBuf = NULL;
- FILE *fp;
- FILE *CTRfp;
- UINT32 fileSize;
- UINT32 streamSize;
- void *handle;
- INT32 width, height, samplemode;
- JPEG_ERRORTYPE ret;
- char outFilename[128];
- char inFilename[128];
- BOOL result = TRUE;
- // int i;//added by lqm.
- #if (FPS == 1)
- INT32 decodeTime;
- #endif
- DWORD startTime;
- RETAILMSG(1,(L"------------------------Decoder Test Start ---------------------/n"));
- //
- // 0. Get input/output file name //
- //
- //CTRfp = fopen(CTRL_FILE_NAME, "rb");// 解码时,CTRL_FILE_NAME = "fname_dec.txt"
- CTRfp = fopen("//Nand-disk//JPEG//fname_dec.txt", "rb");
- if(CTRfp == NULL)
- {
- RETAILMSG(1,(L"file open error : %s/n", CTRL_FILE_NAME));
- return;
- }
- do
- {
- memset(outFilename, 0x00, sizeof(outFilename));// 将数组里面的128个数据全部填0
- memset(inFilename, 0x00, sizeof(inFilename));
- fscanf(CTRfp, "%s", inFilename);//将*CTRfp指向的文件CTRL_FILE_NAME里的第n行数据读到inFilename[]数组
- if(inFilename[0] == '#')//文件以"#"表示结束,当读到"#"时表示解码结束
- {
- RETAILMSG(1,(L"------------------------Decoder Test Done ---------------------/n"));
- fclose(CTRfp);
- return;
- }
- fscanf(CTRfp, "%s", outFilename);//将*CTRfp指向的文件CTRL_FILE_NAME里的第n+1行数据读到outFilename[]数组
- if(inFilename == NULL || outFilename == NULL)
- {
- RETAILMSG(1,(L"read file error/n"));
- RETAILMSG(1,(L"------------------------Decoder Test Done ---------------------/n"));
- fclose(CTRfp);
- return;
- }
- // 为什么下面的打印信息是隔一个字符打印一个?
- RETAILMSG(1,(L"inFilename : %s /noutFilename : %s/n", inFilename, outFilename));
- //
- // 1. handle Init //
- //
- #if (FPS == 1)
- decodeTime = GetTickCount();//读取以毫秒为单位的计算机启动后经历的时间间隔。
- #endif
- handle = SsbSipJPEGDecodeInit();
- #if (FPS == 1)
- decodeTime = GetTickCount() - decodeTime;
- RETAILMSG(1,(L"Initialization Time : %d /n", decodeTime));
- #endif
- if(handle == NULL)
- {
- RETAILMSG(1,(L"Decoder Init failed/n"));
- break;
- }
- //
- // 2. open JPEG file to decode //
- //
- fp = fopen(inFilename, "rb");// 打开inFilename数组中指定的文件
- if(fp == NULL)
- {
- result = FALSE;
- RETAILMSG(1,(L"file open error : %s/n", inFilename));
- break;
- }
- // 以下三句用于计算文件的长度
- // 在这里用于计算打开的JTAG图像文件的大小(byte)
- fseek(fp, 0, SEEK_END);//把文件指针指向文件尾部
- fileSize = ftell(fp);//读取当前指针位置偏离文件头部的字节数
- fseek(fp, 0, SEEK_SET);//把文件指针指向文件首部
- RETAILMSG(1,(L"filesize : %d/n", fileSize));
- //
- // 3. get Input buffer address //
- //
- InBuf = SsbSipJPEGGetDecodeInBuf(handle, fileSize);
- if(InBuf == NULL){
- RETAILMSG(1,(L"Input buffer is NULL/n"));
- result = FALSE;
- break;
- }
- RETAILMSG(1,(L"inBuf : 0x%x/n", InBuf));
- //
- // 4. put JPEG frame to Input buffer //
- //
- fread(InBuf, 1, fileSize, fp);//把fp指向的图像文件的数据存入输入缓冲区
- fclose(fp);//释放打开的图像文件
- //
- // 5. Decode JPEG frame //
- //
- #if (FPS == 1)
- decodeTime = GetTickCount();
- #endif
- ret = SsbSipJPEGDecodeExe(handle);//JPEG格式解码
- #if (FPS == 1)
- decodeTime = GetTickCount() - decodeTime;
- RETAILMSG(1,(L"decodeTime : %d ms/n", decodeTime));//打印解码所花的时间
- #endif
- if(ret != JPEG_OK){
- RETAILMSG(1,(L"Decoding failed/n"));
- result = FALSE;
- break;
- }
- //
- // 6. get Output buffer address //
- //
- OutBuf = SsbSipJPEGGetDecodeOutBuf(handle, &streamSize);
- if(OutBuf == NULL){
- RETAILMSG(1,(L"Output buffer is NULL/n"));
- result = FALSE;
- break;
- }
- printD("OutBuf : 0x%x streamsize : %d/n", OutBuf, streamSize);
- //
- // 7. get decode config. //
- //
- SsbSipJPEGGetConfig(JPEG_GET_DECODE_WIDTH, &width);
- SsbSipJPEGGetConfig(JPEG_GET_DECODE_HEIGHT, &height);
- SsbSipJPEGGetConfig(JPEG_GET_SAMPING_MODE, &samplemode);
- RETAILMSG(1,(L"width : %d height : %d samplemode : %d/n/n", width, height, samplemode));
- //
- // 8. write output file //
- //
- #if (TEST_DECODE_OUTPUT_YCBYCR == 1)
- DecodeFileOutYCBYCR(OutBuf, streamSize, outFilename); // YCBYCR interleaved
- #elif (TEST_DECODE_OUTPUT_YUV422 == 1)
- DecodeFileOutYUV422(OutBuf, streamSize, outFilename); // yuv422 non-interleaved
- #elif (TEST_DECODE_OUTPUT_RGB16 == 1) //RGB16
- OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(handle);
- OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(handle, LCD_X, LCD_Y);
- if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height,
- POST_SRC_YUV422_CRYCBY,
- (int)OutRGBPhyBuf, LCD_X, LCD_Y,
- POST_DST_RGB16) == FALSE){
- RETAILMSG(1,(L"ConvertYCBYCRToRGB error/n"));
- result = FALSE;
- break;
- }
- OutRGBBuf = SsbSipJPEGGetRGBBuf(handle, LCD_X, LCD_Y);
- DecodeFileOutRGB16ToPPM(OutRGBBuf, LCD_X, LCD_Y, outFilename);
- #elif(TEST_DECODE_OUTPUT_LCD == 1)
- OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(handle);//获得解码输出缓冲的物理地址
- OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(handle, LCD_X, LCD_Y);//获得解码输出缓冲的物理地址
- startTime = GetTickCount();
- if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height,
- POST_SRC_YUV422_CRYCBY,
- (int)OutRGBPhyBuf, LCD_X, LCD_Y,
- POST_DST_RGB16) == FALSE){
- RETAILMSG(1,(L"ConvertYCBYCRToRGB error/n"));
- result = FALSE;
- break;
- }
- RETAILMSG(1,(L"converting time : %d/n/n", GetTickCount() - startTime));
- RETAILMSG(1,(L"/n/n This image will be disappeared after %d seconds....../n/n", DISPLAY_TIME));
- DisplayJPEG((int)OutRGBPhyBuf, LCD_X, LCD_Y, LCD_X, LCD_Y, DISPLAY_TIME);
- #endif
- //
- // 9. finalize handle //
- //
- SsbSipJPEGDecodeDeInit(handle);
- Sleep(5);
- }
- while(1);
- if(result == FALSE)
- {
- SsbSipJPEGDecodeDeInit(handle);
- }
- fclose(CTRfp);
- RETAILMSG(1,(L"------------------------Decoder Test Done ---------------------/n"));
- }
这些代码会调用JPGApi.c中的若干API函数,在API函数中可以看到他们开始打开驱动,然后逐个调用JPEG驱动了。例如,解码JPEG的函数如下:
- JPEG_ERRORTYPE SsbSipJPEGDecodeExe(void *openHandle)
- {
- int ret;
- printD("API :: jCtx->decParam->fileSize : %d/n", jCtx->decParam->fileSize);
- if(jCtx->decParam->decType == JPG_MAIN){
- ret = DeviceIoControl(openHandle, IOCTL_JPG_DECODE, NULL,
- 0, NULL, 0,
- (PDWORD)jCtx->decParam, NULL);
- if(ret == 0){
- RETAILMSG(1, (TEXT("API :: IOCTL_JPG_DECODE failed/r/n")));
- return JPEG_FAIL;
- }
- printD("API :: decParam->width : %d decParam->height : %d/n", jCtx->decParam->width, jCtx->decParam->height);
- printD("API :: streamSize : %d/n", jCtx->decParam->dataSize);
- }
- else{
- // thumbnail decode, for the future work.
- }
- return JPEG_OK;
- }
驱动三星也已经都做好了,这里就不一一把代码贴上来了。
值得注意的是,将该例子生成的可执行文件拷到WINCE平台运行的同时,还要将测试图片,记录测试图片路径的文本文件一并拷到WINCE平台,注意拷备的最终路径,要和程序中代码严格对应,否则无法打开图片文件或是文本文件。
存放的图片路径如下:
E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG/test/testVectors
存放的广本文件的路径如下:
E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG/test/fname_dec.txt