diff options
author | Ludvig Rappe <ludvigr@axis.com> | 2021-08-25 17:01:19 +0200 |
---|---|---|
committer | GStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org> | 2021-08-30 08:49:33 +0000 |
commit | 4a1d8eac31408a5e6e01183a6217899538ac0628 (patch) | |
tree | 495956f673976f107f823cf4237b04e755f2a4f5 | |
parent | 3823f9431115440afbe4b23fe832e2bff6fcfb8b (diff) | |
download | gstreamer-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.c | 52 | ||||
-rw-r--r-- | gst-libs/gst/pbutils/codec-utils.h | 7 | ||||
-rw-r--r-- | tests/check/libs/pbutils.c | 42 |
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; } |