S3C6410 裸機(jī)硬件JPEG解碼
?
2012年12月25日,晚上我找到問(wèn)題所在了,JPEG解碼源圖像地址必須是16字節(jié)(128位)對(duì)齊的,也就是最低4位必須為0,這個(gè)害的我好久,還好終于解決了。
修復(fù)了已知的bug;
這個(gè)是我實(shí)驗(yàn)用的原圖,用工具把他變成了數(shù)組后直接放在程序里面了.
解碼后的圖片
附上代碼
/*************************************************************************************************************
?*?文件名 : JpegCodec.c
?*?功能 : S3C6410?JPEG解碼底層驅(qū)動(dòng)函數(shù)
?*?作者 : cp1300@139.com
?*?創(chuàng)建時(shí)間 : 2012年9月20日20:59
?*?最后修改時(shí)間 : 2012年12月02日
?*?詳細(xì) : JPEG硬解碼
?*? 通過(guò)S3C6410?DATASHEETV1.2版以及官方WINCE的JPEG驅(qū)動(dòng)的分析,得出結(jié)論,S3C6410的JPEG解碼模塊不支持硬件控制自動(dòng)解碼
?*? 只能使用軟件控制解碼模式
?*? 20121202:修復(fù)連續(xù)解碼BUG,目前有少數(shù)jpeg420,jpeg444會(huì)解碼出錯(cuò),就像windows也有可能有不支持的jpeg圖片一樣,少數(shù)圖片硬解碼
?*? 失敗可以嘗試使用軟解碼即可。
?*? 20121225:發(fā)現(xiàn)JPEG必須16字節(jié)(128位)地址對(duì)齊,否則可能會(huì)出現(xiàn)解碼失敗問(wèn)題。
?*? 20130113:增加尺寸非8或16倍數(shù)的jpeg圖片解碼功能
?*? 20130113:將程序外部依賴(lài)降低,目前只依賴(lài)外部的數(shù)據(jù)類(lèi)型定義(高類(lèi)聚,低耦合),打印調(diào)試也依賴(lài)外部,不用可以修改宏,JPEG_DBUG=0來(lái)取消,方便移植。
*************************************************************************************************************/
#include?"JpegCodec.h"
#include?"jpeg_tables.h"
//調(diào)試宏開(kāi)關(guān)
#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) //使能動(dòng)態(tài)編碼
#define?DISABLE_MOTION_ENC??????(0x0<<3)
#define?ENABLE_HW_DEC???????????(0x1<<2)
#define?DISABLE_HW_DEC??????????(0x0<<2)
#define?ENABLE_MOTION_DEC???????(0x1<<0) //使能動(dòng)態(tài)解碼
#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)
//等待超時(shí)定義
#define?WaitTimeOut 0xffffff //等待超時(shí)計(jì)數(shù)器
//定義最大圖像寬高度
#define?MAX_JPG_WIDTH 4096
#define?MAX_JPG_HEIGHT 4096
//JPEG寄存器結(jié)構(gòu)定義
typedef?struct
{
u32 Mode; //模式寄存器
u32 Status; //狀態(tài)寄存器
u32 QTblNo;
u32 RSTPos;
u32 Vertical; //垂直分辨率
u32 Horizontal; //水平分辨率
u32 DataSize; //壓縮數(shù)據(jù)字節(jié)數(shù)
u32 IRQ; //中斷設(shè)置寄存器
u32 IRQStatus; //中斷狀態(tài)寄存器 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解碼開(kāi)始
u32 ReStart; //重新開(kāi)始JPEG解碼
u32 SofReset; //JPEG復(fù)位
u32 Cntl; //控制寄存器
u32 COEF1;
u32 COEF2;
u32 COEF3;
u32 Misc; //雜項(xiàng)寄存器
u32 FramIntv;
}JPEG_TypeDef;
//定義JPEG文件標(biāo)記
enum
{
????UNKNOWN,
????BASELINE?=?0xC0,
????EXTENDED_SEQ?=?0xC1,
????PROGRESSIVE?=?0xC2
}JPG_SOF_MARKER;
//S3C6410?jpeg編解碼器基址
#define?JPEG_BASE 0x78800000
//寄存器結(jié)構(gòu)指針
#define?JPEG ((JPEG_TypeDef?*)JPEG_BASE)
//內(nèi)部靜態(tài)函數(shù)聲明
static?void?JPEG_Reset(void); //JPEG解碼器軟件復(fù)位
static?JPEG_TYPE?JPEG_GetJpegType(void); //獲取JPEG采樣模式
static?void?JPEG_GetWidthHeight(u16*?width,?u16*?height);//獲取圖像大小
static?JPEG_ERROR?JPEG_WaitForIRQ(void); //等待中斷,并返回狀態(tài)
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);
/*************************************************************************************************************************
*函數(shù)???? : void?JPEG_Init(void)
*功能???? : JPEG解碼初始化
*參數(shù)???? : 無(wú)
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間????? : 20120920
*最后修改時(shí)間 : 20120923
*說(shuō)明????? : 無(wú)
*************************************************************************************************************************/
void?JPEG_Init(void)
{
//rCLK_DIV0?|=?0x03?<<?24;
//Set_GateClk(SCLK_JPEG,ENABLE); //使能JPEG模塊時(shí)鐘
}
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_Reset(void)
*功能???? : JPEG解碼器軟件復(fù)位
*參數(shù)???? : 無(wú)
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 無(wú)
*************************************************************************************************************************/
static?void?JPEG_Reset(void)
{
JPEG->SofReset?=?0;
}
/*************************************************************************************************************************
*函數(shù)???? : static?JPEG_TYPE?JPEG_Reset(void)
*功能???? : 獲取JPEG采樣模式
*參數(shù)???? : 無(wú)
*返回???? : JPEG類(lèi)型,見(jiàn)定義
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 編碼模式只有0x1,0x2兩種模式
*************************************************************************************************************************/
static?JPEG_TYPE?JPEG_GetJpegType(void)
{
switch?(JPEG->Mode?&?0x07) //通過(guò)判斷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;
}
}
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_GetWidthHeight(u16*?width,?u16*?height)
*功能???? : 獲取圖像尺寸大小
*參數(shù)???? : HSize:圖像寬度緩沖區(qū)指針;VSize:圖像高度緩沖區(qū)指針
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 16BIT
*************************************************************************************************************************/
static?void?JPEG_GetWidthHeight(u16*?width,?u16*?height)
{
*width?=?JPEG->Horizontal; //在水平方向上定義圖像大小的值
*height?=?JPEG->Vertical; //在垂直方向上定義圖像大小的值
}
/*************************************************************************************************************************
*函數(shù)???? : u32?JPEG_GetYUVSize(JPEG_TYPE?jpegType,u16?width,?u16?height)
*功能???? : 獲取解碼后數(shù)據(jù)大小
*參數(shù)???? : jpegType:jpeg圖像類(lèi)型,width,height:圖像尺寸
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 2010113
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 無(wú)
*************************************************************************************************************************/
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);
}
}
/*************************************************************************************************************************
*函數(shù)???? : void?JPEG_ReadClearStatus(u8*?Status,?u8*?IrqStatus)
*功能???? : 讀取并清除JPEG狀態(tài)
*參數(shù)???? : Status:解碼器狀態(tài)緩沖區(qū)指針;IrqStatus:中斷狀態(tài)緩沖區(qū)指針
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : JPGSTS和JPGIRQ;JPGIRQ讀取后自動(dòng)清除
*? JPGIRQ: BIT6結(jié)果狀態(tài) 0:不正常的處理結(jié)束;?1:正常的處理完成
*? BIT4位流的錯(cuò)誤狀態(tài)。只有在解壓縮期間有效。0:在被壓縮的文件上,沒(méi)有語(yǔ)法錯(cuò)誤。1:在被壓縮的文件上,有語(yǔ)法錯(cuò)誤。
*? BIT3標(biāo)題狀態(tài)。只有在解壓縮期間有效。0:圖像大小和取樣因素值不可讀。1:圖像大小和取樣因素值可讀。
*************************************************************************************************************************/
void?JPEG_ReadClearStatus(u8*?Status,?u8*?IrqStatus)
{
*Status?=?JPEG->Status;
*IrqStatus?=?JPEG->IRQStatus?&?((1<<6)|(1<<4)|(1<IRQStatus; //讀取中斷狀態(tài)寄存器,并消除狀態(tài)?
????????TimeOut?--;????????????? //計(jì)數(shù)器自減??
????}??
????while((IRQStatus?==?0)?&&?TimeOut);?????//當(dāng)發(fā)生中斷或者計(jì)數(shù)器為0時(shí)退出等待?
????IRQStatus?&=?((1<<6)|(1<<4)|(1<Status;
????return?error;
}?
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_DecodeHeader(u32?JpegAddr)
*功能???? : 開(kāi)始解碼JPEG頭部信息(軟件控制解碼)
*參數(shù)???? : JpegAddr: jpeg圖像地址
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 用于軟件解碼的第一步,用于獲取JPEG分辨率以及采樣模式信息
*************************************************************************************************************************/
static?void?JPEG_DecodeHeader(u32?JpegAddr)
{
JPEG->JpegAddr0?=?JpegAddr;
JPEG->JpegAddr1?=?JpegAddr;? //jpeg圖片數(shù)據(jù)地址
JPEG->Mode?=?0x8;? //設(shè)置為解碼模式
JPEG->IRQ?=?ENABLE_IRQ; //使能中斷
JPEG->Cntl?=?DISABLE_HW_DEC; //解碼JPEG頭部
JPEG->Misc?=?(NORMAL_DEC?|?YCBCR_MEMORY);
JPEG->Start?=?1; //開(kāi)始JPEG處理
}
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_DecodeBody(u32?ImageAddr)
*功能???? : 開(kāi)始JPEG主體解碼(軟件控制解碼)
*參數(shù)???? : ImageAddr: 解碼后圖像地址
*返回???? : 無(wú)
*依賴(lài) :? 底層宏定義
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 軟件控制解碼的第二步,一定要先調(diào)用JPEG_StartParsingHeader
*************************************************************************************************************************/
static?void?JPEG_DecodeBody(u32?ImageAddr)
{
JPEG->ImageAddr0?=?ImageAddr;
JPEG->ImageAddr1?=?ImageAddr; //解碼數(shù)據(jù)緩沖器地址
JPEG->Cntl?=?0; //解碼JPEG頭部
JPEG->Misc?=?0;
JPEG->ReStart?=?1; //開(kāi)始主解碼處理
}
/*************************************************************************************************************************
*函數(shù)???? : JPEG_ERROR?JPEG_DecodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?u32?jpegSize,?JPEG_INFO?*JpegInfo)
*功能???? : 開(kāi)始解碼一幀JPEG
*參數(shù)???? : JpegAddr: jpeg圖像地址
*? ImageAddr: 解碼后圖像地址
*? jpegSize: 圖片數(shù)據(jù)大小
*? JpegInfo: 圖像信息結(jié)構(gòu)指針
*返回???? : JPEG_ERROR
*依賴(lài) :? JPEG_StartParsingHeader;JPEG_StartDecodingBody
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 軟件控制解碼模式
*? 修改源圖像地址128位對(duì)齊bug
*? 20120113:增加尺寸非8或16倍數(shù)的jpeg圖片解碼功能,需要傳遞一個(gè)參數(shù),即圖片大小,通過(guò)FileSize傳遞
*? 非對(duì)齊的jpeg解碼效率將低于對(duì)齊的圖片,由于解碼前需要先改寫(xiě)數(shù)據(jù)。
*************************************************************************************************************************/
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字節(jié)(128位)對(duì)齊的,否則會(huì)出現(xiàn)各種意想不到的問(wèn)題,這個(gè)問(wèn)題困擾了我5個(gè)多月。
{
jpeg_debug("jpeg?addr?errorrn");
return?JPEG_OTHER_ERROR;
}
JpegInfo->FileSize?=?jpegSize; //存儲(chǔ)圖片大小
jpeg_debug("rn");
jpeg_debug("start?jpeg?decoding...rn");
JPEG_Reset();
JPEG_DecodeHeader(JpgAddr); //分析JPEG文信息
status?=?JPEG_WaitForIRQ(); //等待完成
if(status?!=?JPEG_HEADER_OK) //圖像分析錯(cuò)誤
{
return?status;
}
JpegInfo->Type?=?JPEG_GetJpegType(); //獲取圖片類(lèi)型
jpeg_debug("Jpeg?Mod:%srn",JpegType[JpegInfo->Type]);
if(JpegInfo->Type?==?TYPE_JPEG_UNKNOWN) //未定義類(lèi)型
{
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*%drn",JpegInfo->Width,JpegInfo->Height);
if(JpegInfo->Width?Width?>?MAX_JPG_WIDTH?||?JpegInfo->Height?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) //圖像分析錯(cuò)誤
{
return?status;
}
JPEG_DecodeBody(ImageAddr); //解碼JPEG
status?=?JPEG_WaitForIRQ(); //等待完成
if(status?==?JPEG_OK)
{
jpeg_debug("Jpeg?decode?OK(%d)rn",status);
//JPEG_GetStreamLen(&(JpegInfo->DataSize)); //獲取解碼后圖像大小
}
else
{
jpeg_debug("Jpeg?decode?error(%d)rn",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)rn",status);
}
else
{
jpeg_debug("Jpeg?decode?error(%d)rn",status);
return?status;
}
}
JpegInfo->DataSize?=?JPEG_GetYUVSize(JpegInfo->Type,JpegInfo->Width,JpegInfo->Height);
return?status; //返回錯(cuò)誤
}
/*************************************************************************************************************************
*函數(shù)???? : JPEG_ERROR?JPEG_EncodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?JPEG_INFO?*JpegInfo)
*功能???? : 壓縮一張JPEG
*參數(shù)???? : JpegAddr: jpeg圖像地址
*? ImageAddr: 解碼后圖像地址
*? JpegInfo: 圖像信息結(jié)構(gòu)指針
*返回???? : JPEG_ERROR
*依賴(lài) :? 無(wú)
*作者????? : cp1300@139.com
*時(shí)間???? : 20130114
*最后修改時(shí)間 : 201310114
*說(shuō)明???? : 只支持YCbCr4:2:2,YCbCr4:2:0的輸入格式
*? 只測(cè)試了編碼,能成功,但是沒(méi)有生成jpeg文件進(jìn)行測(cè)試,如果要生成jpeg文件應(yīng)該還需要添加相應(yīng)的文件頭和尾部。
*************************************************************************************************************************/
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?Width?>?MAX_JPG_WIDTH?||?JpegInfo->Height?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<Cntl?=?DISABLE_MOTION_ENC;
????
????//?Quantiazation?and?Huffman?Table?setting
????for?(i=0;?iQTBL0[i]?=?(u32)QTBL_Luminance[jpegQuality][i];
????for?(i=0;?iQTBL1[i]?=?(u32)QTBL_Chrominance[jpegQuality][i];
????for?(i=0;?iHDCTBL0[i]?=?(u32)HDCTBL0[i];
????for?(i=0;?iHDCTBLG0[i]?=?(u32)HDCTBLG0[i];
????for?(i=0;?iHACTBL0[i]?=?(u32)HACTBL0[i];
????for?(i=0;?iHACTBLG0[i]?=?(u32)HACTBLG0[i];
????JPEG->Start?=?0;
????
????status?=?JPEG_WaitForIRQ();
????if(status?==?JPEG_OK)
????{
???? jpeg_debug("Jpeg?encode?OK!(%d)rn",status);
???? JpegInfo->FileSize?=?JPEG->DataSize;
????}
????else
????{
???? JpegInfo->FileSize?=?0;
???? jpeg_debug("Jpeg?encode?error!(%d)rn",status);
????}
????
return?status;
}
/*************************************************************************************************************************
*函數(shù)???? : static?bool?JPEG_CorrectHeader(JPEG_TYPE?jpegType,?u16?*width,?u16?*height)
*功能???? : 檢查圖像的寬高時(shí)候滿(mǎn)足要求
*參數(shù)???? : jpegType: jpeg類(lèi)型,見(jiàn)JPEG_TYPE
*? width: 圖像寬度
*? height: 圖像高度
*返回???? : TRUE:需要重寫(xiě)寬度,高度
*? FALSE:無(wú)需重寫(xiě)寬度,高度
*依賴(lài) :? 無(wú)
*作者????? : cp1300@139.com
*時(shí)間???? : 20130113
*最后修改時(shí)間 : 20130113
*說(shuō)明???? : 直接由S3C6410官方代碼移植而來(lái)
*? 如果不滿(mǎn)足要求,將計(jì)算最接近的滿(mǎn)足要求的分辨率,JPEG分辨率需要能被8或者16整除,具體可以查閱相關(guān)資料
*************************************************************************************************************************/
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);
}
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_WriteHeader(u32?JpgAddr,?u32?fileSize,?u16?width,?u16?height)
*功能???? : 重寫(xiě)jpeg頭部信息
*參數(shù)???? : JpgAddr: jpeg文件的起始指針
*? fileSize: jpeg文件大小
*? width: jpeg文件寬度,需要重寫(xiě)的寬度
*? height: jpeg文件高度,需要重寫(xiě)的寬度
*返回???? : 無(wú)
*依賴(lài) :? 無(wú)
*作者????? : cp1300@139.com
*時(shí)間???? : 20130113
*最后修改時(shí)間 : 20130113
*說(shuō)明???? : 重寫(xiě)的只是內(nèi)存中的數(shù)據(jù)
*************************************************************************************************************************/
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?MCUrn");
????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)rn",?i);
????????????????SOF1?=?ptr2+1;
????????????????break;????????????????
????????????}
????????}
????}
????jpeg_debug("jpeg?start?header?correctionrn");
????if(i?>8)?&?0xFF;
????????*header++;
????????*header?=?height?&?0xFF;
????????*header++;
????????*header?=?(width>>8)?&?0xFF;
????????*header++;
????????*header?=?width?&?0xFF;
????}
}
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_MemMove(u8*?dest,?u8*?src,u32?count)
*功能???? : 由src所指內(nèi)存區(qū)域復(fù)制count個(gè)字節(jié)到dest所指內(nèi)存區(qū)域
*參數(shù)???? : src: 源地址
*? dest: 目標(biāo)地址
*? count: 數(shù)據(jù)數(shù)量
*返回???? : 無(wú)
*依賴(lài) :? 無(wú)
*作者????? : cp1300@139.com
*時(shí)間???? : 2013014
*最后修改時(shí)間 : 2013114
*說(shuō)明???? : 內(nèi)存復(fù)制,8bit對(duì)齊,為了減少外部函數(shù)的依賴(lài)
*************************************************************************************************************************/
static?void?JPEG_MemMove(u8*?dest,?u8*?src,u32?count)
{
u32?i;
for(i?=?0;i?<?count;i?++)
{
dest[i]?=?src[i];
}
}
/*************************************************************************************************************************
*函數(shù)???? : static?void?JPEG_WriteYUV(u32?ImageAddr,?u16?width,?u16?orgwidth,?u16?height,?u16?orgheight)
*功能???? : 重寫(xiě)YUV數(shù)據(jù),將數(shù)據(jù)對(duì)齊
*參數(shù)???? : ImageAddr: 解碼后圖像地址
*? width: 圖像對(duì)齊后的寬度
*? orgwidth: 圖像原始寬度
*? height: 圖像對(duì)齊后的高度
*? orgheight: 圖像原始高度
*返回???? : 無(wú)
*依賴(lài) :? 無(wú)
*作者????? : cp1300@139.com
*時(shí)間???? : 20120920
*最后修改時(shí)間 : 2010113
*說(shuō)明???? : 無(wú)
*************************************************************************************************************************/
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;
????}
}
?
/*************************************************************************************************************
?*?文件名 : JpegCodec.H
?*?功能 : S3C6410?JPEG解碼底層驅(qū)動(dòng)函數(shù)
?*?作者 : cp1300@139.com
?*?創(chuàng)建時(shí)間 : 2012年9月20日20:59
?*?最后修改時(shí)間 : 2012年12月02日
?*?詳細(xì) : JPEG硬解碼
?*? 通過(guò)S3C6410?DATASHEETV1.2版以及官方WINCE的JPEG驅(qū)動(dòng)的分析,得出結(jié)論,S3C6410的JPEG解碼模塊不支持硬件控制自動(dòng)解碼
?*? 只能使用軟件控制解碼模式
?*? 20121202:修復(fù)連續(xù)解碼BUG,目前有少數(shù)jpeg420,jpeg444會(huì)解碼出錯(cuò),就像windows也有可能有不支持的jpeg圖片一樣,少數(shù)圖片硬解碼
?*? 失敗可以嘗試使用軟解碼即可。
?*? 20121225:發(fā)現(xiàn)JPEG必須16字節(jié)(128位)地址對(duì)齊,否則可能會(huì)出現(xiàn)解碼失敗問(wèn)題。
?*? 20130113:增加尺寸非8或16倍數(shù)的jpeg圖片解碼功能
?*? 20130113:將程序外部依賴(lài)降低,目前只依賴(lài)外部的數(shù)據(jù)類(lèi)型定義,打印調(diào)試也依賴(lài)外部,不用可以修改宏,JPEG_DBUG=0來(lái)取消,方便移植。
*************************************************************************************************************/
#ifndef?__JPEGCODEC_H__
#define?__JPEGCODEC_H__
#include?"sys_types.h" //數(shù)據(jù)類(lèi)型定義
//JPEG類(lèi)型定義
typedef?enum
{
TYPE_JPEG_444?=?0,? //JPEG?444
TYPE_JPEG_422?=?1,? //JPEG?422
TYPE_JPEG_420?=?2,? //JPEG?420
TYPE_JPEG_400?=?3,? //JPEG?400?(Gray)
TYPE_JPEG_411?=?4, //JPEG?411
TYPE_JPEG_UNKNOWN?=?5 //未知
}?JPEG_TYPE;
//JPEG?DEC模式
typedef?enum
{
DEC_HEADER?=?0,? //只解碼頭部信息
DEC_BODY?=?1,? //只解碼主體
}?JPEG_DEC_MODE;
//JPEG?DEC模式
typedef?enum
{
JPEG_OK = 0, //正常處理完成
JPEG_HEADER_OK = 1, //圖像大小和取樣因素值可讀。
JPEG_BITSTRE_ERROR= 2, //在被壓縮的文件上,有語(yǔ)法錯(cuò)誤
JPEG_WAIT_TIME_OUT= 3, //等待超時(shí)
JPEG_TYPE_ERROR???=?4, //不支持的圖像類(lèi)型,圖像類(lèi)型錯(cuò)誤
JPEG_SIZE_ERROR???=?5, //圖像大小錯(cuò)誤,圖像分辨率為0,或超出范圍
JPEG_OTHER_ERROR= 6 //其它未知錯(cuò)誤,一般是地址未16字節(jié)對(duì)齊
}?JPEG_ERROR;
//JPEG?文件信息
typedef?struct
{
u16?Width; //圖像寬度
u16?Height; //圖像高度
u32?FileSize; //JPEG圖片大小
u32?DataSize; //圖像解碼后數(shù)據(jù)大小
JPEG_TYPE?Type; //圖像類(lèi)型定義
}?JPEG_INFO;
//圖像壓縮質(zhì)量等級(jí)
typedef?enum
{
????JPEG_QUALITY_LEVEL_1?=?0,? //高質(zhì)量
????JPEG_QUALITY_LEVEL_2?=?1,
????JPEG_QUALITY_LEVEL_3?=?2,
????JPEG_QUALITY_LEVEL_4?=?3 //低質(zhì)量???
}JPEG_QUALITY_TYPE;
//相關(guān)函數(shù)聲明
void?JPEG_Init(void); //JPEG解碼初始化
void?JPEG_ReadClearStatus(u8*?Status,?u8*?IrqStatus);//讀取并清除JPEG狀態(tài)
u32?JPEG_GetYUVSize(JPEG_TYPE?jpegType,u16?width,?u16?height); //獲取解碼后數(shù)據(jù)大小
JPEG_ERROR?JPEG_DecodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?u32?jpegSize,?JPEG_INFO?*JpegInfo);//開(kāi)始解碼一幀JPEG
JPEG_ERROR?JPEG_EncodeOneFrame(u32?JpgAddr,?u32?ImageAddr,?JPEG_QUALITY_TYPE?jpegQuality,?JPEG_INFO?*JpegInfo); //開(kāi)始編碼一張JPEG
#endif?//?__JPEGCODEC_H__
?
/*************************************************************************************************************
?*?文件名: jpeg_tables.h
?*?功能: S3C6410?jpeg編碼表
?*?作者: cp1300@139.com
?*?創(chuàng)建時(shí)間: 2013年01月14日
?*?最后修改時(shí)間:2013年01月14日
?*?詳細(xì): 直接使用的官方的代碼
*************************************************************************************************************/
#ifndef?__JPEG_TABLES_H__
#define?__JPEG_TABLES_H__
const?unsigned?char?QTBL_Luminance[4][64]=
{
????//?level?1?-?high?quality
????{
????????8,?6,?6,?8,?12,?14,?16,?17,
????????6,?6,?6,?8,?10,?13,?12,?15,
????????6,?6,?7,?8,?13,?14,?18,?24,
????????8,?8,?8,?14,?13,?19,?24,?35,
????????12,?10,?13,?13,?20,?26,?34,?39,
????????14,?13,?14,?19,?26,?34,?39,?39,
????????16,?12,?18,?24,?34,?39,?39,?39,
????????17,?15,?24,?35,?39,?39,?39,?39
????},????
????//?level?2
????{
????????12,?8,?8,?12,?17,?21,?24,?23,?
????????8,?9,?9,?11,?15,?19,?18,?23,?
????????8,?9,?10,?12,?19,?20,?27,?36,?
????????12,?11,?12,?21,?20,?28,?36,?53,?
????????17,?15,?19,?20,?30,?39,?51,?59,?
????????21,?19,?20,?28,?39,?51,?59,?59,?
????????24,?18,?27,?36,?51,?59,?59,?59,?
????????23,?23,?36,?53,?59,?59,?59,?59?
????},
????//?level?3
????{
????????16,?11,?11,?16,?23,?27,?31,?30,?
????????11,?12,?12,?15,?20,?23,?23,?30,?
????????11,?12,?13,?16,?23,?26,?35,?47,?
????????16,?15,?16,?23,?26,?37,?47,?64,?
????????23,?20,?23,?26,?39,?51,?64,?64,?
????????27,?23,?26,?37,?51,?64,?64,?64,?
????????31,?23,?35,?47,?64,?64,?64,?64,?
????????30,?30,?47,?64,?64,?64,?64,?64?
????},
????//?level?4?-?low?quality
????{
????????20,?16,?25,?39,?50,?46,?62,?68,?
????????16,?18,?23,?38,?38,?53,?65,?68,?
????????25,?23,?31,?38,?53,?65,?68,?68,?
????????39,?38,?38,?53,?65,?68,?68,?68,?
????????50,?38,?53,?65,?68,?68,?68,?68,?
????????46,?53,?65,?68,?68,?68,?68,?68,?
????????62,?65,?68,?68,?68,?68,?68,?68,?
????????68,?68,?68,?68,?68,?68,?68,?68?
????}
};
const?unsigned?char?QTBL_Chrominance[4][64]=
{
????//?level?1?-?high?quality
????{
????????9,?8,?9,?11,?14,?17,?19,?24,?
????????8,?10,?9,?11,?14,?13,?17,?22,?
????????9,?9,?13,?14,?13,?15,?23,?26,?
????????11,?11,?14,?14,?15,?20,?26,?33,?
????????14,?14,?13,?15,?20,?24,?33,?39,?
????????17,?13,?15,?20,?24,?32,?39,?39,?
????????19,?17,?23,?26,?33,?39,?39,?39,?
????????24,?22,?26,?33,?39,?39,?39,?39
????},
????//?level?2
????{
????????13,?11,?13,?16,?20,?20,?29,?37,?
????????11,?14,?14,?14,?16,?20,?26,?32,?
????????13,?14,?15,?17,?20,?23,?35,?40,?
????????16,?14,?17,?21,?23,?30,?40,?50,?
????????20,?16,?20,?23,?30,?37,?50,?59,?
????????20,?20,?23,?30,?37,?48,?59,?59,?
????????29,?26,?35,?40,?50,?59,?59,?59,?
????????37,?32,?40,?50,?59,?59,?59,?59?
????},
????//?level?3
????{
????????17,?15,?17,?21,?20,?26,?38,?48,?
????????15,?19,?18,?17,?20,?26,?35,?43,?
????????17,?18,?20,?22,?26,?30,?46,?53,?
????????21,?17,?22,?28,?30,?39,?53,?64,?
????????20,?20,?26,?30,?39,?48,?64,?64,?
????????26,?26,?30,?39,?48,?63,?64,?64,?
????????38,?35,?46,?53,?64,?64,?64,?64,?
????????48,?43,?53,?64,?64,?64,?64,?64?
?
????},
????//?level?4?-?low?quality
????{
????????21,?25,?32,?38,?54,?68,?68,?68,?
????????25,?28,?24,?38,?54,?68,?68,?68,?
????????32,?24,?32,?43,?66,?68,?68,?68,?
????????38,?38,?43,?53,?68,?68,?68,?68,?
????????54,?54,?66,?68,?68,?68,?68,?68,?
????????68,?68,?68,?68,?68,?68,?68,?68,?
????????68,?68,?68,?68,?68,?68,?68,?68,?
????????68,?68,?68,?68,?68,?68,?68,?68?
?
????}
};
const?unsigned?char?QTBL0[64]=
{
#if?1
????0x10,?0x0B,?0x0A,?0x10,?0x18,?0x28,?0x33,?0x3D,
????0x0C,?0x0C,?0x0E,?0x13,?0x1A,?0x3A,?0x3C,?0x37,
????0x0E,?0x0D,?0x10,?0x18,?0x28,?0x39,?0x45,?0x38,
????0x0E,?0x11,?0x16,?0x1D,?0x33,?0x57,?0x50,?0x3E,
????0x12,?0x16,?0x25,?0x38,?0x44,?0x6D,?0x67,?0x4D,
????0x18,?0x23,?0x37,?0x40,?0x51,?0x68,?0x71,?0x5C,
????0x31,?0x40,?0x4E,?0x57,?0x67,?0x79,?0x78,?0x65,
????0x48,?0x5C,?0x5F,?0x62,?0x70,?0x64,?0x67,?0x63
#else
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,
????0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01,?0x01
#endif
};
//Added?Quantization?Table
const?unsigned?char?std_chrominance_quant_tbl_plus[64]=
{????
????0x11,?0x12,?0x18,?0x2F,?0x63,?0x63,?0x63,?0x63,
????0x12,?0x15,?0x1A,?0x42,?0x63,?0x63,?0x63,?0x63,
????0x18,?0x1A,?0x38,?0x63,?0x63,?0x63,?0x63,?0x63,
????0x2F,?0x42,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,
????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,
????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,
????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,
????0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63,?0x63
};
//Quantization?Table0
unsigned?char?std_luminance_quant_tbl[64]?=
{
????1,???1,???2,???1,???1,???2,???2,???2,
????2,???3,???2,???2,???3,???3,???6,???4,
????3,???3,???3,???3,???7,???5,???8,???4,
????6,???8,???8,??10,???9,???8,???7,??11,
????8,??10,??14,??13,??11,??10,??10,??12,
????10,???8,???8,??11,??16,??12,??12,??13,
????15,??15,??15,??15,???9,??11,??16,??17,
????15,??14,??17,??13,??14,??14,??14,???1
?};
//Quantization?Table1
unsigned?char?std_chrominance_quant_tbl[64]?=
{
????4,???4,???4,???5,???4,???5,???9,???5,
????5,???9,??15,??10,???8,??10,??15,??26,
????19,???9,???9,??19,??26,??26,??26,??26,
????13,??26,??26,??26,??26,??26,??26,??26,
????26,??26,??26,??26,??26,??26,??26,??26,
????26,??26,??26,??26,??26,??26,??26,??26,
????26,??26,??26,??26,??26,??26,??26,??26,
????26,??26,??26,??26,??26,??26,??26,??26
};
//Huffman?Table
unsigned?char?HDCTBL0[16]??=?{0,?1,?5,?1,?1,?1,?1,?1,?1,?0,?0,?0,?0,?0,?0,?0};
unsigned?char?HDCTBLG0[12]?=?{0,?1,?2,?3,?4,?5,?6,?7,?8,?9,?0xa,?0xb};
unsigned?char?HACTBL0[16]=?{0,?2,?1,?3,?3,?2,?4,?3,?5,?5,?4,?4,?0,?0,?1,?0x7d};
const?unsigned?char?HACTBLG0[162]=
{
????0x01,?0x02,?0x03,?0x00,?0x04,?0x11,?0x05,?0x12,
????0x21,?0x31,?0x41,?0x06,?0x13,?0x51,?0x61,?0x07,
????0x22,?0x71,?0x14,?0x32,?0x81,?0x91,?0xa1,?0x08,
????0x23,?0x42,?0xb1,?0xc1,?0x15,?0x52,?0xd1,?0xf0,
????0x24,?0x33,?0x62,?0x72,?0x82,?0x09,?0x0a,?0x16,
????0x17,?0x18,?0x19,?0x1a,?0x25,?0x26,?0x27,?0x28,
????0x29,?0x2a,?0x34,?0x35,?0x36,?0x37,?0x38,?0x39,
????0x3a,?0x43,?0x44,?0x45,?0x46,?0x47,?0x48,?0x49,
????0x4a,?0x53,?0x54,?0x55,?0x56,?0x57,?0x58,?0x59,
????0x5a,?0x63,?0x64,?0x65,?0x66,?0x67,?0x68,?0x69,
????0x6a,?0x73,?0x74,?0x75,?0x76,?0x77,?0x78,?0x79,
????0x7a,?0x83,?0x84,?0x85,?0x86,?0x87,?0x88,?0x89,
????0x8a,?0x92,?0x93,?0x94,?0x95,?0x96,?0x97,?0x98,
????0x99,?0x9a,?0xa2,?0xa3,?0xa4,?0xa5,?0xa6,?0xa7,
????0xa8,?0xa9,?0xaa,?0xb2,?0xb3,?0xb4,?0xb5,?0xb6,
????0xb7,?0xb8,?0xb9,?0xba,?0xc2,?0xc3,?0xc4,?0xc5,
????0xc6,?0xc7,?0xc8,?0xc9,?0xca,?0xd2,?0xd3,?0xd4,
????0xd5,?0xd6,?0xd7,?0xd8,?0xd9,?0xda,?0xe1,?0xe2,
????0xe3,?0xe4,?0xe5,?0xe6,?0xe7,?0xe8,?0xe9,?0xea,
????0xf1,?0xf2,?0xf3,?0xf4,?0xf5,?0xf6,?0xf7,?0xf8,
????0xf9,?0xfa
};
//Huffman?Table0
unsigned?char?len_dc_luminance[16]?={?0,?1,?5,?1,?1,?1,?1,?1,?1,?0,?0,?0,?0,?0,?0,?0?};
unsigned?char?val_dc_luminance[12]?={?0,?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11?};
unsigned?char?len_ac_luminance[16]?={?0,?2,?1,?3,?3,?2,?4,?3,?5,?5,?4,?4,?0,?0,?1,?0x7d?};
unsigned?char?val_ac_luminance[162]?=
{
????0x01,?0x02,?0x03,?0x00,?0x04,?0x11,?0x05,?0x12,
????0x21,?0x31,?0x41,?0x06,?0x13,?0x51,?0x61,?0x07,
????0x22,?0x71,?0x14,?0x32,?0x81,?0x91,?0xa1,?0x08,
????0x23,?0x42,?0xb1,?0xc1,?0x15,?0x52,?0xd1,?0xf0,
????0x24,?0x33,?0x62,?0x72,?0x82,?0x09,?0x0a,?0x16,
????0x17,?0x18,?0x19,?0x1a,?0x25,?0x26,?0x27,?0x28,
????0x29,?0x2a,?0x34,?0x35,?0x36,?0x37,?0x38,?0x39,
????0x3a,?0x43,?0x44,?0x45,?0x46,?0x47,?0x48,?0x49,
????0x4a,?0x53,?0x54,?0x55,?0x56,?0x57,?0x58,?0x59,
????0x5a,?0x63,?0x64,?0x65,?0x66,?0x67,?0x68,?0x69,
????0x6a,?0x73,?0x74,?0x75,?0x76,?0 




