benchmark: cleanup last change in capsnego benchmark
[platform/upstream/gstreamer.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)
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, GST_MESSAGE_STATE_CHANGED, -1);
145
146     if (GST_MESSAGE_SRC (msg) == (GstObject *) bin) {
147       GstState old_state, new_state;
148
149       gst_message_parse_state_changed (msg, &old_state, &new_state, NULL);
150       if (old_state == GST_STATE_READY && new_state == GST_STATE_PAUSED) {
151         running = FALSE;
152       }
153     }
154     gst_message_unref (msg);
155   }
156 }
157
158
159 gint
160 main (gint argc, gchar * argv[])
161 {
162   GstBin *bin;
163   GstClockTime start, end;
164   GstElement *sink, *new_sink;
165
166   /* default parameters */
167   gint depth = 4;
168   gint children = 3;
169   gint flavour = FLAVOUR_AUDIO;
170   const gchar *flavour_str = "audio";
171
172   gst_init (&argc, &argv);
173
174   /* check command line options */
175   if (argc) {
176     gint arg;
177     for (arg = 0; arg < argc; arg++) {
178       if (!strcmp (argv[arg], "-d")) {
179         arg++;
180         if (arg < argc)
181           depth = atoi (argv[arg]);
182       } else if (!strcmp (argv[arg], "-c")) {
183         arg++;
184         if (arg < argc)
185           children = atoi (argv[arg]);
186       } else if (!strcmp (argv[arg], "-f")) {
187         arg++;
188         if (arg < argc) {
189           flavour_str = argv[arg];
190           switch (*flavour_str) {
191             case 'a':
192               flavour = FLAVOUR_AUDIO;
193               break;
194             case 'v':
195               flavour = FLAVOUR_VIDEO;
196               break;
197             default:
198               break;
199           }
200         }
201       }
202     }
203   }
204
205   /* build pipeline */
206   g_print ("building %s pipeline with depth = %d and children = %d\n",
207       flavour_str, depth, children);
208   start = gst_util_get_timestamp ();
209   bin = GST_BIN (gst_pipeline_new ("pipeline"));
210   sink = gst_element_factory_make ("fakesink", NULL);
211   gst_bin_add (bin, sink);
212   if (!create_node (bin, sink, "sink", &new_sink, children, flavour)) {
213     goto Error;
214   }
215   if (!create_nodes (bin, new_sink, depth, children, flavour)) {
216     goto Error;
217   }
218   end = gst_util_get_timestamp ();
219   g_print ("%" GST_TIME_FORMAT " built pipeline with %d elements\n",
220       GST_TIME_ARGS (end - start), GST_BIN_NUMCHILDREN (bin));
221
222   /* meassure */
223   g_print ("starting pipeline\n");
224   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY);
225   GST_DEBUG_BIN_TO_DOT_FILE (bin, GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE, "capsnego");
226   start = gst_util_get_timestamp ();
227   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
228   event_loop (GST_ELEMENT (bin));
229   end = gst_util_get_timestamp ();
230   g_print ("%" GST_TIME_FORMAT " reached paused\n",
231       GST_TIME_ARGS (end - start));
232
233   /* clean up */
234 Error:
235   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
236   gst_object_unref (bin);
237   return 0;
238 }