首页 / 操作系统 / Linux / S3C6410 裸机硬件JPEG解码
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<<3)); } /************************************************************************************************************************* *函数 : static JPEG_ERROR JPEG_WaitForIRQ(void) *功能 : 等待中断,并返回状态 *参数 : 无 *返回 : 返回中断状态,见定义 *依赖 : 底层宏定义 *作者 : cp1300@139.com *时间 : 20120922 *最后修改时间 : 2010113 *说明 : 通过判断JPGIRQ中断寄存器的值返回相应状态 *************************************************************************************************************************/ static JPEG_ERROR JPEG_WaitForIRQ(void) { vu32 TimeOut = WaitTimeOut; //初始化计数器值 vu8 IRQStatus,Status; JPEG_ERROR error; do { IRQStatus = JPEG->IRQStatus; //读取中断状态寄存器,并消除状态 TimeOut --; //计数器自减 } while((IRQStatus == 0) && TimeOut); //当发生中断或者计数器为0时退出等待 IRQStatus &= ((1<<6)|(1<<4)|(1<<3)); switch (IRQStatus) //判断中断状态 { case 0x00 : error = JPEG_WAIT_TIME_OUT;break; //超时错误 case 0x40 : error = JPEG_OK;break; //正常完成 case 0x08 : error = JPEG_HEADER_OK;break; //头分析完成,可以读取大小以及采样信息 case 0x10 : error = JPEG_BITSTRE_ERROR;break; //语法错误 case 0x18 : error = JPEG_BITSTRE_ERROR;break; //语法错误 default : error = JPEG_OTHER_ERROR;break; //其它错误 } Status = JPEG->Status; return error; } /************************************************************************************************************************* *函数 : static void JPEG_DecodeHeader(u32 JpegAddr) *功能 : 开始解码JPEG头部信息(软件控制解码) *参数 : JpegAddr: jpeg图像地址 *返回 : 无 *依赖 : 底层宏定义 *作者 : 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 error
"); return JPEG_OTHER_ERROR; } JpegInfo->FileSize = jpegSize; //存储图片大小 jpeg_debug("
"); jpeg_debug("start jpeg decoding...
"); JPEG_Reset(); JPEG_DecodeHeader(JpgAddr); //分析JPEG文信息 status = JPEG_WaitForIRQ(); //等待完成 if(status != JPEG_HEADER_OK) //图像分析错误 { return status; } JpegInfo->Type = JPEG_GetJpegType(); //获取图片类型 jpeg_debug("Jpeg Mod:%s
",JpegType[JpegInfo->Type]); if(JpegInfo->Type == TYPE_JPEG_UNKNOWN) //未定义类型 { return JPEG_TYPE_ERROR; } JPEG_GetWidthHeight(&(JpegInfo->Width),&(JpegInfo->Height)); //获取图片分辨率 width = JpegInfo->Width; height = JpegInfo->Height; if(!JPEG_CorrectHeader(JpegInfo->Type, &(JpegInfo->Width), &(JpegInfo->Height))) { JPEG_WriteHeader(JpgAddr,jpegSize,JpegInfo->Width, JpegInfo->Height); headerFixed = TRUE; } jpeg_debug("jpeg image size %d*%d
",JpegInfo->Width,JpegInfo->Height); if(JpegInfo->Width <= 0 || JpegInfo->Width > MAX_JPG_WIDTH || JpegInfo->Height <= 0 || JpegInfo->Height > MAX_JPG_HEIGHT) { return JPEG_SIZE_ERROR; } if(headerFixed == TRUE) { JPEG_Reset(); JPEG_DecodeHeader(JpgAddr); //分析JPEG文信息 status = JPEG_WaitForIRQ(); //等待完成 if(status != JPEG_HEADER_OK) //图像分析错误 { return status; } JPEG_DecodeBody(ImageAddr); //解码JPEG status = JPEG_WaitForIRQ(); //等待完成 if(status == JPEG_OK) { jpeg_debug("Jpeg decode OK(%d)
",status); //JPEG_GetStreamLen(&(JpegInfo->DataSize)); //获取解码后图像大小 } else { jpeg_debug("Jpeg decode error(%d)
",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)
",status); } else { jpeg_debug("Jpeg decode error(%d)
",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 <= 0 || JpegInfo->Width > MAX_JPG_WIDTH || JpegInfo->Height <= 0 || JpegInfo->Height > MAX_JPG_HEIGHT) { return JPEG_SIZE_ERROR; } JPEG_Reset(); JPEG->Mode = (JpegInfo->Type == TYPE_JPEG_422) ? (0x01 << 0) : (0x02 << 0); //亚抽样模式 JPEG->RSTPos = 2; // MCU inserts RST marker JPEG->QTblNo = (1 << 12) | (1 << 14); JPEG->Horizontal = JpegInfo->Width; JPEG->Vertical = JpegInfo->Height; JPEG->ImageAddr0 = ImageAddr; JPEG->ImageAddr1 = ImageAddr; JPEG->JpegAddr0 = JpgAddr; JPEG->JpegAddr1 = JpgAddr; JPEG->COEF1 = COEF1_RGB_2_YUV; // Coefficient value 1 for RGB to YCbCr JPEG->COEF2 = COEF2_RGB_2_YUV; // Coefficient value 2 for RGB to YCbCr JPEG->COEF3 = COEF3_RGB_2_YUV; // Coefficient value 3 for RGB to YCbCr JPEG->Misc = (1<<5) | (0<<2); JPEG->Cntl = DISABLE_MOTION_ENC; // Quantiazation and Huffman Table setting for (i=0; i<64; i++) JPEG->QTBL0[i] = (u32)QTBL_Luminance[jpegQuality][i]; for (i=0; i<64; i++) JPEG->QTBL1[i] = (u32)QTBL_Chrominance[jpegQuality][i]; for (i=0; i<16; i++) JPEG->HDCTBL0[i] = (u32)HDCTBL0[i]; for (i=0; i<12; i++) JPEG->HDCTBLG0[i] = (u32)HDCTBLG0[i]; for (i=0; i<16; i++) JPEG->HACTBL0[i] = (u32)HACTBL0[i]; for (i=0; i<162; i++) JPEG->HACTBLG0[i] = (u32)HACTBLG0[i]; JPEG->Start = 0; status = JPEG_WaitForIRQ(); if(status == JPEG_OK) { jpeg_debug("Jpeg encode OK!(%d)
",status); JpegInfo->FileSize = JPEG->DataSize; } else { JpegInfo->FileSize = 0; jpeg_debug("Jpeg encode error!(%d)
",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 MCU
"); 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)
", i); SOF1 = ptr2+1; break; } } } jpeg_debug("jpeg start header correction
"); if(i <= fileSize){ //header = (SOF2 == NULL) ? (SOF1) : (SOF2); header = SOF1; jpeg_debug("header: %x %x %x
", header[0], header[1], header[2]); header += 3; //length(2) + sampling bit(1) *header = (height>>8) & 0xFF; *header++; *header = height & 0xFF; *header++; *header = (width>>8) & 0xFF; *header++; *header = width & 0xFF; } } /************************************************************************************************************************* *函数 : static void JPEG_MemMove(u8* dest, u8* src,u32 count) *功能 : 由src所指内存区域复制count个字节到dest所指内存区域 *参数 : src: 源地址 * dest: 目标地址 * count: 数据数量 *返回 : 无 *依赖 : 无 *作者 : 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; } }
收藏该网址