LOCAL JPEG_RET_E GetSOF(BOOLEAN isProgressive, JPEG_DEC_INPUT_PARA_T *jpeg_dec_input) { uint16 length = 0; uint16 width = 0; uint16 height = 0; uint8 ci = 0, c = 0; uint8 component_num = 0; int8 yuv_id = 0; jpeg_component_info *compptr; JPEG_CODEC_T *jpeg_fw_codec = Get_JPEGDecCodec(); jpeg_dec_input->progressive_mode = isProgressive; if(isProgressive) { JPEG_TRACE("\nJPEG Mode is: Progressive\n"); } else { JPEG_TRACE("JPEG Mode is: Baseline\n"); } if (!get_short_word(&length) || length < 8) /*get length*/ { JPEG_TRACE("GetSOF get length error %d", length); return JPEG_FAILED; } if (!get_char(&c)) /*get sample precision*/ { JPEG_TRACE("GetSOF pricision error, %d", c); return JPEG_FAILED; } if (c !=8 ) { JPEG_TRACE("ERROR!!! pricision = %d\n", c); return JPEG_FAILED; } if (!get_short_word(&height) || !get_short_word(&width)) { JPEG_TRACE("GetSOF get size error "); return JPEG_FAILED; } jpeg_dec_input->input_height = height; jpeg_dec_input->input_width = width; if ((jpeg_dec_input->input_height < 8)||(jpeg_dec_input->input_width < 8)) { JPEG_TRACE("WARNING!!! width =%d, height = %d\n", jpeg_dec_input->input_height, jpeg_dec_input->input_width); } if (!get_char(&component_num)) /*get the component number*/ { JPEG_TRACE("GetSOF get component num error"); return JPEG_FAILED; } if(component_num != 3) { JPEG_TRACE("WARNING!!! component num = %d\n", component_num); } /*check length*/ if (length != (component_num * 3 + 8)) { JPEG_TRACE("Error!!! length = %d\n", length); return JPEG_FAILED; } jpeg_fw_codec->num_components = component_num; JPEG_TRACE("JPEG: GetSOF, width=%d, height=%d\n",jpeg_dec_input->input_width, jpeg_dec_input->input_height); /*Caution: current we only support the YUV format, sequence is Y..U..V*/ // if (jpeg_dec_input->comp_info == NULL) /* do only once, even if suspend */ { jpeg_fw_codec->comp_info = (jpeg_component_info *)JpegDec_ExtraMemAlloc(component_num * sizeof(jpeg_component_info)); } for(ci = 0, compptr = jpeg_fw_codec->comp_info; ci < component_num; ci++, compptr++) { if (!get_char(&c)) { JPEG_TRACE("[GetSOF] get yuvid error = %d", c); return JPEG_FAILED; } yuv_id = c; compptr->component_index = ci; compptr->component_id = yuv_id; //index starts from 1, but in our program, ratio and tbl_map starts from 0, //so we need minus yuv_id to 1 before use it. Noted by xiaowei.luo@20090107 yuv_id--; if((yuv_id<0)||(yuv_id>2)) { JPEG_TRACE("Error!!! component id = %d\n", yuv_id); return JPEG_FAILED; } if (!get_char(&c)) /*get sample ratio*/ { JPEG_TRACE("Get sample ratio error"); return JPEG_FAILED; } compptr->h_samp_factor = (c >> 4) & 0x0F; compptr->v_samp_factor = (c ) & 0x0F; if(ci == 0) { compptr->MCU_width = compptr->h_samp_factor; compptr->MCU_height = compptr->v_samp_factor; }else { compptr->MCU_width = 1; compptr->MCU_height = 1; } if (!get_char(&c)) /*get quant table*/ { JPEG_TRACE("Get quant table error"); return JPEG_FAILED; } if(c >= 2/*JPEG_FW_CHR_ID*/) //be compliant with two chroma quant table. { #if 0 //JPEG_ERROR(JPEG_EID_MISSQUANT, "quant id = %d\n", c); return JPEG_FAILED; #else c -= 2; #endif } jpeg_fw_codec->tbl_map[yuv_id].quant_tbl_id = c; } c = (jpeg_fw_codec->comp_info[0].h_samp_factor << 4) | (jpeg_fw_codec->comp_info[0].v_samp_factor); if (1 == component_num) { jpeg_dec_input->input_mcu_info = JPEG_FW_YUV400; JPEG_TRACE("YUV Mode is: 4:0:0\n"); } else // componet num is 2 or 3 { switch(c) { case 0x11: jpeg_dec_input->input_mcu_info = JPEG_FW_YUV444; JPEG_TRACE("YUV Mode is: 4:4:4\n"); break; case 0x21: jpeg_dec_input->input_mcu_info = JPEG_FW_YUV422; JPEG_TRACE("YUV Mode is: 4:2:2, V1,H2\n"); break; case 0x41: jpeg_dec_input->input_mcu_info = JPEG_FW_YUV411; JPEG_TRACE("YUV Mode is: 4:1:1\n"); break; case 0x14: jpeg_dec_input->input_mcu_info = JPEG_FW_YUV411_R; JPEG_TRACE("YUV Mode is: 4:1:1, V4, H1\n"); break; case 0x22: jpeg_dec_input->input_mcu_info = JPEG_FW_YUV420; JPEG_TRACE("YUV Mode is: 4:2:0\n"); break; case 0x12: jpeg_dec_input->input_mcu_info = JPEG_FW_YUV422_R; JPEG_TRACE("YUV Mode is: 4:2:2, V2,H1\n"); break; default: // JPEG_ERROR(JPEG_EID_SAMPLEFORMAT, "format = %d\n", sample_format); JPEG_TRACE("unsupport format = %d", c); return JPEG_FAILED; } //check u sample ratio c = (jpeg_fw_codec->comp_info[1].h_samp_factor << 4) | (jpeg_fw_codec->comp_info[1].v_samp_factor); if (0x11 != c) { JPEG_TRACE("unsupport u sample ratio = %d", c); return JPEG_FAILED; } //check v sample ratio if (component_num > 2) { //check u sample ratio c = (jpeg_fw_codec->comp_info[2].h_samp_factor << 4) | (jpeg_fw_codec->comp_info[2].v_samp_factor); if (0x11 != c) { JPEG_TRACE("unsupport v sample ratio = %d", c); return JPEG_FAILED; } } } return JPEG_SUCCESS; }
LOCAL JPEG_RET_E GetHuffTbl() { uint16 length = 0; uint16 i = 0, index = 0, count = 0; HUFF_TBL_T *htblptr = NULL; uint8 *bits; uint8 *huffval; uint8 *default_bits; uint8 *default_huffval; JPEG_CODEC_T *jpeg_fw_codec = Get_JPEGDecCodec(); uint8 c = 0; if(!g_huff_tbl_malloced) { for(i = 0; i < NUM_HUFF_TBLS; i++) { jpeg_fw_codec->dc_huff_tbl[i].bits = (uint8*)JpegDec_ExtraMemAlloc((sizeof(uint8))*(MAX_BITS_SIZE+1)); jpeg_fw_codec->dc_huff_tbl[i].huffval = (uint8*)JpegDec_ExtraMemAlloc((sizeof(uint8))*(AC_SYMBOL_NUM+1)); jpeg_fw_codec->ac_huff_tbl[i].bits = (uint8*)JpegDec_ExtraMemAlloc((sizeof(uint8))*(MAX_BITS_SIZE+1)); jpeg_fw_codec->ac_huff_tbl[i].huffval = (uint8*)JpegDec_ExtraMemAlloc((sizeof(uint8))*(AC_SYMBOL_NUM+1)); } g_huff_tbl_malloced = TRUE; } if (!get_short_word(&length) || length < 2) { JPEG_TRACE("[GetHuffTbl] get length error, length = %d", length); return JPEG_FAILED; } length -= 2; while (length > 0) { if (!get_char(&c)) { JPEG_TRACE("[GetHuffTbl] get table error"); return JPEG_FAILED; } //clear the invalid bits index = c & 0x13; if (index & 0x10) { index -= 0x10; /* AC table definition */ htblptr = &(jpeg_fw_codec->ac_huff_tbl[index]); bits = htblptr->bits; huffval = htblptr->huffval; if(index == 00) //luma { default_bits = jpeg_fw_lum_ac_bits_default; default_huffval = jpeg_fw_lum_ac_huffvalue_default; } else //chroma { default_bits = jpeg_fw_chr_ac_bits_default; default_huffval = jpeg_fw_chr_ac_huffvalue_default; } } else { /* DC table definition */ htblptr = &(jpeg_fw_codec->dc_huff_tbl[index]); bits = htblptr->bits; huffval = htblptr->huffval; if(index == 00) //luma { default_bits = jpeg_fw_lum_dc_bits_default; default_huffval = jpeg_fw_lum_dc_huffvalue_default; } else //chroma { default_bits = jpeg_fw_chr_dc_bits_default; default_huffval = jpeg_fw_chr_dc_huffvalue_default; } } /*read bits*/ bits[0] = 0; count = 0; for (i = 1; i <= 16; i++) { if (!get_char(&c)) { JPEG_TRACE("[GetHuffTbl] get table error"); return JPEG_FAILED; } bits[i] = c; if(bits[i] != default_bits[i]) { jpeg_fw_codec->using_default_huff_tab = FALSE; } count += bits[i]; } if (count > 256) { JPEG_TRACE("huff value table len = %d is larger than 256\n", count); return JPEG_FAILED; } for (i = 0; i < count; i++) { if (!get_char(&c)) { JPEG_TRACE("[GetHuffTbl] get table error"); return JPEG_FAILED; } huffval[i] = c; if(huffval[i] != default_huffval[i]) { jpeg_fw_codec->using_default_huff_tab = FALSE; } } if (length < (1 + 16 + count)) { JPEG_TRACE("[GetHuffTbl] huffman table error!"); return JPEG_FAILED; } else { length -= (1 + 16 + count); } // htblptr->bits = bits; // htblptr->huffval = huffval; } return JPEG_SUCCESS; }
LOCAL JPEG_RET_E GetQuantTbl() { uint16 length = 0; uint8 n = 0, j = 0, prec = 0; uint8 *quant_ptr = NULL; int32 has_two_chroma_quant_tbl = FALSE; JPEG_CODEC_T *jpeg_fw_codec = Get_JPEGDecCodec(); jpeg_fw_codec->using_default_quant_tab = FALSE; if (!get_short_word(&length) || length < 2) { JPEG_TRACE("[GetHuffTbl] get length error, length = %d", length); return JPEG_FAILED; } length -= 2; while (length > 0) { if (!get_char(&n)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } prec = n>>4; n &= 0x0F; if (prec) { JPEG_TRACE("error quant table precision = %d\n", prec); // return JPEG_FAILED; } if (n >= 2) { #if 0 JPEG_TRACE("warning: error quant table id = %d\n", n); return JPEG_FAILED; #else n -= 2; #endif } if (n > 1) { JPEG_TRACE("warning: error quant table id = %d\n", n); //return JPEG_SUCCESS; //removed by xwluo, @20090330 has_two_chroma_quant_tbl = TRUE; } jpeg_fw_codec->quant_tbl[n] = (uint8*)JpegDec_ExtraMemAlloc((sizeof(uint8))*64); quant_ptr = &jpeg_fw_codec->quant_tbl[n][0]; if (prec == 0) { for(j = 0; j < 64; j+=4) { uint8 c = 0; if (!get_char(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j]] = c; if (!get_char(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j+1]] = c; if (!get_char(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j+2]] = c; if (!get_char(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j+3]] = c; } } else { for(j = 0; j < 64; j+=4) { uint16 c = 0; if (!get_short_word(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j]] = (uint8)c; if (!get_short_word(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j+1]] = (uint8)c; if (!get_short_word(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j+2]] = (uint8)c; if (!get_short_word(&c)) { JPEG_TRACE("[GetQuantTbl] get table error"); return JPEG_FAILED; } quant_ptr[jpeg_fw_zigzag_order[j+3]] = (uint8)c; } } if (length < (64 + 1 + 64 * prec)) { JPEG_TRACE("[GetQuantTbl] huffman table error!"); return JPEG_FAILED; } else { length -= (64 + 1 + 64 * prec); } } #if 0 if(has_two_chroma_quant_tbl) //check if these two chroma quant tables are same or not. { uint8 *u_tbl_ptr = &jpeg_fw_codec->quant_tbl[1][0]; uint8 *v_tbl_ptr = &jpeg_fw_codec->quant_tbl[2][0]; for(j = 0; j < 64; j++) { if(u_tbl_ptr[j] != v_tbl_ptr[j]) { return JPEG_FAILED; } } JPEG_TRACE("U and V quant table is same\n"); } #endif return JPEG_SUCCESS; }
PUBLIC JPEG_RET_E JPEGFW_AdjustQuantTbl_Dec() { int32 time_out_flag = 0; uint8 tbl_id = 0; uint8 tbl_num = 0; uint32 qtable_addr = (uint32)INV_QUANT_TBL_ADDR; uint32 cmd = 0; int32 tmp = 0; int32 index1 = 0, index2 = 0; uint16 yuv_id = 0; JPEG_CODEC_T *jpeg_fw_codec = Get_JPEGDecCodec(); SCI_ASSERT(jpeg_fw_codec != PNULL); if(jpeg_fw_codec->num_components == 1) { tbl_num = 1; }else { tbl_num = 2; } if(!jpeg_fw_codec->progressive_mode) { cmd = JPG_READ_REG(JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, "DCAM_CFG: allow software to access the vsp buffer"); cmd |= (1<<2); JPG_WRITE_REG(JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, cmd, "DCAM_CFG: allow software to access the vsp buffer"); time_out_flag = JPG_READ_REG_POLL(JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, (1<<8), (1<<8), TIME_OUT_CLK, "DCAM_CFG: polling dcam clock status"); if(time_out_flag != 0) { SCI_TRACE_LOW("time_out_flag %s,%d",__FUNCTION__,__LINE__); return JPEG_FAILED; } for(tbl_id = 0; tbl_id < tbl_num; tbl_id++) { const uint8 *quant_tbl_current = PNULL; uint32 i = 0; yuv_id = jpeg_fw_codec->tbl_map[tbl_id].quant_tbl_id; quant_tbl_current = jpeg_fw_codec->quant_tbl[yuv_id]; for(i=0; i < JPEG_FW_DCTSIZE2; i+=2) { index1 = jpeg_fw_ASIC_DCT_Matrix[i]; index2 = jpeg_fw_ASIC_DCT_Matrix[i+1]; /*lint !e661 */ tmp = ((quant_tbl_current[index1] & 0xFFFF) | (quant_tbl_current[index2]<<16)); JPG_WRITE_REG(qtable_addr, tmp, "INV_QUANT_TAB_ADDR: Write Qtalbe into Qbuffer"); qtable_addr += 4; #if _CMODEL_ { // FILE *qfile = fopen("D:/SC6800H/code/Firmware/jpeg_codec/simulation/VC/Dec_WinPrj/trace/dct/qtable.txt", "ab+"); // fprintf_oneWord_hex(qfile, tmp); // fclose(qfile); } #endif//_CMODEL_ } } cmd = JPG_READ_REG(JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, "DCAM_CFG: allow hardware to access the vsp buffer"); cmd = (cmd & ~0x4) ; JPG_WRITE_REG(JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, cmd, "DCAM_CFG: allow hardware to access the vsp buffer"); time_out_flag = JPG_READ_REG_POLL (JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, 1, 1, TIME_OUT_CLK, "DCAM_CFG: polling dcam clock status"); if(time_out_flag != 0) { time_out_flag = JPG_READ_REG (JPG_GLB_REG_BASE+GLB_CTRL_OFFSET, "DCAM_CFG: allow hardware to access the vsp buffer"); SCI_TRACE_LOW("time_out_flag %s,%d %x",__FUNCTION__,__LINE__,time_out_flag); return JPEG_FAILED; } }else { JPEG_PROGRESSIVE_INFO_T *progressive_info = JPEGFW_GetProgInfo(); int32 i; progressive_info->quant_tbl_new[0] = (int32 *)JpegDec_ExtraMemAlloc(sizeof(int32)*64); progressive_info->quant_tbl_new[1] = (int32 *)JpegDec_ExtraMemAlloc(sizeof(int32)*64); for(tbl_id = 0; tbl_id < tbl_num; tbl_id++) { const uint8 *quant; yuv_id = jpeg_fw_codec->tbl_map[tbl_id].quant_tbl_id; quant = jpeg_fw_codec->quant_tbl[yuv_id]; if(progressive_info->low_quality_idct) { for(i = 0; i < JPEG_FW_DCTSIZE2; i++) { progressive_info->quant_tbl_new[tbl_id][i] = (int32)DESCALE(MULTIPLY16V16((int32)quant[i/*jpeg_fw_zigzag_tbl[i]*/], (int32)aanscales[i]), IFAST_SCALE_BITS); } }else { for(i = 0; i < JPEG_FW_DCTSIZE2; i++) { progressive_info->quant_tbl_new[tbl_id][jpeg_fw_zigzag_order[i]] = (int32)quant[i]; } } } } return JPEG_SUCCESS; }