summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libvdpau/dpb.c4
-rw-r--r--src/libvdpau/dpb.h2
-rw-r--r--src/libvdpau/h264_parser.c53
-rw-r--r--src/libvdpau/vdpau_h264.c18
4 files changed, 57 insertions, 20 deletions
diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c
index 01f147639..d82a2e16d 100644
--- a/src/libvdpau/dpb.c
+++ b/src/libvdpau/dpb.c
@@ -51,12 +51,12 @@ void free_decoded_picture(struct decoded_picture *pic)
free(pic);
}
-struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb)
+struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush)
{
struct decoded_picture *pic = dpb->pictures;
struct decoded_picture *outpic = NULL;
- if(dpb->used < MAX_DPB_SIZE)
+ if(!do_flush && dpb->used < MAX_DPB_SIZE)
return NULL;
if (pic != NULL)
diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h
index 6578aa42f..6be2acec8 100644
--- a/src/libvdpau/dpb.h
+++ b/src/libvdpau/dpb.h
@@ -55,7 +55,7 @@ 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_next_out_picture(struct dpb *dpb, int do_flush);
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);
diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c
index 6507a577a..f97176859 100644
--- a/src/libvdpau/h264_parser.c
+++ b/src/libvdpau/h264_parser.c
@@ -1286,7 +1286,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len);
parser->prebuf_len += inbuf_len;
- while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-2*start_seq_len+(2*offset), parser)) > 0) {
+ while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-start_seq_len+offset, parser)) > 0) {
if(!parser->nal_size_length &&
(parser->prebuf[0] != 0x00 || parser->prebuf[1] != 0x00 || parser->prebuf[2] != 0x01)) {
@@ -1295,7 +1295,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
} else
parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser);
- if (parser->last_nal_res == 1 && parser->buf_len > 0) {
+ printf("nal res: %d\n", parser->last_nal_res);
+ if ((parser->last_nal_res == 1 || parser->last_nal_res == 3) && parser->buf_len > 0) {
//printf("Frame complete: %d bytes\n", parser->buf_len);
*ret_len = parser->buf_len;
@@ -1308,15 +1309,18 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_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, start_seq, 3);
- parser->buf_len += 3;
- }
+ if(parser->last_nal_res != 3) {
+ 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;
+ }
- 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;
+ 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;
+ }
+ printf("move %d bytes\n", parser->prebuf_len-(next_nal+start_seq_len-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;
@@ -1326,7 +1330,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
/* got a new nal, which is part of the current
* coded picture. add it to buf
*/
- if (parser->last_nal_res != 2) {
+ 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;
@@ -1348,6 +1352,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len,
parser->prebuf_len -= next_nal+start_seq_len-offset;
} else {
/* got a non-relevant nal, just remove it */
+ printf("move: %d bytes\n", parser->prebuf_len-(next_nal+start_seq_len-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;
}
@@ -1363,6 +1368,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int 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
+ * 3: NAL is marked as END_OF_SEQUENCE
*/
int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser)
{
@@ -1483,11 +1489,20 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser)
parser->slice_cnt++;
return ret;
- }
- else if (res == NAL_PPS || res == NAL_SPS) {
+ } else if (res == NAL_PPS || res == NAL_SPS) {
return 2;
- }
- else if (res >= NAL_SEI) {
+ } else if (res == NAL_END_OF_SEQUENCE) {
+ if (parser->current_nal == parser->nal0) {
+ parser->current_nal = parser->nal1;
+ parser->last_nal = parser->nal0;
+ }
+ else {
+ parser->current_nal = parser->nal0;
+ parser->last_nal = parser->nal1;
+ }
+
+ return 3;
+ } else if (res >= NAL_SEI) {
return 2;
}
@@ -1496,9 +1511,11 @@ 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(buf_len <= 0)
+ return -1;
+
if(parser->nal_size_length > 0) {
- if(buf_len <= 0 ||
- buf_len < parser->nal_size_length) {
+ if(buf_len < parser->nal_size_length) {
return -1;
}
@@ -1523,6 +1540,10 @@ int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser)
return next_nal;
}
+ /* NAL_END_OF_SEQUENCE */
+ if(buf[0] == 0x0a)
+ return 1;
+
int i;
for (i = 0; i < buf_len - 2; i++) {
if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) {
diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c
index ad0a77b9b..82a18af64 100644
--- a/src/libvdpau/vdpau_h264.c
+++ b/src/libvdpau/vdpau_h264.c
@@ -87,6 +87,7 @@ typedef struct vdpau_h264_decoder_s {
} vdpau_h264_decoder_t;
static void vdpau_h264_reset (video_decoder_t *this_gen);
+static void vdpau_h264_flush (video_decoder_t *this_gen);
/**************************************************************************
* vdpau_h264 specific decode functions
@@ -552,7 +553,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v
this->last_img = img = NULL;
/* now retrieve the next output frame */
- if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) {
+ if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 0)) != NULL) {
decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt);
//printf("draw pts: %lld\n", decoded_pic->img->pts);
decoded_pic->img->draw(decoded_pic->img, this->stream);
@@ -654,6 +655,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
this->nal_parser->current_nal->pps != NULL) {
vdpau_decoder_render(this_gen, &vdp_buffer, slice_count);
}
+
+ /* in case the last nal was detected as END_OF_SEQUENCE
+ * we will flush the dpb, so that all pictures get drawn
+ */
+ if(this->nal_parser->last_nal_res == 3)
+ vdpau_h264_flush(this_gen);
}
if(buf->pts != 0 && buf->pts != this->next_pts) {
@@ -670,6 +677,15 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
* This function is called when xine needs to flush the system.
*/
static void vdpau_h264_flush (video_decoder_t *this_gen) {
+ vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t*) this_gen;
+ struct decoded_picture *decoded_pic = NULL;
+
+ while ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 1)) != NULL) {
+ decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt);
+ printf("FLUSH draw pts: %lld\n", decoded_pic->img->pts);
+ decoded_pic->img->draw(decoded_pic->img, this->stream);
+ dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic);
+ }
}
/*