summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudvig Rappe <ludvigr@axis.com>2021-08-25 17:01:19 +0200
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>2021-08-30 08:49:33 +0000
commit4a1d8eac31408a5e6e01183a6217899538ac0628 (patch)
tree495956f673976f107f823cf4237b04e755f2a4f5
parent3823f9431115440afbe4b23fe832e2bff6fcfb8b (diff)
downloadgstreamer-plugins-base-4a1d8eac31408a5e6e01183a6217899538ac0628.tar.gz
pbutils: Add function for parsing H.264 extradata
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1265>
-rw-r--r--gst-libs/gst/pbutils/codec-utils.c52
-rw-r--r--gst-libs/gst/pbutils/codec-utils.h7
-rw-r--r--tests/check/libs/pbutils.c42
3 files changed, 101 insertions, 0 deletions
diff --git a/gst-libs/gst/pbutils/codec-utils.c b/gst-libs/gst/pbutils/codec-utils.c
index 9714f8042..7f585d1d1 100644
--- a/gst-libs/gst/pbutils/codec-utils.c
+++ b/gst-libs/gst/pbutils/codec-utils.c
@@ -818,6 +818,58 @@ gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * caps,
return (level != NULL && profile != NULL);
}
+/**
+ * gst_codec_utils_h264_get_profile_flags_level:
+ * @codec_data: H264 AVCC extradata
+ * @len: lenth of @codec_data
+ * @profile: return location for h264 profile_idc or %NULL
+ * @flags: return location for h264 constraint set flags or %NULL
+ * @level: return location h264 level_idc or %NULL
+ *
+ * Parses profile, flags, and level from a H264 AVCC extradata/sequence_header.
+ * These are most commonly retrieved from a video/x-h264 caps with a codec_data
+ * buffer.
+ * The format of H264 AVCC extradata/sequence_header is documented in the
+ * ITU-T H.264 specification section 7.3.2.1.1 as well as in ISO/IEC 14496-15
+ * section 5.3.3.1.2.
+ *
+ * Returns: %TRUE on success, %FALSE on failure
+ *
+ * Since: 1.20
+ */
+gboolean
+gst_codec_utils_h264_get_profile_flags_level (const guint8 * codec_data,
+ guint len, guint8 * profile, guint8 * flags, guint8 * level)
+{
+ gboolean ret = FALSE;
+
+ g_return_val_if_fail (codec_data != NULL, FALSE);
+
+ if (len < 7) {
+ GST_WARNING ("avc codec data is too small");
+ goto done;
+ }
+ if (codec_data[0] != 1) {
+ GST_WARNING ("failed to parse avc codec version, must be 1");
+ goto done;
+ }
+
+ if (profile) {
+ *profile = codec_data[1];
+ }
+ if (flags) {
+ *flags = codec_data[2];
+ }
+ if (level) {
+ *level = codec_data[3];
+ }
+
+ ret = TRUE;
+
+done:
+ return ret;
+}
+
/* forked from gsth265parse.c */
typedef struct
{
diff --git a/gst-libs/gst/pbutils/codec-utils.h b/gst-libs/gst/pbutils/codec-utils.h
index 2d3dc0c96..36bf0d619 100644
--- a/gst-libs/gst/pbutils/codec-utils.h
+++ b/gst-libs/gst/pbutils/codec-utils.h
@@ -68,6 +68,13 @@ gboolean gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * ca
const guint8 * sps,
guint len);
+GST_PBUTILS_API
+gboolean gst_codec_utils_h264_get_profile_flags_level (const guint8 * codecs_data,
+ guint len,
+ guint8 * profile,
+ guint8 * flags,
+ guint8 * level);
+
/* H.265 */
GST_PBUTILS_API
diff --git a/tests/check/libs/pbutils.c b/tests/check/libs/pbutils.c
index ea1092beb..846a26329 100644
--- a/tests/check/libs/pbutils.c
+++ b/tests/check/libs/pbutils.c
@@ -994,6 +994,47 @@ GST_START_TEST (test_pb_utils_h264_profiles)
GST_END_TEST;
+GST_START_TEST (test_pb_utils_h264_get_profile_flags_level)
+{
+ gboolean ret = FALSE;
+ guint codec_data_len = 7;
+ guint8 codec_data[] = { 0x01, 0x64, 0x00, 0x32, 0x00, 0x00, 0x00 };
+ guint8 codec_data_bad_version[] =
+ { 0x00, 0x64, 0x00, 0x32, 0x00, 0x00, 0x00 };
+ guint8 profile;
+ guint8 flags;
+ guint8 level;
+
+ /* happy path */
+ ret =
+ gst_codec_utils_h264_get_profile_flags_level (codec_data, codec_data_len,
+ &profile, &flags, &level);
+ fail_unless (ret == TRUE);
+ fail_unless (profile == 0x64);
+ fail_unless (flags == 0x00);
+ fail_unless (level == 0x32);
+
+ /* happy path, return locations null */
+ ret =
+ gst_codec_utils_h264_get_profile_flags_level (codec_data, codec_data_len,
+ NULL, NULL, NULL);
+ fail_unless (ret == TRUE);
+
+ /* data too short */
+ ret =
+ gst_codec_utils_h264_get_profile_flags_level (codec_data, 6, &profile,
+ &flags, &level);
+ fail_unless (ret == FALSE);
+
+ /* wrong codec version */
+ ret =
+ gst_codec_utils_h264_get_profile_flags_level (codec_data_bad_version,
+ codec_data_len, &profile, &flags, &level);
+ fail_unless (ret == FALSE);
+}
+
+GST_END_TEST;
+
#define PROFILE_TIER_LEVEL_LEN 11
static void
@@ -1318,6 +1359,7 @@ libgstpbutils_suite (void)
tcase_add_test (tc_chain, test_pb_utils_versions);
tcase_add_test (tc_chain, test_pb_utils_aac_get_profile);
tcase_add_test (tc_chain, test_pb_utils_h264_profiles);
+ tcase_add_test (tc_chain, test_pb_utils_h264_get_profile_flags_level);
tcase_add_test (tc_chain, test_pb_utils_h265_profiles);
return s;
}