歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

S3C6410 裸機硬件JPEG解碼

2012年12月25日,晚上我找到問題所在了,JPEG解碼源圖像地址必須是16字節(128位)對齊的,也就是最低4位必須為0,這個害的我好久,還好終於解決了。

修復了已知的bug;

這個是我實驗用的原圖,用工具把他變成了數組後直接放在程序裡面了.

解碼後的圖片

附上代碼

/*************************************************************************************************************
 * 文件名   : JpegCodec.c
 * 功能   : S3C6410 JPEG解碼底層驅動函數
 * 作者   : [email protected]
 * 創建時間  : 2012年9月20日20:59
 * 最後修改時間 : 2012年12月02日
 * 詳細   : JPEG硬解碼
 *      通過S3C6410 DATASHEETV1.2版以及官方WINCE的JPEG驅動的分析,得出結論,S3C6410的JPEG解碼模塊不支持硬件控制自動解碼
 *      只能使用軟件控制解碼模式
 *    20121202:修復連續解碼BUG,目前有少數jpeg420,jpeg444會解碼出錯,就像windows也有可能有不支持的jpeg圖片一樣,少數圖片硬解碼
 *      失敗可以嘗試使用軟解碼即可。
 *    20121225:發現JPEG必須16字節(128位)地址對齊,否則可能會出現解碼失敗問題。
 *    20130113:增加尺寸非8或16倍數的jpeg圖片解碼功能
 *    20130113:將程序外部依賴降低,目前只依賴外部的數據類型定義(高類聚,低耦合),打印調試也依賴外部,不用可以修改宏,JPEG_DBUG=0來取消,方便移植。
*************************************************************************************************************/
#include "JpegCodec.h"
#include "jpeg_tables.h"


//調試宏開關
#define JPEG_DBUG 0
#if JPEG_DBUG
 #include "system.h"
 #define jpeg_debug(format,...) uart_printf(format,##__VA_ARGS__)
#else
 #define jpeg_debug(format,...) /\
/
#endif //JPEG_DBUG

 

//jpeg編解碼模式配置
#define COEF1_RGB_2_YUV        0x4d971e
#define COEF2_RGB_2_YUV        0x2c5783
#define COEF3_RGB_2_YUV        0x836e13

#define ENABLE_MOTION_ENC      (0x1<<3)  //使能動態編碼
#define DISABLE_MOTION_ENC      (0x0<<3)

#define ENABLE_HW_DEC          (0x1<<2)
#define DISABLE_HW_DEC          (0x0<<2)

#define ENABLE_MOTION_DEC      (0x1<<0)  //使能動態解碼
#define DISABLE_MOTION_DEC      (0x0<<0) 

#define INCREMENTAL_DEC   (0x1<<3)  //增量解碼模式
#define NORMAL_DEC              (0x0<<3)  //正常解碼模式
#define YCBCR_MEMORY   (0x1<<5)

#define ENABLE_IRQ    (0xf<<3)

//等待超時定義
#define WaitTimeOut    0xffffff   //等待超時計數器

//定義最大圖像寬高度
#define MAX_JPG_WIDTH  4096
#define MAX_JPG_HEIGHT  4096

//JPEG寄存器結構定義
typedef struct
{
 u32  Mode;    //模式寄存器
 u32  Status;    //狀態寄存器
 u32  QTblNo;
 u32  RSTPos;
 u32  Vertical;   //垂直分辨率
 u32  Horizontal;   //水平分辨率
 u32  DataSize;   //壓縮數據字節數
 u32  IRQ;    //中斷設置寄存器
 u32  IRQStatus;   //中斷狀態寄存器 0x20
 u32  Reserved0[247];
 u32  QTBL0[64];       //0x400
 u32  QTBL1[64];
 u32  QTBL2[64];
 u32  QTBL3[64];
 u32  HDCTBL0[16];      //0x800
 u32  HDCTBLG0[12];
 u32  Reserved1[4];
 u32  HACTBL0[16];
 u32  HACTBLG0[162];      //0x8c0
 u32  Reserved2[46];
 u32  HDCTBL1[16];      //0xc00
 u32  HDCTBLG1[12];
 u32  Reserved3[4];
 u32  HACTBL1[16];
 u32  HACTBLG1[162];      //0xcc0
 u32  Reserved4[46];
 u32  ImageAddr0;   //目的圖像地址1
 u32  ImageAddr1;   //目的圖像地址2
 u32  JpegAddr0;   //源JPEG圖像地址1
 u32  JpegAddr1;   //源JPEG圖像地址2
 u32  Start;    //JPEG解碼開始
 u32  ReStart;   //重新開始JPEG解碼
 u32  SofReset;   //JPEG復位
 u32  Cntl;    //控制寄存器
 u32  COEF1;
 u32  COEF2;
 u32  COEF3;
 u32  Misc;    //雜項寄存器
 u32  FramIntv;
}JPEG_TypeDef;

 

