mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
pbutils: Add function for parsing H.264 extradata
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1265>
This commit is contained in:
parent
3823f94311
commit
4a1d8eac31
3 changed files with 101 additions and 0 deletions
|
@ -818,6 +818,58 @@ gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * caps,
|
||||||
return (level != NULL && profile != NULL);
|
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 */
|
/* forked from gsth265parse.c */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -68,6 +68,13 @@ gboolean gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * ca
|
||||||
const guint8 * sps,
|
const guint8 * sps,
|
||||||
guint len);
|
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 */
|
/* H.265 */
|
||||||
|
|
||||||
GST_PBUTILS_API
|
GST_PBUTILS_API
|
||||||
|
|
|
@ -994,6 +994,47 @@ GST_START_TEST (test_pb_utils_h264_profiles)
|
||||||
|
|
||||||
GST_END_TEST;
|
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
|
#define PROFILE_TIER_LEVEL_LEN 11
|
||||||
|
|
||||||
static void
|
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_versions);
|
||||||
tcase_add_test (tc_chain, test_pb_utils_aac_get_profile);
|
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_profiles);
|
||||||
|
tcase_add_test (tc_chain, test_pb_utils_h264_get_profile_flags_level);
|
||||||
tcase_add_test (tc_chain, test_pb_utils_h265_profiles);
|
tcase_add_test (tc_chain, test_pb_utils_h265_profiles);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue