source: trunk/third/gst-plugins/examples/indexing/indexmpeg.c @ 21443

Revision 21443, 8.6 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21442, which included commits to RCS files with non-trunk default branches.
Line 
1/* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
19
20#include <string.h>
21#include <gst/gst.h>
22
23static gboolean verbose = FALSE;
24static gboolean quiet = FALSE;
25
26static void
27entry_added (GstIndex * index, GstIndexEntry * entry)
28{
29  switch (entry->type) {
30    case GST_INDEX_ENTRY_ID:
31      g_print ("id %d describes writer %s\n", entry->id,
32          GST_INDEX_ID_DESCRIPTION (entry));
33      break;
34    case GST_INDEX_ENTRY_FORMAT:
35      g_print ("%d: registered format %d for %s\n", entry->id,
36          GST_INDEX_FORMAT_FORMAT (entry), GST_INDEX_FORMAT_KEY (entry));
37      break;
38    case GST_INDEX_ENTRY_ASSOCIATION:
39    {
40      gint i;
41
42      g_print ("%p, %d: %08x ", entry, entry->id,
43          GST_INDEX_ASSOC_FLAGS (entry));
44      for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) {
45        g_print ("%d %" G_GINT64_FORMAT " ", GST_INDEX_ASSOC_FORMAT (entry, i),
46            GST_INDEX_ASSOC_VALUE (entry, i));
47      }
48      g_print ("\n");
49      break;
50    }
51    default:
52      break;
53  }
54}
55
56typedef struct
57{
58  const gchar *padname;
59  GstPad *target;
60  GstElement *bin;
61  GstElement *pipeline;
62  GstIndex *index;
63}
64dyn_link;
65
66static void
67dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
68{
69  dyn_link *link = (dyn_link *) data;
70
71  if (!strcmp (gst_pad_get_name (newpad), link->padname)) {
72    gst_element_set_state (link->pipeline, GST_STATE_PAUSED);
73    gst_bin_add (GST_BIN (link->pipeline), link->bin);
74    gst_pad_link (newpad, link->target);
75    gst_element_set_index (link->bin, link->index);
76    gst_element_set_state (link->pipeline, GST_STATE_PLAYING);
77  }
78}
79
80static void
81setup_dynamic_linking (GstElement * pipeline,
82    GstElement * element,
83    const gchar * padname, GstPad * target, GstElement * bin, GstIndex * index)
84{
85  dyn_link *link;
86
87  link = g_new0 (dyn_link, 1);
88  link->padname = g_strdup (padname);
89  link->target = target;
90  link->bin = bin;
91  link->pipeline = pipeline;
92  link->index = index;
93
94  g_signal_connect (G_OBJECT (element), "new_pad", G_CALLBACK (dynamic_link),
95      link);
96}
97
98static GstElement *
99make_mpeg_systems_pipeline (const gchar * path, GstIndex * index)
100{
101  GstElement *pipeline;
102  GstElement *src, *demux;
103
104  pipeline = gst_pipeline_new ("pipeline");
105
106  src = gst_element_factory_make ("filesrc", "src");
107  g_object_set (G_OBJECT (src), "location", path, NULL);
108
109  demux = gst_element_factory_make ("mpegdemux", "demux");
110
111  gst_bin_add (GST_BIN (pipeline), src);
112  gst_bin_add (GST_BIN (pipeline), demux);
113
114  if (index) {
115    gst_element_set_index (pipeline, index);
116  }
117
118  gst_element_link_pads (src, "src", demux, "sink");
119
120  return pipeline;
121}
122
123static GstElement *
124make_mpeg_decoder_pipeline (const gchar * path, GstIndex * index)
125{
126  GstElement *pipeline;
127  GstElement *src, *demux;
128  GstElement *video_bin, *audio_bin;
129  GstElement *video_decoder, *audio_decoder;
130
131  pipeline = gst_pipeline_new ("pipeline");
132
133  src = gst_element_factory_make ("filesrc", "src");
134  g_object_set (G_OBJECT (src), "location", path, NULL);
135
136  demux = gst_element_factory_make ("mpegdemux", "demux");
137
138  gst_bin_add (GST_BIN (pipeline), src);
139  gst_bin_add (GST_BIN (pipeline), demux);
140
141  gst_element_link_pads (src, "src", demux, "sink");
142
143  video_bin = gst_bin_new ("video_bin");
144  video_decoder = gst_element_factory_make ("mpeg2dec", "video_decoder");
145
146  gst_bin_add (GST_BIN (video_bin), video_decoder);
147
148  setup_dynamic_linking (pipeline, demux, "video_00",
149      gst_element_get_pad (video_decoder, "sink"), video_bin, index);
150
151  audio_bin = gst_bin_new ("audio_bin");
152  audio_decoder = gst_element_factory_make ("mad", "audio_decoder");
153
154  setup_dynamic_linking (pipeline, demux, "audio_00",
155      gst_element_get_pad (audio_decoder, "sink"), audio_bin, index);
156
157  gst_bin_add (GST_BIN (audio_bin), audio_decoder);
158
159  if (index) {
160    gst_element_set_index (pipeline, index);
161  }
162
163  return pipeline;
164}
165
166static void
167print_progress (GstPad * pad)
168{
169  gint i = 0;
170  gchar status[53];
171  GstFormat format;
172  gboolean res;
173  gint64 value;
174  gint percent = 0;
175
176  status[0] = '|';
177
178  format = GST_FORMAT_PERCENT;
179  res = gst_pad_query (pad, GST_QUERY_POSITION, &format, &value);
180  if (res) {
181    percent = value / (2 * GST_FORMAT_PERCENT_SCALE);
182  }
183
184  for (i = 0; i < percent; i++) {
185    status[i + 1] = '=';
186  }
187  for (i = percent; i < 50; i++) {
188    status[i + 1] = ' ';
189  }
190  status[51] = '|';
191  status[52] = 0;
192
193  g_print ("%s\r", status);
194}
195
196gint
197main (gint argc, gchar * argv[])
198{
199  GstElement *pipeline;
200  GstElement *src;
201  GstPad *pad;
202  GstIndex *index;
203  gint count = 0;
204  GstEvent *event;
205  gboolean res;
206  GstElement *sink;
207  struct poptOption options[] = {
208    {"verbose", 'v', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &verbose, 0,
209        "Print index entries", NULL},
210    {"quiet", 'q', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &quiet, 0,
211        "don't print progress bar", NULL},
212    POPT_TABLEEND
213  };
214
215  if (!gst_init_check_with_popt_table (&argc, &argv, options) || argc < 3) {
216    g_print ("usage: %s [-v] <type> <filename>  \n"
217        "  type can be: 0 mpeg_systems\n"
218        "               1 mpeg_decoder\n"
219        "  -v : report added index entries\n"
220        "  -q : don't print progress\n", argv[0]);
221    return -1;
222  }
223
224  /* create index that elements can fill */
225  index = gst_index_factory_make ("memindex");
226  if (index) {
227    if (verbose)
228      g_signal_connect (G_OBJECT (index), "entry_added",
229          G_CALLBACK (entry_added), NULL);
230
231    g_object_set (G_OBJECT (index), "resolver", 1, NULL);
232  }
233
234  /* construct pipeline */
235  switch (atoi (argv[1])) {
236    case 0:
237      pipeline = make_mpeg_systems_pipeline (argv[2], index);
238      break;
239    case 1:
240      pipeline = make_mpeg_decoder_pipeline (argv[2], index);
241      break;
242    default:
243      g_print ("unknown type %d\n", atoi (argv[1]));
244      return -1;
245  }
246
247  /* setup some default info/error handlers */
248  g_signal_connect (G_OBJECT (pipeline), "deep_notify",
249      G_CALLBACK (gst_element_default_deep_notify), NULL);
250  g_signal_connect (G_OBJECT (pipeline), "error",
251      G_CALLBACK (gst_element_default_error), NULL);
252
253  /* get a pad to perform progress reporting on */
254  src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
255  pad = gst_element_get_pad (src, "src");
256
257  /* prepare for iteration */
258  gst_element_set_state (pipeline, GST_STATE_PLAYING);
259
260  g_print ("indexing %s...\n", argv[2]);
261  /* run through the complete stream to let it generate an index */
262  while (gst_bin_iterate (GST_BIN (pipeline))) {
263    if (!quiet && (count % 1000 == 0)) {
264      print_progress (pad);
265    }
266    count++;
267  }
268  g_print ("\n");
269
270  /* bring to ready to restart the pipeline */
271  gst_element_set_state (pipeline, GST_STATE_READY);
272  gst_element_set_state (pipeline, GST_STATE_PAUSED);
273
274  if (index)
275    GST_FLAG_UNSET (index, GST_INDEX_WRITABLE);
276
277  src = gst_bin_get_by_name (GST_BIN (pipeline), "video_decoder");
278
279  {
280    gint id;
281    GstIndexEntry *entry;
282    gint64 result;
283    gint total_tm;
284
285    gst_index_get_writer_id (index, GST_OBJECT (src), &id);
286
287    entry = gst_index_get_assoc_entry (index, id, GST_INDEX_LOOKUP_BEFORE, 0,
288        GST_FORMAT_TIME, G_MAXINT64);
289    g_assert (entry);
290    gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &result);
291    total_tm = result * 60 / GST_SECOND;
292    g_print ("total time = %.2fs\n", total_tm / 60.0);
293  }
294
295  pad = gst_element_get_pad (src, "src");
296  sink = gst_element_factory_make ("fakesink", "sink");
297  gst_element_link_pads (src, "src", sink, "sink");
298  gst_bin_add (GST_BIN (pipeline), sink);
299
300  g_print ("seeking %s...\n", argv[2]);
301  event = gst_event_new_seek (GST_FORMAT_TIME |
302      GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, 5 * GST_SECOND);
303
304  res = gst_pad_send_event (pad, event);
305  if (!res) {
306    g_warning ("seek failed");
307  }
308
309  gst_element_set_state (pipeline, GST_STATE_PLAYING);
310  count = 0;
311  while (gst_bin_iterate (GST_BIN (pipeline))) {
312    if (!quiet && (count % 1000 == 0)) {
313      print_progress (pad);
314    }
315    count++;
316  }
317
318  gst_element_set_state (pipeline, GST_STATE_NULL);
319
320  return 1;
321}
Note: See TracBrowser for help on using the repository browser.