diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libvdpau/nal_parser.c | 189 | ||||
-rw-r--r-- | src/libvdpau/nal_parser.h | 82 |
2 files changed, 256 insertions, 15 deletions
diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 7422bd118..ebe9d562f 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -40,7 +40,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); - +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); +void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal); static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) { @@ -433,7 +435,8 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) return -1; slc->first_mb_in_slice = read_exp_golomb(buf); - slc->slice_type = read_exp_golomb(buf); + /* we do some parsing on the slice type, because the list is doubled */ + slc->slice_type = slice_type(read_exp_golomb(buf)); slc->pic_parameter_set_id = read_exp_golomb(buf); slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); if(!sps->frame_mbs_only_flag) { @@ -459,11 +462,182 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) if(pps->pic_order_present_flag && !slc->field_pic_flag) slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); } - /* do not need more information for packetizing */ + + if(pps->redundant_pic_cnt_present_flag == 1) { + slc->redundant_pic_cnt = read_exp_golomb(buf); + } + + if(slc->slice_type == SLICE_B) + slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); + + if(slc->slice_type == SLICE_P || + slc->slice_type == SLICE_SP || + slc->slice_type == SLICE_B) { + slc->num_ref_idx_active_override_flag = read_bits(buf, 1); + + if(slc->num_ref_idx_active_override_flag == 1) { + slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + + if(slc->slice_type == SLICE_B) { + slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + } + } + } + + /* --- ref_pic_list_reordering --- */ + parse_ref_pic_list_reordering(buf, nal); + + /* --- pred_weight_table --- */ + if((pps->weighted_pred_flag && + (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP)) || + (pps->weighted_bipred_idc == 1 && slc->slice_type == SLICE_B)) { + parse_pred_weight_table(buf, nal); + } + + /* --- dec_ref_pic_marking --- */ + if(nal->nal_ref_idc != 0) + parse_dec_ref_pic_marking(buf, nal); return 0; } +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + if(slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits(buf, 1); + + if(slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { + do { + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc = read_exp_golomb(buf); + + if(slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 || + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 = read_exp_golomb(buf); + } else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); + } + } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); + } + } + + if(slc->slice_type == SLICE_B) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits(buf, 1); + + if(slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { + do { + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc = read_exp_golomb(buf); + + if(slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 || + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 = read_exp_golomb(buf); + } else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); + } + } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); + } + } +} + +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); + + if(sps->chroma_format_idc != 0) + nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); + + int i; + for(i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { + uint8_t luma_weight_l0_flag = read_bits(buf, 1); + + if(luma_weight_l0_flag == 1 ) { + nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); + } + + if(sps->chroma_format_idc != 0) { + uint8_t chroma_weight_l0_flag = read_bits(buf, 1); + + if(chroma_weight_l0_flag == 1 ) { + int j; + for(j = 0; j < 2 ; j++) { + nal->slc->pred_weight_table.chroma_weight_l0[i][j] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l0[i][j] = read_exp_golomb_s(buf); + } + } + } + } + + if(slc->slice_type == SLICE_B) { + for(i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { + uint8_t luma_weight_l1_flag = read_bits(buf, 1); + + if(luma_weight_l1_flag == 1 ) { + nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); + } + + if(sps->chroma_format_idc != 0) { + uint8_t chroma_weight_l1_flag = read_bits(buf, 1); + + if(chroma_weight_l1_flag == 1 ) { + int j; + for(j = 0; j < 2 ; j++) { + nal->slc->pred_weight_table.chroma_weight_l1[i][j] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l1[i][j] = read_exp_golomb_s(buf); + } + } + } + } + } +} + +void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + if(nal->nal_unit_type == NAL_SLICE_IDR) { + slc->dec_ref_pic_marking.no_output_of_prior_pics_flag = read_bits(buf, 1); + slc->dec_ref_pic_marking.long_term_reference_flag = read_bits(buf, 1); + } else { + slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits(buf, 1); + + if(slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { + do { + slc->dec_ref_pic_marking.memory_management_control_operation = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 1 || + slc->dec_ref_pic_marking.memory_management_control_operation == 3) + slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 2) + slc->dec_ref_pic_marking.long_term_pic_num = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 3 || + slc->dec_ref_pic_marking.memory_management_control_operation == 6) + slc->dec_ref_pic_marking.long_term_frame_idx = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 4) + slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 = read_exp_golomb(buf); + } while(slc->dec_ref_pic_marking.memory_management_control_operation != 0); + } + } +} /* ----------------- NAL parser ----------------- */ @@ -642,15 +816,6 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) if(parser->current_nal->pps == NULL) parser->current_nal->pps = parser->last_nal->pps; - /*if(ret) - parser->slice = 0;*/ - /*if(parser->slice && parser->have_top && parser->field != 0) { - parser->have_frame = 1; - parser->have_top = 0; - parser->slice = 0; - return ret; - }*/ - /* increase the slice_cnt until a new frame is detected */ if(!ret) parser->slice_cnt++; diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index fed12ff0d..609f700a1 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -22,6 +22,19 @@ enum nal_unit_types { NAL_SPS_EXT }; +/* slice types repeat from 5-9, we + * need a helper function for comparison + */ +enum slice_types { + SLICE_P = 0, + SLICE_B, + SLICE_I, + SLICE_SP, + SLICE_SI +}; + +static inline uint32_t slice_type(uint32_t slice_type) { return (slice_type < 10 ? slice_type % 5 : slice_type); } + struct nal_unit { uint8_t nal_ref_idc; // 0x03 uint8_t nal_unit_type; // 0x1f @@ -145,10 +158,73 @@ struct slice_header { /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ int32_t delta_pic_order_cnt[2]; - /* not needed for packetizing */ - /*int32_t redundant_pic_cnt; - uint8_t direct_spatial_mv_pred_flag;*/ + /* pps->redundant_pic_cnt_present_flag == 1 */ + int32_t redundant_pic_cnt; + + /* slice_type == B */ + uint8_t direct_spatial_mv_pred_flag; + + /* slice_type == P, SP, B */ + uint8_t num_ref_idx_active_override_flag; + /* num_ref_idx_active_override_flag == 1 */ + uint32_t num_ref_idx_l0_active_minus1; + /* slice type == B */ + uint32_t num_ref_idx_l1_active_minus1; + + /* ref_pic_list_reordering */ + union { + /* slice_type != I && slice_type != SI */ + uint8_t ref_pic_list_reordering_flag_l0; + + /* slice_type == B */ + uint8_t ref_pic_list_reordering_flag_l1; + + /* ref_pic_list_reordering_flag_l0 == 1 */ + uint32_t reordering_of_pic_nums_idc; + + /* reordering_of_pic_nums_idc == 0, 1 */ + uint32_t abs_diff_pic_num_minus1; + + /* reordering_of_pic_nums_idc == 2) */ + uint32_t long_term_pic_num; + } ref_pic_list_reordering; + + /* pred_weight_table */ + union { + uint32_t luma_log2_weight_denom; + + /* chroma_format_idc != 0 */ + uint32_t chroma_log2_weight_denom; + + int32_t luma_weight_l0[31]; + int32_t luma_offset_l0[31]; + + int32_t chroma_weight_l0[31][2]; + int32_t chroma_offset_l0[31][2]; + + int32_t luma_weight_l1[31]; + int32_t luma_offset_l1[31]; + + int32_t chroma_weight_l1[31][2]; + int32_t chroma_offset_l1[31][2]; + } pred_weight_table; + + /* def_rec_pic_marking */ + union { + + /* nal_unit_type == NAL_SLICE_IDR */ + uint8_t no_output_of_prior_pics_flag; + uint8_t long_term_reference_flag; + + /* else */ + uint8_t adaptive_ref_pic_marking_mode_flag; + uint32_t memory_management_control_operation; + uint32_t difference_of_pic_nums_minus1; + uint32_t long_term_pic_num; + uint32_t long_term_frame_idx; + uint32_t max_long_term_frame_idx_plus1; + } dec_ref_pic_marking; }; |