//定義JPEG文件標記
enum
{
    UNKNOWN,
    BASELINE = 0xC0,
    EXTENDED_SEQ = 0xC1,
    PROGRESSIVE = 0xC2
}JPG_SOF_MARKER;


//S3C6410 jpeg編解碼器基址
#define JPEG_BASE  0x78800000 


//寄存器結構指針
#define JPEG ((JPEG_TypeDef *)JPEG_BASE)


//內部靜態函數聲明
static void JPEG_Reset(void);  //JPEG解碼器軟件復位
static JPEG_TYPE JPEG_GetJpegType(void); //獲取JPEG采樣模式
static void JPEG_GetWidthHeight(u16* width, u16* height);//獲取圖像大小
static JPEG_ERROR JPEG_WaitForIRQ(void); //等待中斷,並返回狀態
static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height);
static void JPEG_WriteHeader(u32 JpgAddr, u32 fileSize, u16 width, u16 height);
static void JPEG_WriteYUV(u32 ImageAddr, u16 width, u16 orgwidth, u16 height, u16 orgheight);
static void JPEG_MemMove(u8* dest, u8* src,u32 count);


/*************************************************************************************************************************
*函數      : void JPEG_Init(void)
*功能      : JPEG解碼初始化
*參數      : 無
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間     : 20120920
*最後修改時間 : 20120923
*說明     : 無
*************************************************************************************************************************/
void JPEG_Init(void)
{
 //rCLK_DIV0 |= 0x03 << 24;
 //Set_GateClk(SCLK_JPEG,ENABLE); //使能JPEG模塊時鐘
}


/*************************************************************************************************************************
*函數      : static void JPEG_Reset(void)
*功能      : JPEG解碼器軟件復位
*參數      : 無
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 無
*************************************************************************************************************************/
static void JPEG_Reset(void)
{
 JPEG->SofReset = 0;
}


/*************************************************************************************************************************
*函數      : static JPEG_TYPE JPEG_Reset(void)
*功能      : 獲取JPEG采樣模式
*參數      : 無
*返回      : JPEG類型,見定義
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 編碼模式只有0x1,0x2兩種模式
*************************************************************************************************************************/
static JPEG_TYPE JPEG_GetJpegType(void)
{
 switch (JPEG->Mode & 0x07) //通過判斷0-2BIT
 {
  case 0 : return TYPE_JPEG_444;  //色度4:4:4格式
  case 1 :  return TYPE_JPEG_422;  //色度4:2:2格式
  case 2 :  return TYPE_JPEG_420;  //色度4:2:0格式
  case 3 :  return TYPE_JPEG_400;  //灰色格式(單一組成)
  case 6 :  return TYPE_JPEG_411;  //色度4:1:1格式
  default :  return TYPE_JPEG_UNKNOWN; 
 }
}

 

/*************************************************************************************************************************
*函數      : static void JPEG_GetWidthHeight(u16* width, u16* height)
*功能      : 獲取圖像尺寸大小
*參數      : HSize:圖像寬度緩沖區指針;VSize:圖像高度緩沖區指針
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 16BIT
*************************************************************************************************************************/
static void JPEG_GetWidthHeight(u16* width, u16* height)
{
 *width = JPEG->Horizontal;  //在水平方向上定義圖像大小的值
 *height = JPEG->Vertical;  //在垂直方向上定義圖像大小的值
}


