decoder: fix memory leak when processing interlaced pictures.

Fix memory leak when processing interlaced pictures and that occurs
because the first field, represented as a GstVideoCodecFrame, never
gets released. i.e. when the picture is completed, this is generally
the case when the second field is successfully decoded, we need to
propagate the GstVideoCodecFrame of the first field to the original
GstVideoDecoder so that it could reclaim memory.

Otherwise, we keep accumulating the first fields into GstVideoDecoder
private frames list until the end-of-stream is reached. The frames
are eventually released there, but too late, i.e. too much memory
may have been consumed.

https://bugzilla.gnome.org/show_bug.cgi?id=701257
This commit is contained in:
Gwenole Beauchesne 2013-06-11 15:11:34 +02:00
parent cee9101dd8
commit 1fff3a44dd
2 changed files with 32 additions and 3 deletions

View file

@ -86,6 +86,7 @@ gst_vaapi_picture_destroy(GstVaapiPicture *picture)
gst_video_codec_frame_unref(picture->frame);
picture->frame = NULL;
}
gst_vaapi_picture_replace(&picture->parent_picture, NULL);
}
gboolean
@ -99,6 +100,8 @@ gst_vaapi_picture_create(
if (args->flags & GST_VAAPI_CREATE_PICTURE_FLAG_CLONE) {
GstVaapiPicture * const parent_picture = GST_VAAPI_PICTURE(args->data);
picture->parent_picture = gst_vaapi_picture_ref(parent_picture);
picture->proxy = gst_vaapi_surface_proxy_ref(parent_picture->proxy);
picture->type = parent_picture->type;
picture->pts = parent_picture->pts;
@ -300,14 +303,15 @@ gst_vaapi_picture_decode(GstVaapiPicture *picture)
return TRUE;
}
gboolean
gst_vaapi_picture_output(GstVaapiPicture *picture)
static gboolean
do_output(GstVaapiPicture *picture)
{
GstVideoCodecFrame * const out_frame = picture->frame;
GstVaapiSurfaceProxy *proxy;
guint flags = 0;
g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
if (GST_VAAPI_PICTURE_IS_OUTPUT(picture))
return TRUE;
if (!picture->proxy)
return FALSE;
@ -339,6 +343,30 @@ gst_vaapi_picture_output(GstVaapiPicture *picture)
return TRUE;
}
gboolean
gst_vaapi_picture_output(GstVaapiPicture *picture)
{
g_return_val_if_fail(GST_VAAPI_IS_PICTURE(picture), FALSE);
if (G_UNLIKELY(picture->parent_picture)) {
/* Emit the first field to GstVideoDecoder so that to release
the underlying GstVideoCodecFrame. However, mark this
picture as skipped so that to not display it */
GstVaapiPicture * const parent_picture = picture->parent_picture;
do {
if (!GST_VAAPI_PICTURE_IS_INTERLACED(parent_picture))
break;
if (!GST_VAAPI_PICTURE_IS_FIRST_FIELD(parent_picture))
break;
GST_VAAPI_PICTURE_FLAG_SET(parent_picture,
GST_VAAPI_PICTURE_FLAG_SKIPPED);
if (!do_output(parent_picture))
return FALSE;
} while (0);
}
return do_output(picture);
}
void
gst_vaapi_picture_set_crop_rect(GstVaapiPicture *picture,
const GstVaapiRectangle *crop_rect)

View file

@ -114,6 +114,7 @@ typedef enum {
struct _GstVaapiPicture {
/*< private >*/
GstVaapiCodecObject parent_instance;
GstVaapiPicture *parent_picture;
GstVideoCodecFrame *frame;
GstVaapiSurface *surface;
GstVaapiSurfaceProxy *proxy;