From f5a3d3d7995d537b282204f0f089c9a5c1d0aa56 Mon Sep 17 00:00:00 2001 From: Sreerenj Balachandran Date: Tue, 6 Mar 2018 13:52:04 +0000 Subject: [PATCH] msdk: vpp: Add deinterlacing support https://bugzilla.gnome.org/show_bug.cgi?id=793705 --- sys/msdk/gstmsdkvpp.c | 56 ++++++++++++++++++++++++++++++++ sys/msdk/gstmsdkvpp.h | 9 ++++-- sys/msdk/gstmsdkvpputil.c | 82 +++++++++++++++++++++++++++++++++++++++++++++-- sys/msdk/gstmsdkvpputil.h | 4 +++ sys/msdk/msdk-enums.c | 66 ++++++++++++++++++++++++++++++++++++++ sys/msdk/msdk-enums.h | 15 +++++++++ sys/msdk/msdk.c | 4 ++- 7 files changed, 230 insertions(+), 6 deletions(-) diff --git a/sys/msdk/gstmsdkvpp.c b/sys/msdk/gstmsdkvpp.c index b031a03..6b71e1e 100644 --- a/sys/msdk/gstmsdkvpp.c +++ b/sys/msdk/gstmsdkvpp.c @@ -69,6 +69,8 @@ enum PROP_ASYNC_DEPTH, PROP_DENOISE, PROP_ROTATION, + PROP_DEINTERLACE_MODE, + PROP_DEINTERLACE_METHOD, PROP_N, }; @@ -76,6 +78,8 @@ enum #define PROP_ASYNC_DEPTH_DEFAULT 1 #define PROP_DENOISE_DEFAULT 0 #define PROP_ROTATION_DEFAULT MFX_ANGLE_0 +#define PROP_DEINTERLACE_MODE_DEFAULT GST_MSDKVPP_DEINTERLACE_MODE_AUTO +#define PROP_DEINTERLACE_METHOD_DEFAULT MFX_DEINTERLACING_BOB #define gst_msdkvpp_parent_class parent_class G_DEFINE_TYPE (GstMsdkVPP, gst_msdkvpp, GST_TYPE_BASE_TRANSFORM); @@ -581,6 +585,7 @@ gst_msdkvpp_close (GstMsdkVPP * thiz) gst_object_unref (thiz->srcpad_buffer_pool); thiz->srcpad_buffer_pool = NULL; + thiz->field_duration = GST_CLOCK_TIME_NONE; gst_video_info_init (&thiz->sinkpad_info); gst_video_info_init (&thiz->srcpad_info); } @@ -612,6 +617,17 @@ ensure_filters (GstMsdkVPP * thiz) n_filters++; } + /* Deinterlace */ + if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE) { + mfxExtVPPDeinterlacing *mfx_deinterlace = &thiz->mfx_deinterlace; + mfx_deinterlace->Header.BufferId = MFX_EXTBUFF_VPP_DEINTERLACING; + mfx_deinterlace->Header.BufferSz = sizeof (mfxExtVPPDeinterlacing); + mfx_deinterlace->Mode = thiz->deinterlace_method; + gst_msdkvpp_add_extra_param (thiz, (mfxExtBuffer *) mfx_deinterlace); + thiz->max_filter_algorithms[n_filters] = MFX_EXTBUFF_VPP_DEINTERLACING; + n_filters++; + } + /* mfxExtVPPDoUse */ if (n_filters) { mfxExtVPPDoUse *mfx_vpp_douse = &thiz->mfx_vpp_douse; @@ -682,6 +698,10 @@ gst_msdkvpp_initialize (GstMsdkVPP * thiz) thiz->param.vpp.Out.FrameRateExtD = GST_VIDEO_INFO_FPS_D (&thiz->sinkpad_info); + /* set vpp out picstruct as progressive if deinterlacing enabled */ + if (thiz->flags & GST_MSDK_FLAG_DEINTERLACE) + thiz->param.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + /* validate parameters and allow the Media SDK to make adjustments */ status = MFXVideoVPP_Query (session, &thiz->param, &thiz->param); if (status < MFX_ERR_NONE) { @@ -753,6 +773,7 @@ gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps, GstVideoInfo in_info, out_info; gboolean sinkpad_info_changed = FALSE; gboolean srcpad_info_changed = FALSE; + gboolean deinterlace; gst_video_info_from_caps (&in_info, caps); gst_video_info_from_caps (&out_info, out_caps); @@ -773,6 +794,14 @@ gst_msdkvpp_set_caps (GstBaseTransform * trans, GstCaps * caps, if (!sinkpad_info_changed && !srcpad_info_changed) return TRUE; + /* check for deinterlace requirement */ + deinterlace = gst_msdkvpp_is_deinterlace_enabled (thiz, &in_info); + if (deinterlace) + thiz->flags |= GST_MSDK_FLAG_DEINTERLACE; + thiz->field_duration = GST_VIDEO_INFO_FPS_N (&in_info) > 0 ? + gst_util_uint64_scale (GST_SECOND, GST_VIDEO_INFO_FPS_D (&in_info), + (1 + deinterlace) * GST_VIDEO_INFO_FPS_N (&in_info)) : 0; + if (!gst_msdkvpp_initialize (thiz)) return FALSE; @@ -880,6 +909,12 @@ gst_msdkvpp_set_property (GObject * object, guint prop_id, thiz->rotation = g_value_get_enum (value); thiz->flags |= GST_MSDK_FLAG_ROTATION; break; + case PROP_DEINTERLACE_MODE: + thiz->deinterlace_mode = g_value_get_enum (value); + break; + case PROP_DEINTERLACE_METHOD: + thiz->deinterlace_method = g_value_get_enum (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -905,6 +940,12 @@ gst_msdkvpp_get_property (GObject * object, guint prop_id, case PROP_ROTATION: g_value_set_enum (value, thiz->rotation); break; + case PROP_DEINTERLACE_MODE: + g_value_set_enum (value, thiz->deinterlace_mode); + break; + case PROP_DEINTERLACE_METHOD: + g_value_set_enum (value, thiz->deinterlace_method); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -995,6 +1036,18 @@ gst_msdkvpp_class_init (GstMsdkVPPClass * klass) "Rotation Angle", gst_msdkvpp_rotation_get_type (), PROP_ROTATION_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEINTERLACE_MODE] = + g_param_spec_enum ("deinterlace-mode", "Deinterlace Mode", + "Deinterlace mode to use", gst_msdkvpp_deinterlace_mode_get_type (), + PROP_DEINTERLACE_MODE_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + obj_properties[PROP_DEINTERLACE_METHOD] = + g_param_spec_enum ("deinterlace-method", "Deinterlace Method", + "Deinterlace method to use", gst_msdkvpp_deinterlace_method_get_type (), + PROP_DEINTERLACE_METHOD_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (gobject_class, PROP_N, obj_properties); } @@ -1005,6 +1058,9 @@ gst_msdkvpp_init (GstMsdkVPP * thiz) thiz->async_depth = PROP_ASYNC_DEPTH_DEFAULT; thiz->denoise_factor = PROP_DENOISE_DEFAULT; thiz->rotation = PROP_ROTATION_DEFAULT; + thiz->deinterlace_mode = PROP_DEINTERLACE_MODE_DEFAULT; + thiz->deinterlace_method = PROP_DEINTERLACE_METHOD_DEFAULT; + thiz->field_duration = GST_CLOCK_TIME_NONE; gst_video_info_init (&thiz->sinkpad_info); gst_video_info_init (&thiz->srcpad_info); } diff --git a/sys/msdk/gstmsdkvpp.h b/sys/msdk/gstmsdkvpp.h index b4c68ff..ca3d21a 100644 --- a/sys/msdk/gstmsdkvpp.h +++ b/sys/msdk/gstmsdkvpp.h @@ -61,8 +61,9 @@ typedef struct _GstMsdkVPP GstMsdkVPP; typedef struct _GstMsdkVPPClass GstMsdkVPPClass; typedef enum { - GST_MSDK_FLAG_DENOISE = 1 << 0, - GST_MSDK_FLAG_ROTATION = 1 << 1, + GST_MSDK_FLAG_DENOISE = 1 << 0, + GST_MSDK_FLAG_ROTATION = 1 << 1, + GST_MSDK_FLAG_DEINTERLACE = 1 << 2, } GstMsdkVppFlags; struct _GstMsdkVPP @@ -99,12 +100,16 @@ struct _GstMsdkVPP guint async_depth; guint denoise_factor; guint rotation; + guint deinterlace_mode; + guint deinterlace_method; + GstClockTime field_duration; /* MFX Filters */ mfxExtVPPDoUse mfx_vpp_douse; mfxU32 max_filter_algorithms [MAX_FILTER_ALGORITHMS]; mfxExtVPPDenoise mfx_denoise; mfxExtVPPRotation mfx_rotation; + mfxExtVPPDeinterlacing mfx_deinterlace; /* Extended buffers */ mfxExtBuffer *extra_params[MAX_EXTRA_PARAMS]; diff --git a/sys/msdk/gstmsdkvpputil.c b/sys/msdk/gstmsdkvpputil.c index bc337ea..82695aa 100644 --- a/sys/msdk/gstmsdkvpputil.c +++ b/sys/msdk/gstmsdkvpputil.c @@ -26,6 +26,26 @@ */ #include "gstmsdkvpputil.h" +#include "msdk-enums.h" + +gboolean +gst_msdkvpp_is_deinterlace_enabled (GstMsdkVPP * msdkvpp, GstVideoInfo * vip) +{ + gboolean deinterlace; + + switch (msdkvpp->deinterlace_mode) { + case GST_MSDKVPP_DEINTERLACE_MODE_AUTO: + deinterlace = GST_VIDEO_INFO_IS_INTERLACED (vip); + break; + case GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED: + deinterlace = TRUE; + break; + default: + deinterlace = FALSE; + break; + } + return deinterlace; +} static gboolean fixate_output_frame_size (GstMsdkVPP * thiz, GstVideoInfo * vinfo, @@ -407,6 +427,31 @@ overflow_error: } static gboolean +fixate_frame_rate (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstStructure * outs) +{ + gint fps_n, fps_d; + + fps_n = GST_VIDEO_INFO_FPS_N (vinfo); + fps_d = GST_VIDEO_INFO_FPS_D (vinfo); + if (gst_msdkvpp_is_deinterlace_enabled (thiz, vinfo)) { + /* Fixme: set double framerate?: + * msdk is not outputting double framerate for bob or adv deinterlace */ + if (!gst_util_fraction_multiply (fps_n, fps_d, 1, 1, &fps_n, &fps_d)) + goto overflow_error; + } + gst_structure_set (outs, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); + return TRUE; + + /* ERRORS */ +overflow_error: + { + GST_ELEMENT_ERROR (thiz, CORE, NEGOTIATION, (NULL), + ("Error calculating the output framerate - integer overflow")); + return FALSE; + } +} + +static gboolean set_multiview_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstStructure * outs) { @@ -429,6 +474,28 @@ set_multiview_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo, return TRUE; } +static gboolean +set_interlace_mode (GstMsdkVPP * thiz, GstVideoInfo * vinfo, + GstStructure * outs) +{ + const gchar *interlace_mode = NULL; + + if (gst_msdkvpp_is_deinterlace_enabled (thiz, vinfo)) { + interlace_mode = "progressive"; + } else { + interlace_mode = + gst_video_interlace_mode_to_string (GST_VIDEO_INFO_INTERLACE_MODE + (vinfo)); + } + + if (!interlace_mode) + return FALSE; + + gst_structure_set (outs, "interlace-mode", G_TYPE_STRING, interlace_mode, + NULL); + return TRUE; +} + static GstCaps * _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstCaps * srccaps) @@ -450,14 +517,18 @@ _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo, goto fixate_failed; /* Fixate the framerate */ - gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, - GST_VIDEO_INFO_FPS_N (vinfo), GST_VIDEO_INFO_FPS_D (vinfo), NULL); + if (!fixate_frame_rate (thiz, vinfo, structure)) + goto fixate_failed; /* set multiview mode based on input caps */ if (!set_multiview_mode (thiz, vinfo, structure)) goto fixate_failed; - /*Fixme: Set colorimetry and interlace mode */ + /*Fixme: Set colorimetry */ + + /* set interlace mode */ + if (!set_interlace_mode (thiz, vinfo, structure)) + goto interlace_mode_failed; outcaps = gst_caps_new_empty (); gst_caps_append_structure (outcaps, structure); @@ -471,6 +542,11 @@ fixate_failed: gst_structure_free (structure); return NULL; } +interlace_mode_failed: + { + GST_WARNING_OBJECT (thiz, "Invalid sink caps interlace mode"); + return NULL; + } } /** diff --git a/sys/msdk/gstmsdkvpputil.h b/sys/msdk/gstmsdkvpputil.h index ab6abe5..560ea94 100644 --- a/sys/msdk/gstmsdkvpputil.h +++ b/sys/msdk/gstmsdkvpputil.h @@ -33,6 +33,10 @@ G_BEGIN_DECLS GstCaps *gst_msdkvpp_fixate_srccaps (GstMsdkVPP * msdkvpp, GstCaps * sinkcaps, GstCaps * srccaps); +gboolean +gst_msdkvpp_is_deinterlace_enabled (GstMsdkVPP * msdkvpp, + GstVideoInfo * vip); + G_END_DECLS #endif /* GST_MSDKVPPUTIL_H */ diff --git a/sys/msdk/msdk-enums.c b/sys/msdk/msdk-enums.c index 1479715..51dd7cc 100644 --- a/sys/msdk/msdk-enums.c +++ b/sys/msdk/msdk-enums.c @@ -176,3 +176,69 @@ gst_msdkvpp_rotation_get_type (void) } return type; } + +GType +gst_msdkvpp_deinterlace_mode_get_type (void) +{ + static GType type = 0; + + static const GEnumValue values[] = { + {GST_MSDKVPP_DEINTERLACE_MODE_AUTO, + "Auto detection", "auto"}, + {GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED, + "Force deinterlacing", "interlaced"}, + {GST_MSDKVPP_DEINTERLACE_MODE_DISABLED, + "Never deinterlace", "disabled"}, + {0, NULL, NULL}, + }; + + if (!type) { + type = g_enum_register_static ("GstMsdkVPPDeinterlaceMode", values); + } + return type; +} + +GType +gst_msdkvpp_deinterlace_method_get_type (void) +{ + static GType type = 0; + + static const GEnumValue values[] = { + {_MFX_DEINTERLACE_METHOD_NONE, + "Disable deinterlacing", "none"}, + {MFX_DEINTERLACING_BOB, "Bob deinterlacing", "bob"}, + {MFX_DEINTERLACING_ADVANCED, "Advanced deinterlacing (Motion adaptive)", + "advanced"}, +#if 0 + {MFX_DEINTERLACING_AUTO_DOUBLE, + "Auto mode with deinterlacing double framerate output", + "auto-double"}, + {MFX_DEINTERLACING_AUTO_SINGLE, + "Auto mode with deinterlacing single framerate output", + "auto-single"}, + {MFX_DEINTERLACING_FULL_FR_OUT, + "Deinterlace only mode with full framerate output", "full-fr"}, + {MFX_DEINTERLACING_HALF_FR_OUT, + "Deinterlace only Mode with half framerate output", "half-fr"}, + {MFX_DEINTERLACING_24FPS_OUT, "24 fps fixed output mode", "24-fps"}, + {MFX_DEINTERLACING_FIXED_TELECINE_PATTERN, + "Fixed telecine pattern removal mode", "fixed-telecine-removal"}, + {MFX_DEINTERLACING_30FPS_OUT, "30 fps fixed output mode", "30-fps"}, + {MFX_DEINTERLACING_DETECT_INTERLACE, "Only interlace detection", + "only-detect"}, +#endif + {MFX_DEINTERLACING_ADVANCED_NOREF, + "Advanced deinterlacing mode without using of reference frames", + "advanced-no-ref"}, + {MFX_DEINTERLACING_ADVANCED_SCD, + "Advanced deinterlacing mode with scene change detection", + "advanced-scd"}, + {MFX_DEINTERLACING_FIELD_WEAVING, "Field weaving", "field-weave"}, + {0, NULL, NULL}, + }; + + if (!type) { + type = g_enum_register_static ("GstMsdkVPPDeinterlaceMethod", values); + } + return type; +} diff --git a/sys/msdk/msdk-enums.h b/sys/msdk/msdk-enums.h index dde0cc5..14c7d46 100644 --- a/sys/msdk/msdk-enums.h +++ b/sys/msdk/msdk-enums.h @@ -60,8 +60,23 @@ GType gst_msdkenc_adaptive_b_get_type (void); /*========= MSDK VPP Enums =========================*/ + GType gst_msdkvpp_rotation_get_type (void); +typedef enum +{ + GST_MSDKVPP_DEINTERLACE_MODE_AUTO = 0, + GST_MSDKVPP_DEINTERLACE_MODE_INTERLACED, + GST_MSDKVPP_DEINTERLACE_MODE_DISABLED, +} GstMskdVPPDeinterlaceMode; + +GType +gst_msdkvpp_deinterlace_mode_get_type (void); + +#define _MFX_DEINTERLACE_METHOD_NONE 0 +GType +gst_msdkvpp_deinterlace_method_get_type (void); + G_END_DECLS #endif diff --git a/sys/msdk/msdk.c b/sys/msdk/msdk.c index aaeffc4..e2c80bf 100644 --- a/sys/msdk/msdk.c +++ b/sys/msdk/msdk.c @@ -265,7 +265,9 @@ gst_msdk_set_mfx_frame_info_from_video_info (mfxFrameInfo * mfx_info, mfx_info->FrameRateExtD = GST_VIDEO_INFO_FPS_D (info); mfx_info->AspectRatioW = GST_VIDEO_INFO_PAR_N (info); mfx_info->AspectRatioH = GST_VIDEO_INFO_PAR_D (info); - mfx_info->PicStruct = MFX_PICSTRUCT_PROGRESSIVE; /* this is by default */ + mfx_info->PicStruct = + !GST_VIDEO_INFO_IS_INTERLACED (info) ? MFX_PICSTRUCT_PROGRESSIVE : + MFX_PICSTRUCT_UNKNOWN; mfx_info->FourCC = gst_msdk_get_mfx_fourcc_from_format (GST_VIDEO_INFO_FORMAT (info)); mfx_info->ChromaFormat = -- 2.7.4