/* GStreamer * * unit tests for audio support library * * Copyright (C) 2006 Tim-Philipp Müller * Copyright (C) 2011 Sebastian Dröge * * 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 static GstBuffer * make_buffer (guint8 ** _data) { GstBuffer *buf = gst_buffer_new (); guint8 *data = (guint8 *) g_malloc (1000); gst_buffer_append_memory (buf, gst_memory_new_wrapped (0, data, 1000, 0, 1000, data, g_free)); if (_data) *_data = data; return buf; } static void setup_segment (GstSegment * s, GstFormat fmt, guint64 start, guint64 stop, guint64 stream_time) { gst_segment_init (s, fmt); s->start = start; s->stop = stop; s->time = stream_time; } GST_START_TEST (test_buffer_clip_unsupported_format) { GstSegment s; GstBuffer *buf; guint8 *data; /* If the format is not TIME or DEFAULT it should assert() * FIXME: check if return value is the same as the input buffer. * probably can't be done because the assert() does a SIGABRT. */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_PERCENT, 0, 10, 0); GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND; GST_BUFFER_DURATION (buf) = 0; GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ASSERT_CRITICAL (gst_audio_buffer_clip (buf, &s, 100, 1)); gst_buffer_unref (buf); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_start_and_stop) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip start and end */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_TIME, 4 * GST_SECOND, 8 * GST_SECOND, 4 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 800); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data + 200); fail_unless (map.size == 400); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_start_and_stop_planar) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstAudioInfo info; GstAudioBuffer abuf; guint8 *data; /* Clip start and end */ buf = make_buffer (&data); gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S8, 44100, 1, NULL); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; gst_buffer_add_audio_meta (buf, &info, 1000, NULL); setup_segment (&s, GST_FORMAT_TIME, 4 * GST_SECOND, 8 * GST_SECOND, 4 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 800); gst_audio_buffer_map (&abuf, &info, ret, GST_MAP_READ); fail_unless_equals_int (abuf.n_planes, 1); fail_unless_equals_int (GST_AUDIO_BUFFER_PLANE_SIZE (&abuf), 400); fail_unless_equals_pointer (abuf.planes[0], data + 200); gst_audio_buffer_unmap (&abuf); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_start) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip only start */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_TIME, 4 * GST_SECOND, 12 * GST_SECOND, 4 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 8 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 1200); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data + 200); fail_unless (map.size == 800); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_start_planar) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstAudioInfo info; GstAudioMeta *meta; GstAudioBuffer abuf; guint8 *data; /* Clip only start */ buf = make_buffer (&data); gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S8, 44100, 2, NULL); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; gst_buffer_add_audio_meta (buf, &info, 500, NULL); setup_segment (&s, GST_FORMAT_TIME, 4 * GST_SECOND, 12 * GST_SECOND, 4 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 5 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 700; ret = gst_audio_buffer_clip (buf, &s, 100, 2); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 3 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 700); meta = gst_buffer_get_audio_meta (ret); fail_unless (meta); fail_unless_equals_int (meta->info.channels, 2); fail_unless_equals_int (meta->samples, 300); gst_audio_buffer_map (&abuf, &info, ret, GST_MAP_READ); fail_unless_equals_int (abuf.n_planes, 2); fail_unless_equals_int (GST_AUDIO_BUFFER_PLANE_SIZE (&abuf), 300); fail_unless_equals_pointer (abuf.planes[0], data + 200); fail_unless_equals_pointer (abuf.planes[1], data + 700); gst_audio_buffer_unmap (&abuf); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_stop) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip only stop */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_TIME, 2 * GST_SECOND, 10 * GST_SECOND, 2 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 2 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 8 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 200); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 1000); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data); fail_unless (map.size == 800); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_stop_planar) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstAudioInfo info; GstAudioMeta *meta; GstAudioBuffer abuf; guint8 *data; /* Clip only stop */ buf = make_buffer (&data); gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S8, 44100, 2, NULL); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; gst_buffer_add_audio_meta (buf, &info, 500, NULL); setup_segment (&s, GST_FORMAT_TIME, 2 * GST_SECOND, 6 * GST_SECOND, 2 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 5 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 700; ret = gst_audio_buffer_clip (buf, &s, 100, 2); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 2 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 200); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 600); meta = gst_buffer_get_audio_meta (ret); fail_unless (meta); fail_unless_equals_int (meta->info.channels, 2); fail_unless_equals_int (meta->samples, 400); gst_audio_buffer_map (&abuf, &info, ret, GST_MAP_READ); fail_unless_equals_int (abuf.n_planes, 2); fail_unless_equals_int (GST_AUDIO_BUFFER_PLANE_SIZE (&abuf), 400); fail_unless_equals_pointer (abuf.planes[0], data); fail_unless_equals_pointer (abuf.planes[1], data + 500); gst_audio_buffer_unmap (&abuf); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_outside) { GstSegment s; GstBuffer *buf; GstBuffer *ret; /* Buffer outside segment */ buf = make_buffer (NULL); setup_segment (&s, GST_FORMAT_TIME, 12 * GST_SECOND, 20 * GST_SECOND, 12 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret == NULL); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_start_and_stop_no_meta) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip start and end but don't touch duration, offset and offset_end */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_TIME, 4 * GST_SECOND, 8 * GST_SECOND, 4 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), GST_CLOCK_TIME_NONE); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), GST_BUFFER_OFFSET_NONE); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), GST_BUFFER_OFFSET_NONE); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data + 200); fail_unless (map.size == 400); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_no_timestamp) { GstSegment s; GstBuffer *buf; GstBuffer *ret; /* If the buffer has no timestamp it should assert() * FIXME: check if return value is the same as the input buffer. * probably can't be done because the assert() does a SIGABRT. */ buf = make_buffer (NULL); setup_segment (&s, GST_FORMAT_TIME, 0 * GST_SECOND, 10 * GST_SECOND, 0 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret == buf); gst_buffer_unref (buf); } GST_END_TEST; GST_START_TEST (test_buffer_clip_time_handles_rounding) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; GstClockTime time_per_sample = GST_SECOND / 100; /* Clip only stop */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_TIME, 2 * GST_SECOND, 10 * GST_SECOND, 2 * GST_SECOND); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; /* the max duration that still converts back to the same size of samples */ GST_BUFFER_DURATION (buf) = 10 * GST_SECOND + (time_per_sample - 1); GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 2 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 8 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 200); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 1000); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data); fail_unless (map.size == 800); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_start_and_stop) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip start and end */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_DEFAULT, 400, 800, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 800); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data + 200); fail_unless (map.size == 400); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_start_and_stop_planar) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstAudioInfo info; GstAudioMeta *meta; GstAudioBuffer abuf; guint8 *data; /* Clip start and end */ buf = make_buffer (&data); gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S8, 44100, 2, NULL); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; gst_buffer_add_audio_meta (buf, &info, 500, NULL); setup_segment (&s, GST_FORMAT_DEFAULT, 400, 600, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 5 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 700; ret = gst_audio_buffer_clip (buf, &s, 100, 2); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 2 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 600); meta = gst_buffer_get_audio_meta (ret); fail_unless (meta); fail_unless_equals_int (meta->info.channels, 2); fail_unless_equals_int (meta->samples, 200); gst_audio_buffer_map (&abuf, &info, ret, GST_MAP_READ); fail_unless_equals_int (abuf.n_planes, 2); fail_unless_equals_int (GST_AUDIO_BUFFER_PLANE_SIZE (&abuf), 200); fail_unless_equals_pointer (abuf.planes[0], data + 200); fail_unless_equals_pointer (abuf.planes[1], data + 700); gst_audio_buffer_unmap (&abuf); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_start) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip only start */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_DEFAULT, 400, 1200, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 8 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 1200); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data + 200); fail_unless (map.size == 800); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_stop) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip only stop */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_DEFAULT, 200, 1000, 200); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 2 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), 8 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 200); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 1000); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data); fail_unless (map.size == 800); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_outside) { GstSegment s; GstBuffer *buf; GstBuffer *ret; /* Buffer outside segment */ buf = make_buffer (NULL); setup_segment (&s, GST_FORMAT_DEFAULT, 1200, 2000, 1200); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret == NULL); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_start_and_stop_no_meta) { GstSegment s; GstBuffer *buf; GstBuffer *ret; GstMapInfo map; guint8 *data; /* Clip start and end but don't touch duration and offset_end */ buf = make_buffer (&data); setup_segment (&s, GST_FORMAT_DEFAULT, 400, 800, 400); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ret = gst_audio_buffer_clip (buf, &s, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), 4 * GST_SECOND); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), GST_CLOCK_TIME_NONE); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 400); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 800); gst_buffer_map (ret, &map, GST_MAP_READ); fail_unless (map.data == data + 200); fail_unless (map.size == 400); gst_buffer_unmap (ret, &map); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_clip_samples_no_timestamp) { GstSegment s; GstBuffer *buf; /* If the buffer has no offset it should assert() in DEFAULT format * FIXME: check if return value is the same as the input buffer. * probably can't be done because the assert() does a SIGABRT. */ buf = make_buffer (NULL); setup_segment (&s, GST_FORMAT_DEFAULT, 0, 10, 0); GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ASSERT_CRITICAL (gst_audio_buffer_clip (buf, &s, 100, 1)); gst_buffer_unref (buf); } GST_END_TEST; GST_START_TEST (test_buffer_truncate_samples_offset_end) { GstBuffer *buf; GstBuffer *ret; guint8 *data; buf = make_buffer (&data); GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; GST_BUFFER_OFFSET (buf) = 200; GST_BUFFER_OFFSET_END (buf) = 1200; ret = gst_audio_buffer_truncate (buf, 4, 100, 100); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), GST_CLOCK_TIME_NONE); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), GST_CLOCK_TIME_NONE); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), 300); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), 400); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_buffer_truncate_samples_no_timestamp) { GstBuffer *buf; GstBuffer *ret; guint8 *data; buf = make_buffer (&data); GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; ret = gst_audio_buffer_truncate (buf, 4, 100, 1); fail_unless (ret != NULL); fail_unless_equals_int64 (GST_BUFFER_TIMESTAMP (ret), GST_CLOCK_TIME_NONE); fail_unless_equals_int64 (GST_BUFFER_DURATION (ret), GST_CLOCK_TIME_NONE); fail_unless_equals_int64 (GST_BUFFER_OFFSET (ret), GST_BUFFER_OFFSET_NONE); fail_unless_equals_int64 (GST_BUFFER_OFFSET_END (ret), GST_BUFFER_OFFSET_NONE); gst_buffer_unref (ret); } GST_END_TEST; GST_START_TEST (test_multichannel_checks) { GstAudioChannelPosition pos_2_mixed[2] = { GST_AUDIO_CHANNEL_POSITION_MONO, GST_AUDIO_CHANNEL_POSITION_NONE }; GstAudioChannelPosition pos_2_none[2] = { GST_AUDIO_CHANNEL_POSITION_NONE, GST_AUDIO_CHANNEL_POSITION_NONE }; GstAudioChannelPosition pos_2_flr[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; GstAudioChannelPosition pos_2_frl[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT }; GstAudioChannelPosition pos_2_frr[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; GstAudioChannelPosition pos_3_flrc[3] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER }; GstAudioChannelPosition pos_3_frcl[3] = { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT }; GstAudioInfo info, info2; GstCaps *caps; gst_audio_info_init (&info); gst_audio_info_init (&info2); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 2, NULL); fail_unless (memcmp (&info.position, pos_2_flr, sizeof (pos_2_flr)) == 0); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 2, pos_2_flr); fail_unless (memcmp (&info.position, pos_2_flr, sizeof (pos_2_flr)) == 0); caps = gst_audio_info_to_caps (&info); fail_unless (gst_audio_info_from_caps (&info2, caps)); fail_unless (memcmp (&info, &info2, sizeof (info)) == 0); gst_caps_unref (caps); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 2, pos_2_none); fail_unless (memcmp (&info.position, pos_2_none, sizeof (pos_2_none)) == 0); caps = gst_audio_info_to_caps (&info); fail_unless (gst_audio_info_from_caps (&info2, caps)); fail_unless (memcmp (&info, &info2, sizeof (info)) == 0); gst_caps_unref (caps); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 3, pos_3_flrc); fail_unless (memcmp (&info.position, pos_3_flrc, sizeof (pos_3_flrc)) == 0); caps = gst_audio_info_to_caps (&info); fail_unless (gst_audio_info_from_caps (&info2, caps)); fail_unless (memcmp (&info, &info2, sizeof (info)) == 0); gst_caps_unref (caps); ASSERT_WARNING (gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 2, pos_2_frl)); ASSERT_WARNING (gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 2, pos_2_mixed)); ASSERT_WARNING (gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 2, pos_2_frr)); ASSERT_WARNING (gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_F32, 48000, 3, pos_3_frcl)); } GST_END_TEST; typedef struct { gint channels; GstAudioChannelPosition from[32], to[32]; gint32 in[32], out[32]; gint32 plane_offsets[32]; gboolean fail; } MultichannelReorderData; GST_START_TEST (test_multichannel_reorder) { MultichannelReorderData tests[] = { {1, {GST_AUDIO_CHANNEL_POSITION_MONO}, {GST_AUDIO_CHANNEL_POSITION_MONO}, {0, 1, 2, 3}, {0, 1, 2, 3}, {0}, FALSE}, {1, {GST_AUDIO_CHANNEL_POSITION_MONO}, {GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {0, 1, 2, 3}, {0, 1, 2, 3}, {0}, TRUE}, {2, {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {0, 1, 2, 3}, {0, 1, 2, 3}, {0, 1}, FALSE}, {2, {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {0, 1, 2, 3}, {1, 0, 3, 2}, {1, 0}, FALSE}, {4, {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {0, 1, 2, 3}, {1, 2, 0, 3}, {1, 2, 0, 3}, FALSE}, {4, {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {0, 1, 2, 3}, {3, 0, 1, 2}, {3, 0, 1, 2}, FALSE}, {4, {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {0, 1, 2, 3}, {3, 2, 1, 0}, {3, 2, 1, 0}, FALSE}, }; gint i, j; GstBuffer *buf; GstMapInfo map; GstAudioInfo info; GstAudioBuffer abuf; for (i = 0; i < G_N_ELEMENTS (tests); i++) { buf = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY, tests[i].in, sizeof (tests[i].in), 0, sizeof (tests[i].in), NULL, NULL); if (tests[i].fail) { fail_if (gst_audio_buffer_reorder_channels (buf, GST_AUDIO_FORMAT_S32, tests[i].channels, tests[i].from, tests[i].to)); } else { /* first interpret as interleaved */ fail_unless (gst_audio_buffer_reorder_channels (buf, GST_AUDIO_FORMAT_S32, tests[i].channels, tests[i].from, tests[i].to)); gst_buffer_map (buf, &map, GST_MAP_READ); fail_unless_equals_int (map.size, sizeof (tests[i].in)); fail_unless (memcmp (tests[i].out, map.data, map.size) == 0); gst_buffer_unmap (buf, &map); /* now interpret as planar */ gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S32, 44100, tests[i].channels, NULL); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; gst_buffer_add_audio_meta (buf, &info, sizeof (tests[i].in) / (tests[i].channels * sizeof (gint32)), NULL); fail_unless (gst_audio_buffer_reorder_channels (buf, GST_AUDIO_FORMAT_S32, tests[i].channels, tests[i].from, tests[i].to)); fail_unless (gst_audio_buffer_map (&abuf, &info, buf, GST_MAP_READ)); fail_unless_equals_int (abuf.n_planes, tests[i].channels); fail_unless_equals_int (GST_AUDIO_BUFFER_PLANE_SIZE (&abuf), sizeof (tests[i].in) / tests[i].channels); for (j = 0; j < abuf.n_planes; j++) { fail_unless_equals_pointer (abuf.planes[j], abuf.map_infos[0].data + tests[i].plane_offsets[j] * GST_AUDIO_BUFFER_PLANE_SIZE (&abuf)); } gst_audio_buffer_unmap (&abuf); } gst_buffer_unref (buf); } } GST_END_TEST; GST_START_TEST (test_audio_format_s8) { GstAudioFormat fmt; fmt = gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, 8, 8); fail_unless (fmt == GST_AUDIO_FORMAT_S8); } GST_END_TEST; GST_START_TEST (test_audio_format_u8) { GstAudioFormat fmt; fmt = gst_audio_format_build_integer (FALSE, G_BYTE_ORDER, 8, 8); fail_unless (fmt == GST_AUDIO_FORMAT_U8); } GST_END_TEST; GST_START_TEST (test_fill_silence) { GstAudioInfo info; GstAudioFormat f; gint i; guint8 test_silence[32]; for (f = GST_AUDIO_FORMAT_S8; f < GST_AUDIO_FORMAT_F64; f++) { gst_audio_info_set_format (&info, f, 48000, 1, NULL); gst_audio_format_info_fill_silence (info.finfo, test_silence, GST_AUDIO_INFO_BPF (&info) * 4); for (i = 0; i < 4; i++) fail_unless (memcmp (test_silence + i * GST_AUDIO_INFO_BPF (&info), info.finfo->silence, GST_AUDIO_INFO_BPF (&info)) == 0); } } GST_END_TEST; GST_START_TEST (test_stream_align) { GstAudioStreamAlign *align; guint i; GstClockTime timestamp; GstClockTime out_timestamp, out_duration; gboolean discont; align = gst_audio_stream_align_new (1000, 40 * GST_MSECOND, 1 * GST_SECOND); for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; discont = i == 0; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i == 0) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } /* Drift forwards by 1ms per 10ms buffer for the first 40 buffers. * - after 40 buffers we're above alignment threshold * - after 40 + 96 buffers we're at discont wait */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; discont = i == 0; if (i > 0) timestamp += 1 * GST_MSECOND * MIN (i, 40); discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i < 136) { if (i == 0) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 136) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i + 40 * GST_MSECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } /* Drift backwards by 1ms per 10ms buffer for the first 40 buffers. * - after 40 buffers we're above alignment threshold * - after 40 + 104 buffers we're at discont wait */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; discont = i == 0; if (i > 0) timestamp -= 1 * GST_MSECOND * MIN (i, 40); discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i < 144) { if (i == 0) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 144) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i - 40 * GST_MSECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } /* Shift all buffers but the first by 40ms * - after 1 buffers we're above alignment threshold * - after 97 buffers we're at discont wait */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; discont = i == 0; if (i > 0) timestamp += 40 * GST_MSECOND; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i < 97) { if (i == 0) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 97) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i + 40 * GST_MSECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } /* Shift every second buffer by 40ms: * - never discont! */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; discont = i == 0; if (i % 2 == 0 && i > 0) timestamp += 40 * GST_MSECOND; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i == 0) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } /* Shift every buffer after 100 by 2s: discont at buffer 100 */ for (i = 0; i < 500; i++) { timestamp = 10 * GST_MSECOND * i; discont = i == 0; if (i >= 100) timestamp += 2 * GST_SECOND; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i < 100) { if (i == 0) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 100) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i + 2 * GST_SECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } gst_audio_stream_align_free (align); } GST_END_TEST; GST_START_TEST (test_stream_align_reverse) { GstAudioStreamAlign *align; gint i; GstClockTime timestamp; GstClockTime out_timestamp, out_duration; gboolean discont; align = gst_audio_stream_align_new (-1000, 40 * GST_MSECOND, 1 * GST_SECOND); for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; discont = i == 499; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i == 499) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } /* Drift forwards by 1ms per 10ms buffer for the first 40 buffers. * - after 40 buffers we're above alignment threshold * - after 40 + 100 buffers we're at discont wait */ for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; discont = i == 499; if (i < 499) timestamp += 1 * GST_MSECOND * MIN (499 - i, 40); discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i >= 500 - 144) { if (i == 499) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 499 - 144) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i + 40 * GST_MSECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } /* Drift backwards by 1ms per 10ms buffer for the first 40 buffers. * - after 40 buffers we're above alignment threshold * - after 40 + 100 buffers we're at discont wait */ for (i = 499; i >= 4; i--) { timestamp = 10 * GST_MSECOND * i; discont = i == 499; if (i < 499) timestamp -= 1 * GST_MSECOND * MIN (499 - i, 40); discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i >= 500 - 136) { if (i == 499) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 499 - 136) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i - 40 * GST_MSECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } /* Shift all buffers but the first by 40ms * - after 1 buffers we're above alignment threshold * - after 106 buffers we're at discont wait */ for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; discont = i == 499; if (i < 499) timestamp += 40 * GST_MSECOND; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i >= 500 - 105) { if (i == 499) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 499 - 105) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i + 40 * GST_MSECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } /* Shift every second buffer by 40ms: * - never discont! */ for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; discont = i == 499; if (i % 2 == 0 && i < 499) timestamp += 40 * GST_MSECOND; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i == 499) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } /* Shift every buffer after 100 by 2s: discont at buffer 100 */ for (i = 499; i >= 0; i--) { timestamp = 10 * GST_MSECOND * i; discont = i == 499; if (i < 500 - 100) timestamp += 2 * GST_SECOND; discont = gst_audio_stream_align_process (align, discont, timestamp, 10, &out_timestamp, &out_duration, NULL); if (i >= 500 - 100) { if (i == 499) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } else { if (i == 499 - 100) fail_unless (discont); else fail_unless (!discont); fail_unless_equals_uint64 (out_timestamp, 10 * GST_MSECOND * i + 2 * GST_SECOND); fail_unless_equals_uint64 (out_duration, 10 * GST_MSECOND); } } gst_audio_stream_align_free (align); } GST_END_TEST; typedef struct { GstAudioFormat format; GstAudioLayout layout; gint channels; gsize samples; gsize plane_size; gsize offsets[10]; gboolean add_meta; gboolean use_offsets; } AudioBufferTestData; GST_START_TEST (test_audio_buffer_and_audio_meta) { AudioBufferTestData td[] = { {GST_AUDIO_FORMAT_S24_32, GST_AUDIO_LAYOUT_NON_INTERLEAVED, 4, 60, 240, {10, 760, 510, 260}, TRUE, TRUE}, {GST_AUDIO_FORMAT_F32, GST_AUDIO_LAYOUT_NON_INTERLEAVED, 4, 60, 240, {0, 240, 480, 720}, TRUE, FALSE}, {GST_AUDIO_FORMAT_S16, GST_AUDIO_LAYOUT_INTERLEAVED, 4, 125, 1000, {0}, TRUE, FALSE}, {GST_AUDIO_FORMAT_S16, GST_AUDIO_LAYOUT_INTERLEAVED, 4, 125, 1000, {0}, FALSE, FALSE}, {GST_AUDIO_FORMAT_S8, GST_AUDIO_LAYOUT_INTERLEAVED, 8, 125, 1000, {0}, FALSE, FALSE}, {GST_AUDIO_FORMAT_U8, GST_AUDIO_LAYOUT_NON_INTERLEAVED, 8, 125, 125, {0, 125, 250, 375, 500, 625, 750, 875}, TRUE, FALSE}, {GST_AUDIO_FORMAT_U32, GST_AUDIO_LAYOUT_NON_INTERLEAVED, 10, 25, 100, {0, 100, 200, 300, 400, 500, 600, 700, 800, 900}, TRUE, FALSE}, {GST_AUDIO_FORMAT_U32, GST_AUDIO_LAYOUT_INTERLEAVED, 10, 25, 1000, {0}, FALSE, FALSE}, }; gint i; for (i = 0; i < G_N_ELEMENTS (td); i++) { GstBuffer *buf; guint8 *data; GstAudioInfo info; GstAudioMeta *meta; GstAudioBuffer buffer; gint j; gst_audio_info_init (&info); gst_audio_info_set_format (&info, td[i].format, 44100, td[i].channels, NULL); info.layout = td[i].layout; buf = make_buffer (&data); if (td[i].add_meta) { meta = gst_buffer_add_audio_meta (buf, &info, td[i].samples, td[i].use_offsets ? td[i].offsets : NULL); fail_unless (meta); fail_unless (GST_AUDIO_INFO_IS_VALID (&meta->info)); fail_unless (gst_audio_info_is_equal (&meta->info, &info)); fail_unless_equals_int (meta->info.finfo->format, td[i].format); fail_unless_equals_int (meta->info.layout, td[i].layout); fail_unless_equals_int (meta->info.channels, td[i].channels); fail_unless_equals_int (meta->samples, td[i].samples); if (td[i].layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) { fail_unless (meta->offsets); for (j = 0; j < td[i].channels; j++) { fail_unless_equals_int (meta->offsets[j], td[i].offsets[j]); } } else { fail_if (meta->offsets); } } fail_unless (gst_audio_buffer_map (&buffer, &info, buf, GST_MAP_READ)); fail_unless_equals_pointer (buffer.buffer, buf); fail_unless (GST_AUDIO_INFO_IS_VALID (&buffer.info)); fail_unless (gst_audio_info_is_equal (&buffer.info, &info)); fail_unless_equals_int (buffer.n_samples, td[i].samples); if (td[i].layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) { fail_unless_equals_int (buffer.n_planes, td[i].channels); for (j = 0; j < td[i].channels; j++) { fail_unless_equals_pointer (buffer.planes[j], data + td[i].offsets[j]); } } else { fail_unless_equals_int (buffer.n_planes, 1); fail_unless_equals_pointer (buffer.planes[0], data); } fail_unless_equals_int (GST_AUDIO_BUFFER_PLANE_SIZE (&buffer), td[i].plane_size); if (buffer.n_planes <= 8) { fail_unless_equals_pointer (buffer.map_infos, buffer.priv_map_infos_arr); fail_unless_equals_pointer (buffer.planes, buffer.priv_planes_arr); } else { fail_if (buffer.map_infos == buffer.priv_map_infos_arr); fail_if (buffer.planes == buffer.priv_planes_arr); } gst_audio_buffer_unmap (&buffer); gst_buffer_unref (buf); } } GST_END_TEST; typedef struct { const gchar *str; GstAudioFormat format; GstAudioLayout layout; gint rate; gint channels; gboolean ret; } AudioInfoFromCapsData; GST_START_TEST (test_audio_info_from_caps) { static const AudioInfoFromCapsData format_list[] = { /* raw format, positive */ {"audio/x-raw, format = (string) S8, layout = (string) non-interleaved, " "rate = (int) 44100, channels = (int) 2", GST_AUDIO_FORMAT_S8, GST_AUDIO_LAYOUT_NON_INTERLEAVED, 44100, 2, TRUE}, {"audio/x-raw, format = (string) U8, layout = (string) interleaved, " "rate = (int) 44100, channels = (int) 1", GST_AUDIO_FORMAT_U8, GST_AUDIO_LAYOUT_INTERLEAVED, 44100, 1, TRUE}, /* raw format, negative */ /* unknown format */ {"audio/x-raw, format = (string) foo, layout = (string) interleaved, " "rate = (int) 44100, channels = (int) 2", GST_AUDIO_FORMAT_UNKNOWN, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, FALSE}, {"audio/x-raw, layout = (string) non-interleaved, " "rate = (int) 44100, channels = (int) 2", GST_AUDIO_FORMAT_UNKNOWN, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, FALSE}, /* unknown layout */ {"audio/x-raw, format = (string) U8, " "rate = (int) 44100, channels = (int) 2", GST_AUDIO_FORMAT_UNKNOWN, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, FALSE}, /* unknown rate */ {"audio/x-raw, format = (string) U8, layout = (string) interleaved, " "channels = (int) 2", GST_AUDIO_FORMAT_UNKNOWN, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, FALSE}, /* unknown channels */ {"audio/x-raw, format = (string) U8, layout = (string) interleaved, " "rate = (int) 44100", GST_AUDIO_FORMAT_UNKNOWN, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, FALSE}, /* video caps */ {"video/x-raw, format = (string) NV12", GST_AUDIO_FORMAT_UNKNOWN, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, FALSE}, /* encoded format, it allow empty fields */ {"audio/x-opus", GST_AUDIO_FORMAT_ENCODED, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 0, TRUE}, /* rate only */ {"audio/x-opus, rate = (int) 44100", GST_AUDIO_FORMAT_ENCODED, GST_AUDIO_LAYOUT_INTERLEAVED, 44100, 0, TRUE}, /* channels only */ {"audio/x-opus, channels = (int) 2", GST_AUDIO_FORMAT_ENCODED, GST_AUDIO_LAYOUT_INTERLEAVED, 0, 2, TRUE}, /* rate and channels */ {"audio/x-opus, rate = (int) 44100, channels = (int) 2", GST_AUDIO_FORMAT_ENCODED, GST_AUDIO_LAYOUT_INTERLEAVED, 44100, 2, TRUE}, }; gint i; for (i = 0; i < G_N_ELEMENTS (format_list); i++) { GstAudioInfo info; GstCaps *caps; GST_LOG ("checking %dth format", i); caps = gst_caps_from_string (format_list[i].str); fail_unless (caps != NULL); gst_audio_info_init (&info); fail_unless_equals_int (gst_audio_info_from_caps (&info, caps), format_list[i].ret); if (format_list[i].ret) { fail_unless_equals_int (GST_AUDIO_INFO_FORMAT (&info), format_list[i].format); fail_unless_equals_int (GST_AUDIO_INFO_LAYOUT (&info), format_list[i].layout); fail_unless_equals_int (GST_AUDIO_INFO_RATE (&info), format_list[i].rate); fail_unless_equals_int (GST_AUDIO_INFO_CHANNELS (&info), format_list[i].channels); } gst_caps_unref (caps); } } GST_END_TEST; GST_START_TEST (test_audio_make_raw_caps) { GstCaps *caps, *expected; GstAudioFormat f1[] = { GST_AUDIO_FORMAT_U8 }; GstAudioFormat f2[] = { GST_AUDIO_FORMAT_U8, GST_AUDIO_FORMAT_S8 }; caps = gst_audio_make_raw_caps (f1, G_N_ELEMENTS (f1), GST_AUDIO_LAYOUT_INTERLEAVED); expected = gst_caps_from_string ("audio/x-raw, format = (string) U8, rate = (int) [ 1, max ], channels = (int) [ 1, max ], layout = (string) interleaved"); fail_unless (gst_caps_is_equal (caps, expected)); gst_caps_unref (caps); gst_caps_unref (expected); caps = gst_audio_make_raw_caps (f2, G_N_ELEMENTS (f2), GST_AUDIO_LAYOUT_NON_INTERLEAVED); expected = gst_caps_from_string ("audio/x-raw, format = (string) { U8, S8 }, rate = (int) [ 1, max ], channels = (int) [ 1, max ], layout = (string) non-interleaved"); fail_unless (gst_caps_is_equal (caps, expected)); gst_caps_unref (caps); gst_caps_unref (expected); caps = gst_audio_make_raw_caps (NULL, 0, GST_AUDIO_LAYOUT_INTERLEAVED); expected = gst_caps_from_string ("audio/x-raw, format = (string) { S8, U8, S16LE, S16BE, U16LE, U16BE, S24_32LE, S24_32BE, U24_32LE, U24_32BE, S32LE, S32BE, U32LE, U32BE, S24LE, S24BE, U24LE, U24BE, S20LE, S20BE, U20LE, U20BE, S18LE, S18BE, U18LE, U18BE, F32LE, F32BE, F64LE, F64BE }, rate = (int) [ 1, max ], channels = (int) [ 1, max ], layout = (string) interleaved"); fail_unless (gst_caps_is_equal (caps, expected)); gst_caps_unref (caps); gst_caps_unref (expected); } GST_END_TEST; GST_START_TEST (test_audio_meta_serialize) { GstBuffer *buf; GstAudioInfo info; GstAudioMeta *meta; GstAudioChannelPosition position[] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S32, 44100, 2, position); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; /* Add audio meta */ gsize samples = 1; gsize buf_size = 4 * 2 * samples; buf = gst_buffer_new_and_alloc (buf_size); gsize offsets[] = { 0, buf_size / 2 }; meta = gst_buffer_add_audio_meta (buf, &info, samples, offsets); /* Serialize */ GByteArray *data = g_byte_array_new (); fail_unless (gst_meta_serialize_simple ((GstMeta *) meta, data)); gst_buffer_unref (buf); /* Create a new buffer */ buf = gst_buffer_new_and_alloc (buf_size); guint32 consumed; meta = (GstAudioMeta *) gst_meta_deserialize (buf, data->data, data->len, &consumed); fail_unless (meta); fail_unless (consumed == data->len); g_byte_array_unref (data); /* Check meta's content */ g_assert_cmpint (meta->info.finfo->format, ==, GST_AUDIO_FORMAT_S32); g_assert_cmpint (meta->info.layout, ==, GST_AUDIO_LAYOUT_NON_INTERLEAVED); g_assert_cmpint (meta->info.rate, ==, 44100); g_assert_cmpint (meta->info.channels, ==, 2); g_assert_cmpint (meta->info.position[0], ==, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT); g_assert_cmpint (meta->info.position[1], ==, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT); g_assert_cmpuint (meta->samples, ==, samples); g_assert_cmpuint (meta->offsets[0], ==, 0); g_assert_cmpuint (meta->offsets[1], ==, buf_size / 2); gst_buffer_unref (buf); } GST_END_TEST; GST_START_TEST (test_audio_meta_serialize_65_chans) { GstBuffer *buf; GstAudioInfo info; GstAudioMeta *meta; /* With more than 64 channels we cannot have positions */ gst_audio_info_init (&info); gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S32, 44100, 65, NULL); info.layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; /* Add audio meta */ gsize samples = 1; gsize buf_size = 4 * 65 * samples; buf = gst_buffer_new_and_alloc (buf_size); gsize offsets[65]; for (int i = 0; i < 65; i++) offsets[i] = i * samples * 4; meta = gst_buffer_add_audio_meta (buf, &info, samples, offsets); /* Serialize */ GByteArray *data = g_byte_array_new (); fail_unless (gst_meta_serialize_simple ((GstMeta *) meta, data)); gst_buffer_unref (buf); /* Create a new buffer */ buf = gst_buffer_new_and_alloc (buf_size); guint32 consumed; meta = (GstAudioMeta *) gst_meta_deserialize (buf, data->data, data->len, &consumed); fail_unless (meta); fail_unless (consumed == data->len); g_byte_array_unref (data); /* Check meta's content */ g_assert_cmpint (meta->info.finfo->format, ==, GST_AUDIO_FORMAT_S32); g_assert_cmpint (meta->info.layout, ==, GST_AUDIO_LAYOUT_NON_INTERLEAVED); g_assert_cmpint (meta->info.rate, ==, 44100); g_assert_cmpint (meta->info.channels, ==, 65); g_assert_cmpuint (meta->samples, ==, samples); for (int i = 0; i < 65; i++) g_assert_cmpuint (meta->offsets[i], ==, i * samples * 4); gst_buffer_unref (buf); } GST_END_TEST; static Suite * audio_suite (void) { Suite *s = suite_create ("audio support library"); TCase *tc_chain = tcase_create ("general"); suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_buffer_clip_unsupported_format); tcase_add_test (tc_chain, test_buffer_clip_time_start_and_stop); tcase_add_test (tc_chain, test_buffer_clip_time_start_and_stop_planar); tcase_add_test (tc_chain, test_buffer_clip_time_start); tcase_add_test (tc_chain, test_buffer_clip_time_start_planar); tcase_add_test (tc_chain, test_buffer_clip_time_stop); tcase_add_test (tc_chain, test_buffer_clip_time_stop_planar); tcase_add_test (tc_chain, test_buffer_clip_time_outside); tcase_add_test (tc_chain, test_buffer_clip_time_start_and_stop_no_meta); tcase_add_test (tc_chain, test_buffer_clip_time_no_timestamp); tcase_add_test (tc_chain, test_buffer_clip_time_handles_rounding); tcase_add_test (tc_chain, test_buffer_clip_samples_start_and_stop); tcase_add_test (tc_chain, test_buffer_clip_samples_start_and_stop_planar); tcase_add_test (tc_chain, test_buffer_clip_samples_start); tcase_add_test (tc_chain, test_buffer_clip_samples_stop); tcase_add_test (tc_chain, test_buffer_clip_samples_outside); tcase_add_test (tc_chain, test_buffer_clip_samples_start_and_stop_no_meta); tcase_add_test (tc_chain, test_buffer_clip_samples_no_timestamp); tcase_add_test (tc_chain, test_buffer_truncate_samples_offset_end); tcase_add_test (tc_chain, test_buffer_truncate_samples_no_timestamp); tcase_add_test (tc_chain, test_multichannel_checks); tcase_add_test (tc_chain, test_multichannel_reorder); tcase_add_test (tc_chain, test_audio_format_s8); tcase_add_test (tc_chain, test_audio_format_u8); tcase_add_test (tc_chain, test_fill_silence); tcase_add_test (tc_chain, test_stream_align); tcase_add_test (tc_chain, test_stream_align_reverse); tcase_add_test (tc_chain, test_audio_buffer_and_audio_meta); tcase_add_test (tc_chain, test_audio_info_from_caps); tcase_add_test (tc_chain, test_audio_make_raw_caps); tcase_add_test (tc_chain, test_audio_meta_serialize); tcase_add_test (tc_chain, test_audio_meta_serialize_65_chans); return s; } GST_CHECK_MAIN (audio);