diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libvdpau/h264_parser.c | 252 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 9 |
2 files changed, 88 insertions, 173 deletions
diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index c5dfbb373..154c99c0a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -310,6 +310,9 @@ void calculate_pic_order(struct nal_parser *parser) else if(slc->bottom_field_flag) nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + /*if(slc->bottom_field_flag) + nal->top_field_order_cnt = parser->last_nal->top_field_order_cnt;*/ + } else if (sps->pic_order_cnt_type == 2) { uint32_t prev_frame_num = parser->last_nal->slc->frame_num; uint32_t prev_frame_num_offset = parser->frame_num_offset; @@ -1261,172 +1264,106 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { int32_t next_nal = 0; - int parsed_len = 0; - int search_offset = 0; + int32_t offset = 0; int start_seq_len = 3; - uint8_t completed_nal = 0; if(parser->nal_size_length > 0) - start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; - - /* seek for nal start sequences split across buffer boundaries */ - if(!parser->nal_size_length) { - if(parser->prebuf_len >= 2 && inbuf_len >= 1 && - parser->prebuf[parser->prebuf_len-2] == 0x00 && - parser->prebuf[parser->prebuf_len-1] == 0x00 && - inbuf[0] == 0x01) { - parsed_len = 1; - } else if (parser->prebuf_len >= 1 && inbuf_len >= 2 && - parser->prebuf[parser->prebuf_len-1] == 0x00 && - inbuf[0] == 0x00 && - inbuf[1] == 0x01) { - parsed_len = 2; - } + start_seq_len = offset = parser->nal_size_length; + + if (parser->prebuf_len + inbuf_len > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + parser->prebuf_len = 0; + return inbuf_len; + } - /* in case a start seq was splitted call ourself with just a start - * sequences and strip incomplete start seq parts from the buffer - * before. - */ + /* copy the whole inbuf to the prebuf, + * then search for a nal-start sequence in the prebuf, + * if it's in there, parse the nal and append to parser->buf + * or return a frame */ - if(parsed_len > 0) { - static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - parser->prebuf_len -= start_seq_len - parsed_len; + xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len); + parser->prebuf_len += inbuf_len; - /* if we are just at a frame boundary the sequence wouldn't - * be taken over but we would just be notified about a new - * completed frame. - * so in this case we have to send the start sequence another - * time to get it into the prebuf again. - */ - uint8_t *tmp_ret_buf; - uint32_t tmp_ret_len; - uint32_t tmp_slice_cnt; + while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-2*start_seq_len+(2*offset), parser)) > 0) { - if(parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt) == 0) - parse_frame(parser, start_seq, start_seq_len, &tmp_ret_buf, &tmp_ret_len, &tmp_slice_cnt); + if(!parser->nal_size_length && + (parser->prebuf[0] != 0x00 || parser->prebuf[1] != 0x00 || parser->prebuf[2] != 0x01)) { + printf("Broken NAL, skip it.\n"); + parser->last_nal_res = 2; + } else + parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser); - return parsed_len; - } - } + if (parser->last_nal_res == 1 && parser->buf_len > 0) { - 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 = parser->nal_size_length-parser->have_nal_size_length_buf; + //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, parser->buf_len); + *ret_slice_cnt = parser->slice_cnt; - if(parser->incomplete_nal || completed_nal || next_nal == 0 || - parser->nal_size_length) { + parser->slice_cnt = 1; + parser->buf_len = 0; - if (parser->prebuf_len + next_nal > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } + /* this is a SLICE, keep it in the buffer */ - xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, next_nal); - parser->prebuf_len += next_nal; - parser->incomplete_nal = 0; + if(parser->nal_size_length > 0) { + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; + } - parsed_len += next_nal; - inbuf += next_nal; + xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); + parser->buf_len += next_nal+start_seq_len-2*offset; - parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); - if (parser->last_nal_res == 1 && parser->buf_len > 0) { + memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); + parser->prebuf_len -= next_nal+start_seq_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, *ret_len); - *ret_slice_cnt = parser->slice_cnt; + return inbuf_len; + } - parser->slice_cnt = 1; + /* got a new nal, which is part of the current + * coded picture. add it to buf + */ + if (parser->last_nal_res != 2) { + if (parser->buf_len + next_nal+start_seq_len-offset > MAX_FRAME_SIZE) { + printf("buf underrun 1!!\n"); 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); - if(parser->nal_size_length > 0) { - static const 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, parser->prebuf+offset, parser->prebuf_len-offset); - parser->buf_len += (parser->prebuf_len-offset); - parser->prebuf_len = 0; - parser->incomplete_nal = 0; - - return parsed_len; + *ret_len = 0; + *ret_buf = NULL; + return inbuf_len; } - if (parser->last_nal_res != 2) { - if (parser->buf_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun 1!!\n"); - parser->buf_len = 0; - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } - - //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); - /* this is a SLICE, keep it in the buffer */ - if(parser->nal_size_length > 0) { - static const 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, parser->prebuf+offset, parser->prebuf_len-offset); - parser->buf_len += (parser->prebuf_len-offset); + if(parser->nal_size_length > 0) { + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; } - parser->prebuf_len = 0; - completed_nal = 1; + xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); + parser->buf_len += next_nal+start_seq_len-2*offset; + memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); + parser->prebuf_len -= next_nal+start_seq_len-offset; } else { - /* most likely we are at the beginning of the stream here - * which starts not with a nal-boundardy but with some garbage - * -> throw it away - */ - parsed_len += next_nal; - inbuf += next_nal; - } - - if(!parser->nal_size_length) - search_offset = start_seq_len; - } - - /* if inbuf does not end with the start of a new nal - * copy the left data into prebuf - */ - if(parsed_len < inbuf_len) { - if (inbuf_len-parsed_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun 0!!\n"); - parser->prebuf_len = 0; - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; + /* got a non-relevant nal, just remove it */ + memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); + parser->prebuf_len -= next_nal+start_seq_len-offset; } - - parser->incomplete_nal = 1; - xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); - parser->prebuf_len += inbuf_len-parsed_len; - inbuf += inbuf_len-parsed_len; - parsed_len += inbuf_len-parsed_len; } - *ret_len = 0; *ret_buf = NULL; - return parsed_len; + *ret_len = 0; + return inbuf_len; } + +/** + * @return 0: NAL is part of coded picture + * 2: NAL is not part of coded picture + * 1: NAL is the beginning of a new coded picture + */ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { struct buf_reader bufr; @@ -1561,49 +1498,24 @@ int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { if(parser->nal_size_length > 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; - } + buf_len < parser->nal_size_length) { return -1; } uint32_t next_nal = parser->next_nal_position; if(!next_nal) { - 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; + struct buf_reader bufr; - 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; + 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-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; - } + next_nal = read_bits(&bufr, parser->nal_size_length*8)+parser->nal_size_length; } if(next_nal > buf_len) { - parser->next_nal_position = next_nal-buf_len; + parser->next_nal_position = next_nal; return -1; } else parser->next_nal_position = 0; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 6ae22d3bc..ad0a77b9b 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -533,15 +533,18 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v 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; + //decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); this->dangling_img = NULL; + if(decoded_pic->nal->slc->bottom_field_flag) decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; - } else - decoded_pic->delayed_output = 1; + } + + decoded_pic->delayed_output = 1; if(this->wait_for_bottom_field && slc->bottom_field_flag) decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; |