summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Scheel <julian@jusst.de>2010-01-30 12:45:49 +0100
committerJulian Scheel <julian@jusst.de>2010-01-30 12:45:49 +0100
commit474815e24bf5ed57813bab2c970bce13ad822e3c (patch)
tree97e1e0e12fe9a6d5e49683d5b4fd16006e13ee87
parentaba6adc0529ceed3406faabdc682efab035ef5ca (diff)
downloadxine-lib-474815e24bf5ed57813bab2c970bce13ad822e3c.tar.gz
xine-lib-474815e24bf5ed57813bab2c970bce13ad822e3c.tar.bz2
fix a memleak with interlaced content
some minor cleanups
-rw-r--r--src/video_dec/libvdpau/dpb.c54
-rw-r--r--src/video_dec/libvdpau/dpb.h5
-rw-r--r--src/video_dec/libvdpau/h264_parser.c9
-rw-r--r--src/video_dec/libvdpau/vdpau_h264.c29
4 files changed, 65 insertions, 32 deletions
diff --git a/src/video_dec/libvdpau/dpb.c b/src/video_dec/libvdpau/dpb.c
index 819f1f9a2..509075134 100644
--- a/src/video_dec/libvdpau/dpb.c
+++ b/src/video_dec/libvdpau/dpb.c
@@ -30,6 +30,8 @@
#include <xine/video_out.h>
+void free_decoded_picture(struct decoded_picture *pic);
+
struct decoded_picture* init_decoded_picture(struct coded_picture *cpic,
VdpVideoSurface surface, vo_frame_t *img)
{
@@ -43,6 +45,7 @@ struct decoded_picture* init_decoded_picture(struct coded_picture *cpic,
pic->surface = surface;
pic->img = img;
pic->delayed_output = 1;
+ pic->lock_counter = 1;
return pic;
}
@@ -64,12 +67,32 @@ void dpb_add_coded_picture(struct decoded_picture *pic,
}
}
+void release_decoded_picture(struct decoded_picture *pic)
+{
+ if(!pic)
+ return;
+
+ pic->lock_counter--;
+
+ if(pic->lock_counter <= 0) {
+ free_decoded_picture(pic);
+ }
+}
+
+void lock_decoded_picture(struct decoded_picture *pic)
+{
+ if(!pic)
+ return;
+
+ pic->lock_counter++;
+}
+
void free_decoded_picture(struct decoded_picture *pic)
{
pic->img->free(pic->img);
+ free_coded_picture(pic->coded_pic[1]);
free_coded_picture(pic->coded_pic[0]);
pic->coded_pic[0] = NULL;
- free_coded_picture(pic->coded_pic[1]);
pic->coded_pic[1] = NULL;
free(pic);
}
@@ -127,13 +150,6 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush)
} while ((pic = pic->next) != NULL);
}
- int32_t out_top_field_order_cnt = outpic != NULL ?
- outpic->coded_pic[0]->top_field_order_cnt : 0;
- int32_t out_bottom_field_order_cnt = outpic != NULL ?
- (outpic->coded_pic[1] != NULL ?
- outpic->coded_pic[1]->bottom_field_order_cnt :
- outpic->coded_pic[0]->top_field_order_cnt) : 0;
-
return outpic;
}
@@ -327,7 +343,7 @@ int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, int32_t longterm_idx)
int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic)
{
- struct decoded_picture *pic = dpb->pictures;
+ /*struct decoded_picture *pic = dpb->pictures;
if (pic != NULL)
do {
if (pic == outpic) {
@@ -336,9 +352,15 @@ int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic)
dpb_remove_picture(dpb, pic);
return 0;
}
- } while ((pic = pic->next) != NULL);
+ } while ((pic = pic->next) != NULL);*/
+ if(!outpic)
+ return -1;
- return -1;
+ outpic->delayed_output = 0;
+ if(!outpic->used_for_reference)
+ dpb_remove_picture(dpb, outpic);
+
+ return 0;
}
int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic)
@@ -353,7 +375,7 @@ int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic)
last_pic->next = pic->next;
else
dpb->pictures = pic->next;
- free_decoded_picture(pic);
+ release_decoded_picture(pic);
dpb->used--;
return 0;
}
@@ -376,7 +398,7 @@ static int dpb_remove_picture_by_img(struct dpb *dpb, vo_frame_t *remimg)
last_pic->next = pic->next;
else
dpb->pictures = pic->next;
- free_decoded_picture(pic);
+ release_decoded_picture(pic);
dpb->used--;
return 0;
}
@@ -460,7 +482,7 @@ void dpb_free_all( struct dpb *dpb )
if (pic != NULL)
do {
struct decoded_picture *next_pic = pic->next;
- free_decoded_picture(pic);
+ release_decoded_picture(pic);
--dpb->used;
pic = next_pic;
} while (pic != NULL);
@@ -493,7 +515,9 @@ int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist)
reflist[i].is_long_term = pic->coded_pic[0]->used_for_long_term_ref ||
(pic->coded_pic[1] != NULL && pic->coded_pic[1]->used_for_long_term_ref);
- reflist[i].frame_idx = pic->coded_pic[0]->slc_nal->slc.frame_num;
+ reflist[i].frame_idx = pic->coded_pic[0]->used_for_long_term_ref ?
+ pic->coded_pic[0]->long_term_pic_num :
+ pic->coded_pic[0]->slc_nal->slc.frame_num;
reflist[i].top_is_reference = pic->top_is_reference;
reflist[i].bottom_is_reference = pic->bottom_is_reference;
reflist[i].field_order_cnt[0] = pic->coded_pic[0]->top_field_order_cnt;
diff --git a/src/video_dec/libvdpau/dpb.h b/src/video_dec/libvdpau/dpb.h
index 9a667b79f..9881ebccb 100644
--- a/src/video_dec/libvdpau/dpb.h
+++ b/src/video_dec/libvdpau/dpb.h
@@ -50,6 +50,8 @@ struct decoded_picture {
uint8_t delayed_output;
struct decoded_picture *next;
+
+ uint32_t lock_counter;
};
/* Decoded Picture Buffer */
@@ -62,7 +64,8 @@ struct dpb {
struct decoded_picture* init_decoded_picture(struct coded_picture *cpic,
VdpVideoSurface surface, vo_frame_t *img);
-void free_decoded_picture(struct decoded_picture *pic);
+void release_decoded_picture(struct decoded_picture *pic);
+void lock_decoded_picture(struct decoded_picture *pic);
void dpb_add_coded_picture(struct decoded_picture *pic,
struct coded_picture *cpic);
diff --git a/src/video_dec/libvdpau/h264_parser.c b/src/video_dec/libvdpau/h264_parser.c
index 505891caf..d26d53f0c 100644
--- a/src/video_dec/libvdpau/h264_parser.c
+++ b/src/video_dec/libvdpau/h264_parser.c
@@ -1541,11 +1541,6 @@ struct h264_parser* init_parser(xine_t *xine)
parser->xine = xine;
memset(&parser->dpb, 0x00, sizeof(struct dpb));
- /* no idea why we do that. inspired by libavcodec,
- * as we couldn't figure in the specs....
- */
- parser->prev_pic_order_cnt_msb = 1 << 16;
-
return parser;
}
@@ -1561,7 +1556,7 @@ void reset_parser(struct h264_parser *parser)
}
parser->last_vcl_nal = NULL;
- parser->prev_pic_order_cnt_msb = 1 << 16;
+ parser->prev_pic_order_cnt_msb = 0;
parser->prev_pic_order_cnt_lsb = 0;
parser->frame_num_offset = 0;
parser->prev_top_field_order_cnt = 0;
@@ -1898,7 +1893,7 @@ int parse_nal(uint8_t *buf, int buf_len, struct h264_parser *parser,
}
/* increase the slice_cnt until a new frame is detected */
- if (ret) {
+ if (ret && *completed_picture == NULL) {
*completed_picture = parser->pic;
parser->pic = create_coded_picture();
}
diff --git a/src/video_dec/libvdpau/vdpau_h264.c b/src/video_dec/libvdpau/vdpau_h264.c
index 6341a1b9a..e20ac2ac9 100644
--- a/src/video_dec/libvdpau/vdpau_h264.c
+++ b/src/video_dec/libvdpau/vdpau_h264.c
@@ -396,7 +396,10 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v
// picture? - should we keep the first field in dpb?
if(this->completed_pic->flag_mask & IDR_PIC) {
dpb_flush(&(this->nal_parser->dpb));
- this->last_ref_pic = NULL;
+ if(this->last_ref_pic) {
+ release_decoded_picture(this->last_ref_pic);
+ this->last_ref_pic = NULL;
+ }
}
VdpPictureInfoH264 pic;
@@ -471,8 +474,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v
VdpVideoSurface surface = this->vdpau_accel->surface;
- //xprintf(this->xine, XINE_VERBOSITY_DEBUG,
- // "Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->completed_pic->pts);
+ /*xprintf(this->xine, XINE_VERBOSITY_DEBUG,
+ "Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->completed_pic->pts);*/
VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder,
surface, (VdpPictureInfo*)&pic, 1, vdp_buffer);
@@ -529,16 +532,19 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v
if(!slc->field_pic_flag || !this->wait_for_bottom_field) {
decoded_pic = init_decoded_picture(this->completed_pic, surface, img);
this->completed_pic = NULL;
+ if(this->last_ref_pic) {
+ release_decoded_picture(this->last_ref_pic);
+ this->last_ref_pic = NULL;
+ }
this->last_ref_pic = decoded_pic;
+ lock_decoded_picture(this->last_ref_pic);
decoded_pic->used_for_reference = 1;
dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames);
this->dangling_img = NULL;
} else if(slc->field_pic_flag && this->wait_for_bottom_field) {
if(this->last_ref_pic) {
decoded_pic = this->last_ref_pic;
- //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal);
-
- dpb_add_coded_picture(this->last_ref_pic, this->completed_pic);
+ dpb_add_coded_picture(decoded_pic, this->completed_pic);
this->completed_pic = NULL;
}
}
@@ -550,7 +556,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v
if(!decoded_pic) {
decoded_pic = init_decoded_picture(this->completed_pic, surface, img);
this->completed_pic = NULL;
- //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;
}
@@ -570,10 +576,13 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v
this->wait_for_bottom_field = 0;
} else if(slc->field_pic_flag && !slc->bottom_field_flag) {
- // don't draw yet, second field is missing.
- //this->last_top_field_order_cnt = this->nal_parser->completed_pic->top_field_order_cnt;
+ /* don't draw yet, second field is missing. */
this->wait_for_bottom_field = 1;
this->last_img = img;
+ if(this->completed_pic) {
+ free_coded_picture(this->completed_pic);
+ }
+ this->completed_pic = NULL;
}
}
@@ -664,6 +673,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen,
this->completed_pic->slc_nal != NULL &&
this->completed_pic->pps_nal != NULL) {
vdpau_decoder_render(this_gen, &vdp_buffer, this->completed_pic->slice_cnt);
+ } else if (this->completed_pic != NULL) {
+ free_coded_picture(this->completed_pic);
}
/* in case the last nal was detected as END_OF_SEQUENCE