2 * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
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.
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.
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.
21 /* #define GST_DEBUG_ENABLED */
24 #include "gstavidemux.h"
27 /* elementfactory information */
28 static GstElementDetails gst_avi_demux_details = {
32 "Demultiplex an avi file into audio and video",
34 "Erik Walthinsen <omega@cse.ogi.edu>\n"
35 "Wim Taymans <wim.taymans@tvd.be>",
39 static GstCaps* avi_type_find (GstBuffer *buf, gpointer private);
41 /* typefactory for 'avi' */
42 static GstTypeDefinition avidefinition = {
49 /* AviDemux signals and args */
61 GST_PAD_TEMPLATE_FACTORY (sink_templ,
68 "format", GST_PROPS_STRING ("AVI")
72 GST_PAD_TEMPLATE_FACTORY (src_video_templ,
79 "format", GST_PROPS_LIST (
80 GST_PROPS_STRING ("strf_vids"),
81 GST_PROPS_STRING ("strf_iavs")
83 "width", GST_PROPS_INT_RANGE (16, 4096),
84 "height", GST_PROPS_INT_RANGE (16, 4096)
90 "format", GST_PROPS_LIST (
91 GST_PROPS_FOURCC (GST_MAKE_FOURCC('Y','U','Y','2')),
92 GST_PROPS_FOURCC (GST_MAKE_FOURCC('I','4','2','0'))
94 "width", GST_PROPS_INT_RANGE (16, 4096),
95 "height", GST_PROPS_INT_RANGE (16, 4096)
100 "width", GST_PROPS_INT_RANGE (16, 4096),
101 "height", GST_PROPS_INT_RANGE (16, 4096)
104 "avidemux_src_video",
106 "format", GST_PROPS_LIST (
107 GST_PROPS_STRING ("NTSC"),
108 GST_PROPS_STRING ("PAL")
110 "width", GST_PROPS_INT_RANGE (16, 4096),
111 "height", GST_PROPS_INT_RANGE (16, 4096)
115 GST_PAD_TEMPLATE_FACTORY (src_audio_templ,
120 "avidemux_src_audio",
122 "format", GST_PROPS_STRING ("strf_auds")
125 "avidemux_src_audio",
127 "format", GST_PROPS_STRING ("int"),
128 "law", GST_PROPS_INT (0),
129 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
130 "signed", GST_PROPS_LIST (
131 GST_PROPS_BOOLEAN (TRUE),
132 GST_PROPS_BOOLEAN (FALSE)
134 "width", GST_PROPS_LIST (
138 "depth", GST_PROPS_LIST (
142 "rate", GST_PROPS_INT_RANGE (11025, 44100),
143 "channels", GST_PROPS_INT_RANGE (1, 2)
146 "avidemux_src_audio",
151 "avidemux_src_audio",
157 static void gst_avi_demux_class_init (GstAviDemuxClass *klass);
158 static void gst_avi_demux_init (GstAviDemux *avi_demux);
160 static void gst_avi_demux_loop (GstElement *element);
162 static gboolean gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
164 gint rec_depth, guint32 *chunksize);
166 static gboolean gst_avi_demux_send_event (GstElement *element, GstEvent *event);
168 static const GstEventMask*
169 gst_avi_demux_get_event_mask (GstPad *pad);
170 static gboolean gst_avi_demux_handle_src_event (GstPad *pad, GstEvent *event);
171 static const GstFormat* gst_avi_demux_get_src_formats (GstPad *pad);
172 static const GstPadQueryType*
173 gst_avi_demux_get_src_query_types (GstPad *pad);
174 static gboolean gst_avi_demux_handle_src_query (GstPad *pad, GstPadQueryType type,
175 GstFormat *format, gint64 *value);
176 static gboolean gst_avi_demux_src_convert (GstPad *pad, GstFormat src_format, gint64 src_value,
177 GstFormat *dest_format, gint64 *dest_value);
179 static GstElementStateReturn
180 gst_avi_demux_change_state (GstElement *element);
182 static void gst_avi_demux_get_property (GObject *object, guint prop_id,
183 GValue *value, GParamSpec *pspec);
186 static GstElementClass *parent_class = NULL;
187 /*static guint gst_avi_demux_signals[LAST_SIGNAL] = { 0 }; */
190 gst_avi_demux_get_type(void)
192 static GType avi_demux_type = 0;
194 if (!avi_demux_type) {
195 static const GTypeInfo avi_demux_info = {
196 sizeof(GstAviDemuxClass),
199 (GClassInitFunc)gst_avi_demux_class_init,
204 (GInstanceInitFunc)gst_avi_demux_init,
206 avi_demux_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviDemux", &avi_demux_info, 0);
208 return avi_demux_type;
212 gst_avi_demux_class_init (GstAviDemuxClass *klass)
214 GObjectClass *gobject_class;
215 GstElementClass *gstelement_class;
217 gobject_class = (GObjectClass*)klass;
218 gstelement_class = (GstElementClass*)klass;
220 g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_BITRATE,
221 g_param_spec_long ("bitrate","bitrate","bitrate",
222 G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */
224 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
226 gobject_class->get_property = gst_avi_demux_get_property;
228 gstelement_class->change_state = gst_avi_demux_change_state;
229 gstelement_class->send_event = gst_avi_demux_send_event;
233 gst_avi_demux_init (GstAviDemux *avi_demux)
235 GST_FLAG_SET (avi_demux, GST_ELEMENT_EVENT_AWARE);
237 avi_demux->sinkpad = gst_pad_new_from_template (
238 GST_PAD_TEMPLATE_GET (sink_templ), "sink");
239 gst_element_add_pad (GST_ELEMENT (avi_demux), avi_demux->sinkpad);
241 gst_element_set_loop_function (GST_ELEMENT (avi_demux), gst_avi_demux_loop);
243 avi_demux->num_streams = 0;
244 avi_demux->num_v_streams = 0;
245 avi_demux->num_a_streams = 0;
246 avi_demux->index_entries = NULL;
247 avi_demux->index_size = 0;
248 avi_demux->seek_pending = 0;
249 avi_demux->restart = FALSE;
254 avi_type_find (GstBuffer *buf,
257 gchar *data = GST_BUFFER_DATA (buf);
260 GST_DEBUG (0,"avi_demux: typefind");
262 if (GUINT32_FROM_LE (((guint32 *)data)[0]) != GST_RIFF_TAG_RIFF)
264 if (GUINT32_FROM_LE (((guint32 *)data)[2]) != GST_RIFF_RIFF_AVI)
267 new = GST_CAPS_NEW ("avi_type_find",
269 "format", GST_PROPS_STRING ("AVI"));
274 gst_avi_demux_avih (GstAviDemux *avi_demux)
278 GstByteStream *bs = avi_demux->bs;
280 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&avih, sizeof (gst_riff_avih));
281 if (got_bytes == sizeof (gst_riff_avih)) {
282 avi_demux->avih.us_frame = GUINT32_FROM_LE (avih->us_frame);
283 avi_demux->avih.max_bps = GUINT32_FROM_LE (avih->max_bps);
284 avi_demux->avih.pad_gran = GUINT32_FROM_LE (avih->pad_gran);
285 avi_demux->avih.flags = GUINT32_FROM_LE (avih->flags);
286 avi_demux->avih.tot_frames = GUINT32_FROM_LE (avih->tot_frames);
287 avi_demux->avih.init_frames = GUINT32_FROM_LE (avih->init_frames);
288 avi_demux->avih.streams = GUINT32_FROM_LE (avih->streams);
289 avi_demux->avih.bufsize = GUINT32_FROM_LE (avih->bufsize);
290 avi_demux->avih.width = GUINT32_FROM_LE (avih->width);
291 avi_demux->avih.height = GUINT32_FROM_LE (avih->height);
292 avi_demux->avih.scale = GUINT32_FROM_LE (avih->scale);
293 avi_demux->avih.rate = GUINT32_FROM_LE (avih->rate);
294 avi_demux->avih.start = GUINT32_FROM_LE (avih->start);
295 avi_demux->avih.length = GUINT32_FROM_LE (avih->length);
297 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: avih tag found");
298 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: us_frame %d", avi_demux->avih.us_frame);
299 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: max_bps %d", avi_demux->avih.max_bps);
300 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: pad_gran %d", avi_demux->avih.pad_gran);
301 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: flags 0x%08x", avi_demux->avih.flags);
302 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: tot_frames %d", avi_demux->avih.tot_frames);
303 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: init_frames %d", avi_demux->avih.init_frames);
304 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: streams %d", avi_demux->avih.streams);
305 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: bufsize %d", avi_demux->avih.bufsize);
306 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: width %d", avi_demux->avih.width);
307 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: height %d", avi_demux->avih.height);
308 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: scale %d", avi_demux->avih.scale);
309 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: rate %d", avi_demux->avih.rate);
310 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: start %d", avi_demux->avih.start);
311 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: length %d", avi_demux->avih.length);
319 gst_avi_demux_strh (GstAviDemux *avi_demux)
322 GstByteStream *bs = avi_demux->bs;
325 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&strh, sizeof (gst_riff_strh));
326 if (got_bytes == sizeof (gst_riff_strh)) {
327 avi_stream_context *target;
329 avi_demux->fcc_type = GUINT32_FROM_LE (strh->type);
331 target = &avi_demux->stream[avi_demux->num_streams];
333 target->num = avi_demux->num_streams;
335 target->strh.type = avi_demux->fcc_type;
336 target->strh.fcc_handler = GUINT32_FROM_LE (strh->fcc_handler);
337 target->strh.flags = GUINT32_FROM_LE (strh->flags);
338 target->strh.priority = GUINT32_FROM_LE (strh->priority);
339 target->strh.init_frames = GUINT32_FROM_LE (strh->init_frames);
340 target->strh.scale = GUINT32_FROM_LE (strh->scale);
341 target->strh.rate = GUINT32_FROM_LE (strh->rate);
342 target->strh.start = GUINT32_FROM_LE (strh->start);
343 target->strh.length = GUINT32_FROM_LE (strh->length);
344 target->strh.bufsize = GUINT32_FROM_LE (strh->bufsize);
345 target->strh.quality = GUINT32_FROM_LE (strh->quality);
346 target->strh.samplesize = GUINT32_FROM_LE (strh->samplesize);
348 if (!target->strh.scale)
349 target->strh.scale = 1; /* avoid division by zero */
350 if (!target->strh.rate)
351 target->strh.rate = 1; /* avoid division by zero */
353 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strh tag found");
354 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: type 0x%08x (%s)",
355 target->strh.type, gst_riff_id_to_fourcc (strh->type));
356 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: fcc_handler 0x%08x (%s)",
357 target->strh.fcc_handler, gst_riff_id_to_fourcc (strh->fcc_handler));
358 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: flags 0x%08x", strh->flags);
359 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: priority %d", target->strh.priority);
360 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: init_frames %d", target->strh.init_frames);
361 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: scale %d", target->strh.scale);
362 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: rate %d", target->strh.rate);
363 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: start %d", target->strh.start);
364 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: length %d", target->strh.length);
365 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: bufsize %d", target->strh.bufsize);
366 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: quality %d", target->strh.quality);
367 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: samplesize %d", target->strh.samplesize);
370 target->total_bytes = 0LL;
371 target->total_frames = 0;
372 target->end_pos = -1;
376 avi_demux->avih.bufsize = MAX (avi_demux->avih.bufsize, target->strh.bufsize);
384 gst_avi_demux_strf_vids (GstAviDemux *avi_demux)
386 gst_riff_strf_vids *strf;
388 GstByteStream *bs = avi_demux->bs;
389 GstCaps *newcaps = NULL, *capslist = NULL;
390 avi_stream_context *stream;
393 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&strf, sizeof (gst_riff_strf_vids));
395 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context vids");
396 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: size %d", GUINT32_FROM_LE (strf->size));
397 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: width %d", GUINT32_FROM_LE (strf->width));
398 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: height %d", GUINT32_FROM_LE (strf->height));
399 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: planes %d", GUINT16_FROM_LE (strf->planes));
400 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: bit_cnt %d", GUINT16_FROM_LE (strf->bit_cnt));
401 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: compression 0x%08x (%s)",
402 GUINT32_FROM_LE (strf->compression), gst_riff_id_to_fourcc (strf->compression));
403 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: image_size %d", GUINT32_FROM_LE (strf->image_size));
404 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: xpels_meter %d", GUINT32_FROM_LE (strf->xpels_meter));
405 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: ypels_meter %d", GUINT32_FROM_LE (strf->ypels_meter));
406 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: num_colors %d", GUINT32_FROM_LE (strf->num_colors));
407 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: imp_colors %d", GUINT32_FROM_LE (strf->imp_colors));
409 srcpad = gst_pad_new_from_template (
410 GST_PAD_TEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d",
411 avi_demux->num_v_streams));
413 capslist = gst_caps_append(NULL, GST_CAPS_NEW (
414 "avidemux_video_src",
416 "format", GST_PROPS_STRING ("strf_vids"),
417 "size", GST_PROPS_INT (GUINT32_FROM_LE (strf->size)),
418 "width", GST_PROPS_INT (GUINT32_FROM_LE (strf->width)),
419 "height", GST_PROPS_INT (GUINT32_FROM_LE (strf->height)),
420 "planes", GST_PROPS_INT (GUINT16_FROM_LE (strf->planes)),
421 "bit_cnt", GST_PROPS_INT (GUINT16_FROM_LE (strf->bit_cnt)),
422 "compression", GST_PROPS_FOURCC (GUINT32_FROM_LE (strf->compression)),
423 "image_size", GST_PROPS_INT (GUINT32_FROM_LE (strf->image_size)),
424 "xpels_meter", GST_PROPS_INT (GUINT32_FROM_LE (strf->xpels_meter)),
425 "ypels_meter", GST_PROPS_INT (GUINT32_FROM_LE (strf->ypels_meter)),
426 "num_colors", GST_PROPS_INT (GUINT32_FROM_LE (strf->num_colors)),
427 "imp_colors", GST_PROPS_INT (GUINT32_FROM_LE (strf->imp_colors))
430 /* let's try some gstreamer-like mime-type caps */
431 switch (GUINT32_FROM_LE(strf->compression))
433 case GST_MAKE_FOURCC('I','4','2','0'):
434 case GST_MAKE_FOURCC('Y','U','Y','2'):
435 newcaps = GST_CAPS_NEW (
436 "avidemux_video_src",
438 "format", GST_PROPS_FOURCC(GUINT32_FROM_LE(strf->compression)),
439 "width", GST_PROPS_INT(strf->width),
440 "height", GST_PROPS_INT(strf->height)
443 case GST_MAKE_FOURCC('M','J','P','G'):
444 newcaps = GST_CAPS_NEW (
445 "avidemux_video_src",
447 "width", GST_PROPS_INT(strf->width),
448 "height", GST_PROPS_INT(strf->height)
451 case GST_MAKE_FOURCC('d','v','s','d'):
452 newcaps = GST_CAPS_NEW (
453 "avidemux_video_src",
455 "format", GST_PROPS_STRING("NTSC"), /* FIXME??? */
456 "width", GST_PROPS_INT(strf->width),
457 "height", GST_PROPS_INT(strf->height)
462 if (newcaps) capslist = gst_caps_append (capslist, newcaps);
464 gst_pad_try_set_caps (srcpad, capslist);
465 gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats);
466 gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask);
467 gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
468 gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
469 gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
470 gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
472 stream = &avi_demux->stream[avi_demux->num_streams];
473 stream->pad = srcpad;
474 gst_pad_set_element_private (srcpad, stream);
475 avi_demux->num_streams++;
476 avi_demux->num_v_streams++;
478 gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
482 gst_avi_demux_strf_auds (GstAviDemux *avi_demux)
484 gst_riff_strf_auds *strf;
486 GstByteStream *bs = avi_demux->bs;
487 GstCaps *newcaps = NULL, *capslist = NULL;
488 avi_stream_context *stream;
491 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&strf, sizeof (gst_riff_strf_auds));
493 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context auds");
494 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: format %d", GUINT16_FROM_LE (strf->format));
495 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: channels %d", GUINT16_FROM_LE (strf->channels));
496 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: rate %d", GUINT32_FROM_LE (strf->rate));
497 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: av_bps %d", GUINT32_FROM_LE (strf->av_bps));
498 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: blockalign %d", GUINT16_FROM_LE (strf->blockalign));
499 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: size %d", GUINT16_FROM_LE (strf->size));
501 srcpad = gst_pad_new_from_template (
502 GST_PAD_TEMPLATE_GET (src_audio_templ), g_strdup_printf ("audio_%02d",
503 avi_demux->num_a_streams));
505 capslist = gst_caps_append(NULL, GST_CAPS_NEW (
506 "avidemux_audio_src",
508 "format", GST_PROPS_STRING ("strf_auds"),
509 "fmt", GST_PROPS_INT (GUINT16_FROM_LE (strf->format)),
510 "channels", GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)),
511 "rate", GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)),
512 "av_bps", GST_PROPS_INT (GUINT32_FROM_LE (strf->av_bps)),
513 "blockalign", GST_PROPS_INT (GUINT16_FROM_LE (strf->blockalign)),
514 "size", GST_PROPS_INT (GUINT16_FROM_LE (strf->size))
517 /* let's try some gstreamer-formatted mime types */
518 switch (GUINT16_FROM_LE(strf->format))
520 case GST_RIFF_WAVE_FORMAT_MPEGL3:
521 case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp3 */
522 newcaps = gst_caps_new ("avidemux_audio_src",
526 case GST_RIFF_WAVE_FORMAT_PCM: /* PCM/wav */
527 newcaps = gst_caps_new ("avidemux_audio_src",
530 "format", GST_PROPS_STRING ("int"),
531 "law", GST_PROPS_INT (0),
532 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
533 "signed", GST_PROPS_BOOLEAN ((GUINT16_FROM_LE (strf->size) != 8)),
534 "width", GST_PROPS_INT ((GUINT16_FROM_LE (strf->blockalign)*8) /
535 GUINT16_FROM_LE (strf->channels)),
536 "depth", GST_PROPS_INT (GUINT16_FROM_LE (strf->size)),
537 "rate", GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)),
538 "channels", GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)),
542 case GST_RIFF_WAVE_FORMAT_VORBIS1: /* ogg/vorbis mode 1 */
543 case GST_RIFF_WAVE_FORMAT_VORBIS2: /* ogg/vorbis mode 2 */
544 case GST_RIFF_WAVE_FORMAT_VORBIS3: /* ogg/vorbis mode 3 */
545 case GST_RIFF_WAVE_FORMAT_VORBIS1PLUS: /* ogg/vorbis mode 1+ */
546 case GST_RIFF_WAVE_FORMAT_VORBIS2PLUS: /* ogg/vorbis mode 2+ */
547 case GST_RIFF_WAVE_FORMAT_VORBIS3PLUS: /* ogg/vorbis mode 3+ */
548 newcaps = gst_caps_new ("avidemux_audio_src",
554 if (newcaps) capslist = gst_caps_append(capslist, newcaps);
557 gst_pad_try_set_caps(srcpad, capslist);
558 gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats);
559 gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask);
560 gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
561 gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
562 gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
563 gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
565 stream = &avi_demux->stream[avi_demux->num_streams];
566 stream->pad = srcpad;
567 gst_pad_set_element_private (srcpad, stream);
568 avi_demux->num_streams++;
569 avi_demux->num_a_streams++;
571 gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
575 gst_avi_demux_strf_iavs (GstAviDemux *avi_demux)
577 gst_riff_strf_iavs *strf;
579 GstByteStream *bs = avi_demux->bs;
580 GstCaps *newcaps = NULL, *capslist = NULL;
581 avi_stream_context *stream;
584 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&strf, sizeof (gst_riff_strf_iavs));
586 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context iavs");
587 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVAAuxSrc %08x", GUINT32_FROM_LE (strf->DVAAuxSrc));
588 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVAAuxCtl %08x", GUINT32_FROM_LE (strf->DVAAuxCtl));
589 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVAAuxSrc1 %08x", GUINT32_FROM_LE (strf->DVAAuxSrc1));
590 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVAAuxCtl1 %08x", GUINT32_FROM_LE (strf->DVAAuxCtl1));
591 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVVAuxSrc %08x", GUINT32_FROM_LE (strf->DVVAuxSrc));
592 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVVAuxCtl %08x", GUINT32_FROM_LE (strf->DVVAuxCtl));
593 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVReserved1 %08x", GUINT32_FROM_LE (strf->DVReserved1));
594 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: DVReserved2 %08x", GUINT32_FROM_LE (strf->DVReserved2));
596 srcpad = gst_pad_new_from_template (
597 GST_PAD_TEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d",
598 avi_demux->num_v_streams));
600 capslist = gst_caps_append(NULL, GST_CAPS_NEW (
601 "avidemux_video_src",
603 "format", GST_PROPS_STRING ("strf_iavs"),
604 "DVAAuxSrc", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc)),
605 "DVAAuxCtl", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl)),
606 "DVAAuxSrc1", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc1)),
607 "DVAAuxCtl1", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl1)),
608 "DVVAuxSrc", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxSrc)),
609 "DVVAuxCtl", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxCtl)),
610 "DVReserved1", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved1)),
611 "DVReserved2", GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved2))
614 newcaps = gst_caps_new ("avi_type_dv",
617 "format", GST_PROPS_STRING ("NTSC"), /* FIXME??? */
620 if (newcaps) capslist = gst_caps_append(capslist, newcaps);
622 gst_pad_try_set_caps(srcpad, capslist);
623 gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats);
624 gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask);
625 gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
626 gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
627 gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
628 gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
630 stream = &avi_demux->stream[avi_demux->num_streams];
631 stream->pad = srcpad;
632 gst_pad_set_element_private (srcpad, stream);
633 avi_demux->num_streams++;
634 avi_demux->num_v_streams++;
636 gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
640 gst_avi_debug_entry (const gchar *prefix, gst_avi_index_entry *entry)
642 GST_DEBUG (0, "%s: %05d %d %08llx %05d %14lld %08x %08x (%d) %08x", prefix, entry->index_nr, entry->stream_nr,
643 entry->bytes_before, entry->frames_before, entry->ts, entry->flags, entry->offset,
644 entry->offset, entry->size);
648 gst_avi_demux_parse_index (GstAviDemux *avi_demux,
649 gulong filepos, gulong offset)
655 gst_riff_index_entry *entry;
657 if (!gst_bytestream_seek (avi_demux->bs, filepos + offset, GST_SEEK_METHOD_SET)) {
658 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek to index");
661 got_bytes = gst_bytestream_read (avi_demux->bs, &buf, 8);
662 while (got_bytes < 8) {
666 gst_bytestream_get_status (avi_demux->bs, &remaining, &event);
667 gst_event_unref (event);
669 got_bytes = gst_bytestream_read (avi_demux->bs, &buf, 8);
672 if (GST_BUFFER_OFFSET (buf) != filepos + offset || GST_BUFFER_SIZE (buf) != 8) {
673 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not get index, got %lld %d, expected %ld",
674 GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf), filepos + offset);
678 if (gst_riff_fourcc_to_id (GST_BUFFER_DATA (buf)) != GST_RIFF_TAG_idx1) {
679 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: no index found");
683 index_size = GUINT32_FROM_LE(*(guint32 *)(GST_BUFFER_DATA (buf) + 4));
684 gst_buffer_unref (buf);
686 gst_bytestream_size_hint (avi_demux->bs, index_size);
688 got_bytes = gst_bytestream_read (avi_demux->bs, &buf, index_size);
689 if (got_bytes < index_size) {
690 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: error reading index");
694 avi_demux->index_size = index_size/sizeof(gst_riff_index_entry);
695 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: index size %lu", avi_demux->index_size);
697 avi_demux->index_entries = g_malloc (avi_demux->index_size * sizeof (gst_avi_index_entry));
699 entry = (gst_riff_index_entry *) GST_BUFFER_DATA (buf);
701 for (i = 0; i < avi_demux->index_size; i++) {
702 avi_stream_context *stream;
704 gst_avi_index_entry *target = &avi_demux->index_entries[i];
707 stream_nr = CHUNKID_TO_STREAMNR (entry[i].id);
708 if (stream_nr > avi_demux->num_streams || stream_nr < 0) {
709 avi_demux->index_entries[i].stream_nr = -1;
713 target->stream_nr = stream_nr;
714 stream = &avi_demux->stream[stream_nr];
716 target->index_nr = i;
717 target->flags = entry[i].flags;
718 target->size = entry[i].size;
719 target->offset = entry[i].offset;
721 /* figure out if the index is 0 based or relative to the MOVI start */
723 if (target->offset < filepos)
724 avi_demux->index_offset = filepos;
726 avi_demux->index_offset = 0;
729 target->bytes_before = stream->total_bytes;
730 target->frames_before = stream->total_frames;
732 format = GST_FORMAT_TIME;
733 if (stream->strh.type == GST_RIFF_FCC_auds) {
734 /* all audio frames are keyframes */
735 target->flags |= GST_RIFF_IF_KEYFRAME;
738 /* constant rate stream */
739 if (stream->strh.samplesize) {
740 gst_pad_convert (stream->pad, GST_FORMAT_BYTES, stream->total_bytes,
741 &format, &target->ts);
745 gst_pad_convert (stream->pad, GST_FORMAT_UNITS, stream->total_frames,
746 &format, &target->ts);
748 gst_avi_debug_entry ("index", target);
750 stream->total_bytes += target->size;
751 stream->total_frames++;
753 for (i = 0; i < avi_demux->num_streams; i++) {
754 avi_stream_context *stream;
756 stream = &avi_demux->stream[i];
757 GST_DEBUG (GST_CAT_PLUGIN_INFO, "stream %i: %d frames, %lld bytes", i, stream->total_frames, stream->total_bytes);
759 gst_buffer_unref (buf);
762 GST_DEBUG (GST_CAT_PLUGIN_INFO, "index offset at %08lx", filepos);
764 if (!gst_bytestream_seek (avi_demux->bs, filepos, GST_SEEK_METHOD_SET)) {
765 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek back to movi");
770 static gst_avi_index_entry*
771 gst_avi_demux_index_next (GstAviDemux *avi_demux, gint stream_nr, gint start, guint32 flags)
774 gst_avi_index_entry *entry = NULL;
776 for (i = start; i < avi_demux->index_size; i++) {
777 entry = &avi_demux->index_entries[i];
779 if (entry->stream_nr == stream_nr && (entry->flags & flags) == flags) {
787 static gst_avi_index_entry*
788 gst_avi_demux_index_entry_for_time (GstAviDemux *avi_demux, gint stream_nr, guint64 time, guint32 flags)
790 gst_avi_index_entry *entry = NULL, *last_entry = NULL;
795 entry = gst_avi_demux_index_next (avi_demux, stream_nr, i + 1, flags);
801 if (entry->ts <= time) {
805 while (entry->ts <= time);
810 static const GstFormat*
811 gst_avi_demux_get_src_formats (GstPad *pad)
813 avi_stream_context *stream = gst_pad_get_element_private (pad);
815 static const GstFormat src_a_formats[] = {
821 static const GstFormat src_v_formats[] = {
827 return (stream->strh.type == GST_RIFF_FCC_auds ? src_a_formats : src_v_formats);
831 gst_avi_demux_src_convert (GstPad *pad, GstFormat src_format, gint64 src_value,
832 GstFormat *dest_format, gint64 *dest_value)
835 avi_stream_context *stream = gst_pad_get_element_private (pad);
837 if (stream->strh.type != GST_RIFF_FCC_auds &&
838 (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
841 switch (src_format) {
842 case GST_FORMAT_TIME:
843 switch (*dest_format) {
844 case GST_FORMAT_BYTES:
845 *dest_value = src_value * stream->strh.rate / (stream->strh.scale * GST_SECOND);
847 case GST_FORMAT_DEFAULT:
848 *dest_format = GST_FORMAT_UNITS;
849 case GST_FORMAT_UNITS:
850 *dest_value = src_value * stream->strh.rate / (stream->strh.scale * GST_SECOND);
857 case GST_FORMAT_BYTES:
858 case GST_FORMAT_UNITS:
859 switch (*dest_format) {
860 case GST_FORMAT_TIME:
861 *dest_value = ((((gfloat)src_value) * stream->strh.scale) / stream->strh.rate) * GST_SECOND;
875 static const GstPadQueryType*
876 gst_avi_demux_get_src_query_types (GstPad *pad)
878 static const GstPadQueryType src_types[] = {
880 GST_PAD_QUERY_POSITION,
888 gst_avi_demux_handle_src_query (GstPad *pad, GstPadQueryType type,
889 GstFormat *format, gint64 *value)
892 //GstAviDemux *avi_demux = GST_AVI_DEMUX (gst_pad_get_parent (pad));
893 avi_stream_context *stream = gst_pad_get_element_private (pad);
896 case GST_PAD_QUERY_TOTAL:
898 case GST_FORMAT_DEFAULT:
899 *format = GST_FORMAT_TIME;
901 case GST_FORMAT_TIME:
902 *value = (((gfloat)stream->strh.scale) * stream->strh.length / stream->strh.rate) * GST_SECOND;
904 case GST_FORMAT_BYTES:
905 if (stream->strh.type == GST_RIFF_FCC_auds) {
906 *value = stream->total_bytes;
911 case GST_FORMAT_UNITS:
912 if (stream->strh.type == GST_RIFF_FCC_auds)
913 *value = stream->strh.length * stream->strh.samplesize;
914 else if (stream->strh.type == GST_RIFF_FCC_vids)
915 *value = stream->strh.length;
924 case GST_PAD_QUERY_POSITION:
926 case GST_FORMAT_DEFAULT:
927 *format = GST_FORMAT_TIME;
929 case GST_FORMAT_TIME:
930 if (stream->strh.samplesize) {
931 *value = (((gfloat)stream->current_byte) * stream->strh.scale / stream->strh.rate) * GST_SECOND;
934 *value = (((gfloat)stream->current_frame) * stream->strh.scale / stream->strh.rate) * GST_SECOND;
937 case GST_FORMAT_BYTES:
938 *value = stream->current_byte;
940 case GST_FORMAT_UNITS:
941 if (stream->strh.samplesize)
942 *value = stream->current_byte * stream->strh.samplesize;
944 *value = stream->current_frame;
960 gst_avi_demux_sync_streams (GstAviDemux *avi_demux, guint64 time)
963 guint32 min_index = G_MAXUINT;
964 avi_stream_context *stream;
965 gst_avi_index_entry *entry;
967 for (i = 0; i < avi_demux->num_streams; i++) {
968 stream = &avi_demux->stream[i];
970 GST_DEBUG (0, "finding %d for time %lld", i, time);
972 entry = gst_avi_demux_index_entry_for_time (avi_demux, stream->num, time, GST_RIFF_IF_KEYFRAME);
974 gst_avi_debug_entry ("sync entry", entry);
976 min_index = MIN (entry->index_nr, min_index);
979 GST_DEBUG (0, "first index at %d", min_index);
981 /* now we know the entry we need to sync on. calculate number of frames to
982 * skip fro there on and the stream stats */
983 for (i = 0; i < avi_demux->num_streams; i++) {
984 gst_avi_index_entry *next_entry;
985 stream = &avi_demux->stream[i];
988 next_entry = gst_avi_demux_index_next (avi_demux, stream->num, min_index, 0);
989 /* next entry with keyframe */
990 entry = gst_avi_demux_index_next (avi_demux, stream->num, min_index, GST_RIFF_IF_KEYFRAME);
991 gst_avi_debug_entry ("final sync", entry);
993 stream->current_byte = next_entry->bytes_before;
994 stream->current_frame = next_entry->frames_before;
995 stream->skip = entry->frames_before - next_entry->frames_before;
997 GST_DEBUG (0, "%d skip %d", stream->num, stream->skip);
999 GST_DEBUG (0, "final index at %d", min_index);
1005 gst_avi_demux_send_event (GstElement *element, GstEvent *event)
1009 pads = gst_element_get_pad_list (element);
1012 GstPad *pad = GST_PAD (pads->data);
1014 if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC) {
1015 /* we ref the event here as we might have to try again if the event
1016 * failed on this pad */
1017 gst_event_ref (event);
1018 if (gst_avi_demux_handle_src_event (pad, event)) {
1019 gst_event_unref (event);
1024 pads = g_list_next (pads);
1027 gst_event_unref (event);
1031 static const GstEventMask*
1032 gst_avi_demux_get_event_mask (GstPad *pad)
1034 static const GstEventMask masks[] = {
1035 { GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_KEY_UNIT },
1036 { GST_EVENT_SEEK_SEGMENT, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_KEY_UNIT },
1044 gst_avi_demux_handle_src_event (GstPad *pad, GstEvent *event)
1046 gboolean res = TRUE;
1047 GstAviDemux *avi_demux = GST_AVI_DEMUX (gst_pad_get_parent (pad));
1048 avi_stream_context *stream;
1050 stream = gst_pad_get_element_private (pad);
1052 switch (GST_EVENT_TYPE (event)) {
1053 case GST_EVENT_SEEK_SEGMENT:
1054 stream->end_pos = GST_EVENT_SEEK_ENDOFFSET (event);
1055 case GST_EVENT_SEEK:
1056 GST_DEBUG (0, "seek format %d, %08x", GST_EVENT_SEEK_FORMAT (event), stream->strh.type);
1057 switch (GST_EVENT_SEEK_FORMAT (event)) {
1058 case GST_FORMAT_BYTES:
1059 case GST_FORMAT_UNITS:
1061 case GST_FORMAT_TIME:
1063 gst_avi_index_entry *seek_entry, *entry;
1064 gint64 desired_offset = GST_EVENT_SEEK_OFFSET (event);
1069 /* no seek on audio yet */
1070 if (stream->strh.type == GST_RIFF_FCC_auds) {
1074 GST_DEBUG (0, "seeking to %lld", desired_offset);
1076 flags = GST_RIFF_IF_KEYFRAME;
1078 entry = gst_avi_demux_index_entry_for_time (avi_demux, stream->num, desired_offset, GST_RIFF_IF_KEYFRAME);
1080 desired_offset = entry->ts;
1081 min_index = gst_avi_demux_sync_streams (avi_demux, desired_offset);
1082 seek_entry = &avi_demux->index_entries[min_index];
1084 gst_avi_debug_entry ("syncing to entry", seek_entry);
1086 avi_demux->seek_offset = seek_entry->offset + avi_demux->index_offset;
1087 avi_demux->seek_pending = TRUE;
1088 avi_demux->last_seek = seek_entry->ts;
1091 GST_DEBUG (0, "no index entry found for time %lld", desired_offset);
1107 gst_event_unref (event);
1113 gst_avi_demux_handle_sink_event (GstAviDemux *avi_demux)
1119 gst_bytestream_get_status (avi_demux->bs, &remaining, &event);
1121 type = event? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
1125 gst_bytestream_flush (avi_demux->bs, remaining);
1126 gst_pad_event_default (avi_demux->sinkpad, event);
1128 case GST_EVENT_FLUSH:
1129 g_warning ("flush event");
1131 case GST_EVENT_DISCONTINUOUS:
1136 for (i = 0; i < avi_demux->num_streams; i++) {
1137 avi_stream_context *stream = &avi_demux->stream[i];
1139 if (GST_PAD_IS_USABLE (stream->pad)) {
1140 GST_DEBUG (GST_CAT_EVENT, "sending discont on %d %lld + %lld = %lld", i,
1141 avi_demux->last_seek, stream->delay, avi_demux->last_seek + stream->delay);
1142 discont = gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
1143 avi_demux->last_seek + stream->delay , NULL);
1144 gst_pad_push (stream->pad, GST_BUFFER (discont));
1150 g_warning ("unhandled event %d", type);
1154 gst_event_unref (event);
1159 static inline gboolean
1160 gst_avi_demux_read_chunk (GstAviDemux *avi_demux, guint32 *id, guint32 *size)
1162 gst_riff_chunk *chunk;
1163 GstByteStream *bs = avi_demux->bs;
1167 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&chunk, sizeof (gst_riff_chunk));
1168 if (got_bytes == sizeof (gst_riff_chunk)) {
1169 *id = GUINT32_FROM_LE (chunk->id);
1170 *size = GUINT32_FROM_LE (chunk->size);
1172 gst_bytestream_flush (bs, sizeof (gst_riff_chunk));
1176 } while (gst_avi_demux_handle_sink_event (avi_demux));
1182 gst_avi_demux_process_movi (GstAviDemux *avi_demux, gint rec_depth, guint64 *filepos)
1184 guint32 subchunksize = 0;
1186 while (!avi_demux->restart) { /* while not showed all: */
1187 if (avi_demux->seek_pending) {
1188 GST_DEBUG (0, "avidemux: seek pending to %lld %08llx", avi_demux->seek_offset, avi_demux->seek_offset);
1189 if (!gst_bytestream_seek (avi_demux->bs, avi_demux->seek_offset, GST_SEEK_METHOD_SET)) {
1190 GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: could not seek");
1193 *filepos = avi_demux->seek_offset;
1195 avi_demux->seek_pending = FALSE;
1198 GST_INFO (GST_CAT_PLUGIN_INFO, "process chunk filepos %08llx", *filepos);
1199 /* recurse for subchunks of RIFF and LIST chunks: */
1200 if (!gst_avi_demux_process_chunk (avi_demux, filepos, 0,
1201 rec_depth + 1, &subchunksize)) {
1204 /* we are running in an infinite loop, we need to _yield
1205 * from time to time */
1206 gst_element_yield (GST_ELEMENT (avi_demux));
1212 gst_avi_demux_process_chunk (GstAviDemux *avi_demux, guint64 *filepos,
1213 guint32 desired_tag,
1214 gint rec_depth, guint32 *chunksize)
1217 GstByteStream *bs = avi_demux->bs;
1219 if (!gst_avi_demux_read_chunk (avi_demux, &chunkid, chunksize)) {
1220 g_print (" ***** Error reading chunk at filepos 0x%08llx\n", *filepos);
1223 if (desired_tag) { /* do we have to test identity? */
1224 if (desired_tag != chunkid) {
1225 g_print ("\n\n *** Error: Expected chunk '%s', found '%s'\n",
1226 gst_riff_id_to_fourcc (desired_tag),
1227 gst_riff_id_to_fourcc (chunkid));
1232 GST_INFO (GST_CAT_PLUGIN_INFO, "chunkid %s, size %08x, filepos %08llx",
1233 gst_riff_id_to_fourcc (chunkid), *chunksize, *filepos);
1235 *filepos += (sizeof (guint32) + sizeof (guint32));
1238 case GST_RIFF_TAG_RIFF:
1239 case GST_RIFF_TAG_LIST:
1242 guint32 subchunksize = 0; /* size of a read subchunk */
1246 got_bytes = gst_bytestream_peek_bytes (bs, (guint8**)&formtype, sizeof (guint32));
1247 if (got_bytes < sizeof(guint32))
1250 switch (GUINT32_FROM_LE (*((guint32*)formtype))) {
1251 case GST_RIFF_LIST_movi:
1252 gst_avi_demux_parse_index (avi_demux, *filepos, *chunksize);
1253 while (!gst_bytestream_flush (bs, sizeof (guint32))) {
1257 gst_bytestream_get_status (avi_demux->bs, &remaining, &event);
1258 gst_event_unref (event);
1260 if (avi_demux->avih.bufsize)
1261 gst_bytestream_size_hint (avi_demux->bs, avi_demux->avih.bufsize);
1263 gst_avi_demux_process_movi (avi_demux, rec_depth, filepos);
1266 /* flush the form type */
1267 gst_bytestream_flush_fast (bs, sizeof (guint32));
1271 datashowed = sizeof (guint32); /* we showed the form type */
1272 *filepos += datashowed; /* for the rest of the routine */
1274 while (datashowed < *chunksize) { /* while not showed all: */
1276 GST_INFO (GST_CAT_PLUGIN_INFO, "process chunk filepos %08llx", *filepos);
1277 /* recurse for subchunks of RIFF and LIST chunks: */
1278 if (!gst_avi_demux_process_chunk (avi_demux, filepos, 0,
1279 rec_depth + 1, &subchunksize)) {
1281 g_print (" ***** Error processing chunk at filepos 0x%08llxi %u %u\n",
1282 *filepos, *chunksize, datashowed);
1285 if (avi_demux->restart)
1288 subchunksize = ((subchunksize + 1) & ~1);
1290 datashowed += (sizeof (guint32) + sizeof (guint32) + subchunksize);
1291 GST_INFO (GST_CAT_PLUGIN_INFO, "process chunk done filepos %08llx, subchunksize %08x",
1292 *filepos, subchunksize);
1294 if (datashowed != *chunksize) {
1295 g_warning ("error parsing AVI %u %u", datashowed, *chunksize);
1299 case GST_RIFF_TAG_avih:
1300 gst_avi_demux_avih (avi_demux);
1302 case GST_RIFF_TAG_strh:
1304 gst_avi_demux_strh (avi_demux);
1307 case GST_RIFF_TAG_strf:
1308 switch (avi_demux->fcc_type) {
1309 case GST_RIFF_FCC_vids:
1310 gst_avi_demux_strf_vids (avi_demux);
1312 case GST_RIFF_FCC_auds:
1313 gst_avi_demux_strf_auds (avi_demux);
1315 case GST_RIFF_FCC_iavs:
1316 gst_avi_demux_strf_iavs (avi_demux);
1318 case GST_RIFF_FCC_pads:
1319 case GST_RIFF_FCC_txts:
1321 GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux_chain: strh type %s not supported",
1322 gst_riff_id_to_fourcc (avi_demux->fcc_type));
1332 avi_stream_context *stream;
1336 stream_id = CHUNKID_TO_STREAMNR (chunkid);
1338 stream = &avi_demux->stream[stream_id];
1340 GST_DEBUG (0,"gst_avi_demux_chain: tag found %08x size %08x stream_id %d",
1341 chunkid, *chunksize, stream_id);
1343 format = GST_FORMAT_TIME;
1344 gst_pad_query (stream->pad, GST_PAD_QUERY_POSITION, &format, &next_ts);
1346 if (stream->strh.init_frames == stream->current_frame && stream->delay==0)
1347 stream->delay = next_ts;
1349 stream->current_frame++;
1350 stream->current_byte += *chunksize;
1356 if (GST_PAD_IS_USABLE (stream->pad)) {
1357 if (next_ts >= stream->end_pos) {
1358 gst_pad_push (stream->pad, GST_BUFFER (gst_event_new (GST_EVENT_EOS)));
1359 GST_DEBUG (0, "end stream %d: %lld %d %lld", stream_id, next_ts, stream->current_frame - 1,
1367 got_bytes = gst_bytestream_peek (bs, &buf, *chunksize);
1369 GST_BUFFER_TIMESTAMP (buf) = next_ts;
1371 if (stream->need_flush) {
1372 /* FIXME, do some flush event here */
1373 stream->need_flush = FALSE;
1375 GST_DEBUG (0, "send stream %d: %lld %d %lld %08x", stream_id, next_ts, stream->current_frame - 1,
1376 stream->delay, *chunksize);
1378 gst_pad_push(stream->pad, buf);
1384 *chunksize = (*chunksize + 1) & ~1;
1388 GST_DEBUG (0, " ***** unknown chunkid %08x (%s)", chunkid, gst_riff_id_to_fourcc (chunkid));
1389 *chunksize = (*chunksize + 1) & ~1;
1392 GST_INFO (GST_CAT_PLUGIN_INFO, "chunkid %s, flush %08x, filepos %08llx",
1393 gst_riff_id_to_fourcc (chunkid), *chunksize, *filepos);
1395 *filepos += *chunksize;
1396 if (!gst_bytestream_flush (bs, *chunksize)) {
1397 return gst_avi_demux_handle_sink_event (avi_demux);
1406 gst_avi_demux_loop (GstElement *element)
1408 GstAviDemux *avi_demux;
1410 guint64 filepos = 0;
1412 g_return_if_fail (element != NULL);
1413 g_return_if_fail (GST_IS_AVI_DEMUX (element));
1415 avi_demux = GST_AVI_DEMUX (element);
1417 avi_demux->restart = FALSE;
1419 /* this is basically an infinite loop */
1420 if (!gst_avi_demux_process_chunk (avi_demux, &filepos, GST_RIFF_TAG_RIFF, 0, &chunksize)) {
1421 gst_element_error (element, "This doesn't appear to be an AVI file");
1424 if (!avi_demux->restart)
1425 /* if we exit the loop we are EOS */
1426 gst_pad_event_default (avi_demux->sinkpad, gst_event_new (GST_EVENT_EOS));
1429 static GstElementStateReturn
1430 gst_avi_demux_change_state (GstElement *element)
1432 GstAviDemux *avi_demux = GST_AVI_DEMUX (element);
1434 switch (GST_STATE_TRANSITION (element)) {
1435 case GST_STATE_NULL_TO_READY:
1437 case GST_STATE_READY_TO_PAUSED:
1438 avi_demux->bs = gst_bytestream_new (avi_demux->sinkpad);
1439 avi_demux->last_seek = 0;
1441 case GST_STATE_PAUSED_TO_PLAYING:
1443 case GST_STATE_PLAYING_TO_PAUSED:
1445 case GST_STATE_PAUSED_TO_READY:
1446 gst_bytestream_destroy (avi_demux->bs);
1447 avi_demux->restart = TRUE;
1449 case GST_STATE_READY_TO_NULL:
1455 parent_class->change_state (element);
1457 return GST_STATE_SUCCESS;
1461 gst_avi_demux_get_property (GObject *object, guint prop_id, GValue *value,
1466 g_return_if_fail (GST_IS_AVI_DEMUX (object));
1468 src = GST_AVI_DEMUX (object);
1479 plugin_init (GModule *module, GstPlugin *plugin)
1481 GstElementFactory *factory;
1482 GstTypeFactory *type;
1484 /* this filter needs the riff parser */
1485 if (!gst_library_load ("gstbytestream"))
1487 if (!gst_library_load ("gstriff"))
1490 /* create an elementfactory for the avi_demux element */
1491 factory = gst_element_factory_new ("avidemux", GST_TYPE_AVI_DEMUX,
1492 &gst_avi_demux_details);
1493 g_return_val_if_fail (factory != NULL, FALSE);
1494 gst_element_factory_set_rank (factory, GST_ELEMENT_RANK_PRIMARY);
1496 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_audio_templ));
1497 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (src_video_templ));
1498 gst_element_factory_add_pad_template (factory, GST_PAD_TEMPLATE_GET (sink_templ));
1500 type = gst_type_factory_new (&avidefinition);
1501 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (type));
1503 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
1508 GstPluginDesc plugin_desc = {