/*************************************************************************************************************************
*函數      : u32 JPEG_GetYUVSize(JPEG_TYPE jpegType,u16 width, u16 height)
*功能      : 獲取解碼後數據大小
*參數      : jpegType:jpeg圖像類型,width,height:圖像尺寸
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 2010113
*最後修改時間 : 2010113
*說明      : 無
*************************************************************************************************************************/
u32 JPEG_GetYUVSize(JPEG_TYPE jpegType,u16 width, u16 height)
{
 switch(jpegType)
 {
  case TYPE_JPEG_444 :  return(width*height*3);
    case TYPE_JPEG_422 :  return(width*height*2);
    case TYPE_JPEG_420 : 
    case TYPE_JPEG_411 :  return((width*height) + (width*height>>1));
    case TYPE_JPEG_400 :  return(width*height);
    default :     return(0);
 }
}

 

/*************************************************************************************************************************
*函數      : void JPEG_ReadClearStatus(u8* Status, u8* IrqStatus)
*功能      : 讀取並清除JPEG狀態
*參數      : Status:解碼器狀態緩沖區指針;IrqStatus:中斷狀態緩沖區指針
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : JPGSTS和JPGIRQ;JPGIRQ讀取後自動清除
*     JPGIRQ: BIT6結果狀態 0:不正常的處理結束; 1:正常的處理完成
*      BIT4位流的錯誤狀態。只有在解壓縮期間有效。0:在被壓縮的文件上,沒有語法錯誤。1:在被壓縮的文件上,有語法錯誤。
*      BIT3標題狀態。只有在解壓縮期間有效。0:圖像大小和取樣因素值不可讀。1:圖像大小和取樣因素值可讀。 
*************************************************************************************************************************/
void JPEG_ReadClearStatus(u8* Status, u8* IrqStatus)
{
 *Status = JPEG->Status;
 *IrqStatus = JPEG->IRQStatus & ((1<<6)|(1<<4)|(1<<3));
}


/*************************************************************************************************************************
*函數      : static JPEG_ERROR JPEG_WaitForIRQ(void)
*功能      : 等待中斷,並返回狀態
*參數      : 無
*返回      : 返回中斷狀態,見定義
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120922
*最後修改時間 : 2010113
*說明      : 通過判斷JPGIRQ中斷寄存器的值返回相應狀態
*************************************************************************************************************************/
static JPEG_ERROR JPEG_WaitForIRQ(void)

    vu32 TimeOut = WaitTimeOut;  //初始化計數器值 
    vu8 IRQStatus,Status;
    JPEG_ERROR error;
   
    do 
    {   
        IRQStatus = JPEG->IRQStatus;  //讀取中斷狀態寄存器,並消除狀態
        TimeOut --;               //計數器自減 
    } 
    while((IRQStatus == 0) && TimeOut);    //當發生中斷或者計數器為0時退出等待
    IRQStatus &= ((1<<6)|(1<<4)|(1<<3));
 switch (IRQStatus)                //判斷中斷狀態 
    { 
  case 0x00 : error =  JPEG_WAIT_TIME_OUT;break;  //超時錯誤
        case 0x40 : error =  JPEG_OK;break;    //正常完成 
        case 0x08 : error =  JPEG_HEADER_OK;break;   //頭分析完成,可以讀取大小以及采樣信息 
        case 0x10 : error =  JPEG_BITSTRE_ERROR;break;  //語法錯誤 
        case 0x18 : error =  JPEG_BITSTRE_ERROR;break;  //語法錯誤 
        default : error =  JPEG_OTHER_ERROR;break;      //其它錯誤 
    }
    Status = JPEG->Status;
    return error;
}

 

