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
This commit is contained in:
Hyunjun Ko 2018-02-13 13:51:18 -09:00 committed by Sreerenj Balachandran
parent dc82ccb9a2
commit f2b35abcab
4 changed files with 133 additions and 33 deletions

View file

@ -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,21 +250,20 @@ gst_msdkdec_init_decoder (GstMsdkDec * thiz)
mfxStatus status;
mfxFrameAllocRequest request;
if (thiz->initialized)
return TRUE;
if (!thiz->context) {
GST_WARNING_OBJECT (thiz, "No MSDK Context");
return FALSE;
}
if (!thiz->input_state) {
GST_DEBUG_OBJECT (thiz, "Have no input state yet");
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");
return FALSE;
}
GST_OBJECT_LOCK (thiz);
if (thiz->use_video_memory) {
@ -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);

View file

@ -67,6 +67,7 @@ struct _GstMsdkDec
GstVideoInfo pool_info;
mfxFrameAllocResponse alloc_resp;
gboolean use_video_memory;
gboolean initialized;
/* MFX context */
GstMsdkContext *context;

View file

@ -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,21 +175,20 @@ gst_msdkenc_init_encoder (GstMsdkEnc * thiz)
mfxFrameAllocRequest request[2];
guint i;
if (thiz->initialized)
return TRUE;
if (!thiz->context) {
GST_WARNING_OBJECT (thiz, "No MSDK Context");
return FALSE;
}
if (!thiz->input_state) {
GST_DEBUG_OBJECT (thiz, "Have no input state yet");
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");
return FALSE;
}
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);

View file

@ -91,6 +91,7 @@ struct _GstMsdkEnc
GstBufferPool *msdk_converted_pool;
GstVideoInfo aligned_info;
gboolean use_video_memory;
gboolean initialized;
/* element properties */
gboolean hardware;