mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
d3d11h265dec: Add support for interlaced stream
Note that we have no D3D11 deinterlace element yet. If downstream is not support format:Interlaced caps feature including all D3D11 the other elements, aspect-ratio will be adjusted as an alternative approach. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2008>
This commit is contained in:
parent
f49f039ff2
commit
e8df47b022
2 changed files with 135 additions and 25 deletions
|
@ -1431,7 +1431,10 @@ gst_d3d11_decoder_negotiate (GstVideoDecoder * decoder,
|
|||
GstVideoCodecState ** output_state, gboolean * downstream_supports_d3d11)
|
||||
{
|
||||
GstCaps *peer_caps;
|
||||
GstVideoCodecState *state;
|
||||
GstVideoCodecState *state = NULL;
|
||||
gboolean alternate_interlaced;
|
||||
gboolean alternate_supported = FALSE;
|
||||
gboolean d3d11_supported = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_VIDEO_DECODER (decoder), FALSE);
|
||||
g_return_val_if_fail (input_state != NULL, FALSE);
|
||||
|
@ -1441,21 +1444,11 @@ gst_d3d11_decoder_negotiate (GstVideoDecoder * decoder,
|
|||
g_return_val_if_fail (output_state != NULL, FALSE);
|
||||
g_return_val_if_fail (downstream_supports_d3d11 != NULL, FALSE);
|
||||
|
||||
state = gst_video_decoder_set_output_state (decoder,
|
||||
format, width, height, input_state);
|
||||
if (interlace_mode != GST_VIDEO_INTERLACE_MODE_PROGRESSIVE)
|
||||
state->info.interlace_mode = interlace_mode;
|
||||
state->caps = gst_video_info_to_caps (&state->info);
|
||||
|
||||
if (*output_state)
|
||||
gst_video_codec_state_unref (*output_state);
|
||||
*output_state = state;
|
||||
alternate_interlaced = (interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE);
|
||||
|
||||
peer_caps = gst_pad_get_allowed_caps (GST_VIDEO_DECODER_SRC_PAD (decoder));
|
||||
GST_DEBUG_OBJECT (decoder, "Allowed caps %" GST_PTR_FORMAT, peer_caps);
|
||||
|
||||
*downstream_supports_d3d11 = FALSE;
|
||||
|
||||
if (!peer_caps || gst_caps_is_any (peer_caps)) {
|
||||
GST_DEBUG_OBJECT (decoder,
|
||||
"cannot determine output format, use system memory");
|
||||
|
@ -1466,19 +1459,79 @@ gst_d3d11_decoder_negotiate (GstVideoDecoder * decoder,
|
|||
|
||||
for (i = 0; i < size; i++) {
|
||||
features = gst_caps_get_features (peer_caps, i);
|
||||
if (features && gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
|
||||
GST_DEBUG_OBJECT (decoder, "found D3D11 memory feature");
|
||||
gst_caps_set_features (state->caps, 0,
|
||||
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
|
||||
|
||||
*downstream_supports_d3d11 = TRUE;
|
||||
break;
|
||||
if (!features)
|
||||
continue;
|
||||
|
||||
if (gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY)) {
|
||||
d3d11_supported = TRUE;
|
||||
}
|
||||
|
||||
/* FIXME: software deinterlace element will not return interlaced caps
|
||||
* feature... We should fix it */
|
||||
if (gst_caps_features_contains (features,
|
||||
GST_CAPS_FEATURE_FORMAT_INTERLACED)) {
|
||||
alternate_supported = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_clear_caps (&peer_caps);
|
||||
|
||||
GST_DEBUG_OBJECT (decoder,
|
||||
"Downstream feature support, D3D11 memory: %d, interlaced format %d",
|
||||
d3d11_supported, alternate_supported);
|
||||
|
||||
if (alternate_interlaced) {
|
||||
/* FIXME: D3D11 cannot support alternating interlaced stream yet */
|
||||
GST_FIXME_OBJECT (decoder,
|
||||
"Implement alternating interlaced stream for D3D11");
|
||||
|
||||
if (alternate_supported) {
|
||||
/* Set caps resolution with display size, that's how we designed
|
||||
* for alternating interlaced stream */
|
||||
height = 2 * height;
|
||||
state = gst_video_decoder_set_interlaced_output_state (decoder,
|
||||
format, interlace_mode, width, height, input_state);
|
||||
} else {
|
||||
GST_WARNING_OBJECT (decoder,
|
||||
"Downstream doesn't support alternating interlaced stream");
|
||||
|
||||
state = gst_video_decoder_set_output_state (decoder,
|
||||
format, width, height, input_state);
|
||||
|
||||
/* XXX: adjust PAR, this would produce output similar to that of
|
||||
* "line doubling" (so called bob deinterlacing) processing.
|
||||
* apart from missing anchor line (top-field or bottom-field) information.
|
||||
* Potentially flickering could happen. So this might not be correct.
|
||||
* But it would be better than negotiation error of half-height squeezed
|
||||
* image */
|
||||
state->info.par_d *= 2;
|
||||
state->info.fps_n *= 2;
|
||||
}
|
||||
} else {
|
||||
state = gst_video_decoder_set_interlaced_output_state (decoder,
|
||||
format, interlace_mode, width, height, input_state);
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
GST_ERROR_OBJECT (decoder, "Couldn't set output state");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
state->caps = gst_video_info_to_caps (&state->info);
|
||||
|
||||
if (*output_state)
|
||||
gst_video_codec_state_unref (*output_state);
|
||||
*output_state = state;
|
||||
|
||||
if (d3d11_supported) {
|
||||
gst_caps_set_features (state->caps, 0,
|
||||
gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, NULL));
|
||||
}
|
||||
|
||||
*downstream_supports_d3d11 = d3d11_supported;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ typedef struct _GstD3D11H265Dec
|
|||
guint bitdepth;
|
||||
guint chroma_format_idc;
|
||||
GstVideoFormat out_format;
|
||||
GstVideoInterlaceMode interlace_mode;
|
||||
|
||||
/* Array of DXVA_Slice_HEVC_Short */
|
||||
GArray *slice_list;
|
||||
|
@ -309,9 +310,9 @@ gst_d3d11_h265_dec_negotiate (GstVideoDecoder * decoder)
|
|||
|
||||
if (!gst_d3d11_decoder_negotiate (decoder, h265dec->input_state,
|
||||
self->out_format, self->width, self->height,
|
||||
GST_VIDEO_INTERLACE_MODE_PROGRESSIVE,
|
||||
&self->output_state, &self->use_d3d11_output))
|
||||
self->interlace_mode, &self->output_state, &self->use_d3d11_output)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
|
||||
}
|
||||
|
@ -359,6 +360,7 @@ gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
|
|||
static const GUID *main_10_guid =
|
||||
&GST_GUID_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10;
|
||||
static const GUID *main_guid = &GST_GUID_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN;
|
||||
GstVideoInterlaceMode interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
|
||||
|
||||
GST_LOG_OBJECT (self, "new sequence");
|
||||
|
||||
|
@ -387,6 +389,25 @@ gst_d3d11_h265_dec_new_sequence (GstH265Decoder * decoder,
|
|||
modified = TRUE;
|
||||
}
|
||||
|
||||
if (sps->vui_parameters_present_flag && sps->vui_params.field_seq_flag) {
|
||||
interlace_mode = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
|
||||
} else {
|
||||
/* 7.4.4 Profile, tier and level sementics */
|
||||
if (sps->profile_tier_level.progressive_source_flag &&
|
||||
!sps->profile_tier_level.interlaced_source_flag) {
|
||||
interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
|
||||
} else {
|
||||
interlace_mode = GST_VIDEO_INTERLACE_MODE_MIXED;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->interlace_mode != interlace_mode) {
|
||||
GST_INFO_OBJECT (self, "Interlace mode change %d -> %d",
|
||||
self->interlace_mode, interlace_mode);
|
||||
self->interlace_mode = interlace_mode;
|
||||
modified = TRUE;
|
||||
}
|
||||
|
||||
if (self->chroma_format_idc != sps->chroma_format_idc) {
|
||||
GST_INFO_OBJECT (self, "chroma format changed");
|
||||
self->chroma_format_idc = sps->chroma_format_idc;
|
||||
|
@ -775,8 +796,9 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
GstBuffer *view_buffer;
|
||||
gboolean direct_rendering = FALSE;
|
||||
|
||||
GST_LOG_OBJECT (self,
|
||||
"Outputting picture %p, poc %d", picture, picture->pic_order_cnt);
|
||||
GST_LOG_OBJECT (self, "Outputting picture %p, poc %d, picture_struct %d, "
|
||||
"buffer flags 0x%x", picture, picture->pic_order_cnt, picture->pic_struct,
|
||||
picture->buffer_flags);
|
||||
|
||||
view_buffer = (GstBuffer *) gst_h265_picture_get_user_data (picture);
|
||||
|
||||
|
@ -824,6 +846,7 @@ gst_d3d11_h265_dec_output_picture (GstH265Decoder * decoder,
|
|||
goto error;
|
||||
}
|
||||
|
||||
GST_BUFFER_FLAG_SET (frame->output_buffer, picture->buffer_flags);
|
||||
gst_h265_picture_unref (picture);
|
||||
|
||||
return gst_video_decoder_finish_frame (GST_VIDEO_DECODER (self), frame);
|
||||
|
@ -1384,6 +1407,9 @@ gst_d3d11_h265_dec_register (GstPlugin * plugin, GstD3D11Device * device,
|
|||
};
|
||||
GstCaps *sink_caps = NULL;
|
||||
GstCaps *src_caps = NULL;
|
||||
GstCaps *src_caps_copy;
|
||||
GstCaps *tmp;
|
||||
GstCapsFeatures *caps_features;
|
||||
guint max_width = 0;
|
||||
guint max_height = 0;
|
||||
guint resolution;
|
||||
|
@ -1450,8 +1476,7 @@ gst_d3d11_h265_dec_register (GstPlugin * plugin, GstD3D11Device * device,
|
|||
sink_caps = gst_caps_from_string ("video/x-h265, "
|
||||
"stream-format=(string) { hev1, hvc1, byte-stream }, "
|
||||
"alignment= (string) au");
|
||||
src_caps = gst_caps_from_string ("video/x-raw("
|
||||
GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY "); video/x-raw");
|
||||
src_caps = gst_caps_new_empty_simple ("video/x-raw");
|
||||
|
||||
if (have_main10) {
|
||||
/* main10 profile covers main and main10 */
|
||||
|
@ -1499,6 +1524,38 @@ gst_d3d11_h265_dec_register (GstPlugin * plugin, GstD3D11Device * device,
|
|||
"width", GST_TYPE_INT_RANGE, 64, resolution,
|
||||
"height", GST_TYPE_INT_RANGE, 64, resolution, NULL);
|
||||
|
||||
/* Copy src caps to append other capsfeatures */
|
||||
src_caps_copy = gst_caps_copy (src_caps);
|
||||
|
||||
/* System memory with alternate interlace-mode */
|
||||
tmp = gst_caps_copy (src_caps_copy);
|
||||
caps_features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED,
|
||||
NULL);
|
||||
gst_caps_set_features_simple (tmp, caps_features);
|
||||
gst_caps_set_simple (tmp, "interlace-mode", G_TYPE_STRING, "alternate", NULL);
|
||||
gst_caps_append (src_caps, tmp);
|
||||
|
||||
/* D3D11 memory feature */
|
||||
tmp = gst_caps_copy (src_caps_copy);
|
||||
caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
|
||||
NULL);
|
||||
gst_caps_set_features_simple (tmp, caps_features);
|
||||
gst_caps_append (src_caps, tmp);
|
||||
|
||||
/* FIXME: D3D11 deinterlace element is not prepared, so this D3D11 with
|
||||
* interlaced caps feature is pointless at the moment */
|
||||
#if 0
|
||||
/* D3D11 memory with alternate interlace-mode */
|
||||
tmp = gst_caps_copy (src_caps_copy);
|
||||
caps_features = gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY,
|
||||
GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
|
||||
gst_caps_set_features_simple (tmp, caps_features);
|
||||
gst_caps_set_simple (tmp, "interlace-mode", G_TYPE_STRING, "alternate", NULL);
|
||||
gst_caps_append (src_caps, tmp);
|
||||
#endif
|
||||
|
||||
gst_caps_unref (src_caps_copy);
|
||||
|
||||
type_info.class_data =
|
||||
gst_d3d11_decoder_class_data_new (device, sink_caps, src_caps);
|
||||
|
||||
|
|
Loading…
Reference in a new issue