mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
nvdec: Add support for 10bits 4:2:0 decoding
This commit includes h265 main-10 profile support if the device can decode it. Note that since h264 10bits decoding is not supported by nvidia GPU for now, the additional code path for h264 high-10 profile is a preparation for the future Nvidia's enhancement.
This commit is contained in:
parent
d692350fc3
commit
e5a98cf9d8
2 changed files with 103 additions and 9 deletions
|
@ -195,6 +195,7 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format)
|
||||||
{
|
{
|
||||||
guint width, height, fps_n, fps_d;
|
guint width, height, fps_n, fps_d;
|
||||||
CUVIDDECODECREATEINFO create_info = { 0, };
|
CUVIDDECODECREATEINFO create_info = { 0, };
|
||||||
|
GstVideoFormat out_format = GST_VIDEO_FORMAT_NV12;
|
||||||
|
|
||||||
width = format->display_area.right - format->display_area.left;
|
width = format->display_area.right - format->display_area.left;
|
||||||
height = format->display_area.bottom - format->display_area.top;
|
height = format->display_area.bottom - format->display_area.top;
|
||||||
|
@ -227,6 +228,17 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format)
|
||||||
create_info.display_area.right = format->display_area.right;
|
create_info.display_area.right = format->display_area.right;
|
||||||
create_info.display_area.bottom = format->display_area.bottom;
|
create_info.display_area.bottom = format->display_area.bottom;
|
||||||
create_info.OutputFormat = cudaVideoSurfaceFormat_NV12;
|
create_info.OutputFormat = cudaVideoSurfaceFormat_NV12;
|
||||||
|
create_info.bitDepthMinus8 = format->bit_depth_luma_minus8;
|
||||||
|
if (format->bit_depth_luma_minus8 > 0) {
|
||||||
|
GST_DEBUG_OBJECT (nvdec, "out format bitdepth : %d",
|
||||||
|
format->bit_depth_luma_minus8 + 8);
|
||||||
|
create_info.OutputFormat = cudaVideoSurfaceFormat_P016;
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
out_format = GST_VIDEO_FORMAT_P010_10LE;
|
||||||
|
#else
|
||||||
|
out_format = GST_VIDEO_FORMAT_P010_10BE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
create_info.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
|
create_info.DeinterlaceMode = cudaVideoDeinterlaceMode_Weave;
|
||||||
create_info.ulTargetWidth = width;
|
create_info.ulTargetWidth = width;
|
||||||
create_info.ulTargetHeight = height;
|
create_info.ulTargetHeight = height;
|
||||||
|
@ -265,7 +277,7 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format)
|
||||||
nvdec->fps_d = fps_d;
|
nvdec->fps_d = fps_d;
|
||||||
|
|
||||||
state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (nvdec),
|
state = gst_video_decoder_set_output_state (GST_VIDEO_DECODER (nvdec),
|
||||||
GST_VIDEO_FORMAT_NV12, nvdec->width, nvdec->height, nvdec->input_state);
|
out_format, nvdec->width, nvdec->height, nvdec->input_state);
|
||||||
vinfo = &state->info;
|
vinfo = &state->info;
|
||||||
vinfo->fps_n = fps_n;
|
vinfo->fps_n = fps_n;
|
||||||
vinfo->fps_d = fps_d;
|
vinfo->fps_d = fps_d;
|
||||||
|
@ -332,7 +344,10 @@ parser_sequence_callback (GstNvDec * nvdec, CUVIDEOFORMAT * format)
|
||||||
gst_caps_set_simple (state->caps, "texture-target", G_TYPE_STRING,
|
gst_caps_set_simple (state->caps, "texture-target", G_TYPE_STRING,
|
||||||
"2D", NULL);
|
"2D", NULL);
|
||||||
|
|
||||||
gst_video_codec_state_unref (state);
|
if (nvdec->output_state)
|
||||||
|
gst_video_codec_state_unref (nvdec->output_state);
|
||||||
|
|
||||||
|
nvdec->output_state = state;
|
||||||
|
|
||||||
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (nvdec))) {
|
if (!gst_video_decoder_negotiate (GST_VIDEO_DECODER (nvdec))) {
|
||||||
GST_WARNING_OBJECT (nvdec, "failed to negotiate with downstream");
|
GST_WARNING_OBJECT (nvdec, "failed to negotiate with downstream");
|
||||||
|
@ -634,6 +649,11 @@ gst_nvdec_stop (GstVideoDecoder * decoder)
|
||||||
nvdec->input_state = NULL;
|
nvdec->input_state = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nvdec->output_state) {
|
||||||
|
gst_video_codec_state_unref (nvdec->output_state);
|
||||||
|
nvdec->output_state = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (nvdec->ctx_lock) {
|
if (nvdec->ctx_lock) {
|
||||||
CuvidCtxLockDestroy (nvdec->ctx_lock);
|
CuvidCtxLockDestroy (nvdec->ctx_lock);
|
||||||
nvdec->ctx_lock = NULL;
|
nvdec->ctx_lock = NULL;
|
||||||
|
@ -698,6 +718,7 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
|
||||||
CUarray array;
|
CUarray array;
|
||||||
guint pitch, i;
|
guint pitch, i;
|
||||||
CUDA_MEMCPY2D mcpy2d = { 0, };
|
CUDA_MEMCPY2D mcpy2d = { 0, };
|
||||||
|
GstVideoInfo *info = &nvdec->output_state->info;
|
||||||
|
|
||||||
GST_LOG_OBJECT (nvdec, "picture index: %u", dispinfo->picture_index);
|
GST_LOG_OBJECT (nvdec, "picture index: %u", dispinfo->picture_index);
|
||||||
|
|
||||||
|
@ -724,8 +745,9 @@ copy_video_frame_to_gl_textures (GstGLContext * context, gpointer * args)
|
||||||
mcpy2d.srcMemoryType = CU_MEMORYTYPE_DEVICE;
|
mcpy2d.srcMemoryType = CU_MEMORYTYPE_DEVICE;
|
||||||
mcpy2d.srcPitch = pitch;
|
mcpy2d.srcPitch = pitch;
|
||||||
mcpy2d.dstMemoryType = CU_MEMORYTYPE_ARRAY;
|
mcpy2d.dstMemoryType = CU_MEMORYTYPE_ARRAY;
|
||||||
mcpy2d.dstPitch = nvdec->width;
|
mcpy2d.dstPitch = GST_VIDEO_INFO_WIDTH (info);
|
||||||
mcpy2d.WidthInBytes = nvdec->width;
|
mcpy2d.WidthInBytes = GST_VIDEO_INFO_COMP_WIDTH (info, 0)
|
||||||
|
* GST_VIDEO_INFO_COMP_PSTRIDE (info, 0);
|
||||||
|
|
||||||
for (i = 0; i < num_resources; i++) {
|
for (i = 0; i < num_resources; i++) {
|
||||||
if (!cuda_OK (CuGraphicsSubResourceGetMappedArray (&array, resources[i], 0,
|
if (!cuda_OK (CuGraphicsSubResourceGetMappedArray (&array, resources[i], 0,
|
||||||
|
@ -1044,6 +1066,56 @@ gst_nvdec_subclass_register (GstPlugin * plugin, GType type,
|
||||||
g_free (type_name);
|
g_free (type_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_nvdec_get_supported_codec_profiles (GValue * profiles,
|
||||||
|
cudaVideoCodec codec_type, guint max_bitdepth_minus8)
|
||||||
|
{
|
||||||
|
GValue val = G_VALUE_INIT;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
|
g_value_init (&val, G_TYPE_STRING);
|
||||||
|
|
||||||
|
switch (codec_type) {
|
||||||
|
case cudaVideoCodec_H264:
|
||||||
|
g_value_set_static_string (&val, "constrained-baseline");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
|
||||||
|
g_value_set_static_string (&val, "baseline");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
|
||||||
|
g_value_set_static_string (&val, "main");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
|
||||||
|
g_value_set_static_string (&val, "high");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
|
||||||
|
if (max_bitdepth_minus8 >= 2) {
|
||||||
|
g_value_set_static_string (&val, "high-10");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
case cudaVideoCodec_HEVC:
|
||||||
|
g_value_set_static_string (&val, "main");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
|
||||||
|
if (max_bitdepth_minus8 >= 2) {
|
||||||
|
g_value_set_static_string (&val, "main-10");
|
||||||
|
gst_value_list_append_value (profiles, &val);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_value_unset (&val);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
guint idx;
|
guint idx;
|
||||||
|
@ -1065,8 +1137,9 @@ gst_nvdec_register (GstPlugin * plugin, GType type, cudaVideoCodec codec_type,
|
||||||
gint max_height = 0, min_height = G_MAXINT;
|
gint max_height = 0, min_height = G_MAXINT;
|
||||||
GstCaps *sink_templ = NULL;
|
GstCaps *sink_templ = NULL;
|
||||||
GstCaps *src_templ = NULL;
|
GstCaps *src_templ = NULL;
|
||||||
/* FIXME: support 10/12bits format */
|
/* FIXME: support 12bits format */
|
||||||
guint bitdepth_minus8[1] = { 0 };
|
guint bitdepth_minus8[2] = { 0, 2 };
|
||||||
|
guint max_bitdepth_minus8 = 0;
|
||||||
gint c_idx, b_idx;
|
gint c_idx, b_idx;
|
||||||
guint num_support = 0;
|
guint num_support = 0;
|
||||||
cudaVideoChromaFormat chroma_list[] = {
|
cudaVideoChromaFormat chroma_list[] = {
|
||||||
|
@ -1081,6 +1154,7 @@ gst_nvdec_register (GstPlugin * plugin, GType type, cudaVideoCodec codec_type,
|
||||||
};
|
};
|
||||||
GValue format_list = G_VALUE_INIT;
|
GValue format_list = G_VALUE_INIT;
|
||||||
GValue format = G_VALUE_INIT;
|
GValue format = G_VALUE_INIT;
|
||||||
|
GValue profile_list = G_VALUE_INIT;
|
||||||
|
|
||||||
if (CuDeviceGet (&cuda_device, i) != CUDA_SUCCESS)
|
if (CuDeviceGet (&cuda_device, i) != CUDA_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1090,6 +1164,7 @@ gst_nvdec_register (GstPlugin * plugin, GType type, cudaVideoCodec codec_type,
|
||||||
|
|
||||||
g_value_init (&format_list, GST_TYPE_LIST);
|
g_value_init (&format_list, GST_TYPE_LIST);
|
||||||
g_value_init (&format, G_TYPE_STRING);
|
g_value_init (&format, G_TYPE_STRING);
|
||||||
|
g_value_init (&profile_list, GST_TYPE_LIST);
|
||||||
|
|
||||||
if (CuCtxPushCurrent (cuda_ctx) != CUDA_SUCCESS)
|
if (CuCtxPushCurrent (cuda_ctx) != CUDA_SUCCESS)
|
||||||
goto cuda_free;
|
goto cuda_free;
|
||||||
|
@ -1122,20 +1197,32 @@ gst_nvdec_register (GstPlugin * plugin, GType type, cudaVideoCodec codec_type,
|
||||||
if (max_height < decoder_caps.nMaxHeight)
|
if (max_height < decoder_caps.nMaxHeight)
|
||||||
max_height = decoder_caps.nMaxHeight;
|
max_height = decoder_caps.nMaxHeight;
|
||||||
|
|
||||||
|
max_bitdepth_minus8 = bitdepth_minus8[b_idx];
|
||||||
|
|
||||||
GST_INFO ("%s bit-depth %d with chroma format %d [%d - %d] x [%d - %d]",
|
GST_INFO ("%s bit-depth %d with chroma format %d [%d - %d] x [%d - %d]",
|
||||||
codec, bitdepth_minus8[b_idx] + 8, c_idx, min_width, max_width,
|
codec, bitdepth_minus8[b_idx] + 8, c_idx, min_width, max_width,
|
||||||
min_height, max_height);
|
min_height, max_height);
|
||||||
|
|
||||||
switch (chroma_list[c_idx]) {
|
switch (chroma_list[c_idx]) {
|
||||||
case cudaVideoChromaFormat_420:
|
case cudaVideoChromaFormat_420:
|
||||||
g_value_set_string (&format, "NV12");
|
if (b_idx == 0) {
|
||||||
|
g_value_set_string (&format, "NV12");
|
||||||
|
} else if (b_idx == 1) {
|
||||||
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||||
|
g_value_set_string (&format, "P010_10LE");
|
||||||
|
#else
|
||||||
|
g_value_set_string (&format, "P010_10BE");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
/* unknown bit-depth */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
num_support++;
|
||||||
gst_value_list_append_value (&format_list, &format);
|
gst_value_list_append_value (&format_list, &format);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
num_support++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1162,6 +1249,11 @@ gst_nvdec_register (GstPlugin * plugin, GType type, cudaVideoCodec codec_type,
|
||||||
"width", GST_TYPE_INT_RANGE, min_width, max_width,
|
"width", GST_TYPE_INT_RANGE, min_width, max_width,
|
||||||
"height", GST_TYPE_INT_RANGE, min_height, max_height, NULL);
|
"height", GST_TYPE_INT_RANGE, min_height, max_height, NULL);
|
||||||
|
|
||||||
|
if (gst_nvdec_get_supported_codec_profiles (&profile_list, codec_type,
|
||||||
|
max_bitdepth_minus8)) {
|
||||||
|
gst_caps_set_value (sink_templ, "profile", &profile_list);
|
||||||
|
}
|
||||||
|
|
||||||
GST_DEBUG ("sink template caps %" GST_PTR_FORMAT, sink_templ);
|
GST_DEBUG ("sink template caps %" GST_PTR_FORMAT, sink_templ);
|
||||||
GST_DEBUG ("src template caps %" GST_PTR_FORMAT, src_templ);
|
GST_DEBUG ("src template caps %" GST_PTR_FORMAT, src_templ);
|
||||||
|
|
||||||
|
@ -1172,6 +1264,7 @@ gst_nvdec_register (GstPlugin * plugin, GType type, cudaVideoCodec codec_type,
|
||||||
|
|
||||||
g_value_unset (&format_list);
|
g_value_unset (&format_list);
|
||||||
g_value_unset (&format);
|
g_value_unset (&format);
|
||||||
|
g_value_unset (&profile_list);
|
||||||
|
|
||||||
if (sink_templ && src_templ) {
|
if (sink_templ && src_templ) {
|
||||||
gst_nvdec_subclass_register (plugin, type, codec_type, codec, i, rank,
|
gst_nvdec_subclass_register (plugin, type, codec_type, codec, i, rank,
|
||||||
|
|
|
@ -71,6 +71,7 @@ struct _GstNvDec
|
||||||
guint fps_d;
|
guint fps_d;
|
||||||
GstClockTime min_latency;
|
GstClockTime min_latency;
|
||||||
GstVideoCodecState *input_state;
|
GstVideoCodecState *input_state;
|
||||||
|
GstVideoCodecState *output_state;
|
||||||
|
|
||||||
GstFlowReturn last_ret;
|
GstFlowReturn last_ret;
|
||||||
GstNvDecState state;
|
GstNvDecState state;
|
||||||
|
|
Loading…
Reference in a new issue