S3C6410 jpeg 硬件解码

   三星已经对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的解码测试代码如下:

  1. void TestDecoder()  
  2. {  
  3.     char *InBuf = NULL;  
  4.     char *OutBuf = NULL;  
  5.     char *OutPhyBuf = NULL;  
  6.     char *OutRGBBuf = NULL;  
  7.     char *OutRGBPhyBuf = NULL;  
  8.     FILE *fp;  
  9.     FILE *CTRfp;  
  10.     UINT32 fileSize;  
  11.     UINT32 streamSize;  
  12.     void *handle;  
  13.     INT32 width, height, samplemode;  
  14.     JPEG_ERRORTYPE ret;  
  15.     char outFilename[128];  
  16.     char inFilename[128];  
  17.     BOOL result = TRUE;  
  18. //  int i;//added by lqm.  
  19. #if (FPS == 1)  
  20.     INT32    decodeTime;  
  21. #endif  
  22.     DWORD    startTime;  
  23.     RETAILMSG(1,(L"------------------------Decoder Test Start ---------------------/n"));  
  24.     //  
  25.     // 0. Get input/output file name                            //  
  26.     //  
  27.     //CTRfp = fopen(CTRL_FILE_NAME, "rb");// 解码时,CTRL_FILE_NAME = "fname_dec.txt"  
  28.     CTRfp = fopen("//Nand-disk//JPEG//fname_dec.txt""rb");  
  29.     if(CTRfp == NULL)  
  30.     {  
  31.         RETAILMSG(1,(L"file open error : %s/n", CTRL_FILE_NAME));  
  32.         return;  
  33.     }  
  34.     do  
  35.     {  
  36.         memset(outFilename, 0x00, sizeof(outFilename));// 将数组里面的128个数据全部填0  
  37.         memset(inFilename, 0x00, sizeof(inFilename));  
  38.         fscanf(CTRfp, "%s", inFilename);//将*CTRfp指向的文件CTRL_FILE_NAME里的第n行数据读到inFilename[]数组  
  39.         if(inFilename[0] == '#')//文件以"#"表示结束,当读到"#"时表示解码结束  
  40.         {  
  41.             RETAILMSG(1,(L"------------------------Decoder Test Done ---------------------/n"));  
  42.             fclose(CTRfp);  
  43.             return;  
  44.         }  
  45.         fscanf(CTRfp, "%s", outFilename);//将*CTRfp指向的文件CTRL_FILE_NAME里的第n+1行数据读到outFilename[]数组  
  46.         if(inFilename == NULL || outFilename == NULL)  
  47.         {  
  48.             RETAILMSG(1,(L"read file error/n"));  
  49.             RETAILMSG(1,(L"------------------------Decoder Test Done ---------------------/n"));  
  50.             fclose(CTRfp);  
  51.             return;  
  52.         }  
  53.         // 为什么下面的打印信息是隔一个字符打印一个?  
  54.         RETAILMSG(1,(L"inFilename : %s /noutFilename : %s/n", inFilename, outFilename));  
  55.         //  
  56.         // 1. handle Init                                           //  
  57.         //  
  58. #if (FPS == 1)  
  59.         decodeTime = GetTickCount();//读取以毫秒为单位的计算机启动后经历的时间间隔。  
  60. #endif  
  61.         handle = SsbSipJPEGDecodeInit();  
  62. #if (FPS == 1)          
  63.         decodeTime = GetTickCount() - decodeTime;  
  64.         RETAILMSG(1,(L"Initialization Time : %d /n", decodeTime));  
  65. #endif  
  66.         if(handle == NULL)  
  67.         {  
  68.             RETAILMSG(1,(L"Decoder Init failed/n"));  
  69.             break;  
  70.         }  
  71.         //  
  72.         // 2. open JPEG file to decode                              //  
  73.         //  
  74.         fp = fopen(inFilename, "rb");// 打开inFilename数组中指定的文件  
  75.         if(fp == NULL)  
  76.         {  
  77.             result = FALSE;  
  78.             RETAILMSG(1,(L"file open error : %s/n", inFilename));  
  79.             break;  
  80.         }  
  81.         // 以下三句用于计算文件的长度  
  82.         // 在这里用于计算打开的JTAG图像文件的大小(byte)  
  83.         fseek(fp, 0, SEEK_END);//把文件指针指向文件尾部  
  84.         fileSize = ftell(fp);//读取当前指针位置偏离文件头部的字节数  
  85.         fseek(fp, 0, SEEK_SET);//把文件指针指向文件首部  
  86.         RETAILMSG(1,(L"filesize : %d/n", fileSize));  
  87.         //  
  88.         // 3. get Input buffer address                              //  
  89.         //  
  90.         InBuf = SsbSipJPEGGetDecodeInBuf(handle, fileSize);  
  91.         if(InBuf == NULL){  
  92.             RETAILMSG(1,(L"Input buffer is NULL/n"));  
  93.             result = FALSE;  
  94.             break;  
  95.         }  
  96.         RETAILMSG(1,(L"inBuf : 0x%x/n", InBuf));  
  97.         //  
  98.         // 4. put JPEG frame to Input buffer                        //  
  99.         //  
  100.         fread(InBuf, 1, fileSize, fp);//把fp指向的图像文件的数据存入输入缓冲区  
  101.         fclose(fp);//释放打开的图像文件  
  102.   
  103.         //  
  104.         // 5. Decode JPEG frame                                     //  
  105.         //  
  106. #if (FPS == 1)  
  107.         decodeTime = GetTickCount();  
  108. #endif  
  109.         ret = SsbSipJPEGDecodeExe(handle);//JPEG格式解码  
  110. #if (FPS == 1)          
  111.             decodeTime = GetTickCount() - decodeTime;  
  112.             RETAILMSG(1,(L"decodeTime : %d ms/n", decodeTime));//打印解码所花的时间  
  113. #endif  
  114.         if(ret != JPEG_OK){  
  115.             RETAILMSG(1,(L"Decoding failed/n"));  
  116.             result = FALSE;  
  117.             break;  
  118.         }  
  119.         //  
  120.         // 6. get Output buffer address                             //  
  121.         //  
  122.         OutBuf = SsbSipJPEGGetDecodeOutBuf(handle, &streamSize);  
  123.         if(OutBuf == NULL){  
  124.             RETAILMSG(1,(L"Output buffer is NULL/n"));  
  125.             result = FALSE;  
  126.             break;  
  127.         }  
  128.         printD("OutBuf : 0x%x streamsize : %d/n", OutBuf, streamSize);  
  129.         //  
  130.         // 7. get decode config.                                    //  
  131.         //  
  132.         SsbSipJPEGGetConfig(JPEG_GET_DECODE_WIDTH, &width);  
  133.         SsbSipJPEGGetConfig(JPEG_GET_DECODE_HEIGHT, &height);  
  134.         SsbSipJPEGGetConfig(JPEG_GET_SAMPING_MODE, &samplemode);  
  135.         RETAILMSG(1,(L"width : %d height : %d samplemode : %d/n/n", width, height, samplemode));  
  136.         //  
  137.         // 8. write output file                                     //  
  138.         //  
  139. #if (TEST_DECODE_OUTPUT_YCBYCR == 1)  
  140.         DecodeFileOutYCBYCR(OutBuf, streamSize, outFilename);    // YCBYCR interleaved  
  141. #elif (TEST_DECODE_OUTPUT_YUV422 == 1)  
  142.         DecodeFileOutYUV422(OutBuf, streamSize, outFilename);    // yuv422 non-interleaved  
  143. #elif (TEST_DECODE_OUTPUT_RGB16 == 1)                            //RGB16  
  144.         OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(handle);  
  145.         OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(handle, LCD_X, LCD_Y);  
  146.         if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height,   
  147.                               POST_SRC_YUV422_CRYCBY,  
  148.                               (int)OutRGBPhyBuf, LCD_X, LCD_Y,  
  149.                               POST_DST_RGB16) == FALSE){  
  150.             RETAILMSG(1,(L"ConvertYCBYCRToRGB error/n"));  
  151.             result = FALSE;  
  152.             break;  
  153.         }  
  154.         OutRGBBuf = SsbSipJPEGGetRGBBuf(handle, LCD_X, LCD_Y);  
  155.         DecodeFileOutRGB16ToPPM(OutRGBBuf, LCD_X, LCD_Y, outFilename);   
  156. #elif(TEST_DECODE_OUTPUT_LCD == 1)  
  157.         OutPhyBuf = SsbSipJPEGGetDecodeOutPhyBuf(handle);//获得解码输出缓冲的物理地址  
  158.         OutRGBPhyBuf = SsbSipJPEGGetRGBPhyBuf(handle, LCD_X, LCD_Y);//获得解码输出缓冲的物理地址  
  159.         startTime = GetTickCount();  
  160.         if(ConvertYCBYCRToRGB((int)OutPhyBuf, width, height,   
  161.                               POST_SRC_YUV422_CRYCBY,  
  162.                               (int)OutRGBPhyBuf, LCD_X, LCD_Y,  
  163.                               POST_DST_RGB16) == FALSE){  
  164.             RETAILMSG(1,(L"ConvertYCBYCRToRGB error/n"));  
  165.             result = FALSE;  
  166.             break;  
  167.         }  
  168.         RETAILMSG(1,(L"converting time : %d/n/n", GetTickCount() - startTime));  
  169.         RETAILMSG(1,(L"/n/n This image will be disappeared after %d seconds....../n/n", DISPLAY_TIME));  
  170.         DisplayJPEG((int)OutRGBPhyBuf, LCD_X, LCD_Y, LCD_X, LCD_Y, DISPLAY_TIME);  
  171. #endif  
  172.         //  
  173.         // 9. finalize handle                                      //  
  174.         //  
  175.         SsbSipJPEGDecodeDeInit(handle);  
  176.         Sleep(5);  
  177.     }  
  178.     while(1);  
  179.     if(result == FALSE)  
  180.     {  
  181.         SsbSipJPEGDecodeDeInit(handle);  
  182.     }  
  183.     fclose(CTRfp);  
  184.     RETAILMSG(1,(L"------------------------Decoder Test Done ---------------------/n"));  
  185. }  

    这些代码会调用JPGApi.c中的若干API函数,在API函数中可以看到他们开始打开驱动,然后逐个调用JPEG驱动了。例如,解码JPEG的函数如下:

  1. JPEG_ERRORTYPE SsbSipJPEGDecodeExe(void *openHandle)  
  2. {  
  3.     int    ret;  
  4.     printD("API :: jCtx->decParam->fileSize : %d/n", jCtx->decParam->fileSize);  
  5.     if(jCtx->decParam->decType == JPG_MAIN){  
  6.         ret = DeviceIoControl(openHandle, IOCTL_JPG_DECODE, NULL,   
  7.                             0, NULL, 0,   
  8.                             (PDWORD)jCtx->decParam, NULL);  
  9.         if(ret == 0){  
  10.             RETAILMSG(1, (TEXT("API :: IOCTL_JPG_DECODE failed/r/n")));  
  11.             return JPEG_FAIL;  
  12.         }  
  13.         printD("API :: decParam->width : %d decParam->height : %d/n", jCtx->decParam->width, jCtx->decParam->height);  
  14.         printD("API :: streamSize : %d/n", jCtx->decParam->dataSize);  
  15.     }  
  16.     else{  
  17.         // thumbnail decode, for the future work.  
  18.     }  
  19.     return JPEG_OK;  
  20. }  

    驱动三星也已经都做好了,这里就不一一把代码贴上来了。

 

    值得注意的是,将该例子生成的可执行文件拷到WINCE平台运行的同时,还要将测试图片,记录测试图片路径的文本文件一并拷到WINCE平台,注意拷备的最终路径,要和程序中代码严格对应,否则无法打开图片文件或是文本文件。

    存放的图片路径如下:

    E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG/test/testVectors

    存放的广本文件的路径如下:

    E:/WINCE600/PLATFORM/SMDK6410/SAMPLES/JPEG/test/fname_dec.txt


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值