gstavidemux.c 60.2 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 */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
22 23 24 25 26 27
#include <string.h>

#include "gstavidemux.h"

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

38
static GstCaps* avi_type_find (GstBuffer *buf, gpointer private);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
39 40 41 42 43 44

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

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

enum {
  ARG_0,
  ARG_BITRATE,
57 58
  ARG_METADATA,
  ARG_STREAMINFO,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
59 60 61
  /* FILL ME */
};

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

73
GST_PAD_TEMPLATE_FACTORY (src_video_templ,
Wim Taymans's avatar
Wim Taymans committed
74
  "video_%02d",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
75
  GST_PAD_SRC,
76
  GST_PAD_SOMETIMES,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
77
  GST_CAPS_NEW (
78
    "avidemux_src_video_avi",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
79 80 81 82
    "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
83 84 85 86
      		 ),
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)

Ronald S. Bultje's avatar
Ronald S. Bultje committed
87 88
  ),
  GST_CAPS_NEW (
89
    "avidemux_src_video_raw",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
90 91 92 93 94 95 96 97 98
    "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 (
99
    "avidemux_src_video_jpeg",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
100 101 102 103 104
    "video/jpeg",
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)
  ),
  GST_CAPS_NEW (
105
    "avidemux_src_video_dv",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
106 107 108 109
    "video/dv",
      "format",  GST_PROPS_LIST (
                   GST_PROPS_STRING ("NTSC"),
                   GST_PROPS_STRING ("PAL")
Ronald S. Bultje's avatar
Ronald S. Bultje committed
110 111 112
                 ),
      "width",   GST_PROPS_INT_RANGE (16, 4096),
      "height",  GST_PROPS_INT_RANGE (16, 4096)
113 114 115 116 117 118 119 120 121 122 123 124
  ),
  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
125 126 127
  )
)

128
GST_PAD_TEMPLATE_FACTORY (src_audio_templ,
Wim Taymans's avatar
Wim Taymans committed
129
  "audio_%02d",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
130
  GST_PAD_SRC,
131
  GST_PAD_SOMETIMES,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
132
  GST_CAPS_NEW (
133
    "avidemux_src_audio_avi",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
134
    "video/avi",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
135 136 137
      "format",  GST_PROPS_STRING ("strf_auds")
  ),
  GST_CAPS_NEW (
138
    "avidemux_src_audio_raw",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
139 140 141
    "audio/raw",
      "format",           GST_PROPS_STRING ("int"),
      "law",              GST_PROPS_INT (0),
142
      "endianness",       GST_PROPS_INT (G_LITTLE_ENDIAN),
Ronald S. Bultje's avatar
Ronald S. Bultje committed
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
      "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 (
159
    "avidemux_src_audio_mp3",
160
    "audio/x-mp3",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
161
      NULL
162
  ),
Wim Taymans's avatar
Wim Taymans committed
163
  GST_CAPS_NEW (
164
    "avidemux_src_audio_ac3",
Wim Taymans's avatar
Wim Taymans committed
165 166 167
    "audio/a52",
      NULL
  ),
168
  GST_CAPS_NEW (
169
    "avidemux_src_audio_vorbis",
170 171
    "application/x-ogg",
    NULL
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
172 173 174
  )
)

175 176
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
177

178
static void 		gst_avi_demux_loop 			(GstElement *element);
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
179

180
static gboolean 	gst_avi_demux_send_event 		(GstElement *element, GstEvent *event);
181

182 183 184 185
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
186
static const GstQueryType*
187
			gst_avi_demux_get_src_query_types 	(GstPad *pad);
Wim Taymans's avatar
Wim Taymans committed
188
static gboolean 	gst_avi_demux_handle_src_query 		(GstPad *pad, GstQueryType type, 
189 190 191
								 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
192

Wim Taymans's avatar
Wim Taymans committed
193
static GstElementStateReturn
194
			gst_avi_demux_change_state 		(GstElement *element);
Wim Taymans's avatar
Wim Taymans committed
195

196 197
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
198 199 200


static GstElementClass *parent_class = NULL;
201
/*static guint gst_avi_demux_signals[LAST_SIGNAL] = { 0 }; */
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
202 203 204 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

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",
236
                       G_MINLONG, G_MAXLONG, 0, G_PARAM_READABLE)); /* CHECKME */
237 238 239 240 241 242
  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
243 244 245 246

  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
247 248
  
  gstelement_class->change_state = gst_avi_demux_change_state;
249
  gstelement_class->send_event = gst_avi_demux_send_event;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
250 251 252 253 254 255 256 257
}

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 (
258
		  GST_PAD_TEMPLATE_GET (sink_templ), "sink");
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
259 260 261 262 263 264
  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*
