audiotestsrc: Fix the way we compute EOS in reverse playback
authorThibault Saunier <tsaunier@igalia.com>
Sat, 23 May 2020 03:24:55 +0000 (23:24 -0400)
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Mon, 25 May 2020 08:19:02 +0000 (08:19 +0000)
In reverse playback we were not taking into account the current buffer
samples to check if we had reached EOS which was leading to a buffer
with PTS = CLOCK_TIME_NONE containing too many frames followed by a
useless buffer with pts=0 duration=0, and a g_critical issue in
gst_object_sync_values.

Also add a validate based test case.
Without that patch this is how the expectation fails:

``` diff
--- log-asink-sink-expected       2020-05-22 23:22:42.654384579 -0400
+++ log-asink-sink-actual  2020-05-22 23:29:35.671586380 -0400
@@ -27,5 +27,6 @@
 buffer: pts=0:00:00.058820861, due=0:00:00.023219955, flags=discont
 buffer: pts=0:00:00.035600907, due=0:00:00.023219954, flags=discont
 buffer: pts=0:00:00.012380952, due=0:00:00.023219955, flags=discont
-buffer: pts=0:00:00.000000000, due=0:00:00.012380952, flags=discont
+buffer: due=0:00:00.012380953, flags=discont
+buffer: pts=0:00:00.000000000, flags=discont
 event eos: (no structure)
 ```

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/667>

gst/audiotestsrc/gstaudiotestsrc.c
meson_options.txt
tests/check/meson.build
tests/meson.build
tests/validate/audiotestsrc/reverse.validatetest [new file with mode: 0644]
tests/validate/audiotestsrc/reverse/flow-expectations/log-asink-sink-expected [new file with mode: 0644]
tests/validate/meson.build [new file with mode: 0644]

