gstavidemux.c 58.9 KB
Newer Older
1
2
/* GStreamer
 * Copyright (C) <1999> Erik Walthinsen <omega@temple-baptist.com>
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


21
/* #define GST_DEBUG_ENABLED */
22
23
24
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
25
26
27
28
29
30
#include <string.h>

#include "gstavidemux.h"

/* elementfactory information */
static GstElementDetails gst_avi_demux_details = {
31
32
  "Avi demuxer",
  "Codec/Demuxer",
33
  "LGPL",
34
  "Demultiplex an avi file into audio and video",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
35
36
  VERSION,
  "Erik Walthinsen <omega@cse.ogi.edu>\n"
37
  "Wim Taymans <wim.taymans@chello.be>",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
38
39
40
  "(C) 1999",
};

41
static GstCaps* avi_type_find (GstBuffer *buf, gpointer private);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
42
43
44
45
46
47

/* typefactory for 'avi' */
static GstTypeDefinition avidefinition = {
  "avidemux_video/avi",
  "video/avi",
  ".avi",
48
  avi_type_find,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
49
50
51
52
53
54
55
56
57
58
59
};

/* AviDemux signals and args */
enum {
  /* FILL ME */
  LAST_SIGNAL
};

enum {
  ARG_0,
  ARG_BITRATE,
60
61
  ARG_METADATA,
  ARG_STREAMINFO,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
62
63
64
  /* FILL ME */
};

65
GST_PAD_TEMPLATE_FACTORY (sink_templ,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
66
67
68
69
70
71
  "sink",
  GST_PAD_SINK,
  GST_PAD_ALWAYS,
  GST_CAPS_NEW (
    "avidemux_sink",
     "video/avi",
72
      "format",    GST_PROPS_STRING ("AVI")
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
73
74
75
  )
)

76
GST_PAD_TEMPLATE_FACTORY (src_video_templ,
Wim Taymans's avatar
Wim Taymans committed
77
  "video_%02d",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
78
  GST_PAD_SRC,
79
  GST_PAD_SOMETIMES,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
80
  GST_CAPS_NEW (
81
    "avidemux_src_video_avi",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
82
83
84
85
    "video/avi",
      "format",  GST_PROPS_LIST (
	           GST_PROPS_STRING ("strf_vids"),
	           GST_PROPS_STRING ("strf_iavs")
Ronald S. Bultje's avatar
Ronald S. Bultje committed
86
87
88
89
      		 ),
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)

Ronald S. Bultje's avatar
Ronald S. Bultje committed
90
91
  ),
  GST_CAPS_NEW (
92
    "avidemux_src_video_raw",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
93
94
95
96
97
98
99
100
101
    "video/raw",
      "format",  GST_PROPS_LIST (
                   GST_PROPS_FOURCC (GST_MAKE_FOURCC('Y','U','Y','2')),
                   GST_PROPS_FOURCC (GST_MAKE_FOURCC('I','4','2','0'))
                 ),
      "width",          GST_PROPS_INT_RANGE (16, 4096),
      "height",         GST_PROPS_INT_RANGE (16, 4096)
  ),
  GST_CAPS_NEW (
102
    "avidemux_src_video_jpeg",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
103
104
105
106
107
    "video/jpeg",
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)
  ),
  GST_CAPS_NEW (
108
    "avidemux_src_video_dv",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
109
110
111
112
    "video/dv",
      "format",  GST_PROPS_LIST (
                   GST_PROPS_STRING ("NTSC"),
                   GST_PROPS_STRING ("PAL")
Ronald S. Bultje's avatar
Ronald S. Bultje committed
113
114
115
                 ),
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)
116
117
118
119
120
121
122
123
124
125
126
127
  ),
  GST_CAPS_NEW (
    "avidemux_src_video_divx",
    "video/divx",
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)
  ),
  GST_CAPS_NEW (
    "avidemux_src_video_xvid",
    "video/xvid",
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
128
129
130
  )
)

131
GST_PAD_TEMPLATE_FACTORY (src_audio_templ,
Wim Taymans's avatar
Wim Taymans committed
132
  "audio_%02d",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
133
  GST_PAD_SRC,
134
  GST_PAD_SOMETIMES,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
135
  GST_CAPS_NEW (
136
    "avidemux_src_audio_avi",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
137
    "video/avi",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
138
139
140
      "format",  GST_PROPS_STRING ("strf_auds")
  ),
  GST_CAPS_NEW (
141
    "avidemux_src_audio_raw",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
142
143
144
    "audio/raw",
      "format",           GST_PROPS_STRING ("int"),
      "law",              GST_PROPS_INT (0),
145
      "endianness",       GST_PROPS_INT (G_LITTLE_ENDIAN),
Ronald S. Bultje's avatar
Ronald S. Bultje committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
      "signed",           GST_PROPS_LIST (
      			    GST_PROPS_BOOLEAN (TRUE),
      			    GST_PROPS_BOOLEAN (FALSE)
			  ),
      "width",            GST_PROPS_LIST (
      			    GST_PROPS_INT (8),
      			    GST_PROPS_INT (16)
			  ),
      "depth",            GST_PROPS_LIST (
      			    GST_PROPS_INT (8),
      			    GST_PROPS_INT (16)
			  ),
      "rate",             GST_PROPS_INT_RANGE (11025, 44100),
      "channels",         GST_PROPS_INT_RANGE (1, 2)
  ),
  GST_CAPS_NEW (
162
    "avidemux_src_audio_mp3",
163
    "audio/x-mp3",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
164
      NULL
165
  ),
Wim Taymans's avatar
Wim Taymans committed
166
  GST_CAPS_NEW (
167
    "avidemux_src_audio_ac3",
Wim Taymans's avatar
Wim Taymans committed
168
169
170
    "audio/a52",
      NULL
  ),
171
  GST_CAPS_NEW (
172
    "avidemux_src_audio_vorbis",
173
174
    "application/x-ogg",
    NULL
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
175
176
177
  )
)

178
179
static void 		gst_avi_demux_class_init		(GstAviDemuxClass *klass);
static void 		gst_avi_demux_init			(GstAviDemux *avi_demux);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
180

181
static void 		gst_avi_demux_loop 			(GstElement *element);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
182

183
static gboolean 	gst_avi_demux_send_event 		(GstElement *element, GstEvent *event);
184

185
186
187
188
static const GstEventMask*
			gst_avi_demux_get_event_mask 		(GstPad *pad);
static gboolean 	gst_avi_demux_handle_src_event 		(GstPad *pad, GstEvent *event);
static const GstFormat* gst_avi_demux_get_src_formats 		(GstPad *pad); 
Wim Taymans's avatar
Wim Taymans committed
189
static const GstQueryType*
190
			gst_avi_demux_get_src_query_types 	(GstPad *pad);
