video: Add GST_VIDEO_INTERLACE_MODE_ALTERNATE

Add a new interlace mode enum to represent buffers containing a single
field of an interlaced video in a buffer. The name is based on the
equivalent video format in the V4L2 API, V4L2_FIELD_ALTERNATE:

https://01.org/linuxgraphics/gfx-docs/drm/media/uapi/v4l/field-order.html

Since caps fields are optional, we also introduce a new caps feature,
"format:Interlaced" that always goes with "alternate" interlace mode to ensure
that caps for this incompatible format are incompatible with other interlaced
and progressive video caps.

https://bugzilla.gnome.org/show_bug.cgi?id=796106
This commit is contained in:
Zeeshan Ali 2018-05-04 16:16:28 +02:00 committed by Nicolas Dufresne
parent 8fa9fda226
commit bd9c7b36d8
3 changed files with 90 additions and 3 deletions

View file

@ -237,7 +237,8 @@ static const gchar *interlace_mode[] = {
"progressive",
"interleaved",
"mixed",
"fields"
"fields",
"alternate"
};
/**
@ -604,6 +605,15 @@ gst_video_info_to_caps (GstVideoInfo * info)
NULL);
}
if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE) {
/* 'alternate' mode must always be accompanied by interlaced caps feature.
*/
GstCapsFeatures *features;
features = gst_caps_features_new (GST_CAPS_FEATURE_FORMAT_INTERLACED, NULL);
gst_caps_set_features (caps, 0, features);
}
if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
const gchar *caps_str = NULL;
@ -683,7 +693,11 @@ fill_planes (GstVideoInfo * info)
gint bpp = 0, i;
width = (gsize) info->width;
height = (gsize) info->height;
if (GST_VIDEO_INFO_INTERLACE_MODE (info) ==
GST_VIDEO_INTERLACE_MODE_ALTERNATE)
height = (gsize) info->height / 2;
else
height = (gsize) info->height;
/* Sanity check the resulting frame size for overflows */
for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)

View file

@ -30,6 +30,16 @@ G_BEGIN_DECLS
typedef struct _GstVideoInfo GstVideoInfo;
/**
* GST_CAPS_FEATURE_FORMAT_INTERLACED:
*
* Name of the caps feature indicating that the stream is interlaced. Currently
* it is only used for video.
*
* Since: 1.16.
*/
#define GST_CAPS_FEATURE_FORMAT_INTERLACED "format:Interlaced"
/**
* GstVideoInterlaceMode:
* @GST_VIDEO_INTERLACE_MODE_PROGRESSIVE: all frames are progressive
@ -44,6 +54,11 @@ typedef struct _GstVideoInfo GstVideoInfo;
* Each field has only half the amount of lines as noted in the
* height property. This mode requires multiple GstVideoMeta metadata
* to describe the fields.
* @GST_VIDEO_INTERLACE_MODE_ALTERNATE: 1 field is stored in one buffer,
* @GST_VIDEO_BUFFER_FLAG_TF or @GST_VIDEO_BUFFER_FLAG_BF indicates if
* the buffer is carrying the top or bottom field, respectively. The top and
* bottom buffers are expected to alternate in the pipeline, with this mode
* (Since: 1.16).
*
* The possible values of the #GstVideoInterlaceMode describing the interlace
* mode of the stream.
@ -52,7 +67,8 @@ typedef enum {
GST_VIDEO_INTERLACE_MODE_PROGRESSIVE = 0,
GST_VIDEO_INTERLACE_MODE_INTERLEAVED,
GST_VIDEO_INTERLACE_MODE_MIXED,
GST_VIDEO_INTERLACE_MODE_FIELDS
GST_VIDEO_INTERLACE_MODE_FIELDS,
GST_VIDEO_INTERLACE_MODE_ALTERNATE,
} GstVideoInterlaceMode;
GST_VIDEO_API

View file

@ -1194,6 +1194,62 @@ GST_START_TEST (test_video_size_from_caps)
GST_END_TEST;
GST_START_TEST (test_interlace_mode)
{
GstVideoInfo vinfo;
GstCaps *caps;
GstStructure *structure;
GstCapsFeatures *features;
const char *mode_str;
int mode;
gst_video_info_init (&vinfo);
/* Progressive */
gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_YV12, 320, 240);
GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
caps = gst_video_info_to_caps (&vinfo);
fail_unless (caps != NULL);
structure = gst_caps_get_structure (caps, 0);
fail_unless (structure != NULL);
mode_str = gst_structure_get_string (structure, "interlace-mode");
mode = gst_video_interlace_mode_from_string (mode_str);
fail_unless (mode == GST_VIDEO_INTERLACE_MODE_PROGRESSIVE);
/* Converting back to video info */
fail_unless (gst_video_info_from_caps (&vinfo, caps));
fail_unless (GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) ==
GST_VIDEO_INTERLACE_MODE_PROGRESSIVE);
gst_caps_unref (caps);
/* Interlaced with alternate frame on buffers */
gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_YV12, 320, 240);
GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) = GST_VIDEO_INTERLACE_MODE_ALTERNATE;
caps = gst_video_info_to_caps (&vinfo);
fail_unless (caps != NULL);
structure = gst_caps_get_structure (caps, 0);
fail_unless (structure != NULL);
mode_str = gst_structure_get_string (structure, "interlace-mode");
mode = gst_video_interlace_mode_from_string (mode_str);
fail_unless (mode == GST_VIDEO_INTERLACE_MODE_ALTERNATE);
/* 'alternate' mode must always be accompanied by interlaced caps feature. */
features = gst_caps_get_features (caps, 0);
fail_unless (gst_caps_features_contains (features,
GST_CAPS_FEATURE_FORMAT_INTERLACED));
/* Converting back to video info */
fail_unless (gst_video_info_from_caps (&vinfo, caps));
fail_unless (GST_VIDEO_INFO_INTERLACE_MODE (&vinfo) ==
GST_VIDEO_INTERLACE_MODE_ALTERNATE);
gst_caps_unref (caps);
}
GST_END_TEST;
GST_START_TEST (test_overlay_composition)
{
GstVideoOverlayComposition *comp1, *comp2;
@ -2851,6 +2907,7 @@ video_suite (void)
tcase_add_test (tc_chain, test_convert_frame);
tcase_add_test (tc_chain, test_convert_frame_async);
tcase_add_test (tc_chain, test_video_size_from_caps);
tcase_add_test (tc_chain, test_interlace_mode);
tcase_add_test (tc_chain, test_overlay_composition);
tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
tcase_add_test (tc_chain, test_overlay_composition_global_alpha);