summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libvdpau/h264_parser.c105
-rw-r--r--src/libvdpau/h264_parser.h2
-rw-r--r--src/libvdpau/nal.c6
-rw-r--r--src/libvdpau/vdpau_h264.c62
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) );