Wim Taymans's avatar
Wim Taymans committed
191
static gboolean 	gst_avi_demux_handle_src_query 		(GstPad *pad, GstQueryType type, 
192
193
194
								 GstFormat *format, gint64 *value);
static gboolean 	gst_avi_demux_src_convert 		(GstPad *pad, GstFormat src_format, gint64 src_value,
	        	          				 GstFormat *dest_format, gint64 *dest_value);
Wim Taymans's avatar
Wim Taymans committed
195

Wim Taymans's avatar
Wim Taymans committed
196
static GstElementStateReturn
197
			gst_avi_demux_change_state 		(GstElement *element);
Wim Taymans's avatar
Wim Taymans committed
198

199
200
static void     	gst_avi_demux_get_property      	(GObject *object, guint prop_id, 	
								 GValue *value, GParamSpec *pspec);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
201
202
203


static GstElementClass *parent_class = NULL;
204
/*static guint gst_avi_demux_signals[LAST_SIGNAL] = { 0 }; */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

GType
gst_avi_demux_get_type(void) 
{
  static GType avi_demux_type = 0;

  if (!avi_demux_type) {
    static const GTypeInfo avi_demux_info = {
      sizeof(GstAviDemuxClass),      
      NULL,
      NULL,
      (GClassInitFunc)gst_avi_demux_class_init,
      NULL,
      NULL,
      sizeof(GstAviDemux),
      0,
      (GInstanceInitFunc)gst_avi_demux_init,
    };
    avi_demux_type = g_type_register_static(GST_TYPE_ELEMENT, "GstAviDemux", &avi_demux_info, 0);
  }
  return avi_demux_type;
}