index b06b336..00645eb 100644 (file)
@@ -1489,10 +1489,10 @@ gst_audio_test_src_fill (GstBaseSrc * basesrc, guint64 offset,
     next_sample = src->sample_stop;
     src->eos_reached = TRUE;
   } else if (src->check_seek_stop && src->reverse &&
-      (src->sample_stop > src->next_sample)
+      (src->sample_stop >= (src->next_sample - samples))
       ) {
     /* calculate only partial buffer */
-    src->generate_samples_per_buffer = src->sample_stop - src->next_sample;
+    src->generate_samples_per_buffer = src->next_sample - src->sample_stop;
     next_sample = src->sample_stop;
     src->eos_reached = TRUE;
   } else {
index bb3cb3c..a1bee94 100644 (file)
@@ -87,3 +87,5 @@ option('package-origin', type : 'string', value : 'Unknown package origin', yiel
        description : 'package origin URL to use in plugins')
 option('doc', type : 'feature', value : 'auto', yield: true,
        description: 'Enable documentation.')
+option('validate', type : 'feature', value : 'auto', yield: true,
+       description: 'Enable validate tests.')
index f06bc08..81e8b45 100644 (file)
@@ -131,15 +131,6 @@ test_deps = [gst_dep, gst_base_dep, gst_net_dep, gst_check_dep, audio_dep,
   video_dep, pbutils_dep, rtp_dep, rtsp_dep, tag_dep, allocators_dep, app_dep,
   fft_dep, riff_dep, sdp_dep, gio_dep, valgrind_dep] + glib_deps
 
-pluginsdirs = []
-if gst_dep.type_name() == 'pkgconfig'
-  pluginsdirs = [gst_dep.get_pkgconfig_variable('pluginsdir')]
-  gst_plugin_scanner_dir = gst_dep.get_pkgconfig_variable('pluginscannerdir')
-else
-  gst_plugin_scanner_dir = gst_proj.get_variable('gst_scanner_dir')
-endif
-gst_plugin_scanner_path = join_paths(gst_plugin_scanner_dir, 'gst-plugin-scanner')
-
 foreach t : base_tests
   fname = t.get(0)
   test_name = fname.split('.').get(0).underscorify()
index c53d538..b15dd52 100644 (file)
@@ -1,3 +1,12 @@
+pluginsdirs = []
+if gst_dep.type_name() == 'pkgconfig'
+  pluginsdirs = [gst_dep.get_pkgconfig_variable('pluginsdir')]
+  gst_plugin_scanner_dir = gst_dep.get_pkgconfig_variable('pluginscannerdir')
+else
+  gst_plugin_scanner_dir = gst_proj.get_variable('gst_scanner_dir')
+endif
+gst_plugin_scanner_path = join_paths(gst_plugin_scanner_dir, 'gst-plugin-scanner')
+
 if not get_option('tests').disabled() and gst_check_dep.found()
   subdir('check')
   subdir('icles')
@@ -5,3 +14,7 @@ endif
 if not get_option('examples').disabled()
   subdir('examples')
 endif
+
+if not get_option('validate').disabled()
+  subdir('validate')
+endif
diff --git a/tests/validate/audiotestsrc/reverse.validatetest b/tests/validate/audiotestsrc/reverse.validatetest
new file mode 100644 (file)
index 0000000..3c7438a
--- /dev/null
@@ -0,0 +1,24 @@
+meta,
+    args = {
+        "audiotestsrc name=src samplesperbuffer=1024 ! audio/x-raw,format=S16LE,rate=44100 ! fakesink name=asink sync=true",
+    },
+    configs = {
+        "$(validateflow), pad=asink:sink, record-buffers=true",
+    },
+    handles-states=true,
+    ignore-eos=true
+
+play;
+seek, start=0.0, stop=0.5, rate=-1.0, flags=accurate+flush
+
+crank-clock, expected-time=0.0
+
+# roundup((44100 / 2 / 1024) - 1 (already cranked) + 1 (for eos)) = 22
+crank-clock, repeat=22
+
+set-property, target-element-name="src", property-name="samplesperbuffer", property-value=4410, on-message=eos
+seek, start=0.0, stop=1.0, rate=-1.0, flags=accurate+flush
+crank-clock, expected-elapsed-time=0.0
+crank-clock, repeat=10,  expected-elapsed-time=0.1
+
+stop, on-message=eos;
\ No newline at end of file
diff --git a/tests/validate/audiotestsrc/reverse/flow-expectations/log-asink-sink-expected b/tests/validate/audiotestsrc/reverse/flow-expectations/log-asink-sink-expected
new file mode 100644 (file)
index 0000000..5f0ca2a
--- /dev/null
@@ -0,0 +1,45 @@
+event stream-start: GstEventStreamStart, flags=(GstStreamFlags)GST_STREAM_FLAG_NONE, group-id=(uint)1;
+event caps: audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)44100, channels=(int)1;
+event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=none, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.000000000
+event tag: GstTagList-stream, taglist=(taglist)"taglist\,\ description\=\(string\)\"audiotest\\\ wave\"\;";
+buffer: pts=0:00:00.000000000, dur=0:00:00.023219954, flags=discont
+event flush-start: (no structure)
+event flush-stop: GstEventFlushStop, reset-time=(boolean)true;
+event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:00.500000000, rate=-1.000000, flags=0x01, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:00.500000000
+buffer: pts=0:00:00.476780045, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.453560090, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.430340136, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.407120181, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.383900226, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.360680272, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.337460317, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.314240362, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.291020408, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.267800453, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.244580498, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.221360544, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.198140589, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.174920634, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.151700680, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.128480725, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.105260770, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.082040816, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.058820861, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.035600907, dur=0:00:00.023219954, flags=discont
+buffer: pts=0:00:00.012380952, dur=0:00:00.023219955, flags=discont
+buffer: pts=0:00:00.000000000, dur=0:00:00.012380952, flags=discont
+event eos: (no structure)
+event flush-start: (no structure)
+event flush-stop: GstEventFlushStop, reset-time=(boolean)true;
+event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, stop=0:00:01.000000000, rate=-1.000000, flags=0x01, time=0:00:00.000000000, base=0:00:00.000000000, position=0:00:01.000000000
+buffer: pts=0:00:00.900000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.800000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.700000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.600000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.500000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.400000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.300000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.200000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.100000000, dur=0:00:00.100000000, flags=discont
+buffer: pts=0:00:00.000000000, dur=0:00:00.100000000, flags=discont
+event eos: (no structure)
diff --git a/tests/validate/meson.build b/tests/validate/meson.build
new file mode 100644 (file)
index 0000000..9d7d065
--- /dev/null
@@ -0,0 +1,33 @@
+if gst_dep.type_name() == 'internal'
+    gst_tester = gst_proj.get_variable('gst_tester')
+else
+    gst_tester = find_program('gst-tester-@0@'.format(api_version), required: get_option('validate'))
+    if not gst_tester.found()
+        subdir_done()
+    endif
+endif
+
+tests = [
+    'audiotestsrc/reverse',
+]
+
+env = environment()
+env.set('GST_PLUGIN_PATH_1_0', meson.build_root(), pluginsdirs)
+env.set('GST_PLUGIN_SYSTEM_PATH_1_0', '')
+env.set('GST_REGISTRY', '@0@/@1@.registry'.format(meson.current_build_dir(), 'validate'))
+env.set('GST_PLUGIN_SCANNER_1_0', gst_plugin_scanner_path)
+env.set('GST_PLUGIN_LOADING_WHITELIST', 'gstreamer',
+    'gst-plugins-base@' + meson.build_root())
+
+foreach t: tests
+    test_dir_name = t.split('/')
+    test_name = 'validate'
+    foreach c: test_dir_name
+        test_name += '.' + c
+    endforeach
+    test_env = env
+    test_env.set('GST_VALIDATE_LOGSDIR', join_paths(meson.current_build_dir(), test_name))
+    test_file = join_paths(meson.current_source_dir(), t + '.validatetest')
+    test(test_name, gst_tester, args: [test_file, '--use-fakesinks'],
+        env: test_env, timeout : 3 * 60, protocol: 'tap')
+endforeach
\ No newline at end of file