diff options
-rw-r--r-- | src/libvdpau/nal_parser.c | 124 | ||||
-rw-r--r-- | src/libvdpau/nal_parser.h | 122 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 12 |
3 files changed, 240 insertions, 18 deletions
diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index ebe9d562f..9835cb1a4 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -34,10 +34,14 @@ struct buf_reader { static inline uint32_t read_bits(struct buf_reader *buf, int len); uint32_t read_exp_golomb(struct buf_reader *buf); int32_t read_exp_golomb_s(struct buf_reader *buf); + +void calculate_pic_order(struct nal_parser *parser); void skip_scaling_list(struct buf_reader *buf, int size); void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); 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); +void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); 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); @@ -223,6 +227,27 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) return ret; } +void calculate_pic_order(struct nal_parser *parser) +{ + struct nal_unit *nal = parser->current_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(sps->pic_order_cnt_type == 0) { + if(nal->nal_unit_type == NAL_SLICE_IDR) { + parser->prev_pic_order_cnt_lsb = 0; + parser->prev_pic_order_cnt_msb = 0; + } else { + + } + } + +} + void skip_scaling_list(struct buf_reader *buf, int size) { int i; @@ -351,12 +376,99 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->frame_crop_bottom_offset = read_exp_golomb(buf); } sps->vui_parameters_present_flag = read_bits(buf, 1); - /*if(sps->vui_parameters_present_flag) - printf("ERROR: vui_parameters is not implemented\n");*/ + if(sps->vui_parameters_present_flag) { + parse_vui_parameters(buf, sps); + } return 0; } +void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +{ + sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.aspect_ration_info_present_flag == 1) { + sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); + if(sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { + sps->vui_parameters.sar_width = read_bits(buf, 16); + sps->vui_parameters.sar_height = read_bits(buf, 16); + } + } + + sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.overscan_info_present_flag) { + sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1); + } + + sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.video_signal_type_present_flag) { + sps->vui_parameters.video_format = read_bits(buf, 3); + sps->vui_parameters.video_full_range_flag = read_bits(buf, 1); + sps->vui_parameters.colour_description_present = read_bits(buf, 1); + if(sps->vui_parameters.colour_description_present) { + sps->vui_parameters.colour_primaries = read_bits(buf, 8); + sps->vui_parameters.transfer_characteristics = read_bits(buf, 8); + sps->vui_parameters.matrix_coefficients = read_bits(buf, 8); + } + } + + sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.chroma_loc_info_present_flag) { + sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf); + sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb(buf); + } + + sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.timing_info_present_flag) { + sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); + sps->vui_parameters.time_scale = read_bits(buf, 32); + sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); + } + + sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.nal_hrd_parameters_present_flag) + parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters); + + sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.vc1_hrd_parameters_present_flag) + parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters); + + if(sps->vui_parameters.nal_hrd_parameters_present_flag || + sps->vui_parameters.vc1_hrd_parameters_present_flag) + sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1); + + sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1); + sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1); + + if(sps->vui_parameters.bitstream_restriction_flag) { + sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1); + sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf); + sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf); + sps->vui_parameters.log2_max_mv_length_horizontal = read_exp_golomb(buf); + sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); + sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); + sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); + } +} + +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) +{ + hrd->cpb_cnt_minus1 = read_exp_golomb(buf); + hrd->bit_rate_scale = read_bits(buf, 4); + hrd->cpb_size_scale = read_bits(buf, 4); + + int i; + for(i = 0; i <= hrd->cpb_cnt_minus1; i++) { + hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf); + hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf); + hrd->cbr_flag[i] = read_bits(buf, 1); + } + + hrd->initial_cpb_removal_delay_length_minus1 = read_bits(buf, 5); + hrd->cpb_removal_delay_length_minus1 = read_bits(buf, 5); + hrd->dpb_output_delay_length_minus1 = read_bits(buf, 5); + hrd->time_offset_length = read_bits(buf, 5); +} + uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) { pps->pic_parameter_set_id = read_exp_golomb(buf); @@ -740,6 +852,8 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) int res = parse_nal_header(&bufr, nal); + calculate_pic_order(parser); + if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! int ret = 0; @@ -822,14 +936,14 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return ret; } else if(res == NAL_PPS || res == NAL_SPS) { - return 1; + return 0; } else if (res == NAL_AU_DELIMITER || res == NAL_SEI || (res >= 13 && res <= 18)) { //printf("New Frame\n"); - return 1; + return 0; } - return 0; + return 1; } int seek_for_nal(uint8_t *buf, int buf_len) diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index 609f700a1..792f2e0f2 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -33,6 +33,27 @@ enum slice_types { SLICE_SI }; +enum aspect_ratio { + ASPECT_UNSPECIFIED = 0, + ASPECT_1_1, + ASPECT_12_11, + ASPECT_10_11, + ASPECT_16_11, + ASPECT_40_33, + ASPECT_24_11, + ASPECT_20_11, + ASPECT_32_11, + ASPECT_80_33, + ASPECT_18_11, + ASPECT_15_11, + ASPECT_64_33, + ASPECT_160_99, + ASPECT_4_3, + ASPECT_3_2, + ASPECT_2_1, + ASPECT_RESERVED +}; + static inline uint32_t slice_type(uint32_t slice_type) { return (slice_type < 10 ? slice_type % 5 : slice_type); } struct nal_unit { @@ -44,6 +65,21 @@ struct nal_unit { struct slice_header *slc; }; +struct hrd_parameters { + uint32_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + + uint32_t bit_rate_value_minus1[32]; + uint32_t cpb_size_value_minus1[32]; + uint8_t cbr_flag[32]; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t time_offset_length; +}; + struct seq_parameter_set_rbsp { uint8_t profile_idc; // 0xff uint8_t constraint_setN_flag; // 0x0f @@ -89,7 +125,61 @@ struct seq_parameter_set_rbsp { uint32_t frame_crop_top_offset; uint32_t frame_crop_bottom_offset; uint8_t vui_parameters_present_flag; - // TODO: add vui_parameters, rtbsp_trailing_bits + + /* vui_parameters */ + union { + uint8_t aspect_ration_info_present_flag; + + /* aspect_ration_info_present_flag == 1 */ + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + /* overscan_info_present_flag == 1 */ + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + /* video_signal_type_present_flag == 1 */ + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present; + /* colour_description_present == 1 */ + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + /* chroma_loc_info_present_flag == 1 */ + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t timing_info_present_flag; + /* timing_info_present_flag == 1 */ + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t fixed_frame_rate_flag; + + uint8_t nal_hrd_parameters_present_flag; + struct hrd_parameters nal_hrd_parameters; + + uint8_t vc1_hrd_parameters_present_flag; + struct hrd_parameters vc1_hrd_parameters; + + uint8_t low_delay_hrd_flag; + + uint8_t pic_struct_present_flag; + uint8_t bitstream_restriction_flag; + + /* bitstream_restriction_flag == 1 */ + uint8_t motion_vectors_over_pic_boundaries; + uint32_t max_bytes_per_pic_denom; + uint32_t max_bits_per_mb_denom; + uint32_t log2_max_mv_length_horizontal; + uint32_t log2_max_mv_length_vertical; + uint32_t num_reorder_frames; + uint32_t max_dec_frame_buffering; + } vui_parameters; }; @@ -196,17 +286,17 @@ struct slice_header { /* chroma_format_idc != 0 */ uint32_t chroma_log2_weight_denom; - int32_t luma_weight_l0[31]; - int32_t luma_offset_l0[31]; + int32_t luma_weight_l0[32]; + int32_t luma_offset_l0[32]; - int32_t chroma_weight_l0[31][2]; - int32_t chroma_offset_l0[31][2]; + int32_t chroma_weight_l0[32][2]; + int32_t chroma_offset_l0[32][2]; - int32_t luma_weight_l1[31]; - int32_t luma_offset_l1[31]; + int32_t luma_weight_l1[32]; + int32_t luma_offset_l1[32]; - int32_t chroma_weight_l1[31][2]; - int32_t chroma_offset_l1[31][2]; + int32_t chroma_weight_l1[32][2]; + int32_t chroma_offset_l1[32][2]; } pred_weight_table; /* def_rec_pic_marking */ @@ -236,15 +326,29 @@ struct nal_parser { int found_sps; int found_pps; int last_nal_res; + int field; /* 0=top, 1=bottom, -1=both */ int slice; int slice_cnt; int have_top; int have_frame; + struct nal_unit *nal0; struct nal_unit *nal1; struct nal_unit *current_nal; struct nal_unit *last_nal; + + /* pic_order_cnt */ + int32_t top_field_order_cnt; + int32_t bottom_field_oder_cnt; + int32_t prev_pic_order_cnt_msb; + int32_t prev_pic_order_cnt_lsb; +}; + +/* Decoded Picture Buffer */ +struct dpb { + uint32_t max_frame_number; + }; int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 841a94eb1..10577bc59 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -178,7 +178,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } if(this->decoder_initialized) { - if(this->nal_parser->current_nal->slc != NULL && + if(vdp_buffer.bitstream_bytes > 0 && + this->nal_parser->current_nal->slc != NULL && this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { @@ -197,7 +198,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.slice_count = slice_count; pic.field_order_cnt[0] = 0; // FIXME - pic.is_reference = 1; // FIXME + pic.is_reference = + (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; pic.frame_num = slc->frame_num; pic.field_pic_flag = slc->field_pic_flag; pic.bottom_field_flag = slc->bottom_field_flag; @@ -229,6 +231,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->pts = buf->pts; img->bad_frame = 0; + printf("Decode pts: %lld, %d\n", img->pts, vdp_buffer.bitstream_bytes); /* create surface if needed */ if(this->vdpau_accel->surface == VDP_INVALID_HANDLE) { VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, @@ -240,17 +243,18 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - this->vdpau_accel->surface, &pic, 1, (VdpPictureInfo*)&vdp_buffer); + this->vdpau_accel->surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); + else + printf("DECODING SUCCESS\n"); img->draw(img, this->stream); img->free(img); } } } - } } |