三星已经对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的解码测试代码如下:
//////////////////////////////////////////////////////////////
// 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的函数如下:
驱动三星也已经都做好了,这里就不一一把代码贴上来了。
值得注意的是,将该例子生成的可执行文件拷到WINCE平台运行的同时,还要将测试图片,记录测试图片路径的文本文件一并拷到WINCE平台,注意拷备的最终路径,要和程序中代码严格对应,否则无法打开图片文件或是文本文件。
存放的图片路径如下:
E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG/test/testVectors
存放的广本文件的路径如下:
E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG/test/fname_dec.txt