libs: audio: Handle meta changes in gst_audio_buffer_truncate

Set timestamp and duration to GST_CLOCK_TIME_NONE unless trim==0,
because that function doesn't know the rate and therefore can't
calculate them. Set offset and offset_end to appropriate values. Make it
clear in the documentation that the caller is responsible for setting
the timestamp and duration.

Fixes https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/issues/869

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/1039>
This commit is contained in:
Vivia Nikolaidou 2021-02-17 12:41:06 +02:00
parent c7f1fd8320
commit 2527c8f9f8
2 changed files with 81 additions and 3 deletions

View file

@ -258,6 +258,12 @@ gst_audio_buffer_clip (GstBuffer * buffer, const GstSegment * segment,
* the necessary amount of samples from the end and @trim number of samples
* from the beginning.
*
* This function does not know the audio rate, therefore the caller is
* responsible for re-setting the correct timestamp and duration to the
* buffer. However, timestamp will be preserved if trim == 0, and duration
* will also be preserved if there is no trimming to be done. Offset and
* offset end will be preserved / updated.
*
* After calling this function the caller does not own a reference to
* @buffer anymore.
*
@ -274,11 +280,14 @@ gst_audio_buffer_truncate (GstBuffer * buffer, gint bpf, gsize trim,
GstBuffer *ret = NULL;
gsize orig_samples;
gint i;
GstClockTime orig_ts, orig_offset;
g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
meta = gst_buffer_get_audio_meta (buffer);
orig_samples = meta ? meta->samples : gst_buffer_get_size (buffer) / bpf;
orig_ts = GST_BUFFER_PTS (buffer);
orig_offset = GST_BUFFER_OFFSET (buffer);
g_return_val_if_fail (trim < orig_samples, NULL);
g_return_val_if_fail (samples == -1 || trim + samples <= orig_samples, NULL);
@ -312,5 +321,22 @@ gst_audio_buffer_truncate (GstBuffer * buffer, gint bpf, gsize trim,
}
}
GST_BUFFER_DTS (ret) = GST_CLOCK_TIME_NONE;
if (GST_CLOCK_TIME_IS_VALID (orig_ts) && trim == 0) {
GST_BUFFER_PTS (ret) = orig_ts;
} else {
GST_BUFFER_PTS (ret) = GST_CLOCK_TIME_NONE;
}
/* If duration was the same, it would have meant there's no trimming to be
* done, so we have an early return further up */
GST_BUFFER_DURATION (ret) = GST_CLOCK_TIME_NONE;
if (orig_offset != GST_BUFFER_OFFSET_NONE) {
GST_BUFFER_OFFSET (ret) = orig_offset + trim;
GST_BUFFER_OFFSET_END (ret) = GST_BUFFER_OFFSET (ret) + samples;
} else {
GST_BUFFER_OFFSET (ret) = GST_BUFFER_OFFSET_NONE;
GST_BUFFER_OFFSET_END (ret) = GST_BUFFER_OFFSET_NONE;
}
return ret;
}

View file

@ -647,8 +647,7 @@ GST_START_TEST (test_buffer_clip_samples_start_and_stop_no_meta)
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),
GST_BUFFER_OFFSET_NONE);
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);
@ -664,7 +663,7 @@ GST_START_TEST (test_buffer_clip_samples_no_timestamp)
GstSegment s;
GstBuffer *buf;
/* If the buffer has no offset it should assert()
/* 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.
*/
@ -683,6 +682,57 @@ GST_START_TEST (test_buffer_clip_samples_no_timestamp)
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] = {
@ -1554,6 +1604,8 @@ audio_suite (void)
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);