gst-indent
[platform/upstream/gst-plugins-good.git] / examples / seeking / vorbisfile.c
1 #include <stdlib.h>
2 #include <gst/gst.h>
3 #include <string.h>
4
5 static gboolean ready = FALSE;
6
7 struct probe_context
8 {
9   GstElement *pipeline;
10   GstElement *element;
11   GstPad *pad;
12   GstFormat ls_format;
13
14   gint total_ls;
15
16   GstCaps *metadata;
17   GstCaps *streaminfo;
18   GstCaps *caps;
19 };
20
21 static void
22 print_caps (GstCaps * caps)
23 {
24   char *s;
25
26   s = gst_caps_to_string (caps);
27   g_print ("  %s\n", s);
28   g_free (s);
29 }
30
31 static void
32 print_format (GstCaps * caps)
33 {
34   char *s;
35
36   s = gst_caps_to_string (caps);
37   g_print ("  format: %s\n", s);
38   g_free (s);
39 }
40
41 static void
42 print_lbs_info (struct probe_context *context, gint stream)
43 {
44   const GstFormat *formats;
45
46   /* FIXME: need a better name here */
47   g_print ("  stream info:\n");
48
49   /* report info in all supported formats */
50   formats = gst_pad_get_formats (context->pad);
51   while (*formats) {
52     const GstFormatDefinition *definition;
53     gint64 value_start, value_end;
54     gboolean res;
55     GstFormat format;
56
57     format = *formats;
58     formats++;
59
60     if (format == context->ls_format) {
61       continue;
62     }
63
64     definition = gst_format_get_details (format);
65
66     /* get start and end position of this stream */
67     res = gst_pad_convert (context->pad,
68         context->ls_format, stream, &format, &value_start);
69     res &= gst_pad_convert (context->pad,
70         context->ls_format, stream + 1, &format, &value_end);
71
72     if (res) {
73       /* substract to get the length */
74       value_end -= value_start;
75
76       if (format == GST_FORMAT_TIME) {
77         value_end /= (GST_SECOND / 100);
78         g_print ("    %s: %lld:%02lld.%02lld\n", definition->nick,
79             value_end / 6000, (value_end / 100) % 60, (value_end % 100));
80       } else {
81         g_print ("    %s: %lld\n", definition->nick, value_end);
82       }
83     } else
84       g_print ("    could not get logical stream %s\n", definition->nick);
85
86   }
87 }
88
89 static void
90 deep_notify (GObject * object, GstObject * origin,
91     GParamSpec * pspec, gpointer data)
92 {
93   struct probe_context *context = (struct probe_context *) data;
94   GValue value = { 0, };
95
96   if (!strcmp (pspec->name, "metadata")) {
97
98     g_value_init (&value, pspec->value_type);
99     g_object_get_property (G_OBJECT (origin), pspec->name, &value);
100     context->metadata = g_value_peek_pointer (&value);
101   } else if (!strcmp (pspec->name, "streaminfo")) {
102
103     g_value_init (&value, pspec->value_type);
104     g_object_get_property (G_OBJECT (origin), pspec->name, &value);
105     context->streaminfo = g_value_peek_pointer (&value);
106   } else if (!strcmp (pspec->name, "caps")) {
107     if (GST_IS_PAD (origin) && GST_PAD (origin) == context->pad) {
108       g_value_init (&value, pspec->value_type);
109       g_object_get_property (G_OBJECT (origin), pspec->name, &value);
110       context->caps = g_value_peek_pointer (&value);
111
112       ready = TRUE;
113     }
114   }
115 }
116
117 static gboolean
118 collect_logical_stream_properties (struct probe_context *context, gint stream)
119 {
120   GstEvent *event;
121   gboolean res;
122   gint count;
123
124   g_print ("info for logical stream %d:\n", stream);
125
126   /* seek to stream */
127   event = gst_event_new_seek (context->ls_format |
128       GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, stream);
129   res = gst_pad_send_event (context->pad, event);
130   if (!res) {
131     g_warning ("seek to logical track failed");
132     return FALSE;
133   }
134
135   /* run the pipeline to get the info */
136   count = 0;
137   ready = FALSE;
138   while (gst_bin_iterate (GST_BIN (context->pipeline)) && !ready) {
139     count++;
140     if (count > 10)
141       break;
142   }
143
144   print_caps (context->metadata);
145   print_caps (context->streaminfo);
146   print_format (context->caps);
147   print_lbs_info (context, stream);
148
149   g_print ("\n");
150
151   return TRUE;
152 }
153
154 static void
155 collect_stream_properties (struct probe_context *context)
156 {
157   const GstFormat *formats;
158
159   ready = FALSE;
160   while (gst_bin_iterate (GST_BIN (context->pipeline)) && !ready);
161
162   g_print ("stream info:\n");
163
164   context->total_ls = -1;
165
166   /* report info in all supported formats */
167   formats = gst_pad_get_formats (context->pad);
168   while (*formats) {
169     const GstFormatDefinition *definition;
170     gint64 value;
171     gboolean res;
172     GstFormat format;
173
174     format = *formats;
175     formats++;
176
177     res = gst_pad_query (context->pad, GST_QUERY_TOTAL, &format, &value);
178
179     definition = gst_format_get_details (format);
180
181     if (res) {
182       if (format == GST_FORMAT_TIME) {
183         value /= (GST_SECOND / 100);
184         g_print ("  total %s: %lld:%02lld.%02lld\n", definition->nick,
185             value / 6000, (value / 100) % 60, (value % 100));
186       } else {
187         if (format == context->ls_format)
188           context->total_ls = value;
189         g_print ("  total %s: %lld\n", definition->nick, value);
190       }
191     }
192   }
193
194   if (context->total_ls == -1) {
195     g_warning ("  could not get number of logical streams");
196   }
197   g_print ("\n");
198 }
199
200 int
201 main (int argc, char **argv)
202 {
203   GstElement *pipeline;
204   GstElement *filesrc;
205   GstElement *vorbisfile;
206   GstPad *pad;
207   GstFormat logical_stream_format;
208   struct probe_context *context;
209   gint stream;
210
211   gst_init (&argc, &argv);
212
213   if (argc < 2) {
214     g_print ("usage: %s <oggfile>\n", argv[0]);
215     return (-1);
216   }
217
218   pipeline = gst_pipeline_new ("pipeline");
219
220   filesrc = gst_element_factory_make ("filesrc", "filesrc");
221   g_assert (filesrc);
222   g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
223
224   vorbisfile = gst_element_factory_make ("vorbisfile", "vorbisfile");
225   //vorbisfile = gst_element_factory_make ("mad", "vorbisfile");
226   g_assert (vorbisfile);
227
228   gst_bin_add (GST_BIN (pipeline), filesrc);
229   gst_bin_add (GST_BIN (pipeline), vorbisfile);
230
231   gst_element_link_pads (filesrc, "src", vorbisfile, "sink");
232
233   pad = gst_element_get_pad (vorbisfile, "src");
234   g_assert (pad);
235
236   logical_stream_format = gst_format_get_by_nick ("logical_stream");
237   g_assert (logical_stream_format != 0);
238
239   context = g_new0 (struct probe_context, 1);
240   context->pipeline = pipeline;
241   context->element = vorbisfile;
242   context->pad = pad;
243   context->ls_format = logical_stream_format;
244
245   g_signal_connect (G_OBJECT (pipeline), "deep_notify",
246       G_CALLBACK (deep_notify), context);
247
248   gst_element_set_state (pipeline, GST_STATE_PLAYING);
249
250   /* at this point we can inspect the stream */
251   collect_stream_properties (context);
252
253   /* loop over all logical streams to get info */
254   stream = 0;
255   while (stream < context->total_ls) {
256     collect_logical_stream_properties (context, stream);
257     stream++;
258   }
259
260   /* stop probe */
261   gst_element_set_state (pipeline, GST_STATE_NULL);
262
263   return 0;
264 }