265
avi_type_find (GstBuffer *buf,
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
266 267 268 269 270
              gpointer private)
{
  gchar *data = GST_BUFFER_DATA (buf);
  GstCaps *new;

271
  GST_DEBUG (0,"avi_demux: typefind");
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
272 273 274 275 276 277

  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;

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

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

Benjamin Otte's avatar
Benjamin Otte committed
292 293
  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
294

295
  if (got_bytes == sizeof (gst_riff_avih)) {
Wim Taymans's avatar
Wim Taymans committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
    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);

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

    return TRUE;
  }
  return FALSE;
}

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

Benjamin Otte's avatar
Benjamin Otte committed
340 341
  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
342

343
  if (got_bytes == sizeof (gst_riff_strh)) {
Wim Taymans's avatar
Wim Taymans committed
344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
    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 */

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

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

395 396
    avi_demux->avih.bufsize = MAX (avi_demux->avih.bufsize, target->strh.bufsize);

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
397 398 399 400 401
    return TRUE;
  }
  return FALSE;
}

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

Benjamin Otte's avatar
Benjamin Otte committed
410 411
  got_bytes = gst_bytestream_peek_bytes (bs, &dmlhdata, sizeof (gst_riff_dmlh));
  dmlh = (gst_riff_dmlh *) dmlhdata;
412 413
}

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

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

  GST_DEBUG (0, "Stream name: \"%s\"", name);
}

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

  props = gst_props_empty_new ();

  while (len > 0) {
Benjamin Otte's avatar
Benjamin Otte committed
444 445 446
    got_bytes = gst_bytestream_peek_bytes (bs, &tempdata, sizeof (gst_riff_chunk));
    temp_chunk = (gst_riff_chunk *) tempdata;
    
447 448 449 450 451 452
    /* 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))
453
      return;
454
    len -= sizeof (gst_riff_chunk);
455 456

    /* don't care about empty entries - move on */
457
    if (chunk.size == 0)
458 459
      continue;

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

    /* we now have an info string in 'name' of type 'chunk.id' - find 'type' */
468
    switch (chunk.id) {
469 470 471 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
      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 */
545
      entry = gst_props_entry_new (type, GST_PROPS_STRING (name));
546 547 548 549 550 551
      gst_props_add_entry (props, entry);
    }
  }

  gst_props_debug(props);

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

  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 */

569 570 571 572
  gst_caps_replace_sink (&avi_demux->streaminfo,
		  	 gst_caps_new("avi_streaminfo",
                                      "application/x-gst-streaminfo",
                                      props));
573 574 575 576

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

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

Benjamin Otte's avatar
Benjamin Otte committed
590 591
  got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_vids));
  strf = (gst_riff_strf_vids *) strfdata;
592 593
  if (got_bytes != sizeof (gst_riff_strf_vids))
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609

  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context vids");
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  size        %d", GUINT32_FROM_LE (strf->size));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  width       %d", GUINT32_FROM_LE (strf->width));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  height      %d", GUINT32_FROM_LE (strf->height));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  planes      %d", GUINT16_FROM_LE (strf->planes));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  bit_cnt     %d", GUINT16_FROM_LE (strf->bit_cnt));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  compression 0x%08x (%s)", 
		  GUINT32_FROM_LE (strf->compression), gst_riff_id_to_fourcc (strf->compression));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  image_size  %d", GUINT32_FROM_LE (strf->image_size));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  xpels_meter %d", GUINT32_FROM_LE (strf->xpels_meter));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  ypels_meter %d", GUINT32_FROM_LE (strf->ypels_meter));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  num_colors  %d", GUINT32_FROM_LE (strf->num_colors));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  imp_colors  %d", GUINT32_FROM_LE (strf->imp_colors));

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

Ronald S. Bultje's avatar
Ronald S. Bultje committed
613 614
  capslist = gst_caps_append(NULL, GST_CAPS_NEW (
			  "avidemux_video_src",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
615 616 617 618 619 620 621 622 623 624 625 626
			  "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)),
627 628
			      "imp_colors", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->imp_colors))
			      ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
629

Ronald S. Bultje's avatar
Ronald S. Bultje committed
630
  /* let's try some gstreamer-like mime-type caps */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
631 632 633 634 635 636 637 638 639 640 641
  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)
                );
642 643
      codecname = g_strdup_printf("Raw Video (%4.4s)",
                                  (char *) &strf->compression);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
644
      break;
645 646 647 648
    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
649 650 651 652 653 654
      newcaps = GST_CAPS_NEW (
                  "avidemux_video_src",
                  "video/jpeg",
                    "width",   GST_PROPS_INT(strf->width),
                    "height",  GST_PROPS_INT(strf->height)
                );
655 656 657 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
      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
