gstreamer/subprojects/gst-plugins-base/tests/check/libs/audio.c
Xavier Claessens 06d9d934f9 meta: Add serialize/deserialize API
This allows metas to be serialized to be transmitted or stored. This is
intended to be used for example by gdppay or unixfdsink.

Implemented on GstCustomMeta, GstVideoMeta, GstReferenceTimestampMeta,
and GstAudioMeta.

Sponsored-by: Netflix Inc.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5355>
2023-12-17 16:13:26 +00:00

1725 lines
53 KiB
C

/* GStreamer
*
* unit tests for audio support library
*
* Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
* Copyright (C) 2011 Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* 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 <gst/check/gstcheck.h>
#include <gst/audio/audio.h>
#include <string.h>
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);