static void
gst_avi_demux_class_init (GstAviDemuxClass *klass) 
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;

  gobject_class = (GObjectClass*)klass;
  gstelement_class = (GstElementClass*)klass;

  g_object_class_install_property (G_OBJECT_CLASS(klass), ARG_BITRATE,
    g_param_spec_long ("bitrate","bitrate","bitrate",
239
                       G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */
240
241
242
243
244
245
  g_object_class_install_property (gobject_class, ARG_METADATA,
    g_param_spec_boxed ("metadata", "Metadata", "Metadata",
                        GST_TYPE_CAPS, G_PARAM_READABLE));
  g_object_class_install_property (gobject_class, ARG_STREAMINFO,
    g_param_spec_boxed ("streaminfo", "Streaminfo", "Streaminfo",
                        GST_TYPE_CAPS, G_PARAM_READABLE));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
246
247
248
249

  parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
  
  gobject_class->get_property = gst_avi_demux_get_property;
Wim Taymans's avatar
Wim Taymans committed
250
251
  
  gstelement_class->change_state = gst_avi_demux_change_state;
252
  gstelement_class->send_event = gst_avi_demux_send_event;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
253
254
255
256
257
258
259
260
}

static void 
gst_avi_demux_init (GstAviDemux *avi_demux) 
{
  GST_FLAG_SET (avi_demux, GST_ELEMENT_EVENT_AWARE);
				
  avi_demux->sinkpad = gst_pad_new_from_template (
261
		  GST_PAD_TEMPLATE_GET (sink_templ), "sink");
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
262
263
264
265
266
267
  gst_element_add_pad (GST_ELEMENT (avi_demux), avi_demux->sinkpad);

  gst_element_set_loop_function (GST_ELEMENT (avi_demux), gst_avi_demux_loop);
}

static GstCaps*
268
avi_type_find (GstBuffer *buf,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
269
270
271
272
273
              gpointer private)
{
  gchar *data = GST_BUFFER_DATA (buf);
  GstCaps *new;

274
  GST_DEBUG ("avi_demux: typefind");
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
275
276
277
278
279
280

  if (GUINT32_FROM_LE (((guint32 *)data)[0]) != GST_RIFF_TAG_RIFF)
    return NULL;
  if (GUINT32_FROM_LE (((guint32 *)data)[2]) != GST_RIFF_RIFF_AVI)
    return NULL;

281
  new = GST_CAPS_NEW ("avi_type_find",
282
		      "video/avi", 
283
		        "format", GST_PROPS_STRING ("AVI"));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
284
285
286
287
288
289
290
  return new;
}

static gboolean
gst_avi_demux_avih (GstAviDemux *avi_demux)
{
  gst_riff_avih *avih;
Benjamin Otte's avatar
Benjamin Otte committed
291
  guint8 *avihdata;
292
293
294
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;

Benjamin Otte's avatar
Benjamin Otte committed
295
296
  got_bytes = gst_bytestream_peek_bytes (bs, &avihdata, sizeof (gst_riff_avih));
  avih = (gst_riff_avih *) avihdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
297

298
  if (got_bytes == sizeof (gst_riff_avih)) {
Wim Taymans's avatar
Wim Taymans committed
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
    avi_demux->avih.us_frame 	= GUINT32_FROM_LE (avih->us_frame);
    avi_demux->avih.max_bps 	= GUINT32_FROM_LE (avih->max_bps);
    avi_demux->avih.pad_gran 	= GUINT32_FROM_LE (avih->pad_gran);
    avi_demux->avih.flags 	= GUINT32_FROM_LE (avih->flags);
    avi_demux->avih.tot_frames 	= GUINT32_FROM_LE (avih->tot_frames);
    avi_demux->avih.init_frames = GUINT32_FROM_LE (avih->init_frames);
    avi_demux->avih.streams 	= GUINT32_FROM_LE (avih->streams);
    avi_demux->avih.bufsize 	= GUINT32_FROM_LE (avih->bufsize);
    avi_demux->avih.width 	= GUINT32_FROM_LE (avih->width);
    avi_demux->avih.height 	= GUINT32_FROM_LE (avih->height);
    avi_demux->avih.scale 	= GUINT32_FROM_LE (avih->scale);
    avi_demux->avih.rate 	= GUINT32_FROM_LE (avih->rate);
    avi_demux->avih.start 	= GUINT32_FROM_LE (avih->start);
    avi_demux->avih.length 	= GUINT32_FROM_LE (avih->length);

314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
    GST_INFO ( "gst_avi_demux: avih tag found");
    GST_INFO ( "gst_avi_demux:  us_frame    %d", avi_demux->avih.us_frame);
    GST_INFO ( "gst_avi_demux:  max_bps     %d", avi_demux->avih.max_bps);
    GST_INFO ( "gst_avi_demux:  pad_gran    %d", avi_demux->avih.pad_gran);
    GST_INFO ( "gst_avi_demux:  flags       0x%08x", avi_demux->avih.flags);
    GST_INFO ( "gst_avi_demux:  tot_frames  %d", avi_demux->avih.tot_frames);
    GST_INFO ( "gst_avi_demux:  init_frames %d", avi_demux->avih.init_frames);
    GST_INFO ( "gst_avi_demux:  streams     %d", avi_demux->avih.streams);
    GST_INFO ( "gst_avi_demux:  bufsize     %d", avi_demux->avih.bufsize);
    GST_INFO ( "gst_avi_demux:  width       %d", avi_demux->avih.width);
    GST_INFO ( "gst_avi_demux:  height      %d", avi_demux->avih.height);
    GST_INFO ( "gst_avi_demux:  scale       %d", avi_demux->avih.scale);
    GST_INFO ( "gst_avi_demux:  rate        %d", avi_demux->avih.rate);
    GST_INFO ( "gst_avi_demux:  start       %d", avi_demux->avih.start);
    GST_INFO ( "gst_avi_demux:  length      %d", avi_demux->avih.length);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
329
330
331
332
333
334
335
336
337
338

    return TRUE;
  }
  return FALSE;
}

static gboolean 
gst_avi_demux_strh (GstAviDemux *avi_demux)
{
  gst_riff_strh *strh;
Benjamin Otte's avatar
Benjamin Otte committed
339
  guint8 *strhdata;
340
341
342
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;

Benjamin Otte's avatar
Benjamin Otte committed
343
344
  got_bytes = gst_bytestream_peek_bytes (bs, &strhdata, sizeof (gst_riff_strh));
  strh = (gst_riff_strh *) strhdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
345

346
  if (got_bytes == sizeof (gst_riff_strh)) {
Wim Taymans's avatar
Wim Taymans committed
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
    avi_stream_context *target;

    avi_demux->fcc_type = GUINT32_FROM_LE (strh->type);

    target = &avi_demux->stream[avi_demux->num_streams];

    target->num = avi_demux->num_streams;

    target->strh.type 		= avi_demux->fcc_type;
    target->strh.fcc_handler 	= GUINT32_FROM_LE (strh->fcc_handler);
    target->strh.flags		= GUINT32_FROM_LE (strh->flags);
    target->strh.priority	= GUINT32_FROM_LE (strh->priority);
    target->strh.init_frames	= GUINT32_FROM_LE (strh->init_frames);
    target->strh.scale		= GUINT32_FROM_LE (strh->scale);
    target->strh.rate		= GUINT32_FROM_LE (strh->rate);
    target->strh.start		= GUINT32_FROM_LE (strh->start);
    target->strh.length		= GUINT32_FROM_LE (strh->length);
    target->strh.bufsize	= GUINT32_FROM_LE (strh->bufsize);
    target->strh.quality	= GUINT32_FROM_LE (strh->quality);
    target->strh.samplesize	= GUINT32_FROM_LE (strh->samplesize);

    if (!target->strh.scale)
      target->strh.scale = 1; /* avoid division by zero */
    if (!target->strh.rate)
      target->strh.rate = 1; /* avoid division by zero */

373
374
    GST_INFO ( "gst_avi_demux: strh tag found");
    GST_INFO ( "gst_avi_demux:  type        0x%08x (%s)", 
Wim Taymans's avatar
Wim Taymans committed
375
  		  target->strh.type, gst_riff_id_to_fourcc (strh->type));
376
    GST_INFO ( "gst_avi_demux:  fcc_handler 0x%08x (%s)", 
Wim Taymans's avatar
Wim Taymans committed
377
		  target->strh.fcc_handler, gst_riff_id_to_fourcc (strh->fcc_handler));
378
379
380
381
382
383
384
385
386
387
    GST_INFO ( "gst_avi_demux:  flags       0x%08x", strh->flags);
    GST_INFO ( "gst_avi_demux:  priority    %d", target->strh.priority);
    GST_INFO ( "gst_avi_demux:  init_frames %d", target->strh.init_frames);
    GST_INFO ( "gst_avi_demux:  scale       %d", target->strh.scale);
    GST_INFO ( "gst_avi_demux:  rate        %d", target->strh.rate);
    GST_INFO ( "gst_avi_demux:  start       %d", target->strh.start);
    GST_INFO ( "gst_avi_demux:  length      %d", target->strh.length);
    GST_INFO ( "gst_avi_demux:  bufsize     %d", target->strh.bufsize);
    GST_INFO ( "gst_avi_demux:  quality     %d", target->strh.quality);
    GST_INFO ( "gst_avi_demux:  samplesize  %d", target->strh.samplesize);
Wim Taymans's avatar
Wim Taymans committed
388
389
390
391

    target->delay = 0LL;
    target->total_bytes = 0LL;
    target->total_frames = 0;
Wim Taymans's avatar
Wim Taymans committed
392
    target->end_pos = -1;
393
394
395
    target->current_frame = 0;
    target->current_byte = 0;
    target->need_flush = FALSE;
Wim Taymans's avatar
Wim Taymans committed
396
    target->skip = 0;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
397

398
399
    avi_demux->avih.bufsize = MAX (avi_demux->avih.bufsize, target->strh.bufsize);

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
400
401
402
403
404
    return TRUE;
  }
  return FALSE;
}

405
406
407
408
static void
gst_avi_demux_dmlh (GstAviDemux *avi_demux)
{
  gst_riff_dmlh *dmlh;
Benjamin Otte's avatar
Benjamin Otte committed
409
  guint8 *dmlhdata;
410
  GstByteStream  *bs = avi_demux->bs;
411
412
  guint32 got_bytes;

Benjamin Otte's avatar
Benjamin Otte committed
413
414
  got_bytes = gst_bytestream_peek_bytes (bs, &dmlhdata, sizeof (gst_riff_dmlh));
  dmlh = (gst_riff_dmlh *) dmlhdata;
415
416
}

Wim Taymans's avatar
Wim Taymans committed
417
418
419
420
static void
gst_avi_demux_strn (GstAviDemux *avi_demux, gint len)
{
  gchar *name;
Benjamin Otte's avatar
Benjamin Otte committed
421
  guint8 *namedata;
Wim Taymans's avatar
Wim Taymans committed
422
423
424
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;

Benjamin Otte's avatar
Benjamin Otte committed
425
426
  got_bytes = gst_bytestream_peek_bytes (bs, &namedata, len);
  name = (gchar *) namedata;
Wim Taymans's avatar
Wim Taymans committed
427
428
429
  if (got_bytes != len)
    return;

430
  GST_DEBUG ("Stream name: \"%s\"", name);
Wim Taymans's avatar
Wim Taymans committed
431
432
}

433
434
435
436
437
static void
gst_avi_demux_metadata (GstAviDemux *avi_demux, gint len)
{
  guint32 got_bytes;
  GstByteStream  *bs = avi_demux->bs;
438
  gst_riff_chunk *temp_chunk, chunk;
Benjamin Otte's avatar
Benjamin Otte committed
439
  guint8 *tempdata;
440
441
442
443
444
445
446
  gchar *name, *type;
  GstProps *props;
  GstPropsEntry *entry;

  props = gst_props_empty_new ();

  while (len > 0) {
Benjamin Otte's avatar
Benjamin Otte committed
447
448
449
    got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, sizeof (gst_riff_chunk));
    temp_chunk = (gst_riff_chunk *) tempdata;
    
450
451
452
453
454
455
    /* fixup for our big endian friends */
    chunk.id = GUINT32_FROM_LE (temp_chunk->id);
    chunk.size = GUINT32_FROM_LE (temp_chunk->size);

    gst_bytestream_flush (bs, sizeof (gst_riff_chunk));
    if (got_bytes != sizeof (gst_riff_chunk))
456
      return;
457
    len -= sizeof (gst_riff_chunk);
458
459

    /* don't care about empty entries - move on */
460
    if (chunk.size == 0)
461
462
      continue;

Benjamin Otte's avatar
Benjamin Otte committed
463
464
    got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, chunk.size);
    name = (gchar *) tempdata;
465
466
    gst_bytestream_flush (bs, (chunk.size + 1) & ~1);
    if (got_bytes != chunk.size)
467
      return;
468
    len -= ((chunk.size + 1) & ~1);
469
470

    /* we now have an info string in 'name' of type 'chunk.id' - find 'type' */
471
    switch (chunk.id) {
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
      case GST_RIFF_INFO_IARL:
        type = "Location";
        break;
      case GST_RIFF_INFO_IART:
        type = "Artist";
        break;
      case GST_RIFF_INFO_ICMS:
        type = "Commissioner";
        break;
      case GST_RIFF_INFO_ICMT:
        type = "Comment";
        break;
      case GST_RIFF_INFO_ICOP:
        type = "Copyright";
        break;
      case GST_RIFF_INFO_ICRD:
        type = "Creation Date";
        break;
      case GST_RIFF_INFO_ICRP:
        type = "Cropped";
        break;
      case GST_RIFF_INFO_IDIM:
        type = "Dimensions";
        break;
      case GST_RIFF_INFO_IDPI:
        type = "Dots per Inch";
        break;
      case GST_RIFF_INFO_IENG:
        type = "Engineer";
        break;
      case GST_RIFF_INFO_IGNR:
        type = "Genre";
        break;
      case GST_RIFF_INFO_IKEY:
        type = "Keywords";
        break;
      case GST_RIFF_INFO_ILGT:
        type = "Lightness";
        break;
      case GST_RIFF_INFO_IMED:
        type = "Medium";
        break;
      case GST_RIFF_INFO_INAM:
        type = "Title"; /* "Name" */
        break;
      case GST_RIFF_INFO_IPLT:
        type = "Palette";
        break;
      case GST_RIFF_INFO_IPRD:
        type = "Product";
        break;
      case GST_RIFF_INFO_ISBJ:
        type = "Subject";
        break;
      case GST_RIFF_INFO_ISFT:
        type = "Encoder"; /* "Sotware" */
        break;
      case GST_RIFF_INFO_ISHP:
        type = "Sharpness";
        break;
      case GST_RIFF_INFO_ISRC:
        type = "Source";
        break;
      case GST_RIFF_INFO_ISRF:
        type = "Source Form";
        break;
      case GST_RIFF_INFO_ITCH:
        type = "Technician";
        break;
      default:
	type = NULL;
	break;
    }

    if (type) {
      /* create props entry */
548
      entry = gst_props_entry_new (type, GST_PROPS_STRING (name));
549
550
551
552
553
554
      gst_props_add_entry (props, entry);
    }
  }

  gst_props_debug(props);