/*************************************************************************************************************************
*函數      : static void JPEG_DecodeHeader(u32 JpegAddr)
*功能      : 開始解碼JPEG頭部信息(軟件控制解碼)
*參數      : JpegAddr: jpeg圖像地址
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 用於軟件解碼的第一步,用於獲取JPEG分辨率以及采樣模式信息
*************************************************************************************************************************/
static void JPEG_DecodeHeader(u32 JpegAddr)
{
 JPEG->JpegAddr0 = JpegAddr;
 JPEG->JpegAddr1 = JpegAddr;   //jpeg圖片數據地址
 JPEG->Mode = 0x8;      //設置為解碼模式
 JPEG->IRQ = ENABLE_IRQ;    //使能中斷
 JPEG->Cntl = DISABLE_HW_DEC;  //解碼JPEG頭部
 JPEG->Misc = (NORMAL_DEC | YCBCR_MEMORY);
 JPEG->Start = 1;     //開始JPEG處理
}

 

/*************************************************************************************************************************
*函數      : static void JPEG_DecodeBody(u32 ImageAddr)
*功能      : 開始JPEG主體解碼(軟件控制解碼)
*參數      : ImageAddr: 解碼後圖像地址
*返回      : 無
*依賴  :  底層宏定義
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 軟件控制解碼的第二步,一定要先調用JPEG_StartParsingHeader
*************************************************************************************************************************/
static void JPEG_DecodeBody(u32 ImageAddr)
{
 JPEG->ImageAddr0 = ImageAddr;
 JPEG->ImageAddr1 = ImageAddr;  //解碼數據緩沖器地址
 JPEG->Cntl = 0;      //解碼JPEG頭部
 JPEG->Misc = 0;
 JPEG->ReStart = 1;     //開始主解碼處理
}


