diff options
-rw-r--r-- | src/libvdpau/h264_parser.c | 105 | ||||
-rw-r--r-- | src/libvdpau/h264_parser.h | 2 | ||||
-rw-r--r-- | src/libvdpau/nal.c | 6 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 62 |
4 files changed, 110 insertions, 65 deletions
diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 568901829..abd4c329d 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -70,7 +70,8 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, 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); + parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, + struct nal_parser *parser); void decode_ref_pic_marking(struct nal_unit *nal, uint32_t memory_management_control_operation, uint32_t marking_nr, @@ -722,6 +723,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) slc->first_mb_in_slice = 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)); + //print_slice_type(slc->slice_type); slc->pic_parameter_set_id = read_exp_golomb(buf); slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); @@ -778,7 +780,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) } /* --- ref_pic_list_reordering --- */ - parse_ref_pic_list_reordering(buf, nal); + parse_ref_pic_list_reordering(buf, nal, parser); /* --- pred_weight_table --- */ if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P @@ -796,7 +798,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) return 0; } -void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, struct nal_parser *parser) { struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; @@ -1127,6 +1129,7 @@ void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_le read_bits(&bufr, 6); parser->nal_size_length = read_bits(&bufr, 2) + 1; + parser->nal_size_length_buf = calloc(1, parser->nal_size_length); read_bits(&bufr, 3); uint8_t sps_count = read_bits(&bufr, 5); @@ -1175,7 +1178,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t *prebuf = parser->prebuf; if(parser->nal_size_length > 0) - start_seq_len = 4; + start_seq_len = 4-parser->have_nal_size_length_buf; if(parser->last_nal_res == 1 && parser->current_nal && parser->current_nal->slc) { @@ -1188,10 +1191,14 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser); } } + while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { next_nal += search_offset; + if(parser->nal_size_length > 0) + start_seq_len = 4-parser->have_nal_size_length_buf; - if(parser->incomplete_nal || completed_nal || next_nal == 0) { + if(parser->incomplete_nal || completed_nal || next_nal == 0 || + parser->nal_size_length) { if (parser->prebuf_len + next_nal > MAX_FRAME_SIZE) { printf("buf underrun!!\n"); @@ -1209,25 +1216,29 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = parse_nal(prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { - int offset = 0; - if(parser->nal_size_length > 0) - offset = start_seq_len; - //printf("Frame complete: %d bytes\n", parser->buf_len-offset); - *ret_len = parser->buf_len-offset; + //printf("Frame complete: %d bytes\n", parser->buf_len); + *ret_len = parser->buf_len; *ret_buf = malloc(*ret_len); - xine_fast_memcpy(*ret_buf, parser->buf+offset, *ret_len); + xine_fast_memcpy(*ret_buf, parser->buf, *ret_len); *ret_slice_cnt = parser->slice_cnt; - //memset(parser->buf, 0x00, parser->buf_len); - parser->buf_len = 0; - parser->last_nal_res = 1; parser->slice_cnt = 1; + parser->buf_len = 0; /* this is a SLICE, keep it in the buffer */ //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); - xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); - parser->buf_len += parser->prebuf_len; + if(parser->nal_size_length > 0) { + uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; + } + + int offset = 0; + if(parser->nal_size_length > 0) + offset = start_seq_len; + xine_fast_memcpy(parser->buf+parser->buf_len, prebuf+offset, parser->prebuf_len-offset); + parser->buf_len += parser->prebuf_len-offset; parser->prebuf_len = 0; parser->incomplete_nal = 0; @@ -1242,7 +1253,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, if (parser->last_nal_res != 2) { if (parser->buf_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); + printf("buf underrun 1!!\n"); parser->buf_len = 0; *ret_len = 0; *ret_buf = NULL; @@ -1251,8 +1262,18 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_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; + if(parser->nal_size_length > 0) { + uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf + parser->buf_len, start_seq, 3); + parser->buf_len += 3; + } + + int offset = 0; + if(parser->nal_size_length > 0) + offset = start_seq_len; + + xine_fast_memcpy(parser->buf + parser->buf_len, prebuf+offset, parser->prebuf_len-offset); + parser->buf_len += (parser->prebuf_len-offset); } parser->prebuf_len = 0; @@ -1276,7 +1297,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, */ if(parsed_len < inbuf_len) { if (inbuf_len-parsed_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); + printf("buf underrun 0!!\n"); parser->prebuf_len = 0; *ret_len = 0; *ret_buf = NULL; @@ -1438,20 +1459,46 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { if(parser->nal_size_length > 0) { - - if(buf_len <= 0) + if(buf_len <= 0 || + (buf_len < parser->nal_size_length && + (parser->next_nal_position == 0 || + parser->next_nal_position > buf_len))) { + /* if we have less than nal_size_length bytes + * left in the buffer we need to store them, so + * that the next length calculation will be correct + */ + if(!parser->next_nal_position) { + memcpy(parser->nal_size_length_buf, buf, buf_len); + parser->have_nal_size_length_buf = buf_len; + } return -1; + } - int next_nal = parser->next_nal_position; + uint32_t next_nal = parser->next_nal_position; if(!next_nal) { - struct buf_reader bufr; + if(parser->have_nal_size_length_buf > 0) { + memcpy(parser->nal_size_length_buf+parser->have_nal_size_length_buf, buf, parser->nal_size_length-parser->have_nal_size_length_buf); + + struct buf_reader bufr; - bufr.buf = buf; - bufr.cur_pos = buf; - bufr.cur_offset = 8; - bufr.len = buf_len; + bufr.buf = parser->nal_size_length_buf; + bufr.cur_pos = parser->nal_size_length_buf; + bufr.cur_offset = 8; + bufr.len = parser->nal_size_length; - next_nal = read_bits(&bufr, parser->nal_size_length*8)+4; + next_nal = read_bits(&bufr, parser->nal_size_length*8)+4-parser->have_nal_size_length_buf; + + parser->have_nal_size_length_buf = 0; + } else { + struct buf_reader bufr; + + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; + + next_nal = read_bits(&bufr, parser->nal_size_length*8)+4; + } } if(next_nal > buf_len) { diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index bb9e12f79..c99c3cd80 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -57,6 +57,8 @@ struct nal_parser { uint8_t nal_size_length; uint32_t next_nal_size; + uint8_t *nal_size_length_buf; + uint8_t have_nal_size_length_buf; struct nal_unit *nal0; struct nal_unit *nal1; diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index 541699dbd..7e0cbdf7f 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -58,13 +58,13 @@ void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) xine_fast_memcpy(dest, src, size); if(!dest->sps) - dest->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + dest->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); if(!dest->pps) - dest->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + dest->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); if(!dest->slc) - dest->slc = malloc(sizeof(struct slice_header)); + dest->slc = calloc(1, sizeof(struct slice_header)); if(src->sps) xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 971876abd..1124cfa31 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -51,10 +51,6 @@ typedef struct vdpau_h264_decoder_s { /* these are traditional variables in a video decoder object */ uint64_t video_step; /* frame duration in pts units */ - unsigned char *buf; /* the accumulated buffer data */ - int bufsize; /* the maximum size of buf */ - int size; /* the current size of buf */ - int width; /* the width of a video frame */ int height; /* the height of a video frame */ double ratio; /* the width to height ratio */ @@ -371,7 +367,7 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) return 1; } -static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count, int use_vdp_buffers) +static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img = this->last_img; @@ -407,14 +403,14 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /*int i; printf("Decode data: \n"); - for(i = 0; i < ((vdp_buffer[use_vdp_buffers-1].bitstream_bytes < 20) ? vdp_buffer[use_vdp_buffers-1].bitstream_bytes : 20); i++) { - printf("%02x ", ((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream)[i]); + for(i = 0; i < ((vdp_buffer->bitstream_bytes < 20) ? vdp_buffer->bitstream_bytes : 20); i++) { + printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); } printf("\n...\n"); - for(i = vdp_buffer[use_vdp_buffers-1].bitstream_bytes - 20; i < vdp_buffer[use_vdp_buffers-1].bitstream_bytes; i++) { - printf("%02x ", ((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream)[i]); + for(i = vdp_buffer->bitstream_bytes - 20; i < vdp_buffer->bitstream_bytes; i++) { + printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); }*/ @@ -435,6 +431,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { printf("VDPAU was preempted. Reinitialise the decoder.\n"); + this->decoder = VDP_INVALID_HANDLE; vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; this->last_img = NULL; @@ -445,12 +442,12 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - surface, (VdpPictureInfo*)&pic, use_vdp_buffers, vdp_buffer); + surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); /* only free the actual data, as the start seq is only * locally allocated anyway. */ - if(((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream) != NULL) { - free((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream); + if(((uint8_t*)vdp_buffer->bitstream) != NULL) { + free((uint8_t*)vdp_buffer->bitstream); } this->curr_pts = this->next_pts; @@ -542,16 +539,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - VdpBitstreamBuffer vdp_buffer[2]; - uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - vdp_buffer[0].struct_version = vdp_buffer[1].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - int use_vdp_buffers = 1; - - if(this->nal_parser->nal_size_length > 0) { - vdp_buffer[0].bitstream_bytes = 3; - vdp_buffer[0].bitstream = start_seq; - use_vdp_buffers = 2; - } + VdpBitstreamBuffer vdp_buffer; + vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) @@ -570,7 +559,21 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, uint8_t *codec_private = buf->content + sizeof(xine_bmiheader); uint32_t codec_private_len = bih->biSize - sizeof(xine_bmiheader); - parse_codec_private(this->nal_parser, codec_private, codec_private_len); + if(codec_private_len > 0) { + parse_codec_private(this->nal_parser, codec_private, codec_private_len); + vdpau_decoder_init(this_gen); + } + } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) { + if(buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG) { + uint8_t *codec_private = buf->decoder_info_ptr[2]; + uint32_t codec_private_len = buf->decoder_info[2]; + + if(codec_private_len > 0) { + parse_codec_private(this->nal_parser, codec_private, codec_private_len); + vdpau_decoder_init(this_gen); + } + } + } else { /* parse the first nal packages to retrieve profile type */ int len = 0; @@ -581,7 +584,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, while(len < buf->size) { len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (void*)&vdp_buffer[use_vdp_buffers-1].bitstream, &vdp_buffer[use_vdp_buffers-1].bitstream_bytes, &slice_count); + (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); if(this->decoder == VDP_INVALID_HANDLE && this->nal_parser->current_nal->sps != NULL && @@ -592,11 +595,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } if(this->decoder != VDP_INVALID_HANDLE && - vdp_buffer[use_vdp_buffers-1].bitstream_bytes > 0 && + 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) { - vdpau_decoder_render(this_gen, vdp_buffer, slice_count, use_vdp_buffers); + vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); } } @@ -617,8 +620,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { printf("vdpau_h264_reset\n"); - this->size = 0; - dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder != VDP_INVALID_HANDLE) { @@ -634,7 +635,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->nal_parser = init_parser(); } - this->buf = NULL; this->wait_for_bottom_field = 0; this->video_step = 0; this->curr_pts = 0; @@ -669,10 +669,6 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->dangling_img = NULL; } - if (this->buf) { - free (this->buf); - this->buf = NULL; - } dpb_free_all( &(this->nal_parser->dpb) ); |