From 67a1e19bed995d79721e4e5f0e24b6ffe304b4d5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 11 May 2023 16:25:11 +0100 Subject: [PATCH 1/1] qtdemux: add unit test for edit list regression File is the mp4 file from #2549 with the mdat atom zeroed out and compressed. We compress twice because apparently compressing 5MB of zeroes effectively in one run is too difficult for gzip. https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2549 Part-of: --- .../tests/check/elements/qtdemux.c | 142 ++++++++++++++++++++- .../tests/files/editlists.mp4.gz.gz | Bin 0 -> 3597 bytes 2 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 subprojects/gst-plugins-good/tests/files/editlists.mp4.gz.gz diff --git a/subprojects/gst-plugins-good/tests/check/elements/qtdemux.c b/subprojects/gst-plugins-good/tests/check/elements/qtdemux.c index 4a14c45..60c63aa 100644 --- a/subprojects/gst-plugins-good/tests/check/elements/qtdemux.c +++ b/subprojects/gst-plugins-good/tests/check/elements/qtdemux.c @@ -22,7 +22,25 @@ #include "qtdemux.h" #include -#include + +#include + +#include +#include + +#define TEST_FILE_PREFIX GST_TEST_FILES_PATH G_DIR_SEPARATOR_S + +static gboolean +load_file (const gchar * fn, guint8 ** p_data, guint expected_len) +{ + gsize read_len = 0; + + if (!g_file_get_contents (fn, (gchar **) p_data, &read_len, NULL)) + return FALSE; + + g_assert_cmpuint (read_len, ==, expected_len); + return TRUE; +} typedef struct { @@ -888,6 +906,127 @@ GST_START_TEST (test_qtdemux_pad_names) GST_END_TEST; +GST_START_TEST (test_qtdemux_editlist) +{ + const gsize editlist_mp4_size = 5322593; + guint8 *editlist_mp4 = NULL; + GstElement *src, *sink, *pipe; + GstSample *sample; + guint frame_count = 0; + + { + GZlibDecompressor *decompress; + GConverterResult decomp_res; + gsize bytes_read, gz_size, mp4_size; + guint8 *gz_gz = NULL; + guint8 gz[8705]; + + /* read .mp4.gz.gz */ + g_assert (load_file (TEST_FILE_PREFIX "editlists.mp4.gz.gz", &gz_gz, 3597)); + + /* mp4.gz.gz -> mp4.gz */ + decompress = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); + decomp_res = g_converter_convert (G_CONVERTER (decompress), gz_gz, 3597, + gz, 8705, G_CONVERTER_INPUT_AT_END, &bytes_read, &gz_size, NULL); + fail_unless_equals_int (decomp_res, G_CONVERTER_FINISHED); + fail_unless_equals_int (bytes_read, 3597); + fail_unless_equals_int (gz_size, 8705); + g_object_unref (decompress); + g_clear_pointer (&gz_gz, (GDestroyNotify) g_free); + + editlist_mp4 = g_malloc0 (editlist_mp4_size); + + /* mp4.gz -> mp4 */ + decompress = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); + decomp_res = g_converter_convert (G_CONVERTER (decompress), gz, 8705, + editlist_mp4, editlist_mp4_size, G_CONVERTER_INPUT_AT_END, &bytes_read, + &mp4_size, NULL); + fail_unless_equals_int (decomp_res, G_CONVERTER_FINISHED); + fail_unless_equals_int (bytes_read, 8705); + fail_unless_equals_int (mp4_size, editlist_mp4_size); + g_object_unref (decompress); + } + + fail_unless_equals_int (editlist_mp4[28 + 4], 'm'); + fail_unless_equals_int (editlist_mp4[28 + 5], 'd'); + fail_unless_equals_int (editlist_mp4[28 + 6], 'a'); + fail_unless_equals_int (editlist_mp4[28 + 7], 't'); + + pipe = gst_parse_launch ("dataurisrc name=src ! qtdemux name=d " + "d.video_0 ! appsink name=sink", NULL); + + fail_unless (pipe != NULL); + + src = gst_bin_get_by_name (GST_BIN (pipe), "src"); + fail_unless (src != NULL); + + sink = gst_bin_get_by_name (GST_BIN (pipe), "sink"); + fail_unless (sink != NULL); + + /* Convert to data: URI so we can use dataurisrc. Bit silly of course, + * should have a memsrc or somesuch, but does the job for now */ + { + gsize s_alloc_len = 32 + (editlist_mp4_size / 3 + 1) * 4 + 4; + gchar *s = g_malloc0 (s_alloc_len); + gsize s_len = 0; + gsize base64_size; + gint state = 0; + gint save = 0; + + s_len = g_strlcat (s, "data:video/quicktime;base64,", s_alloc_len); + + base64_size = + g_base64_encode_step (editlist_mp4, editlist_mp4_size, FALSE, s + s_len, + &state, &save); + s_len += base64_size; + base64_size = g_base64_encode_close (FALSE, s + s_len, &state, &save); + s_len += base64_size; + g_clear_pointer (&editlist_mp4, (GDestroyNotify) g_free); + + { + GValue v = G_VALUE_INIT; + + /* Avoids at least one of the two string copies */ + g_value_init (&v, G_TYPE_STRING); + g_value_take_string (&v, s); + g_object_set_property (G_OBJECT (src), "uri", &v); + g_value_reset (&v); + } + } + + g_object_set (sink, "sync", FALSE, NULL); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + + /* wait for preroll */ + { + GstMessage *msg; + + GST_LOG ("waiting for preroll"); + msg = + gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, + GST_MESSAGE_ASYNC_DONE); + + gst_message_unref (msg); + } + + /* pull video frames out of qtdemux */ + while ((sample = gst_app_sink_pull_sample (GST_APP_SINK (sink)))) { + ++frame_count; + gst_sample_unref (sample); + } + + fail_unless_equals_int (frame_count, 361); + + gst_element_set_state (pipe, GST_STATE_NULL); + + gst_clear_object (&src); + gst_clear_object (&sink); + gst_clear_object (&pipe); +} + +GST_END_TEST; + static Suite * qtdemux_suite (void) { @@ -901,6 +1040,7 @@ qtdemux_suite (void) tcase_add_test (tc_chain, test_qtdemux_duplicated_moov); tcase_add_test (tc_chain, test_qtdemux_stream_change); tcase_add_test (tc_chain, test_qtdemux_pad_names); + tcase_add_test (tc_chain, test_qtdemux_editlist); return s; } diff --git a/subprojects/gst-plugins-good/tests/files/editlists.mp4.gz.gz b/subprojects/gst-plugins-good/tests/files/editlists.mp4.gz.gz new file mode 100644 index 0000000000000000000000000000000000000000..93cafdca132a0ac95fc1b65a9217a6649c201c8a GIT binary patch literal 3597 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 T18YAAT;KNpkx%nK0U`hZ&I%5H literal 0 HcmV?d00001 -- 2.7.4