/*************************************************************************************************************************
*函數      : JPEG_ERROR JPEG_DecodeOneFrame(u32 JpgAddr, u32 ImageAddr, u32 jpegSize, JPEG_INFO *JpegInfo)
*功能      : 開始解碼一幀JPEG
*參數      : JpegAddr: jpeg圖像地址
*     ImageAddr: 解碼後圖像地址
*     jpegSize: 圖片數據大小
*     JpegInfo: 圖像信息結構指針
*返回      : JPEG_ERROR
*依賴  :  JPEG_StartParsingHeader;JPEG_StartDecodingBody
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 軟件控制解碼模式
*     修改源圖像地址128位對齊bug
*     20120113:增加尺寸非8或16倍數的jpeg圖片解碼功能,需要傳遞一個參數,即圖片大小,通過FileSize傳遞
*        非對齊的jpeg解碼效率將低於對齊的圖片,由於解碼前需要先改寫數據。
*************************************************************************************************************************/
JPEG_ERROR JPEG_DecodeOneFrame(u32 JpgAddr, u32 ImageAddr, u32 jpegSize, JPEG_INFO *JpegInfo)
{
 JPEG_ERROR status;
 u16  width,height;
 bool headerFixed = FALSE;
#if JPEG_DBUG 
 const char *JpegType[6] = {"JPEG 4:4:4","JPEG 4:2:2","JPEG 4:2:0","JPEG 4:0:0","JPEG 4:1:1","JPEG UNKNOWN"};
#endif
 
 if(JpgAddr % 16)     //源地址一定要是16字節(128位)對齊的,否則會出現各種意想不到的問題,這個問題困擾了我5個多月。
 { 
  jpeg_debug("jpeg addr error\r\n");
  return JPEG_OTHER_ERROR;
 }
 
 JpegInfo->FileSize = jpegSize;  //存儲圖片大小
 jpeg_debug("\r\n");
 jpeg_debug("start jpeg decoding...\r\n");
 JPEG_Reset();
 JPEG_DecodeHeader(JpgAddr);   //分析JPEG文信息
 status = JPEG_WaitForIRQ();   //等待完成
 if(status != JPEG_HEADER_OK)  //圖像分析錯誤
 {
  return status;
 }
 
 JpegInfo->Type = JPEG_GetJpegType();  //獲取圖片類型
 jpeg_debug("Jpeg Mod:%s\r\n",JpegType[JpegInfo->Type]);
 if(JpegInfo->Type == TYPE_JPEG_UNKNOWN) //未定義類型
 {
  return JPEG_TYPE_ERROR;
 }
 
 JPEG_GetWidthHeight(&(JpegInfo->Width),&(JpegInfo->Height));    //獲取圖片分辨率
 
 width = JpegInfo->Width;
 height = JpegInfo->Height;
 if(!JPEG_CorrectHeader(JpegInfo->Type, &(JpegInfo->Width), &(JpegInfo->Height)))
 {
        JPEG_WriteHeader(JpgAddr,jpegSize,JpegInfo->Width, JpegInfo->Height);
        headerFixed = TRUE;
 }
 
 jpeg_debug("jpeg image size %d*%d\r\n",JpegInfo->Width,JpegInfo->Height);
 
 
 if(JpegInfo->Width <= 0 || JpegInfo->Width > MAX_JPG_WIDTH || JpegInfo->Height <= 0 || JpegInfo->Height > MAX_JPG_HEIGHT)
 {
  return JPEG_SIZE_ERROR;
 }
 
 if(headerFixed == TRUE)
 {
  JPEG_Reset();
  JPEG_DecodeHeader(JpgAddr);   //分析JPEG文信息
  status = JPEG_WaitForIRQ();   //等待完成
  if(status != JPEG_HEADER_OK)  //圖像分析錯誤
  {
   return status;
  }
 
  JPEG_DecodeBody(ImageAddr);   //解碼JPEG
  status = JPEG_WaitForIRQ();   //等待完成
  if(status == JPEG_OK)
  {
   jpeg_debug("Jpeg decode OK(%d)\r\n",status);
   //JPEG_GetStreamLen(&(JpegInfo->DataSize)); //獲取解碼後圖像大小
  }
  else
  {
   jpeg_debug("Jpeg decode error(%d)\r\n",status);
   return status;
  }
 
  // for post processor, discard pixel
  if(width % 4 != 0)
   width = (width/4)*4;
 
        if(height % 2 != 0)
            height = (height/2)*2;
       
        JPEG_WriteYUV(ImageAddr,JpegInfo->Width,width,JpegInfo->Height,height);
     
        JpegInfo->Width = width;
        JpegInfo->Height = height;
 }
 else
 {
  JPEG_DecodeBody(ImageAddr);   //解碼JPEG
  status = JPEG_WaitForIRQ();   //等待完成
  if(status == JPEG_OK)
  {
   jpeg_debug("Jpeg decode OK(%d)\r\n",status);
   
  }
  else
  {
   jpeg_debug("Jpeg decode error(%d)\r\n",status);
   return status;
  }
 }
 JpegInfo->DataSize = JPEG_GetYUVSize(JpegInfo->Type,JpegInfo->Width,JpegInfo->Height);
 
 return status; //返回錯誤
}

 

