libs: audio: Handle meta changes in gst_audio_buffer_truncate
authorVivia Nikolaidou <vivia@ahiru.eu>
Wed, 17 Feb 2021 10:41:06 +0000 (12:41 +0200)
committerVivia Nikolaidou <vivia@ahiru.eu>
Thu, 18 Feb 2021 09:25:32 +0000 (11:25 +0200)
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>

gst-libs/gst/audio/audio.c
tests/check/libs/audio.c

index 440a4e8..075b8db 100644 (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;
 }
index 3221450..7a01995 100644 (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);