Git init
[framework/multimedia/gstreamer0.10.git] / tests / benchmarks / capsnego.c
1 /* GStreamer
2  * Copyright (C) 2010 Stefan Kost <ensonic@users.sf.net>
3  *
4  * capsnego.c: benchmark for caps negotiation
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 /* this benchmark recursively builds a pipeline and meassures the time to go
23  * from ready to paused.
24  * The graph size and type can be controlled with a few commandline args:
25  *  -d depth: is the depth of the tree
26  *  -c children: is the number of branches on each level
27  *  -f <flavour>: can be a=udio/v=ideo and is conttrolling the kind of elements
28  *                that are used.
29  */
30
31 #include <gst/gst.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 enum
36 {
37   FLAVOUR_AUDIO = 0,
38   FLAVOUR_VIDEO,
39   NUM_FLAVOURS
40 };
41
42 enum
43 {
44   ELEM_SRC = 0,
45   ELEM_MIX,
46   ELEM_PROC,
47   ELEM_CONV,
48   NUM_ELEM
49 };
50
51 static const gchar *factories[NUM_FLAVOURS][NUM_ELEM] = {
52   {"audiotestsrc", "adder", "volume", "audioconvert"},
53   {"videotestsrc", "videomixer", "videoscale", "ffmpegcolorspace"}
54 };
55
56 static const gchar *sink_pads[NUM_FLAVOURS][NUM_ELEM] = {
57   {NULL, "sink%d", NULL, NULL},
58   {NULL, "sink_%d", NULL, NULL}
59 };
60
61
62 static gboolean
63 create_node (GstBin * bin, GstElement * sink, const gchar * sinkpadname,
64     GstElement ** new_sink, gint children, gint flavour)
65 {
66   GstElement *mix, *proc, *conv;
67
68   if (children >= 1) {
69     mix = gst_element_factory_make (factories[flavour][ELEM_MIX], NULL);
70     if (!mix) {
71       GST_WARNING ("need element '%s'", factories[flavour][ELEM_MIX]);
72       return FALSE;
73     }
74   } else {
75     mix = gst_element_factory_make ("identity", NULL);
76   }
77   proc = gst_element_factory_make (factories[flavour][ELEM_PROC], NULL);
78   if (!proc) {
79     GST_WARNING ("need element '%s'", factories[flavour][ELEM_PROC]);
80     return FALSE;
81   }
82   conv = gst_element_factory_make (factories[flavour][ELEM_CONV], NULL);
83   if (!conv) {
84     GST_WARNING ("need element '%s'", factories[flavour][ELEM_CONV]);
85     return FALSE;
86   }
87   gst_bin_add_many (bin, mix, proc, conv, NULL);
88   if (!gst_element_link_pads_full (mix, "src", proc, "sink",
89           GST_PAD_LINK_CHECK_NOTHING)
90       || !gst_element_link_pads_full (proc, "src", conv, "sink",
91           GST_PAD_LINK_CHECK_NOTHING)
92       || !gst_element_link_pads_full (conv, "src", sink, sinkpadname,
93           GST_PAD_LINK_CHECK_NOTHING)) {
94     GST_WARNING ("can't link elements");
95     return FALSE;
96   }
97   *new_sink = mix;
98   return TRUE;
99 }
100
101 static gboolean
102 create_nodes (GstBin * bin, GstElement * sink, gint depth, gint children,
103     gint flavour)
104 {
105   GstElement *new_sink, *src;
106   gint i;
107
108   for (i = 0; i < children; i++) {
109     if (depth > 0) {
110       if (!create_node (bin, sink, sink_pads[flavour][ELEM_MIX], &new_sink,
111               children, flavour)) {
112         return FALSE;
113       }
114       if (!create_nodes (bin, new_sink, depth - 1, children, flavour)) {
115         return FALSE;
116       }
117     } else {
118       src = gst_element_factory_make (factories[flavour][ELEM_SRC], NULL);
119       if (!src) {
120         GST_WARNING ("need element '%s'", factories[flavour][ELEM_SRC]);
121         return FALSE;
122       }
123       gst_bin_add (bin, src);
124       if (!gst_element_link_pads_full (src, "src", sink,
125               sink_pads[flavour][ELEM_MIX], GST_PAD_LINK_CHECK_NOTHING)) {
126         GST_WARNING ("can't link elements");
127         return FALSE;
128       }
129     }
130   }
131   return TRUE;
132 }
133
134 static void
135 event_loop (GstElement * bin, GstClockTime start)
136 {
137   GstBus *bus;
138   GstMessage *msg = NULL;
139   gboolean running = TRUE;
140
141   bus = gst_element_get_bus (bin);
142
143   while (running) {
144     msg = gst_bus_poll (bus,
145         GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_WARNING,
146         -1);
147
148     switch (GST_MESSAGE_TYPE (msg)) {
149       case GST_MESSAGE_STATE_CHANGED:
150         if (GST_MESSAGE_SRC (msg) == (GstObject *) bin) {
151           GstState old_state, new_state;
152           GstClockTime end;
153
154           gst_message_parse_state_changed (msg, &old_state, &new_state, NULL);
155
156           end = gst_util_get_timestamp ();
157           g_print ("%" GST_TIME_FORMAT " state change on the bin: %s -> %s\n",
158               GST_TIME_ARGS (end - start),
159               gst_element_state_get_name (old_state),
160               gst_element_state_get_name (new_state));
161
162           if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) {
163             running = FALSE;
164           }
165         }
166         break;
167       case GST_MESSAGE_WARNING:{
168         GError *err = NULL;
169         gchar *dbg = NULL;
170
171         gst_message_parse_warning (msg, &err, &dbg);
172         GST_WARNING_OBJECT (GST_MESSAGE_SRC (msg), "%s (%s)", err->message,
173             (dbg ? dbg : "no details"));
174         g_error_free (err);
175         g_free (dbg);
176         break;
177       }
178       case GST_MESSAGE_ERROR:{
179         GError *err = NULL;
180         gchar *dbg = NULL;
181
182         gst_message_parse_error (msg, &err, &dbg);
183         GST_ERROR_OBJECT (GST_MESSAGE_SRC (msg), "%s (%s)", err->message,
184             (dbg ? dbg : "no details"));
185         g_error_free (err);
186         g_free (dbg);
187         running = FALSE;
188         break;
189       }
190       default:
191         break;
192     }
193     gst_message_unref (msg);
194   }
195   gst_object_unref (bus);
196 }
197
198
199 gint
200 main (gint argc, gchar * argv[])
201 {
202   GstBin *bin;
203   GstClockTime start, end;
204   GstElement *sink, *new_sink;
205
206   /* default parameters */
207   gint depth = 4;
208   gint children = 3;
209   gint flavour = FLAVOUR_AUDIO;
210   const gchar *flavour_str = "audio";
211
212   gst_init (&argc, &argv);
213
214   /* check command line options */
215   if (argc) {
216     gint arg;
217     for (arg = 0; arg < argc; arg++) {
218       if (!strcmp (argv[arg], "-d")) {
219         arg++;
220         if (arg < argc)
221           depth = atoi (argv[arg]);
222       } else if (!strcmp (argv[arg], "-c")) {
223         arg++;
224         if (arg < argc)
225           children = atoi (argv[arg]);
226       } else if (!strcmp (argv[arg], "-f")) {
227         arg++;
228         if (arg < argc) {
229           flavour_str = argv[arg];
230           switch (*flavour_str) {
231             case 'a':
232               flavour = FLAVOUR_AUDIO;
233               break;
234             case 'v':
235               flavour = FLAVOUR_VIDEO;
236               break;
237             default:
238               break;
239           }
240         }
241       }
242     }
243   }
244
245   /* build pipeline */
246   g_print ("building %s pipeline with depth = %d and children = %d\n",
247       flavour_str, depth, children);
248   start = gst_util_get_timestamp ();
249   bin = GST_BIN (gst_pipeline_new ("pipeline"));
250   sink = gst_element_factory_make ("fakesink", NULL);
251   gst_bin_add (bin, sink);
252   if (!create_node (bin, sink, "sink", &new_sink, children, flavour)) {
253     goto Error;
254   }
255   if (!create_nodes (bin, new_sink, depth, children, flavour)) {
256     goto Error;
257   }
258   end = gst_util_get_timestamp ();
259   /* num-threads = num-sources = pow (children, depth) */
260   g_print ("%" GST_TIME_FORMAT " built pipeline with %d elements\n",
261       GST_TIME_ARGS (end - start), GST_BIN_NUMCHILDREN (bin));
262
263   /* meassure */
264   g_print ("starting pipeline\n");
265   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
266   GST_DEBUG_BIN_TO_DOT_FILE (bin, GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE, "capsnego");
267   start = gst_util_get_timestamp ();
268   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
269   event_loop (GST_ELEMENT (bin), start);
270   end = gst_util_get_timestamp ();
271   g_print ("%" GST_TIME_FORMAT " reached paused\n",
272       GST_TIME_ARGS (end - start));
273
274   /* clean up */
275 Error:
276   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
277   gst_object_unref (bin);
278   return 0;
279 }