/*************************************************************************************************************************
*函數      : JPEG_ERROR JPEG_EncodeOneFrame(u32 JpgAddr, u32 ImageAddr, JPEG_INFO *JpegInfo)
*功能      : 壓縮一張JPEG
*參數      : JpegAddr: jpeg圖像地址
*     ImageAddr: 解碼後圖像地址
*     JpegInfo: 圖像信息結構指針
*返回      : JPEG_ERROR
*依賴  :  無
*作者      : [email protected]
*時間      : 20130114
*最後修改時間 : 201310114
*說明      : 只支持YCbCr4:2:2,YCbCr4:2:0的輸入格式
*     只測試了編碼,能成功,但是沒有生成jpeg文件進行測試,如果要生成jpeg文件應該還需要添加相應的文件頭和尾部。
*************************************************************************************************************************/
JPEG_ERROR JPEG_EncodeOneFrame(u32 JpgAddr, u32 ImageAddr, JPEG_QUALITY_TYPE jpegQuality, JPEG_INFO *JpegInfo)
{
 JPEG_ERROR status = JPEG_OK;
    u32    i;

    if(JpegInfo->Width <= 0 || JpegInfo->Width > MAX_JPG_WIDTH || JpegInfo->Height <= 0 || JpegInfo->Height > MAX_JPG_HEIGHT)
 {
  return JPEG_SIZE_ERROR;
 }
   
    JPEG_Reset();
    JPEG->Mode = (JpegInfo->Type == TYPE_JPEG_422) ? (0x01 << 0) : (0x02 << 0);  //亞抽樣模式
    JPEG->RSTPos = 2;                // MCU inserts RST marker
    JPEG->QTblNo = (1 << 12) | (1 << 14);
    JPEG->Horizontal = JpegInfo->Width;
    JPEG->Vertical = JpegInfo->Height;

    JPEG->ImageAddr0 = ImageAddr;
    JPEG->ImageAddr1 = ImageAddr;
    JPEG->JpegAddr0 = JpgAddr;
    JPEG->JpegAddr1 = JpgAddr;
 
    JPEG->COEF1 = COEF1_RGB_2_YUV; // Coefficient value 1 for RGB to YCbCr
    JPEG->COEF2 = COEF2_RGB_2_YUV; // Coefficient value 2 for RGB to YCbCr
    JPEG->COEF3 = COEF3_RGB_2_YUV; // Coefficient value 3 for RGB to YCbCr

    JPEG->Misc = (1<<5) | (0<<2);
    JPEG->Cntl = DISABLE_MOTION_ENC;
   
    // Quantiazation and Huffman Table setting
    for (i=0; i<64; i++)
     JPEG->QTBL0[i] = (u32)QTBL_Luminance[jpegQuality][i];

    for (i=0; i<64; i++)
     JPEG->QTBL1[i] = (u32)QTBL_Chrominance[jpegQuality][i];

    for (i=0; i<16; i++)
     JPEG->HDCTBL0[i] = (u32)HDCTBL0[i];

    for (i=0; i<12; i++)
     JPEG->HDCTBLG0[i] = (u32)HDCTBLG0[i];

    for (i=0; i<16; i++)
     JPEG->HACTBL0[i] = (u32)HACTBL0[i];

    for (i=0; i<162; i++)
     JPEG->HACTBLG0[i] = (u32)HACTBLG0[i];

    JPEG->Start = 0;
   
    status = JPEG_WaitForIRQ();
    if(status == JPEG_OK)
    {
     jpeg_debug("Jpeg encode OK!(%d)\r\n",status);
     JpegInfo->FileSize = JPEG->DataSize;
    }
    else
    {
     JpegInfo->FileSize = 0;
     jpeg_debug("Jpeg encode error!(%d)\r\n",status);
    }
     
 return status;
}

 

/*************************************************************************************************************************
*函數      : static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height)
*功能      : 檢查圖像的寬高時候滿足要求
*參數      : jpegType: jpeg類型,見JPEG_TYPE
*     width:  圖像寬度
*     height:  圖像高度
*返回      : TRUE:需要重寫寬度,高度
*     FALSE:無需重寫寬度,高度
*依賴  :  無
*作者      : [email protected]
*時間      : 20130113
*最後修改時間 : 20130113
*說明      : 直接由S3C6410官方代碼移植而來
*     如果不滿足要求,將計算最接近的滿足要求的分辨率,JPEG分辨率需要能被8或者16整除,具體可以查閱相關資料
*************************************************************************************************************************/
static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height)
{
    bool result = FALSE;

    switch(jpegType){
        case TYPE_JPEG_400 :
        case TYPE_JPEG_444 :  
         {
          if((*width % 8 == 0) && (*height % 8 == 0))
                 result = TRUE;
                if(*width % 8 != 0)
                 *width += 8 - (*width % 8);
                if(*height % 8 != 0)
                 *height += 8 - (*height % 8);
                       
         }break;
        case TYPE_JPEG_422 :
         {
          if((*width % 16 == 0) && (*height % 8 == 0))
           result = TRUE;
          if(*width % 16 != 0)
           *width += 16 - (*width % 16);
          if(*height % 8 != 0)
           *height += 8 - (*height % 8);
         }break;
        case TYPE_JPEG_420 :
        case TYPE_JPEG_411 :
         {
          if((*width % 16 == 0) && (*height % 16 == 0))
           result = TRUE;
          if(*width % 16 != 0)
           *width += 16 - (*width % 16);
          if(*height % 16 != 0)
           *height += 16 - (*height % 16);
         }break;
        default : break;
    }
 
    return(result);
}

 


