diff options
author | Julian Scheel <julian@jusst.de> | 2009-04-14 09:37:35 +0100 |
---|---|---|
committer | Julian Scheel <julian@jusst.de> | 2009-04-14 09:37:35 +0100 |
commit | c52ce94d57dab4d67f0689d785ad373f92b60a90 (patch) | |
tree | 5ed1fb69455dc99c9a81ffcf607d0df34e44d220 | |
parent | 3fa3377b8390478732b72fc03d95ced445e4bb1c (diff) | |
download | xine-lib-c52ce94d57dab4d67f0689d785ad373f92b60a90.tar.gz xine-lib-c52ce94d57dab4d67f0689d785ad373f92b60a90.tar.bz2 |
Add H.264 still frame support.
-rw-r--r-- | src/libvdpau/dpb.c | 4 | ||||
-rw-r--r-- | src/libvdpau/dpb.h | 2 | ||||
-rw-r--r-- | src/libvdpau/h264_parser.c | 53 | ||||
-rw-r--r-- | src/libvdpau/vdpau_h264.c | 18 |
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); + } } /* |