From f2b35abcabeafe5de0bc78bfcde4e5615deb166d Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Tue, 13 Feb 2018 13:51:18 -0900 Subject: msdkdec/enc: query GstContext to share GstMsdkContext How to share/create GstMsdkcontext is the following: - Search GstMsdkContext if there's in the pipeline. - If found, check if it's decoder, encoder or vpp by job type. - If it's same job type, it creates another instance of GstMsdkContext with joined-session. - Otherwise just use the shared GstMsdkContext. - If not found, just creates new instance of GstMsdkContext. https://bugzilla.gnome.org/show_bug.cgi?id=790752 --- sys/msdk/gstmsdkdec.c | 84 +++++++++++++++++++++++++++++++++++++++++---------- sys/msdk/gstmsdkdec.h | 1 + sys/msdk/gstmsdkenc.c | 80 +++++++++++++++++++++++++++++++++++++----------- sys/msdk/gstmsdkenc.h | 1 + 4 files changed, 133 insertions(+), 33 deletions(-) diff --git a/sys/msdk/gstmsdkdec.c b/sys/msdk/gstmsdkdec.c index a4ed46503..916b3d22c 100644 --- a/sys/msdk/gstmsdkdec.c +++ b/sys/msdk/gstmsdkdec.c @@ -39,6 +39,7 @@ #include "gstmsdkbufferpool.h" #include "gstmsdkvideomemory.h" #include "gstmsdksystemmemory.h" +#include "gstmsdkcontextutil.h" GST_DEBUG_CATEGORY_EXTERN (gst_msdkdec_debug); #define GST_CAT_DEFAULT gst_msdkdec_debug @@ -203,10 +204,11 @@ gst_msdkdec_close_decoder (GstMsdkDec * thiz) { mfxStatus status; - if (!thiz->context) + if (!thiz->context || !thiz->initialized) return; - GST_DEBUG_OBJECT (thiz, "Closing decoder 0x%p", thiz->context); + GST_DEBUG_OBJECT (thiz, "Closing decoder with context %" GST_PTR_FORMAT, + thiz->context); if (thiz->use_video_memory) gst_msdk_frame_free (thiz->context, &thiz->alloc_resp); @@ -220,9 +222,23 @@ gst_msdkdec_close_decoder (GstMsdkDec * thiz) g_array_set_size (thiz->tasks, 0); g_ptr_array_set_size (thiz->extra_params, 0); - if (thiz->context) - gst_object_replace ((GstObject **) & thiz->context, NULL); memset (&thiz->param, 0, sizeof (thiz->param)); + thiz->initialized = FALSE; +} + +static void +gst_msdkdec_set_context (GstElement * element, GstContext * context) +{ + GstMsdkContext *msdk_context = NULL; + GstMsdkDec *thiz = GST_MSDKDEC (element); + + if (gst_msdk_context_get_context (context, &msdk_context)) { + gst_object_replace ((GstObject **) & thiz->context, + (GstObject *) msdk_context); + gst_object_unref (msdk_context); + } + + GST_ELEMENT_CLASS (parent_class)->set_context (element, context); } static gboolean @@ -234,20 +250,19 @@ gst_msdkdec_init_decoder (GstMsdkDec * thiz) mfxStatus status; mfxFrameAllocRequest request; - if (!thiz->input_state) { - GST_DEBUG_OBJECT (thiz, "Have no input state yet"); + if (thiz->initialized) + return TRUE; + + if (!thiz->context) { + GST_WARNING_OBJECT (thiz, "No MSDK Context"); return FALSE; } - info = &thiz->input_state->info; - - /* make sure that the decoder is closed */ - gst_msdkdec_close_decoder (thiz); - thiz->context = gst_msdk_context_new (thiz->hardware, GST_MSDK_JOB_DECODER); - if (!thiz->context) { - GST_ERROR_OBJECT (thiz, "Context creation failed"); + if (!thiz->input_state) { + GST_DEBUG_OBJECT (thiz, "Have no input state yet"); return FALSE; } + info = &thiz->input_state->info; GST_OBJECT_LOCK (thiz); @@ -346,12 +361,11 @@ gst_msdkdec_init_decoder (GstMsdkDec * thiz) GST_OBJECT_UNLOCK (thiz); + thiz->initialized = TRUE; return TRUE; failed: GST_OBJECT_UNLOCK (thiz); - gst_object_replace ((GstObject **) & thiz->context, NULL); - thiz->context = NULL; return FALSE; } @@ -473,6 +487,39 @@ gst_msdkdec_finish_task (GstMsdkDec * thiz, MsdkDecTask * task) return GST_FLOW_OK; } +static gboolean +gst_msdkdec_start (GstVideoDecoder * decoder) +{ + GstMsdkDec *thiz = GST_MSDKDEC (decoder); + + if (gst_msdk_context_prepare (GST_ELEMENT_CAST (thiz), &thiz->context)) { + GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour", + thiz->context); + + if (gst_msdk_context_get_job_type (thiz->context) & GST_MSDK_JOB_DECODER) { + GstMsdkContext *parent_context; + + parent_context = thiz->context; + thiz->context = gst_msdk_context_new_with_parent (parent_context); + gst_object_unref (parent_context); + + GST_INFO_OBJECT (thiz, + "Creating new context %" GST_PTR_FORMAT " with joined session", + thiz->context); + } else { + gst_msdk_context_add_job_type (thiz->context, GST_MSDK_JOB_DECODER); + } + } else { + gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz), thiz->hardware, + GST_MSDK_JOB_DECODER); + + GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT, + thiz->context); + } + + return TRUE; +} + static gboolean gst_msdkdec_close (GstVideoDecoder * decoder) { @@ -498,6 +545,8 @@ gst_msdkdec_stop (GstVideoDecoder * decoder) } gst_video_info_init (&thiz->output_info); gst_video_info_init (&thiz->pool_info); + + gst_msdkdec_close_decoder (thiz); return TRUE; } @@ -853,7 +902,7 @@ gst_msdkdec_drain (GstVideoDecoder * decoder) mfxStatus status; guint i; - if (!thiz->context) + if (!thiz->initialized) return GST_FLOW_OK; session = gst_msdk_context_get_session (thiz->context); @@ -1017,7 +1066,10 @@ gst_msdkdec_class_init (GstMsdkDecClass * klass) gobject_class->get_property = gst_msdkdec_get_property; gobject_class->finalize = gst_msdkdec_finalize; + element_class->set_context = gst_msdkdec_set_context; + decoder_class->close = GST_DEBUG_FUNCPTR (gst_msdkdec_close); + decoder_class->start = GST_DEBUG_FUNCPTR (gst_msdkdec_start); decoder_class->stop = GST_DEBUG_FUNCPTR (gst_msdkdec_stop); decoder_class->set_format = GST_DEBUG_FUNCPTR (gst_msdkdec_set_format); decoder_class->finish = GST_DEBUG_FUNCPTR (gst_msdkdec_finish); diff --git a/sys/msdk/gstmsdkdec.h b/sys/msdk/gstmsdkdec.h index ec386daaf..8488b42bc 100644 --- a/sys/msdk/gstmsdkdec.h +++ b/sys/msdk/gstmsdkdec.h @@ -67,6 +67,7 @@ struct _GstMsdkDec GstVideoInfo pool_info; mfxFrameAllocResponse alloc_resp; gboolean use_video_memory; + gboolean initialized; /* MFX context */ GstMsdkContext *context; diff --git a/sys/msdk/gstmsdkenc.c b/sys/msdk/gstmsdkenc.c index 602e66f72..50edcc3c3 100644 --- a/sys/msdk/gstmsdkenc.c +++ b/sys/msdk/gstmsdkenc.c @@ -48,7 +48,7 @@ #include "gstmsdkbufferpool.h" #include "gstmsdkvideomemory.h" #include "gstmsdksystemmemory.h" -#include "gstmsdkallocator.h" +#include "gstmsdkcontextutil.h" static inline void * _aligned_alloc (size_t alignment, size_t size) @@ -150,6 +150,21 @@ gst_msdkenc_add_extra_param (GstMsdkEnc * thiz, mfxExtBuffer * param) } } +static void +gst_msdkenc_set_context (GstElement * element, GstContext * context) +{ + GstMsdkContext *msdk_context = NULL; + GstMsdkEnc *thiz = GST_MSDKENC (element); + + if (gst_msdk_context_get_context (context, &msdk_context)) { + gst_object_replace ((GstObject **) & thiz->context, + (GstObject *) msdk_context); + gst_object_unref (msdk_context); + } + + GST_ELEMENT_CLASS (parent_class)->set_context (element, context); +} + static gboolean gst_msdkenc_init_encoder (GstMsdkEnc * thiz) { @@ -160,20 +175,19 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz) mfxFrameAllocRequest request[2]; guint i; - if (!thiz->input_state) { - GST_DEBUG_OBJECT (thiz, "Have no input state yet"); + if (thiz->initialized) + return TRUE; + + if (!thiz->context) { + GST_WARNING_OBJECT (thiz, "No MSDK Context"); return FALSE; } - info = &thiz->input_state->info; - - /* make sure that the encoder is closed */ - gst_msdkenc_close_encoder (thiz); - thiz->context = gst_msdk_context_new (thiz->hardware, GST_MSDK_JOB_ENCODER); - if (!thiz->context) { - GST_ERROR_OBJECT (thiz, "Context creation failed"); + if (!thiz->input_state) { + GST_DEBUG_OBJECT (thiz, "Have no input state yet"); return FALSE; } + info = &thiz->input_state->info; GST_OBJECT_LOCK (thiz); session = gst_msdk_context_get_session (thiz->context); @@ -346,6 +360,9 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz) msdk_status_to_string (status)); } + if (thiz->has_vpp) + request[0].NumFrameSuggested += thiz->num_vpp_surfaces + 1 - 4; + if (thiz->use_video_memory) gst_msdk_frame_alloc (thiz->context, &(request[0]), &thiz->alloc_resp); @@ -400,6 +417,7 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz) thiz->next_task = 0; thiz->reconfig = FALSE; + thiz->initialized = TRUE; GST_OBJECT_UNLOCK (thiz); @@ -408,8 +426,6 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz) no_vpp: failed: GST_OBJECT_UNLOCK (thiz); - if (thiz->context) - gst_object_replace ((GstObject **) & thiz->context, NULL); return FALSE; } @@ -419,10 +435,11 @@ gst_msdkenc_close_encoder (GstMsdkEnc * thiz) guint i; mfxStatus status; - if (!thiz->context) + if (!thiz->context || !thiz->initialized) return; - GST_DEBUG_OBJECT (thiz, "Closing encoder 0x%p", thiz->context); + GST_DEBUG_OBJECT (thiz, "Closing encoder with context %" GST_PTR_FORMAT, + thiz->context); gst_object_replace ((GstObject **) & thiz->msdk_pool, NULL); gst_object_replace ((GstObject **) & thiz->msdk_converted_pool, NULL); @@ -460,11 +477,9 @@ gst_msdkenc_close_encoder (GstMsdkEnc * thiz) } } - if (thiz->context) - gst_object_replace ((GstObject **) & thiz->context, NULL); - memset (&thiz->param, 0, sizeof (thiz->param)); thiz->num_extra_params = 0; + thiz->initialized = FALSE; } typedef struct @@ -1115,6 +1130,33 @@ invalid_frame: static gboolean gst_msdkenc_start (GstVideoEncoder * encoder) { + GstMsdkEnc *thiz = GST_MSDKENC (encoder); + + if (gst_msdk_context_prepare (GST_ELEMENT_CAST (thiz), &thiz->context)) { + GST_INFO_OBJECT (thiz, "Found context %" GST_PTR_FORMAT " from neighbour", + thiz->context); + + if (gst_msdk_context_get_job_type (thiz->context) & GST_MSDK_JOB_ENCODER) { + GstMsdkContext *parent_context; + + parent_context = thiz->context; + thiz->context = gst_msdk_context_new_with_parent (parent_context); + gst_object_unref (parent_context); + + GST_INFO_OBJECT (thiz, + "Creating new context %" GST_PTR_FORMAT " with joined session", + thiz->context); + } else { + gst_msdk_context_add_job_type (thiz->context, GST_MSDK_JOB_ENCODER); + } + } else { + gst_msdk_context_ensure_context (GST_ELEMENT_CAST (thiz), thiz->hardware, + GST_MSDK_JOB_ENCODER); + + GST_INFO_OBJECT (thiz, "Creating new context %" GST_PTR_FORMAT, + thiz->context); + } + /* Set the minimum pts to some huge value (1000 hours). This keeps the dts at the start of the stream from needing to be negative. */ @@ -1136,6 +1178,8 @@ gst_msdkenc_stop (GstVideoEncoder * encoder) gst_video_codec_state_unref (thiz->input_state); thiz->input_state = NULL; + gst_object_replace ((GstObject **) & thiz->context, NULL); + return TRUE; } @@ -1360,6 +1404,8 @@ gst_msdkenc_class_init (GstMsdkEncClass * klass) gobject_class->get_property = gst_msdkenc_get_property; gobject_class->finalize = gst_msdkenc_finalize; + element_class->set_context = gst_msdkenc_set_context; + gstencoder_class->set_format = GST_DEBUG_FUNCPTR (gst_msdkenc_set_format); gstencoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_msdkenc_handle_frame); gstencoder_class->start = GST_DEBUG_FUNCPTR (gst_msdkenc_start); diff --git a/sys/msdk/gstmsdkenc.h b/sys/msdk/gstmsdkenc.h index ae4f94c21..d59158587 100644 --- a/sys/msdk/gstmsdkenc.h +++ b/sys/msdk/gstmsdkenc.h @@ -91,6 +91,7 @@ struct _GstMsdkEnc GstBufferPool *msdk_converted_pool; GstVideoInfo aligned_info; gboolean use_video_memory; + gboolean initialized; /* element properties */ gboolean hardware; -- cgit v1.2.1