/*************************************************************************************************************************
*函數      : static void JPEG_WriteHeader(u32 JpgAddr, u32 fileSize, u16 width, u16 height)
*功能      : 重寫jpeg頭部信息
*參數      : JpgAddr:  jpeg文件的起始指針
*     fileSize: jpeg文件大小
*     width:  jpeg文件寬度,需要重寫的寬度
*     height:  jpeg文件高度,需要重寫的寬度
*返回      : 無
*依賴  :  無
*作者      : [email protected]
*時間      : 20130113
*最後修改時間 : 20130113
*說明      : 重寫的只是內存中的數據
*************************************************************************************************************************/
static void JPEG_WriteHeader(u32 JpgAddr, u32 fileSize, u16 width, u16 height)
{
    u32    i;
    u8    *ptr = (u8 *)(JpgAddr + fileSize);
    u8    *ptr2;
    u8    *SOF1;
    u8    *header;

    jpeg_debug("DD::Header is not multiple of MCU\r\n");
    for(i=0; i < fileSize; i++)
    {
        ptr--;
        if(*ptr == 0xFF)
        {
            ptr2 = ptr+1;
            if((*ptr2 == BASELINE) || (*ptr2 == EXTENDED_SEQ) || (*ptr2 == PROGRESSIVE))
            {
             jpeg_debug("jpeg match FFC0(i : %d)\r\n", i);
                SOF1 = ptr2+1;
                break;               
            }
        }
    }
    jpeg_debug("jpeg start header correction\r\n");
    if(i <= fileSize){
        //header = (SOF2 == NULL) ? (SOF1) : (SOF2);
        header = SOF1;
        jpeg_debug("header: %x %x %x\r\n", header[0], header[1], header[2]);
        header += 3; //length(2) + sampling bit(1)
        *header = (height>>8) & 0xFF;
        *header++;
        *header = height & 0xFF;
        *header++;
        *header = (width>>8) & 0xFF;
        *header++;
        *header = width & 0xFF;

    }
}

 

/*************************************************************************************************************************
*函數      : static void JPEG_MemMove(u8* dest, u8* src,u32 count)
*功能      : 由src所指內存區域復制count個字節到dest所指內存區域
*參數      : src:  源地址
*     dest: 目標地址
*     count: 數據數量
*返回      : 無
*依賴  :  無
*作者      : [email protected]
*時間      : 2013014
*最後修改時間 : 2013114
*說明      : 內存復制,8bit對齊,為了減少外部函數的依賴
*************************************************************************************************************************/
static void JPEG_MemMove(u8* dest, u8* src,u32 count)
{
 u32 i;
 
 for(i = 0;i < count;i ++)
 {
  dest[i] = src[i];
 }
}


/*************************************************************************************************************************
*函數      : static void JPEG_WriteYUV(u32 ImageAddr, u16 width, u16 orgwidth, u16 height, u16 orgheight)
*功能      : 重寫YUV數據,將數據對齊
*參數      : ImageAddr: 解碼後圖像地址
*     width:  圖像對齊後的寬度
*     orgwidth: 圖像原始寬度
*     height:  圖像對齊後的高度
*     orgheight: 圖像原始高度 
*返回      : 無
*依賴  :  無
*作者      : [email protected]
*時間      : 20120920
*最後修改時間 : 2010113
*說明      : 無
*************************************************************************************************************************/
static void JPEG_WriteYUV(u32 ImageAddr, u16 width, u16 orgwidth, u16 height, u16 orgheight)
{
    u32    src, dst;
    u32    i;
    u8    *streamPtr;

    streamPtr = (u8 *)ImageAddr;
    src = 2*width;
    dst = 2*orgwidth;
    for(i = 1; i < orgheight; i++)
    {
     JPEG_MemMove(&streamPtr[dst], &streamPtr[src], 2*orgwidth);
        src += 2*width;
        dst += 2*orgwidth;
    }
}

Copyright © Linux教程網 All Rights Reserved