diff --git a/subprojects/gst-docs/markdown/additional/design/dmabuf.md b/subprojects/gst-docs/markdown/additional/design/dmabuf.md index e713d7dc72..d89c474800 100644 --- a/subprojects/gst-docs/markdown/additional/design/dmabuf.md +++ b/subprojects/gst-docs/markdown/additional/design/dmabuf.md @@ -121,10 +121,11 @@ format. For example, `NV12:0x0100000000000002` is a new video format combined by video format NV12 and the modifier `0x0100000000000002`. It's not NV12 and it's not its subset either. -*DRM_FORMAT* can be printed by using -`GST_FOURCC_FORMAT` and `GST_FOURCC_ARGS` macros from the -`DRM_FORMAT_*` constants, it is NOT a `GstVideoFormat`, so it would be -different from the content of the `format` field in a non-dmabuf caps. +The 7 least significant bits of *DRM_FORMAT* is a fourcc. That fourcc is used +to serialize it into a string. The result is different from the serialization of +gstreamer video formats. The 8th bit is used to indicate that tis is a big +endian format. In this case, the serializer will postfix the name with `_BE`. + A modifier must always be present, except if the modifier is linear, then it should not be included, so `NV12:0x0000000000000000` is invalid, it must be `drm-format=NV12`. DRM fourcc are used diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/video-info-dma.c b/subprojects/gst-plugins-base/gst-libs/gst/video/video-info-dma.c index 7908f22e3f..181d1fb645 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/video-info-dma.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/video-info-dma.c @@ -434,12 +434,18 @@ gst_video_dma_drm_fourcc_from_string (const gchar * format_str, const gchar *mod_str; guint32 fourcc = DRM_FORMAT_INVALID; guint64 m = DRM_FORMAT_MOD_INVALID; + gboolean big_endian = FALSE; g_return_val_if_fail (format_str != NULL, 0); mod_str = strchr (format_str, ':'); if (mod_str) { - if (mod_str - format_str != 4) { + gint fmt_len = mod_str - format_str; + + /* Handle big endian (FOURCC_BE) case */ + if (fmt_len == 7 && strstr (format_str + 4, "_BE")) { + big_endian = TRUE; + } else if (fmt_len != 4) { /* fourcc always has 4 characters. */ GST_DEBUG ("%s is not a drm string", format_str); return DRM_FORMAT_INVALID; @@ -458,7 +464,12 @@ gst_video_dma_drm_fourcc_from_string (const gchar * format_str, return DRM_FORMAT_INVALID; } } else { - if (strlen (format_str) != 4) { + gint fmt_len = strlen (format_str); + + /* Handle big endian (FOURCC_BE) case */ + if (fmt_len == 7 && strstr (format_str + 4, "_BE")) { + big_endian = TRUE; + } else if (fmt_len != 4) { /* fourcc always has 4 characters. */ GST_DEBUG ("%s is not a drm string", format_str); return DRM_FORMAT_INVALID; @@ -470,6 +481,9 @@ gst_video_dma_drm_fourcc_from_string (const gchar * format_str, fourcc = GST_MAKE_FOURCC (format_str[0], format_str[1], format_str[2], format_str[3]); + if (big_endian) + fourcc |= DRM_FORMAT_BIG_ENDIAN; + if (modifier) *modifier = m; @@ -492,16 +506,23 @@ gst_video_dma_drm_fourcc_from_string (const gchar * format_str, gchar * gst_video_dma_drm_fourcc_to_string (guint32 fourcc, guint64 modifier) { + gboolean big_endian = FALSE; gchar *s; g_return_val_if_fail (fourcc != DRM_FORMAT_INVALID, NULL); g_return_val_if_fail (modifier != DRM_FORMAT_MOD_INVALID, NULL); + if (fourcc & DRM_FORMAT_BIG_ENDIAN) { + big_endian = TRUE; + fourcc &= ~DRM_FORMAT_BIG_ENDIAN; + } + if (modifier == DRM_FORMAT_MOD_LINEAR) { - s = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc)); + s = g_strdup_printf ("%" GST_FOURCC_FORMAT "%s", GST_FOURCC_ARGS (fourcc), + big_endian ? "_BE" : ""); } else { - s = g_strdup_printf ("%" GST_FOURCC_FORMAT ":0x%016" G_GINT64_MODIFIER "x", - GST_FOURCC_ARGS (fourcc), modifier); + s = g_strdup_printf ("%" GST_FOURCC_FORMAT "%s:0x%016" G_GINT64_MODIFIER + "x", GST_FOURCC_ARGS (fourcc), big_endian ? "_BE" : "", modifier); } return s; diff --git a/subprojects/gst-plugins-base/tests/check/libs/video.c b/subprojects/gst-plugins-base/tests/check/libs/video.c index d7442032e8..78a1786173 100644 --- a/subprojects/gst-plugins-base/tests/check/libs/video.c +++ b/subprojects/gst-plugins-base/tests/check/libs/video.c @@ -4310,6 +4310,32 @@ GST_START_TEST (test_video_meta_serialize) GST_END_TEST; +GST_START_TEST (test_dma_drm_big_engian) +{ + const guint32 fourcc = GST_MAKE_FOURCC ('A', 'B', 'C', 'D') | 1U << 31; + + gchar *fmt = gst_video_dma_drm_fourcc_to_string (fourcc, 0); + fail_unless (g_strcmp0 (fmt, "ABCD_BE") == 0); + + gchar *fmt_mod = gst_video_dma_drm_fourcc_to_string (fourcc, 1); + fail_unless (g_strcmp0 (fmt_mod, "ABCD_BE:0x0000000000000001") == 0); + + guint64 parsed_mod; + guint32 parsed_fourcc = + gst_video_dma_drm_fourcc_from_string (fmt, &parsed_mod); + g_assert_cmpuint (parsed_fourcc, ==, fourcc); + g_assert_cmpuint (parsed_mod, ==, G_GUINT64_CONSTANT (0)); + + parsed_fourcc = gst_video_dma_drm_fourcc_from_string (fmt_mod, &parsed_mod); + g_assert_cmpuint (parsed_fourcc, ==, fourcc); + g_assert_cmpuint (parsed_mod, ==, G_GUINT64_CONSTANT (1)); + + g_free (fmt); + g_free (fmt_mod); +} + +GST_END_TEST; + static Suite * video_suite (void) { @@ -4370,6 +4396,7 @@ video_suite (void) tcase_add_test (tc_chain, test_info_dma_drm); tcase_add_test (tc_chain, test_video_meta_serialize); tcase_add_test (tc_chain, test_video_convert_with_config_update); + tcase_add_test (tc_chain, test_dma_drm_big_engian); return s; }