/* * Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved. */ #include "jpegd_image.h" #include "jpegd_drv.h" #include "jpegd_entry.h" static const unsigned char g_zigzag_for_qtable[ZIGZAG_TABLE_SIZE] = { 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, }; motion_jpeg_obj g_jpegd_ctx; int jpegd_dec_baseline(motion_jpeg_obj *jpegd_hdl_ctx, unsigned char **str, unsigned int *flag, unsigned int *idx, unsigned int len) { unsigned char *stream = *str; int result = GK_SUCCESS; if (*flag == 1) { int tmp_len = (stream[0] << 8) + stream[1]; /* shift left 8 bits */ tmp_len = MIN(tmp_len, len - *idx); jpegd_hdl_ctx->stream_buffer = stream; *idx += (tmp_len + 2); /* 2 number of bytes */ stream += (tmp_len); result = decode_sof0(jpegd_hdl_ctx, jpegd_hdl_ctx->stream_buffer); if (result == GK_JPEG_DEC_OK) { *flag = 2; /* 2 decode sof0 success */ } } *str = stream; return result; } int jpegd_dec_dht(motion_jpeg_obj *jpegd_hdl_ctx, unsigned char **str, unsigned int len, unsigned int *idx) { unsigned char *stream = *str; unsigned int tmp_len = (stream[0] << 8) + stream[1]; /* shift left 8 bits */ tmp_len = MIN(tmp_len, len - *idx); jpegd_hdl_ctx->stream_buffer = stream; *idx += (tmp_len + 2); /* 2 number of bytes */ stream += (tmp_len); if (decode_dht(jpegd_hdl_ctx, jpegd_hdl_ctx->stream_buffer)) { return GK_FAILURE; } *str = stream; return GK_SUCCESS; } int jpegd_dec_sos(motion_jpeg_obj *jpegd_hdl_ctx, unsigned char **str, unsigned int *flag, unsigned int *idx, unsigned int len) { unsigned char *stream = *str; int result = GK_SUCCESS; if (*flag == 2) { /* 2 decode sof0 success */ int tmp_len = (stream[0] << 8) + stream[1]; /* shift left 8 bits */ tmp_len = MIN(tmp_len, len - *idx); jpegd_hdl_ctx->stream_buffer = stream; *idx += (tmp_len); stream += (tmp_len); jpegd_hdl_ctx->first_mcu = 0; result = decode_sos(jpegd_hdl_ctx, jpegd_hdl_ctx->stream_buffer); if (result == GK_JPEG_DEC_OK) { *flag = 3; /* 3 scan header decoding success */ } else { return GK_FAILURE; } } *str = stream; return GK_SUCCESS; } int jpegd_dec_dqt(motion_jpeg_obj *jpegd_hdl_ctx, unsigned char **str, unsigned int *idx, unsigned int len) { unsigned char *stream = *str; int tmp_len = (stream[0] << 8) + stream[1]; /* shift left 8 bits */ tmp_len = MIN(tmp_len, len - *idx); jpegd_hdl_ctx->stream_buffer = stream; *idx += (tmp_len + 2); /* 2 DQT number of bytes */ stream += (tmp_len); if (decode_dqt(jpegd_hdl_ctx, jpegd_hdl_ctx->stream_buffer)) { return GK_FAILURE; } *str = stream; return GK_SUCCESS; } int jpegd_dec_dri(motion_jpeg_obj *jpegd_hdl_ctx, unsigned char **str, unsigned int *flag, unsigned int *idx) { unsigned char *stream = *str; jpegd_hdl_ctx->stream_buffer = stream; if (decode_dri(jpegd_hdl_ctx, jpegd_hdl_ctx->stream_buffer)) { /* 4 dri len */ *flag = 0; return GK_FAILURE; } *idx += 6; /* 6 define restart interval */ stream += 4; /* 4 define restart interval */ *str = stream; return GK_SUCCESS; } int jpegd_dec_err(unsigned char **str, unsigned int *idx, unsigned int type, unsigned int *flag) { unsigned char *stream = *str; int result = GK_SUCCESS; if ((type & 0xE0) == 0xE0) { /* 0xE0:APP_0 value */ int tmp_len = (stream[0] << 8) + stream[1]; /* shift left 8 bits */ *idx += (tmp_len + 2); /* 2 number of bytes */ stream += (tmp_len); } else if ((type & 0xF0) == 0xC0) { /* 0xF0:JPG_0 0xC0:baseline */ *flag = 0; result = GK_FAILURE; } else { *idx += 2; /* 2 number of bytes */ } *str = stream; return result; } void jpegd_dec_sos_success(motion_jpeg_obj *jpegd_hdl_ctx, mjpeg_dec_frame *tmp_dec_frame, bool quant_table_valid, bool huffman_table_valid, unsigned int idx) { jpegd_hdl_ctx->stream_offest = idx + 2; /* 2 number of bytes */ tmp_dec_frame->width = jpegd_hdl_ctx->frame.y_width; tmp_dec_frame->height = jpegd_hdl_ctx->frame.y_height; tmp_dec_frame->y_stride = jpegd_hdl_ctx->y_stride; tmp_dec_frame->c_stride = jpegd_hdl_ctx->c_stride; tmp_dec_frame->pic_format = jpegd_hdl_ctx->pic_format; tmp_dec_frame->pts = jpegd_hdl_ctx->stream.pts; tmp_dec_frame->reserved = 0; tmp_dec_frame->user_data = NULL; jpegd_hdl_ctx->valid_frame ^= 0x1; /* 0x1:change to another buffer */ if (quant_table_valid == GK_FALSE) { init_default_quant_table(jpegd_hdl_ctx); } if (huffman_table_valid == GK_FALSE) { init_default_huffman_table(jpegd_hdl_ctx); } return; } void jpegd_dec_sos_failed(mjpeg_dec_frame *tmp_dec_frame) { tmp_dec_frame->y = NULL; tmp_dec_frame->u = NULL; tmp_dec_frame->v = NULL; tmp_dec_frame->width = 0; tmp_dec_frame->height = 0; tmp_dec_frame->y_stride = 0; tmp_dec_frame->c_stride = 0; tmp_dec_frame->pic_format = PICTURE_FORMAT_BUTT; tmp_dec_frame->pts = 0; tmp_dec_frame->reserved = 0; tmp_dec_frame->user_data = NULL; return; } /* decode jpeg picture */ int jpegd_dec_frame(jpegd_handle handle, unsigned int flags) { motion_jpeg_obj *jpegd_hdl_ctx = (motion_jpeg_obj *)handle; unsigned int i; unsigned int jpeg_flag = 0; int result = 0; unsigned int type; unsigned char *stream = NULL; unsigned int len; mjpeg_dec_frame *tmp_dec_frame = NULL; mjpeg_dec_frame dec_frame; gk_bool quant_table_valid = GK_FALSE; gk_bool huffman_table_valid = GK_FALSE; if (jpegd_hdl_ctx == NULL) { gk_trace("jpegd handle is null!\n"); return GK_MJPEG_ERR_HANDLE; } stream = jpegd_hdl_ctx->stream.vir_addr; len = jpegd_hdl_ctx->stream.len; tmp_dec_frame = &dec_frame; if (stream == NULL) { gk_trace("jpegd stream vir_addr is null!\n"); return GK_MJPEG_ERR_HANDLE; } tmp_dec_frame->error_code = 0; tmp_dec_frame->error = 0; jpegd_hdl_ctx->frame.restart_interval = 0; for (i = 0; i < len;) { type = 0xFF; /* 0xFF:jpeg maker */ while ((i < len) && (*(stream++) != 0xff)) { /* 0xFF:jpeg maker */ i++; } type = *(stream++); while ((i < len) && (type == 0xff)) { /* 0xFF:jpeg maker */ type = *(stream++); i++; } switch (type) { case BASELINE: { /* sequential DCT */ result = jpegd_dec_baseline(jpegd_hdl_ctx, &stream, &jpeg_flag, &i, len); if (result != GK_SUCCESS) { tmp_dec_frame->error_code = result; gk_trace("jpeg decode DCT error!\n"); goto end; } } break; case DHT: { /* DHT */ result = jpegd_dec_dht(jpegd_hdl_ctx, &stream, len, &i); if (result != GK_SUCCESS) { tmp_dec_frame->error_code += GK_ERR_HUFFMAN_TABLE; gk_trace("jpeg decode huffman error!\n"); goto end; } huffman_table_valid = GK_TRUE; } break; case SOS: { /* scan header */ result = jpegd_dec_sos(jpegd_hdl_ctx, &stream, &jpeg_flag, &i, len); if (result != GK_SUCCESS) { gk_trace("jpeg decode SOS error!\n"); goto end; /* scan header decoding error */ } goto end; } break; case SOI: { /* a new jpeg picture */ i += 2; /* 2 SOI number of bytes */ jpeg_flag = 1; } break; case EOI: { /* end of jpeg picture */ i += 2; /* 2 EOI number of bytes */ goto end; } case DQT: { result = jpegd_dec_dqt(jpegd_hdl_ctx, &stream, &i, len); if (result != GK_SUCCESS) { tmp_dec_frame->error_code += GK_ERR_HUFFMAN_TABLE; gk_trace("jpeg decode DQT error!\n"); goto end; } quant_table_valid = GK_TRUE; } break; case DNL: { i += 6; /* 6 define number of lines */ stream += 4; /* 4 number of lines' size */ jpeg_flag = 0; } break; case DRI: { result = jpegd_dec_dri(jpegd_hdl_ctx, &stream, &jpeg_flag, &i); if (result != GK_SUCCESS) { tmp_dec_frame->error_code = GK_ERR_RESTART_ERROR; gk_trace("jpeg decode DRI error!\n"); goto end; } } break; default: { /* do not support */ result = jpegd_dec_err(&stream, &i, type, &jpeg_flag); if (result != GK_SUCCESS) { tmp_dec_frame->error_code = GK_ERR_NOT_BASELINE; gk_trace("jpeg decode error, unsupport type!\n"); goto end; } } break; } } end: if (jpeg_flag == 3) { /* 3 scan header decoding success */ jpegd_dec_sos_success(jpegd_hdl_ctx, tmp_dec_frame, quant_table_valid, huffman_table_valid, i); return GK_MJPEG_DEC_OK; } else { jpegd_dec_sos_failed(tmp_dec_frame); return GK_MJPEG_NO_PICTURE; } } /* create a JPEG decoder handle */ jpegd_handle jpegd_get_handle(void) { motion_jpeg_obj *mjpeg = &g_jpegd_ctx; int pic_size; mjpeg->max_width = JPEGD_MAX_WIDTH; mjpeg->max_height = JPEGD_MAX_HEIGHT; pic_size = mjpeg->max_width * mjpeg->max_height; mjpeg->buf_size = pic_size + 0x10000; /* 0x10000:extra mem */ mjpeg->stream_buffer = NULL; mjpeg->pic_buffer = NULL; mjpeg->valid_frame = 0; mjpeg->width_in_mcu = 1; mjpeg->height_in_mcu = 0; mjpeg->y_stride = 0; mjpeg->c_stride = 0; mjpeg->pic_format = PICTURE_FORMAT_BUTT; mjpeg->first_mcu = 0; mjpeg->bits.bit_len = 0; mjpeg->bits.bit_offset = 0; mjpeg->bits.buffer = NULL; mjpeg->frame.nf = 0; mjpeg->frame.y_height = 0; mjpeg->frame.y_width = 0; mjpeg->frame.restart_interval = 0; mjpeg->frame.restart_interval_logic = 0; mjpeg->frame.max_mcu_number = 0; init_default_huffman_table(mjpeg); init_default_quant_table(mjpeg); mjpeg->state = STATE_IDLE; return (jpegd_handle)mjpeg; } void jpegd_config_huffman_dc(motion_jpeg_obj *jpeg_hdl_ctx, unsigned int *huffman_table, unsigned int cs) { huffman_tab *huf_tab = &jpeg_hdl_ctx->h_tab[cs]; unsigned int i, num, j, index; for (index = 0, i = 0; i < JPEGD_CODE_LEN; i++) { num = huf_tab->len[i]; for (j = 0; (j < num) && (index < 12); j++, index++) { /* 12 max index */ int pos = huf_tab->huffman_val[index]; if (cs == 1) { huffman_table[pos] |= ((i + 1) << 20) + /* shift left 20 bits 0xFF000:overflow protection */ (((j + (unsigned int)huf_tab->min_code[i]) << 12) & 0xFF000); /* shift left 12 bits */ } else { huffman_table[pos] |= ((i + 1) << 8) + ((j + (unsigned int)huf_tab->min_code[i]) & 0xFF); /* shift left 8 bits */ } } } return; } void jpegd_config_huffman_ac(motion_jpeg_obj *jpeg_hdl_ctx, unsigned char *ac_min_table, unsigned char *ac_base_table, unsigned int idx) { huffman_tab *huf_tab = &jpeg_hdl_ctx->h_tab[idx]; int i; for (i = 0; i < JPEGD_CODE_LEN; i++) { unsigned int base_code = 0; if (huf_tab->len[i]) { base_code = huf_tab->huffman_val_ptr[i] - huf_tab->min_code[i]; } ac_min_table[i] = ((unsigned int)huf_tab->min_code[i]) & 0xFF; /* 0xFF:get low 8 bits */ ac_base_table[i] = base_code & 0xFF; /* 0xFF:get low 8 bits */ } return; } void jpegd_config_huffman_table(motion_jpeg_obj *jpeg_hdl_ctx) { unsigned int i; unsigned int huffman_table[HDC_TABLE_SIZE] = {0}; unsigned char luma_ac_min_table[JPEGD_CODE_LEN] = {0}; unsigned char luma_ac_base_table[JPEGD_CODE_LEN] = {0}; unsigned char chroma_ac_min_table[JPEGD_CODE_LEN] = {0}; unsigned char chroma_ac_base_table[JPEGD_CODE_LEN] = {0}; /* config huffman dc */ jpegd_config_huffman_dc(jpeg_hdl_ctx, huffman_table, 1); jpegd_config_huffman_dc(jpeg_hdl_ctx, huffman_table, 0); /* config huffman ac */ jpegd_config_huffman_ac(jpeg_hdl_ctx, luma_ac_min_table, luma_ac_base_table, 2); /* 2:table index */ jpegd_config_huffman_ac(jpeg_hdl_ctx, chroma_ac_min_table, chroma_ac_base_table, 3); /* 3:table index */ /* config huffman table */ for (i = 0; i < HDC_TABLE_SIZE; i++) { jpeg_hdl_ctx->vpu_config.huffman_table[i] = huffman_table[i]; } /* config huffman_min_table table */ for (i = 0; i < HAC_MIN_TABLE_SIZE; i++) { jpeg_hdl_ctx->vpu_config.huffman_min_table[i] = (chroma_ac_min_table[2 * i + 1] << 24) + /* 2 config chroma ac table shift left 24 bits */ (chroma_ac_min_table[2 * i] << 16) + /* 2 config chroma ac table shift left 16 bits */ (luma_ac_min_table[2 * i + 1] << 8) + /* 2 config luma ac table shift left 8 bits */ (luma_ac_min_table[2 * i]); /* 2 config luma ac min table */ } /* config huffman_base_table table */ for (i = 0; i < HAC_BASE_TABLE_SIZE; i++) { jpeg_hdl_ctx->vpu_config.huffman_base_table[i] = (chroma_ac_base_table[2 * i + 1] << 24) + /* 2 config chroma ac base table shift left 24 bits */ (chroma_ac_base_table[2 * i] << 16) + /* 2 config chroma ac base table shift left 16 bits */ (luma_ac_base_table[2 * i + 1] << 8) + /* 2 config luma ac base table shift left 8 bits */ (luma_ac_base_table[2 * i]); /* 2 config luma ac base table */ } /* config huffman_symbol_table table */ for (i = 0; i < HAC_SYMBOL_TABLE_SIZE; i++) { jpeg_hdl_ctx->vpu_config.huffman_symbol_table[i] = (jpeg_hdl_ctx->h_tab[3].huffman_val[i] << 8) + /* table 3 shift left 8 bits */ jpeg_hdl_ctx->h_tab[2].huffman_val[i]; /* plus table 2 */ } return; } void jpegd_config_quant_table(motion_jpeg_obj *jpeg_hdl_ctx) { unsigned int i; unsigned int q_tab_y_index = jpeg_hdl_ctx->frame.tq[COM0] & 3; /* 3 overflow protection */ unsigned int q_tab_u_index = jpeg_hdl_ctx->frame.tq[COM1] & 3; /* 3 overflow protection */ unsigned int q_tab_v_index = jpeg_hdl_ctx->frame.tq[COM2] & 3; /* 3 overflow protection */ unsigned char *q_cr = (unsigned char *)&jpeg_hdl_ctx->q_tab[q_tab_v_index]; unsigned char *q_cb = (unsigned char *)&jpeg_hdl_ctx->q_tab[q_tab_u_index]; unsigned char *q_y = (unsigned char *)&jpeg_hdl_ctx->q_tab[q_tab_y_index]; int pos; for (i = 0; i < QUANT_TABLE_SIZE; i++) { pos = g_zigzag_for_qtable[i & 0x3f]; /* 0x3f:get low 6bits */ jpeg_hdl_ctx->vpu_config.quant_table[pos] = q_y[i] + (q_cb[i] << 8) + (q_cr[i] << 16); /* shift left 8 bits shift left 16 bits */ } return; } void jpegd_config_rgb_info(motion_jpeg_obj *jpeg_hdl_ctx) { if (jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_YVU_SEMIPLANAR_420) { jpeg_hdl_ctx->vpu_config.out_yuv = GK_TRUE; } else { jpeg_hdl_ctx->vpu_config.out_yuv = GK_FALSE; if ((jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_ARGB_8888) || (jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_ABGR_8888)) { jpeg_hdl_ctx->vpu_config.rgb_stride = align_up(jpeg_hdl_ctx->frame.y_width * 4, 16); /* 4,16 align up */ } else if ((jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_ARGB_1555) || (jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_ABGR_1555)) { jpeg_hdl_ctx->vpu_config.rgb_stride = align_up(jpeg_hdl_ctx->frame.y_width * 2, 16); /* 2,16 align up */ } else if ((jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_RGB_888) || (jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_BGR_888)) { jpeg_hdl_ctx->vpu_config.rgb_stride = align_up(jpeg_hdl_ctx->frame.y_width * 3, 16); /* 3,16 align up */ } else if ((jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_RGB_565) || (jpeg_hdl_ctx->vpu_config.pixel_format == PIXEL_FORMAT_BGR_565)) { jpeg_hdl_ctx->vpu_config.rgb_stride = align_up(jpeg_hdl_ctx->frame.y_width * 2, 16); /* 2,16 align up */ } } return; } unsigned int jpegd_prepare_pic_type(picture_format pic_format) { unsigned int pic_type = 0; switch (pic_format) { case PICTURE_FORMAT_YUV420: pic_type = 3; /* 3: value of hardware regulation */ break; case PICTURE_FORMAT_YUV422: pic_type = 4; /* 4: value of hardware regulation */ break; case PICTURE_FORMAT_YUV444: pic_type = 6; /* 6: value of hardware regulation */ break; case PICTURE_FORMAT_YUV422V: pic_type = 5; /* 5: value of hardware regulation */ break; case PICTURE_FORMAT_YUV400: pic_type = 0; /* 0: value of hardware regulation */ break; default: printf("Unkonwn picture format %d!", pic_format); } return pic_type; } /* Prepare the jpegd Hardware Info */ int jpegd_prepare_hardware_info(motion_jpeg_obj *jpeg_hdl_ctx) { unsigned int ysize; ysize = align_up(jpeg_hdl_ctx->frame.y_width, 64) * /* 64 align up */ align_up(jpeg_hdl_ctx->frame.y_height, 16); /* 16 align up */ jpeg_hdl_ctx->vpu_config.width = jpeg_hdl_ctx->frame.y_width; jpeg_hdl_ctx->vpu_config.height = jpeg_hdl_ctx->frame.y_height; jpeg_hdl_ctx->vpu_config.width_in_mcu = jpeg_hdl_ctx->width_in_mcu; jpeg_hdl_ctx->vpu_config.height_in_mcu = jpeg_hdl_ctx->height_in_mcu; jpeg_hdl_ctx->vpu_config.c_phy_addr = jpeg_hdl_ctx->vpu_config.y_phy_addr + ysize; jpeg_hdl_ctx->vpu_config.y_stride = align_up(jpeg_hdl_ctx->frame.y_width, 64); /* 64 align up */ jpeg_hdl_ctx->vpu_config.c_stride = align_up(jpeg_hdl_ctx->frame.y_width, 64); /* 64 align up */ jpeg_hdl_ctx->vpu_config.phy_str_start = jpeg_hdl_ctx->vpu_config.phy_str_start + jpeg_hdl_ctx->stream_offest; jpeg_hdl_ctx->vpu_config.y_fac = jpeg_hdl_ctx->frame.h[0]; jpeg_hdl_ctx->vpu_config.u_fac = jpeg_hdl_ctx->frame.h[1]; jpeg_hdl_ctx->vpu_config.v_fac = jpeg_hdl_ctx->frame.h[2]; /* 2 array index */ jpeg_hdl_ctx->vpu_config.dri = jpeg_hdl_ctx->frame.restart_interval_logic; jpeg_hdl_ctx->vpu_config.pic_format = jpeg_hdl_ctx->pic_format; jpeg_hdl_ctx->vpu_config.pic_type = jpegd_prepare_pic_type(jpeg_hdl_ctx->vpu_config.pic_format); /* config RGB info */ jpegd_config_rgb_info(jpeg_hdl_ctx); /* config quant table */ jpegd_config_quant_table(jpeg_hdl_ctx); /* config huffman table */ jpegd_config_huffman_table(jpeg_hdl_ctx); return GK_SUCCESS; } int jpegd_start_one_frame(jpegd_handle handle, unsigned int flags) { int ret; motion_jpeg_obj *jpegd_hdl_ctx = (motion_jpeg_obj *)handle; ret = jpegd_dec_frame(handle, flags); if (ret != GK_SUCCESS) { gk_trace("vdec_start_one_frame: decode stream fail for 0x%x\n", ret); return ret; } ret = jpegd_prepare_hardware_info(jpegd_hdl_ctx); if (ret != GK_SUCCESS) { gk_trace("vdec_start_one_frame: decode stream fail for 0x%x\n", ret); return ret; } return GK_SUCCESS; } /* write the jpegd register */ void jpegd_write_regs(jpegd_handle handle, S_JPGD_REGS_TYPE *reg_base) { motion_jpeg_obj *jpeg_hdl_ctx = (motion_jpeg_obj *)handle; jpegd_drv_write_regs(reg_base, &jpeg_hdl_ctx->vpu_config); return; } /* read the jpegd register */ void jpegd_read_regs(jpegd_handle handle, S_JPGD_REGS_TYPE *reg_base) { motion_jpeg_obj *jpeg_hdl_ctx = (motion_jpeg_obj *)handle; jpegd_drv_read_regs(reg_base, &jpeg_hdl_ctx->vpu_status); return; } int jpegd_start_decoding(jpegd_handle handle) { motion_jpeg_obj *jpegd_hld_ctx = NULL; int ret; jpegd_hld_ctx = (motion_jpeg_obj *)handle; jpegd_hld_ctx->vpu_config.y_phy_addr = get_video_data_base(); jpegd_hld_ctx->vpu_config.phy_str_buf_start = get_logo(); jpegd_hld_ctx->vpu_config.phy_str_buf_end = get_logo() + align_up(get_jpeg_size_val(), 128); /* 128 align up */ jpegd_hld_ctx->vpu_config.phy_str_start = get_logo(); jpegd_hld_ctx->vpu_config.phy_str_end = get_logo() + get_jpeg_size_val(); jpegd_hld_ctx->vpu_config.phy_emar_buffer0 = get_jpegd_emar_buf(); jpegd_hld_ctx->vpu_config.phy_emar_buffer1 = get_jpegd_emar_buf() + ONE_EMAR_BUF_SIZE; jpegd_hld_ctx->stream.vir_addr = (unsigned char *)(uintptr_t)get_logo(); jpegd_hld_ctx->stream.len = get_jpeg_size_val(); jpegd_hld_ctx->stream.phy_addr = get_logo(); jpegd_hld_ctx->stream.pts = 0; jpegd_hld_ctx->vpu_config.chn_id = 0; jpegd_hld_ctx->vpu_config.alpha = 255; /* 255 transparency */ if (get_output_format() == 0) { jpegd_hld_ctx->vpu_config.pixel_format = PIXEL_FORMAT_YVU_SEMIPLANAR_420; } else if (get_output_format() == 1) { jpegd_hld_ctx->vpu_config.pixel_format = PIXEL_FORMAT_ARGB_1555; } else if (get_output_format() == 2) { /* 2 output format */ jpegd_hld_ctx->vpu_config.pixel_format = PIXEL_FORMAT_ARGB_8888; } else { jpegd_hld_ctx->vpu_config.pixel_format = PIXEL_FORMAT_YVU_SEMIPLANAR_420; } ret = jpegd_start_one_frame(handle, 0); if (ret != GK_SUCCESS) { gk_trace("jpegd_start_decoding: decode stream fail for 0x%x\n", ret); return ret; } jpegd_set_clock_en(0, GK_TRUE); jpegd_reset(0); jpegd_set_time_out(0, 0xFFFFFFFF); /* 0xFFFFFFFF:time out value */ jpegd_write_regs(handle, (S_JPGD_REGS_TYPE *)JPEGD_REGS_ADDR); jpegd_start_vpu(0); return GK_SUCCESS; } void jpegd_finish_decoding(jpegd_handle handle) { unsigned int int_statue; unsigned int cnt = 0; motion_jpeg_obj *jpegd_hld_ctx = (motion_jpeg_obj *)handle; while (1) { udelay(10); /* 10 delay time */ int_statue = jpegd_read_int(0); if (int_statue & 0x1f) { break; } if (cnt++ > 2000) { /* 2000:Maximum decoding time */ gk_trace("jpeg decode over time\n"); break; } } jpegd_read_regs(handle, (S_JPGD_REGS_TYPE *)JPEGD_REGS_ADDR); if (jpegd_hld_ctx->vpu_status.int_dec_finish == 0) { printf("hardware decoding error!\n"); } else { if (jpegd_hld_ctx->vpu_config.out_yuv != GK_TRUE) { printf("hardware decoding success! %ux%u, stride %u.\n", jpegd_hld_ctx->frame.y_width, jpegd_hld_ctx->frame.y_height, jpegd_hld_ctx->vpu_config.rgb_stride); } else { printf("hardware decoding success! %ux%u, stride %u.\n", jpegd_hld_ctx->frame.y_width, jpegd_hld_ctx->frame.y_height, jpegd_hld_ctx->vpu_config.y_stride); } } jpegd_clear_int(0); jpegd_reset_select(0, GK_TRUE); return; }