static int parse_picture_header_intra(davs2_t *h, davs2_bs_t *bs)
{
    int time_code_flag;
    int progressive_frame;
    int predict;
    int i;

    h->i_frame_type = AVS2_I_SLICE;

    /* skip start code */
    bs->i_bit_pos += 32;

    u_v(bs, 32, "bbv_delay");
    time_code_flag                      = u_v(bs, 1, "time_code_flag");

    if (time_code_flag) {
        /* time_code                 = */ u_v(bs, 24, "time_code");
    }

    if (h->b_bkgnd_picture) {
        int background_picture_flag     = u_v(bs, 1, "background_picture_flag");

        if (background_picture_flag) {
            int b_output                = u_v(bs, 1, "background_picture_output_flag");
            if (b_output) {
                h->i_frame_type = AVS2_G_SLICE;
            } else {
                h->i_frame_type = AVS2_GB_SLICE;
            }
        }
    }

    h->i_coi                            = u_v(bs, 8, "coding_order");

    if (h->seq_info.b_temporal_id_exist == 1) {
        h->i_cur_layer                  = u_v(bs, TEMPORAL_MAXLEVEL_BIT, "temporal_id");
    }

    if (h->seq_info.head.low_delay == 0) {
        h->i_display_delay              = ue_v(bs, "picture_output_delay");
        if (h->i_display_delay >= 64) {
            davs2_log(h, DAVS2_LOG_ERROR, "invalid picture output delay intra.");
            return -1;
        }
    }

    predict                             = u_v(bs, 1, "use RCS in SPS");
    if (predict) {
        int index                       = u_v(bs, 5, "predict for RCS");
        if (index >= h->seq_info.num_of_rps) {
            davs2_log(h, DAVS2_LOG_ERROR, "invalid rps index.");
            return -1;
        }

        h->rps                          = h->seq_info.seq_rps[index];
    } else {
        h->rps.refered_by_others        = u_v(bs, 1, "refered by others");
        h->rps.num_of_ref               = u_v(bs, 3, "num of reference picture");
        if (h->rps.num_of_ref > AVS2_MAX_REFS) {
            davs2_log(h, DAVS2_LOG_ERROR, "invalid number of references.");
            return -1;
        }

        for (i = 0; i < h->rps.num_of_ref; i++) {
            h->rps.ref_pic[i]           = u_v(bs, 6, "delta COI of ref pic");
        }

        h->rps.num_to_remove            = u_v(bs, 3, "num of removed picture");
        assert((unsigned int)h->rps.num_to_remove <= sizeof(h->rps.remove_pic) / sizeof(h->rps.remove_pic[0]));

        for (i = 0; i < h->rps.num_to_remove; i++) {
            h->rps.remove_pic[i]        = u_v(bs, 6, "delta COI of removed pic");
        }
        u_v(bs, 1, "marker bit");
    }

    if (h->seq_info.head.low_delay) {
        /* bbv_check_times           = */ ue_v(bs, "bbv check times");
    }

    progressive_frame                   = u_v(bs, 1, "progressive_frame");

    if (!progressive_frame) {
        h->i_pic_coding_type            = (int8_t)u_v(bs, 1, "picture_structure");
    } else {
        h->i_pic_coding_type            = FRAME;
    }

    h->b_top_field_first                = u_flag(bs, "top_field_first");
    h->b_repeat_first_field             = u_flag(bs, "repeat_first_field");

    if (h->seq_info.b_field_coding) {
        h->b_top_field                  = u_flag(bs, "is_top_field");
        /* reserved                  = */ u_v(bs, 1, "reserved bit for interlace coding");
    }

    h->b_fixed_picture_qp               = u_flag(bs, "fixed_picture_qp");
    h->i_picture_qp                     = u_v(bs, 7, "picture_qp");

    h->b_loop_filter                    = u_v(bs, 1, "loop_filter_disable") ^ 0x01;

    if (h->b_loop_filter) {
        int loop_filter_parameter_flag  = u_v(bs, 1, "loop_filter_parameter_flag");

        if (loop_filter_parameter_flag) {
            h->i_alpha_offset           = se_v(bs, "alpha_offset");
            h->i_beta_offset            = se_v(bs, "beta_offset");
        } else {
            h->i_alpha_offset           = 0;
            h->i_beta_offset            = 0;
        }

        deblock_init_frame_parames(h);
    }

    h->enable_chroma_quant_param        = !u_flag(bs, "chroma_quant_param_disable");
    if (h->enable_chroma_quant_param) {
        h->chroma_quant_param_delta_u = se_v(bs, "chroma_quant_param_delta_cb");
        h->chroma_quant_param_delta_v = se_v(bs, "chroma_quant_param_delta_cr");
    } else {
        h->chroma_quant_param_delta_u = 0;
        h->chroma_quant_param_delta_v = 0;
    }

    // adaptive frequency weighting quantization
    h->seq_info.enable_weighted_quant = 0;

    if (h->seq_info.enable_weighted_quant) {
        int pic_weight_quant_enable     = u_v(bs, 1, "pic_weight_quant_enable");
        if (pic_weight_quant_enable) {
            weighted_quant_t *p = &h->wq;
            p->pic_wq_data_index        = u_v(bs, 2, "pic_wq_data_index");

            if (p->pic_wq_data_index == 1) {
                /* int mb_adapt_wq_disable = */       u_v(bs, 1, "reserved_bits");

                p->wq_param             = u_v(bs, 2, "weighting_quant_param_index");
                p->wq_model             = u_v(bs, 2, "wq_model");

                if (p->wq_param == 1) {
                    for (i = 0; i < 6; i++) {
                        p->quant_param_undetail[i] = (int16_t)se_v(bs, "quant_param_delta_u") + wq_param_default[UNDETAILED][i];
                    }
                }

                if (p->wq_param == 2) {
                    for (i = 0; i < 6; i++) {
                        p->quant_param_detail[i] = (int16_t)se_v(bs, "quant_param_delta_d") + wq_param_default[DETAILED][i];
                    }
                }
            } else if (p->pic_wq_data_index == 2) {
                int x, y, sizeId, uiWqMSize;

                for (sizeId = 0; sizeId < 2; sizeId++) {
                    i = 0;
                    uiWqMSize = DAVS2_MIN(1 << (sizeId + 2), 8);

                    for (y = 0; y < uiWqMSize; y++) {
                        for (x = 0; x < uiWqMSize; x++) {
                            p->pic_user_wq_matrix[sizeId][i++] = (int16_t)ue_v(bs, "weight_quant_coeff");
                        }
                    }
                }
            }

            h->seq_info.enable_weighted_quant = 1;
        }
    }

    alf_read_param(h, bs);

    h->i_qp = h->i_picture_qp;
    if (!is_valid_qp(h, h->i_qp)) {
        davs2_log(h, DAVS2_LOG_ERROR, "Invalid I Picture QP: %d\n", h->i_qp);
    }

    /* align position in bitstream buffer */
    bs_align(bs);

    return 0;
}