Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
vivia committed Feb 18, 2021
1 parent c7f1fd8 commit 2527c8f
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 3 deletions.
26 changes: 26 additions & 0 deletions gst-libs/gst/audio/audio.c
Expand Up @@ -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.
*
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
58 changes: 55 additions & 3 deletions tests/check/libs/audio.c
Expand Up @@ -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);
Expand All @@ -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.
*/
Expand All @@ -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] = {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 2527c8f

Please sign in to comment.