libmix: refine HW JPEG decoder following DDK_3_3_20

BZ: 99010

refine HW JPEG decoder in parse part following DDK_3_3_20 and
memory leak issue

Change-Id: I7c05ce09405082c22de6c201ae2c53c97bd45d16
Signed-off-by: Nana GUo <nana.n.guo@intel.com>
Reviewed-on: http://android.intel.com:8080/101682
Reviewed-by: cactus <cactus@intel.com>
Reviewed-by: Shi, PingX <pingx.shi@intel.com>
Tested-by: Shi, PingX <pingx.shi@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
diff --git a/imagedecoder/JPEGDecoder.c b/imagedecoder/JPEGDecoder.c
index b1ecb49..f692ede 100644
--- a/imagedecoder/JPEGDecoder.c
+++ b/imagedecoder/JPEGDecoder.c
@@ -53,18 +53,11 @@
    * them here and return false is meaningless, same situation for all internal methods
    * related to VA API
   */
-    int va_major_version;
-    int va_minor_version;
-#if 0
-    int va_max_num_profiles, va_max_num_entrypoints, va_max_num_attribs;
-    int va_num_profiles,  va_num_entrypoints;
-
-    VAProfile *va_profiles = NULL;
-    VAEntrypoint *va_entrypoints = NULL;
-#endif
+    uint32_t va_major_version = 0;
+    uint32_t va_minor_version = 0;
     VAStatus va_status = VA_STATUS_SUCCESS;
     Decode_Status status = DECODE_SUCCESS;
-    int index;
+    uint32_t index;
 
     if (jd_libva_ptr->initialized)
         return DECODE_NOT_STARTED;
@@ -86,54 +79,7 @@
         status = DECODE_DRIVER_FAIL;
         goto cleanup;
     }
-#if 0
-    /*get the max number for profiles/entrypoints/attribs*/
-    va_max_num_profiles = vaMaxNumProfiles(jd_libva_ptr->va_display);
-    va_max_num_entrypoints = vaMaxNumEntrypoints(jd_libva_ptr->va_display);
-    va_max_num_attribs = vaMaxNumConfigAttributes(jd_libva_ptr->va_display);
 
-    va_profiles = malloc (sizeof(VAProfile)*va_max_num_profiles);
-    va_entrypoints = malloc(sizeof(VAEntrypoint)*va_max_num_entrypoints);
-
-    if (va_profiles == NULL || va_entrypoints ==NULL) {
-        jd_libva_ptr->initialized = TRUE; // make sure we can call into jva_deinitialize()
-        jdva_deinitialize (jd_libva_ptr);
-        return DECODE_MEMORY_FAIL;
-    }
-
-    va_status = vaQueryConfigProfiles (jd_libva_ptr->va_display, va_profiles, &va_num_profiles);
-
-    if (va_status != VA_STATUS_SUCCESS) {
-        ETRACE("vaQueryConfigProfiles failed. va_status = 0x%x", va_status);
-        status = DECODE_DRIVER_FAIL;
-        goto cleanup;
-    }
-
-    /*check whether profile is supported*/
-    for(index= 0; index < va_num_profiles; index++) {
-        if(VAProfileJPEGBaseline == va_profiles[index])
-            break;
-    }
-
-    if(index == va_num_profiles) {
-        WTRACE("Profile not surportted\n");
-        status = DECODE_FAIL;
-        goto cleanup;
-
-    }
-
-    va_status = vaQueryConfigEntrypoints(jd_libva_ptr->va_display, VAProfileJPEGBaseline, va_entrypoints, &va_num_entrypoints);
-    if (va_status != VA_STATUS_SUCCESS) {
-        ETRACE("vaQueryConfigProfiles failed. va_status = 0x%x", va_status);
-        status = DECODE_DRIVER_FAIL;
-        goto cleanup;
-    }
-    /* traverse entrypoints arrary to see whether VLD is there */
-    for (index = 0; index < va_num_entrypoints; index ++) {
-        if (va_entrypoints[index] == VAEntrypointVLD)
-            break;
-    }
-#endif
     VAConfigAttrib attrib;
     attrib.type = VAConfigAttribRTFormat;
     va_status = vaGetConfigAttributes(jd_libva_ptr->va_display, VAProfileJPEGBaseline, VAEntrypointVLD, &attrib, 1);
