summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2020-01-17 11:07:47 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2020-01-20 10:51:15 +0530
commit2343fd60e43f5a78ca6e6fa1f40d57522a9bafce (patch)
tree3234bc363e4ca6d6b583acbf203455ceeb5bdd5f
parent0a0f929f5e5ccd3944812cb55674a92a9611f2cf (diff)
downloadgstreamer-plugins-bad-2343fd60e43f5a78ca6e6fa1f40d57522a9bafce.tar.gz
msdk: Fix increasing memory usage in dynamic pipelines
Our context is non-persistent, and we propagate it throughout the pipeline. This means that if we try to reuse any gstmsdk element by removing it from the pipeline and then re-adding it, we'll clone the mfxSession and create a new gstmsdk context as a child of the old one inside `gst_msdk_context_new_with_parent()`. Normally this only allocates a few KB inside the driver, but on Windows it seems to allocate tens of MBs which leads to linearly increasing memory usage for each PLAYING->NULL->PLAYING state cycle for the process. The contexts will only be freed when the pipeline itself goes to `NULL`, which would defeat the purpose of dynamic pipelines. Essentially, we need to optimize the case in which the element is removed from the pipeline and re-added and the same context is re-set on it. To detect that case, we set the context on `old_context`, and compare it to the new one when preparing the context. If they're the same, we don't need to do anything. Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/issues/946
-rw-r--r--sys/msdk/gstmsdkcontextutil.c1
-rw-r--r--sys/msdk/gstmsdkdec.c11
-rw-r--r--sys/msdk/gstmsdkdec.h1
-rw-r--r--sys/msdk/gstmsdkenc.c12
-rw-r--r--sys/msdk/gstmsdkenc.h1
-rw-r--r--sys/msdk/gstmsdkvpp.c15
-rw-r--r--sys/msdk/gstmsdkvpp.h1
7 files changed, 42 insertions, 0 deletions
diff --git a/sys/msdk/gstmsdkcontextutil.c b/sys/msdk/gstmsdkcontextutil.c
index 0e25080ef..6f5c7e41d 100644
--- a/sys/msdk/gstmsdkcontextutil.c
+++ b/sys/msdk/gstmsdkcontextutil.c
@@ -161,6 +161,7 @@ gst_msdk_context_find (GstElement * element, GstMsdkContext ** context_ptr)
return TRUE;
}
+ /* This may indirectly set *context_ptr, see function body */
_gst_context_query (element, GST_MSDK_CONTEXT_TYPE_NAME);
if (*context_ptr)
diff --git a/sys/msdk/gstmsdkdec.c b/sys/msdk/gstmsdkdec.c
index 03a4fbb27..684a992e5 100644
--- a/sys/msdk/gstmsdkdec.c
+++ b/sys/msdk/gstmsdkdec.c
@@ -649,6 +649,12 @@ gst_msdkdec_context_prepare (GstMsdkDec * thiz)
if (!gst_msdk_context_find (GST_ELEMENT_CAST (thiz), &thiz->context))
return FALSE;
+ if (thiz->context == thiz->old_context) {
+ GST_INFO_OBJECT (thiz, "Found old context %" GST_PTR_FORMAT
+ ", reusing as-is", thiz->context);
+ return TRUE;
+ }
+
thiz->use_video_memory = TRUE;
GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour",
@@ -697,6 +703,11 @@ gst_msdkdec_start (GstVideoDecoder * decoder)
thiz->context);
}
+ /* Save the current context in a separate field so that we know whether it
+ * has changed between calls to _start() */
+ gst_object_replace ((GstObject **) & thiz->old_context,
+ (GstObject *) thiz->context);
+
gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
return TRUE;
diff --git a/sys/msdk/gstmsdkdec.h b/sys/msdk/gstmsdkdec.h
index 9ab21e2e1..60d62df7d 100644
--- a/sys/msdk/gstmsdkdec.h
+++ b/sys/msdk/gstmsdkdec.h
@@ -91,6 +91,7 @@ struct _GstMsdkDec
/* MFX context */
GstMsdkContext *context;
+ GstMsdkContext *old_context;
mfxVideoParam param;
GArray *tasks;
guint next_task;
diff --git a/sys/msdk/gstmsdkenc.c b/sys/msdk/gstmsdkenc.c
index f97e35cee..f11c43e2e 100644
--- a/sys/msdk/gstmsdkenc.c
+++ b/sys/msdk/gstmsdkenc.c
@@ -1402,6 +1402,12 @@ gst_msdkenc_context_prepare (GstMsdkEnc * thiz)
if (!gst_msdk_context_find (GST_ELEMENT_CAST (thiz), &thiz->context))
return FALSE;
+ if (thiz->context == thiz->old_context) {
+ GST_INFO_OBJECT (thiz, "Found old context %" GST_PTR_FORMAT
+ ", reusing as-is", thiz->context);
+ return TRUE;
+ }
+
GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour",
thiz->context);
@@ -1453,6 +1459,11 @@ gst_msdkenc_start (GstVideoEncoder * encoder)
thiz->context);
}
+ /* Save the current context in a separate field so that we know whether it
+ * has changed between calls to _start() */
+ gst_object_replace ((GstObject **) & thiz->old_context,
+ (GstObject *) thiz->context);
+
gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
/* Set the minimum pts to some huge value (1000 hours). This keeps
@@ -1574,6 +1585,7 @@ gst_msdkenc_finalize (GObject * object)
gst_clear_object (&thiz->msdk_pool);
gst_clear_object (&thiz->msdk_converted_pool);
+ gst_clear_object (&thiz->old_context);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
diff --git a/sys/msdk/gstmsdkenc.h b/sys/msdk/gstmsdkenc.h
index 1cfaf50ae..501b52372 100644
--- a/sys/msdk/gstmsdkenc.h
+++ b/sys/msdk/gstmsdkenc.h
@@ -99,6 +99,7 @@ struct _GstMsdkEnc
/* MFX context */
GstMsdkContext *context;
+ GstMsdkContext *old_context;
mfxVideoParam param;
guint num_surfaces;
guint num_tasks;
diff --git a/sys/msdk/gstmsdkvpp.c b/sys/msdk/gstmsdkvpp.c
index 2c7e07c40..bf5430973 100644
--- a/sys/msdk/gstmsdkvpp.c
+++ b/sys/msdk/gstmsdkvpp.c
@@ -161,6 +161,12 @@ gst_msdkvpp_context_prepare (GstMsdkVPP * thiz)
if (!gst_msdk_context_find (GST_ELEMENT_CAST (thiz), &thiz->context))
return FALSE;
+ if (thiz->context == thiz->old_context) {
+ GST_INFO_OBJECT (thiz, "Found old context %" GST_PTR_FORMAT
+ ", reusing as-is", thiz->context);
+ return TRUE;
+ }
+
GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour",
thiz->context);
@@ -211,6 +217,11 @@ ensure_context (GstBaseTransform * trans)
thiz->context);
}
+ /* Save the current context in a separate field so that we know whether it
+ * has changed between calls to _start() */
+ gst_object_replace ((GstObject **) & thiz->old_context,
+ (GstObject *) thiz->context);
+
gst_msdk_context_add_shared_async_depth (thiz->context, thiz->async_depth);
return TRUE;
@@ -1359,6 +1370,10 @@ gst_msdkvpp_get_property (GObject * object, guint prop_id,
static void
gst_msdkvpp_finalize (GObject * object)
{
+ GstMsdkVPP *thiz = GST_MSDKVPP (object);
+
+ gst_clear_object (&thiz->old_context);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
diff --git a/sys/msdk/gstmsdkvpp.h b/sys/msdk/gstmsdkvpp.h
index e82925952..f426a2dd8 100644
--- a/sys/msdk/gstmsdkvpp.h
+++ b/sys/msdk/gstmsdkvpp.h
@@ -88,6 +88,7 @@ struct _GstMsdkVPP
/* MFX context */
GstMsdkContext *context;
+ GstMsdkContext *old_context;
mfxVideoParam param;
guint in_num_surfaces;
guint out_num_surfaces;