5bd0898ac6402ea6244d32cbae3de7b4bdc58ef7
[platform/upstream/gst-plugins-good.git] / gst / qtdemux / qtdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include "qtdemux.h"
25
26 #include <string.h>
27 #include <zlib.h>
28
29 #define QTDEMUX_GUINT32_GET(a) GUINT32_FROM_BE(*(guint32 *)(a))
30 #define QTDEMUX_GUINT16_GET(a) GUINT16_FROM_BE(*(guint16 *)(a))
31 #define QTDEMUX_GUINT8_GET(a) (*(guint8 *)(a))
32 #define QTDEMUX_FP32_GET(a) (GUINT32_FROM_BE(*(guint16 *)(a))/65536.0)
33 #define QTDEMUX_FP16_GET(a) (GUINT16_FROM_BE(*(guint16 *)(a))/256.0)
34 #define QTDEMUX_FOURCC_GET(a) GUINT32_FROM_LE(*(guint32 *)(a))
35
36 #define QTDEMUX_GUINT64_GET(a) ((((guint64)QTDEMUX_GUINT32_GET(a))<<32)|QTDEMUX_GUINT32_GET(((void *)a)+4))
37
38 typedef struct _QtNode QtNode;
39 typedef struct _QtNodeType QtNodeType;
40 typedef struct _QtDemuxSample QtDemuxSample;
41 //typedef struct _QtDemuxStream QtDemuxStream;
42
43 struct _QtNode {
44   guint32 type;
45   gpointer data;
46   int len;
47 };
48
49 struct _QtNodeType {
50   guint32 fourcc;
51   char *name;
52   int flags;
53   void (*dump)(GstQTDemux *qtdemux, void *buffer, int depth);
54 };
55
56 struct _QtDemuxSample {
57   int sample_index;
58   int chunk;
59   int size;
60   guint32 offset;
61   guint64 timestamp;
62   guint64 duration;
63 };
64
65 struct _QtDemuxStream {
66   guint32 subtype;
67   GstCaps *caps;
68   GstPad *pad;
69   int n_samples;
70   QtDemuxSample *samples;
71   int timescale;
72
73   int sample_index;
74
75   int width;
76   int height;
77   float fps;
78   double rate;
79   int n_channels;
80 };
81
82 enum QtDemuxState {
83   QTDEMUX_STATE_NULL,
84   QTDEMUX_STATE_HEADER,
85   QTDEMUX_STATE_HEADER_SEEKING,
86   QTDEMUX_STATE_SEEKING,
87   QTDEMUX_STATE_MOVIE,
88   QTDEMUX_STATE_SEEKING_EOS,
89   QTDEMUX_STATE_EOS,
90 };
91
92 static GNode *qtdemux_tree_get_child_by_type(GNode *node, guint32 fourcc);
93 static GNode *qtdemux_tree_get_sibling_by_type(GNode *node, guint32 fourcc);
94
95 static GstElementDetails 
96 gst_qtdemux_details = 
97 {
98   "QuickTime Demuxer",
99   "Codec/Demuxer",
100   "Demultiplex a QuickTime file into audio and video streams",
101   "David Schleef <ds@schleef.org>"
102 };
103
104 enum {
105   LAST_SIGNAL
106 };
107
108 enum {
109   ARG_0
110 };
111
112 GST_PAD_TEMPLATE_FACTORY (sink_templ,
113   "sink",
114   GST_PAD_SINK,
115   GST_PAD_ALWAYS,
116   GST_CAPS_NEW (
117     "qtdemux_sink",
118     "video/quicktime",
119       NULL
120   ),
121   GST_CAPS_NEW (
122     "qtdemux_sink",
123     "audio/x-m4a",
124     NULL
125   )
126 )
127
128 static GstPadTemplate *videosrctempl, *audiosrctempl;
129 static GstElementClass *parent_class = NULL;
130
131 static void gst_qtdemux_class_init (GstQTDemuxClass *klass);
132 static void gst_qtdemux_base_init (GstQTDemuxClass *klass);
133 static void gst_qtdemux_init (GstQTDemux *quicktime_demux);
134 static GstElementStateReturn gst_qtdemux_change_state(GstElement *element);
135 static void gst_qtdemux_loop_header (GstElement *element);
136 static gboolean gst_qtdemux_handle_sink_event (GstQTDemux *qtdemux);
137
138 static void qtdemux_parse_moov(GstQTDemux *qtdemux, void *buffer, int length);
139 static void qtdemux_parse(GstQTDemux *qtdemux, GNode *node, void *buffer, int length);
140 static QtNodeType *qtdemux_type_get(guint32 fourcc);
141 static void qtdemux_node_dump(GstQTDemux *qtdemux, GNode *node);
142 static void qtdemux_parse_tree(GstQTDemux *qtdemux);
143 static GstCaps *qtdemux_video_caps(GstQTDemux *qtdemux, guint32 fourcc);
144 static GstCaps *qtdemux_audio_caps(GstQTDemux *qtdemux, guint32 fourcc);
145
146 static GType gst_qtdemux_get_type (void) 
147 {
148   static GType qtdemux_type = 0;
149
150   if (!qtdemux_type) {
151     static const GTypeInfo qtdemux_info = {
152       sizeof(GstQTDemuxClass),
153       (GBaseInitFunc)gst_qtdemux_base_init, NULL,
154       (GClassInitFunc)gst_qtdemux_class_init,
155       NULL, NULL, sizeof(GstQTDemux), 0,
156       (GInstanceInitFunc)gst_qtdemux_init,
157     };
158     qtdemux_type = g_type_register_static (GST_TYPE_ELEMENT, "GstQTDemux", &qtdemux_info, 0);
159   }
160   return qtdemux_type;
161 }
162
163 static void gst_qtdemux_base_init (GstQTDemuxClass *klass)
164 {
165   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
166
167   gst_element_class_add_pad_template (element_class,
168                 GST_PAD_TEMPLATE_GET (sink_templ));
169   gst_element_class_add_pad_template (element_class, videosrctempl);
170   gst_element_class_add_pad_template (element_class, audiosrctempl);
171   gst_element_class_set_details (element_class, &gst_qtdemux_details);
172 }
173
174 static void gst_qtdemux_class_init (GstQTDemuxClass *klass) 
175 {
176   GObjectClass *gobject_class;
177   GstElementClass *gstelement_class;
178
179   gobject_class = (GObjectClass*)klass;
180   gstelement_class = (GstElementClass*)klass;
181
182   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
183
184   gstelement_class->change_state = gst_qtdemux_change_state;
185 }
186
187 static void 
188 gst_qtdemux_init (GstQTDemux *qtdemux) 
189 {
190   qtdemux->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (sink_templ), "sink");
191   gst_element_set_loop_function (GST_ELEMENT (qtdemux), gst_qtdemux_loop_header);
192   gst_element_add_pad (GST_ELEMENT (qtdemux), qtdemux->sinkpad);
193 }
194
195 static gboolean
196 plugin_init (GstPlugin *plugin)
197 {
198   GstCaps *audiocaps = NULL, *videocaps = NULL, *temp;
199   const guint32 audio_fcc[] = {
200     /* FILLME */
201     0,
202   }, video_fcc[] = {
203     /* FILLME */
204     0,
205   };
206   gint i;
207
208   if (!gst_library_load ("gstbytestream"))
209     return FALSE;
210
211   for (i = 0; audio_fcc[i] != 0; i++) {
212     temp = qtdemux_audio_caps (NULL, audio_fcc[i]);
213     audiocaps = gst_caps_append (audiocaps, temp);
214   }
215   audiosrctempl = gst_pad_template_new ("audio_%02d",
216                                         GST_PAD_SRC,
217                                         GST_PAD_SOMETIMES,
218                                         audiocaps, NULL);
219
220   for (i = 0; video_fcc[i] != 0; i++) {
221     temp = qtdemux_video_caps (NULL, video_fcc[i]);
222     videocaps = gst_caps_append (videocaps, temp);
223   }
224   videosrctempl = gst_pad_template_new ("video_%02d",
225                                         GST_PAD_SRC,
226                                         GST_PAD_SOMETIMES,
227                                         videocaps, NULL);
228
229   return gst_element_register (plugin, "qtdemux",
230                                GST_RANK_PRIMARY, GST_TYPE_QTDEMUX);
231 }
232
233 GST_PLUGIN_DEFINE (
234   GST_VERSION_MAJOR,
235   GST_VERSION_MINOR,
236   "qtdemux",
237   "Quicktime stream demuxer",
238   plugin_init,
239   VERSION,
240   "LGPL",
241   GST_PACKAGE,
242   GST_ORIGIN
243 )
244
245 static gboolean gst_qtdemux_handle_sink_event (GstQTDemux *qtdemux)
246 {
247   guint32 remaining;
248   GstEvent *event;
249   GstEventType type;
250
251   gst_bytestream_get_status(qtdemux->bs, &remaining, &event);
252
253   type = event ? GST_EVENT_TYPE(event) : GST_EVENT_UNKNOWN;
254   GST_DEBUG ("qtdemux: event %p %d", event, type);
255
256   switch(type){
257     case GST_EVENT_EOS:
258       gst_bytestream_flush(qtdemux->bs, remaining);
259       gst_pad_event_default(qtdemux->sinkpad, event);
260       return FALSE;
261     case GST_EVENT_FLUSH:
262       g_warning("flush event");
263       break;
264     case GST_EVENT_DISCONTINUOUS:
265       GST_DEBUG ("discontinuous event\n");
266       //gst_bytestream_flush_fast(qtdemux->bs, remaining);
267       break;
268     default:
269       g_warning("unhandled event %d",type);
270       break;
271   }
272
273   gst_event_unref(event);
274   return TRUE;
275 }
276
277 static GstElementStateReturn gst_qtdemux_change_state(GstElement *element)
278 {
279   GstQTDemux *qtdemux = GST_QTDEMUX(element);
280
281   switch(GST_STATE_TRANSITION(element)){
282     case GST_STATE_NULL_TO_READY:
283       break;
284     case GST_STATE_READY_TO_PAUSED:
285       qtdemux->bs = gst_bytestream_new(qtdemux->sinkpad);
286       qtdemux->state = QTDEMUX_STATE_HEADER;
287       /* FIXME */
288       break;
289     case GST_STATE_PAUSED_TO_PLAYING:
290       break;
291     case GST_STATE_PLAYING_TO_PAUSED:
292       break;
293     case GST_STATE_PAUSED_TO_READY:
294       gst_bytestream_destroy(qtdemux->bs);
295       break;
296     case GST_STATE_READY_TO_NULL:
297       break;
298     default:
299       break;
300   }
301
302   return GST_ELEMENT_CLASS(parent_class)->change_state(element);
303 }
304
305 static void gst_qtdemux_loop_header (GstElement *element)
306 {
307   GstQTDemux *qtdemux = GST_QTDEMUX(element);
308   guint8 *data;
309   guint32 length;
310   guint32 fourcc;
311   GstBuffer *buf;
312   int offset;
313   int cur_offset;
314   int size;
315   int ret;
316
317   /* FIXME _tell gets the offset wrong */
318   //cur_offset = gst_bytestream_tell(qtdemux->bs);
319   
320   cur_offset = qtdemux->offset;
321   GST_DEBUG ("loop at position %d",cur_offset);
322
323   switch(qtdemux->state){
324   case QTDEMUX_STATE_HEADER:
325   {
326     do{
327       ret = gst_bytestream_peek_bytes(qtdemux->bs, &data, 16);
328       if(ret<16){
329         if(!gst_qtdemux_handle_sink_event(qtdemux)){
330           return;
331         }
332       }else{
333         break;
334       }
335     }while(1);
336
337     length = GUINT32_FROM_BE(*(guint32 *)data);
338     GST_DEBUG ("length %08x",length);
339     fourcc = GUINT32_FROM_LE(*(guint32 *)(data+4));
340     GST_DEBUG ("fourcc " GST_FOURCC_FORMAT, GST_FOURCC_ARGS(fourcc));
341
342     if(length==0){
343       length = gst_bytestream_length(qtdemux->bs) - cur_offset;
344     }
345     if(length==1){
346       guint32 length1, length2;
347   
348       length1 = GUINT32_FROM_BE(*(guint32 *)(data+8));
349       GST_DEBUG ("length1 %08x",length1);
350       length2 = GUINT32_FROM_BE(*(guint32 *)(data+12));
351       GST_DEBUG ("length2 %08x",length2);
352   
353       length=length2;
354     }
355   
356     switch(fourcc){
357       case GST_MAKE_FOURCC('m','d','a','t'):
358       case GST_MAKE_FOURCC('f','r','e','e'):
359       case GST_MAKE_FOURCC('w','i','d','e'):
360       case GST_MAKE_FOURCC('P','I','C','T'):
361       case GST_MAKE_FOURCC('p','n','o','t'):
362         break;
363       case GST_MAKE_FOURCC('m','o','o','v'):
364       {
365         GstBuffer *moov;
366   
367         do{
368           ret = gst_bytestream_read(qtdemux->bs, &moov, length);
369           if(ret < length){
370             GST_DEBUG ("read failed (%d < %d)",ret,length);
371             if(!gst_qtdemux_handle_sink_event(qtdemux)){
372               return;
373             }
374           }else{
375             break;
376           }
377         }while(1);
378
379         qtdemux_parse_moov(qtdemux, GST_BUFFER_DATA(moov), length);
380         if(1)qtdemux_node_dump(qtdemux, qtdemux->moov_node);
381         qtdemux_parse_tree(qtdemux);
382         qtdemux->state = QTDEMUX_STATE_MOVIE;
383         break;
384       }
385       default:
386       {
387         g_print("unknown %08x '" GST_FOURCC_FORMAT "' at %d\n",
388             fourcc, GST_FOURCC_ARGS(fourcc), cur_offset);
389         break;
390       }
391     }
392     ret = gst_bytestream_seek(qtdemux->bs, cur_offset + length,
393         GST_SEEK_METHOD_SET);
394     qtdemux->offset = cur_offset + length;
395     GST_DEBUG ("seek returned %d\n",ret);
396     break;
397   }
398   case QTDEMUX_STATE_SEEKING_EOS:
399   {
400     guint8 *data;
401
402     do{
403       ret = gst_bytestream_peek_bytes(qtdemux->bs, &data, 1);
404       if(ret<1){
405         if(!gst_qtdemux_handle_sink_event(qtdemux)){
406           return;
407         }
408       }else{
409         break;
410       }
411     }while(TRUE);
412     gst_element_set_eos(element);
413
414     qtdemux->state = QTDEMUX_STATE_EOS;
415     return;
416   }
417   case QTDEMUX_STATE_EOS:
418     g_warning("spinning in EOS\n");
419     return;
420   case QTDEMUX_STATE_MOVIE:
421   {
422     QtDemuxStream *stream;
423     guint64 min_time;
424     int index = -1;
425     int i;
426
427     min_time = G_MAXUINT64;
428     for(i=0;i<qtdemux->n_streams;i++){
429       stream = qtdemux->streams[i];
430
431       if(stream->sample_index < stream->n_samples &&
432           stream->samples[stream->sample_index].timestamp < min_time){
433         min_time = stream->samples[stream->sample_index].timestamp;
434         index = i;
435       }
436     }
437
438     if(index==-1){
439       for(i=0;i<qtdemux->n_streams;i++){
440         gst_pad_push(qtdemux->streams[i]->pad,
441             GST_DATA(gst_event_new (GST_EVENT_EOS)));
442       }
443       ret = gst_bytestream_seek(qtdemux->bs, 0, GST_SEEK_METHOD_END);
444       GST_DEBUG ("seek returned %d",ret);
445
446       qtdemux->state = QTDEMUX_STATE_SEEKING_EOS;
447       return;
448     }
449
450     stream = qtdemux->streams[index];
451
452     offset = stream->samples[stream->sample_index].offset;
453     size = stream->samples[stream->sample_index].size;
454
455     GST_DEBUG ("pushing from stream %d, sample_index=%d offset=%d size=%d",
456         index, stream->sample_index, offset, size);
457
458     cur_offset = gst_bytestream_tell(qtdemux->bs);
459     if(offset != cur_offset){
460       GST_DEBUG ("seeking to offset %d",offset);
461       ret = gst_bytestream_seek(qtdemux->bs, offset, GST_SEEK_METHOD_SET);
462       GST_DEBUG ("seek returned %d",ret);
463       return;
464     }
465
466     GST_DEBUG ("reading %d bytes\n",size);
467     buf = NULL;
468     do{
469       ret = gst_bytestream_read(qtdemux->bs, &buf, size);
470       if(ret < size){
471         GST_DEBUG ("read failed (%d < %d)",ret,size);
472         if(!gst_qtdemux_handle_sink_event(qtdemux)){
473           return;
474         }
475       }else{
476         break;
477       }
478     }while(TRUE);
479
480     if(buf){
481       /* hum... */
482       if(stream->subtype == GST_MAKE_FOURCC('v','i','d','e')){
483         float fps = 1. * GST_SECOND / stream->samples[stream->sample_index].duration;
484         if (fps != stream->fps) {
485           gst_props_remove_entry_by_name(stream->caps->properties, "framerate");
486           gst_props_add_entry(stream->caps->properties,
487                               gst_props_entry_new("framerate", GST_PROPS_FLOAT(fps)));
488           stream->fps = fps;
489           gst_pad_try_set_caps(stream->pad, stream->caps);
490         }
491       }
492
493       GST_BUFFER_TIMESTAMP(buf) = stream->samples[stream->sample_index].timestamp;
494       GST_BUFFER_DURATION(buf) = stream->samples[stream->sample_index].duration;
495       gst_pad_push(stream->pad, GST_DATA (buf));
496     }
497     stream->sample_index++;
498     break;
499   }
500   default:
501     /* unreached */
502     g_assert(0);
503   }
504
505 }
506
507 static GstCaps *gst_qtdemux_src_getcaps(GstPad *pad, GstCaps *caps)
508 {
509   GstQTDemux *qtdemux;
510   QtDemuxStream *stream;
511   int i;
512
513   GST_DEBUG ("gst_qtdemux_src_getcaps");
514
515   qtdemux = GST_QTDEMUX(gst_pad_get_parent(pad));
516
517   g_return_val_if_fail(GST_IS_QTDEMUX(qtdemux), NULL);
518
519   GST_DEBUG ("looking for pad %p in qtdemux %p", pad, qtdemux);
520   GST_DEBUG ("n_streams is %d", qtdemux->n_streams);
521   for(i=0;i<qtdemux->n_streams;i++){
522     stream = qtdemux->streams[i];
523     if(stream->pad == pad){
524       return stream->caps;
525     }
526   }
527
528   GST_DEBUG ("Couldn't find stream cooresponding to pad\n");
529
530   return NULL;
531 }
532
533 static GstPadLinkReturn
534 gst_qtdemux_src_link(GstPad *pad, GstCaps *caps)
535 {
536   GstQTDemux *qtdemux;
537   QtDemuxStream *stream;
538   int i;
539
540   GST_DEBUG ("gst_qtdemux_src_link");
541
542   qtdemux = GST_QTDEMUX(gst_pad_get_parent(pad));
543
544   GST_DEBUG ("looking for pad %p in qtdemux %p", pad, qtdemux);
545   g_return_val_if_fail(GST_IS_QTDEMUX(qtdemux), GST_PAD_LINK_REFUSED);
546
547   GST_DEBUG ("n_streams is %d", qtdemux->n_streams);
548   for(i=0;i<qtdemux->n_streams;i++){
549     stream = qtdemux->streams[i];
550     GST_DEBUG ("pad[%d] is %p", i, stream->pad);
551     if(stream->pad == pad){
552       return GST_PAD_LINK_OK;
553     }
554   }
555
556   GST_DEBUG ("Couldn't find stream cooresponding to pad\n");
557
558   return GST_PAD_LINK_REFUSED;
559 }
560
561 void gst_qtdemux_add_stream(GstQTDemux *qtdemux, QtDemuxStream *stream)
562 {
563   if(stream->subtype == GST_MAKE_FOURCC('v','i','d','e')){
564     stream->pad = gst_pad_new_from_template (videosrctempl,
565         g_strdup_printf ("video_%02d", qtdemux->n_video_streams));
566     stream->fps = 1. * GST_SECOND / stream->samples[0].duration;
567     if(stream->caps){
568       GstProps *properties = gst_props_intersect(
569           stream->caps->properties,
570           gst_props_new("width",GST_PROPS_INT(stream->width),
571               "height",GST_PROPS_INT(stream->height),
572               "framerate", GST_PROPS_FLOAT(stream->fps), NULL));
573       if (stream->caps->properties != NULL)
574         gst_props_unref (stream->caps->properties);
575       stream->caps->properties = properties;
576     }
577     qtdemux->n_video_streams++;
578   }else{
579     stream->pad = gst_pad_new_from_template (audiosrctempl,
580         g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams));
581     if(stream->caps){
582       GstProps *properties = gst_props_intersect(
583           stream->caps->properties,
584           gst_props_new("rate",GST_PROPS_INT((int)stream->rate),
585               "channels",GST_PROPS_INT(stream->n_channels), NULL));
586       if (stream->caps->properties != NULL)
587         gst_props_unref (stream->caps->properties);
588       stream->caps->properties = properties;
589     }
590     qtdemux->n_audio_streams++;
591   }
592
593   gst_pad_set_getcaps_function(stream->pad, gst_qtdemux_src_getcaps);
594   gst_pad_set_link_function(stream->pad, gst_qtdemux_src_link);
595
596   qtdemux->streams[qtdemux->n_streams] = stream;
597   qtdemux->n_streams++;
598   GST_DEBUG ("n_streams is now %d", qtdemux->n_streams);
599
600   GST_DEBUG ("adding pad %p to qtdemux %p", stream->pad, qtdemux);
601   gst_element_add_pad(GST_ELEMENT (qtdemux), stream->pad);
602
603   /* Note: we need to have everything set up before calling try_set_caps */
604   if(stream->caps){
605     g_print("setting caps to %s\n",gst_caps_to_string(stream->caps));
606
607     gst_pad_try_set_caps(stream->pad, stream->caps);
608   }
609 }
610
611
612 #define QT_CONTAINER 1
613
614 #define FOURCC_moov     GST_MAKE_FOURCC('m','o','o','v')
615 #define FOURCC_mvhd     GST_MAKE_FOURCC('m','v','h','d')
616 #define FOURCC_clip     GST_MAKE_FOURCC('c','l','i','p')
617 #define FOURCC_trak     GST_MAKE_FOURCC('t','r','a','k')
618 #define FOURCC_udta     GST_MAKE_FOURCC('u','d','t','a')
619 #define FOURCC_ctab     GST_MAKE_FOURCC('c','t','a','b')
620 #define FOURCC_tkhd     GST_MAKE_FOURCC('t','k','h','d')
621 #define FOURCC_crgn     GST_MAKE_FOURCC('c','r','g','n')
622 #define FOURCC_matt     GST_MAKE_FOURCC('m','a','t','t')
623 #define FOURCC_kmat     GST_MAKE_FOURCC('k','m','a','t')
624 #define FOURCC_edts     GST_MAKE_FOURCC('e','d','t','s')
625 #define FOURCC_elst     GST_MAKE_FOURCC('e','l','s','t')
626 #define FOURCC_load     GST_MAKE_FOURCC('l','o','a','d')
627 #define FOURCC_tref     GST_MAKE_FOURCC('t','r','e','f')
628 #define FOURCC_imap     GST_MAKE_FOURCC('i','m','a','p')
629 #define FOURCC___in     GST_MAKE_FOURCC(' ',' ','i','n')
630 #define FOURCC___ty     GST_MAKE_FOURCC(' ',' ','t','y')
631 #define FOURCC_mdia     GST_MAKE_FOURCC('m','d','i','a')
632 #define FOURCC_mdhd     GST_MAKE_FOURCC('m','d','h','d')
633 #define FOURCC_hdlr     GST_MAKE_FOURCC('h','d','l','r')
634 #define FOURCC_minf     GST_MAKE_FOURCC('m','i','n','f')
635 #define FOURCC_vmhd     GST_MAKE_FOURCC('v','m','h','d')
636 #define FOURCC_smhd     GST_MAKE_FOURCC('s','m','h','d')
637 #define FOURCC_gmhd     GST_MAKE_FOURCC('g','m','h','d')
638 #define FOURCC_gmin     GST_MAKE_FOURCC('g','m','i','n')
639 #define FOURCC_dinf     GST_MAKE_FOURCC('d','i','n','f')
640 #define FOURCC_dref     GST_MAKE_FOURCC('d','r','e','f')
641 #define FOURCC_stbl     GST_MAKE_FOURCC('s','t','b','l')
642 #define FOURCC_stsd     GST_MAKE_FOURCC('s','t','s','d')
643 #define FOURCC_stts     GST_MAKE_FOURCC('s','t','t','s')
644 #define FOURCC_stss     GST_MAKE_FOURCC('s','t','s','s')
645 #define FOURCC_stsc     GST_MAKE_FOURCC('s','t','s','c')
646 #define FOURCC_stsz     GST_MAKE_FOURCC('s','t','s','z')
647 #define FOURCC_stco     GST_MAKE_FOURCC('s','t','c','o')
648 #define FOURCC_vide     GST_MAKE_FOURCC('v','i','d','e')
649 #define FOURCC_soun     GST_MAKE_FOURCC('s','o','u','n')
650 #define FOURCC_co64     GST_MAKE_FOURCC('c','o','6','4')
651 #define FOURCC_cmov     GST_MAKE_FOURCC('c','m','o','v')
652 #define FOURCC_dcom     GST_MAKE_FOURCC('d','c','o','m')
653 #define FOURCC_cmvd     GST_MAKE_FOURCC('c','m','v','d')
654
655
656 static void qtdemux_dump_mvhd(GstQTDemux *qtdemux, void *buffer, int depth);
657 static void qtdemux_dump_tkhd(GstQTDemux *qtdemux, void *buffer, int depth);
658 static void qtdemux_dump_elst(GstQTDemux *qtdemux, void *buffer, int depth);
659 static void qtdemux_dump_mdhd(GstQTDemux *qtdemux, void *buffer, int depth);
660 static void qtdemux_dump_hdlr(GstQTDemux *qtdemux, void *buffer, int depth);
661 static void qtdemux_dump_vmhd(GstQTDemux *qtdemux, void *buffer, int depth);
662 static void qtdemux_dump_dref(GstQTDemux *qtdemux, void *buffer, int depth);
663 static void qtdemux_dump_stsd(GstQTDemux *qtdemux, void *buffer, int depth);
664 static void qtdemux_dump_stts(GstQTDemux *qtdemux, void *buffer, int depth);
665 static void qtdemux_dump_stss(GstQTDemux *qtdemux, void *buffer, int depth);
666 static void qtdemux_dump_stsc(GstQTDemux *qtdemux, void *buffer, int depth);
667 static void qtdemux_dump_stsz(GstQTDemux *qtdemux, void *buffer, int depth);
668 static void qtdemux_dump_stco(GstQTDemux *qtdemux, void *buffer, int depth);
669 static void qtdemux_dump_co64(GstQTDemux *qtdemux, void *buffer, int depth);
670 static void qtdemux_dump_dcom(GstQTDemux *qtdemux, void *buffer, int depth);
671 static void qtdemux_dump_cmvd(GstQTDemux *qtdemux, void *buffer, int depth);
672
673 QtNodeType qt_node_types[] = {
674   { FOURCC_moov, "movie",               QT_CONTAINER, },
675   { FOURCC_mvhd, "movie header",        0,
676         qtdemux_dump_mvhd },
677   { FOURCC_clip, "clipping",            QT_CONTAINER, },
678   { FOURCC_trak, "track",               QT_CONTAINER, },
679   { FOURCC_udta, "user data",           0, }, /* special container */
680   { FOURCC_ctab, "color table",         0, },
681   { FOURCC_tkhd, "track header",        0,
682         qtdemux_dump_tkhd },
683   { FOURCC_crgn, "clipping region",     0, },
684   { FOURCC_matt, "track matte",         QT_CONTAINER, },
685   { FOURCC_kmat, "compressed matte",    0, },
686   { FOURCC_edts, "edit",                QT_CONTAINER, },
687   { FOURCC_elst, "edit list",           0,
688         qtdemux_dump_elst },
689   { FOURCC_load, "track load settings", 0, },
690   { FOURCC_tref, "track reference",     QT_CONTAINER, },
691   { FOURCC_imap, "track input map",     QT_CONTAINER, },
692   { FOURCC___in, "track input",         0, }, /* special container */
693   { FOURCC___ty, "input type",          0, },
694   { FOURCC_mdia, "media",               QT_CONTAINER },
695   { FOURCC_mdhd, "media header",        0,
696         qtdemux_dump_mdhd },
697   { FOURCC_hdlr, "handler reference",   0,
698         qtdemux_dump_hdlr },
699   { FOURCC_minf, "media information",   QT_CONTAINER },
700   { FOURCC_vmhd, "video media information", 0,
701         qtdemux_dump_vmhd },
702   { FOURCC_smhd, "sound media information", 0 },
703   { FOURCC_gmhd, "base media information header", 0 },
704   { FOURCC_gmin, "base media info",     0 },
705   { FOURCC_dinf, "data information",    QT_CONTAINER },
706   { FOURCC_dref, "data reference",      0,
707         qtdemux_dump_dref },
708   { FOURCC_stbl, "sample table",        QT_CONTAINER },
709   { FOURCC_stsd, "sample description",  0,
710         qtdemux_dump_stsd },
711   { FOURCC_stts, "time-to-sample",      0,
712         qtdemux_dump_stts },
713   { FOURCC_stss, "sync sample",         0,
714         qtdemux_dump_stss },
715   { FOURCC_stsc, "sample-to-chunk",     0,
716         qtdemux_dump_stsc },
717   { FOURCC_stsz, "sample size",         0,
718         qtdemux_dump_stsz },
719   { FOURCC_stco, "chunk offset",        0,
720         qtdemux_dump_stco },
721   { FOURCC_co64, "64-bit chunk offset", 0,
722         qtdemux_dump_co64 },
723   { FOURCC_vide, "video media",         0 },
724   { FOURCC_cmov, "compressed movie",    QT_CONTAINER },
725   { FOURCC_dcom, "compressed data",     0,
726         qtdemux_dump_dcom },
727   { FOURCC_cmvd, "compressed movie data", 0,
728         qtdemux_dump_cmvd },
729   { 0, "unknown", 0 },
730 };
731 static int n_qt_node_types = sizeof(qt_node_types)/sizeof(qt_node_types[0]);
732
733
734 static void *qtdemux_zalloc(void *opaque, unsigned int items, unsigned int size)
735 {
736   return g_malloc(items*size);
737 }
738
739 static void qtdemux_zfree(void *opaque, void *addr)
740 {
741   g_free(addr);
742 }
743
744 static void *qtdemux_inflate(void *z_buffer, int z_length, int length)
745 {
746   void *buffer;
747   z_stream *z;
748   int ret;
749
750   z = g_new0(z_stream, 1);
751   z->zalloc = qtdemux_zalloc;
752   z->zfree = qtdemux_zfree;
753   z->opaque = NULL;
754
755   z->next_in = z_buffer;
756   z->avail_in = z_length;
757
758   buffer = g_malloc(length);
759   ret = inflateInit(z);
760   while(z->avail_in > 0){
761     if(z->avail_out == 0){
762       length += 1024;
763       buffer = realloc(buffer, length);
764       z->next_out = buffer + z->total_out;
765       z->avail_out = 1024;
766     }
767     ret = inflate(z,Z_SYNC_FLUSH);
768     if(ret != Z_OK)break;
769   }
770   if(ret != Z_STREAM_END){
771     g_warning("inflate() returned %d\n",ret);
772   }
773
774   g_free(z);
775   return buffer;
776 }
777
778 static void qtdemux_parse_moov(GstQTDemux *qtdemux, void *buffer, int length)
779 {
780   GNode *cmov;
781
782   qtdemux->moov_node = g_node_new(buffer);
783
784   qtdemux_parse(qtdemux, qtdemux->moov_node, buffer, length);
785
786   cmov = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_cmov);
787   if(cmov){
788     GNode *dcom;
789     GNode *cmvd;
790
791     dcom = qtdemux_tree_get_child_by_type(cmov, FOURCC_dcom);
792     cmvd = qtdemux_tree_get_child_by_type(cmov, FOURCC_cmvd);
793
794     if(QTDEMUX_FOURCC_GET(dcom->data+8) == GST_MAKE_FOURCC('z','l','i','b')){
795       int uncompressed_length;
796       int compressed_length;
797       void *buf;
798       
799       uncompressed_length = QTDEMUX_GUINT32_GET(cmvd->data+8);
800       compressed_length = QTDEMUX_GUINT32_GET(cmvd->data+4) - 12;
801       g_print("length = %d\n",uncompressed_length);
802
803       buf = qtdemux_inflate(cmvd->data + 12, compressed_length,
804           uncompressed_length);
805
806       qtdemux->moov_node_compressed = qtdemux->moov_node;
807       qtdemux->moov_node = g_node_new(buf);
808
809       qtdemux_parse(qtdemux, qtdemux->moov_node, buf, uncompressed_length);
810     }else{
811       g_print("unknown header compression type\n");
812     }
813   }
814 }
815
816 static void qtdemux_parse(GstQTDemux *qtdemux, GNode *node, void *buffer, int length)
817 {
818   guint32 fourcc;
819   guint32 node_length;
820   QtNodeType *type;
821   void *end;
822
823   //g_print("qtdemux_parse %p %d\n",buffer, length);
824
825   node_length = QTDEMUX_GUINT32_GET(buffer);
826   fourcc = QTDEMUX_FOURCC_GET(buffer+4);
827
828   type = qtdemux_type_get(fourcc);
829   
830   /*g_print("parsing '" GST_FOURCC_FORMAT "', length=%d\n",
831       GST_FOURCC_ARGS(fourcc), node_length);*/
832
833   if(type->flags & QT_CONTAINER){
834     void *buf;
835     guint32 len;
836
837     buf = buffer + 8;
838     end = buffer + length;
839     while(buf < end){
840       GNode *child;
841
842       if(buf + 8 >= end){
843         /* FIXME: get annoyed */
844         g_print("buffer overrun\n");
845       }
846       len = QTDEMUX_GUINT32_GET(buf);
847
848       child = g_node_new(buf);
849       g_node_append(node, child);
850       qtdemux_parse(qtdemux, child, buf, len);
851
852       buf += len;
853     }
854   }else{
855 #if 0
856     if(fourcc == FOURCC_cmvd){
857       int uncompressed_length;
858       void *buf;
859       
860       uncompressed_length = QTDEMUX_GUINT32_GET(buffer+8);
861       g_print("length = %d\n",uncompressed_length);
862
863       buf = qtdemux_inflate(buffer + 12, node_length-12, uncompressed_length);
864
865       end = buf + uncompressed_length;
866       while(buf < end){
867         GNode *child;
868         guint32 len;
869
870         if(buf + 8 >= end){
871           /* FIXME: get annoyed */
872           g_print("buffer overrun\n");
873         }
874         len = QTDEMUX_GUINT32_GET(buf);
875
876         child = g_node_new(buf);
877         g_node_append(node, child);
878         qtdemux_parse(qtdemux, child, buf, len);
879
880         buf += len;
881       }
882     }
883 #endif
884   }
885 }
886
887 static QtNodeType *qtdemux_type_get(guint32 fourcc)
888 {
889   int i;
890
891   for(i=0;i<n_qt_node_types;i++){
892     if(qt_node_types[i].fourcc == fourcc)
893       return qt_node_types+i;
894   }
895   return qt_node_types+n_qt_node_types-1;
896 }
897
898 static gboolean qtdemux_node_dump_foreach(GNode *node, gpointer data)
899 {
900   void *buffer = node->data;
901   guint32 node_length;
902   guint32 fourcc;
903   QtNodeType *type;
904   int depth;
905
906   node_length = GUINT32_FROM_BE(*(guint32 *)buffer);
907   fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
908
909   type = qtdemux_type_get(fourcc);
910
911   depth = (g_node_depth(node)-1)*2;
912   g_print("%*s'" GST_FOURCC_FORMAT "', [%d], %s\n",
913       depth, "",
914       GST_FOURCC_ARGS(fourcc),
915       node_length,
916       type->name);
917
918   if(type->dump)type->dump(data, buffer, depth);
919
920   return FALSE;
921 }
922
923 static void qtdemux_node_dump(GstQTDemux *qtdemux, GNode *node)
924 {
925   g_node_traverse(qtdemux->moov_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
926       qtdemux_node_dump_foreach, qtdemux);
927 }
928
929 static void qtdemux_dump_mvhd(GstQTDemux *qtdemux, void *buffer, int depth)
930 {
931   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
932   g_print("%*s  creation time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
933   g_print("%*s  modify time:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
934   g_print("%*s  time scale:    1/%u sec\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20));
935   g_print("%*s  duration:      %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+24));
936   g_print("%*s  pref. rate:    %g\n", depth, "", QTDEMUX_FP32_GET(buffer+28));
937   g_print("%*s  pref. volume:  %g\n", depth, "", QTDEMUX_FP16_GET(buffer+32));
938   g_print("%*s  preview time:  %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+80));
939   g_print("%*s  preview dur.:  %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+84));
940   g_print("%*s  poster time:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+88));
941   g_print("%*s  select time:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+92));
942   g_print("%*s  select dur.:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+96));
943   g_print("%*s  current time:  %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+100));
944   g_print("%*s  next track ID: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+104));
945 }
946
947 static void qtdemux_dump_tkhd(GstQTDemux *qtdemux, void *buffer, int depth)
948 {
949   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
950   g_print("%*s  creation time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
951   g_print("%*s  modify time:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
952   g_print("%*s  track ID:      %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20));
953   g_print("%*s  duration:      %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+28));
954   g_print("%*s  layer:         %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+36));
955   g_print("%*s  alt group:     %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+38));
956   g_print("%*s  volume:        %g\n", depth, "", QTDEMUX_FP16_GET(buffer+44));
957   g_print("%*s  track width:   %g\n", depth, "", QTDEMUX_FP32_GET(buffer+84));
958   g_print("%*s  track height:  %g\n", depth, "", QTDEMUX_FP32_GET(buffer+88));
959
960 }
961
962 static void qtdemux_dump_elst(GstQTDemux *qtdemux, void *buffer, int depth)
963 {
964   int i;
965   int n;
966
967   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
968   g_print("%*s  n entries:     %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
969   n = QTDEMUX_GUINT32_GET(buffer+12);
970   for(i=0;i<n;i++){
971     g_print("%*s    track dur:     %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16+i*12));
972     g_print("%*s    media time:    %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20+i*12));
973     g_print("%*s    media rate:    %g\n", depth, "", QTDEMUX_FP32_GET(buffer+24+i*12));
974   }
975 }
976
977 static void qtdemux_dump_mdhd(GstQTDemux *qtdemux, void *buffer, int depth)
978 {
979   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
980   g_print("%*s  creation time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
981   g_print("%*s  modify time:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
982   g_print("%*s  time scale:    1/%u sec\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20));
983   g_print("%*s  duration:      %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+24));
984   g_print("%*s  language:      %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+28));
985   g_print("%*s  quality:       %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+30));
986
987 }
988
989 static void qtdemux_dump_hdlr(GstQTDemux *qtdemux, void *buffer, int depth)
990 {
991   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
992   g_print("%*s  type:          " GST_FOURCC_FORMAT "\n", depth, "",
993       GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+12)));
994   g_print("%*s  subtype:       " GST_FOURCC_FORMAT "\n", depth, "",
995       GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+16)));
996   g_print("%*s  manufacturer:  " GST_FOURCC_FORMAT "\n", depth, "",
997       GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+20)));
998   g_print("%*s  flags:         %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+24));
999   g_print("%*s  flags mask:    %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+28));
1000   g_print("%*s  name:          %*s\n", depth, "",
1001       QTDEMUX_GUINT8_GET(buffer+32), (char *)(buffer+33));
1002
1003 }
1004
1005 static void qtdemux_dump_vmhd(GstQTDemux *qtdemux, void *buffer, int depth)
1006 {
1007   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1008   g_print("%*s  mode/color:    %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
1009 }
1010
1011 static void qtdemux_dump_dref(GstQTDemux *qtdemux, void *buffer, int depth)
1012 {
1013   int n;
1014   int i;
1015   int offset;
1016
1017   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1018   g_print("%*s  n entries:     %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1019   n = QTDEMUX_GUINT32_GET(buffer+12);
1020   offset = 16;
1021   for(i=0;i<n;i++){
1022     g_print("%*s    size:          %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1023     g_print("%*s    type:          " GST_FOURCC_FORMAT "\n", depth, "",
1024         GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+offset+4)));
1025     offset += QTDEMUX_GUINT32_GET(buffer+offset);
1026   }
1027 }
1028
1029 static void qtdemux_dump_stsd(GstQTDemux *qtdemux, void *buffer, int depth)
1030 {
1031   int i;
1032   int n;
1033   int offset;
1034
1035   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1036   g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1037   n = QTDEMUX_GUINT32_GET(buffer+12);
1038   offset = 16;
1039   for(i=0;i<n;i++){
1040     g_print("%*s    size:          %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1041     g_print("%*s    type:          " GST_FOURCC_FORMAT "\n", depth, "",
1042         GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+offset+4)));
1043     g_print("%*s    data reference:%d\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+14));
1044
1045     g_print("%*s    version/rev.:  %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+16));
1046     g_print("%*s    vendor:        " GST_FOURCC_FORMAT "\n", depth, "",
1047         GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+offset+20)));
1048     g_print("%*s    temporal qual: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+24));
1049     g_print("%*s    spatial qual:  %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+28));
1050     g_print("%*s    width:         %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+32));
1051     g_print("%*s    height:        %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+34));
1052     g_print("%*s    horiz. resol:  %g\n", depth, "", QTDEMUX_FP32_GET(buffer+offset+36));
1053     g_print("%*s    vert. resol.:  %g\n", depth, "", QTDEMUX_FP32_GET(buffer+offset+40));
1054     g_print("%*s    data size:     %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+44));
1055     g_print("%*s    frame count:   %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+48));
1056     g_print("%*s    compressor:    %*s\n", depth, "",
1057         QTDEMUX_GUINT8_GET(buffer+offset+49), (char *)(buffer+offset+51));
1058     g_print("%*s    depth:         %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+82));
1059     g_print("%*s    color table ID:%u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+84));
1060
1061     offset += QTDEMUX_GUINT32_GET(buffer+offset);
1062   }
1063 }
1064
1065 static void qtdemux_dump_stts(GstQTDemux *qtdemux, void *buffer, int depth)
1066 {
1067   int i;
1068   int n;
1069   int offset;
1070
1071   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1072   g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1073   n = QTDEMUX_GUINT32_GET(buffer+12);
1074   offset = 16;
1075   for(i=0;i<n;i++){
1076     g_print("%*s    count:         %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1077     g_print("%*s    duration:      %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset + 4));
1078
1079     offset += 8;
1080   }
1081 }
1082
1083 static void qtdemux_dump_stss(GstQTDemux *qtdemux, void *buffer, int depth)
1084 {
1085   int i;
1086   int n;
1087   int offset;
1088
1089   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1090   g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1091   n = QTDEMUX_GUINT32_GET(buffer+12);
1092   offset = 16;
1093   for(i=0;i<n;i++){
1094     g_print("%*s    sample:        %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1095
1096     offset += 4;
1097   }
1098 }
1099
1100 static void qtdemux_dump_stsc(GstQTDemux *qtdemux, void *buffer, int depth)
1101 {
1102   int i;
1103   int n;
1104   int offset;
1105
1106   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1107   g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1108   n = QTDEMUX_GUINT32_GET(buffer+12);
1109   offset = 16;
1110   for(i=0;i<n;i++){
1111     g_print("%*s    first chunk:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1112     g_print("%*s    sample per ch: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+4));
1113     g_print("%*s    sample desc id:%08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+8));
1114
1115     offset += 12;
1116   }
1117 }
1118
1119 static void qtdemux_dump_stsz(GstQTDemux *qtdemux, void *buffer, int depth)
1120 {
1121   int i;
1122   int n;
1123   int offset;
1124   int sample_size;
1125
1126   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1127   g_print("%*s  sample size:   %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1128   sample_size = QTDEMUX_GUINT32_GET(buffer+12);
1129   if(sample_size == 0){
1130     g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
1131     n = QTDEMUX_GUINT32_GET(buffer+16);
1132     offset = 20;
1133     for(i=0;i<n;i++){
1134       g_print("%*s    sample size:   %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1135
1136       offset += 4;
1137     }
1138   }
1139 }
1140
1141 static void qtdemux_dump_stco(GstQTDemux *qtdemux, void *buffer, int depth)
1142 {
1143   int i;
1144   int n;
1145   int offset;
1146
1147   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1148   g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1149   n = QTDEMUX_GUINT32_GET(buffer+12);
1150   offset = 16;
1151   for(i=0;i<n;i++){
1152     g_print("%*s    chunk offset:  %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1153
1154     offset += 4;
1155   }
1156 }
1157
1158 static void qtdemux_dump_co64(GstQTDemux *qtdemux, void *buffer, int depth)
1159 {
1160   int i;
1161   int n;
1162   int offset;
1163
1164   g_print("%*s  version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1165   g_print("%*s  n entries:     %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1166   n = QTDEMUX_GUINT32_GET(buffer+12);
1167   offset = 16;
1168   for(i=0;i<n;i++){
1169     g_print("%*s    chunk offset:  %" G_GUINT64_FORMAT "\n", depth, "", QTDEMUX_GUINT64_GET(buffer+offset));
1170
1171     offset += 8;
1172   }
1173 }
1174
1175 static void qtdemux_dump_dcom(GstQTDemux *qtdemux, void *buffer, int depth)
1176 {
1177   g_print("%*s  compression type: " GST_FOURCC_FORMAT "\n", depth, "",
1178       GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+8)));
1179 }
1180
1181 static void qtdemux_dump_cmvd(GstQTDemux *qtdemux, void *buffer, int depth)
1182 {
1183   g_print("%*s  length: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1184 }
1185
1186
1187 static GNode *qtdemux_tree_get_child_by_type(GNode *node, guint32 fourcc)
1188 {
1189   GNode *child;
1190   void *buffer;
1191   guint32 child_fourcc;
1192
1193   for(child = g_node_first_child(node); child; child = g_node_next_sibling(child)){
1194     buffer = child->data;
1195
1196     child_fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
1197
1198     if(child_fourcc == fourcc){
1199       return child;
1200     }
1201   }
1202   return NULL;
1203 }
1204
1205 static GNode *qtdemux_tree_get_sibling_by_type(GNode *node, guint32 fourcc)
1206 {
1207   GNode *child;
1208   void *buffer;
1209   guint32 child_fourcc;
1210
1211   for(child = g_node_next_sibling(node); child; child = g_node_next_sibling(child)){
1212     buffer = child->data;
1213
1214     child_fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
1215
1216     if(child_fourcc == fourcc){
1217       return child;
1218     }
1219   }
1220   return NULL;
1221 }
1222
1223 static void qtdemux_parse_trak(GstQTDemux *qtdemux, GNode *trak);
1224
1225 static void qtdemux_parse_tree(GstQTDemux *qtdemux)
1226 {
1227   GNode *mvhd;
1228   GNode *trak;
1229
1230   mvhd = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_mvhd);
1231   if(mvhd==NULL){
1232     g_print("No mvhd node found.\n");
1233     return;
1234   }
1235
1236   qtdemux->timescale = QTDEMUX_GUINT32_GET(mvhd->data + 20);
1237   qtdemux->duration = QTDEMUX_GUINT32_GET(mvhd->data + 24);
1238
1239   g_print("timescale: %d\n", qtdemux->timescale);
1240   g_print("duration: %d\n", qtdemux->duration);
1241
1242   trak = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_trak);
1243   qtdemux_parse_trak(qtdemux, trak);
1244
1245 /*  trak = qtdemux_tree_get_sibling_by_type(trak, FOURCC_trak);
1246   if(trak)qtdemux_parse_trak(qtdemux, trak);*/
1247
1248   while ((trak = qtdemux_tree_get_sibling_by_type(trak, FOURCC_trak)) != NULL)
1249     qtdemux_parse_trak(qtdemux, trak);
1250 }
1251
1252 static void qtdemux_parse_trak(GstQTDemux *qtdemux, GNode *trak)
1253 {
1254   int offset;
1255   GNode *tkhd;
1256   GNode *mdia;
1257   GNode *mdhd;
1258   GNode *hdlr;
1259   GNode *minf;
1260   GNode *stbl;
1261   GNode *stsd;
1262   GNode *stsc;
1263   GNode *stsz;
1264   GNode *stco;
1265   GNode *co64;
1266   GNode *stts;
1267   int n_samples;
1268   QtDemuxSample *samples;
1269   int n_samples_per_chunk;
1270   int index;
1271   int i,j,k;
1272   QtDemuxStream *stream;
1273   int n_sample_times;
1274   guint64 timestamp;
1275   int sample_size;
1276   int sample_index;
1277
1278   stream = g_new0(QtDemuxStream,1);
1279
1280   tkhd = qtdemux_tree_get_child_by_type(trak, FOURCC_tkhd);
1281   g_assert(tkhd);
1282
1283   /* track duration? */
1284
1285   mdia = qtdemux_tree_get_child_by_type(trak, FOURCC_mdia);
1286   g_assert(mdia);
1287
1288   mdhd = qtdemux_tree_get_child_by_type(mdia, FOURCC_mdhd);
1289   g_assert(mdhd);
1290
1291   stream->timescale = QTDEMUX_GUINT32_GET(mdhd->data+20);
1292   
1293   hdlr = qtdemux_tree_get_child_by_type(mdia, FOURCC_hdlr);
1294   g_assert(hdlr);
1295   
1296   g_print("track type: " GST_FOURCC_FORMAT "\n",
1297       GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(hdlr->data+12)));
1298   g_print("track subtype: " GST_FOURCC_FORMAT "\n",
1299       GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(hdlr->data+16)));
1300
1301   stream->subtype = QTDEMUX_FOURCC_GET(hdlr->data+16);
1302
1303   minf = qtdemux_tree_get_child_by_type(mdia, FOURCC_minf);
1304   g_assert(minf);
1305
1306   stbl = qtdemux_tree_get_child_by_type(minf, FOURCC_stbl);
1307   g_assert(stbl);
1308
1309   stsd = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsd);
1310   g_assert(stsd);
1311
1312   if(stream->subtype == FOURCC_vide){
1313     offset = 16;
1314     g_print("st type:          " GST_FOURCC_FORMAT "\n",
1315           GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(stsd->data+offset+4)));
1316
1317     stream->width = QTDEMUX_GUINT16_GET(stsd->data+offset+32);
1318     stream->height = QTDEMUX_GUINT16_GET(stsd->data+offset+34);
1319     stream->fps = 0.; /* this is filled in later */
1320
1321     g_print("frame count:   %u\n", QTDEMUX_GUINT16_GET(stsd->data+offset+48));
1322     
1323     stream->caps = qtdemux_video_caps(qtdemux,
1324         QTDEMUX_FOURCC_GET(stsd->data+offset+4));
1325     g_print("caps %s\n",gst_caps_to_string(stream->caps));
1326   }else if(stream->subtype == FOURCC_soun){
1327     int version;
1328
1329     g_print("st type:          " GST_FOURCC_FORMAT "\n",
1330           GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(stsd->data+16+4)));
1331
1332     offset = 32;
1333     g_print("version/rev:      %08x\n", QTDEMUX_GUINT32_GET(stsd->data+offset));
1334     version = QTDEMUX_GUINT32_GET(stsd->data+offset);
1335     g_print("vendor:           %08x\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 4));
1336     g_print("n_channels:       %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 8));
1337     stream->n_channels = QTDEMUX_GUINT16_GET(stsd->data+offset + 8);
1338     g_print("sample_size:      %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 10));
1339     g_print("compression_id:   %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 12));
1340     g_print("packet size:      %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 14));
1341     g_print("sample rate:      %g\n", QTDEMUX_FP32_GET(stsd->data+offset + 16));
1342     stream->rate = QTDEMUX_FP32_GET(stsd->data+offset + 16);
1343
1344     if(version == 0x00010000){
1345       g_print("samples/packet:   %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 20));
1346       g_print("bytes/packet:     %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 24));
1347       g_print("bytes/frame:      %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 28));
1348       g_print("bytes/sample:     %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 32));
1349     }
1350
1351     stream->caps = qtdemux_audio_caps(qtdemux,
1352         QTDEMUX_FOURCC_GET(stsd->data+16+4));
1353     g_print("caps %s\n",gst_caps_to_string(stream->caps));
1354   }else{
1355     g_print("unknown subtype\n");
1356     return;
1357   }
1358
1359   if(stream->caps){
1360     gst_caps_ref(stream->caps);
1361     gst_caps_sink(stream->caps);
1362   }
1363
1364   /* sample to chunk */
1365   stsc = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsc);
1366   g_assert(stsc);
1367   /* sample size */
1368   stsz = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsz);
1369   g_assert(stsz);
1370   /* chunk offsets */
1371   stco = qtdemux_tree_get_child_by_type(stbl, FOURCC_stco);
1372   co64 = qtdemux_tree_get_child_by_type(stbl, FOURCC_co64);
1373   g_assert(stco || co64);
1374   /* sample time */
1375   stts = qtdemux_tree_get_child_by_type(stbl, FOURCC_stts);
1376   g_assert(stts);
1377
1378   sample_size = QTDEMUX_GUINT32_GET(stsz->data+12);
1379   if(sample_size == 0){
1380     n_samples = QTDEMUX_GUINT32_GET(stsz->data+16);
1381     stream->n_samples = n_samples;
1382     samples = g_malloc(sizeof(QtDemuxSample)*n_samples);
1383     stream->samples = samples;
1384
1385     for(i=0;i<n_samples;i++){
1386       samples[i].size = QTDEMUX_GUINT32_GET(stsz->data + i*4 + 20);
1387     }
1388     n_samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data+12);
1389     index = 0;
1390     offset = 16;
1391     for(i=0;i<n_samples_per_chunk;i++){
1392       int first_chunk, last_chunk;
1393       int samples_per_chunk;
1394   
1395       first_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 0) - 1;
1396       if(i==n_samples_per_chunk-1){
1397         last_chunk = INT_MAX;
1398       }else{
1399         last_chunk = QTDEMUX_GUINT32_GET(stsc->data +16 + i*12 + 12) - 1;
1400       }
1401       samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 4);
1402
1403       for(j=first_chunk;j<last_chunk;j++){
1404         int chunk_offset;
1405         if(stco){
1406           chunk_offset = QTDEMUX_GUINT32_GET(stco->data + 16 + j*4);
1407         }else{
1408           chunk_offset = QTDEMUX_GUINT64_GET(co64->data + 16 + j*8);
1409         }
1410         for(k=0;k<samples_per_chunk;k++){
1411           samples[index].chunk = j;
1412           samples[index].offset = chunk_offset;
1413           chunk_offset += samples[index].size;
1414           index++;
1415           if(index>=n_samples)goto done;
1416         }
1417       }
1418     }
1419 done:
1420     
1421     n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12);
1422     timestamp = 0;
1423     index = 0;
1424     for(i=0;i<n_sample_times;i++){
1425       int n;
1426       int duration;
1427       guint64 time;
1428   
1429       n = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i);
1430       duration = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i + 4);
1431       time = (GST_SECOND * duration)/stream->timescale;
1432       for(j=0;j<n;j++){
1433         samples[index].timestamp = timestamp;
1434         samples[index].duration = time;
1435         timestamp += time;
1436         index++;
1437       }
1438     }
1439   }else{
1440     int sample_width;
1441
1442     g_print("treating chunks as samples\n");
1443
1444     /* treat chunks as samples */
1445     if(stco){
1446       n_samples = QTDEMUX_GUINT32_GET(stco->data+12);
1447     }else{
1448       n_samples = QTDEMUX_GUINT32_GET(co64->data+12);
1449     }
1450     stream->n_samples = n_samples;
1451     samples = g_malloc(sizeof(QtDemuxSample)*n_samples);
1452     stream->samples = samples;
1453
1454     sample_width = QTDEMUX_GUINT16_GET(stsd->data+offset + 10) / 8;
1455
1456     n_samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data+12);
1457     offset = 16;
1458     sample_index = 0;
1459     for(i=0;i<n_samples_per_chunk;i++){
1460       int first_chunk, last_chunk;
1461       int samples_per_chunk;
1462   
1463       first_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 0) - 1;
1464       if(i==n_samples-1){
1465         last_chunk = INT_MAX;
1466       }else{
1467         last_chunk = QTDEMUX_GUINT32_GET(stsc->data +16 + i*12 + 12) - 1;
1468       }
1469       samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 4);
1470
1471       for(j=first_chunk;j<last_chunk;j++){
1472         int chunk_offset;
1473         if(stco){
1474           chunk_offset = QTDEMUX_GUINT32_GET(stco->data + 16 + j*4);
1475         }else{
1476           chunk_offset = QTDEMUX_GUINT64_GET(co64->data + 16 + j*8);
1477         }
1478         samples[j].chunk = j;
1479         samples[j].offset = chunk_offset;
1480         samples[j].size = samples_per_chunk * stream->n_channels * sample_width;
1481         samples[j].sample_index = sample_index;
1482         sample_index += samples_per_chunk;
1483         if(j>=n_samples)goto done2;
1484       }
1485     }
1486 done2:
1487
1488     n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12);
1489     g_print("n_sample_times = %d\n",n_sample_times);
1490     timestamp = 0;
1491     index = 0;
1492     sample_index = 0;
1493     for(i=0;i<n_sample_times;i++){
1494       int duration;
1495       guint64 time;
1496   
1497       sample_index += QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i);
1498       duration = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i + 4);
1499       for(;index < n_samples && samples[index].sample_index < sample_index;index++){
1500         int size;
1501
1502         samples[index].timestamp = timestamp;
1503         size = samples[index+1].sample_index - samples[index].sample_index;
1504         time = (GST_SECOND * duration * samples[index].size)/stream->timescale ;
1505         timestamp += time;
1506         samples[index].duration = time;
1507       }
1508     }
1509   }
1510
1511 #if 0
1512   for(i=0;i<n_samples;i++){
1513     g_print("%d: %d %d %d %d %" G_GUINT64_FORMAT "\n",i,
1514         samples[i].sample_index,samples[i].chunk,
1515         samples[i].offset, samples[i].size, samples[i].timestamp);
1516     if(i>10)break;
1517   }
1518 #endif
1519
1520   gst_qtdemux_add_stream(qtdemux,stream);
1521 }
1522
1523
1524 static GstCaps *qtdemux_video_caps(GstQTDemux *qtdemux, guint32 fourcc)
1525 {
1526   switch(fourcc){
1527     case GST_MAKE_FOURCC('j','p','e','g'):
1528       /* JPEG */
1529       return GST_CAPS_NEW("jpeg_caps","image/jpeg",
1530           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1531           "width", GST_PROPS_INT_RANGE (16, 4096),
1532           "height", GST_PROPS_INT_RANGE (16, 4096));
1533     case GST_MAKE_FOURCC('m','j','p','a'):
1534       /* Motion-JPEG (format A) */
1535       return GST_CAPS_NEW("mjpa_caps","image/jpeg",
1536           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1537           "width", GST_PROPS_INT_RANGE (16, 4096),
1538           "height", GST_PROPS_INT_RANGE (16, 4096));
1539     case GST_MAKE_FOURCC('m','j','p','b'):
1540       /* Motion-JPEG (format B) */
1541       return GST_CAPS_NEW("mjpb_caps","image/jpeg",
1542           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1543           "width", GST_PROPS_INT_RANGE (16, 4096),
1544           "height", GST_PROPS_INT_RANGE (16, 4096));
1545     case GST_MAKE_FOURCC('S','V','Q','3'):
1546       return GST_CAPS_NEW("SVQ3_caps","video/x-svq",
1547           "svqversion", GST_PROPS_INT(3),
1548           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1549           "width", GST_PROPS_INT_RANGE (16, 4096),
1550           "height", GST_PROPS_INT_RANGE (16, 4096));
1551     case GST_MAKE_FOURCC('s','v','q','i'):
1552     case GST_MAKE_FOURCC('S','V','Q','1'):
1553       return GST_CAPS_NEW("SVQ1_caps","video/x-svq",
1554           "svqversion", GST_PROPS_INT(1),
1555           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1556           "width", GST_PROPS_INT_RANGE (16, 4096),
1557           "height", GST_PROPS_INT_RANGE (16, 4096));
1558     case GST_MAKE_FOURCC('r','a','w',' '):
1559       /* uncompressed RGB */
1560       return GST_CAPS_NEW("raw__caps","video/x-raw-rgb",
1561           "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1562           /*"bpp", GST_PROPS_INT(x),
1563           "depth", GST_PROPS_INT(x),
1564           "red_mask", GST_PROPS_INT(x),
1565           "green_mask", GST_PROPS_INT(x),
1566           "blue_mask", GST_PROPS_INT(x), FIXME! */
1567           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1568           "width", GST_PROPS_INT_RANGE (16, 4096),
1569           "height", GST_PROPS_INT_RANGE (16, 4096));
1570     case GST_MAKE_FOURCC('Y','u','v','2'):
1571       /* uncompressed YUV2 */
1572       return GST_CAPS_NEW("Yuv2_caps","video/x-raw-yuv",
1573           "format",GST_PROPS_FOURCC(GST_MAKE_FOURCC('Y','U','V','2')),
1574           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1575           "width", GST_PROPS_INT_RANGE (16, 4096),
1576           "height", GST_PROPS_INT_RANGE (16, 4096));
1577     case GST_MAKE_FOURCC('m','p','e','g'):
1578       /* MPEG */
1579       return GST_CAPS_NEW("mpeg_caps","video/mpeg",
1580           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1581           "width", GST_PROPS_INT_RANGE (16, 4096),
1582           "height", GST_PROPS_INT_RANGE (16, 4096),
1583           "systemstream", GST_PROPS_BOOLEAN(FALSE),
1584           "mpegversion", GST_PROPS_INT(1));
1585     case GST_MAKE_FOURCC('g','i','f',' '):
1586       return GST_CAPS_NEW("gif__caps","image/gif",
1587           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1588           "width", GST_PROPS_INT_RANGE (16, 4096),
1589           "height", GST_PROPS_INT_RANGE (16, 4096));
1590     case GST_MAKE_FOURCC('h','2','6','3'):
1591       /* H.263 */
1592       /* ffmpeg uses the height/width props, don't know why */
1593       return GST_CAPS_NEW("h263_caps","video/x-h263",
1594           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1595           "width", GST_PROPS_INT_RANGE (16, 4096),
1596           "height", GST_PROPS_INT_RANGE (16, 4096));
1597     case GST_MAKE_FOURCC('m','p','4','v'):
1598       /* MPEG-4 */
1599       return GST_CAPS_NEW("mp4v_caps", "video/mpeg",
1600           "mpegversion",GST_PROPS_INT(4),
1601           "systemstream", GST_PROPS_BOOLEAN(FALSE),
1602           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1603           "width", GST_PROPS_INT_RANGE (16, 4096),
1604           "height", GST_PROPS_INT_RANGE (16, 4096));
1605     case GST_MAKE_FOURCC('3','I','V','1'):
1606       return GST_CAPS_NEW("3IV1_caps", "video/x-3ivx",
1607           "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1608           "width", GST_PROPS_INT_RANGE (16, 4096),
1609           "height", GST_PROPS_INT_RANGE (16, 4096));
1610     case GST_MAKE_FOURCC('r','p','z','a'):
1611     case GST_MAKE_FOURCC('c','v','i','d'):
1612       /* Cinepak */
1613     case GST_MAKE_FOURCC('r','l','e',' '):
1614       /* Run-length encoding */
1615     case GST_MAKE_FOURCC('s','m','c',' '):
1616     case GST_MAKE_FOURCC('k','p','c','d'):
1617     default:
1618       g_print("Don't know how to convert fourcc '" GST_FOURCC_FORMAT
1619           "' to caps\n", GST_FOURCC_ARGS(fourcc));
1620       return NULL;
1621   }
1622 }
1623
1624 static GstCaps *qtdemux_audio_caps(GstQTDemux *qtdemux, guint32 fourcc)
1625 {
1626   switch(fourcc){
1627     case GST_MAKE_FOURCC('N','O','N','E'):
1628       return NULL; /*GST_CAPS_NEW("NONE_caps","audio/raw",NULL);*/
1629     case GST_MAKE_FOURCC('r','a','w',' '):
1630       /* FIXME */
1631       return GST_CAPS_NEW("raw__caps","audio/x-raw-int",
1632           "width",GST_PROPS_INT(8),
1633           "depth",GST_PROPS_INT(8),
1634           "signed",GST_PROPS_BOOLEAN(FALSE),
1635           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1636           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1637     case GST_MAKE_FOURCC('t','w','o','s'):
1638       /* FIXME */
1639       return GST_CAPS_NEW("twos_caps","audio/x-raw-int",
1640           "width",GST_PROPS_INT(16),
1641           "depth",GST_PROPS_INT(16),
1642           "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1643           "signed",GST_PROPS_BOOLEAN(TRUE),
1644           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1645           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1646     case GST_MAKE_FOURCC('s','o','w','t'):
1647       /* FIXME */
1648       return GST_CAPS_NEW("sowt_caps","audio/x-raw-int",
1649           "width",GST_PROPS_INT(16),
1650           "depth",GST_PROPS_INT(16),
1651           "endianness",GST_PROPS_INT(G_LITTLE_ENDIAN),
1652           "signed",GST_PROPS_BOOLEAN(TRUE),
1653           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1654           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1655     case GST_MAKE_FOURCC('f','l','6','4'):
1656       return GST_CAPS_NEW("fl64_caps","audio/x-raw-float",
1657           "width",GST_PROPS_INT (64),
1658           "endianness",GST_PROPS_INT (G_BIG_ENDIAN),
1659           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1660           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1661     case GST_MAKE_FOURCC('f','l','3','2'):
1662       return GST_CAPS_NEW("fl32_caps","audio/x-raw-float",
1663           "width",GST_PROPS_INT (32),
1664           "endianness",GST_PROPS_INT (G_BIG_ENDIAN),
1665           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1666           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1667     case GST_MAKE_FOURCC('i','n','2','4'):
1668       /* FIXME */
1669       return GST_CAPS_NEW("in24_caps","audio/x-raw-int",
1670           "width",GST_PROPS_INT(24),
1671           "depth",GST_PROPS_INT(32),
1672           "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1673           "signed",GST_PROPS_BOOLEAN(TRUE),
1674           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1675           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1676     case GST_MAKE_FOURCC('i','n','3','2'):
1677       /* FIXME */
1678       return GST_CAPS_NEW("in32_caps","audio/x-raw-int",
1679           "width",GST_PROPS_INT(24),
1680           "depth",GST_PROPS_INT(32),
1681           "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1682           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1683           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1684     case GST_MAKE_FOURCC('u','l','a','w'):
1685       /* FIXME */
1686       return GST_CAPS_NEW("ulaw_caps","audio/x-mulaw",
1687           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1688           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1689     case GST_MAKE_FOURCC('a','l','a','w'):
1690       /* FIXME */
1691       return GST_CAPS_NEW("alaw_caps","audio/x-alaw",
1692           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1693           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1694     case 0x6d730002:
1695       /* Microsoft ADPCM-ACM code 2 */
1696       return GST_CAPS_NEW("msxx_caps","audio/x-adpcm",
1697           "layout", GST_PROPS_STRING("microsoft"),
1698           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1699           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1700           NULL);
1701     case 0x6d730011:
1702       /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
1703       return GST_CAPS_NEW("msxx_caps","audio/x-adpcm",
1704           "layout", GST_PROPS_STRING("quicktime"),
1705           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1706           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1707           NULL);
1708     case 0x6d730055:
1709       /* MPEG layer 3, CBR only (pre QT4.1) */
1710     case 0x5500736d:
1711     case GST_MAKE_FOURCC('.','m','p','3'):
1712       /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
1713       return GST_CAPS_NEW("_mp3_caps","audio/mpeg",
1714           "layer", GST_PROPS_INT(3),
1715           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1716           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1717           NULL);
1718     case GST_MAKE_FOURCC('M','A','C','3'):
1719       /* MACE 3:1 */
1720       return GST_CAPS_NEW("MAC3_caps","audio/x-mace",
1721           "maceversion",GST_PROPS_INT(3),
1722           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1723           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1724           NULL);
1725     case GST_MAKE_FOURCC('M','A','C','6'):
1726       /* MACE 6:1 */
1727       return GST_CAPS_NEW("MAC3_caps","audio/x-mace",
1728           "maceversion",GST_PROPS_INT(6),
1729           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1730           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1731           NULL);
1732     case GST_MAKE_FOURCC('O','g','g','V'):
1733       /* Ogg Vorbis */
1734       return GST_CAPS_NEW("OggV_caps","application/ogg",
1735           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1736           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1737           NULL);
1738     case GST_MAKE_FOURCC('d','v','c','a'):
1739       /* DV audio */
1740       return GST_CAPS_NEW("dvca_caps","audio/x-dv",
1741           "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1742           "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1743           NULL);
1744     case GST_MAKE_FOURCC('m','p','4','a'):
1745       /* MPEG-4 AAC */
1746       return GST_CAPS_NEW("mp4a_caps", "audio/mpeg",
1747            "mpegversion", GST_PROPS_INT(4),
1748            "rate", GST_PROPS_INT_RANGE(1, G_MAXINT),
1749            "channels", GST_PROPS_INT_RANGE(1, G_MAXINT),
1750            "systemstream", GST_PROPS_BOOLEAN(FALSE), NULL);
1751     case GST_MAKE_FOURCC('q','t','v','r'):
1752       /* ? */
1753     case GST_MAKE_FOURCC('Q','D','M','2'):
1754       /* QDesign music version 2 (no constant) */
1755     case GST_MAKE_FOURCC('Q','D','M','C'):
1756       /* QDesign music */
1757     case GST_MAKE_FOURCC('i','m','a','4'):
1758       /* IMA 4:1 */
1759     case GST_MAKE_FOURCC('Q','c','l','p'):
1760       /* QUALCOMM PureVoice */
1761     case GST_MAKE_FOURCC('a','g','s','m'):
1762       /* ? */
1763     default:
1764       g_print("Don't know how to convert fourcc '" GST_FOURCC_FORMAT
1765           "' to caps\n", GST_FOURCC_ARGS(fourcc));
1766       return NULL;
1767   }
1768 }
1769