@@ -166,7 +112,7 @@
     if (va_entrypoints)
         free (va_entrypoints);
 #endif
-    if (!status) {
+    if (status) {
         jd_libva_ptr->initialized = TRUE; // make sure we can call into jva_deinitialize()
         jdva_deinitialize (jd_libva_ptr);
         return status;
@@ -201,7 +147,7 @@
 
 Decode_Status jdva_create_resource (jd_libva_struct * jd_libva_ptr) {
     VAStatus va_status = VA_STATUS_SUCCESS;
-    Decode_Status status;
+    Decode_Status status = DECODE_SUCCESS;
     jd_libva_ptr->image_width = jd_libva_ptr->picture_param_buf.picture_width;
     jd_libva_ptr->image_height = jd_libva_ptr->picture_param_buf.picture_height;
     jd_libva_ptr->surface_count = 1;
@@ -210,8 +156,8 @@
         return DECODE_MEMORY_FAIL;
     }
     va_status = vaCreateSurfaces(jd_libva_ptr->va_display, VA_RT_FORMAT_YUV444,
-                                    (((jd_libva_ptr->image_width + 7) & (~7)) + 15) & (~15),
-                                    (((jd_libva_ptr->image_width + 7) & (~7)) + 15) & (~15),
+                                    jd_libva_ptr->image_width,
+                                    jd_libva_ptr->image_height,
                                     jd_libva_ptr->va_surfaces,
                                     jd_libva_ptr->surface_count, NULL, 0);
     if (va_status != VA_STATUS_SUCCESS) {
@@ -220,8 +166,8 @@
         goto cleanup;
     }
     va_status = vaCreateContext(jd_libva_ptr->va_display, jd_libva_ptr->va_config,
-                                   (( ( jd_libva_ptr->image_width + 7 ) & ( ~7 )) + 15 ) & ( ~15 ),
-                                   ((( jd_libva_ptr->image_height + 7 ) & ( ~7 )) + 15 ) & ( ~15 ),
+                                   jd_libva_ptr->image_width,
+                                   jd_libva_ptr->image_height,
                                    0,  //VA_PROGRESSIVE
                                    jd_libva_ptr->va_surfaces,
                                    jd_libva_ptr->surface_count, &(jd_libva_ptr->va_context));
@@ -298,13 +244,13 @@
     Decode_Status status = DECODE_SUCCESS;
     VAStatus va_status = VA_STATUS_SUCCESS;
     VABufferID desc_buf[5];
-    uint32_t bitstream_buffer_size;
+    uint32_t bitstream_buffer_size = 0;
     uint32_t scan_idx = 0;
     uint32_t buf_idx = 0;
     uint32_t chopping = VA_SLICE_DATA_FLAG_ALL;
-    uint32_t bytes_remaining = jd_libva_ptr->file_size;
-    uint32_t src_offset = 0;
-    bitstream_buffer_size = 1024*512*5;
+    uint32_t bytes_remaining = jd_libva_ptr->eoi_offset - jd_libva_ptr->soi_offset;
+    uint32_t src_offset = jd_libva_ptr->soi_offset;
+    bitstream_buffer_size = 1024*1024*5;
 
     va_status = vaBeginPicture(jd_libva_ptr->va_display, jd_libva_ptr->va_context, jd_libva_ptr->va_surfaces[0]);
     if (va_status != VA_STATUS_SUCCESS) {
@@ -340,7 +286,7 @@
         bytes_remaining -= bytes;
         /* Get Slice Control Buffer */
         VASliceParameterBufferJPEG dest_scan_ctrl[JPEG_MAX_COMPONENTS];
-        uint32_t src_idx;
+        uint32_t src_idx = 0;
         uint32_t dest_idx = 0;
         memset(dest_scan_ctrl, 0, sizeof(dest_scan_ctrl));
         for (src_idx = scan_idx; src_idx < jd_libva_ptr->scan_ctrl_count ; src_idx++) {
@@ -365,7 +311,7 @@
             }
             dest_scan_ctrl[dest_idx].slice_data_flag = chopping;
             dest_scan_ctrl[dest_idx].slice_data_offset = ((chopping == VA_SLICE_DATA_FLAG_ALL) ||      (chopping == VA_SLICE_DATA_FLAG_BEGIN) )?
-jd_libva_ptr->slice_param_buf[ src_idx ].slice_data_offset - src_offset : 0;
+jd_libva_ptr->slice_param_buf[ src_idx ].slice_data_offset : 0;
 
             const int32_t bytes_in_seg = bytes - dest_scan_ctrl[dest_idx].slice_data_offset;
             const uint32_t scan_data = (bytes_in_seg < jd_libva_ptr->slice_param_buf[src_idx].slice_data_size) ? bytes_in_seg : jd_libva_ptr->slice_param_buf[src_idx].slice_data_size ;
@@ -477,8 +423,12 @@
 
     uint8_t marker = jd_libva_ptr->JPEGParser->getNextMarker(jd_libva_ptr->JPEGParser);
 
-    while (marker != CODE_EOI) {
+    while (marker != CODE_EOI &&( !jd_libva_ptr->JPEGParser->endOfBuffer(jd_libva_ptr->JPEGParser))) {
         switch (marker) {
+            case CODE_SOI: {
+                 jd_libva_ptr->soi_offset = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser) - 2;
+                break;
+            }
             // If the marker is an APP marker skip over the data
             case CODE_APP0:
             case CODE_APP1:
@@ -503,10 +453,15 @@
             }
             // Store offset to DQT data to avoid parsing bitstream in user mode
             case CODE_DQT: {
-                jd_libva_ptr->dqt_byte_offset[dqt_ind] = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser);
-                dqt_ind++;
-                uint32_t bytes_to_burn = jd_libva_ptr->JPEGParser->readBytes( jd_libva_ptr->JPEGParser, 2 ) - 2;
-                jd_libva_ptr->JPEGParser->burnBytes( jd_libva_ptr->JPEGParser, bytes_to_burn );
+                if (dqt_ind < 4) {
+                    jd_libva_ptr->dqt_byte_offset[dqt_ind] = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser) - jd_libva_ptr->soi_offset;
+                    dqt_ind++;
+                    uint32_t bytes_to_burn = jd_libva_ptr->JPEGParser->readBytes( jd_libva_ptr->JPEGParser, 2 ) - 2;
+                    jd_libva_ptr->JPEGParser->burnBytes( jd_libva_ptr->JPEGParser, bytes_to_burn );
+                } else {
+                    ETRACE("ERROR: Decoder does not support more than 4 Quant Tables\n");
+                    return DECODE_PARSER_FAIL;
+                }
                 break;
             }
             // Throw exception for all SOF marker other than SOF0
@@ -523,7 +478,7 @@
             case CODE_SOF13:
             case CODE_SOF14:
             case CODE_SOF15: {
-                fprintf(stderr, "ERROR: unsupport SOF\n");
+                ETRACE("ERROR: unsupport SOF\n");
                 break;
             }
             // Parse component information in SOF marker
@@ -531,8 +486,9 @@
                 frame_marker_found = TRUE;
 
                 jd_libva_ptr->JPEGParser->burnBytes(jd_libva_ptr->JPEGParser, 2); // Throw away frame header length
-                jd_libva_ptr->picture_param_buf.sample_precision = jd_libva_ptr->JPEGParser->readNextByte(jd_libva_ptr->JPEGParser);
-                if (jd_libva_ptr->picture_param_buf.sample_precision != 8) {
+                uint8_t sample_precision = jd_libva_ptr->JPEGParser->readNextByte(jd_libva_ptr->JPEGParser);
+                if (sample_precision != 8) {
+                    ETRACE("sample_precision is not supported\n");
                     return DECODE_PARSER_FAIL;
                 }
                 // Extract pic width and height
@@ -543,7 +499,7 @@
                 if (jd_libva_ptr->picture_param_buf.num_components > JPEG_MAX_COMPONENTS) {
                     return DECODE_PARSER_FAIL;
                 }
-                uint8_t comp_ind;
+                uint8_t comp_ind = 0;
                 for (comp_ind = 0; comp_ind < jd_libva_ptr->picture_param_buf.num_components; comp_ind++) {
                     jd_libva_ptr->picture_param_buf.components[comp_ind].component_id = jd_libva_ptr->JPEGParser->readNextByte(jd_libva_ptr->JPEGParser);
 
@@ -558,17 +514,22 @@
             }
             // Store offset to DHT data to avoid parsing bitstream in user mode
             case CODE_DHT: {
-                jd_libva_ptr->dht_byte_offset[dht_ind] = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser);
-                dht_ind++;
-                uint32_t bytes_to_burn = jd_libva_ptr->JPEGParser->readBytes(jd_libva_ptr->JPEGParser, 2) - 2;
-                jd_libva_ptr->JPEGParser->burnBytes(jd_libva_ptr->JPEGParser,  bytes_to_burn );
+                if (dht_ind < 4) {
+                    jd_libva_ptr->dht_byte_offset[dht_ind] = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser) - jd_libva_ptr->soi_offset;
+                    dht_ind++;
+                    uint32_t bytes_to_burn = jd_libva_ptr->JPEGParser->readBytes(jd_libva_ptr->JPEGParser, 2) - 2;
+                    jd_libva_ptr->JPEGParser->burnBytes(jd_libva_ptr->JPEGParser,  bytes_to_burn );
+                } else {
+                    ETRACE("ERROR: Decoder does not support more than 4 Huff Tables\n");
+                    return DECODE_PARSER_FAIL;
+                }
                 break;
             }
             // Parse component information in SOS marker
             case CODE_SOS: {
                 jd_libva_ptr->JPEGParser->burnBytes(jd_libva_ptr->JPEGParser, 2);
                 uint32_t component_in_scan = jd_libva_ptr->JPEGParser->readNextByte(jd_libva_ptr->JPEGParser);
-                uint8_t comp_ind;
+                uint8_t comp_ind = 0;
 
                 for (comp_ind = 0; comp_ind < component_in_scan; comp_ind++) {
                     uint8_t comp_id = jd_libva_ptr->JPEGParser->readNextByte(jd_libva_ptr->JPEGParser);
@@ -596,7 +557,7 @@
                     return DECODE_PARSER_FAIL;
                 }
                 // Set slice control variables needed
-                jd_libva_ptr->slice_param_buf[scan_ind].slice_data_offset = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser);
+                jd_libva_ptr->slice_param_buf[scan_ind].slice_data_offset = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser) - jd_libva_ptr->soi_offset;
                 jd_libva_ptr->slice_param_buf[scan_ind].num_components = component_in_scan;
                 if (scan_ind) {
                     /* If there is more than one scan, the slice for all but the final scan should only run up to the beginning of the next scan */
@@ -618,13 +579,18 @@
         }
 
         marker = jd_libva_ptr->JPEGParser->getNextMarker(jd_libva_ptr->JPEGParser);
