diff options
-rw-r--r-- | src/libvdpau/dpb.c | 158 | ||||
-rw-r--r-- | src/libvdpau/dpb.h | 16 | ||||
-rw-r--r-- | src/libvdpau/h264_parser.c | 85 | ||||
-rw-r--r-- | src/libvdpau/h264_parser.h | 2 | ||||
-rw-r--r-- | src/libvdpau/nal.h | 59 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 36 |
6 files changed, 258 insertions, 98 deletions
diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index d27611e64..0f5970ced 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -18,6 +18,8 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); pic->nal = init_nal_unit(); copy_nal_unit(pic->nal, src_nal); + pic->used_for_reference = 0; + pic->delayed_output = 0; pic->top_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; pic->bottom_is_reference = pic->nal->slc->field_pic_flag @@ -35,6 +37,27 @@ void free_decoded_picture(struct decoded_picture *pic) free_nal_unit(pic->nal); } +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *outpic = pic; + + printf("dpb used: %d\n", dpb->used); + + if(dpb->used < MAX_DPB_SIZE) + return NULL; + + if (pic != NULL) + do { + if (pic->img->pts < outpic->img->pts) + outpic = pic; + } while ((pic = pic->next) != NULL); + + if(outpic) + printf("OUTPUT: %lld\n", outpic->img->pts); + return outpic; +} + struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; @@ -76,75 +99,114 @@ struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, return NULL; } -int dpb_remove_picture(struct dpb *dpb, uint32_t picnum) +int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; - struct decoded_picture *last_pic = NULL; - +printf("UNUSED 1\n"); if (pic != NULL) do { if (pic->nal->curr_pic_num == picnum) { - // FIXME: free the picture.... + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + return 0; + } + } while ((pic = pic->next) != NULL); - if (last_pic != NULL) - last_pic->next = pic->next; - else - dpb->pictures = pic->next; + return -1; +} - free_decoded_picture(pic); - dpb->used--; +int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum) +{ + struct decoded_picture *pic = dpb->pictures; + printf("UNUSED 2\n"); + if (pic != NULL) + do { + if (pic->nal->long_term_pic_num == longterm_picnum) { + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); return 0; } - - last_pic = pic; } while ((pic = pic->next) != NULL); return -1; } -int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum) +int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx) { struct decoded_picture *pic = dpb->pictures; - struct decoded_picture *last_pic = NULL; + printf("UNUSED 3\n"); + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx == longterm_idx) { + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + return 0; + } + } while ((pic = pic->next) != NULL); + + return -1; +} +int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx) +{ + struct decoded_picture *pic = dpb->pictures; + printf("UNUSED 4\n"); if (pic != NULL) do { - if (pic->nal->long_term_pic_num == longterm_picnum) { - // FIXME: free the picture.... + if (pic->nal->long_term_frame_idx >= longterm_idx) { + pic->used_for_reference = 0; + if(!pic->delayed_output) { + struct decoded_picture *next_pic = pic->next; + dpb_remove_picture(dpb, pic); + pic = next_pic; + continue; + } + } + } while ((pic = pic->next) != NULL); - if (last_pic != NULL) - last_pic->next = pic->next; - else - dpb->pictures = pic->next; + return -1; +} - free_decoded_picture(pic); - dpb->used--; + +int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic) +{ + struct decoded_picture *pic = dpb->pictures; +printf("DPB set output pic\n"); + if (pic != NULL) + do { + if (pic == outpic) { + printf("DPB pic num %d output, refuse: %d\n", pic->nal->curr_pic_num, pic->used_for_reference); + pic->delayed_output = 0; + if(!pic->used_for_reference) + dpb_remove_picture(dpb, pic); return 0; } - - last_pic = pic; } while ((pic = pic->next) != NULL); return -1; } -int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) +int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *last_pic = NULL; - +printf("DPB remove pic\n"); if (pic != NULL) do { - if (pic->nal->long_term_frame_idx == longterm_idx) { + if (pic == rempic) { + printf("DPB found rempic\n"); // FIXME: free the picture.... if (last_pic != NULL) last_pic->next = pic->next; else dpb->pictures = pic->next; - free_decoded_picture(pic); dpb->used--; + printf("DPB Used: %d\n", dpb->used); return 0; } @@ -154,32 +216,21 @@ int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) return -1; } -int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max) +int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *last_pic = NULL; if (pic != NULL) do { - if (pic->nal->long_term_frame_idx > longterm_max) { - // FIXME: free the picture.... - if (last_pic != NULL) - last_pic->next = pic->next; - else - dpb->pictures = pic->next; - - - free_decoded_picture(pic); - dpb->used--; - /* don't increase last_pic to current pic - * in case we delete current pic */ - continue; + if (pic->nal->curr_pic_num == picnum) { + dpb_remove_picture(dpb, pic); } last_pic = pic; } while ((pic = pic->next) != NULL); - return 0; + return -1; } int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) @@ -190,17 +241,20 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r pic->next = dpb->pictures; dpb->pictures = pic; dpb->used++; - +printf("ADD: Used: %d\n", dpb->used); if(dpb->used > num_ref_frames) { do { - i++; - if(i>num_ref_frames) { - last_pic->next = pic->next; - free_decoded_picture(pic); - pic = last_pic; - dpb->used--; + if(pic->used_for_reference) { + i++; + if(i>num_ref_frames) { + printf("DPB REMOVE REF FRAME\n"); + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + pic = last_pic; + } + last_pic = pic; } - last_pic = pic; } while ((pic = pic->next) != NULL); } @@ -234,7 +288,7 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) if (pic != NULL) do { - if (pic->nal->nal_ref_idc != 0) { + if (pic->used_for_reference) { reflist[i].surface = pic->surface; reflist[i].is_long_term = pic->nal->used_for_long_term_ref; if(reflist[i].is_long_term) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 06f894e44..c747a38af 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -8,6 +8,8 @@ #ifndef DPB_H_ #define DPB_H_ +#define MAX_DPB_SIZE 10 + #include "nal.h" #include "video_out.h" @@ -21,6 +23,8 @@ struct decoded_picture { uint8_t top_is_reference; uint8_t bottom_is_reference; + uint8_t delayed_output; + struct decoded_picture *next; }; @@ -34,10 +38,20 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, VdpVideoSurface surface, vo_frame_t *img); void free_decoded_picture(struct decoded_picture *pic); +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb); + struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum); struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); -int dpb_remove_picture(struct dpb *dpb, uint32_t picnum); + +int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum); +int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum); +int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx); + +int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic); + +int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic); +int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum); int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max); diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 6d376ae44..e5206a943 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -39,12 +39,13 @@ 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_parser *parser); -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser); 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, struct seq_parameter_set_rbsp *sps); +void parse_sei(struct buf_reader *buf, struct nal_parser *parser); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); @@ -165,7 +166,6 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; nal->nal_unit_type = buf->buf[0] & 0x1f; - //printf("Unit: %d\n", nal->nal_unit_type); buf->cur_pos = buf->buf + 1; //printf("NAL: %d\n", nal->nal_unit_type); @@ -183,7 +183,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); - parse_sps(&ibuf, nal->sps); + parse_sps(&ibuf, parser); free(ibuf.buf); ret = NAL_SPS; break; @@ -210,6 +210,10 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) ret = nal->nal_unit_type; } break; + case NAL_SEI: + parse_sei(buf, parser); + ret = nal->nal_unit_type; + break; default: ret = nal->nal_unit_type; break; @@ -230,7 +234,7 @@ void calculate_pic_order(struct nal_parser *parser) if (sps->pic_order_cnt_type == 0) { if (nal->nal_unit_type == NAL_SLICE_IDR) { - printf("IDR SLICE\n"); + //printf("IDR SLICE\n"); parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; } @@ -319,8 +323,9 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, } } -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) { + struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; sps->profile_idc = buf->buf[0]; sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; sps->level_idc = buf->buf[2]; @@ -339,7 +344,6 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); if (sps->seq_scaling_matrix_present_flag) { - printf("SCALING LIST PRESENT\n"); int i; for (i = 0; i < 8; i++) { sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); @@ -403,11 +407,46 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->vui_parameters_present_flag = read_bits(buf, 1); if (sps->vui_parameters_present_flag) { parse_vui_parameters(buf, sps); - } + if(sps->vui_parameters.nal_hrd_parameters_present_flag || + sps->vui_parameters.vc1_hrd_parameters_present_flag) { + parser->cpb_dpb_delays_present_flag = 1; + } else + parser->cpb_dpb_delays_present_flag = 0; + } else + parser->cpb_dpb_delays_present_flag = 0; return 0; } +void parse_sei(struct buf_reader *buf, struct nal_parser *parser) +{ + struct sei_message *sei = &(parser->current_nal->sei); + uint8_t tmp; + + sei->payload_type = 0; + while((tmp = read_bits(buf, 8)) == 0xff) { + sei->payload_type += 255; + } + sei->last_payload_type_byte = tmp; + sei->payload_type += sei->last_payload_type_byte; + + sei->payload_size = 0; + while((tmp = read_bits(buf, 8)) == 0xff) { + sei->payload_size += 255; + } + sei->last_payload_size_byte = tmp; + sei->payload_size += sei->last_payload_size_byte; + + /* pic_timing */ + if(sei->payload_type == 1) { + if(parser->cpb_dpb_delays_present_flag) { + sei->pic_timing.cpb_removal_delay = read_bits(buf, 5); + sei->pic_timing.dpb_output_delay = read_bits(buf, 5); + printf("output delay: %d\n", sei->pic_timing.dpb_output_delay); + } + } +} + void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) { @@ -566,15 +605,15 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, } if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { - printf("MEMCPY SCALING LIST\n"); + //printf("MEMCPY SCALING LIST\n"); memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pps->scaling_lists_4x4)); memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pps->scaling_lists_8x8)); } - else if (sps == NULL) { + /*else if (sps == NULL) { printf("sPS MISSING\n"); - } + }*/ return 0; } @@ -789,43 +828,46 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, return; if (memory_management_control_operation == 1) { + printf("MMC 1\n"); // short-term -> unused for reference uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); struct decoded_picture* pic = dpb_get_picture(dpb, pic_num_x); if (pic != NULL) { if (pic->nal->slc->field_pic_flag == 0) - dpb_remove_picture(dpb, pic_num_x); + dpb_set_unused_ref_picture(dpb, pic_num_x); else { - dpb_remove_picture(dpb, pic_num_x); + dpb_set_unused_ref_picture(dpb, pic_num_x); printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 } } } else if (memory_management_control_operation == 2) { + printf("MMC 2\n"); // long-term -> unused for reference struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, slc->dec_ref_pic_marking.long_term_pic_num); if (pic != NULL) { if (pic->nal->slc->field_pic_flag == 0) - dpb_remove_picture_by_ltpn(dpb, + dpb_set_unused_ref_picture(dpb, slc->dec_ref_pic_marking.long_term_pic_num); else { - dpb_remove_picture_by_ltpn(dpb, + dpb_set_unused_ref_picture(dpb, slc->dec_ref_pic_marking.long_term_pic_num); printf("FIXME: We might need do delete more from the DPB...\n"); } } } else if (memory_management_control_operation == 3) { + printf("MMC 3\n"); // short-term -> long-term, set long-term frame index uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, slc->dec_ref_pic_marking.long_term_pic_num); if (pic != NULL) - dpb_remove_picture_by_ltidx(dpb, + dpb_set_unused_ref_picture_bylidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); pic = dpb_get_picture(dpb, pic_num_x); @@ -844,16 +886,18 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } else if (memory_management_control_operation == 4) { + printf("MMC 4\n"); // set max-long-term frame index, // mark all long-term pictures with long-term frame idx // greater max-long-term farme idx as unused for ref if (slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 == 0) - dpb_remove_ltidx_gt(dpb, 0); + dpb_set_unused_ref_picture_lidx_gt(dpb, 0); else - dpb_remove_ltidx_gt(dpb, + dpb_set_unused_ref_picture_lidx_gt(dpb, slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 - 1); } else if (memory_management_control_operation == 5) { + printf("MMC 5\n"); // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); @@ -862,12 +906,13 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb = 0; } else if (memory_management_control_operation == 6) { + printf("MMC 6\n"); // mark current picture as used for long-term ref, // assing long-term frame idx to it struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); if (pic != NULL) - dpb_remove_picture_by_ltidx(dpb, + dpb_set_unused_ref_picture_bylidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); nal->long_term_frame_idx = slc->dec_ref_pic_marking.long_term_frame_idx; @@ -961,6 +1006,8 @@ struct nal_parser* init_parser() */ parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16; + parser->cpb_dpb_delays_present_flag = 0; + return parser; } @@ -1044,7 +1091,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, return parsed_len; } - printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); + //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); /* this is a SLICE, keep it in the buffer */ xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); parser->buf_len += parser->prebuf_len; diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index 99691e950..966bf0880 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -38,6 +38,8 @@ struct nal_parser { struct nal_unit *current_nal; struct nal_unit *last_nal; + uint8_t cpb_dpb_delays_present_flag; + uint32_t pic_order_cnt_lsb; uint32_t pic_order_cnt_msb; uint32_t prev_pic_order_cnt_lsb; diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index c07c1d9a3..20c1c32dc 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -63,24 +63,6 @@ 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 - - uint32_t curr_pic_num; - uint8_t used_for_long_term_ref; - uint32_t long_term_pic_num; - uint32_t long_term_frame_idx; - - uint32_t top_field_order_cnt; - uint32_t bottom_field_order_cnt; - - struct seq_parameter_set_rbsp *sps; - struct pic_parameter_set_rbsp *pps; - struct slice_header *slc; -}; - struct hrd_parameters { uint32_t cpb_cnt_minus1; @@ -253,6 +235,27 @@ struct pic_parameter_set_rbsp int32_t second_chroma_qp_index_offset; }; +/* sei contains several additional info, we do + * only care for pic_timing, to handle display + * reordering + */ +struct sei_message +{ + uint32_t payload_type; + uint8_t last_payload_type_byte; + uint32_t payload_size; + uint8_t last_payload_size_byte; + + union + { + /* cpb_dpb_delays_present_flag == 1 */ + uint8_t cpb_removal_delay; + uint8_t dpb_output_delay; + + /* ignore the rest */ + } pic_timing; +}; + struct slice_header { uint32_t first_mb_in_slice; @@ -341,10 +344,28 @@ struct slice_header } dec_ref_pic_marking; }; +struct nal_unit +{ + uint8_t nal_ref_idc; // 0x03 + uint8_t nal_unit_type; // 0x1f + + uint32_t curr_pic_num; + uint8_t used_for_long_term_ref; + uint32_t long_term_pic_num; + uint32_t long_term_frame_idx; + + uint32_t top_field_order_cnt; + uint32_t bottom_field_order_cnt; + + struct sei_message sei; + + struct seq_parameter_set_rbsp *sps; + struct pic_parameter_set_rbsp *pps; + struct slice_header *slc; +}; struct nal_unit* init_nal_unit(); void free_nal_unit(struct nal_unit *nal); void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src); - #endif /* NAL_H_ */ diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 9b66e57c5..fbbdbe205 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -353,7 +353,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, // FIXME: do we really hit all cases here? if(((uint8_t*)vdp_buffer.bitstream) != NULL) { - free(vdp_buffer.bitstream); + free((uint8_t*)vdp_buffer.bitstream); } if(status != VDP_STATUS_OK) @@ -364,13 +364,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->pts = buf->pts; img->bad_frame = 0; + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { - struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - this->last_ref_pic = pic; - dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); + decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + this->last_ref_pic = decoded_pic; + printf("Add ref pic: %d\n", decoded_pic->nal->slc->frame_num); + decoded_pic->used_for_reference = 1; + dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); } else if(slc->field_pic_flag && this->wait_for_bottom_field) { if(this->last_ref_pic) { + decoded_pic = this->last_ref_pic; this->last_ref_pic->bottom_is_reference = 1; } } @@ -378,20 +382,38 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!slc->field_pic_flag || (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + /*if(!decoded_pic) { + decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + decoded_pic->delayed_output = 1; + dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + } else + decoded_pic->delayed_output = 1; + + img = NULL; + + / * now retrieve the next output frame * / + decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); + if(decoded_pic) { + printf("DRAW AN IMAGE\n"); + decoded_pic->img->draw(decoded_pic->img, this->stream); + + dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); + } else + printf("NO IMAGE THIS TIME\n"); + + this->wait_for_bottom_field = 0;*/ + img->draw(img, this->stream); this->wait_for_bottom_field = 0; if(!pic.is_reference) img->free(img); - img = NULL; } else if(slc->field_pic_flag && !slc->bottom_field_flag) { // don't draw yet, second field is missing. this->wait_for_bottom_field = 1; } } - - //this->vdpau_accel->vdp_video_surface_destroy(surface); } } } |