555
556
557
558
  gst_caps_replace_sink (&avi_demux->metadata,
		         gst_caps_new("avi_metadata",
                                      "application/x-gst-metadata",
                                        props));
559
560
561
562
563
564
565
566
567
568
569
570
571

  g_object_notify(G_OBJECT(avi_demux), "metadata");
}

static void
gst_avi_demux_streaminfo (GstAviDemux *avi_demux)
{
  GstProps *props;

  props = gst_props_empty_new ();

  /* compression formats are added later - a bit hacky */

572
573
574
575
  gst_caps_replace_sink (&avi_demux->streaminfo,
		  	 gst_caps_new("avi_streaminfo",
                                      "application/x-gst-streaminfo",
                                      props));
576
577
578
579

  /*g_object_notify(G_OBJECT(avi_demux), "streaminfo");*/
}

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
580
581
582
583
static void 
gst_avi_demux_strf_vids (GstAviDemux *avi_demux)
{
  gst_riff_strf_vids *strf;
Benjamin Otte's avatar
Benjamin Otte committed
584
  guint8 *strfdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
585
  GstPad *srcpad;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
586
  GstCaps *newcaps = NULL, *capslist = NULL;
Wim Taymans's avatar
Wim Taymans committed
587
  avi_stream_context *stream;
588
589
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;
590
591
  gchar *codecname;
  GstPropsEntry *entry;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
592

Benjamin Otte's avatar
Benjamin Otte committed
593
594
  got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_vids));
  strf = (gst_riff_strf_vids *) strfdata;
595
596
  if (got_bytes != sizeof (gst_riff_strf_vids))
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
597

598
599
600
601
602
603
604
  GST_INFO ( "gst_avi_demux: strf tag found in context vids");
  GST_INFO ( "gst_avi_demux:  size        %d", GUINT32_FROM_LE (strf->size));
  GST_INFO ( "gst_avi_demux:  width       %d", GUINT32_FROM_LE (strf->width));
  GST_INFO ( "gst_avi_demux:  height      %d", GUINT32_FROM_LE (strf->height));
  GST_INFO ( "gst_avi_demux:  planes      %d", GUINT16_FROM_LE (strf->planes));
  GST_INFO ( "gst_avi_demux:  bit_cnt     %d", GUINT16_FROM_LE (strf->bit_cnt));
  GST_INFO ( "gst_avi_demux:  compression 0x%08x (%s)", 
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
605
		  GUINT32_FROM_LE (strf->compression), gst_riff_id_to_fourcc (strf->compression));
606
607
608
609
610
  GST_INFO ( "gst_avi_demux:  image_size  %d", GUINT32_FROM_LE (strf->image_size));
  GST_INFO ( "gst_avi_demux:  xpels_meter %d", GUINT32_FROM_LE (strf->xpels_meter));
  GST_INFO ( "gst_avi_demux:  ypels_meter %d", GUINT32_FROM_LE (strf->ypels_meter));
  GST_INFO ( "gst_avi_demux:  num_colors  %d", GUINT32_FROM_LE (strf->num_colors));
  GST_INFO ( "gst_avi_demux:  imp_colors  %d", GUINT32_FROM_LE (strf->imp_colors));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
611
612

  srcpad =  gst_pad_new_from_template (
613
		  GST_PAD_TEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d", 
Wim Taymans's avatar
Wim Taymans committed
614
			  avi_demux->num_v_streams));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
615