+        // If the EOI code is found, store the byte offset before the parsing finishes
+        if( marker == CODE_EOI ) {
+            jd_libva_ptr->eoi_offset = jd_libva_ptr->JPEGParser->getByteOffset(jd_libva_ptr->JPEGParser);
+        }
+
     }
 
     jd_libva_ptr->quant_tables_num = dqt_ind;
     jd_libva_ptr->huffman_tables_num = dht_ind;
 
     /* The slice for the last scan should run up to the end of the picture */
-    jd_libva_ptr->slice_param_buf[scan_ind - 1].slice_data_size = (jd_libva_ptr->file_size - jd_libva_ptr->slice_param_buf[scan_ind - 1].slice_data_offset);
+    jd_libva_ptr->slice_param_buf[scan_ind - 1].slice_data_size = (jd_libva_ptr->eoi_offset - jd_libva_ptr->slice_param_buf[scan_ind - 1].slice_data_offset);
 
     // throw AppException if SOF0 isn't found
     if (!frame_marker_found) {
@@ -639,7 +605,6 @@
 }
 
 Decode_Status parseTableData(jd_libva_struct * jd_libva_ptr) {
-    Decode_Status status;
     CJPEGParse* parser = (CJPEGParse*)malloc(sizeof(CJPEGParse));
     if (parser == NULL)
         return DECODE_MEMORY_FAIL;
@@ -648,7 +613,7 @@
 
     // Parse Quant tables
     memset(&jd_libva_ptr->qmatrix_buf, 0, sizeof(jd_libva_ptr->qmatrix_buf));
-    uint32_t dqt_ind;
+    uint32_t dqt_ind = 0;
     for (dqt_ind = 0; dqt_ind < jd_libva_ptr->quant_tables_num; dqt_ind++) {
         if (parser->setByteOffset(parser, jd_libva_ptr->dqt_byte_offset[dqt_ind])) {
             // uint32_t uiTableBytes = parser->readBytes( 2 ) - 2;
@@ -662,15 +627,18 @@
                     return DECODE_PARSER_FAIL;
                 }
                 uint32_t table_id = table_info & 0xf;
-                if (table_id >= JPEG_MAX_QUANT_TABLES) {
-                    return DECODE_PARSER_FAIL;
-                }
+
                 jd_libva_ptr->qmatrix_buf.load_quantiser_table[dqt_ind] = table_id;
 
-                // Pull Quant table data from bitstream
-                uint32_t byte_ind;
-                for (byte_ind = 0; byte_ind < table_length; byte_ind++) {
-                    jd_libva_ptr->qmatrix_buf.quantiser_table[table_id][byte_ind] = parser->readNextByte(parser);
+                if (table_id < JPEG_MAX_QUANT_TABLES) {
+                    // Pull Quant table data from bitstream
+                    uint32_t byte_ind;
+                    for (byte_ind = 0; byte_ind < table_length; byte_ind++) {
+                        jd_libva_ptr->qmatrix_buf.quantiser_table[table_id][byte_ind] = parser->readNextByte(parser);
+                    }
+                } else {
+                    ETRACE("DQT table ID is not supported");
+                    parser->burnBytes(parser, table_length);
                 }
                 table_bytes -= table_length;
             } while (table_bytes);
@@ -679,7 +647,7 @@
 
     // Parse Huffman tables
     memset(&jd_libva_ptr->hufman_table_buf, 0, sizeof(jd_libva_ptr->hufman_table_buf));
-    uint32_t dht_ind;
+    uint32_t dht_ind = 0;
     for (dht_ind = 0; dht_ind < jd_libva_ptr->huffman_tables_num; dht_ind++) {
         if (parser->setByteOffset(parser, jd_libva_ptr->dht_byte_offset[dht_ind])) {
             uint32_t table_bytes = parser->readBytes( parser, 2 ) - 2;
@@ -687,51 +655,59 @@
                 uint32_t table_info = parser->readNextByte(parser);
                 table_bytes--;
                 uint32_t table_class = table_info >> 4; // Identifies whether the table is for AC or DC
-                if (table_class >= TABLE_CLASS_NUM) {
-                    return DECODE_PARSER_FAIL;
-                }
                 uint32_t table_id = table_info & 0xf;
-                if (table_id >= JPEG_MAX_SETS_HUFFMAN_TABLES) {
-                    return DECODE_PARSER_FAIL;
-                }
-                if (table_class == 0) {
-                    uint8_t* bits = parser->getCurrentIndex(parser);
-                    // Find out the number of entries in the table
-                    uint32_t table_entries = 0;
-                    uint32_t bit_ind;
-                    for (bit_ind = 0; bit_ind < 16; bit_ind++) {
-                        jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_dc_codes[bit_ind] = bits[bit_ind];
-                        table_entries += jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_dc_codes[bit_ind];
-                    }
 
-                    // Create table of code values
-                    parser->burnBytes(parser, 16);
-                    table_bytes -= 16;
-                    uint32_t tbl_ind;
-                    for (tbl_ind = 0; tbl_ind < table_entries; tbl_ind++) {
-                        jd_libva_ptr->hufman_table_buf.huffman_table[table_id].dc_values[tbl_ind] = parser->readNextByte(parser);
+                if ((table_class < TABLE_CLASS_NUM) && (table_id < JPEG_MAX_SETS_HUFFMAN_TABLES)) {
+                    if (table_class == 0) {
+                        uint8_t* bits = parser->getCurrentIndex(parser);
+                        // Find out the number of entries in the table
+                        uint32_t table_entries = 0;
+                        uint32_t bit_ind;
+                        for (bit_ind = 0; bit_ind < 16; bit_ind++) {
+                            jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_dc_codes[bit_ind] = bits[bit_ind];
+                            table_entries += jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_dc_codes[bit_ind];
+                        }
+
+                        // Create table of code values
+                        parser->burnBytes(parser, 16);
+                        table_bytes -= 16;
+                        uint32_t tbl_ind;
+                        for (tbl_ind = 0; tbl_ind < table_entries; tbl_ind++) {
+                            jd_libva_ptr->hufman_table_buf.huffman_table[table_id].dc_values[tbl_ind] = parser->readNextByte(parser);
+                            table_bytes--;
+                        }
+
+                    } else { // for AC class
+                        uint8_t* bits = parser->getCurrentIndex(parser);
+                        // Find out the number of entries in the table
+                        uint32_t table_entries = 0;
+                        uint32_t bit_ind = 0;
+                        for (bit_ind = 0; bit_ind < 16; bit_ind++) {
+                            jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_ac_codes[bit_ind] = bits[bit_ind];
+                            table_entries += jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_ac_codes[bit_ind];
+                        }
+
+                        // Create table of code values
+                        parser->burnBytes(parser, 16);
+                        table_bytes -= 16;
+                        uint32_t tbl_ind = 0;
+                        for (tbl_ind = 0; tbl_ind < table_entries; tbl_ind++) {
+                            jd_libva_ptr->hufman_table_buf.huffman_table[table_id].ac_values[tbl_ind] = parser->readNextByte(parser);
+                            table_bytes--;
+                        }
+                    }//end of else
+                } else {
+                    // Find out the number of entries in the table
+                    ETRACE("DHT table ID is not supported");
+                    uint32_t table_entries = 0;
+                    uint32_t bit_ind = 0;
+                    for(bit_ind = 0; bit_ind < 16; bit_ind++) {
+                        table_entries += parser->readNextByte(parser);
                         table_bytes--;
                     }
-
-                } else { // for AC class
-                    uint8_t* bits = parser->getCurrentIndex(parser);
-                    // Find out the number of entries in the table
-                    uint32_t table_entries = 0;
-                    uint32_t bit_ind;
-                    for (bit_ind = 0; bit_ind < 16; bit_ind++) {
-                        jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_ac_codes[bit_ind] = bits[bit_ind];
-                        table_entries += jd_libva_ptr->hufman_table_buf.huffman_table[table_id].num_ac_codes[bit_ind];
-                    }
-
-                    // Create table of code values
-                    parser->burnBytes(parser, 16);
-                    table_bytes -= 16;
-                    uint32_t tbl_ind;
-                    for (tbl_ind = 0; tbl_ind < table_entries; tbl_ind++) {
-                        jd_libva_ptr->hufman_table_buf.huffman_table[table_id].ac_values[tbl_ind] = parser->readNextByte(parser);
-                        table_bytes--;
-                    }
-                }//end of else
+                    parser->burnBytes(parser, table_entries);
+                    table_bytes -= table_entries;
+		}
 
             } while (table_bytes);
         }
diff --git a/imagedecoder/JPEGDecoder.h b/imagedecoder/JPEGDecoder.h
index efc8091..b1e84b0 100644
--- a/imagedecoder/JPEGDecoder.h
+++ b/imagedecoder/JPEGDecoder.h
@@ -58,6 +58,8 @@
     uint32_t dqt_byte_offset[4];
     uint32_t huffman_tables_num;
     uint32_t quant_tables_num;
+    uint32_t soi_offset;
+    uint32_t eoi_offset;
 
     uint8_t* bitstream_buf;
     uint32_t image_width;