歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> S3C6410 裸機硬件JPEG解碼

S3C6410 裸機硬件JPEG解碼

日期:2017/3/1 9:59:20   编辑:Linux編程

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