1 /* GstInterTest
2  * Copyright (C) 2011 David Schleef <ds@schleef.org>
3  * Copyright (C) 2010 Entropy Wave Inc
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <gst/gst.h>
32 #include <stdlib.h>
33 
34 //#define GETTEXT_PACKAGE "intertest"
35 
36 
37 typedef struct _GstInterTest GstInterTest;
38 struct _GstInterTest
39 {
40   GstElement *pipeline;
41   GstBus *bus;
42   GMainLoop *main_loop;
43 
44   GstElement *source_element;
45   GstElement *sink_element;
46 
47   gboolean paused_for_buffering;
48   guint timer_id;
49 };
50 
51 GstInterTest *gst_inter_test_new (void);
52 void gst_inter_test_free (GstInterTest * intertest);
53 void gst_inter_test_create_pipeline_server (GstInterTest * intertest);
54 void gst_inter_test_create_pipeline_vts (GstInterTest * intertest);
55 void gst_inter_test_create_pipeline_playbin (GstInterTest * intertest,
56     const char *uri);
57 void gst_inter_test_start (GstInterTest * intertest);
58 void gst_inter_test_stop (GstInterTest * intertest);
59 
60 static gboolean gst_inter_test_handle_message (GstBus * bus,
61     GstMessage * message, gpointer data);
62 static gboolean onesecond_timer (gpointer priv);
63 
64 
65 gboolean verbose;
66 
67 static GOptionEntry entries[] = {
68   {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL},
69 
70   {NULL}
71 
72 };
73 
74 int
main(int argc,char * argv[])75 main (int argc, char *argv[])
76 {
77   GError *error = NULL;
78   GOptionContext *context;
79   GstInterTest *intertest1;
80   GstInterTest *intertest2;
81   GMainLoop *main_loop;
82 
83   context = g_option_context_new ("- Internal src/sink test");
84   g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
85   g_option_context_add_group (context, gst_init_get_option_group ());
86   if (!g_option_context_parse (context, &argc, &argv, &error)) {
87     g_print ("option parsing failed: %s\n", error->message);
88     g_option_context_free (context);
89     g_clear_error (&error);
90     exit (1);
91   }
92   g_option_context_free (context);
93 
94   intertest1 = gst_inter_test_new ();
95   gst_inter_test_create_pipeline_server (intertest1);
96   gst_inter_test_start (intertest1);
97 
98   intertest2 = gst_inter_test_new ();
99   gst_inter_test_create_pipeline_playbin (intertest2, NULL);
100   gst_inter_test_start (intertest2);
101 
102   main_loop = g_main_loop_new (NULL, TRUE);
103   intertest1->main_loop = main_loop;
104   intertest2->main_loop = main_loop;
105 
106   g_main_loop_run (main_loop);
107   g_main_loop_unref (main_loop);
108 
109   exit (0);
110 }
111 
112 
113 GstInterTest *
gst_inter_test_new(void)114 gst_inter_test_new (void)
115 {
116   GstInterTest *intertest;
117 
118   intertest = g_new0 (GstInterTest, 1);
119 
120   return intertest;
121 }
122 
123 void
gst_inter_test_free(GstInterTest * intertest)124 gst_inter_test_free (GstInterTest * intertest)
125 {
126   if (intertest->source_element) {
127     gst_object_unref (intertest->source_element);
128     intertest->source_element = NULL;
129   }
130   if (intertest->sink_element) {
131     gst_object_unref (intertest->sink_element);
132     intertest->sink_element = NULL;
133   }
134 
135   if (intertest->bus) {
136     gst_object_unref (intertest->bus);
137     intertest->bus = NULL;
138   }
139 
140   if (intertest->pipeline) {
141     gst_element_set_state (intertest->pipeline, GST_STATE_NULL);
142     gst_object_unref (intertest->pipeline);
143     intertest->pipeline = NULL;
144   }
145   g_free (intertest);
146 }
147 
148 void
gst_inter_test_create_pipeline_playbin(GstInterTest * intertest,const char * uri)149 gst_inter_test_create_pipeline_playbin (GstInterTest * intertest,
150     const char *uri)
151 {
152   GstElement *pipeline;
153 
154   if (uri == NULL) {
155     gst_inter_test_create_pipeline_vts (intertest);
156     return;
157   }
158 
159   pipeline = gst_pipeline_new (NULL);
160   gst_bin_add (GST_BIN (pipeline),
161       gst_element_factory_make ("playbin", "source"));
162 
163   intertest->pipeline = pipeline;
164 
165   gst_pipeline_set_auto_flush_bus (GST_PIPELINE (pipeline), FALSE);
166   intertest->bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
167   gst_bus_add_watch (intertest->bus, gst_inter_test_handle_message, intertest);
168 
169   intertest->source_element =
170       gst_bin_get_by_name (GST_BIN (pipeline), "source");
171   g_print ("source_element is %p\n", intertest->source_element);
172 
173   g_print ("setting uri to %s\n", uri);
174   g_object_set (intertest->source_element, "uri", uri, NULL);
175 }
176 
177 void
gst_inter_test_create_pipeline_vts(GstInterTest * intertest)178 gst_inter_test_create_pipeline_vts (GstInterTest * intertest)
179 {
180   GString *pipe_desc;
181   GstElement *pipeline;
182   GError *error = NULL;
183 
184   pipe_desc = g_string_new ("");
185 
186   g_string_append (pipe_desc, "videotestsrc name=source num-buffers=100 ! ");
187   g_string_append (pipe_desc,
188       "video/x-raw,format=(string)I420,width=320,height=240 ! ");
189   g_string_append (pipe_desc, "timeoverlay ! ");
190   g_string_append (pipe_desc, "intervideosink name=sink sync=true ");
191   g_string_append (pipe_desc,
192       "audiotestsrc samplesperbuffer=1600 num-buffers=100 ! audioconvert ! ");
193   g_string_append (pipe_desc, "interaudiosink sync=true ");
194 
195   if (verbose)
196     g_print ("pipeline: %s\n", pipe_desc->str);
197 
198   pipeline = (GstElement *) gst_parse_launch (pipe_desc->str, &error);
199   g_string_free (pipe_desc, TRUE);
200 
201   if (error) {
202     g_print ("pipeline parsing error: %s\n", error->message);
203     gst_object_unref (pipeline);
204     g_clear_error (&error);
205     return;
206   }
207 
208   intertest->pipeline = pipeline;
209 
210   gst_pipeline_set_auto_flush_bus (GST_PIPELINE (pipeline), FALSE);
211   intertest->bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
212   gst_bus_add_watch (intertest->bus, gst_inter_test_handle_message, intertest);
213 
214   intertest->source_element =
215       gst_bin_get_by_name (GST_BIN (pipeline), "source");
216   intertest->sink_element = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
217 }
218 
219 void
gst_inter_test_create_pipeline_server(GstInterTest * intertest)220 gst_inter_test_create_pipeline_server (GstInterTest * intertest)
221 {
222   GString *pipe_desc;
223   GstElement *pipeline;
224   GError *error = NULL;
225 
226   pipe_desc = g_string_new ("");
227 
228   g_string_append (pipe_desc, "intervideosrc ! queue ! ");
229   g_string_append (pipe_desc, "xvimagesink name=sink ");
230   g_string_append (pipe_desc, "interaudiosrc ! queue ! ");
231   g_string_append (pipe_desc, "alsasink ");
232 
233   if (verbose)
234     g_print ("pipeline: %s\n", pipe_desc->str);
235 
236   pipeline = (GstElement *) gst_parse_launch (pipe_desc->str, &error);
237   g_string_free (pipe_desc, TRUE);
238 
239   if (error) {
240     g_print ("pipeline parsing error: %s\n", error->message);
241     gst_object_unref (pipeline);
242     g_clear_error (&error);
243     return;
244   }
245 
246   intertest->pipeline = pipeline;
247 
248   gst_pipeline_set_auto_flush_bus (GST_PIPELINE (pipeline), FALSE);
249   intertest->bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
250   gst_bus_add_watch (intertest->bus, gst_inter_test_handle_message, intertest);
251 
252   intertest->source_element =
253       gst_bin_get_by_name (GST_BIN (pipeline), "source");
254   intertest->sink_element = gst_bin_get_by_name (GST_BIN (pipeline), "sink");
255 }
256 
257 void
gst_inter_test_start(GstInterTest * intertest)258 gst_inter_test_start (GstInterTest * intertest)
259 {
260   gst_element_set_state (intertest->pipeline, GST_STATE_READY);
261 
262   intertest->timer_id = g_timeout_add (1000, onesecond_timer, intertest);
263 }
264 
265 void
gst_inter_test_stop(GstInterTest * intertest)266 gst_inter_test_stop (GstInterTest * intertest)
267 {
268   gst_element_set_state (intertest->pipeline, GST_STATE_NULL);
269 
270   g_source_remove (intertest->timer_id);
271 }
272 
273 static void
gst_inter_test_handle_eos(GstInterTest * intertest)274 gst_inter_test_handle_eos (GstInterTest * intertest)
275 {
276   gst_inter_test_stop (intertest);
277 }
278 
279 static void
gst_inter_test_handle_error(GstInterTest * intertest,GError * error,const char * debug)280 gst_inter_test_handle_error (GstInterTest * intertest, GError * error,
281     const char *debug)
282 {
283   g_print ("error: %s\n", error->message);
284   gst_inter_test_stop (intertest);
285 }
286 
287 static void
gst_inter_test_handle_warning(GstInterTest * intertest,GError * error,const char * debug)288 gst_inter_test_handle_warning (GstInterTest * intertest, GError * error,
289     const char *debug)
290 {
291   g_print ("warning: %s\n", error->message);
292 }
293 
294 static void
gst_inter_test_handle_info(GstInterTest * intertest,GError * error,const char * debug)295 gst_inter_test_handle_info (GstInterTest * intertest, GError * error,
296     const char *debug)
297 {
298   g_print ("info: %s\n", error->message);
299 }
300 
301 static void
gst_inter_test_handle_null_to_ready(GstInterTest * intertest)302 gst_inter_test_handle_null_to_ready (GstInterTest * intertest)
303 {
304   gst_element_set_state (intertest->pipeline, GST_STATE_PAUSED);
305 
306 }
307 
308 static void
gst_inter_test_handle_ready_to_paused(GstInterTest * intertest)309 gst_inter_test_handle_ready_to_paused (GstInterTest * intertest)
310 {
311   if (!intertest->paused_for_buffering) {
312     gst_element_set_state (intertest->pipeline, GST_STATE_PLAYING);
313   }
314 }
315 
316 static void
gst_inter_test_handle_paused_to_playing(GstInterTest * intertest)317 gst_inter_test_handle_paused_to_playing (GstInterTest * intertest)
318 {
319 
320 }
321 
322 static void
gst_inter_test_handle_playing_to_paused(GstInterTest * intertest)323 gst_inter_test_handle_playing_to_paused (GstInterTest * intertest)
324 {
325 
326 }
327 
328 static void
gst_inter_test_handle_paused_to_ready(GstInterTest * intertest)329 gst_inter_test_handle_paused_to_ready (GstInterTest * intertest)
330 {
331 
332 }
333 
334 static void
gst_inter_test_handle_ready_to_null(GstInterTest * intertest)335 gst_inter_test_handle_ready_to_null (GstInterTest * intertest)
336 {
337   //g_main_loop_quit (intertest->main_loop);
338 
339 }
340 
341 
342 static gboolean
gst_inter_test_handle_message(GstBus * bus,GstMessage * message,gpointer data)343 gst_inter_test_handle_message (GstBus * bus, GstMessage * message,
344     gpointer data)
345 {
346   GstInterTest *intertest = (GstInterTest *) data;
347 
348   switch (GST_MESSAGE_TYPE (message)) {
349     case GST_MESSAGE_EOS:
350       gst_inter_test_handle_eos (intertest);
351       break;
352     case GST_MESSAGE_ERROR:
353     {
354       GError *error = NULL;
355       gchar *debug;
356 
357       gst_message_parse_error (message, &error, &debug);
358       gst_inter_test_handle_error (intertest, error, debug);
359       g_clear_error (&error);
360       g_free (debug);
361     }
362       break;
363     case GST_MESSAGE_WARNING:
364     {
365       GError *error = NULL;
366       gchar *debug;
367 
368       gst_message_parse_warning (message, &error, &debug);
369       gst_inter_test_handle_warning (intertest, error, debug);
370       g_clear_error (&error);
371       g_free (debug);
372     }
373       break;
374     case GST_MESSAGE_INFO:
375     {
376       GError *error = NULL;
377       gchar *debug;
378 
379       gst_message_parse_info (message, &error, &debug);
380       gst_inter_test_handle_info (intertest, error, debug);
381       g_clear_error (&error);
382       g_free (debug);
383     }
384       break;
385     case GST_MESSAGE_TAG:
386     {
387       GstTagList *tag_list;
388 
389       gst_message_parse_tag (message, &tag_list);
390       if (verbose)
391         g_print ("tag\n");
392     }
393       break;
394     case GST_MESSAGE_STATE_CHANGED:
395     {
396       GstState oldstate, newstate, pending;
397 
398       gst_message_parse_state_changed (message, &oldstate, &newstate, &pending);
399       if (GST_ELEMENT (message->src) == intertest->pipeline) {
400         if (verbose)
401           g_print ("state change from %s to %s\n",
402               gst_element_state_get_name (oldstate),
403               gst_element_state_get_name (newstate));
404         switch (GST_STATE_TRANSITION (oldstate, newstate)) {
405           case GST_STATE_CHANGE_NULL_TO_READY:
406             gst_inter_test_handle_null_to_ready (intertest);
407             break;
408           case GST_STATE_CHANGE_READY_TO_PAUSED:
409             gst_inter_test_handle_ready_to_paused (intertest);
410             break;
411           case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
412             gst_inter_test_handle_paused_to_playing (intertest);
413             break;
414           case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
415             gst_inter_test_handle_playing_to_paused (intertest);
416             break;
417           case GST_STATE_CHANGE_PAUSED_TO_READY:
418             gst_inter_test_handle_paused_to_ready (intertest);
419             break;
420           case GST_STATE_CHANGE_READY_TO_NULL:
421             gst_inter_test_handle_ready_to_null (intertest);
422             break;
423           default:
424             if (verbose)
425               g_print ("unknown state change from %s to %s\n",
426                   gst_element_state_get_name (oldstate),
427                   gst_element_state_get_name (newstate));
428         }
429       }
430     }
431       break;
432     case GST_MESSAGE_BUFFERING:
433     {
434       int percent;
435       gst_message_parse_buffering (message, &percent);
436       //g_print("buffering %d\n", percent);
437       if (!intertest->paused_for_buffering && percent < 100) {
438         g_print ("pausing for buffing\n");
439         intertest->paused_for_buffering = TRUE;
440         gst_element_set_state (intertest->pipeline, GST_STATE_PAUSED);
441       } else if (intertest->paused_for_buffering && percent == 100) {
442         g_print ("unpausing for buffing\n");
443         intertest->paused_for_buffering = FALSE;
444         gst_element_set_state (intertest->pipeline, GST_STATE_PLAYING);
445       }
446     }
447       break;
448     case GST_MESSAGE_STATE_DIRTY:
449     case GST_MESSAGE_CLOCK_PROVIDE:
450     case GST_MESSAGE_CLOCK_LOST:
451     case GST_MESSAGE_NEW_CLOCK:
452     case GST_MESSAGE_STRUCTURE_CHANGE:
453     case GST_MESSAGE_STREAM_STATUS:
454       break;
455     case GST_MESSAGE_STEP_DONE:
456     case GST_MESSAGE_APPLICATION:
457     case GST_MESSAGE_ELEMENT:
458     case GST_MESSAGE_SEGMENT_START:
459     case GST_MESSAGE_SEGMENT_DONE:
460     case GST_MESSAGE_LATENCY:
461     case GST_MESSAGE_ASYNC_START:
462     case GST_MESSAGE_ASYNC_DONE:
463     case GST_MESSAGE_REQUEST_STATE:
464     case GST_MESSAGE_STEP_START:
465     default:
466       if (verbose) {
467         g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message));
468       }
469       break;
470     case GST_MESSAGE_QOS:
471       break;
472   }
473 
474   return TRUE;
475 }
476 
477 
478 
479 static gboolean
onesecond_timer(gpointer priv)480 onesecond_timer (gpointer priv)
481 {
482   //GstInterTest *intertest = (GstInterTest *)priv;
483 
484   g_print (".\n");
485 
486   return TRUE;
487 }
488 
489 
490 
491 /* helper functions */
492 
493 #if 0
494 gboolean
495 have_element (const gchar * element_name)
496 {
497   GstPluginFeature *feature;
498 
499   feature = gst_default_registry_find_feature (element_name,
500       GST_TYPE_ELEMENT_FACTORY);
501   if (feature) {
502     g_object_unref (feature);
503     return TRUE;
504   }
505   return FALSE;
506 }
507 #endif
508