diff --git a/gst-libs/gst/video/video-info.c b/gst-libs/gst/video/video-info.c index 5b09afbf7d..0e764a7c7c 100644 --- a/gst-libs/gst/video/video-info.c +++ b/gst-libs/gst/video/video-info.c @@ -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++) diff --git a/gst-libs/gst/video/video-info.h b/gst-libs/gst/video/video-info.h index 002679b161..f9de93833a 100644 --- a/gst-libs/gst/video/video-info.h +++ b/gst-libs/gst/video/video-info.h @@ -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 diff --git a/tests/check/libs/video.c b/tests/check/libs/video.c index 7fffcddbfe..ade6276e9a 100644 --- a/tests/check/libs/video.c +++ b/tests/check/libs/video.c @@ -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);