emeta->width = emeta->height = emeta->n_planes = 0;
memset (emeta->offset, 0, sizeof (emeta->offset));
memset (emeta->stride, 0, sizeof (emeta->stride));
+ gst_video_alignment_reset (&emeta->alignment);
emeta->map = NULL;
emeta->unmap = NULL;
for (i = 0; i < dmeta->n_planes; i++) {
dmeta->offset[i] = smeta->offset[i];
dmeta->stride[i] = smeta->stride[i];
+ dmeta->alignment = smeta->alignment;
}
dmeta->map = smeta->map;
dmeta->unmap = smeta->unmap;
}
static gboolean
+gst_video_meta_validate_alignment (GstVideoMeta * meta,
+ gsize plane_size[GST_VIDEO_MAX_PLANES])
+{
+ GstVideoInfo info;
+ guint i;
+
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, meta->format, meta->width, meta->height);
+
+ if (!gst_video_info_align_full (&info, &meta->alignment, plane_size)) {
+ GST_WARNING ("Failed to align meta with its alignment");
+ return FALSE;
+ }
+
+ for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&info); i++) {
+ if (GST_VIDEO_INFO_PLANE_STRIDE (&info, i) != meta->stride[i]) {
+ GST_WARNING
+ ("Stride of plane %d defined in meta (%d) is different from the one computed from the alignment (%d)",
+ i, meta->stride[i], GST_VIDEO_INFO_PLANE_STRIDE (&info, i));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * gst_video_meta_set_alignment:
+ * @meta: a #GstVideoMeta
+ * @alignment: a #GstVideoAlignment
+ *
+ * Set the alignment of @meta to @alignment. This function checks that
+ * the paddings defined in @alignment are compatible with the strides
+ * defined in @meta and will fail to update if they are not.
+ *
+ * Returns: %TRUE if @alignment's meta has been updated, %FALSE if not
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_video_meta_set_alignment (GstVideoMeta * meta, GstVideoAlignment alignment)
+{
+ GstVideoAlignment old;
+
+ g_return_val_if_fail (meta, FALSE);
+
+ old = meta->alignment;
+ meta->alignment = alignment;
+
+ if (!gst_video_meta_validate_alignment (meta, NULL)) {
+ /* Invalid alignment, restore the previous one */
+ meta->alignment = old;
+ return FALSE;
+ }
+
+ GST_LOG ("Set alignment on meta: padding %u-%ux%u-%u", alignment.padding_top,
+ alignment.padding_left, alignment.padding_right,
+ alignment.padding_bottom);
+
+ return TRUE;
+}
+
+/**
+ * gst_video_meta_get_plane_size:
+ * @meta: a #GstVideoMeta
+ * @plane_size: (out): array used to store the plane sizes
+ *
+ * Compute the size, in bytes, of each video plane described in @meta including
+ * any padding and alignment constraint defined in @meta->alignment.
+ *
+ * Returns: %TRUE if @meta's alignment is valid and @plane_size has been
+ * updated, %FALSE otherwise
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_video_meta_get_plane_size (GstVideoMeta * meta,
+ gsize plane_size[GST_VIDEO_MAX_PLANES])
+{
+ g_return_val_if_fail (meta, FALSE);
+ g_return_val_if_fail (plane_size, FALSE);
+
+ return gst_video_meta_validate_alignment (meta, plane_size);
+}
+
+/**
+ * gst_video_meta_get_plane_height:
+ * @meta: a #GstVideoMeta
+ * @plane_height: (out): array used to store the plane height
+ *
+ * Compute the padded height of each plane from @meta (padded size
+ * divided by stride).
+ *
+ * It is not valid to call this function with a meta associated to a
+ * TILED video format.
+ *
+ * Returns: %TRUE if @meta's alignment is valid and @plane_height has been
+ * updated, %FALSE otherwise
+ *
+ * Since: 1.18
+ */
+gboolean
+gst_video_meta_get_plane_height (GstVideoMeta * meta,
+ guint plane_height[GST_VIDEO_MAX_PLANES])
+{
+ gsize plane_size[GST_VIDEO_MAX_PLANES];
+ guint i;
+ GstVideoInfo info;
+
+ g_return_val_if_fail (meta, FALSE);
+ g_return_val_if_fail (plane_height, FALSE);
+
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, meta->format, meta->width, meta->height);
+ g_return_val_if_fail (!GST_VIDEO_FORMAT_INFO_IS_TILED (&info), FALSE);
+
+ if (!gst_video_meta_get_plane_size (meta, plane_size))
+ return FALSE;
+
+ for (i = 0; i < meta->n_planes; i++) {
+ if (!meta->stride[i])
+ plane_height[i] = 0;
+ else
+ plane_height[i] = plane_size[i] / meta->stride[i];
+ }
+
+ for (; i < GST_VIDEO_MAX_PLANES; i++)
+ plane_height[i] = 0;
+
+ return TRUE;
+}
+
+static gboolean
gst_video_crop_meta_transform (GstBuffer * dest, GstMeta * meta,
GstBuffer * buffer, GQuark type, gpointer data)
{
GST_END_TEST;
+GST_START_TEST (test_video_meta_align)
+{
+ GstBuffer *buf;
+ GstVideoInfo info;
+ GstVideoMeta *meta;
+ gsize plane_size[GST_VIDEO_MAX_PLANES];
+ guint plane_height[GST_VIDEO_MAX_PLANES];
+ GstVideoAlignment alig;
+
+ buf = gst_buffer_new ();
+
+ /* NV12 no alignment */
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_NV12, 1920, 1080);
+
+ meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&info), GST_VIDEO_INFO_WIDTH (&info),
+ GST_VIDEO_INFO_HEIGHT (&info), GST_VIDEO_INFO_N_PLANES (&info),
+ info.offset, info.stride);
+
+ g_assert_cmpuint (meta->alignment.padding_top, ==, 0);
+ g_assert_cmpuint (meta->alignment.padding_bottom, ==, 0);
+ g_assert_cmpuint (meta->alignment.padding_left, ==, 0);
+ g_assert_cmpuint (meta->alignment.padding_right, ==, 0);
+
+ g_assert (gst_video_meta_get_plane_size (meta, plane_size));
+ g_assert_cmpuint (plane_size[0], ==, 1920 * 1080);
+ g_assert_cmpuint (plane_size[1], ==, 1920 * 1080 * 0.5);
+ g_assert_cmpuint (plane_size[2], ==, 0);
+ g_assert_cmpuint (plane_size[3], ==, 0);
+
+ g_assert (gst_video_meta_get_plane_height (meta, plane_height));
+ g_assert_cmpuint (plane_height[0], ==, 1080);
+ g_assert_cmpuint (plane_height[1], ==, 540);
+ g_assert_cmpuint (plane_height[2], ==, 0);
+ g_assert_cmpuint (plane_height[3], ==, 0);
+
+ /* horizontal alignment */
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_NV12, 1920, 1080);
+
+ gst_video_alignment_reset (&alig);
+ alig.padding_left = 2;
+ alig.padding_right = 6;
+
+ g_assert (gst_video_info_align (&info, &alig));
+
+ meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&info), GST_VIDEO_INFO_WIDTH (&info),
+ GST_VIDEO_INFO_HEIGHT (&info), GST_VIDEO_INFO_N_PLANES (&info),
+ info.offset, info.stride);
+ g_assert (gst_video_meta_set_alignment (meta, alig));
+
+ g_assert_cmpuint (meta->alignment.padding_top, ==, 0);
+ g_assert_cmpuint (meta->alignment.padding_bottom, ==, 0);
+ g_assert_cmpuint (meta->alignment.padding_left, ==, 2);
+ g_assert_cmpuint (meta->alignment.padding_right, ==, 6);
+
+ g_assert (gst_video_meta_get_plane_size (meta, plane_size));
+ g_assert_cmpuint (plane_size[0], ==, 1928 * 1080);
+ g_assert_cmpuint (plane_size[1], ==, 1928 * 1080 * 0.5);
+ g_assert_cmpuint (plane_size[2], ==, 0);
+ g_assert_cmpuint (plane_size[3], ==, 0);
+
+ g_assert (gst_video_meta_get_plane_height (meta, plane_height));
+ g_assert_cmpuint (plane_height[0], ==, 1080);
+ g_assert_cmpuint (plane_height[1], ==, 540);
+ g_assert_cmpuint (plane_height[2], ==, 0);
+ g_assert_cmpuint (plane_height[3], ==, 0);
+
+ /* vertical alignment */
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_NV12, 1920, 1080);
+
+ gst_video_alignment_reset (&alig);
+ alig.padding_top = 2;
+ alig.padding_bottom = 6;
+
+ g_assert (gst_video_info_align (&info, &alig));
+
+ meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&info), GST_VIDEO_INFO_WIDTH (&info),
+ GST_VIDEO_INFO_HEIGHT (&info), GST_VIDEO_INFO_N_PLANES (&info),
+ info.offset, info.stride);
+ g_assert (gst_video_meta_set_alignment (meta, alig));
+
+ g_assert_cmpuint (meta->alignment.padding_top, ==, 2);
+ g_assert_cmpuint (meta->alignment.padding_bottom, ==, 6);
+ g_assert_cmpuint (meta->alignment.padding_left, ==, 0);
+ g_assert_cmpuint (meta->alignment.padding_right, ==, 0);
+
+ g_assert (gst_video_meta_get_plane_size (meta, plane_size));
+ g_assert_cmpuint (plane_size[0], ==, 1920 * 1088);
+ g_assert_cmpuint (plane_size[1], ==, 1920 * 1088 * 0.5);
+ g_assert_cmpuint (plane_size[2], ==, 0);
+ g_assert_cmpuint (plane_size[3], ==, 0);
+
+ g_assert (gst_video_meta_get_plane_height (meta, plane_height));
+ g_assert_cmpuint (plane_height[0], ==, 1088);
+ g_assert_cmpuint (plane_height[1], ==, 544);
+ g_assert_cmpuint (plane_height[2], ==, 0);
+ g_assert_cmpuint (plane_height[3], ==, 0);
+
+ /* incompatible alignment */
+ gst_video_info_init (&info);
+ gst_video_info_set_format (&info, GST_VIDEO_FORMAT_NV12, 1920, 1080);
+
+ gst_video_alignment_reset (&alig);
+ alig.padding_right = 2;
+
+ meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE,
+ GST_VIDEO_INFO_FORMAT (&info), GST_VIDEO_INFO_WIDTH (&info),
+ GST_VIDEO_INFO_HEIGHT (&info), GST_VIDEO_INFO_N_PLANES (&info),
+ info.offset, info.stride);
+ g_assert (!gst_video_meta_set_alignment (meta, alig));
+
+ gst_buffer_unref (buf);
+}
+
+GST_END_TEST;
+
static Suite *
video_suite (void)
{
tcase_add_test (tc_chain, test_video_color_from_to_iso);
tcase_add_test (tc_chain, test_video_format_info_plane_to_components);
tcase_add_test (tc_chain, test_video_info_align);
+ tcase_add_test (tc_chain, test_video_meta_align);
return s;
}