From ca4240bd035321820585eb88a6a96b3e22bd8dd5 Mon Sep 17 00:00:00 2001 From: Vivia Nikolaidou Date: Tue, 2 Feb 2021 20:33:27 +0200 Subject: [PATCH] videoconvert: Support for alternate-field interlacing Treat the data just like normal data with half the height. Also treat it as progressive when converting from/to I420 because it requires different handling for chroma subsampling. Part-of: --- gst-libs/gst/video/video-converter.c | 50 ++++++++++++++++++++++++------------ gst/videoconvert/gstvideoconvert.c | 18 +++++++++++-- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/gst-libs/gst/video/video-converter.c b/gst-libs/gst/video/video-converter.c index a259113..5de75b8 100644 --- a/gst-libs/gst/video/video-converter.c +++ b/gst-libs/gst/video/video-converter.c @@ -1611,10 +1611,12 @@ chain_vscale (GstVideoConverter * convert, GstLineCache * prev, gint idx) method = GET_OPT_RESAMPLER_METHOD (convert); taps = GET_OPT_RESAMPLER_TAPS (convert); - if (GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info)) { + if (GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info) + && (GST_VIDEO_INFO_INTERLACE_MODE (&convert->in_info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE)) { convert->v_scaler_i[idx] = - gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_INTERLACED, - taps, convert->in_height, convert->out_height, convert->config); + gst_video_scaler_new (method, GST_VIDEO_SCALER_FLAG_INTERLACED, taps, + convert->in_height, convert->out_height, convert->config); gst_video_scaler_get_coeff (convert->v_scaler_i[idx], 0, NULL, &taps_i); backlog = taps_i; @@ -2281,9 +2283,9 @@ gst_video_converter_new_with_pool (const GstVideoInfo * in_info, gst_video_converter_set_config (convert, config); convert->in_maxwidth = GST_VIDEO_INFO_WIDTH (in_info); - convert->in_maxheight = GST_VIDEO_INFO_HEIGHT (in_info); + convert->in_maxheight = GST_VIDEO_INFO_FIELD_HEIGHT (in_info); convert->out_maxwidth = GST_VIDEO_INFO_WIDTH (out_info); - convert->out_maxheight = GST_VIDEO_INFO_HEIGHT (out_info); + convert->out_maxheight = GST_VIDEO_INFO_FIELD_HEIGHT (out_info); convert->in_x = get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_SRC_X, 0); convert->in_y = get_opt_int (convert, GST_VIDEO_CONVERTER_OPT_SRC_Y, 0); @@ -2694,7 +2696,7 @@ gst_video_converter_frame (GstVideoConverter * convert, GST_VIDEO_FRAME_FORMAT (src) || GST_VIDEO_INFO_WIDTH (&convert->in_info) > GST_VIDEO_FRAME_WIDTH (src) - || GST_VIDEO_INFO_HEIGHT (&convert->in_info) > + || GST_VIDEO_INFO_FIELD_HEIGHT (&convert->in_info) > GST_VIDEO_FRAME_HEIGHT (src))) { g_critical ("Input video frame does not match configuration"); return; @@ -2703,7 +2705,7 @@ gst_video_converter_frame (GstVideoConverter * convert, GST_VIDEO_FRAME_FORMAT (dest) || GST_VIDEO_INFO_WIDTH (&convert->out_info) > GST_VIDEO_FRAME_WIDTH (dest) - || GST_VIDEO_INFO_HEIGHT (&convert->out_info) > + || GST_VIDEO_INFO_FIELD_HEIGHT (&convert->out_info) > GST_VIDEO_FRAME_HEIGHT (dest))) { g_critical ("Output video frame does not match configuration"); return; @@ -2753,7 +2755,9 @@ video_converter_compute_resample (GstVideoConverter * convert, gint idx) in_info->chroma_site != out_info->chroma_site || in_info->width != out_info->width || in_info->height != out_info->height) { - if (GST_VIDEO_INFO_IS_INTERLACED (in_info)) { + if (GST_VIDEO_INFO_IS_INTERLACED (in_info) + && GST_VIDEO_INFO_INTERLACE_MODE (in_info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE) { if (!CHECK_CHROMA_DOWNSAMPLE (convert)) convert->upsample_i[idx] = gst_video_chroma_resample_new (0, in_info->chroma_site, GST_VIDEO_CHROMA_FLAG_INTERLACED, @@ -3309,7 +3313,9 @@ convert_I420_YUY2 (GstVideoConverter * convert, const GstVideoFrame * src, int i; gint width = convert->in_width; gint height = convert->in_height; - gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src); + gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src) + && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE); gint h2; FConvertTask *tasks; FConvertTask **tasks_p; @@ -3382,7 +3388,9 @@ convert_I420_UYVY (GstVideoConverter * convert, const GstVideoFrame * src, int i; gint width = convert->in_width; gint height = convert->in_height; - gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src); + gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src) + && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE); gint h2; FConvertTask *tasks; FConvertTask **tasks_p; @@ -3455,7 +3463,9 @@ convert_I420_AYUV (GstVideoConverter * convert, const GstVideoFrame * src, int i; gint width = convert->in_width; gint height = convert->in_height; - gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src); + gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src) + && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE); guint8 alpha = MIN (convert->alpha_value, 255); gint h2; FConvertTask *tasks; @@ -3533,7 +3543,9 @@ convert_YUY2_I420 (GstVideoConverter * convert, const GstVideoFrame * src, int i; gint width = convert->in_width; gint height = convert->in_height; - gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src); + gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src) + && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE); gint h2; FConvertTask *tasks; FConvertTask **tasks_p; @@ -3692,7 +3704,9 @@ convert_v210_I420 (GstVideoConverter * convert, const GstVideoFrame * src, int i; gint width = convert->in_width; gint height = convert->in_height; - gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src); + gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src) + && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE); gint h2; FConvertTask *tasks; FConvertTask **tasks_p; @@ -4075,7 +4089,9 @@ convert_UYVY_I420 (GstVideoConverter * convert, const GstVideoFrame * src, int i; gint width = convert->in_width; gint height = convert->in_height; - gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src); + gboolean interlaced = GST_VIDEO_FRAME_IS_INTERLACED (src) + && (GST_VIDEO_INFO_INTERLACE_MODE (&src->info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE); gint h2; FConvertTask *tasks; FConvertTask **tasks_p; @@ -6519,7 +6535,9 @@ setup_scale (GstVideoConverter * convert) n_planes = GST_VIDEO_INFO_N_PLANES (out_info); - interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info); + interlaced = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info) + && GST_VIDEO_INFO_INTERLACE_MODE (&convert->in_info) != + GST_VIDEO_INTERLACE_MODE_ALTERNATE; method = GET_OPT_RESAMPLER_METHOD (convert); if (method == GST_VIDEO_RESAMPLER_METHOD_NEAREST) @@ -7247,7 +7265,7 @@ video_converter_lookup_fastpath (GstVideoConverter * convert) guint in_bpp, out_bpp; width = GST_VIDEO_INFO_WIDTH (&convert->in_info); - height = GST_VIDEO_INFO_HEIGHT (&convert->in_info); + height = GST_VIDEO_INFO_FIELD_HEIGHT (&convert->in_info); if (GET_OPT_DITHER_QUANTIZATION (convert) != 1) return FALSE; diff --git a/gst/videoconvert/gstvideoconvert.c b/gst/videoconvert/gstvideoconvert.c index 00f77fa..2d5b6ee 100644 --- a/gst/videoconvert/gstvideoconvert.c +++ b/gst/videoconvert/gstvideoconvert.c @@ -111,6 +111,9 @@ static gboolean gst_video_convert_set_info (GstVideoFilter * filter, static GstFlowReturn gst_video_convert_transform_frame (GstVideoFilter * filter, GstVideoFrame * in_frame, GstVideoFrame * out_frame); +static GstCapsFeatures *features_format_interlaced, + *features_format_interlaced_sysmem; + /* copies the given caps */ static GstCaps * gst_video_convert_caps_remove_format_info (GstCaps * caps) @@ -135,10 +138,14 @@ gst_video_convert_caps_remove_format_info (GstCaps * caps) st = gst_structure_copy (st); /* Only remove format info for the cases when we can actually convert */ if (!gst_caps_features_is_any (f) - && gst_caps_features_is_equal (f, - GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)) + && (gst_caps_features_is_equal (f, + GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY) + || gst_caps_features_is_equal (f, features_format_interlaced) + || gst_caps_features_is_equal (f, + features_format_interlaced_sysmem))) { gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site", NULL); + } gst_caps_append_structure_full (res, st, gst_caps_features_copy (f)); } @@ -743,6 +750,13 @@ plugin_init (GstPlugin * plugin) _colorspace_quark = g_quark_from_static_string ("colorspace"); + features_format_interlaced = + gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL); + features_format_interlaced_sysmem = + gst_caps_features_copy (features_format_interlaced); + gst_caps_features_add (features_format_interlaced_sysmem, + GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY); + return gst_element_register (plugin, "videoconvert", GST_RANK_NONE, GST_TYPE_VIDEO_CONVERT); } -- 2.7.4