Ronald S. Bultje's avatar
Ronald S. Bultje committed
616
617
  capslist = gst_caps_append(NULL, GST_CAPS_NEW (
			  "avidemux_video_src",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
618
619
620
621
622
623
624
625
626
627
628
629
			  "video/avi",
			    "format",    	GST_PROPS_STRING ("strf_vids"),
			      "size", 		GST_PROPS_INT (GUINT32_FROM_LE (strf->size)),
			      "width", 		GST_PROPS_INT (GUINT32_FROM_LE (strf->width)),
			      "height", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->height)),
			      "planes", 	GST_PROPS_INT (GUINT16_FROM_LE (strf->planes)),
			      "bit_cnt", 	GST_PROPS_INT (GUINT16_FROM_LE (strf->bit_cnt)),
			      "compression", 	GST_PROPS_FOURCC (GUINT32_FROM_LE (strf->compression)),
			      "image_size", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->image_size)),
			      "xpels_meter", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->xpels_meter)),
			      "ypels_meter", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->ypels_meter)),
			      "num_colors", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->num_colors)),
630
631
			      "imp_colors", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->imp_colors))
			      ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
632

Ronald S. Bultje's avatar
Ronald S. Bultje committed
633
  /* let's try some gstreamer-like mime-type caps */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
634
635
636
637
638
639
640
641
642
643
644
  switch (GUINT32_FROM_LE(strf->compression))
  {
    case GST_MAKE_FOURCC('I','4','2','0'):
    case GST_MAKE_FOURCC('Y','U','Y','2'):
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/raw",
                    "format",  GST_PROPS_FOURCC(GUINT32_FROM_LE(strf->compression)),
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
645
646
      codecname = g_strdup_printf("Raw Video (%4.4s)",
                                  (char *) &strf->compression);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
647
      break;
648
649
650
651
    case GST_MAKE_FOURCC('M','J','P','G'): /* YUY2 MJPEG */
    case GST_MAKE_FOURCC('J','P','E','G'): /* generic (mostly RGB) MJPEG */
    case GST_MAKE_FOURCC('P','I','X','L'): /* Miro/Pinnacle fourccs */
    case GST_MAKE_FOURCC('V','I','X','L'): /* Miro/Pinnacle fourccs */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
652
653
654
655
656
657
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/jpeg",
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
      codecname = g_strdup_printf("Motion-JPEG (%4.4s)",
                                  (char *) &strf->compression);
      break;
    case GST_MAKE_FOURCC('H','F','Y','U'):
      codecname = g_strdup_printf("HuffYUV (%4.4s)",
                                  (char *) &strf->compression);
      break;
    case GST_MAKE_FOURCC('M','P','E','G'):
    case GST_MAKE_FOURCC('M','P','G','I'):
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/mpeg",
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
      codecname = g_strdup_printf("MPEG-1 (%4.4s)",
                                  (char *) &strf->compression);
      break;
    case GST_MAKE_FOURCC('H','2','6','3'):
    case GST_MAKE_FOURCC('i','2','6','3'):
    case GST_MAKE_FOURCC('L','2','6','3'):
    case GST_MAKE_FOURCC('M','2','6','3'):
    case GST_MAKE_FOURCC('V','D','O','W'):
    case GST_MAKE_FOURCC('V','I','V','O'):
    case GST_MAKE_FOURCC('x','2','6','3'):
      codecname = g_strdup_printf("H263-compatible (%4.4s)",
                                  (char *) &strf->compression);
      break;
    case GST_MAKE_FOURCC('d','i','v','x'):
    case GST_MAKE_FOURCC('D','I','V','3'):
    case GST_MAKE_FOURCC('D','I','V','4'):
    case GST_MAKE_FOURCC('D','I','V','5'):
    case GST_MAKE_FOURCC('D','I','V','X'):
    case GST_MAKE_FOURCC('D','X','5','0'):
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/divx",
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
      codecname = g_strdup_printf("DivX/MPEG-4 (%4.4s)",
                                  (char *) &strf->compression);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
700
      break;
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
    case GST_MAKE_FOURCC('X','V','I','D'):
    case GST_MAKE_FOURCC('x','v','i','d'):
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/xvid",
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
      codecname = g_strdup_printf("XviD/MPEG-4 (%4.4s)",
                                  (char *) &strf->compression);
      break;
    case GST_MAKE_FOURCC('M','P','G','4'):
    case GST_MAKE_FOURCC('M','P','4','2'):
    case GST_MAKE_FOURCC('M','P','4','3'):
      codecname = g_strdup_printf("MS MPEG-4 (%4.4s)",
                                  (char *) &strf->compression);
      break;
    case GST_MAKE_FOURCC('D','V','S','D'):
Ronald S. Bultje's avatar
Ronald S. Bultje committed
719
720
721
722
723
724
725
726
    case GST_MAKE_FOURCC('d','v','s','d'):
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/dv",
                    "format",  GST_PROPS_STRING("NTSC"), /* FIXME??? */
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
727
728
729
730
731
732
      codecname = g_strdup_printf("Digital Video (%4.4s)",
                                  (char *) &strf->compression);
      break;
    default:
      codecname = g_strdup_printf("Unknown (%4.4s)",
                                  (char *) &strf->compression);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
733
734
735
      break;
  }

Wim Taymans's avatar
Wim Taymans committed
736
  if (newcaps) capslist = gst_caps_append (capslist, newcaps);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
737

738
739
740
741
742
  /* set video codec info on streaminfo caps */
  entry = gst_props_entry_new("videocodec", GST_PROPS_STRING(codecname));
  gst_props_add_entry(avi_demux->streaminfo->properties, entry);
  g_free(codecname);

Wim Taymans's avatar
Wim Taymans committed
743
  gst_pad_try_set_caps (srcpad, capslist);
744
745
  gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats);
  gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask);
Wim Taymans's avatar
Wim Taymans committed
746
  gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
747
  gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
Wim Taymans's avatar
Wim Taymans committed
748
  gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
749
  gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
Wim Taymans's avatar
Wim Taymans committed
750
751
752
753
754
755

  stream = &avi_demux->stream[avi_demux->num_streams];
  stream->pad = srcpad;
  gst_pad_set_element_private (srcpad, stream);
  avi_demux->num_streams++;
  avi_demux->num_v_streams++;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
756

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
757
758
759
760
761
762
763
  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
}

static void 
gst_avi_demux_strf_auds (GstAviDemux *avi_demux)
{
  gst_riff_strf_auds *strf;
Benjamin Otte's avatar
Benjamin Otte committed
764
  guint8 *strfdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
765
  GstPad *srcpad;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
766
  GstCaps *newcaps = NULL, *capslist = NULL;
Wim Taymans's avatar
Wim Taymans committed
767
  avi_stream_context *stream;
768
769
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;
770
771
  gchar *codecname;
  GstPropsEntry *entry;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
772

Benjamin Otte's avatar
Benjamin Otte committed
773
774
  got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_auds));
  strf = (gst_riff_strf_auds *) strfdata;
