forked from hzeller/gstreamer-gapless-test
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test-loop.c
131 lines (96 loc) · 3.64 KB
/
test-loop.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
Source including Makefile and test sound file on:
https://github.com/hzeller/gstreamer-gapless-test
This is to investigate various odd behavior of gapless play with URIs with
different versions of gstreamer. The relevant bugs are:
- gstreamer-0.1: "playbin2" leaks threads playing gapless from network URIs
https://bugzilla.gnome.org/show_bug.cgi?id=698750
- gstreamer-1.0: Gapless playing using 'about-to-finish' callback fails
with HTTP-URIs
https://bugzilla.gnome.org/show_bug.cgi?id=698306
To reproduce:
Build both both versions with
make
(This expects pkg-config to work for gstreamer-0.10 and gstreamer-1.0)
== Preparation: provide sound-file via webserver ==
Run a webserver that serves the test sound file.
Webfsd is a lightweight solution (sudo aptitude install webfs). There
is a file in the sounds/ directory, let's serve that.
webfsd -r sounds/ -p 9999
== Playing URI with gstreamer 0.10 ==
Run the binary
./test-loop-0.1 http://localhost:9999/test-sound.ogg
In another shell, watch how the number of threads increase over time
$ while : ; do ps -eLf | grep test-loop | grep -v grep | wc -l ; sleep 1 ; done
.. and after some amount of repeats (~30-100) the whole process just stops
working, with many threads stuck.
== Playing URI with gstreamer 1.0 ==
./test-loop-1.0 http://localhost:9999/test-sound.ogg
This only plays the URI once and then goes into an endless loop.
== Playing a file-uri ==
Same thing works fine with both versions, if the input is a file
./test-loop-0.1 file://`pwd`/sounds/test-sound.ogg
./test-loop-1.0 file://`pwd`/sounds/test-sound.ogg
(works means: plays the same sound indefinetly, and only uses a limited
amount of threads).
*/
#include <assert.h>
#include <gst/gst.h>
#include <glib.h>
#include <string.h>
struct NextStreamData {
GstElement *pipeline;
int count;
int uri_count;
char **uris;
};
static void prepare_next_stream(GstElement *obj, gpointer userdata) {
struct NextStreamData *data = (struct NextStreamData*) userdata;
const char* next_uri = data->uris[MIN(data->count+1, data->uri_count)];
g_print("about-to-finish %4d; setting next to %s\n",
data->count, next_uri);
g_object_set(G_OBJECT(data->pipeline), "uri", next_uri, NULL);
data->count++;
}
int main (int argc, char *argv[]) {
GMainLoop *loop;
GstElement *pipeline;
/* Initialisation */
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
/* Check input arguments */
if (argc < 2) {
g_printerr ("Usage: %s <list of space-delimited filenames or URLs>\n",
argv[0]);
return -1;
}
/* Create playbin. Different names in different versions */
#if (GST_VERSION_MAJOR < 1)
pipeline = gst_element_factory_make("playbin2", "play");
#else
pipeline = gst_element_factory_make("playbin", "play");
#endif
/* Register about-to-finish callback to re-set the URI */
struct NextStreamData replay_data;
replay_data.pipeline = pipeline;
replay_data.count = 0;
replay_data.uris = &(argv[1]);
replay_data.uri_count = argc-2;
g_signal_connect(pipeline, "about-to-finish",
G_CALLBACK(prepare_next_stream), &replay_data);
/* Set initial URI */
g_object_set (G_OBJECT (pipeline), "uri", argv[1], NULL);
g_print ("Now playing: %s\n", argv[1]);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* Iterate */
g_print ("Running...\n");
g_main_loop_run (loop);
/* since we loop endlessly, the follwing is never reached */
/* Out of the main loop, clean up nicely */
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref (GST_OBJECT (pipeline));
g_main_loop_unref (loop);
return 0;
}