summaryrefslogtreecommitdiffstats
path: root/examples/seeking/vorbisfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/seeking/vorbisfile.c')
-rw-r--r--examples/seeking/vorbisfile.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/examples/seeking/vorbisfile.c b/examples/seeking/vorbisfile.c
new file mode 100644
index 00000000..c94199fe
--- /dev/null
+++ b/examples/seeking/vorbisfile.c
@@ -0,0 +1,312 @@
+#include <stdlib.h>
+#include <gst/gst.h>
+#include <string.h>
+
+static gboolean ready = FALSE;
+
+struct probe_context {
+ GstElement *pipeline;
+ GstElement *element;
+ GstPad *pad;
+ GstFormat ls_format;
+
+ gint total_ls;
+
+ GstCaps *metadata;
+ GstCaps *caps;
+};
+
+static void
+print_metadata (GstCaps *caps)
+{
+ g_print (" metadata:\n");
+ if (!caps || caps->properties == NULL) {
+ g_print (" none\n");
+ return;
+ }
+
+ if (!strcmp (gst_caps_get_mime (caps), "application/x-gst-metadata")) {
+ GstProps *props = caps->properties;
+ GList *walk = props->properties;
+
+ while (walk) {
+ GstPropsEntry *entry = (GstPropsEntry *) walk->data;
+ const gchar *name;
+ const gchar *str_val;
+ gint int_val;
+ GstPropsType type;
+
+ name = gst_props_entry_get_name (entry);
+ type = gst_props_entry_get_type (entry);
+ switch (type) {
+ case GST_PROPS_STRING_TYPE:
+ gst_props_entry_get_string (entry, &str_val);
+ g_print (" %s='%s'\n", name, str_val);
+ break;
+ case GST_PROPS_INT_TYPE:
+ gst_props_entry_get_int (entry, &int_val);
+ g_print (" %s=%d\n", name, int_val);
+ break;
+ default:
+ break;
+ }
+
+ walk = g_list_next (walk);
+ }
+ }
+ else {
+ g_print (" unkown metadata type\n");
+ }
+
+}
+
+static void
+print_format (GstCaps *caps)
+{
+ g_print (" format:\n");
+ if (!caps || caps->properties == NULL) {
+ g_print (" unkown\n");
+ return;
+ }
+ if (!strcmp (gst_caps_get_mime (caps), "audio/raw")) {
+ gint channels;
+ gint rate;
+
+ gst_caps_get_int (caps, "channels", &channels);
+ gst_caps_get_int (caps, "rate", &rate);
+
+ g_print (" channels: %d\n", channels);
+ g_print (" rate: %d\n", rate);
+ }
+ else {
+ g_print (" unkown format\n");
+ }
+}
+
+static void
+print_lbs_info (struct probe_context *context, gint stream)
+{
+ const GstFormat *formats;
+
+ g_print (" stream info:\n");
+
+ /* report info in all supported formats */
+ formats = gst_pad_get_formats (context->pad);
+ while (*formats) {
+ const GstFormatDefinition *definition;
+ gint64 value_start, value_end;
+ gboolean res;
+ GstFormat format;
+
+ if (*formats == context->ls_format) {
+ formats++;
+ continue;
+ }
+
+ definition = gst_format_get_details (*formats);
+
+ /* get start and end position of this stream */
+ format = *formats;
+ res = gst_pad_convert (context->pad,
+ context->ls_format, stream,
+ &format, &value_start);
+ res &= gst_pad_convert (context->pad,
+ context->ls_format, stream + 1,
+ &format, &value_end);
+
+ if (res) {
+ /* substract to get the length */
+ value_end -= value_start;
+
+ if (*formats == GST_FORMAT_TIME) {
+ value_end /= (GST_SECOND/100);
+ g_print (" %s: %lld:%02lld.%02lld\n", definition->nick,
+ value_end/6000, (value_end/100)%60, (value_end%100));
+ }
+ else {
+ g_print (" %s: %lld\n", definition->nick, value_end);
+ }
+ }
+ else
+ g_print (" could not get logical stream %s\n", definition->nick);
+
+ formats++;
+ }
+}
+
+static void
+deep_notify (GObject *object, GstObject *origin,
+ GParamSpec *pspec, gpointer data)
+{
+ struct probe_context *context = (struct probe_context *) data;
+ GValue value = { 0, };
+
+ if (!strcmp (pspec->name, "metadata")) {
+
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (origin), pspec->name, &value);
+ context->metadata = g_value_peek_pointer (&value);
+ }
+ else if (!strcmp (pspec->name, "caps")) {
+ if (GST_IS_PAD (origin) && GST_PAD (origin) == context->pad) {
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (origin), pspec->name, &value);
+ context->caps = g_value_peek_pointer (&value);
+
+ ready = TRUE;
+ }
+ }
+}
+
+static gboolean
+collect_logical_stream_properties (struct probe_context *context, gint stream)
+{
+ GstEvent *event;
+ gboolean res;
+ gint count;
+
+ g_print ("info for logical stream %d:\n", stream);
+
+ /* seek to stream */
+ event = gst_event_new_seek (context->ls_format |
+ GST_SEEK_METHOD_SET |
+ GST_SEEK_FLAG_FLUSH,
+ stream);
+ res = gst_pad_send_event (context->pad, event);
+ if (!res) {
+ g_warning ("seek to logical track failed");
+ return FALSE;
+ }
+
+ /* run the pipeline to get the info */
+ count = 0;
+ ready = FALSE;
+ while (gst_bin_iterate (GST_BIN (context->pipeline)) && !ready) {
+ count++;
+ if (count > 10) break;
+ }
+
+ print_metadata (context->metadata);
+ print_format (context->caps);
+ print_lbs_info (context, stream);
+
+ g_print ("\n");
+
+ return TRUE;
+}
+
+static void
+collect_stream_properties (struct probe_context *context)
+{
+ const GstFormat *formats;
+
+ ready = FALSE;
+ while (gst_bin_iterate (GST_BIN (context->pipeline)) && !ready);
+
+ g_print ("stream info:\n");
+
+ context->total_ls = -1;
+
+ /* report info in all supported formats */
+ formats = gst_pad_get_formats (context->pad);
+ while (*formats) {
+ const GstFormatDefinition *definition;
+ gint64 value;
+ gboolean res;
+ GstFormat format;
+
+ format = *formats;
+
+ res = gst_pad_query (context->pad, GST_PAD_QUERY_TOTAL,
+ &format, &value);
+
+ definition = gst_format_get_details (*formats);
+
+ if (res) {
+ if (format == GST_FORMAT_TIME) {
+ value /= (GST_SECOND/100);
+ g_print (" total %s: %lld:%02lld.%02lld\n", definition->nick,
+ value/6000, (value/100)%60, (value%100));
+ }
+ else {
+ if (format == context->ls_format)
+ context->total_ls = value;
+ g_print (" total %s: %lld\n", definition->nick, value);
+ }
+ }
+ formats++;
+ }
+
+ if (context->total_ls == -1) {
+ g_warning (" could not get number of logical streams");
+ }
+ g_print ("\n");
+}
+
+int
+main (int argc, char **argv)
+{
+ GstElement *pipeline;
+ GstElement *filesrc;
+ GstElement *vorbisfile;
+ GstPad *pad;
+ GstFormat logical_stream_format;
+ struct probe_context *context;
+ gint stream;
+
+ gst_init (&argc, &argv);
+
+ if (argc < 2) {
+ g_print ("usage: %s <oggfile>\n", argv[0]);
+ return (-1);
+ }
+
+ pipeline = gst_pipeline_new ("pipeline");
+
+ filesrc = gst_element_factory_make ("filesrc", "filesrc");
+ g_assert (filesrc);
+ g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
+
+ vorbisfile = gst_element_factory_make ("vorbisfile", "vorbisfile");
+ g_assert (vorbisfile);
+
+ gst_bin_add (GST_BIN (pipeline), filesrc);
+ gst_bin_add (GST_BIN (pipeline), vorbisfile);
+
+ gst_element_connect_pads (filesrc, "src", vorbisfile, "sink");
+
+ pad = gst_element_get_pad (vorbisfile, "src");
+ g_assert (pad);
+
+ logical_stream_format = gst_format_get_by_nick ("logical_stream");
+ g_assert (logical_stream_format != 0);
+
+ context = g_new0 (struct probe_context, 1);
+ context->pipeline = pipeline;
+ context->element = vorbisfile;
+ context->pad = pad;
+ context->ls_format = logical_stream_format;
+
+ g_signal_connect (G_OBJECT (pipeline), "deep_notify",
+ G_CALLBACK (deep_notify), context);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ /* at this point we can inspect the stream */
+ collect_stream_properties (context);
+
+ /* loop over all logical streams to get info */
+ stream = 0;
+ while (stream < context->total_ls) {
+ collect_logical_stream_properties (context, stream);
+ stream++;
+ }
+
+ /* stop probe */
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ gst_buffer_print_stats();
+ gst_event_print_stats();
+
+ return 0;
+}