当前位置:首页 > 芯闻号 > 充电吧
[导读] 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月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