775
776
  if (got_bytes != sizeof (gst_riff_strf_auds))
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
777

778
779
780
781
782
783
784
  GST_INFO ( "gst_avi_demux: strf tag found in context auds");
  GST_INFO ( "gst_avi_demux:  format      %d", GUINT16_FROM_LE (strf->format));
  GST_INFO ( "gst_avi_demux:  channels    %d", GUINT16_FROM_LE (strf->channels));
  GST_INFO ( "gst_avi_demux:  rate        %d", GUINT32_FROM_LE (strf->rate));
  GST_INFO ( "gst_avi_demux:  av_bps      %d", GUINT32_FROM_LE (strf->av_bps));
  GST_INFO ( "gst_avi_demux:  blockalign  %d", GUINT16_FROM_LE (strf->blockalign));
  GST_INFO ( "gst_avi_demux:  size        %d", GUINT16_FROM_LE (strf->size));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
785
786

  srcpad =  gst_pad_new_from_template (
787
		  GST_PAD_TEMPLATE_GET (src_audio_templ), g_strdup_printf ("audio_%02d", 
Wim Taymans's avatar
Wim Taymans committed
788
			  avi_demux->num_a_streams));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
789

Ronald S. Bultje's avatar
Ronald S. Bultje committed
790
791
  capslist = gst_caps_append(NULL, GST_CAPS_NEW (
			  "avidemux_audio_src",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
792
793
794
795
796
797
798
			  "video/avi",
			    "format",    	GST_PROPS_STRING ("strf_auds"),
			      "fmt", 		GST_PROPS_INT (GUINT16_FROM_LE (strf->format)),
			      "channels", 	GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)),
			      "rate", 		GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)),
			      "av_bps",		GST_PROPS_INT (GUINT32_FROM_LE (strf->av_bps)),
			      "blockalign",	GST_PROPS_INT (GUINT16_FROM_LE (strf->blockalign)),
799
800
			      "size",		GST_PROPS_INT (GUINT16_FROM_LE (strf->size))
			  ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
801

Ronald S. Bultje's avatar
Ronald S. Bultje committed
802
803
804
  /* let's try some gstreamer-formatted mime types */
  switch (GUINT16_FROM_LE(strf->format))
  {
805
806
    case GST_RIFF_WAVE_FORMAT_MPEGL3:
    case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp3 */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
807
      newcaps = gst_caps_new ("avidemux_audio_src",
808
                              "audio/x-mp3",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
809
                                NULL);
810
811
      codecname = g_strdup_printf("MPEG/audio (0x%04x)",
                                  strf->format);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
812
      break;
813
    case GST_RIFF_WAVE_FORMAT_PCM: /* PCM/wav */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
814
815
816
817
818
      newcaps = gst_caps_new ("avidemux_audio_src",
                              "audio/raw",
                              gst_props_new (
                                "format",     GST_PROPS_STRING ("int"),
                                "law",        GST_PROPS_INT (0),
819
                                "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN),
Ronald S. Bultje's avatar
Ronald S. Bultje committed
820
821
                                "signed",     GST_PROPS_BOOLEAN ((GUINT16_FROM_LE (strf->size) != 8)),
                                "width",      GST_PROPS_INT ((GUINT16_FROM_LE (strf->blockalign)*8) /
Wim Taymans's avatar
Wim Taymans committed
822
                                                              GUINT16_FROM_LE (strf->channels)),
Ronald S. Bultje's avatar
Ronald S. Bultje committed
823
824
825
826
827
                                "depth",      GST_PROPS_INT (GUINT16_FROM_LE (strf->size)),
                                "rate",       GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)),
                                "channels",   GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)),
                                NULL
                              ));
828
829
      codecname = g_strdup_printf("Raw PCM/WAV (0x%04x)",
                                  strf->format);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
830
      break;
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
    case GST_RIFF_WAVE_FORMAT_MULAW:
    case GST_RIFF_WAVE_FORMAT_ALAW:
      if (strf->size != 8)
        g_warning ("invalid depth (%d) of mulaw/alaw audio, overwriting.", strf->size);
      newcaps = gst_caps_new ("avidemux_audio_src",
                              "audio/raw",
                              gst_props_new (
			        "format",	GST_PROPS_STRING ("int"),
			        "law",		GST_PROPS_INT (GUINT16_FROM_LE(strf->format) == GST_RIFF_WAVE_FORMAT_ALAW ? 2 : 1),
			      	"endianness",	GST_PROPS_INT (G_LITTLE_ENDIAN),
			 	"width",	GST_PROPS_INT (8),
			 	"depth",	GST_PROPS_INT (8),
			  	"rate",		GST_PROPS_INT (GUINT32_FROM_LE (strf->rate)),
                                "channels",	GST_PROPS_INT (GUINT16_FROM_LE (strf->channels)),
                                NULL
                              ));
      codecname = g_strdup_printf("%s-law encoded (0x%04x)",
                                  GUINT16_FROM_LE(strf->format) == GST_RIFF_WAVE_FORMAT_ALAW ? "A" : "Mu", strf->format);    
      break;
850
851
852
853
854
855
856
857
858
    case GST_RIFF_WAVE_FORMAT_VORBIS1: /* ogg/vorbis mode 1 */
    case GST_RIFF_WAVE_FORMAT_VORBIS2: /* ogg/vorbis mode 2 */
    case GST_RIFF_WAVE_FORMAT_VORBIS3: /* ogg/vorbis mode 3 */
    case GST_RIFF_WAVE_FORMAT_VORBIS1PLUS: /* ogg/vorbis mode 1+ */
    case GST_RIFF_WAVE_FORMAT_VORBIS2PLUS: /* ogg/vorbis mode 2+ */
    case GST_RIFF_WAVE_FORMAT_VORBIS3PLUS: /* ogg/vorbis mode 3+ */
      newcaps = gst_caps_new ("avidemux_audio_src",
                              "application/x-ogg",
                              NULL);
859
860
      codecname = g_strdup_printf("Ogg/Vorbis (0x%04x)",
                                  strf->format);
861
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
862
    case GST_RIFF_WAVE_FORMAT_A52:
Wim Taymans's avatar
Wim Taymans committed
863
864
865
      newcaps = gst_caps_new ("avidemux_audio_src",
                              "audio/a52",
                              NULL);
866
867
      codecname = g_strdup_printf("AC3/AC52 (0x%04x)",
                                  strf->format);
Wim Taymans's avatar
Wim Taymans committed
868
869
870
      break;
    default:
      g_warning ("avidemux: unkown audio format %d", GUINT16_FROM_LE(strf->format));
871
872
      codecname = g_strdup_printf("Unknown (0x%04x)",
                                  strf->format);
Wim Taymans's avatar
Wim Taymans committed
873
      break;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
