当前位置:首页 > 芯闻号 > 充电吧
[导读] 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
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

据韩媒《朝鲜日报》消息,三星集团已确认已决定将适用于三星电子等部分关联公司的“高管每周工作 6 天”扩大到整个集团。三星子公司的人力资源团队直接通过口头、群聊和电子邮件向高管传达了这一新政,而非正式信函的形式。

关键字: 三星

近日有韩媒称,由于薪资谈判破裂,劳资双方未能缩小对涨薪的意见分歧,三星电子全国工会(NSEU)即日起将发起公司成立以来首次集体行动,工会当天在华城市(Hwaseong)京畿道华城园区的组件研究大楼(DSR)前举行文化活动...

关键字: 三星

美国商务部日前宣布,将向三星提供64亿美元的资助,用于在德克萨斯州建设芯片工厂。

关键字: 芯片工厂 芯片资助 三星

新型LPDDR5X是未来端侧人工智能的理想解决方案,预计将在个人电脑、加速器、服务器和汽车中得到更广泛的应用

关键字: 三星 人工智能 LPDDR5 处理器

业内消息,昨天美国政府宣布将向三星电子提供至多价值 64 亿美元(当前约合 464.64 亿元人民币)的补贴,而三星电子将在得克萨斯州投资超过 400 亿美元,建设包括 2nm 晶圆厂在内的一系列半导体项目。

关键字: 三星 2nm 晶圆厂

据韩联社报道,上周三星电子发布业绩报告显示,随着芯片价格反弹,预计今年第一季度营业利润同比骤增931.25%,为6.6万亿韩元(当前约合人民币354.6亿元),已经超过了2023年全年营业利润6.57万亿韩元。

关键字: 内存 三星

业内消息,上周韩媒报道三星SDI韩国基兴工厂发生火灾,随后三星SDI消防监督员向消防部门报案,消防部门赶往现场并花了约20分钟扑灭火情,火灾原因初步认定为建筑工地焊接引发,具体损失仍在调查中。

关键字: 三星 半导体

近日,三星电子和工会团体就 2024 年员工工资的上调问题举行了新一轮谈判,尽管双方在韩国劳动部委员会的介入进行了多次协商,但在加薪幅度上再次分道扬镳。

关键字: 三星 半导体

业内消息,近日又外媒报道三星电子有望在美国获得超过 60 亿美元(当前约合人民币 432 亿)的芯片法案补贴。

关键字: 三星

3月13日消息,据显示器供应链调研公司Display Supply Chain Consultant(DSCC)发布的预测数据,今年第一季度,华为折叠屏手机市场份额将首次超过三星电子。

关键字: 三星 半导体 芯片
关闭
关闭