static OPJ_BOOL opj_t2_read_packet_header(opj_t2_t* p_t2,
        opj_tcd_tile_t *p_tile,
        opj_tcp_t *p_tcp,
        opj_pi_iterator_t *p_pi,
        OPJ_BOOL * p_is_data_present,
        OPJ_BYTE *p_src_data,
        OPJ_UINT32 * p_data_read,
        OPJ_UINT32 p_max_length,
        opj_packet_info_t *p_pack_info,
        opj_event_mgr_t *p_manager)

{
    /* loop */
    OPJ_UINT32 bandno, cblkno;
    OPJ_UINT32 l_nb_code_blocks;
    OPJ_UINT32 l_remaining_length;
    OPJ_UINT32 l_header_length;
    OPJ_UINT32 * l_modified_length_ptr = 00;
    OPJ_BYTE *l_current_data = p_src_data;
    opj_cp_t *l_cp = p_t2->cp;
    opj_bio_t *l_bio = 00;  /* BIO component */
    opj_tcd_band_t *l_band = 00;
    opj_tcd_cblk_dec_t* l_cblk = 00;
    opj_tcd_resolution_t* l_res =
        &p_tile->comps[p_pi->compno].resolutions[p_pi->resno];

    OPJ_BYTE *l_header_data = 00;
    OPJ_BYTE **l_header_data_start = 00;

    OPJ_UINT32 l_present;

    if (p_pi->layno == 0) {
        l_band = l_res->bands;

        /* reset tagtrees */
        for (bandno = 0; bandno < l_res->numbands; ++bandno) {
            if (!opj_tcd_is_band_empty(l_band)) {
                opj_tcd_precinct_t *l_prc = &l_band->precincts[p_pi->precno];
                if (!(p_pi->precno < (l_band->precincts_data_size / sizeof(
                                          opj_tcd_precinct_t)))) {
                    opj_event_msg(p_manager, EVT_ERROR, "Invalid precinct\n");
                    return OPJ_FALSE;
                }


                opj_tgt_reset(l_prc->incltree);
                opj_tgt_reset(l_prc->imsbtree);
                l_cblk = l_prc->cblks.dec;

                l_nb_code_blocks = l_prc->cw * l_prc->ch;
                for (cblkno = 0; cblkno < l_nb_code_blocks; ++cblkno) {
                    l_cblk->numsegs = 0;
                    l_cblk->real_num_segs = 0;
                    ++l_cblk;
                }
            }

            ++l_band;
        }
    }

    /* SOP markers */

    if (p_tcp->csty & J2K_CP_CSTY_SOP) {
        if (p_max_length < 6) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "Not enough space for expected SOP marker\n");
        } else if ((*l_current_data) != 0xff || (*(l_current_data + 1) != 0x91)) {
            opj_event_msg(p_manager, EVT_WARNING, "Expected SOP marker\n");
        } else {
            l_current_data += 6;
        }

        /** TODO : check the Nsop value */
    }

    /*
    When the marker PPT/PPM is used the packet header are store in PPT/PPM marker
    This part deal with this caracteristic
    step 1: Read packet header in the saved structure
    step 2: Return to codestream for decoding
    */

    l_bio = opj_bio_create();
    if (! l_bio) {
        return OPJ_FALSE;
    }

    if (l_cp->ppm == 1) { /* PPM */
        l_header_data_start = &l_cp->ppm_data;
        l_header_data = *l_header_data_start;
        l_modified_length_ptr = &(l_cp->ppm_len);

    } else if (p_tcp->ppt == 1) { /* PPT */
        l_header_data_start = &(p_tcp->ppt_data);
        l_header_data = *l_header_data_start;
        l_modified_length_ptr = &(p_tcp->ppt_len);
    } else { /* Normal Case */
        l_header_data_start = &(l_current_data);
        l_header_data = *l_header_data_start;
        l_remaining_length = (OPJ_UINT32)(p_src_data + p_max_length - l_header_data);
        l_modified_length_ptr = &(l_remaining_length);
    }

    opj_bio_init_dec(l_bio, l_header_data, *l_modified_length_ptr);

    l_present = opj_bio_read(l_bio, 1);
    JAS_FPRINTF(stderr, "present=%d \n", l_present);
    if (!l_present) {
        /* TODO MSD: no test to control the output of this function*/
        opj_bio_inalign(l_bio);
        l_header_data += opj_bio_numbytes(l_bio);
        opj_bio_destroy(l_bio);

        /* EPH markers */
        if (p_tcp->csty & J2K_CP_CSTY_EPH) {
            if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data -
                    *l_header_data_start)) < 2U) {
                opj_event_msg(p_manager, EVT_WARNING,
                              "Not enough space for expected EPH marker\n");
            } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
                opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n");
            } else {
                l_header_data += 2;
            }
        }

        l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start);
        *l_modified_length_ptr -= l_header_length;
        *l_header_data_start += l_header_length;

        /* << INDEX */
        /* End of packet header position. Currently only represents the distance to start of packet
           Will be updated later by incrementing with packet start value */
        if (p_pack_info) {
            p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data);
        }
        /* INDEX >> */

        * p_is_data_present = OPJ_FALSE;
        *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data);
        return OPJ_TRUE;
    }

    l_band = l_res->bands;
    for (bandno = 0; bandno < l_res->numbands; ++bandno, ++l_band) {
        opj_tcd_precinct_t *l_prc = &(l_band->precincts[p_pi->precno]);

        if (opj_tcd_is_band_empty(l_band)) {
            continue;
        }

        l_nb_code_blocks = l_prc->cw * l_prc->ch;
        l_cblk = l_prc->cblks.dec;
        for (cblkno = 0; cblkno < l_nb_code_blocks; cblkno++) {
            OPJ_UINT32 l_included, l_increment, l_segno;
            OPJ_INT32 n;

            /* if cblk not yet included before --> inclusion tagtree */
            if (!l_cblk->numsegs) {
                l_included = opj_tgt_decode(l_bio, l_prc->incltree, cblkno,
                                            (OPJ_INT32)(p_pi->layno + 1));
                /* else one bit */
            } else {
                l_included = opj_bio_read(l_bio, 1);
            }

            /* if cblk not included */
            if (!l_included) {
                l_cblk->numnewpasses = 0;
                ++l_cblk;
                JAS_FPRINTF(stderr, "included=%d \n", l_included);
                continue;
            }

            /* if cblk not yet included --> zero-bitplane tagtree */
            if (!l_cblk->numsegs) {
                OPJ_UINT32 i = 0;

                while (!opj_tgt_decode(l_bio, l_prc->imsbtree, cblkno, (OPJ_INT32)i)) {
                    ++i;
                }

                l_cblk->numbps = (OPJ_UINT32)l_band->numbps + 1 - i;
                l_cblk->numlenbits = 3;
            }

            /* number of coding passes */
            l_cblk->numnewpasses = opj_t2_getnumpasses(l_bio);
            l_increment = opj_t2_getcommacode(l_bio);

            /* length indicator increment */
            l_cblk->numlenbits += l_increment;
            l_segno = 0;

            if (!l_cblk->numsegs) {
                if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 1)) {
                    opj_bio_destroy(l_bio);
                    return OPJ_FALSE;
                }
            } else {
                l_segno = l_cblk->numsegs - 1;
                if (l_cblk->segs[l_segno].numpasses == l_cblk->segs[l_segno].maxpasses) {
                    ++l_segno;
                    if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
                        opj_bio_destroy(l_bio);
                        return OPJ_FALSE;
                    }
                }
            }
            n = (OPJ_INT32)l_cblk->numnewpasses;

            do {
                OPJ_UINT32 bit_number;
                l_cblk->segs[l_segno].numnewpasses = (OPJ_UINT32)opj_int_min((OPJ_INT32)(
                        l_cblk->segs[l_segno].maxpasses - l_cblk->segs[l_segno].numpasses), n);
                bit_number = l_cblk->numlenbits + opj_uint_floorlog2(
                                 l_cblk->segs[l_segno].numnewpasses);
                if (bit_number > 32) {
                    opj_event_msg(p_manager, EVT_ERROR,
                                  "Invalid bit number %d in opj_t2_read_packet_header()\n",
                                  bit_number);
                    opj_bio_destroy(l_bio);
                    return OPJ_FALSE;
                }
                l_cblk->segs[l_segno].newlen = opj_bio_read(l_bio, bit_number);
                JAS_FPRINTF(stderr, "included=%d numnewpasses=%d increment=%d len=%d \n",
                            l_included, l_cblk->segs[l_segno].numnewpasses, l_increment,
                            l_cblk->segs[l_segno].newlen);

                n -= (OPJ_INT32)l_cblk->segs[l_segno].numnewpasses;
                if (n > 0) {
                    ++l_segno;

                    if (! opj_t2_init_seg(l_cblk, l_segno, p_tcp->tccps[p_pi->compno].cblksty, 0)) {
                        opj_bio_destroy(l_bio);
                        return OPJ_FALSE;
                    }
                }
            } while (n > 0);

            ++l_cblk;
        }
    }

    if (!opj_bio_inalign(l_bio)) {
        opj_bio_destroy(l_bio);
        return OPJ_FALSE;
    }

    l_header_data += opj_bio_numbytes(l_bio);
    opj_bio_destroy(l_bio);

    /* EPH markers */
    if (p_tcp->csty & J2K_CP_CSTY_EPH) {
        if ((*l_modified_length_ptr - (OPJ_UINT32)(l_header_data -
                *l_header_data_start)) < 2U) {
            opj_event_msg(p_manager, EVT_WARNING,
                          "Not enough space for expected EPH marker\n");
        } else if ((*l_header_data) != 0xff || (*(l_header_data + 1) != 0x92)) {
            opj_event_msg(p_manager, EVT_WARNING, "Expected EPH marker\n");
        } else {
            l_header_data += 2;
        }
    }

    l_header_length = (OPJ_UINT32)(l_header_data - *l_header_data_start);
    JAS_FPRINTF(stderr, "hdrlen=%d \n", l_header_length);
    JAS_FPRINTF(stderr, "packet body\n");
    *l_modified_length_ptr -= l_header_length;
    *l_header_data_start += l_header_length;

    /* << INDEX */
    /* End of packet header position. Currently only represents the distance to start of packet
     Will be updated later by incrementing with packet start value */
    if (p_pack_info) {
        p_pack_info->end_ph_pos = (OPJ_INT32)(l_current_data - p_src_data);
    }
    /* INDEX >> */

    *p_is_data_present = OPJ_TRUE;
    *p_data_read = (OPJ_UINT32)(l_current_data - p_src_data);

    return OPJ_TRUE;
}