697
      break;
698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
    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
716 717 718 719 720 721 722 723
    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)
                );
724 725 726 727 728 729
      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
730 731 732
      break;
  }

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

735 736 737 738 739
  /* 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
740
  gst_pad_try_set_caps (srcpad, capslist);
741 742
  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
743
  gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
744
  gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
Wim Taymans's avatar
Wim Taymans committed
745
  gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
746
  gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
Wim Taymans's avatar
Wim Taymans committed
747 748 749 750 751 752

  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
753

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
754 755 756 757 758 759 760
  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
761
  guint8 *strfdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
762
  GstPad *srcpad;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
763
  GstCaps *newcaps = NULL, *capslist = NULL;
Wim Taymans's avatar
Wim Taymans committed
764
  avi_stream_context *stream;
765 766
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;
767 768
  gchar *codecname;
  GstPropsEntry *entry;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
769

Benjamin Otte's avatar
Benjamin Otte committed
770 771
  got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_auds));
  strf = (gst_riff_strf_auds *) strfdata;
772 773
  if (got_bytes != sizeof (gst_riff_strf_auds))
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
774 775 776 777 778 779 780 781 782 783

  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context auds");
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  format      %d", GUINT16_FROM_LE (strf->format));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  channels    %d", GUINT16_FROM_LE (strf->channels));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  rate        %d", GUINT32_FROM_LE (strf->rate));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  av_bps      %d", GUINT32_FROM_LE (strf->av_bps));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  blockalign  %d", GUINT16_FROM_LE (strf->blockalign));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  size        %d", GUINT16_FROM_LE (strf->size));

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

Ronald S. Bultje's avatar
Ronald S. Bultje committed
787 788
  capslist = gst_caps_append(NULL, GST_CAPS_NEW (
			  "avidemux_audio_src",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
789 790 791 792 793 794 795
			  "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)),
796 797
			      "size",		GST_PROPS_INT (GUINT16_FROM_LE (strf->size))
			  ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
798

Ronald S. Bultje's avatar
Ronald S. Bultje committed
799 800 801
  /* let's try some gstreamer-formatted mime types */
  switch (GUINT16_FROM_LE(strf->format))
  {
802 803
    case GST_RIFF_WAVE_FORMAT_MPEGL3:
    case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp3 */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
804
      newcaps = gst_caps_new ("avidemux_audio_src",
805
                              "audio/x-mp3",
Ronald S. Bultje's avatar
Ronald S. Bultje committed
806
                                NULL);
807 808
      codecname = g_strdup_printf("MPEG/audio (0x%04x)",
                                  strf->format);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
809
      break;
810
    case GST_RIFF_WAVE_FORMAT_PCM: /* PCM/wav */
Ronald S. Bultje's avatar
Ronald S. Bultje committed
811 812 813 814 815
      newcaps = gst_caps_new ("avidemux_audio_src",
                              "audio/raw",
                              gst_props_new (
                                "format",     GST_PROPS_STRING ("int"),
                                "law",        GST_PROPS_INT (0),
816
                                "endianness", GST_PROPS_INT (G_LITTLE_ENDIAN),
Ronald S. Bultje's avatar
Ronald S. Bultje committed
817 818
                                "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
819
                                                              GUINT16_FROM_LE (strf->channels)),
Ronald S. Bultje's avatar
Ronald S. Bultje committed
820 821 822 823 824
                                "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
                              ));
825 826
      codecname = g_strdup_printf("Raw PCM/WAV (0x%04x)",
                                  strf->format);
Ronald S. Bultje's avatar
Ronald S. Bultje committed
827
      break;
828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
    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;
847 848 849 850 851 852 853 854 855
    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);
856 857
      codecname = g_strdup_printf("Ogg/Vorbis (0x%04x)",
                                  strf->format);
858
      break;
Thomas Vander Stichele's avatar
Thomas Vander Stichele committed
859
    case GST_RIFF_WAVE_FORMAT_A52:
Wim Taymans's avatar
Wim Taymans committed
860 861 862
      newcaps = gst_caps_new ("avidemux_audio_src",
                              "audio/a52",
                              NULL);
863 864
      codecname = g_strdup_printf("AC3/AC52 (0x%04x)",
                                  strf->format);
Wim Taymans's avatar
Wim Taymans committed
865 866 867
      break;
    default:
      g_warning ("avidemux: unkown audio format %d", GUINT16_FROM_LE(strf->format));
868 869
      codecname = g_strdup_printf("Unknown (0x%04x)",
                                  strf->format);
Wim Taymans's avatar
Wim Taymans committed
870
      break;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
871 872 873 874
  }

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

