vorbisfile.c 6.49 KB
Newer Older
1
2
3
4
5
6
#include <stdlib.h>
#include <gst/gst.h>
#include <string.h>

static gboolean ready = FALSE;

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
7
8
struct probe_context
{
9
10
  GstElement *pipeline;
  GstElement *element;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
11
12
  GstPad *pad;
  GstFormat ls_format;
13

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
14
  gint total_ls;
15

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
16
17
18
  GstCaps *metadata;
  GstCaps *streaminfo;
  GstCaps *caps;
19
20
21
};

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
22
print_caps (GstCaps * caps)
23
{
David Schleef's avatar
David Schleef committed
24
  char *s;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
25

David Schleef's avatar
David Schleef committed
26
  s = gst_caps_to_string (caps);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
27
  g_print ("  %s\n", s);
David Schleef's avatar
David Schleef committed
28
  g_free (s);
29
30
31
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
32
print_format (GstCaps * caps)
33
{
David Schleef's avatar
David Schleef committed
34
  char *s;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
35

David Schleef's avatar
David Schleef committed
36
  s = gst_caps_to_string (caps);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
37
  g_print ("  format: %s\n", s);
David Schleef's avatar
David Schleef committed
38
  g_free (s);
39
40
41
42
43
44
}

static void
print_lbs_info (struct probe_context *context, gint stream)
{
  const GstFormat *formats;
45

46
  /* FIXME: need a better name here */
47
48
49
50
51
52
53
54
55
56
  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;

Wim Taymans's avatar
Wim Taymans committed
57
58
59
60
    format = *formats;
    formats++;

    if (format == context->ls_format) {
61
62
63
      continue;
    }

Wim Taymans's avatar
Wim Taymans committed
64
    definition = gst_format_get_details (format);
65
66

    /* get start and end position of this stream */
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
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
73
74
75

    if (res) {
      /* substract to get the length */
      value_end -= value_start;

Wim Taymans's avatar
Wim Taymans committed
76
      if (format == GST_FORMAT_TIME) {
77
        value_end /= (GST_SECOND / 100);
78
79
80
        g_print ("    %s: %" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ".%02"
            G_GINT64_FORMAT "\n", definition->nick, value_end / 6000,
            (value_end / 100) % 60, (value_end % 100));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
81
      } else {
82
        g_print ("    %s: %" G_GINT64_FORMAT "\n", definition->nick, value_end);
83
      }
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
84
    } else
85
86
87
88
89
90
      g_print ("    could not get logical stream %s\n", definition->nick);

  }
}

static void
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
91
92
deep_notify (GObject * object, GstObject * origin,
    GParamSpec * pspec, gpointer data)
93
94
95
96
97
{
  struct probe_context *context = (struct probe_context *) data;
  GValue value = { 0, };

  if (!strcmp (pspec->name, "metadata")) {
98

99
100
101
    g_value_init (&value, pspec->value_type);
    g_object_get_property (G_OBJECT (origin), pspec->name, &value);
    context->metadata = g_value_peek_pointer (&value);
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
102
  } else if (!strcmp (pspec->name, "streaminfo")) {
103

104
105
    g_value_init (&value, pspec->value_type);
    g_object_get_property (G_OBJECT (origin), pspec->name, &value);
106
    context->streaminfo = g_value_peek_pointer (&value);
107
  } else if (!strcmp (pspec->name, "caps")) {
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    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;
124

125
126
127
128
  g_print ("info for logical stream %d:\n", stream);

  /* seek to stream */
  event = gst_event_new_seek (context->ls_format |
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
129
      GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, stream);
130
131
132
133
134
135
136
137
138
139
140
  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++;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
141
142
    if (count > 10)
      break;
143
  }
144

145
146
  print_caps (context->metadata);
  print_caps (context->streaminfo);
147
148
149
150
  print_format (context->caps);
  print_lbs_info (context, stream);

  g_print ("\n");
151

152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  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;
174

175
    format = *formats;
Wim Taymans's avatar
Wim Taymans committed
176
    formats++;
177

Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
178
    res = gst_pad_query (context->pad, GST_QUERY_TOTAL, &format, &value);
179

Wim Taymans's avatar
Wim Taymans committed
180
    definition = gst_format_get_details (format);
181
182
183

    if (res) {
      if (format == GST_FORMAT_TIME) {
184
        value /= (GST_SECOND / 100);
185
186
187
        g_print ("  total %s: %" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ".%02"
            G_GINT64_FORMAT "\n", definition->nick, value / 6000,
            (value / 100) % 60, (value % 100));
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
188
      } else {
189
190
        if (format == context->ls_format)
          context->total_ls = value;
191
        g_print ("  total %s: %" G_GINT64_FORMAT "\n", definition->nick, value);
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
      }
    }
  }

  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;
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
  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");
Wim Taymans's avatar
Wim Taymans committed
227
  //vorbisfile = gst_element_factory_make ("mad", "vorbisfile");
228
229
230
231
232
  g_assert (vorbisfile);

  gst_bin_add (GST_BIN (pipeline), filesrc);
  gst_bin_add (GST_BIN (pipeline), vorbisfile);

233
  gst_element_link_pads (filesrc, "src", vorbisfile, "sink");
234
235
236
237
238
239
240
241
242
243
244
245
246

  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;

247
  g_signal_connect (G_OBJECT (pipeline), "deep_notify",
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
248
      G_CALLBACK (deep_notify), context);
249

250
251
252
253
254
255
256
257
258
259
260
  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++;
  }
261

262
263
264
265
266
  /* stop probe */
  gst_element_set_state (pipeline, GST_STATE_NULL);

  return 0;
}