msdk: vpp: Add deinterlacing support

https://bugzilla.gnome.org/show_bug.cgi?id=793705
This commit is contained in:
Sreerenj Balachandran 2018-03-06 13:52:04 +00:00
parent 36e81744d1
commit f5a3d3d799
7 changed files with 230 additions and 6 deletions

View file

@ -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);
}

View file

@ -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];

View file

@ -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,
@ -406,6 +426,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;
}
}
/**

View file

@ -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 */

View file

@ -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;
}

View file

@ -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

View file

@ -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 =