875 876 877 878
  /* 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
879

Ronald S. Bultje's avatar
Ronald S. Bultje committed
880
  gst_pad_try_set_caps(srcpad, capslist);
881 882
  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
883
  gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
884
  gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
Wim Taymans's avatar
Wim Taymans committed
885
  gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
886
  gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
Wim Taymans's avatar
Wim Taymans committed
887 888 889 890 891 892

  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
893

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
894 895 896 897 898 899 900
  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
901
  guint8 *strfdata;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
902
  GstPad *srcpad;
Ronald S. Bultje's avatar
Ronald S. Bultje committed
903
  GstCaps *newcaps = NULL, *capslist = NULL;
Wim Taymans's avatar
Wim Taymans committed
904
  avi_stream_context *stream;
905 906
  GstByteStream  *bs = avi_demux->bs;
  guint32 got_bytes;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
907

Benjamin Otte's avatar
Benjamin Otte committed
908 909
  got_bytes = gst_bytestream_peek_bytes (bs, &strfdata, sizeof (gst_riff_strf_iavs));
  strf = (gst_riff_strf_iavs *) strfdata;
910 911
  if (got_bytes != sizeof (gst_riff_strf_iavs))
    return;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
912 913 914 915 916 917 918 919 920 921 922 923

  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux: strf tag found in context iavs");
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxSrc   %08x", GUINT32_FROM_LE (strf->DVAAuxSrc));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxCtl   %08x", GUINT32_FROM_LE (strf->DVAAuxCtl));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxSrc1  %08x", GUINT32_FROM_LE (strf->DVAAuxSrc1));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVAAuxCtl1  %08x", GUINT32_FROM_LE (strf->DVAAuxCtl1));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVVAuxSrc   %08x", GUINT32_FROM_LE (strf->DVVAuxSrc));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVVAuxCtl   %08x", GUINT32_FROM_LE (strf->DVVAuxCtl));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVReserved1 %08x", GUINT32_FROM_LE (strf->DVReserved1));
  GST_INFO (GST_CAT_PLUGIN_INFO, "gst_avi_demux:  DVReserved2 %08x", GUINT32_FROM_LE (strf->DVReserved2));

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

Ronald S. Bultje's avatar
Ronald S. Bultje committed
927 928
  capslist = gst_caps_append(NULL, GST_CAPS_NEW (
			  "avidemux_video_src",
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
929 930 931 932 933 934 935 936 937
			  "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)),
938 939
                              "DVReserved2", 	GST_PROPS_INT (GUINT32_FROM_LE (strf->DVReserved2))
			 ));
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
940

Ronald S. Bultje's avatar
Ronald S. Bultje committed
941 942 943 944 945 946 947 948
  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
949
  gst_pad_try_set_caps(srcpad, capslist);
950 951
  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
952
  gst_pad_set_event_function (srcpad, gst_avi_demux_handle_src_event);
953
  gst_pad_set_query_type_function (srcpad, gst_avi_demux_get_src_query_types);
Wim Taymans's avatar
Wim Taymans committed
954
  gst_pad_set_query_function (srcpad, gst_avi_demux_handle_src_query);
955
  gst_pad_set_convert_function (srcpad, gst_avi_demux_src_convert);
Wim Taymans's avatar
Wim Taymans committed
956 957 958 959 960 961

  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
962

Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
963 964 965 966
  gst_element_add_pad (GST_ELEMENT (avi_demux), srcpad);
}

static void
Wim Taymans's avatar
Wim Taymans committed
967 968
gst_avi_debug_entry (const gchar *prefix, gst_avi_index_entry *entry)
{
Wim Taymans's avatar
Wim Taymans committed
969 970 971 972
  GST_DEBUG (0, "%s: %05d %d %08llx %05d %14" G_GINT64_FORMAT " %08x %08x (%d) %08x", 
		  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
973
		  entry->offset, entry->size);
Wim Taymans's avatar
Wim Taymans committed
974 975 976 977
}

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

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

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

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

Wim Taymans's avatar
Wim Taymans committed
1009 1010 1011
  id = GUINT32_FROM_LE (*(guint32 *)GST_BUFFER_DATA (buf));

  if (id != GST_RIFF_TAG_idx1) {
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1012
    GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: no index found");
Wim Taymans's avatar
Wim Taymans committed
1013
    goto end;
Andy Wingo Wingo's avatar
Andy Wingo Wingo committed
1014 1015 1016
  }

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

1019 1020
  gst_bytestream_size_hint (avi_demux->bs, index_size);

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

  avi_demux->index_size = index_size/sizeof(gst_riff_index_entry);
  GST_INFO (GST_CAT_PLUGIN_INFO, "avidemux: index size %lu", avi_demux->index_size);

Wim Taymans's avatar
Wim Taymans committed
1030 1031 1032 1033 1034 1035