diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2020-01-17 11:07:47 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2020-01-20 10:51:15 +0530 |
commit | 2343fd60e43f5a78ca6e6fa1f40d57522a9bafce (patch) | |
tree | 3234bc363e4ca6d6b583acbf203455ceeb5bdd5f | |
parent | 0a0f929f5e5ccd3944812cb55674a92a9611f2cf (diff) | |
download | gstreamer-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.c | 1 | ||||
-rw-r--r-- | sys/msdk/gstmsdkdec.c | 11 | ||||
-rw-r--r-- | sys/msdk/gstmsdkdec.h | 1 | ||||
-rw-r--r-- | sys/msdk/gstmsdkenc.c | 12 | ||||
-rw-r--r-- | sys/msdk/gstmsdkenc.h | 1 | ||||
-rw-r--r-- | sys/msdk/gstmsdkvpp.c | 15 | ||||
-rw-r--r-- | sys/msdk/gstmsdkvpp.h | 1 |
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; |