mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 11:41:09 +00:00
nvdecoder: Add support for reconfiguration
Instead of creating new decoder instance per new sequence, re-use configured decoder instance via cuvidReconfigureDecoder() API. It will make output surface reusable without re-allocation. Also, in order for application to be able to reserve higher resolution output surface, "init-max-width" and "init-max-height" properties are added to each decoder. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3884>
This commit is contained in:
parent
eb0fca4180
commit
f831b92540
11 changed files with 565 additions and 33 deletions
|
@ -56,6 +56,8 @@ typedef struct _GstnvdecCuvidVTable
|
||||||
unsigned int reserved_flags);
|
unsigned int reserved_flags);
|
||||||
CUresult (CUDAAPI * CuvidCreateDecoder) (CUvideodecoder * phDecoder,
|
CUresult (CUDAAPI * CuvidCreateDecoder) (CUvideodecoder * phDecoder,
|
||||||
CUVIDDECODECREATEINFO * pdci);
|
CUVIDDECODECREATEINFO * pdci);
|
||||||
|
CUresult (CUDAAPI * CuvidReconfigureDecoder) (CUvideodecoder phDecoder,
|
||||||
|
CUVIDRECONFIGUREDECODERINFO * pDecReconfigParams);
|
||||||
CUresult (CUDAAPI * CuvidDestroyDecoder) (CUvideodecoder hDecoder);
|
CUresult (CUDAAPI * CuvidDestroyDecoder) (CUvideodecoder hDecoder);
|
||||||
CUresult (CUDAAPI * CuvidDecodePicture) (CUvideodecoder hDecoder,
|
CUresult (CUDAAPI * CuvidDecodePicture) (CUvideodecoder hDecoder,
|
||||||
CUVIDPICPARAMS * pPicParams);
|
CUVIDPICPARAMS * pPicParams);
|
||||||
|
@ -97,6 +99,7 @@ gst_cuvid_load_library (guint api_major_ver, guint api_minor_ver)
|
||||||
LOAD_SYMBOL (cuvidCtxLock, CuvidCtxLock, TRUE);
|
LOAD_SYMBOL (cuvidCtxLock, CuvidCtxLock, TRUE);
|
||||||
LOAD_SYMBOL (cuvidCtxUnlock, CuvidCtxUnlock, TRUE);
|
LOAD_SYMBOL (cuvidCtxUnlock, CuvidCtxUnlock, TRUE);
|
||||||
LOAD_SYMBOL (cuvidCreateDecoder, CuvidCreateDecoder, TRUE);
|
LOAD_SYMBOL (cuvidCreateDecoder, CuvidCreateDecoder, TRUE);
|
||||||
|
LOAD_SYMBOL (cuvidReconfigureDecoder, CuvidReconfigureDecoder, FALSE);
|
||||||
LOAD_SYMBOL (cuvidDestroyDecoder, CuvidDestroyDecoder, TRUE);
|
LOAD_SYMBOL (cuvidDestroyDecoder, CuvidDestroyDecoder, TRUE);
|
||||||
LOAD_SYMBOL (cuvidDecodePicture, CuvidDecodePicture, TRUE);
|
LOAD_SYMBOL (cuvidDecodePicture, CuvidDecodePicture, TRUE);
|
||||||
LOAD_SYMBOL (cuvidCreateVideoParser, CuvidCreateVideoParser, TRUE);
|
LOAD_SYMBOL (cuvidCreateVideoParser, CuvidCreateVideoParser, TRUE);
|
||||||
|
@ -142,6 +145,15 @@ gst_cuvid_can_get_decoder_caps (void)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_cuvid_can_reconfigure (void)
|
||||||
|
{
|
||||||
|
if (gst_cuvid_vtable.CuvidReconfigureDecoder)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
CUresult CUDAAPI
|
CUresult CUDAAPI
|
||||||
CuvidCtxLockCreate (CUvideoctxlock * pLock, CUcontext ctx)
|
CuvidCtxLockCreate (CUvideoctxlock * pLock, CUcontext ctx)
|
||||||
{
|
{
|
||||||
|
@ -182,6 +194,16 @@ CuvidCreateDecoder (CUvideodecoder * phDecoder, CUVIDDECODECREATEINFO * pdci)
|
||||||
return gst_cuvid_vtable.CuvidCreateDecoder (phDecoder, pdci);
|
return gst_cuvid_vtable.CuvidCreateDecoder (phDecoder, pdci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUresult CUDAAPI
|
||||||
|
CuvidReconfigureDecoder (CUvideodecoder hDecoder,
|
||||||
|
CUVIDRECONFIGUREDECODERINFO * pDecReconfigParams)
|
||||||
|
{
|
||||||
|
g_assert (gst_cuvid_vtable.CuvidReconfigureDecoder != NULL);
|
||||||
|
|
||||||
|
return gst_cuvid_vtable.CuvidReconfigureDecoder (hDecoder,
|
||||||
|
pDecReconfigParams);
|
||||||
|
}
|
||||||
|
|
||||||
CUresult CUDAAPI
|
CUresult CUDAAPI
|
||||||
CuvidDestroyDecoder (CUvideodecoder hDecoder)
|
CuvidDestroyDecoder (CUvideodecoder hDecoder)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,6 +35,8 @@ gboolean gst_cuvid_get_api_version (guint * api_major_ver,
|
||||||
|
|
||||||
gboolean gst_cuvid_can_get_decoder_caps (void);
|
gboolean gst_cuvid_can_get_decoder_caps (void);
|
||||||
|
|
||||||
|
gboolean gst_cuvid_can_reconfigure (void);
|
||||||
|
|
||||||
CUresult CUDAAPI CuvidCtxLockCreate (CUvideoctxlock * pLock,
|
CUresult CUDAAPI CuvidCtxLockCreate (CUvideoctxlock * pLock,
|
||||||
CUcontext ctx);
|
CUcontext ctx);
|
||||||
|
|
||||||
|
@ -49,6 +51,9 @@ CUresult CUDAAPI CuvidCtxUnlock (CUvideoctxlock lck,
|
||||||
CUresult CUDAAPI CuvidCreateDecoder (CUvideodecoder * phDecoder,
|
CUresult CUDAAPI CuvidCreateDecoder (CUvideodecoder * phDecoder,
|
||||||
CUVIDDECODECREATEINFO * pdci);
|
CUVIDDECODECREATEINFO * pdci);
|
||||||
|
|
||||||
|
CUresult CUDAAPI CuvidReconfigureDecoder (CUvideodecoder hDecoder,
|
||||||
|
CUVIDRECONFIGUREDECODERINFO * pDecReconfigParams);
|
||||||
|
|
||||||
CUresult CUDAAPI CuvidDestroyDecoder (CUvideodecoder hDecoder);
|
CUresult CUDAAPI CuvidDestroyDecoder (CUvideodecoder hDecoder);
|
||||||
|
|
||||||
CUresult CUDAAPI CuvidDecodePicture (CUvideodecoder hDecoder,
|
CUresult CUDAAPI CuvidDecodePicture (CUvideodecoder hDecoder,
|
||||||
|
|
|
@ -71,12 +71,16 @@ typedef struct _GstNvAV1Dec
|
||||||
guint8 film_grain_params_present;
|
guint8 film_grain_params_present;
|
||||||
|
|
||||||
guint num_output_surfaces;
|
guint num_output_surfaces;
|
||||||
|
guint init_max_width;
|
||||||
|
guint init_max_height;
|
||||||
} GstNvAV1Dec;
|
} GstNvAV1Dec;
|
||||||
|
|
||||||
typedef struct _GstNvAV1DecClass
|
typedef struct _GstNvAV1DecClass
|
||||||
{
|
{
|
||||||
GstAV1DecoderClass parent_class;
|
GstAV1DecoderClass parent_class;
|
||||||
guint cuda_device_id;
|
guint cuda_device_id;
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
} GstNvAV1DecClass;
|
} GstNvAV1DecClass;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -84,6 +88,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_CUDA_DEVICE_ID,
|
PROP_CUDA_DEVICE_ID,
|
||||||
PROP_NUM_OUTPUT_SURFACES,
|
PROP_NUM_OUTPUT_SURFACES,
|
||||||
|
PROP_INIT_MAX_WIDTH,
|
||||||
|
PROP_INIT_MAX_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
||||||
|
@ -163,6 +169,38 @@ gst_nv_av1_dec_class_init (GstNvAV1DecClass * klass,
|
||||||
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvAV1Dec:init-max-width:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxWidth value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_WIDTH,
|
||||||
|
g_param_spec_uint ("init-max-width", "Initial Maximum Width",
|
||||||
|
"Expected maximum coded width of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_width, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvAV1Dec:init-max-height:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxHeight value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_HEIGHT,
|
||||||
|
g_param_spec_uint ("init-max-height", "Initial Maximum Height",
|
||||||
|
"Expected maximum coded height of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_height, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_av1_dec_set_context);
|
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_av1_dec_set_context);
|
||||||
|
|
||||||
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
||||||
|
@ -204,6 +242,8 @@ gst_nv_av1_dec_class_init (GstNvAV1DecClass * klass,
|
||||||
GST_DEBUG_FUNCPTR (gst_nv_av1_dec_get_preferred_output_delay);
|
GST_DEBUG_FUNCPTR (gst_nv_av1_dec_get_preferred_output_delay);
|
||||||
|
|
||||||
klass->cuda_device_id = cdata->cuda_device_id;
|
klass->cuda_device_id = cdata->cuda_device_id;
|
||||||
|
klass->max_width = cdata->max_width;
|
||||||
|
klass->max_height = cdata->max_height;
|
||||||
|
|
||||||
gst_caps_unref (cdata->sink_caps);
|
gst_caps_unref (cdata->sink_caps);
|
||||||
gst_caps_unref (cdata->src_caps);
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
@ -226,6 +266,12 @@ gst_nv_av1_dec_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
self->num_output_surfaces = g_value_get_uint (value);
|
self->num_output_surfaces = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
self->init_max_width = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
self->init_max_height = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -246,6 +292,12 @@ gst_nv_av1_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
g_value_set_uint (value, self->num_output_surfaces);
|
g_value_set_uint (value, self->num_output_surfaces);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
g_value_set_uint (value, self->init_max_width);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
g_value_set_uint (value, self->init_max_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -421,6 +473,7 @@ gst_nv_av1_dec_new_sequence (GstAV1Decoder * decoder,
|
||||||
const GstAV1SequenceHeaderOBU * seq_hdr, gint max_dpb_size)
|
const GstAV1SequenceHeaderOBU * seq_hdr, gint max_dpb_size)
|
||||||
{
|
{
|
||||||
GstNvAV1Dec *self = GST_NV_AV1_DEC (decoder);
|
GstNvAV1Dec *self = GST_NV_AV1_DEC (decoder);
|
||||||
|
GstNvAV1DecClass *klass = GST_NV_AV1_DEC_GET_CLASS (self);
|
||||||
gboolean modified = FALSE;
|
gboolean modified = FALSE;
|
||||||
guint max_width, max_height;
|
guint max_width, max_height;
|
||||||
|
|
||||||
|
@ -480,10 +533,15 @@ gst_nv_av1_dec_new_sequence (GstAV1Decoder * decoder,
|
||||||
out_format, GST_ROUND_UP_2 (self->max_width),
|
out_format, GST_ROUND_UP_2 (self->max_width),
|
||||||
GST_ROUND_UP_2 (self->max_height));
|
GST_ROUND_UP_2 (self->max_height));
|
||||||
|
|
||||||
|
max_width = gst_nv_decoder_get_max_output_size (self->max_width,
|
||||||
|
self->init_max_width, klass->max_width);
|
||||||
|
max_height = gst_nv_decoder_get_max_output_size (self->max_height,
|
||||||
|
self->init_max_height, klass->max_height);
|
||||||
|
|
||||||
if (!gst_nv_decoder_configure (self->decoder, cudaVideoCodec_AV1,
|
if (!gst_nv_decoder_configure (self->decoder, cudaVideoCodec_AV1,
|
||||||
&info, self->max_width, self->max_height, self->bitdepth,
|
&info, self->max_width, self->max_height, self->bitdepth,
|
||||||
max_dpb_size, self->film_grain_params_present ? TRUE : FALSE,
|
max_dpb_size, self->film_grain_params_present ? TRUE : FALSE,
|
||||||
self->num_output_surfaces)) {
|
self->num_output_surfaces, max_width, max_height)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to create decoder");
|
GST_ERROR_OBJECT (self, "Failed to create decoder");
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
@ -985,6 +1043,8 @@ gst_nv_av1_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
gchar *type_name;
|
gchar *type_name;
|
||||||
gchar *feature_name;
|
gchar *feature_name;
|
||||||
guint index = 0;
|
guint index = 0;
|
||||||
|
const GValue *value;
|
||||||
|
GstStructure *s;
|
||||||
GTypeInfo type_info = {
|
GTypeInfo type_info = {
|
||||||
sizeof (GstNvAV1DecClass),
|
sizeof (GstNvAV1DecClass),
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1001,6 +1061,14 @@ gst_nv_av1_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_nv_av1_dec_debug, "nvav1dec", 0, "nvav1dec");
|
GST_DEBUG_CATEGORY_INIT (gst_nv_av1_dec_debug, "nvav1dec", 0, "nvav1dec");
|
||||||
|
|
||||||
cdata = g_new0 (GstNvDecoderClassData, 1);
|
cdata = g_new0 (GstNvDecoderClassData, 1);
|
||||||
|
|
||||||
|
s = gst_caps_get_structure (sink_caps, 0);
|
||||||
|
value = gst_structure_get_value (s, "width");
|
||||||
|
cdata->max_width = (guint) gst_value_get_int_range_max (value);
|
||||||
|
|
||||||
|
value = gst_structure_get_value (s, "height");
|
||||||
|
cdata->max_height = (guint) gst_value_get_int_range_max (value);
|
||||||
|
|
||||||
cdata->sink_caps = gst_caps_ref (sink_caps);
|
cdata->sink_caps = gst_caps_ref (sink_caps);
|
||||||
cdata->src_caps = gst_caps_ref (src_caps);
|
cdata->src_caps = gst_caps_ref (src_caps);
|
||||||
cdata->cuda_device_id = device_id;
|
cdata->cuda_device_id = device_id;
|
||||||
|
|
|
@ -38,13 +38,14 @@ extern "C"
|
||||||
#define GST_CAT_DEFAULT gst_nv_decoder_debug
|
#define GST_CAT_DEFAULT gst_nv_decoder_debug
|
||||||
|
|
||||||
GST_DEFINE_MINI_OBJECT_TYPE (GstNvDecSurface, gst_nv_dec_surface);
|
GST_DEFINE_MINI_OBJECT_TYPE (GstNvDecSurface, gst_nv_dec_surface);
|
||||||
static GstNvDecSurface *gst_nv_dec_surface_new (void);
|
static GstNvDecSurface *gst_nv_dec_surface_new (guint seq_num);
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
struct GstNvDecOutput
|
struct GstNvDecOutput
|
||||||
{
|
{
|
||||||
GstNvDecObject *self = nullptr;
|
GstNvDecObject *self = nullptr;
|
||||||
CUdeviceptr devptr = 0;
|
CUdeviceptr devptr = 0;
|
||||||
|
guint seq_num = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GstNvDecObjectPrivate
|
struct GstNvDecObjectPrivate
|
||||||
|
@ -76,6 +77,8 @@ struct _GstNvDecObject
|
||||||
guint pool_size;
|
guint pool_size;
|
||||||
guint num_mapped;
|
guint num_mapped;
|
||||||
gboolean alloc_aux_frame;
|
gboolean alloc_aux_frame;
|
||||||
|
guint plane_height;
|
||||||
|
guint seq_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void gst_nv_dec_object_finalize (GObject * object);
|
static void gst_nv_dec_object_finalize (GObject * object);
|
||||||
|
@ -160,9 +163,10 @@ gst_nv_dec_object_new (GstCudaContext * context,
|
||||||
self->create_info = *create_info;
|
self->create_info = *create_info;
|
||||||
self->video_info = *video_info;
|
self->video_info = *video_info;
|
||||||
self->pool_size = pool_size;
|
self->pool_size = pool_size;
|
||||||
|
self->plane_height = create_info->ulTargetHeight;
|
||||||
|
|
||||||
for (guint i = 0; i < pool_size; i++) {
|
for (guint i = 0; i < pool_size; i++) {
|
||||||
GstNvDecSurface *surf = gst_nv_dec_surface_new ();
|
GstNvDecSurface *surf = gst_nv_dec_surface_new (0);
|
||||||
|
|
||||||
surf->index = i;
|
surf->index = i;
|
||||||
|
|
||||||
|
@ -180,6 +184,73 @@ gst_nv_dec_object_new (GstCudaContext * context,
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_nv_dec_object_reconfigure (GstNvDecObject * object,
|
||||||
|
CUVIDRECONFIGUREDECODERINFO * reconfigure_info,
|
||||||
|
const GstVideoInfo * video_info, gboolean alloc_aux_frame)
|
||||||
|
{
|
||||||
|
GstNvDecObjectPrivate *priv = object->priv;
|
||||||
|
CUresult ret;
|
||||||
|
guint pool_size;
|
||||||
|
|
||||||
|
if (!gst_cuvid_can_reconfigure ())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pool_size = reconfigure_info->ulNumDecodeSurfaces;
|
||||||
|
if (alloc_aux_frame)
|
||||||
|
pool_size /= 2;
|
||||||
|
|
||||||
|
std::lock_guard < std::mutex > lk (priv->lock);
|
||||||
|
if (!gst_cuda_context_push (object->context)) {
|
||||||
|
GST_ERROR_OBJECT (object, "Couldn't push context");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = CuvidReconfigureDecoder (object->handle, reconfigure_info);
|
||||||
|
gst_cuda_context_pop (nullptr);
|
||||||
|
|
||||||
|
if (!gst_cuda_result (ret)) {
|
||||||
|
GST_ERROR_OBJECT (object, "Couldn't reconfigure decoder");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((guint) priv->surface_queue.size () != object->pool_size) {
|
||||||
|
GST_WARNING_OBJECT (object, "Unused surfaces %u != pool size %u",
|
||||||
|
(guint) priv->surface_queue.size (), object->pool_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release old surfaces and create new ones */
|
||||||
|
/* *INDENT-OFF* */
|
||||||
|
for (auto it : priv->surface_queue)
|
||||||
|
gst_nv_dec_surface_unref (it);
|
||||||
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
|
priv->surface_queue.clear ();
|
||||||
|
|
||||||
|
object->pool_size = pool_size;
|
||||||
|
object->video_info = *video_info;
|
||||||
|
object->seq_num++;
|
||||||
|
object->plane_height = reconfigure_info->ulTargetHeight;
|
||||||
|
|
||||||
|
for (guint i = 0; i < pool_size; i++) {
|
||||||
|
GstNvDecSurface *surf = gst_nv_dec_surface_new (object->seq_num);
|
||||||
|
|
||||||
|
surf->index = i;
|
||||||
|
|
||||||
|
/* [0, pool_size - 1]: output picture
|
||||||
|
* [pool_size, pool_size * 2 - 1]: decoder output without film-grain,
|
||||||
|
* used for reference picture */
|
||||||
|
if (alloc_aux_frame)
|
||||||
|
surf->decode_frame_index = i + pool_size;
|
||||||
|
else
|
||||||
|
surf->decode_frame_index = i;
|
||||||
|
|
||||||
|
object->priv->surface_queue.push_back (surf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_nv_dec_object_set_flushing (GstNvDecObject * object, gboolean flushing)
|
gst_nv_dec_object_set_flushing (GstNvDecObject * object, gboolean flushing)
|
||||||
{
|
{
|
||||||
|
@ -381,7 +452,7 @@ gst_nv_dec_object_export_surface (GstNvDecObject * object,
|
||||||
|
|
||||||
GST_LOG_OBJECT (object, "Exporting surface %d", surface->index);
|
GST_LOG_OBJECT (object, "Exporting surface %d", surface->index);
|
||||||
|
|
||||||
offset = surface->pitch * object->create_info.ulTargetHeight;
|
offset = surface->pitch * object->plane_height;
|
||||||
|
|
||||||
info = object->video_info;
|
info = object->video_info;
|
||||||
switch (GST_VIDEO_INFO_FORMAT (&info)) {
|
switch (GST_VIDEO_INFO_FORMAT (&info)) {
|
||||||
|
@ -431,11 +502,21 @@ gst_nv_dec_object_export_surface (GstNvDecObject * object,
|
||||||
GST_LOG_OBJECT (object, "Waiting for output release");
|
GST_LOG_OBJECT (object, "Waiting for output release");
|
||||||
priv->cond.wait (lk);
|
priv->cond.wait (lk);
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
|
output = (GstNvDecOutput *)
|
||||||
|
gst_cuda_memory_get_user_data (GST_CUDA_MEMORY_CAST (mem));
|
||||||
|
if (output->seq_num != object->seq_num) {
|
||||||
|
GST_DEBUG_OBJECT (object,
|
||||||
|
"output belongs to previous sequence, need new memory");
|
||||||
|
gst_memory_unref (mem);
|
||||||
|
mem = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mem) {
|
if (!mem) {
|
||||||
output = new GstNvDecOutput ();
|
output = new GstNvDecOutput ();
|
||||||
output->devptr = surface->devptr;
|
output->devptr = surface->devptr;
|
||||||
|
output->seq_num = object->seq_num;
|
||||||
|
|
||||||
GST_LOG_OBJECT (object, "New output, allocating memory");
|
GST_LOG_OBJECT (object, "New output, allocating memory");
|
||||||
|
|
||||||
|
@ -469,6 +550,7 @@ gst_nv_dec_surface_dispose (GstNvDecSurface * surf)
|
||||||
{
|
{
|
||||||
GstNvDecObject *object;
|
GstNvDecObject *object;
|
||||||
GstNvDecObjectPrivate *priv;
|
GstNvDecObjectPrivate *priv;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
if (!surf->object)
|
if (!surf->object)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -476,34 +558,44 @@ gst_nv_dec_surface_dispose (GstNvDecSurface * surf)
|
||||||
object = (GstNvDecObject *) g_steal_pointer (&surf->object);
|
object = (GstNvDecObject *) g_steal_pointer (&surf->object);
|
||||||
priv = object->priv;
|
priv = object->priv;
|
||||||
|
|
||||||
/* Back to surface queue */
|
|
||||||
gst_nv_dec_surface_ref (surf);
|
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
{
|
{
|
||||||
std::lock_guard < std::mutex > lk (priv->lock);
|
std::lock_guard < std::mutex > lk (priv->lock);
|
||||||
/* Keep sorted order */
|
|
||||||
priv->surface_queue.insert (
|
if (surf->seq_num == object->seq_num) {
|
||||||
std::upper_bound (priv->surface_queue.begin (),
|
/* Back to surface queue */
|
||||||
priv->surface_queue.end(), surf,
|
gst_nv_dec_surface_ref (surf);
|
||||||
[] (const GstNvDecSurface * a, const GstNvDecSurface * b)
|
|
||||||
{
|
/* Keep sorted order */
|
||||||
return a->index < b->index;
|
priv->surface_queue.insert (
|
||||||
}), surf);
|
std::upper_bound (priv->surface_queue.begin (),
|
||||||
priv->cond.notify_all ();
|
priv->surface_queue.end(), surf,
|
||||||
|
[] (const GstNvDecSurface * a, const GstNvDecSurface * b)
|
||||||
|
{
|
||||||
|
return a->index < b->index;
|
||||||
|
}), surf);
|
||||||
|
priv->cond.notify_all ();
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (object, "Releasing surface %p of previous sequence",
|
||||||
|
surf);
|
||||||
|
/* Shouldn't happen (e.g., surfaces were not flushed before reconfigure) */
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* *INDENT-ON* */
|
/* *INDENT-ON* */
|
||||||
|
|
||||||
gst_object_unref (object);
|
gst_object_unref (object);
|
||||||
|
|
||||||
return FALSE;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstNvDecSurface *
|
static GstNvDecSurface *
|
||||||
gst_nv_dec_surface_new (void)
|
gst_nv_dec_surface_new (guint seq_num)
|
||||||
{
|
{
|
||||||
GstNvDecSurface *surf = g_new0 (GstNvDecSurface, 1);
|
GstNvDecSurface *surf = g_new0 (GstNvDecSurface, 1);
|
||||||
|
|
||||||
|
surf->seq_num = seq_num;
|
||||||
|
|
||||||
gst_mini_object_init (GST_MINI_OBJECT_CAST (surf),
|
gst_mini_object_init (GST_MINI_OBJECT_CAST (surf),
|
||||||
0, GST_TYPE_NV_DEC_SURFACE, nullptr,
|
0, GST_TYPE_NV_DEC_SURFACE, nullptr,
|
||||||
(GstMiniObjectDisposeFunction) gst_nv_dec_surface_dispose,
|
(GstMiniObjectDisposeFunction) gst_nv_dec_surface_dispose,
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct _GstNvDecSurface
|
||||||
|
|
||||||
CUdeviceptr devptr;
|
CUdeviceptr devptr;
|
||||||
guint pitch;
|
guint pitch;
|
||||||
|
|
||||||
|
guint seq_num;
|
||||||
};
|
};
|
||||||
|
|
||||||
GstNvDecObject * gst_nv_dec_object_new (GstCudaContext * context,
|
GstNvDecObject * gst_nv_dec_object_new (GstCudaContext * context,
|
||||||
|
@ -51,6 +53,11 @@ GstNvDecObject * gst_nv_dec_object_new (GstCudaContext * context,
|
||||||
const GstVideoInfo * video_info,
|
const GstVideoInfo * video_info,
|
||||||
gboolean alloc_aux_frame);
|
gboolean alloc_aux_frame);
|
||||||
|
|
||||||
|
gboolean gst_nv_dec_object_reconfigure (GstNvDecObject * object,
|
||||||
|
CUVIDRECONFIGUREDECODERINFO * reconfigure_info,
|
||||||
|
const GstVideoInfo * video_info,
|
||||||
|
gboolean alloc_aux_frame);
|
||||||
|
|
||||||
void gst_nv_dec_object_set_flushing (GstNvDecObject * object,
|
void gst_nv_dec_object_set_flushing (GstNvDecObject * object,
|
||||||
gboolean flushing);
|
gboolean flushing);
|
||||||
|
|
||||||
|
|
|
@ -242,10 +242,10 @@ gboolean
|
||||||
gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
||||||
GstVideoInfo * info, gint coded_width, gint coded_height,
|
GstVideoInfo * info, gint coded_width, gint coded_height,
|
||||||
guint coded_bitdepth, guint pool_size, gboolean alloc_aux_frame,
|
guint coded_bitdepth, guint pool_size, gboolean alloc_aux_frame,
|
||||||
guint num_output_surfaces)
|
guint num_output_surfaces, guint init_max_width, guint init_max_height)
|
||||||
{
|
{
|
||||||
CUVIDDECODECREATEINFO create_info = { 0, };
|
CUVIDDECODECREATEINFO create_info = { 0, };
|
||||||
GstVideoFormat format;
|
GstVideoFormat format, prev_format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||||
guint alloc_size;
|
guint alloc_size;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_NV_DECODER (decoder), FALSE);
|
g_return_val_if_fail (GST_IS_NV_DECODER (decoder), FALSE);
|
||||||
|
@ -256,15 +256,9 @@ gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
||||||
g_return_val_if_fail (coded_bitdepth >= 8, FALSE);
|
g_return_val_if_fail (coded_bitdepth >= 8, FALSE);
|
||||||
g_return_val_if_fail (pool_size > 0, FALSE);
|
g_return_val_if_fail (pool_size > 0, FALSE);
|
||||||
|
|
||||||
g_mutex_lock (&decoder->lock);
|
|
||||||
gst_nv_decoder_reset_unlocked (decoder);
|
|
||||||
g_mutex_unlock (&decoder->lock);
|
|
||||||
|
|
||||||
decoder->info = *info;
|
|
||||||
gst_video_info_set_format (&decoder->coded_info, GST_VIDEO_INFO_FORMAT (info),
|
|
||||||
coded_width, coded_height);
|
|
||||||
|
|
||||||
format = GST_VIDEO_INFO_FORMAT (info);
|
format = GST_VIDEO_INFO_FORMAT (info);
|
||||||
|
if (decoder->info.finfo)
|
||||||
|
prev_format = GST_VIDEO_INFO_FORMAT (&decoder->info);
|
||||||
|
|
||||||
/* Additional 2 frame margin */
|
/* Additional 2 frame margin */
|
||||||
pool_size += 2;
|
pool_size += 2;
|
||||||
|
@ -278,6 +272,56 @@ gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
||||||
alloc_size = pool_size;
|
alloc_size = pool_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decoder->info = *info;
|
||||||
|
gst_video_info_set_format (&decoder->coded_info, format,
|
||||||
|
coded_width, coded_height);
|
||||||
|
|
||||||
|
g_mutex_lock (&decoder->lock);
|
||||||
|
if (decoder->object) {
|
||||||
|
GST_DEBUG_OBJECT (decoder,
|
||||||
|
"Configured max resolution %ux%u %s (bit-depth %u), "
|
||||||
|
"new resolution %ux%u %s (bit-depth %u)",
|
||||||
|
(guint) decoder->create_info.ulMaxWidth,
|
||||||
|
(guint) decoder->create_info.ulMaxHeight,
|
||||||
|
gst_video_format_to_string (prev_format),
|
||||||
|
(guint) decoder->create_info.bitDepthMinus8 + 8,
|
||||||
|
(guint) coded_width, (guint) coded_height,
|
||||||
|
gst_video_format_to_string (format), coded_bitdepth);
|
||||||
|
|
||||||
|
if (format == prev_format &&
|
||||||
|
(guint) coded_width <= decoder->create_info.ulMaxWidth &&
|
||||||
|
(guint) coded_height <= decoder->create_info.ulMaxHeight &&
|
||||||
|
coded_bitdepth == (guint) decoder->create_info.bitDepthMinus8 + 8) {
|
||||||
|
CUVIDRECONFIGUREDECODERINFO reconfig_info = { 0, };
|
||||||
|
|
||||||
|
reconfig_info.ulWidth = GST_VIDEO_INFO_WIDTH (&decoder->coded_info);
|
||||||
|
reconfig_info.ulHeight = GST_VIDEO_INFO_HEIGHT (&decoder->coded_info);
|
||||||
|
reconfig_info.ulTargetWidth = GST_VIDEO_INFO_WIDTH (info);
|
||||||
|
reconfig_info.ulTargetHeight = GST_VIDEO_INFO_HEIGHT (info);
|
||||||
|
reconfig_info.ulNumDecodeSurfaces = alloc_size;
|
||||||
|
reconfig_info.display_area.right = GST_VIDEO_INFO_WIDTH (info);
|
||||||
|
reconfig_info.display_area.bottom = GST_VIDEO_INFO_HEIGHT (info);
|
||||||
|
reconfig_info.target_rect.right = GST_VIDEO_INFO_WIDTH (info);
|
||||||
|
reconfig_info.target_rect.bottom = GST_VIDEO_INFO_HEIGHT (info);
|
||||||
|
|
||||||
|
if (gst_nv_dec_object_reconfigure (decoder->object,
|
||||||
|
&reconfig_info, info, alloc_aux_frame)) {
|
||||||
|
GST_DEBUG_OBJECT (decoder, "Reconfigured");
|
||||||
|
decoder->configured = TRUE;
|
||||||
|
g_mutex_unlock (&decoder->lock);
|
||||||
|
return TRUE;
|
||||||
|
} else {
|
||||||
|
GST_WARNING_OBJECT (decoder,
|
||||||
|
"Couldn't reconfigure decoder, creating new decoder instance");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (decoder, "Need new decoder instance");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_nv_decoder_reset_unlocked (decoder);
|
||||||
|
g_mutex_unlock (&decoder->lock);
|
||||||
|
|
||||||
decoder->num_output_surfaces = num_output_surfaces;
|
decoder->num_output_surfaces = num_output_surfaces;
|
||||||
|
|
||||||
create_info.ulWidth = GST_VIDEO_INFO_WIDTH (&decoder->coded_info);
|
create_info.ulWidth = GST_VIDEO_INFO_WIDTH (&decoder->coded_info);
|
||||||
|
@ -306,6 +350,9 @@ gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
||||||
create_info.target_rect.right = GST_VIDEO_INFO_WIDTH (info);
|
create_info.target_rect.right = GST_VIDEO_INFO_WIDTH (info);
|
||||||
create_info.target_rect.bottom = GST_VIDEO_INFO_HEIGHT (info);
|
create_info.target_rect.bottom = GST_VIDEO_INFO_HEIGHT (info);
|
||||||
|
|
||||||
|
create_info.ulMaxWidth = MAX (create_info.ulWidth, init_max_width);
|
||||||
|
create_info.ulMaxHeight = MAX (create_info.ulHeight, init_max_height);
|
||||||
|
|
||||||
decoder->create_info = create_info;
|
decoder->create_info = create_info;
|
||||||
decoder->configured = TRUE;
|
decoder->configured = TRUE;
|
||||||
|
|
||||||
|
@ -1609,3 +1656,15 @@ gst_nv_decoder_reset (GstNvDecoder * decoder)
|
||||||
gst_nv_decoder_reset_unlocked (decoder);
|
gst_nv_decoder_reset_unlocked (decoder);
|
||||||
g_mutex_unlock (&decoder->lock);
|
g_mutex_unlock (&decoder->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
guint
|
||||||
|
gst_nv_decoder_get_max_output_size (guint coded_size, guint user_requested,
|
||||||
|
guint device_max)
|
||||||
|
{
|
||||||
|
if (user_requested <= coded_size)
|
||||||
|
return coded_size;
|
||||||
|
|
||||||
|
user_requested = GST_ROUND_UP_16 (user_requested);
|
||||||
|
|
||||||
|
return MIN (user_requested, device_max);
|
||||||
|
}
|
||||||
|
|
|
@ -37,6 +37,8 @@ typedef struct _GstNvDecoderClassData
|
||||||
GstCaps *sink_caps;
|
GstCaps *sink_caps;
|
||||||
GstCaps *src_caps;
|
GstCaps *src_caps;
|
||||||
guint cuda_device_id;
|
guint cuda_device_id;
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
} GstNvDecoderClassData;
|
} GstNvDecoderClassData;
|
||||||
|
|
||||||
GstNvDecoder * gst_nv_decoder_new (GstCudaContext * context);
|
GstNvDecoder * gst_nv_decoder_new (GstCudaContext * context);
|
||||||
|
@ -51,7 +53,9 @@ gboolean gst_nv_decoder_configure (GstNvDecoder * decoder,
|
||||||
guint coded_bitdepth,
|
guint coded_bitdepth,
|
||||||
guint pool_size,
|
guint pool_size,
|
||||||
gboolean alloc_aux_frame,
|
gboolean alloc_aux_frame,
|
||||||
guint num_output_surfaces);
|
guint num_output_surfaces,
|
||||||
|
guint init_max_width,
|
||||||
|
guint init_max_height);
|
||||||
|
|
||||||
GstFlowReturn gst_nv_decoder_acquire_surface (GstNvDecoder * decoder,
|
GstFlowReturn gst_nv_decoder_acquire_surface (GstNvDecoder * decoder,
|
||||||
GstNvDecSurface ** surface);
|
GstNvDecSurface ** surface);
|
||||||
|
@ -95,6 +99,10 @@ gboolean gst_nv_decoder_decide_allocation (GstNvDecoder * decoder,
|
||||||
GstVideoDecoder * videodec,
|
GstVideoDecoder * videodec,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
|
||||||
|
guint gst_nv_decoder_get_max_output_size (guint coded_size,
|
||||||
|
guint user_requested,
|
||||||
|
guint device_max);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_NV_DECODER_H__ */
|
#endif /* __GST_NV_DECODER_H__ */
|
||||||
|
|
|
@ -127,12 +127,16 @@ typedef struct _GstNvH264Dec
|
||||||
GArray *ref_list;
|
GArray *ref_list;
|
||||||
|
|
||||||
guint num_output_surfaces;
|
guint num_output_surfaces;
|
||||||
|
guint init_max_width;
|
||||||
|
guint init_max_height;
|
||||||
} GstNvH264Dec;
|
} GstNvH264Dec;
|
||||||
|
|
||||||
typedef struct _GstNvH264DecClass
|
typedef struct _GstNvH264DecClass
|
||||||
{
|
{
|
||||||
GstH264DecoderClass parent_class;
|
GstH264DecoderClass parent_class;
|
||||||
guint cuda_device_id;
|
guint cuda_device_id;
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
} GstNvH264DecClass;
|
} GstNvH264DecClass;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -140,6 +144,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_CUDA_DEVICE_ID,
|
PROP_CUDA_DEVICE_ID,
|
||||||
PROP_NUM_OUTPUT_SURFACES,
|
PROP_NUM_OUTPUT_SURFACES,
|
||||||
|
PROP_INIT_MAX_WIDTH,
|
||||||
|
PROP_INIT_MAX_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
||||||
|
@ -232,6 +238,38 @@ gst_nv_h264_dec_class_init (GstNvH264DecClass * klass,
|
||||||
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvH264SLDec:init-max-width:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxWidth value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_WIDTH,
|
||||||
|
g_param_spec_uint ("init-max-width", "Initial Maximum Width",
|
||||||
|
"Expected maximum coded width of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_width, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvH264SLDec:init-max-height:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxHeight value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_HEIGHT,
|
||||||
|
g_param_spec_uint ("init-max-height", "Initial Maximum Height",
|
||||||
|
"Expected maximum coded height of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_height, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_h264_dec_set_context);
|
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_h264_dec_set_context);
|
||||||
|
|
||||||
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
||||||
|
@ -274,6 +312,8 @@ gst_nv_h264_dec_class_init (GstNvH264DecClass * klass,
|
||||||
GST_DEBUG_FUNCPTR (gst_nv_h264_dec_get_preferred_output_delay);
|
GST_DEBUG_FUNCPTR (gst_nv_h264_dec_get_preferred_output_delay);
|
||||||
|
|
||||||
klass->cuda_device_id = cdata->cuda_device_id;
|
klass->cuda_device_id = cdata->cuda_device_id;
|
||||||
|
klass->max_width = cdata->max_width;
|
||||||
|
klass->max_height = cdata->max_height;
|
||||||
|
|
||||||
gst_caps_unref (cdata->sink_caps);
|
gst_caps_unref (cdata->sink_caps);
|
||||||
gst_caps_unref (cdata->src_caps);
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
@ -311,6 +351,12 @@ gst_nv_h264_dec_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
self->num_output_surfaces = g_value_get_uint (value);
|
self->num_output_surfaces = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
self->init_max_width = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
self->init_max_height = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -331,6 +377,12 @@ gst_nv_h264_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
g_value_set_uint (value, self->num_output_surfaces);
|
g_value_set_uint (value, self->num_output_surfaces);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
g_value_set_uint (value, self->init_max_width);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
g_value_set_uint (value, self->init_max_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -507,9 +559,11 @@ gst_nv_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
|
||||||
gint max_dpb_size)
|
gint max_dpb_size)
|
||||||
{
|
{
|
||||||
GstNvH264Dec *self = GST_NV_H264_DEC (decoder);
|
GstNvH264Dec *self = GST_NV_H264_DEC (decoder);
|
||||||
|
GstNvH264DecClass *klass = GST_NV_H264_DEC_GET_CLASS (self);
|
||||||
guint crop_width, crop_height;
|
guint crop_width, crop_height;
|
||||||
gboolean modified = FALSE;
|
gboolean modified = FALSE;
|
||||||
gboolean interlaced;
|
gboolean interlaced;
|
||||||
|
guint max_width, max_height;
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "new sequence");
|
GST_LOG_OBJECT (self, "new sequence");
|
||||||
|
|
||||||
|
@ -587,10 +641,16 @@ gst_nv_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
|
||||||
GST_VIDEO_INFO_INTERLACE_MODE (&info) = GST_VIDEO_INTERLACE_MODE_MIXED;
|
GST_VIDEO_INFO_INTERLACE_MODE (&info) = GST_VIDEO_INTERLACE_MODE_MIXED;
|
||||||
|
|
||||||
self->max_dpb_size = max_dpb_size;
|
self->max_dpb_size = max_dpb_size;
|
||||||
|
max_width = gst_nv_decoder_get_max_output_size (self->coded_width,
|
||||||
|
self->init_max_width, klass->max_width);
|
||||||
|
max_height = gst_nv_decoder_get_max_output_size (self->coded_height,
|
||||||
|
self->init_max_height, klass->max_height);
|
||||||
|
|
||||||
/* FIXME: add support cudaVideoCodec_H264_SVC and cudaVideoCodec_H264_MVC */
|
/* FIXME: add support cudaVideoCodec_H264_SVC and cudaVideoCodec_H264_MVC */
|
||||||
if (!gst_nv_decoder_configure (self->decoder,
|
if (!gst_nv_decoder_configure (self->decoder,
|
||||||
cudaVideoCodec_H264, &info, self->coded_width, self->coded_height,
|
cudaVideoCodec_H264, &info, self->coded_width, self->coded_height,
|
||||||
self->bitdepth, max_dpb_size, FALSE, self->num_output_surfaces)) {
|
self->bitdepth, max_dpb_size, FALSE, self->num_output_surfaces,
|
||||||
|
max_width, max_height)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
@ -1064,9 +1124,11 @@ gst_nv_h264_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
|
|
||||||
s = gst_caps_get_structure (sink_caps, 0);
|
s = gst_caps_get_structure (sink_caps, 0);
|
||||||
value = gst_structure_get_value (s, "width");
|
value = gst_structure_get_value (s, "width");
|
||||||
|
cdata->max_width = (guint) gst_value_get_int_range_max (value);
|
||||||
gst_caps_set_value (cdata->sink_caps, "width", value);
|
gst_caps_set_value (cdata->sink_caps, "width", value);
|
||||||
|
|
||||||
value = gst_structure_get_value (s, "height");
|
value = gst_structure_get_value (s, "height");
|
||||||
|
cdata->max_height = (guint) gst_value_get_int_range_max (value);
|
||||||
gst_caps_set_value (cdata->sink_caps, "height", value);
|
gst_caps_set_value (cdata->sink_caps, "height", value);
|
||||||
|
|
||||||
GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
|
GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
|
||||||
|
|
|
@ -123,12 +123,16 @@ typedef struct _GstNvH265Dec
|
||||||
guint chroma_format_idc;
|
guint chroma_format_idc;
|
||||||
|
|
||||||
guint num_output_surfaces;
|
guint num_output_surfaces;
|
||||||
|
guint init_max_width;
|
||||||
|
guint init_max_height;
|
||||||
} GstNvH265Dec;
|
} GstNvH265Dec;
|
||||||
|
|
||||||
typedef struct _GstNvH265DecClass
|
typedef struct _GstNvH265DecClass
|
||||||
{
|
{
|
||||||
GstH265DecoderClass parent_class;
|
GstH265DecoderClass parent_class;
|
||||||
guint cuda_device_id;
|
guint cuda_device_id;
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
} GstNvH265DecClass;
|
} GstNvH265DecClass;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -136,6 +140,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_CUDA_DEVICE_ID,
|
PROP_CUDA_DEVICE_ID,
|
||||||
PROP_NUM_OUTPUT_SURFACES,
|
PROP_NUM_OUTPUT_SURFACES,
|
||||||
|
PROP_INIT_MAX_WIDTH,
|
||||||
|
PROP_INIT_MAX_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
||||||
|
@ -223,6 +229,38 @@ gst_nv_h265_dec_class_init (GstNvH265DecClass * klass,
|
||||||
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvH265SLDec:init-max-width:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxWidth value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_WIDTH,
|
||||||
|
g_param_spec_uint ("init-max-width", "Initial Maximum Width",
|
||||||
|
"Expected maximum coded width of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_width, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvH265SLDec:init-max-height:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxHeight value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_HEIGHT,
|
||||||
|
g_param_spec_uint ("init-max-height", "Initial Maximum Height",
|
||||||
|
"Expected maximum coded height of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_height, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_set_context);
|
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_h265_dec_set_context);
|
||||||
|
|
||||||
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
||||||
|
@ -263,6 +301,8 @@ gst_nv_h265_dec_class_init (GstNvH265DecClass * klass,
|
||||||
GST_DEBUG_FUNCPTR (gst_nv_h265_dec_get_preferred_output_delay);
|
GST_DEBUG_FUNCPTR (gst_nv_h265_dec_get_preferred_output_delay);
|
||||||
|
|
||||||
klass->cuda_device_id = cdata->cuda_device_id;
|
klass->cuda_device_id = cdata->cuda_device_id;
|
||||||
|
klass->max_width = cdata->max_width;
|
||||||
|
klass->max_height = cdata->max_height;
|
||||||
|
|
||||||
gst_caps_unref (cdata->sink_caps);
|
gst_caps_unref (cdata->sink_caps);
|
||||||
gst_caps_unref (cdata->src_caps);
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
@ -285,6 +325,12 @@ gst_nv_h265_dec_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
self->num_output_surfaces = g_value_get_uint (value);
|
self->num_output_surfaces = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
self->init_max_width = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
self->init_max_height = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -305,6 +351,12 @@ gst_nv_h265_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
g_value_set_uint (value, self->num_output_surfaces);
|
g_value_set_uint (value, self->num_output_surfaces);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
g_value_set_uint (value, self->init_max_width);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
g_value_set_uint (value, self->init_max_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -465,8 +517,10 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
|
||||||
gint max_dpb_size)
|
gint max_dpb_size)
|
||||||
{
|
{
|
||||||
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
||||||
|
GstNvH265DecClass *klass = GST_NV_H265_DEC_GET_CLASS (self);
|
||||||
guint crop_width, crop_height;
|
guint crop_width, crop_height;
|
||||||
gboolean modified = FALSE;
|
gboolean modified = FALSE;
|
||||||
|
guint max_width, max_height;
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "new sequence");
|
GST_LOG_OBJECT (self, "new sequence");
|
||||||
|
|
||||||
|
@ -541,9 +595,15 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
|
||||||
gst_video_info_set_format (&info, out_format, GST_ROUND_UP_2 (self->width),
|
gst_video_info_set_format (&info, out_format, GST_ROUND_UP_2 (self->width),
|
||||||
GST_ROUND_UP_2 (self->height));
|
GST_ROUND_UP_2 (self->height));
|
||||||
|
|
||||||
|
max_width = gst_nv_decoder_get_max_output_size (self->coded_width,
|
||||||
|
self->init_max_width, klass->max_width);
|
||||||
|
max_height = gst_nv_decoder_get_max_output_size (self->coded_height,
|
||||||
|
self->init_max_height, klass->max_height);
|
||||||
|
|
||||||
if (!gst_nv_decoder_configure (self->decoder,
|
if (!gst_nv_decoder_configure (self->decoder,
|
||||||
cudaVideoCodec_HEVC, &info, self->coded_width, self->coded_height,
|
cudaVideoCodec_HEVC, &info, self->coded_width, self->coded_height,
|
||||||
self->bitdepth, max_dpb_size, FALSE, self->num_output_surfaces)) {
|
self->bitdepth, max_dpb_size, FALSE, self->num_output_surfaces,
|
||||||
|
max_width, max_height)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
@ -1081,6 +1141,8 @@ gst_nv_h265_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
gint index = 0;
|
gint index = 0;
|
||||||
GValue value_list = G_VALUE_INIT;
|
GValue value_list = G_VALUE_INIT;
|
||||||
GValue value = G_VALUE_INIT;
|
GValue value = G_VALUE_INIT;
|
||||||
|
GstStructure *s;
|
||||||
|
const GValue *res_val;
|
||||||
GTypeInfo type_info = {
|
GTypeInfo type_info = {
|
||||||
sizeof (GstNvH265DecClass),
|
sizeof (GstNvH265DecClass),
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -1098,6 +1160,13 @@ gst_nv_h265_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
cdata = g_new0 (GstNvDecoderClassData, 1);
|
cdata = g_new0 (GstNvDecoderClassData, 1);
|
||||||
cdata->sink_caps = gst_caps_copy (sink_caps);
|
cdata->sink_caps = gst_caps_copy (sink_caps);
|
||||||
|
|
||||||
|
s = gst_caps_get_structure (sink_caps, 0);
|
||||||
|
res_val = gst_structure_get_value (s, "width");
|
||||||
|
cdata->max_width = (guint) gst_value_get_int_range_max (res_val);
|
||||||
|
|
||||||
|
res_val = gst_structure_get_value (s, "height");
|
||||||
|
cdata->max_height = (guint) gst_value_get_int_range_max (res_val);
|
||||||
|
|
||||||
/* Update stream-format since we support packetized format as well */
|
/* Update stream-format since we support packetized format as well */
|
||||||
g_value_init (&value_list, GST_TYPE_LIST);
|
g_value_init (&value_list, GST_TYPE_LIST);
|
||||||
g_value_init (&value, G_TYPE_STRING);
|
g_value_init (&value, G_TYPE_STRING);
|
||||||
|
|
|
@ -55,12 +55,16 @@ typedef struct _GstNvVp8Dec
|
||||||
guint width, height;
|
guint width, height;
|
||||||
|
|
||||||
guint num_output_surfaces;
|
guint num_output_surfaces;
|
||||||
|
guint init_max_width;
|
||||||
|
guint init_max_height;
|
||||||
} GstNvVp8Dec;
|
} GstNvVp8Dec;
|
||||||
|
|
||||||
typedef struct _GstNvVp8DecClass
|
typedef struct _GstNvVp8DecClass
|
||||||
{
|
{
|
||||||
GstVp8DecoderClass parent_class;
|
GstVp8DecoderClass parent_class;
|
||||||
guint cuda_device_id;
|
guint cuda_device_id;
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
} GstNvVp8DecClass;
|
} GstNvVp8DecClass;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -68,6 +72,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_CUDA_DEVICE_ID,
|
PROP_CUDA_DEVICE_ID,
|
||||||
PROP_NUM_OUTPUT_SURFACES,
|
PROP_NUM_OUTPUT_SURFACES,
|
||||||
|
PROP_INIT_MAX_WIDTH,
|
||||||
|
PROP_INIT_MAX_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
||||||
|
@ -149,6 +155,38 @@ gst_nv_vp8_dec_class_init (GstNvVp8DecClass * klass,
|
||||||
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvVp8SLDec:init-max-width:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxWidth value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_WIDTH,
|
||||||
|
g_param_spec_uint ("init-max-width", "Initial Maximum Width",
|
||||||
|
"Expected maximum coded width of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_width, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvVp8SLDec:init-max-height:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxHeight value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_HEIGHT,
|
||||||
|
g_param_spec_uint ("init-max-height", "Initial Maximum Height",
|
||||||
|
"Expected maximum coded height of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_height, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_set_context);
|
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_set_context);
|
||||||
|
|
||||||
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
||||||
|
@ -185,6 +223,8 @@ gst_nv_vp8_dec_class_init (GstNvVp8DecClass * klass,
|
||||||
GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_get_preferred_output_delay);
|
GST_DEBUG_FUNCPTR (gst_nv_vp8_dec_get_preferred_output_delay);
|
||||||
|
|
||||||
klass->cuda_device_id = cdata->cuda_device_id;
|
klass->cuda_device_id = cdata->cuda_device_id;
|
||||||
|
klass->max_width = cdata->max_width;
|
||||||
|
klass->max_height = cdata->max_height;
|
||||||
|
|
||||||
gst_caps_unref (cdata->sink_caps);
|
gst_caps_unref (cdata->sink_caps);
|
||||||
gst_caps_unref (cdata->src_caps);
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
@ -207,6 +247,12 @@ gst_nv_vp8_dec_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
self->num_output_surfaces = g_value_get_uint (value);
|
self->num_output_surfaces = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
self->init_max_width = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
self->init_max_height = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -227,6 +273,12 @@ gst_nv_vp8_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
g_value_set_uint (value, self->num_output_surfaces);
|
g_value_set_uint (value, self->num_output_surfaces);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
g_value_set_uint (value, self->init_max_width);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
g_value_set_uint (value, self->init_max_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -381,7 +433,9 @@ gst_nv_vp8_dec_new_sequence (GstVp8Decoder * decoder,
|
||||||
const GstVp8FrameHdr * frame_hdr, gint max_dpb_size)
|
const GstVp8FrameHdr * frame_hdr, gint max_dpb_size)
|
||||||
{
|
{
|
||||||
GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
|
GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
|
||||||
|
GstNvVp8DecClass *klass = GST_NV_VP8_DEC_GET_CLASS (self);
|
||||||
gboolean modified = FALSE;
|
gboolean modified = FALSE;
|
||||||
|
guint max_width, max_height;
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "new sequence");
|
GST_LOG_OBJECT (self, "new sequence");
|
||||||
|
|
||||||
|
@ -404,9 +458,15 @@ gst_nv_vp8_dec_new_sequence (GstVp8Decoder * decoder,
|
||||||
GST_VIDEO_FORMAT_NV12, GST_ROUND_UP_2 (self->width),
|
GST_VIDEO_FORMAT_NV12, GST_ROUND_UP_2 (self->width),
|
||||||
GST_ROUND_UP_2 (self->height));
|
GST_ROUND_UP_2 (self->height));
|
||||||
|
|
||||||
|
max_width = gst_nv_decoder_get_max_output_size (self->width,
|
||||||
|
self->init_max_width, klass->max_width);
|
||||||
|
max_height = gst_nv_decoder_get_max_output_size (self->height,
|
||||||
|
self->init_max_height, klass->max_height);
|
||||||
|
|
||||||
if (!gst_nv_decoder_configure (self->decoder,
|
if (!gst_nv_decoder_configure (self->decoder,
|
||||||
cudaVideoCodec_VP8, &info, self->width, self->height, 8,
|
cudaVideoCodec_VP8, &info, self->width, self->height, 8,
|
||||||
max_dpb_size, FALSE, self->num_output_surfaces)) {
|
max_dpb_size, FALSE, self->num_output_surfaces, max_width,
|
||||||
|
max_height)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
@ -600,6 +660,8 @@ gst_nv_vp8_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
gchar *feature_name;
|
gchar *feature_name;
|
||||||
GstNvDecoderClassData *cdata;
|
GstNvDecoderClassData *cdata;
|
||||||
gint index = 0;
|
gint index = 0;
|
||||||
|
const GValue *value;
|
||||||
|
GstStructure *s;
|
||||||
GTypeInfo type_info = {
|
GTypeInfo type_info = {
|
||||||
sizeof (GstNvVp8DecClass),
|
sizeof (GstNvVp8DecClass),
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -615,6 +677,14 @@ gst_nv_vp8_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_nv_vp8_dec_debug, "nvvp8dec", 0, "nvvp8dec");
|
GST_DEBUG_CATEGORY_INIT (gst_nv_vp8_dec_debug, "nvvp8dec", 0, "nvvp8dec");
|
||||||
|
|
||||||
cdata = g_new0 (GstNvDecoderClassData, 1);
|
cdata = g_new0 (GstNvDecoderClassData, 1);
|
||||||
|
|
||||||
|
s = gst_caps_get_structure (sink_caps, 0);
|
||||||
|
value = gst_structure_get_value (s, "width");
|
||||||
|
cdata->max_width = (guint) gst_value_get_int_range_max (value);
|
||||||
|
|
||||||
|
value = gst_structure_get_value (s, "height");
|
||||||
|
cdata->max_height = (guint) gst_value_get_int_range_max (value);
|
||||||
|
|
||||||
cdata->sink_caps = gst_caps_ref (sink_caps);
|
cdata->sink_caps = gst_caps_ref (sink_caps);
|
||||||
cdata->src_caps = gst_caps_ref (src_caps);
|
cdata->src_caps = gst_caps_ref (src_caps);
|
||||||
cdata->cuda_device_id = device_id;
|
cdata->cuda_device_id = device_id;
|
||||||
|
|
|
@ -56,12 +56,16 @@ typedef struct _GstNvVp9Dec
|
||||||
GstVP9Profile profile;
|
GstVP9Profile profile;
|
||||||
|
|
||||||
guint num_output_surfaces;
|
guint num_output_surfaces;
|
||||||
|
guint init_max_width;
|
||||||
|
guint init_max_height;
|
||||||
} GstNvVp9Dec;
|
} GstNvVp9Dec;
|
||||||
|
|
||||||
typedef struct _GstNvVp9DecClass
|
typedef struct _GstNvVp9DecClass
|
||||||
{
|
{
|
||||||
GstVp9DecoderClass parent_class;
|
GstVp9DecoderClass parent_class;
|
||||||
guint cuda_device_id;
|
guint cuda_device_id;
|
||||||
|
guint max_width;
|
||||||
|
guint max_height;
|
||||||
} GstNvVp9DecClass;
|
} GstNvVp9DecClass;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -69,6 +73,8 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_CUDA_DEVICE_ID,
|
PROP_CUDA_DEVICE_ID,
|
||||||
PROP_NUM_OUTPUT_SURFACES,
|
PROP_NUM_OUTPUT_SURFACES,
|
||||||
|
PROP_INIT_MAX_WIDTH,
|
||||||
|
PROP_INIT_MAX_HEIGHT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
#define DEFAULT_NUM_OUTPUT_SURFACES 0
|
||||||
|
@ -152,6 +158,38 @@ gst_nv_vp9_dec_class_init (GstNvVp9DecClass * klass,
|
||||||
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
G_PARAM_STATIC_STRINGS)));
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvVp9SLDec:init-max-width:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxWidth value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_WIDTH,
|
||||||
|
g_param_spec_uint ("init-max-width", "Initial Maximum Width",
|
||||||
|
"Expected maximum coded width of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_width, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstNvVp9SLDec:init-max-height:
|
||||||
|
*
|
||||||
|
* Initial CUVIDDECODECREATEINFO.ulMaxHeight value
|
||||||
|
*
|
||||||
|
* Since: 1.24
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (object_class, PROP_INIT_MAX_HEIGHT,
|
||||||
|
g_param_spec_uint ("init-max-height", "Initial Maximum Height",
|
||||||
|
"Expected maximum coded height of stream. This value is used to "
|
||||||
|
"pre-allocate higher dimension of output surfaces than "
|
||||||
|
"that of input stream, in order to help decoder reconfiguration",
|
||||||
|
0, cdata->max_height, 0,
|
||||||
|
(GParamFlags) (GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
|
||||||
|
G_PARAM_STATIC_STRINGS)));
|
||||||
|
|
||||||
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_vp9_dec_set_context);
|
element_class->set_context = GST_DEBUG_FUNCPTR (gst_nv_vp9_dec_set_context);
|
||||||
|
|
||||||
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
|
||||||
|
@ -190,6 +228,8 @@ gst_nv_vp9_dec_class_init (GstNvVp9DecClass * klass,
|
||||||
GST_DEBUG_FUNCPTR (gst_nv_vp9_dec_get_preferred_output_delay);
|
GST_DEBUG_FUNCPTR (gst_nv_vp9_dec_get_preferred_output_delay);
|
||||||
|
|
||||||
klass->cuda_device_id = cdata->cuda_device_id;
|
klass->cuda_device_id = cdata->cuda_device_id;
|
||||||
|
klass->max_width = cdata->max_width;
|
||||||
|
klass->max_height = cdata->max_height;
|
||||||
|
|
||||||
gst_caps_unref (cdata->sink_caps);
|
gst_caps_unref (cdata->sink_caps);
|
||||||
gst_caps_unref (cdata->src_caps);
|
gst_caps_unref (cdata->src_caps);
|
||||||
|
@ -212,6 +252,12 @@ gst_nv_vp9_dec_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
self->num_output_surfaces = g_value_get_uint (value);
|
self->num_output_surfaces = g_value_get_uint (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
self->init_max_width = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
self->init_max_height = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -232,6 +278,12 @@ gst_nv_vp9_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
||||||
case PROP_NUM_OUTPUT_SURFACES:
|
case PROP_NUM_OUTPUT_SURFACES:
|
||||||
g_value_set_uint (value, self->num_output_surfaces);
|
g_value_set_uint (value, self->num_output_surfaces);
|
||||||
break;
|
break;
|
||||||
|
case PROP_INIT_MAX_WIDTH:
|
||||||
|
g_value_set_uint (value, self->init_max_width);
|
||||||
|
break;
|
||||||
|
case PROP_INIT_MAX_HEIGHT:
|
||||||
|
g_value_set_uint (value, self->init_max_height);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -391,8 +443,10 @@ gst_nv_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
||||||
const GstVp9FrameHeader * frame_hdr, gint max_dpb_size)
|
const GstVp9FrameHeader * frame_hdr, gint max_dpb_size)
|
||||||
{
|
{
|
||||||
GstNvVp9Dec *self = GST_NV_VP9_DEC (decoder);
|
GstNvVp9Dec *self = GST_NV_VP9_DEC (decoder);
|
||||||
|
GstNvVp9DecClass *klass = GST_NV_VP9_DEC_GET_CLASS (self);
|
||||||
GstVideoFormat out_format = GST_VIDEO_FORMAT_UNKNOWN;
|
GstVideoFormat out_format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||||
GstVideoInfo info;
|
GstVideoInfo info;
|
||||||
|
guint max_width, max_height;
|
||||||
|
|
||||||
GST_LOG_OBJECT (self, "new sequence");
|
GST_LOG_OBJECT (self, "new sequence");
|
||||||
|
|
||||||
|
@ -417,10 +471,16 @@ gst_nv_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
||||||
|
|
||||||
gst_video_info_set_format (&info, out_format, GST_ROUND_UP_2 (self->width),
|
gst_video_info_set_format (&info, out_format, GST_ROUND_UP_2 (self->width),
|
||||||
GST_ROUND_UP_2 (self->height));
|
GST_ROUND_UP_2 (self->height));
|
||||||
|
|
||||||
|
max_width = gst_nv_decoder_get_max_output_size (self->width,
|
||||||
|
self->init_max_width, klass->max_width);
|
||||||
|
max_height = gst_nv_decoder_get_max_output_size (self->height,
|
||||||
|
self->init_max_height, klass->max_height);
|
||||||
|
|
||||||
if (!gst_nv_decoder_configure (self->decoder,
|
if (!gst_nv_decoder_configure (self->decoder,
|
||||||
cudaVideoCodec_VP9, &info, self->width, self->height,
|
cudaVideoCodec_VP9, &info, self->width, self->height,
|
||||||
frame_hdr->bit_depth, max_dpb_size, FALSE,
|
frame_hdr->bit_depth, max_dpb_size, FALSE,
|
||||||
self->num_output_surfaces)) {
|
self->num_output_surfaces, max_width, max_height)) {
|
||||||
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
GST_ERROR_OBJECT (self, "Failed to configure decoder");
|
||||||
return GST_FLOW_NOT_NEGOTIATED;
|
return GST_FLOW_NOT_NEGOTIATED;
|
||||||
}
|
}
|
||||||
|
@ -696,6 +756,8 @@ gst_nv_vp9_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
gchar *feature_name;
|
gchar *feature_name;
|
||||||
GstNvDecoderClassData *cdata;
|
GstNvDecoderClassData *cdata;
|
||||||
gint index = 0;
|
gint index = 0;
|
||||||
|
const GValue *value;
|
||||||
|
GstStructure *s;
|
||||||
GTypeInfo type_info = {
|
GTypeInfo type_info = {
|
||||||
sizeof (GstNvVp9DecClass),
|
sizeof (GstNvVp9DecClass),
|
||||||
nullptr,
|
nullptr,
|
||||||
|
@ -711,6 +773,14 @@ gst_nv_vp9_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_nv_vp9_dec_debug, "nvvp9dec", 0, "nvvp9dec");
|
GST_DEBUG_CATEGORY_INIT (gst_nv_vp9_dec_debug, "nvvp9dec", 0, "nvvp9dec");
|
||||||
|
|
||||||
cdata = g_new0 (GstNvDecoderClassData, 1);
|
cdata = g_new0 (GstNvDecoderClassData, 1);
|
||||||
|
|
||||||
|
s = gst_caps_get_structure (sink_caps, 0);
|
||||||
|
value = gst_structure_get_value (s, "width");
|
||||||
|
cdata->max_width = (guint) gst_value_get_int_range_max (value);
|
||||||
|
|
||||||
|
value = gst_structure_get_value (s, "height");
|
||||||
|
cdata->max_height = (guint) gst_value_get_int_range_max (value);
|
||||||
|
|
||||||
cdata->sink_caps = gst_caps_copy (sink_caps);
|
cdata->sink_caps = gst_caps_copy (sink_caps);
|
||||||
gst_caps_set_simple (cdata->sink_caps,
|
gst_caps_set_simple (cdata->sink_caps,
|
||||||
"alignment", G_TYPE_STRING, "frame", nullptr);
|
"alignment", G_TYPE_STRING, "frame", nullptr);
|
||||||
|
|
Loading…
Reference in a new issue