mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-12 02:15:31 +00:00
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:
parent
cee9101dd8
commit
1fff3a44dd
2 changed files with 32 additions and 3 deletions
|
@ -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)
|
||||
|
|
|
@ -114,6 +114,7 @@ typedef enum {
|
|||
struct _GstVaapiPicture {
|
||||
/*< private >*/
|
||||
GstVaapiCodecObject parent_instance;
|
||||
GstVaapiPicture *parent_picture;
|
||||
GstVideoCodecFrame *frame;
|
||||
GstVaapiSurface *surface;
|
||||
GstVaapiSurfaceProxy *proxy;
|
||||
|
|
Loading…
Reference in a new issue