mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-22 17:51:16 +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);
|
||||
CUresult (CUDAAPI * CuvidCreateDecoder) (CUvideodecoder * phDecoder,
|
||||
CUVIDDECODECREATEINFO * pdci);
|
||||
CUresult (CUDAAPI * CuvidReconfigureDecoder) (CUvideodecoder phDecoder,
|
||||
CUVIDRECONFIGUREDECODERINFO * pDecReconfigParams);
|
||||
CUresult (CUDAAPI * CuvidDestroyDecoder) (CUvideodecoder hDecoder);
|
||||
CUresult (CUDAAPI * CuvidDecodePicture) (CUvideodecoder hDecoder,
|
||||
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 (cuvidCtxUnlock, CuvidCtxUnlock, TRUE);
|
||||
LOAD_SYMBOL (cuvidCreateDecoder, CuvidCreateDecoder, TRUE);
|
||||
LOAD_SYMBOL (cuvidReconfigureDecoder, CuvidReconfigureDecoder, FALSE);
|
||||
LOAD_SYMBOL (cuvidDestroyDecoder, CuvidDestroyDecoder, TRUE);
|
||||
LOAD_SYMBOL (cuvidDecodePicture, CuvidDecodePicture, TRUE);
|
||||
LOAD_SYMBOL (cuvidCreateVideoParser, CuvidCreateVideoParser, TRUE);
|
||||
|
@ -142,6 +145,15 @@ gst_cuvid_can_get_decoder_caps (void)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_cuvid_can_reconfigure (void)
|
||||
{
|
||||
if (gst_cuvid_vtable.CuvidReconfigureDecoder)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CUresult CUDAAPI
|
||||
CuvidCtxLockCreate (CUvideoctxlock * pLock, CUcontext ctx)
|
||||
{
|
||||
|
@ -182,6 +194,16 @@ CuvidCreateDecoder (CUvideodecoder * phDecoder, CUVIDDECODECREATEINFO * 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
|
||||
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_reconfigure (void);
|
||||
|
||||
CUresult CUDAAPI CuvidCtxLockCreate (CUvideoctxlock * pLock,
|
||||
CUcontext ctx);
|
||||
|
||||
|
@ -49,6 +51,9 @@ CUresult CUDAAPI CuvidCtxUnlock (CUvideoctxlock lck,
|
|||
CUresult CUDAAPI CuvidCreateDecoder (CUvideodecoder * phDecoder,
|
||||
CUVIDDECODECREATEINFO * pdci);
|
||||
|
||||
CUresult CUDAAPI CuvidReconfigureDecoder (CUvideodecoder hDecoder,
|
||||
CUVIDRECONFIGUREDECODERINFO * pDecReconfigParams);
|
||||
|
||||
CUresult CUDAAPI CuvidDestroyDecoder (CUvideodecoder hDecoder);
|
||||
|
||||
CUresult CUDAAPI CuvidDecodePicture (CUvideodecoder hDecoder,
|
||||
|
|
|
@ -71,12 +71,16 @@ typedef struct _GstNvAV1Dec
|
|||
guint8 film_grain_params_present;
|
||||
|
||||
guint num_output_surfaces;
|
||||
guint init_max_width;
|
||||
guint init_max_height;
|
||||
} GstNvAV1Dec;
|
||||
|
||||
typedef struct _GstNvAV1DecClass
|
||||
{
|
||||
GstAV1DecoderClass parent_class;
|
||||
guint cuda_device_id;
|
||||
guint max_width;
|
||||
guint max_height;
|
||||
} GstNvAV1DecClass;
|
||||
|
||||
enum
|
||||
|
@ -84,6 +88,8 @@ enum
|
|||
PROP_0,
|
||||
PROP_CUDA_DEVICE_ID,
|
||||
PROP_NUM_OUTPUT_SURFACES,
|
||||
PROP_INIT_MAX_WIDTH,
|
||||
PROP_INIT_MAX_HEIGHT,
|
||||
};
|
||||
|
||||
#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 |
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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->src_caps);
|
||||
|
@ -226,6 +266,12 @@ gst_nv_av1_dec_set_property (GObject * object, guint prop_id,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
self->num_output_surfaces = g_value_get_uint (value);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -246,6 +292,12 @@ gst_nv_av1_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
g_value_set_uint (value, self->num_output_surfaces);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -421,6 +473,7 @@ gst_nv_av1_dec_new_sequence (GstAV1Decoder * decoder,
|
|||
const GstAV1SequenceHeaderOBU * seq_hdr, gint max_dpb_size)
|
||||
{
|
||||
GstNvAV1Dec *self = GST_NV_AV1_DEC (decoder);
|
||||
GstNvAV1DecClass *klass = GST_NV_AV1_DEC_GET_CLASS (self);
|
||||
gboolean modified = FALSE;
|
||||
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),
|
||||
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,
|
||||
&info, self->max_width, self->max_height, self->bitdepth,
|
||||
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");
|
||||
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 *feature_name;
|
||||
guint index = 0;
|
||||
const GValue *value;
|
||||
GstStructure *s;
|
||||
GTypeInfo type_info = {
|
||||
sizeof (GstNvAV1DecClass),
|
||||
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");
|
||||
|
||||
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->src_caps = gst_caps_ref (src_caps);
|
||||
cdata->cuda_device_id = device_id;
|
||||
|
|
|
@ -38,13 +38,14 @@ extern "C"
|
|||
#define GST_CAT_DEFAULT gst_nv_decoder_debug
|
||||
|
||||
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* */
|
||||
struct GstNvDecOutput
|
||||
{
|
||||
GstNvDecObject *self = nullptr;
|
||||
CUdeviceptr devptr = 0;
|
||||
guint seq_num = 0;
|
||||
};
|
||||
|
||||
struct GstNvDecObjectPrivate
|
||||
|
@ -76,6 +77,8 @@ struct _GstNvDecObject
|
|||
guint pool_size;
|
||||
guint num_mapped;
|
||||
gboolean alloc_aux_frame;
|
||||
guint plane_height;
|
||||
guint seq_num;
|
||||
};
|
||||
|
||||
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->video_info = *video_info;
|
||||
self->pool_size = pool_size;
|
||||
self->plane_height = create_info->ulTargetHeight;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -180,6 +184,73 @@ gst_nv_dec_object_new (GstCudaContext * context,
|
|||
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
|
||||
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);
|
||||
|
||||
offset = surface->pitch * object->create_info.ulTargetHeight;
|
||||
offset = surface->pitch * object->plane_height;
|
||||
|
||||
info = object->video_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");
|
||||
priv->cond.wait (lk);
|
||||
} 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) {
|
||||
output = new GstNvDecOutput ();
|
||||
output->devptr = surface->devptr;
|
||||
output->seq_num = object->seq_num;
|
||||
|
||||
GST_LOG_OBJECT (object, "New output, allocating memory");
|
||||
|
||||
|
@ -469,6 +550,7 @@ gst_nv_dec_surface_dispose (GstNvDecSurface * surf)
|
|||
{
|
||||
GstNvDecObject *object;
|
||||
GstNvDecObjectPrivate *priv;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
if (!surf->object)
|
||||
return TRUE;
|
||||
|
@ -476,34 +558,44 @@ gst_nv_dec_surface_dispose (GstNvDecSurface * surf)
|
|||
object = (GstNvDecObject *) g_steal_pointer (&surf->object);
|
||||
priv = object->priv;
|
||||
|
||||
/* Back to surface queue */
|
||||
gst_nv_dec_surface_ref (surf);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
{
|
||||
std::lock_guard < std::mutex > lk (priv->lock);
|
||||
/* Keep sorted order */
|
||||
priv->surface_queue.insert (
|
||||
std::upper_bound (priv->surface_queue.begin (),
|
||||
priv->surface_queue.end(), surf,
|
||||
[] (const GstNvDecSurface * a, const GstNvDecSurface * b)
|
||||
{
|
||||
return a->index < b->index;
|
||||
}), surf);
|
||||
priv->cond.notify_all ();
|
||||
|
||||
if (surf->seq_num == object->seq_num) {
|
||||
/* Back to surface queue */
|
||||
gst_nv_dec_surface_ref (surf);
|
||||
|
||||
/* Keep sorted order */
|
||||
priv->surface_queue.insert (
|
||||
std::upper_bound (priv->surface_queue.begin (),
|
||||
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* */
|
||||
|
||||
gst_object_unref (object);
|
||||
|
||||
return FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstNvDecSurface *
|
||||
gst_nv_dec_surface_new (void)
|
||||
gst_nv_dec_surface_new (guint seq_num)
|
||||
{
|
||||
GstNvDecSurface *surf = g_new0 (GstNvDecSurface, 1);
|
||||
|
||||
surf->seq_num = seq_num;
|
||||
|
||||
gst_mini_object_init (GST_MINI_OBJECT_CAST (surf),
|
||||
0, GST_TYPE_NV_DEC_SURFACE, nullptr,
|
||||
(GstMiniObjectDisposeFunction) gst_nv_dec_surface_dispose,
|
||||
|
|
|
@ -44,6 +44,8 @@ struct _GstNvDecSurface
|
|||
|
||||
CUdeviceptr devptr;
|
||||
guint pitch;
|
||||
|
||||
guint seq_num;
|
||||
};
|
||||
|
||||
GstNvDecObject * gst_nv_dec_object_new (GstCudaContext * context,
|
||||
|
@ -51,6 +53,11 @@ GstNvDecObject * gst_nv_dec_object_new (GstCudaContext * context,
|
|||
const GstVideoInfo * video_info,
|
||||
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,
|
||||
gboolean flushing);
|
||||
|
||||
|
|
|
@ -242,10 +242,10 @@ gboolean
|
|||
gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
||||
GstVideoInfo * info, gint coded_width, gint coded_height,
|
||||
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, };
|
||||
GstVideoFormat format;
|
||||
GstVideoFormat format, prev_format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
guint alloc_size;
|
||||
|
||||
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 (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);
|
||||
if (decoder->info.finfo)
|
||||
prev_format = GST_VIDEO_INFO_FORMAT (&decoder->info);
|
||||
|
||||
/* Additional 2 frame margin */
|
||||
pool_size += 2;
|
||||
|
@ -278,6 +272,56 @@ gst_nv_decoder_configure (GstNvDecoder * decoder, cudaVideoCodec codec,
|
|||
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;
|
||||
|
||||
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.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->configured = TRUE;
|
||||
|
||||
|
@ -1609,3 +1656,15 @@ gst_nv_decoder_reset (GstNvDecoder * decoder)
|
|||
gst_nv_decoder_reset_unlocked (decoder);
|
||||
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 *src_caps;
|
||||
guint cuda_device_id;
|
||||
guint max_width;
|
||||
guint max_height;
|
||||
} GstNvDecoderClassData;
|
||||
|
||||
GstNvDecoder * gst_nv_decoder_new (GstCudaContext * context);
|
||||
|
@ -51,7 +53,9 @@ gboolean gst_nv_decoder_configure (GstNvDecoder * decoder,
|
|||
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);
|
||||
|
||||
GstFlowReturn gst_nv_decoder_acquire_surface (GstNvDecoder * decoder,
|
||||
GstNvDecSurface ** surface);
|
||||
|
@ -95,6 +99,10 @@ gboolean gst_nv_decoder_decide_allocation (GstNvDecoder * decoder,
|
|||
GstVideoDecoder * videodec,
|
||||
GstQuery * query);
|
||||
|
||||
guint gst_nv_decoder_get_max_output_size (guint coded_size,
|
||||
guint user_requested,
|
||||
guint device_max);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_NV_DECODER_H__ */
|
||||
|
|
|
@ -127,12 +127,16 @@ typedef struct _GstNvH264Dec
|
|||
GArray *ref_list;
|
||||
|
||||
guint num_output_surfaces;
|
||||
guint init_max_width;
|
||||
guint init_max_height;
|
||||
} GstNvH264Dec;
|
||||
|
||||
typedef struct _GstNvH264DecClass
|
||||
{
|
||||
GstH264DecoderClass parent_class;
|
||||
guint cuda_device_id;
|
||||
guint max_width;
|
||||
guint max_height;
|
||||
} GstNvH264DecClass;
|
||||
|
||||
enum
|
||||
|
@ -140,6 +144,8 @@ enum
|
|||
PROP_0,
|
||||
PROP_CUDA_DEVICE_ID,
|
||||
PROP_NUM_OUTPUT_SURFACES,
|
||||
PROP_INIT_MAX_WIDTH,
|
||||
PROP_INIT_MAX_HEIGHT,
|
||||
};
|
||||
|
||||
#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 |
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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->src_caps);
|
||||
|
@ -311,6 +351,12 @@ gst_nv_h264_dec_set_property (GObject * object, guint prop_id,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
self->num_output_surfaces = g_value_get_uint (value);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -331,6 +377,12 @@ gst_nv_h264_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
g_value_set_uint (value, self->num_output_surfaces);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -507,9 +559,11 @@ gst_nv_h264_dec_new_sequence (GstH264Decoder * decoder, const GstH264SPS * sps,
|
|||
gint max_dpb_size)
|
||||
{
|
||||
GstNvH264Dec *self = GST_NV_H264_DEC (decoder);
|
||||
GstNvH264DecClass *klass = GST_NV_H264_DEC_GET_CLASS (self);
|
||||
guint crop_width, crop_height;
|
||||
gboolean modified = FALSE;
|
||||
gboolean interlaced;
|
||||
guint max_width, max_height;
|
||||
|
||||
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;
|
||||
|
||||
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 */
|
||||
if (!gst_nv_decoder_configure (self->decoder,
|
||||
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");
|
||||
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);
|
||||
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);
|
||||
|
||||
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_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
|
||||
|
|
|
@ -123,12 +123,16 @@ typedef struct _GstNvH265Dec
|
|||
guint chroma_format_idc;
|
||||
|
||||
guint num_output_surfaces;
|
||||
guint init_max_width;
|
||||
guint init_max_height;
|
||||
} GstNvH265Dec;
|
||||
|
||||
typedef struct _GstNvH265DecClass
|
||||
{
|
||||
GstH265DecoderClass parent_class;
|
||||
guint cuda_device_id;
|
||||
guint max_width;
|
||||
guint max_height;
|
||||
} GstNvH265DecClass;
|
||||
|
||||
enum
|
||||
|
@ -136,6 +140,8 @@ enum
|
|||
PROP_0,
|
||||
PROP_CUDA_DEVICE_ID,
|
||||
PROP_NUM_OUTPUT_SURFACES,
|
||||
PROP_INIT_MAX_WIDTH,
|
||||
PROP_INIT_MAX_HEIGHT,
|
||||
};
|
||||
|
||||
#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 |
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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->src_caps);
|
||||
|
@ -285,6 +325,12 @@ gst_nv_h265_dec_set_property (GObject * object, guint prop_id,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
self->num_output_surfaces = g_value_get_uint (value);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -305,6 +351,12 @@ gst_nv_h265_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
g_value_set_uint (value, self->num_output_surfaces);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -465,8 +517,10 @@ gst_nv_h265_dec_new_sequence (GstH265Decoder * decoder, const GstH265SPS * sps,
|
|||
gint max_dpb_size)
|
||||
{
|
||||
GstNvH265Dec *self = GST_NV_H265_DEC (decoder);
|
||||
GstNvH265DecClass *klass = GST_NV_H265_DEC_GET_CLASS (self);
|
||||
guint crop_width, crop_height;
|
||||
gboolean modified = FALSE;
|
||||
guint max_width, max_height;
|
||||
|
||||
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_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,
|
||||
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");
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
@ -1081,6 +1141,8 @@ gst_nv_h265_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
|||
gint index = 0;
|
||||
GValue value_list = G_VALUE_INIT;
|
||||
GValue value = G_VALUE_INIT;
|
||||
GstStructure *s;
|
||||
const GValue *res_val;
|
||||
GTypeInfo type_info = {
|
||||
sizeof (GstNvH265DecClass),
|
||||
nullptr,
|
||||
|
@ -1098,6 +1160,13 @@ gst_nv_h265_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
|||
cdata = g_new0 (GstNvDecoderClassData, 1);
|
||||
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 */
|
||||
g_value_init (&value_list, GST_TYPE_LIST);
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
|
|
|
@ -55,12 +55,16 @@ typedef struct _GstNvVp8Dec
|
|||
guint width, height;
|
||||
|
||||
guint num_output_surfaces;
|
||||
guint init_max_width;
|
||||
guint init_max_height;
|
||||
} GstNvVp8Dec;
|
||||
|
||||
typedef struct _GstNvVp8DecClass
|
||||
{
|
||||
GstVp8DecoderClass parent_class;
|
||||
guint cuda_device_id;
|
||||
guint max_width;
|
||||
guint max_height;
|
||||
} GstNvVp8DecClass;
|
||||
|
||||
enum
|
||||
|
@ -68,6 +72,8 @@ enum
|
|||
PROP_0,
|
||||
PROP_CUDA_DEVICE_ID,
|
||||
PROP_NUM_OUTPUT_SURFACES,
|
||||
PROP_INIT_MAX_WIDTH,
|
||||
PROP_INIT_MAX_HEIGHT,
|
||||
};
|
||||
|
||||
#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 |
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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->src_caps);
|
||||
|
@ -207,6 +247,12 @@ gst_nv_vp8_dec_set_property (GObject * object, guint prop_id,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
self->num_output_surfaces = g_value_get_uint (value);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -227,6 +273,12 @@ gst_nv_vp8_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
g_value_set_uint (value, self->num_output_surfaces);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -381,7 +433,9 @@ gst_nv_vp8_dec_new_sequence (GstVp8Decoder * decoder,
|
|||
const GstVp8FrameHdr * frame_hdr, gint max_dpb_size)
|
||||
{
|
||||
GstNvVp8Dec *self = GST_NV_VP8_DEC (decoder);
|
||||
GstNvVp8DecClass *klass = GST_NV_VP8_DEC_GET_CLASS (self);
|
||||
gboolean modified = FALSE;
|
||||
guint max_width, max_height;
|
||||
|
||||
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_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,
|
||||
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");
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
@ -600,6 +660,8 @@ gst_nv_vp8_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
|||
gchar *feature_name;
|
||||
GstNvDecoderClassData *cdata;
|
||||
gint index = 0;
|
||||
const GValue *value;
|
||||
GstStructure *s;
|
||||
GTypeInfo type_info = {
|
||||
sizeof (GstNvVp8DecClass),
|
||||
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");
|
||||
|
||||
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->src_caps = gst_caps_ref (src_caps);
|
||||
cdata->cuda_device_id = device_id;
|
||||
|
|
|
@ -56,12 +56,16 @@ typedef struct _GstNvVp9Dec
|
|||
GstVP9Profile profile;
|
||||
|
||||
guint num_output_surfaces;
|
||||
guint init_max_width;
|
||||
guint init_max_height;
|
||||
} GstNvVp9Dec;
|
||||
|
||||
typedef struct _GstNvVp9DecClass
|
||||
{
|
||||
GstVp9DecoderClass parent_class;
|
||||
guint cuda_device_id;
|
||||
guint max_width;
|
||||
guint max_height;
|
||||
} GstNvVp9DecClass;
|
||||
|
||||
enum
|
||||
|
@ -69,6 +73,8 @@ enum
|
|||
PROP_0,
|
||||
PROP_CUDA_DEVICE_ID,
|
||||
PROP_NUM_OUTPUT_SURFACES,
|
||||
PROP_INIT_MAX_WIDTH,
|
||||
PROP_INIT_MAX_HEIGHT,
|
||||
};
|
||||
|
||||
#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 |
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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->src_caps);
|
||||
|
@ -212,6 +252,12 @@ gst_nv_vp9_dec_set_property (GObject * object, guint prop_id,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
self->num_output_surfaces = g_value_get_uint (value);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -232,6 +278,12 @@ gst_nv_vp9_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_NUM_OUTPUT_SURFACES:
|
||||
g_value_set_uint (value, self->num_output_surfaces);
|
||||
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:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -391,8 +443,10 @@ gst_nv_vp9_dec_new_sequence (GstVp9Decoder * decoder,
|
|||
const GstVp9FrameHeader * frame_hdr, gint max_dpb_size)
|
||||
{
|
||||
GstNvVp9Dec *self = GST_NV_VP9_DEC (decoder);
|
||||
GstNvVp9DecClass *klass = GST_NV_VP9_DEC_GET_CLASS (self);
|
||||
GstVideoFormat out_format = GST_VIDEO_FORMAT_UNKNOWN;
|
||||
GstVideoInfo info;
|
||||
guint max_width, max_height;
|
||||
|
||||
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_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,
|
||||
cudaVideoCodec_VP9, &info, self->width, self->height,
|
||||
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");
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
@ -696,6 +756,8 @@ gst_nv_vp9_dec_register (GstPlugin * plugin, guint device_id, guint rank,
|
|||
gchar *feature_name;
|
||||
GstNvDecoderClassData *cdata;
|
||||
gint index = 0;
|
||||
const GValue *value;
|
||||
GstStructure *s;
|
||||
GTypeInfo type_info = {
|
||||
sizeof (GstNvVp9DecClass),
|
||||
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");
|
||||
|
||||
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);
|
||||
gst_caps_set_simple (cdata->sink_caps,
|
||||
"alignment", G_TYPE_STRING, "frame", nullptr);
|
||||
|
|
Loading…
Reference in a new issue