From: Tim-Philipp Müller Date: Sat, 22 Oct 2022 10:13:10 +0000 (+0100) Subject: fdkaac: add minimal unit test X-Git-Tag: 1.22.0~703 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fupstream%2Fgstreamer.git;a=commitdiff_plain;h=e703374ff823f52c4a0463b339a9829ccf699822 fdkaac: add minimal unit test Part-of: --- diff --git a/subprojects/gst-plugins-bad/tests/check/elements/fdkaac.c b/subprojects/gst-plugins-bad/tests/check/elements/fdkaac.c new file mode 100644 index 0000000..067f59f --- /dev/null +++ b/subprojects/gst-plugins-bad/tests/check/elements/fdkaac.c @@ -0,0 +1,271 @@ +/* GStreamer unit test for fdk-aac elements + * + * Copyright (C) 2022 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +typedef struct +{ + const gchar *base_profile; + const gchar *profile; + guint8 buf_hdr[16]; + guint8 codec_data[16]; + gsize codec_data_len; +} AacSample; + +static AacSample +encode_with_caps (const gchar * caps_str) +{ + GstElement *pipe, *sink; + gchar *pipeline_str; + GError *err = NULL; + GstSample *sample; + AacSample aac_sample = { NULL, }; + + GST_INFO ("Encoding to %s", caps_str); + + pipeline_str = + g_strdup_printf ("audiotestsrc ! fdkaacenc ! appsink name=sink caps=%s", + caps_str); + + pipe = gst_parse_launch (pipeline_str, &err); + g_free (pipeline_str); + fail_if (err != NULL, "Error creating pipeline: %s", err->message); + + sink = gst_bin_get_by_name (GST_BIN (pipe), "sink"); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + + sample = gst_app_sink_pull_preroll (GST_APP_SINK (sink)); + fail_unless (sample != NULL); + { + GstCaps *caps = gst_sample_get_caps (sample); + GstStructure *s = gst_caps_get_structure (caps, 0); + const GValue *val; + GstMapInfo map; + GstBuffer *buf; + + GST_INFO ("Got caps %" GST_PTR_FORMAT, caps); + aac_sample.base_profile = + g_intern_string (gst_structure_get_string (s, "base-profile")); + aac_sample.profile = + g_intern_string (gst_structure_get_string (s, "profile")); + + val = gst_structure_get_value (s, "codec_data"); + if (val != NULL) { + buf = gst_value_get_buffer (val); + gst_buffer_map (buf, &map, GST_MAP_READ); + g_assert (map.size <= 16); + memcpy (aac_sample.codec_data, map.data, map.size); + aac_sample.codec_data_len = map.size; + gst_buffer_unmap (buf, &map); + } else { + aac_sample.codec_data_len = 0; + } + + buf = gst_sample_get_buffer (sample); + gst_buffer_map (buf, &map, GST_MAP_READ); + g_assert (map.size >= sizeof (aac_sample.buf_hdr)); + memcpy (aac_sample.buf_hdr, map.data, sizeof (aac_sample.buf_hdr)); + gst_buffer_unmap (buf, &map); + } + gst_sample_unref (sample); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (sink); + gst_object_unref (pipe); + + return aac_sample; +} + +typedef enum +{ + AAC_AOT_UNKNOWN = -1, + AAC_AOT_MAIN = 1, + AAC_AOT_LC = 2, + AAC_AOT_SSR = 3, + AAC_AOT_LTP = 4, + AAC_AOT_SBR = 5, + AAC_AOT_LD = 23, + AAC_AOT_PS = 29, +} AacAOT; + +static AacAOT +aac_codec_data_get_aot (const guint8 * codec_data, gsize codec_data_len) +{ + AacAOT aot = AAC_AOT_UNKNOWN; + + if (codec_data_len >= 2) { + guint8 hdr_aot = codec_data[0] >> 3; // 5 bits + switch (hdr_aot) { + case AAC_AOT_MAIN: + case AAC_AOT_LC: + case AAC_AOT_SSR: + case AAC_AOT_LTP: + case AAC_AOT_SBR: + case AAC_AOT_LD: + case AAC_AOT_PS: + aot = hdr_aot; + break; + default: + break; + } + } + + return aot; +} + +GST_START_TEST (test_fdkaacenc_adts) +{ + // LC profile + { + AacSample aac; + + aac = encode_with_caps ("audio/mpeg,profile=lc,stream-format=adts"); + fail_unless_equals_string (aac.base_profile, "lc"); + fail_unless_equals_string (aac.profile, "lc"); + fail_unless (aac.codec_data_len == 0); + + // ADTS sync + fail_unless_equals_int (GST_READ_UINT16_BE (aac.buf_hdr) & 0xfff0, 0xfff0); + + // MPEG version (0 = MPEG-4) + fail_unless_equals_int (aac.buf_hdr[1] & 0x08, 0); + + // AOT minus 1 (2=LC) + fail_unless_equals_int ((aac.buf_hdr[2] & 0xC0) >> 6, 2 - 1); + } + + // HE-AACv1 profile + { + AacSample aac; + + aac = encode_with_caps ("audio/mpeg,profile=he-aac-v1,stream-format=adts"); + fail_unless_equals_string (aac.base_profile, "lc"); + fail_unless_equals_string (aac.profile, "he-aac-v1"); + fail_unless (aac.codec_data_len == 0); + + // ADTS sync + fail_unless_equals_int (GST_READ_UINT16_BE (aac.buf_hdr) & 0xfff0, 0xfff0); + + // MPEG version (0 = MPEG-4) + fail_unless_equals_int (aac.buf_hdr[1] & 0x08, 0); + + // AOT minus 1 (2=LC) + fail_unless_equals_int ((aac.buf_hdr[2] & 0xC0) >> 6, 2 - 1); + } + + // HE-AACv2 profile + { + AacSample aac; + + aac = encode_with_caps ("audio/mpeg,profile=he-aac-v2,stream-format=adts"); + fail_unless_equals_string (aac.base_profile, "lc"); + fail_unless_equals_string (aac.profile, "he-aac-v2"); + fail_unless (aac.codec_data_len == 0); + + // ADTS sync + fail_unless_equals_int (GST_READ_UINT16_BE (aac.buf_hdr) & 0xfff0, 0xfff0); + + // MPEG version (0 = MPEG-4) + fail_unless_equals_int (aac.buf_hdr[1] & 0x08, 0); + + // AOT minus 1 (2=LC) + fail_unless_equals_int ((aac.buf_hdr[2] & 0xC0) >> 6, 2 - 1); + } +} + +GST_END_TEST; + +GST_START_TEST (test_fdkaacenc_raw) +{ + const gchar *profile; + AacAOT aot; + + // LC profile + { + AacSample aac; + + aac = encode_with_caps ("audio/mpeg,profile=lc,stream-format=raw"); + fail_unless_equals_string (aac.base_profile, "lc"); + fail_unless_equals_string (aac.profile, "lc"); + fail_unless (aac.codec_data_len == 2); + profile = + gst_codec_utils_aac_get_profile (aac.codec_data, aac.codec_data_len); + fail_unless_equals_string (profile, "lc"); + aot = aac_codec_data_get_aot (aac.codec_data, aac.codec_data_len); + fail_unless_equals_int (aot, AAC_AOT_LC); + } + + // HE-AACv1 profile + { + AacSample aac; + + aac = encode_with_caps ("audio/mpeg,profile=he-aac-v1,stream-format=raw"); + // For raw we use non-backwards compatible hierarchical signaling, so + // caps should not contain a base-profile field + fail_if (aac.base_profile != NULL); + fail_unless (aac.profile != NULL); + fail_unless (aac.codec_data_len > 2); + profile = + gst_codec_utils_aac_get_profile (aac.codec_data, aac.codec_data_len); + fail_unless_equals_string (profile, "lc"); // FIXME: is this right for non-BC hierarchical signaling? + aot = aac_codec_data_get_aot (aac.codec_data, aac.codec_data_len); + fail_unless_equals_int (aot, AAC_AOT_SBR); + } + + // HE-AACv2 profile + { + AacSample aac; + + aac = encode_with_caps ("audio/mpeg,profile=he-aac-v2,stream-format=raw"); + // For raw we use non-backwards compatible hierarchical signaling, so + // caps should not contain a base-profile field + fail_if (aac.base_profile != NULL); + fail_unless (aac.profile != NULL); + fail_unless (aac.codec_data_len > 2); + profile = + gst_codec_utils_aac_get_profile (aac.codec_data, aac.codec_data_len); + fail_unless_equals_string (profile, "lc"); // FIXME: is this right for non-BC hierarchical signaling? + aot = aac_codec_data_get_aot (aac.codec_data, aac.codec_data_len); + fail_unless_equals_int (aot, AAC_AOT_PS); + } +} + +GST_END_TEST; + +static Suite * +fdkaac_suite (void) +{ + Suite *s = suite_create ("fdk-aac"); + TCase *tc_chain_enc = tcase_create ("fdkaacenc"); + + suite_add_tcase (s, tc_chain_enc); + tcase_add_test (tc_chain_enc, test_fdkaacenc_adts); + tcase_add_test (tc_chain_enc, test_fdkaacenc_raw); + + return s; +} + +GST_CHECK_MAIN (fdkaac); diff --git a/subprojects/gst-plugins-bad/tests/check/meson.build b/subprojects/gst-plugins-bad/tests/check/meson.build index a85d70e..ac96323 100644 --- a/subprojects/gst-plugins-bad/tests/check/meson.build +++ b/subprojects/gst-plugins-bad/tests/check/meson.build @@ -35,6 +35,7 @@ base_tests = [ [['elements/cudaconvert.c'], false, [gstgl_dep, gmodule_dep]], [['elements/cudafilter.c'], false, [gstgl_dep, gmodule_dep]], [['elements/d3d11colorconvert.c'], host_machine.system() != 'windows', ], + [['elements/fdkaac.c'], not fdkaac_dep.found(), ], [['elements/gdpdepay.c'], get_option('gdp').disabled()], [['elements/gdppay.c'], get_option('gdp').disabled()], [['elements/h263parse.c'], false, [libparser_dep, gstcodecparsers_dep]],