📄 jpeg.c
字号:
//=============================================================// 文件名称: jpeg_decoder.c// 功能描述: jpeg解码程序// 维护记录: 2007-8-13 by liuxue created// 2007.08.23 V1.0 by lijian <lijian@sunnorth.com.cn>//=============================================================#include "JPEG.h"#include "MPEG4_Driver.h"#include "BLNDMA.h"//=============================================================// 语法格式: unsigned char *find_marker(unsigned char * jpg_ptr);// 实现功能: 找jpeg的marker// 参数: jpg_ptr,指向jpeg数据的指针// 返回值: marker//=============================================================static unsigned char *find_marker(unsigned char * jpg_ptr){ while(*jpg_ptr != 0xff) { jpg_ptr++; } return ++jpg_ptr; // 返回marker}//=============================================================// 语法格式: unsigned int get_jpg_segment_length(unsigned char *jpg_ptr);// 实现功能: 找当前marker栏的长度// 参数: jpg_ptr,指向jpeg数据的指针// 返回值: length,当前marker栏的长度,长度不包括marker,但包括length本身//=============================================================static unsigned int get_jpg_segment_length(unsigned char *jpg_ptr){ unsigned int length; length = (*jpg_ptr << 8) + *(jpg_ptr + 1); return length;}//=============================================================// 语法格式: unsigned char *bypass_jpg_segment(unsigned char *jpg_ptr);// 实现功能: 跳过当前marker栏数据// 参数: jpg_ptr,指向jpeg数据的指针// 返回值: jpr_ptr,指向下一个marker栏首//=============================================================static unsigned char *bypass_jpg_segment(unsigned char *jpg_ptr){ unsigned int length; length = get_jpg_segment_length(jpg_ptr); jpg_ptr = jpg_ptr + length; return jpg_ptr; }//=============================================================// 语法格式: void fill_quantize_sram(unsigned char *jpg_ptr);// 实现功能: 向SPCE3200填充量化表// 参数: jpg_ptr,指向jpeg数据的指针// 返回值: 无//=============================================================static void fill_quantize_sram(unsigned char *jpg_ptr){ const unsigned int jpeg_natural_order[64] = { 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 }; // Zig-Zag变换 unsigned int i; unsigned int length, counter; unsigned char qtable[64]; unsigned char *pointer; unsigned int *ptr; length = get_jpg_segment_length(jpg_ptr); counter = 2; pointer = jpg_ptr + 2; *P_MPEG4_QTABLE_SRAM = C_MPEG4_QTABLESRAM_EN; // enable CPU access Q Sram while(counter < length) { if((*pointer & 0x0f)== 0x00) { ptr = (unsigned int *)P_MPEG4_QTABLE1_START;// fill Y Q_table ,亮度 } else { ptr = (unsigned int *)P_MPEG4_QTABLE2_START;// fill C Q_table chroma,色度 } counter++; pointer++; for(i=0; i<64; i++) { counter++; qtable[jpeg_natural_order[i]] = *pointer++; } for(i=0;i<64;i++) // Fill Q_Table_SRAM { *ptr++ = (unsigned int)qtable[i]; } } // while(counter < length) *P_MPEG4_QTABLE_SRAM = C_MPEG4_QTABLESRAM_DIS; // disable CPU access Q Sram}//=============================================================// 语法格式: int set_jpg_mode(unsigned char *jpg_ptr);// 实现功能: 向SPCE3200填充高度、宽度、FRAME_Buffer 宽度等信息// 根据jpeg图片数据,选择YUV格式// 参数: jpg_ptr,指向jpeg数据的指针// 返回值: 1: 成功; 0: 失败//=============================================================static int set_jpg_mode(unsigned char *jpg_ptr){ unsigned char *pointer; unsigned char word; unsigned int width; pointer = jpg_ptr + 3; word = *pointer++; *P_MPEG4_DECHEIGHT_HIGH = (unsigned int)word; // 高度 word = *pointer++; *P_MPEG4_DECHEIGHT_LOW = (unsigned int)word; word = *pointer++; *P_MPEG4_DECWIDTH_HIGH = (unsigned int)word; // 宽度 width = (unsigned int)word; width = width << 8; word = *pointer++; *P_MPEG4_DECWIDTH_LOW = (unsigned int)word; width = width + (unsigned int)word; *P_MPEG4_FRAMEBUFFER_HSIZE = width; // FRAMEBUFFER_HSIZE word = *pointer++; pointer++; // skip 1 byte if(word==0x01) // 单色 01 { *P_MPEG4_YUV_SEL = 0x00000000; // 0 : {yuv420, yuv422} // 1 : {yuv411, yuv444} *P_MPEG4_MODE_CTRL1 = C_MPEG4_JPEG_DEC | C_MPEG4_YUV422_MODE | C_MPEG4_COLOR_MODE; } else // 彩色 03 { word = *pointer; switch(word) // 分量水平sampling比例 { case 0x11: // yuv444 *P_MPEG4_YUV_SEL = 0x00000001; *P_MPEG4_MODE_CTRL1 = C_MPEG4_JPEG_DEC | C_MPEG4_YUV444_MODE; break; case 0x21: // yuv422 *P_MPEG4_YUV_SEL = 0x00000000; *P_MPEG4_MODE_CTRL1 = C_MPEG4_JPEG_DEC | C_MPEG4_YUV422_MODE; break; case 0x41: // yuv411 *P_MPEG4_YUV_SEL = 0x00000001; *P_MPEG4_MODE_CTRL1 = C_MPEG4_JPEG_DEC | C_MPEG4_YUV411_MODE; break; case 0x22: // yuv420 *P_MPEG4_YUV_SEL = 0x00000000; *P_MPEG4_MODE_CTRL1 = C_MPEG4_JPEG_DEC | C_MPEG4_YUV420_MODE; *P_MPEG4_YUV_MODE = 0x30; break; case 0x12: // 不支持 单 垂直采样2:1模式 return 0; // i can't decode this JPG file } // end switch } // end if return 1;} // end function//=============================================================// 语法格式: Get_Huffman_cs_cw(unsigned char *cs, unsigned int *cw, unsigned char *pointer);// 实现功能: 获得Huffman表// 参数: *cs,huffman的VLC的相对开始;*cw,存储huffman表;*pointer,指向jpeg数据// 返回值: 无//=============================================================static void Get_Huffman_cs_cw(unsigned char *cs, unsigned int *cw, unsigned char *pointer){ unsigned char pcount[16]; unsigned int index; unsigned int l_codeword = 0; // local_codeword unsigned int last_valid; unsigned int j; for(j=0; j<16; j++) { pcount[j] = *pointer++; } for(j=15; j>=0; j--) { if(pcount[j]) break; } last_valid = j; for(index=0; index<16; index++) { if(0 == index) { cs[0] = 0; } else if(1 == index) { cs[1] = pcount[0]; } else { cs[index] = cs[index - 1] + pcount[index - 1]; } // end if(0 == index) if(index == 0) { cw[index] = 0; if(pcount[0] == 1) l_codeword = 1; else l_codeword = 0; } else if(index <= last_valid) { if(0 == cs[index]) { l_codeword = 0; } l_codeword = l_codeword << 1; cw[index] = l_codeword; l_codeword = l_codeword + pcount[index]; } else { cw[index] = 0xffff; } // end if(index == 0) } // end for(index=0; index<16; index++)}//=============================================================// 语法格式: void set_Huff_sram_mode(int Page);// 实现功能: 向SPCE3200填充TSRAM,前4页存储亮度信息,后4页存储色度信息// 参数: Page,选择TSRAM的页数// 返回值: 无//=============================================================static void set_Huff_sram_mode(int Page){ if(Page == 0) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE0; else if(Page == 1) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE1; else if(Page == 2) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE2; else if(Page == 3) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE3; else if(Page == 4) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE4; else if(Page == 5) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE5; else if(Page == 6) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE6; else if(Page == 7) *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_TSRAM | C_MPEG4_TSRAM_PAGE7; else *P_MPEG4_TSRAM_CTRL = C_MPEG4_CPU_REG;}//=============================================================// 语法格式: set_jpg_huffman_cw_reg(unsigned char htype, unsigned int *cw);// 实现功能: 填充Huffman表// 参数: htype,huffman表的类型;*cw,存储的huffman表// 返回值: 无//=============================================================static void set_jpg_huffman_cw_reg(unsigned char htype, unsigned int *cw){ unsigned int i; unsigned int *pointer; if(htype == 0x00) pointer = (unsigned int *)P_MPEG4_HUFFMAN_START; // YDC huffman else if(htype == 0x01) pointer = (unsigned int *)P_MPEG4_CHROMDCCODE_START; // CDC huffman else if(htype == 0x10) pointer = (unsigned int *)P_MPEG4_LUMACHUFFMANTABLE_START; // YAC huffman else if(htype == 0x11) pointer = (unsigned int *)P_MPEG4_CHROMACHUFFMANTABLE_START; // CAC huffman for(i=0; i<8; i++) { *pointer++ = cw[i]; } for(i=8; i<16; i++) { *pointer++ = cw[i]; *pointer++ = cw[i] >> 8; }}//=============================================================// 语法格式: set_jpg_huffman_acs_reg(int chrominance, unsigned char *cs);// 实现功能: 填充 AC Huffman VLC偏移// 参数: chrominance,选择亮度还是色度;*cs,VLC偏移// 返回值: 无//=============================================================static void set_jpg_huffman_acs_reg(int chrominance, unsigned char *cs){ unsigned int i; unsigned int *pointer; if(chrominance == 0) { pointer = (unsigned int *)P_MPEG4_LUMACHUFFMANOFFSET_SA; } else { pointer = (unsigned int *)P_MPEG4_CHROMACHUFFMANOFFSET_SA; } for(i=0; i<16; i++) { *pointer++ = (unsigned int)cs[i]; }}//=============================================================// 语法格式: set_jpg_huffman_acs_reg(int chrominance, unsigned char *cs);// 实现功能: 填充 AC Huffman值// 参数: chrominance,选择亮度还是色度;*cv,AC huffman值// 返回值: 无//=============================================================static void set_jpg_huffman_acv_sram(int chrominance, unsigned char *cv){ unsigned int Huffman_SRAM_Page; unsigned int *pointer; unsigned int j, i, k; if(chrominance == 0) Huffman_SRAM_Page = 0; else Huffman_SRAM_Page = 4; for(j=0; j<4; j++) { set_Huff_sram_mode(Huffman_SRAM_Page); pointer = (unsigned int *)P_MPEG4_LUMDCCODE_START; k= j * 64; for(i=0; i<64; i++) { *pointer++ = (unsigned int)cv[k++]; } Huffman_SRAM_Page++; } set_Huff_sram_mode(8);}//=============================================================// 语法格式: void set_jpg_huffman_dcs_reg(int chrominance, unsigned char *cs);// 实现功能: 填充 DC Huffman VLC偏移// 参数: chrominance,选择亮度还是色度;*cs,VLC偏移// 返回值: 无//=============================================================static void set_jpg_huffman_dcs_reg(int chrominance, unsigned char *cs){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -