First THREADED backport attempt, focusing on adding locks and making sure the API...
[platform/upstream/gstreamer.git] / tools / gst-md5sum.c
1 #ifdef HAVE_CONFIG_H
2 #  include "config.h"
3 #endif
4
5 #include <string.h>
6 #include <stdlib.h>
7 #include <gst/gst.h>
8 #include <locale.h>
9
10 static guint64 iterations = 0;
11 static guint64 sum = 0;
12 static guint64 min = G_MAXINT64;
13 static guint64 max = 0;
14 static GstClock *s_clock;
15 static GMainLoop *loop;
16
17 gboolean
18 idle_func (gpointer data)
19 {
20   gboolean busy;
21   GTimeVal tfthen, tfnow;
22   GstClockTimeDiff diff;
23
24   if (s_clock) {
25     //g_print ("%lld\n", gst_clock_get_time (s_clock));
26   }
27
28   g_get_current_time (&tfthen);
29   busy = gst_bin_iterate (GST_BIN (data));
30   iterations++;
31   g_get_current_time (&tfnow);
32
33   diff = GST_TIMEVAL_TO_TIME (tfnow) - GST_TIMEVAL_TO_TIME (tfthen);
34
35   sum += diff;
36   min = MIN (min, diff);
37   max = MAX (max, diff);
38
39   if (!busy) {
40     g_main_loop_quit (loop);
41     g_main_loop_unref (loop);
42     /*
43        g_print ("execution ended after %llu iterations (sum %llu ns, average %llu ns, min %llu ns, max %llu ns)\n", 
44        iterations, sum, sum/iterations, min, max);
45      */
46   }
47
48   return busy;
49 }
50
51 int
52 main (int argc, char *argv[])
53 {
54   /* options */
55   gboolean verbose = FALSE;
56   gchar *exclude_args = NULL;
57   struct poptOption options[] = {
58     {"verbose", 'v', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &verbose, 0,
59         "do not output status information", NULL},
60     POPT_TABLEEND
61   };
62
63   GstElement *pipeline = NULL;
64   gchar **argvn;
65   GError *error = NULL;
66   GstElement *md5sink;
67   gchar *md5string = g_malloc0 (33);
68
69   free (malloc (8));            /* -lefence */
70
71   setlocale (LC_ALL, "");
72
73   gst_init_with_popt_table (&argc, &argv, options);
74
75   /* make a parseable argvn array */
76   argvn = g_new0 (char *, argc);
77   memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
78
79   /* Check if we have an element already that is called md5sink0
80      in the pipeline; if not, add one */
81   pipeline = (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
82   if (!pipeline) {
83     if (error) {
84       g_warning ("pipeline could not be constructed: %s\n", error->message);
85       g_error_free (error);
86     } else
87       g_warning ("pipeline could not be constructed\n");
88     return 1;
89   }
90
91   md5sink = gst_bin_get_by_name (GST_BIN (pipeline), "md5sink0");
92   if (md5sink == NULL) {
93     g_print ("adding an md5sink element to the pipeline\n");
94     /* make a null-terminated version of argv with ! md5sink appended
95      * ! is stored in argvn[argc - 1], md5sink in argvn[argc],
96      * NULL pointer in argvn[argc + 1] */
97     g_free (argvn);
98     argvn = g_new0 (char *, argc + 2);
99     memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
100     argvn[argc - 1] = g_strdup_printf ("!");
101     argvn[argc] = g_strdup_printf ("md5sink");
102     pipeline =
103         (GstElement *) gst_parse_launchv ((const gchar **) argvn, &error);
104   }
105
106   if (!pipeline) {
107     if (error) {
108       g_warning ("pipeline could not be constructed: %s\n", error->message);
109       g_error_free (error);
110     } else
111       g_warning ("pipeline could not be constructed\n");
112     return 1;
113   }
114
115   if (verbose) {
116     gchar **exclude_list = exclude_args ? g_strsplit (exclude_args, ",", 0)
117         : NULL;
118
119     g_signal_connect (pipeline, "deep_notify",
120         G_CALLBACK (gst_element_default_deep_notify), exclude_list);
121   }
122   g_signal_connect (pipeline, "error",
123       G_CALLBACK (gst_element_default_error), NULL);
124
125   if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS) {
126     g_warning ("pipeline doesn't want to play\n");
127     return 0;
128   }
129
130   if (!GST_FLAG_IS_SET (GST_OBJECT (pipeline), GST_BIN_SELF_SCHEDULABLE)) {
131     g_idle_add (idle_func, pipeline);
132     loop = g_main_loop_new (NULL, FALSE);
133     g_main_loop_run (loop);
134   } else {
135     gst_element_wait_state_change (pipeline);
136   }
137
138   gst_element_set_state (pipeline, GST_STATE_NULL);
139
140   /* print out md5sink here */
141   md5sink = gst_bin_get_by_name (GST_BIN (pipeline), "md5sink0");
142   g_assert (md5sink);
143   g_object_get (G_OBJECT (md5sink), "md5", &md5string, NULL);
144   printf ("%s\n", md5string);
145
146   gst_object_unref (GST_OBJECT (pipeline));
147
148   return 0;
149 }