当前位置:首页 > > 充电吧
[导读] 2012年12月25日,晚上我找到问题所在了,JPEG解码源图像地址必须是16字节(128位)对齐的,也就是最低4位必须为0,这个害的我好久,还好终于解决了。修复了已知的bug;这个是我实验用的原图

 

2012年12月25日,晚上我找到问题所在了,JPEG解码源图像地址必须是16字节(128位)对齐的,也就是最低4位必须为0,这个害的我好久,还好终于解决了。

修复了已知的bug;



这个是我实验用的原图,用工具把他变成了数组后直接放在程序里面了.

解码后的图片




附上代码


/*************************************************************************************************************
 * 文件名			:	JpegCodec.c
 * 功能			:	S3C6410 JPEG解码底层驱动函数
 * 作者			:	cp1300@139.com
 * 创建时间		:	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解码初始化
*参数    		:	无
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间     	:	20120920
*最后修改时间	:	20120923
*说明     	:	无
*************************************************************************************************************************/
void JPEG_Init(void)
{
	//rCLK_DIV0 |= 0x03 << 24;
	//Set_GateClk(SCLK_JPEG,ENABLE);	//使能JPEG模块时钟
}


/*************************************************************************************************************************
*函数    		:	static void JPEG_Reset(void)
*功能    		:	JPEG解码器软件复位
*参数    		:	无
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	20120920
*最后修改时间	:	2010113
*说明    		:	无
*************************************************************************************************************************/
static void JPEG_Reset(void)
{
	JPEG->SofReset = 0;
}


/*************************************************************************************************************************
*函数    		:	static JPEG_TYPE JPEG_Reset(void)
*功能    		:	获取JPEG采样模式
*参数    		:	无
*返回    		:	JPEG类型,见定义
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	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:图像高度缓冲区指针
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	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:图像尺寸
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	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:中断状态缓冲区指针
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	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<IRQStatus;		//读取中断状态寄存器,并消除状态 
        TimeOut --;             			//计数器自减  
    }  
    while((IRQStatus == 0) && TimeOut);     //当发生中断或者计数器为0时退出等待 
    IRQStatus &= ((1<<6)|(1<<4)|(1<Status;
    return error;
} 



/*************************************************************************************************************************
*函数    		:	static void JPEG_DecodeHeader(u32 JpegAddr)
*功能    		:	开始解码JPEG头部信息(软件控制解码)
*参数    		:	JpegAddr:	jpeg图像地址
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	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:	解码后图像地址
*返回    		:	无
*依赖		: 	底层宏定义
*作者     		:	cp1300@139.com
*时间    		:	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
*作者     		:	cp1300@139.com
*时间    		:	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 errorrn");
		return JPEG_OTHER_ERROR;
	}
	
	JpegInfo->FileSize = jpegSize;		//存储图片大小
	jpeg_debug("rn");
	jpeg_debug("start jpeg decoding...rn");
	JPEG_Reset();
	JPEG_DecodeHeader(JpgAddr);			//分析JPEG文信息
	status = JPEG_WaitForIRQ();			//等待完成
	if(status != JPEG_HEADER_OK)		//图像分析错误
	{
		return status;
	}
	
	JpegInfo->Type = JPEG_GetJpegType();		//获取图片类型
	jpeg_debug("Jpeg Mod:%srn",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*%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)		//图像分析错误
		{
			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;	//返回错误
}



/*************************************************************************************************************************
*函数    		:	JPEG_ERROR JPEG_EncodeOneFrame(u32 JpgAddr, u32 ImageAddr, JPEG_INFO *JpegInfo)
*功能    		:	压缩一张JPEG
*参数    		:	JpegAddr:	jpeg图像地址
* 				ImageAddr:	解码后图像地址
* 				JpegInfo:	图像信息结构指针
*返回    		:	JPEG_ERROR
*依赖		: 	无
*作者     		:	cp1300@139.com
*时间    		:	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 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;
}



/*************************************************************************************************************************
*函数    		:	static bool JPEG_CorrectHeader(JPEG_TYPE jpegType, u16 *width, u16 *height)
*功能    		:	检查图像的宽高时候满足要求
*参数    		:	jpegType:	jpeg类型,见JPEG_TYPE
* 				width:		图像宽度
* 				height:		图像高度
*返回    		:	TRUE:需要重写宽度,高度
* 				FALSE:无需重写宽度,高度
*依赖		: 	无
*作者     		:	cp1300@139.com
*时间    		:	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文件高度,需要重写的宽度
*返回    		:	无
*依赖		: 	无
*作者     		:	cp1300@139.com
*时间    		:	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 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;

    }
}



/*************************************************************************************************************************
*函数    		:	static void JPEG_MemMove(u8* dest, u8* src,u32 count)
*功能    		:	由src所指内存区域复制count个字节到dest所指内存区域
*参数    		:	src:		源地址
* 				dest:	目标地址
* 				count:	数据数量
*返回    		:	无
*依赖		: 	无
*作者     		:	cp1300@139.com
*时间    		:	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:	图像原始高度	
*返回    		:	无
*依赖		: 	无
*作者     		:	cp1300@139.com
*时间    		:	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;
    }
}



 

/*************************************************************************************************************
 * 文件名			:	JpegCodec.H
 * 功能			:	S3C6410 JPEG解码底层驱动函数
 * 作者			:	cp1300@139.com
 * 创建时间		:	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来取消,方便移植。
*************************************************************************************************************/
#ifndef __JPEGCODEC_H__
#define __JPEGCODEC_H__