874
875
876
877
  }

  if (newcaps) capslist = gst_caps_append(capslist, newcaps);

878
879
880
881
  /* set audio codec in streaminfo */
  entry = gst_props_entry_new("audiocodec", GST_PROPS_STRING(codecname));
  gst_props_add_entry(avi_demux->streaminfo->properties, entry);
  g_free(codecname);
Wim Taymans's avatar
Wim Taymans committed
882

Ronald S. Bultje's avatar
Ronald S. Bultje committed
883
  gst_pad_try_set_caps(srcpad, capslist);
884
885
  gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats);
  gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask);
Wim Taymans's avatar
Wim Taymans committed
886
  gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
887
  gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
Wim Taymans's avatar
Wim Taymans committed
888
  gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
889
  gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
Wim Taymans's avatar
Wim Taymans committed
890
891
892
893
894
895

  stream = &avi_demux->stream[avi_demux->num_streams];
  stream->pad = srcpad;
  gst_pad_set_element_private (srcpad, stream);
  avi_demux->num_streams++;
  avi_demux->num_a_streams++;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
896

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
897
898
899
900
901
902
903
  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
}

static void 
gst_avi_demux_strf_iavs (GstAviDemux *avi_demux)
{
  gst_riff_strf_iavs *strf;
Benjamin Otte's avatar
Benjamin Otte committed
904
  guint8 *strfdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
905
  GstPad *srcpad;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
906
  GstCaps *newcaps = NULL, *capslist = NULL;
Wim Taymans's avatar
Wim Taymans committed
907
  avi_stream_context *stream;
908
909
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
910

Benjamin Otte's avatar
Benjamin Otte committed
911
912
  got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_iavs));
  strf = (gst_riff_strf_iavs *) strfdata;
913
914
  if (got_bytes != sizeof (gst_riff_strf_iavs))
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
915

916
917
918
919
920
921
922
923
924
  GST_INFO ( "gst_avi_demux: strf tag found in context iavs");
  GST_INFO ( "gst_avi_demux:  DVAAuxSrc   %08x", GUINT32_FROM_LE (strf->DVAAuxSrc));
  GST_INFO ( "gst_avi_demux:  DVAAuxCtl   %08x", GUINT32_FROM_LE (strf->DVAAuxCtl));
  GST_INFO ( "gst_avi_demux:  DVAAuxSrc1  %08x", GUINT32_FROM_LE (strf->DVAAuxSrc1));
  GST_INFO ( "gst_avi_demux:  DVAAuxCtl1  %08x", GUINT32_FROM_LE (strf->DVAAuxCtl1));
  GST_INFO ( "gst_avi_demux:  DVVAuxSrc   %08x", GUINT32_FROM_LE (strf->DVVAuxSrc));
  GST_INFO ( "gst_avi_demux:  DVVAuxCtl   %08x", GUINT32_FROM_LE (strf->DVVAuxCtl));
  GST_INFO ( "gst_avi_demux:  DVReserved1 %08x", GUINT32_FROM_LE (strf->DVReserved1));
  GST_INFO ( "gst_avi_demux:  DVReserved2 %08x", GUINT32_FROM_LE (strf->DVReserved2));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
925
926

  srcpad =  gst_pad_new_from_template (
927
		  GST_PAD_TEMPLATE_GET (src_video_templ), g_strdup_printf ("video_%02d", 
Wim Taymans's avatar
Wim Taymans committed
928
			  avi_demux->num_v_streams));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
929

Ronald S. Bultje's avatar
Ronald S. Bultje committed
930
931
  capslist = gst_caps_append(NULL, GST_CAPS_NEW (
			  "avidemux_video_src",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
932
933
934
935
936
937
938
939
940
			  "video/avi",
			    "format",    	GST_PROPS_STRING ("strf_iavs"),
                              "DVAAuxSrc", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc)),
                              "DVAAuxCtl", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl)),
                              "DVAAuxSrc1", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxSrc1)),
                              "DVAAuxCtl1", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVAAuxCtl1)),
                              "DVVAuxSrc", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxSrc)),
                              "DVVAuxCtl", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVVAuxCtl)),
                              "DVReserved1", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved1)),
941
942
                              "DVReserved2", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved2))
			 ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
943

Ronald S. Bultje's avatar
Ronald S. Bultje committed
944
945
946
947
948
949
950
951
  newcaps = gst_caps_new ("avi_type_dv", 
                          "video/dv", 
                          gst_props_new (
                            "format",		GST_PROPS_STRING ("NTSC"), /* FIXME??? */
                            NULL));

  if (newcaps) capslist = gst_caps_append(capslist, newcaps);

Ronald S. Bultje's avatar
Ronald S. Bultje committed
952
  gst_pad_try_set_caps(srcpad, capslist);
953
954
  gst_pad_set_formats_function (srcpad, gst_avi_demux_get_src_formats);
  gst_pad_set_event_mask_function (srcpad, gst_avi_demux_get_event_mask);
Wim Taymans's avatar
Wim Taymans committed
955
  gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
956
  gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
Wim Taymans's avatar
Wim Taymans committed
957
  gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
958
  gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
Wim Taymans's avatar
Wim Taymans committed
959
960
961
962
963
964

  stream = &avi_demux->stream[avi_demux->num_streams];
  stream->pad = srcpad;
  gst_pad_set_element_private (srcpad, stream);
  avi_demux->num_streams++;
  avi_demux->num_v_streams++;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
965

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
966
967
968
969
  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
}

static void
Wim Taymans's avatar
Wim Taymans committed
970
971
gst_avi_debug_entry (const gchar *prefix, gst_avi_index_entry *entry)
{
972
  GST_DEBUG ("%s: %05d %d %08llx %05d %14" G_GINT64_FORMAT " %08x %08x (%d) %08x", 
Wim Taymans's avatar
Wim Taymans committed
973
974
975
		  prefix, entry->index_nr, entry->stream_nr, 
		  (unsigned long long)entry->bytes_before, 
		  entry->frames_before, entry->ts, entry->flags, entry->offset, 
Wim Taymans's avatar
Wim Taymans committed
976
		  entry->offset, entry->size);
Wim Taymans's avatar
Wim Taymans committed
977
978
979
980
}