#include "sys_types.h"		//数据类型定义


//JPEG类型定义
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,	//在被压缩的文件上,有语法错误
	JPEG_WAIT_TIME_OUT=	3,	//等待超时
	JPEG_TYPE_ERROR   = 4,	//不支持的图像类型,图像类型错误
	JPEG_SIZE_ERROR   = 5,	//图像大小错误,图像分辨率为0,或超出范围
	JPEG_OTHER_ERROR=	6	//其它未知错误,一般是地址未16字节对齐
} JPEG_ERROR;


//JPEG 文件信息
typedef struct
{
	u16 Width;		//图像宽度
	u16 Height;		//图像高度
	u32 FileSize;	//JPEG图片大小
	u32 DataSize;	//图像解码后数据大小
	JPEG_TYPE Type;	//图像类型定义
} JPEG_INFO;


//图像压缩质量等级
typedef enum
{
    JPEG_QUALITY_LEVEL_1 = 0, 	//高质量
    JPEG_QUALITY_LEVEL_2 = 1,
    JPEG_QUALITY_LEVEL_3 = 2,
    JPEG_QUALITY_LEVEL_4 = 3	//低质量   
}JPEG_QUALITY_TYPE;



//相关函数声明
void JPEG_Init(void);	//JPEG解码初始化
void JPEG_ReadClearStatus(u8* Status, u8* IrqStatus);//读取并清除JPEG状态
u32 JPEG_GetYUVSize(JPEG_TYPE jpegType,u16 width, u16 height);	//获取解码后数据大小
JPEG_ERROR JPEG_DecodeOneFrame(u32 JpgAddr, u32 ImageAddr, u32 jpegSize, JPEG_INFO *JpegInfo);//开始解码一帧JPEG
JPEG_ERROR JPEG_EncodeOneFrame(u32 JpgAddr, u32 ImageAddr, JPEG_QUALITY_TYPE jpegQuality, JPEG_INFO *JpegInfo);	//开始编码一张JPEG







#endif // __JPEGCODEC_H__


 

/*************************************************************************************************************
 * 文件名:	jpeg_tables.h
 * 功能:		S3C6410 jpeg编码表
 * 作者:		cp1300@139.com
 * 创建时间:	2013年01月14日
 * 最后修改时间:2013年01月14日
 * 详细:		直接使用的官方的代码
*************************************************************************************************************/
#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
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月4日消息,据媒体报道,SK海力士员工今年将发放约3万亿韩元的奖金,每位员工将获得超过1亿韩元(约合人民币51.3万元)的奖金。

关键字: SK海力士 DRAM 三星

8月21日消息,今天高通正式推出第二代骁龙W5+和第二代骁龙W5可穿戴平台,这是全球首批支持NB-NTN卫星通信的可穿戴平台。

关键字: 高通 三星 谷歌

8月7日消息,苹果公司宣布,三星电子位于得克萨斯州的工厂为包括iPhone在内的苹果产品供应芯片。苹果在声明中称,该工厂将供应能优化苹果产品(包括iPhone设备)功耗与性能的芯片。”对此,三星发言人拒绝发表评论。

关键字: 三星 存储芯片 DRAM

8月6日消息,据媒体报道,作为全球最早量产HBM4的存储器制造商,SK海力士正为AI芯片提供关键解决方案。依托与英伟达的独家供应链关系及自身技术领先地位,SK海力士计划提高HBM4售价,预计相比HBM3E溢价可能高达70...

关键字: QuestMobile AI搜 百度 夸克 SK海力士 DRAM 三星

8月3日消息,内存一哥三星在HBM技术栽了跟头,输给了SK海力士,错失几万亿美元的AI市场,但是三星现在要杀回来了。

关键字: 三星 存储芯片 DRAM

8月3日消息,近日,特斯拉与三星达成了一项价值165亿美元的芯片制造协议,根据协议,三星将为特斯拉生产下一代人工智能芯片,这些芯片将用于电动汽车和机器人。

关键字: 特斯拉 三星

7月29日消息,LG Display已将其在美国的70项LCD液晶显示器相关专利转让给三星显示,值得注意的是,三星显示已于三年前退出LCD业务。

关键字: LCD 三星

7月28日消息,据媒体报道,三星电子与特斯拉达成了一项价值高达165亿美元的芯片制造协议。知情人士透露,三星周一宣布获得价值22.8万亿韩元(约合165亿美元)的芯片制造合同,客户正是与其代工部门已有业务往来的特斯拉。

关键字: 三星 存储芯片 DRAM

当地时间本周一,韩国巨头三星电子向监管机构提交的一份文件显示,该公司已与一家大公司签订了一份价值165亿美元的芯片代工大单。

关键字: 三星 存储芯片 DRAM

7月22日消息,据媒体报道,三星决定推迟1.4nm工艺商用时间,全力提升2nm工艺的产能和良率。

关键字: 三星 存储芯片 DRAM
关闭