static void
gst_avi_demux_parse_index (GstAviDemux *avi_demux,
Wim Taymans's avatar
Wim Taymans committed
981
		          gulong filepos, gulong offset)
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
982
983
984
{
  GstBuffer *buf;
  gulong index_size;
985
  guint32 got_bytes;
Wim Taymans's avatar
Wim Taymans committed
986
987
  gint i;
  gst_riff_index_entry *entry;
Wim Taymans's avatar
Wim Taymans committed
988
  guint32 id;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
989

Wim Taymans's avatar
Wim Taymans committed
990
  if (!gst_bytestream_seek (avi_demux->bs, filepos + offset, GST_SEEK_METHOD_SET)) {
991
    GST_INFO ( "avidemux: could not seek to index");
Wim Taymans's avatar
Wim Taymans committed
992
993
    return;
  }
994
  do {
Wim Taymans's avatar
Wim Taymans committed
995
996
997
    guint32 remaining;
    GstEvent *event;
  
998
999
1000
1001
    got_bytes = gst_bytestream_read (avi_demux->bs, &buf, 8);
    if (got_bytes == 8)
      break;

Wim Taymans's avatar
Wim Taymans committed
1002
    gst_bytestream_get_status (avi_demux->bs, &remaining, &event);
1003
    gst_event_unref (event);
1004
  } while (TRUE);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1005

Wim Taymans's avatar
Wim Taymans committed
1006
  if (GST_BUFFER_OFFSET (buf) != filepos + offset || GST_BUFFER_SIZE (buf) != 8) {
1007
    GST_INFO ( "avidemux: could not get index, got %" G_GINT64_FORMAT " %d, expected %ld", 
Wim Taymans's avatar
Wim Taymans committed
1008
		    GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf), filepos + offset);
Wim Taymans's avatar
Wim Taymans committed
1009
    goto end;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1010
1011
  }

Wim Taymans's avatar
Wim Taymans committed
1012
1013
1014
  id = GUINT32_FROM_LE (*(guint32 *)GST_BUFFER_DATA (buf));

  if (id != GST_RIFF_TAG_idx1) {
1015
    GST_INFO ( "avidemux: no index found");
Wim Taymans's avatar
Wim Taymans committed
1016
    goto end;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1017
1018
1019
  }

  index_size = GUINT32_FROM_LE(*(guint32 *)(GST_BUFFER_DATA (buf) + 4));
Wim Taymans's avatar
Wim Taymans committed
1020
  gst_buffer_unref (buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1021

1022
1023
  gst_bytestream_size_hint (avi_demux->bs, index_size);

1024
  got_bytes = gst_bytestream_read (avi_demux->bs, &buf, index_size);
Wim Taymans's avatar
Wim Taymans committed
1025
  if (got_bytes < index_size) {
1026
    GST_INFO ( "avidemux: error reading index");
Wim Taymans's avatar
Wim Taymans committed
1027
1028
    goto end;
  }
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1029
1030

  avi_demux->index_size = index_size/sizeof(gst_riff_index_entry);
1031
  GST_INFO ( "avidemux: index size %lu", avi_demux->index_size);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1032

Wim Taymans's avatar
Wim Taymans committed
1033
1034
1035
1036
1037
1038
1039
1040
  avi_demux->index_entries = g_malloc (avi_demux->index_size * sizeof (gst_avi_index_entry));

  entry = (gst_riff_index_entry *) GST_BUFFER_DATA (buf);

  for (i = 0; i < avi_demux->index_size; i++) {
    avi_stream_context *stream;
    gint stream_nr;
    gst_avi_index_entry *target = &avi_demux->index_entries[i];
1041
    GstFormat format;
Wim Taymans's avatar
Wim Taymans committed
1042
    guint32 id;
Wim Taymans's avatar
Wim Taymans committed
1043

Wim Taymans's avatar
Wim Taymans committed
1044
1045
    id = GUINT32_FROM_LE (entry[i].id);
    stream_nr = CHUNKID_TO_STREAMNR (id);
Wim Taymans's avatar
Wim Taymans committed
1046
1047
1048
1049
1050
    if (stream_nr > avi_demux->num_streams || stream_nr < 0) {
      avi_demux->index_entries[i].stream_nr = -1;
      continue;
    }

Wim Taymans's avatar
Wim Taymans committed
1051
1052
1053
1054
    target->stream_nr = stream_nr;
    stream = &avi_demux->stream[stream_nr];

    target->index_nr = i;
Wim Taymans's avatar
Wim Taymans committed
1055
1056
1057
    target->flags    = GUINT32_FROM_LE (entry[i].flags);
    target->size     = GUINT32_FROM_LE (entry[i].size);
    target->offset   = GUINT32_FROM_LE (entry[i].offset);
Wim Taymans's avatar
Wim Taymans committed
1058

1059
1060
1061
    /* figure out if the index is 0 based or relative to the MOVI start */
    if (i == 0) {
      if (target->offset < filepos)
1062
	avi_demux->index_offset = filepos - 4;
1063
1064
1065
1066
      else
	avi_demux->index_offset = 0;
    }

Wim Taymans's avatar
Wim Taymans committed
1067
1068
1069
    target->bytes_before = stream->total_bytes;
    target->frames_before = stream->total_frames;

1070
    format = GST_FORMAT_TIME;
Wim Taymans's avatar
Wim Taymans committed
1071
    if (stream->strh.type == GST_RIFF_FCC_auds) {
Wim Taymans's avatar
Wim Taymans committed
1072
1073
      /* all audio frames are keyframes */
      target->flags |= GST_RIFF_IF_KEYFRAME;
1074
    }
Wim Taymans's avatar
Wim Taymans committed
1075
      
1076
    /* constant rate stream */
1077
    if (stream->strh.samplesize && stream->strh.type == GST_RIFF_FCC_auds) {
1078
1079
      gst_pad_convert (stream->pad, GST_FORMAT_BYTES, stream->total_bytes,
		                 &format, &target->ts);
Wim Taymans's avatar
Wim Taymans committed
1080
    }
1081
    /* VBR stream */
Wim Taymans's avatar
Wim Taymans committed
1082
    else {
Wim Taymans's avatar
Wim Taymans committed
1083
      gst_pad_convert (stream->pad, GST_FORMAT_DEFAULT, stream->total_frames,
1084
		                 &format, &target->ts);
Wim Taymans's avatar
Wim Taymans committed
1085
1086
1087
1088
1089
1090
    }
    gst_avi_debug_entry ("index", target);

    stream->total_bytes += target->size;
    stream->total_frames++;
  }
1091
1092
1093
1094
  for (i = 0; i < avi_demux->num_streams; i++) {
    avi_stream_context *stream;

    stream = &avi_demux->stream[i];
1095
    GST_DEBUG ("stream %i: %d frames, %" G_GINT64_FORMAT " bytes", 
1096
	       i, stream->total_frames, stream->total_bytes);
1097
  }
Wim Taymans's avatar
Wim Taymans committed
1098
  gst_buffer_unref (buf);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1099

Wim Taymans's avatar
Wim Taymans committed
1100
end:
1101
  GST_DEBUG ("index offset at %08lx", filepos);
Wim Taymans's avatar
Wim Taymans committed
1102
1103

  if (!gst_bytestream_seek (avi_demux->bs, filepos, GST_SEEK_METHOD_SET)) {
1104
    GST_INFO ( "avidemux: could not seek back to movi");
Wim Taymans's avatar
Wim Taymans committed
1105
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed