2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) <2003> David A. Schleef <ds@schleef.org>
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.
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.
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.
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))
36 #define QTDEMUX_GUINT64_GET(a) ((((guint64)QTDEMUX_GUINT32_GET(a))<<32)|QTDEMUX_GUINT32_GET(((void *)a)+4))
38 typedef struct _QtNode QtNode;
39 typedef struct _QtNodeType QtNodeType;
40 typedef struct _QtDemuxSample QtDemuxSample;
41 //typedef struct _QtDemuxStream QtDemuxStream;
53 void (*dump)(GstQTDemux *qtdemux, void *buffer, int depth);
56 struct _QtDemuxSample {
65 struct _QtDemuxStream {
70 QtDemuxSample *samples;
85 QTDEMUX_STATE_HEADER_SEEKING,
86 QTDEMUX_STATE_SEEKING,
88 QTDEMUX_STATE_SEEKING_EOS,
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);
95 static GstElementDetails
100 "Demultiplex a QuickTime file into audio and video streams",
101 "David Schleef <ds@schleef.org>"
112 GST_PAD_TEMPLATE_FACTORY (sink_templ,
128 static GstPadTemplate *videosrctempl, *audiosrctempl;
129 static GstElementClass *parent_class = NULL;
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);
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);
146 static GType gst_qtdemux_get_type (void)
148 static GType qtdemux_type = 0;
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,
158 qtdemux_type = g_type_register_static (GST_TYPE_ELEMENT, "GstQTDemux", &qtdemux_info, 0);
163 static void gst_qtdemux_base_init (GstQTDemuxClass *klass)
165 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
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);
174 static void gst_qtdemux_class_init (GstQTDemuxClass *klass)
176 GObjectClass *gobject_class;
177 GstElementClass *gstelement_class;
179 gobject_class = (GObjectClass*)klass;
180 gstelement_class = (GstElementClass*)klass;
182 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
184 gstelement_class->change_state = gst_qtdemux_change_state;
188 gst_qtdemux_init (GstQTDemux *qtdemux)
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);
196 plugin_init (GstPlugin *plugin)
198 GstCaps *audiocaps = NULL, *videocaps = NULL, *temp;
199 const guint32 audio_fcc[] = {
208 if (!gst_library_load ("gstbytestream"))
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);
215 audiosrctempl = gst_pad_template_new ("audio_%02d",
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);
224 videosrctempl = gst_pad_template_new ("video_%02d",
229 return gst_element_register (plugin, "qtdemux",
230 GST_RANK_PRIMARY, GST_TYPE_QTDEMUX);
237 "Quicktime stream demuxer",
246 static gboolean gst_qtdemux_handle_sink_event (GstQTDemux *qtdemux)
252 gst_bytestream_get_status(qtdemux->bs, &remaining, &event);
254 type = event ? GST_EVENT_TYPE(event) : GST_EVENT_UNKNOWN;
255 GST_DEBUG ("qtdemux: event %p %d", event, type);
259 gst_bytestream_flush(qtdemux->bs, remaining);
260 gst_pad_event_default(qtdemux->sinkpad, event);
262 case GST_EVENT_FLUSH:
263 g_warning("flush event");
265 case GST_EVENT_DISCONTINUOUS:
266 GST_DEBUG ("discontinuous event\n");
267 //gst_bytestream_flush_fast(qtdemux->bs, remaining);
270 g_warning("unhandled event %d",type);
274 gst_event_unref(event);
278 static GstElementStateReturn gst_qtdemux_change_state(GstElement *element)
280 GstQTDemux *qtdemux = GST_QTDEMUX(element);
282 switch(GST_STATE_TRANSITION(element)){
283 case GST_STATE_NULL_TO_READY:
285 case GST_STATE_READY_TO_PAUSED:
286 qtdemux->bs = gst_bytestream_new(qtdemux->sinkpad);
287 qtdemux->state = QTDEMUX_STATE_HEADER;
290 case GST_STATE_PAUSED_TO_PLAYING:
292 case GST_STATE_PLAYING_TO_PAUSED:
294 case GST_STATE_PAUSED_TO_READY:
295 gst_bytestream_destroy(qtdemux->bs);
297 case GST_STATE_READY_TO_NULL:
303 return GST_ELEMENT_CLASS(parent_class)->change_state(element);
306 static void gst_qtdemux_loop_header (GstElement *element)
308 GstQTDemux *qtdemux = GST_QTDEMUX(element);
318 /* FIXME _tell gets the offset wrong */
319 //cur_offset = gst_bytestream_tell(qtdemux->bs);
321 cur_offset = qtdemux->offset;
322 GST_DEBUG ("loop at position %d",cur_offset);
324 switch(qtdemux->state){
325 case QTDEMUX_STATE_HEADER:
328 ret = gst_bytestream_peek_bytes(qtdemux->bs, &data, 16);
330 if(!gst_qtdemux_handle_sink_event(qtdemux)){
338 length = GUINT32_FROM_BE(*(guint32 *)data);
339 GST_DEBUG ("length %08x",length);
340 fourcc = GUINT32_FROM_LE(*(guint32 *)(data+4));
341 GST_DEBUG ("fourcc " GST_FOURCC_FORMAT, GST_FOURCC_ARGS(fourcc));
344 length = gst_bytestream_length(qtdemux->bs) - cur_offset;
347 guint32 length1, length2;
349 length1 = GUINT32_FROM_BE(*(guint32 *)(data+8));
350 GST_DEBUG ("length1 %08x",length1);
351 length2 = GUINT32_FROM_BE(*(guint32 *)(data+12));
352 GST_DEBUG ("length2 %08x",length2);
358 case GST_MAKE_FOURCC('m','d','a','t'):
359 case GST_MAKE_FOURCC('f','r','e','e'):
360 case GST_MAKE_FOURCC('w','i','d','e'):
361 case GST_MAKE_FOURCC('P','I','C','T'):
362 case GST_MAKE_FOURCC('p','n','o','t'):
364 case GST_MAKE_FOURCC('m','o','o','v'):
369 ret = gst_bytestream_read(qtdemux->bs, &moov, length);
371 GST_DEBUG ("read failed (%d < %d)",ret,length);
372 if(!gst_qtdemux_handle_sink_event(qtdemux)){
380 qtdemux_parse_moov(qtdemux, GST_BUFFER_DATA(moov), length);
381 if(1)qtdemux_node_dump(qtdemux, qtdemux->moov_node);
382 qtdemux_parse_tree(qtdemux);
383 qtdemux->state = QTDEMUX_STATE_MOVIE;
388 g_print("unknown %08x '" GST_FOURCC_FORMAT "' at %d\n",
389 fourcc, GST_FOURCC_ARGS(fourcc), cur_offset);
393 ret = gst_bytestream_seek(qtdemux->bs, cur_offset + length,
394 GST_SEEK_METHOD_SET);
395 qtdemux->offset = cur_offset + length;
396 GST_DEBUG ("seek returned %d\n",ret);
399 case QTDEMUX_STATE_SEEKING_EOS:
404 ret = gst_bytestream_peek_bytes(qtdemux->bs, &data, 1);
406 if(!gst_qtdemux_handle_sink_event(qtdemux)){
413 gst_element_set_eos(element);
415 qtdemux->state = QTDEMUX_STATE_EOS;
418 case QTDEMUX_STATE_EOS:
419 g_warning("spinning in EOS\n");
421 case QTDEMUX_STATE_MOVIE:
423 QtDemuxStream *stream;
428 min_time = G_MAXUINT64;
429 for(i=0;i<qtdemux->n_streams;i++){
430 stream = qtdemux->streams[i];
432 if(stream->sample_index < stream->n_samples &&
433 stream->samples[stream->sample_index].timestamp < min_time){
434 min_time = stream->samples[stream->sample_index].timestamp;
440 for(i=0;i<qtdemux->n_streams;i++){
441 gst_pad_push(qtdemux->streams[i]->pad,
442 GST_DATA(gst_event_new (GST_EVENT_EOS)));
444 ret = gst_bytestream_seek(qtdemux->bs, 0, GST_SEEK_METHOD_END);
445 GST_DEBUG ("seek returned %d",ret);
447 qtdemux->state = QTDEMUX_STATE_SEEKING_EOS;
451 stream = qtdemux->streams[index];
453 offset = stream->samples[stream->sample_index].offset;
454 size = stream->samples[stream->sample_index].size;
456 GST_DEBUG ("pushing from stream %d, sample_index=%d offset=%d size=%d",
457 index, stream->sample_index, offset, size);
459 cur_offset = gst_bytestream_tell(qtdemux->bs);
460 if(offset != cur_offset){
461 GST_DEBUG ("seeking to offset %d",offset);
462 ret = gst_bytestream_seek(qtdemux->bs, offset, GST_SEEK_METHOD_SET);
463 GST_DEBUG ("seek returned %d",ret);
467 GST_DEBUG ("reading %d bytes\n",size);
470 ret = gst_bytestream_read(qtdemux->bs, &buf, size);
472 GST_DEBUG ("read failed (%d < %d)",ret,size);
473 if(!gst_qtdemux_handle_sink_event(qtdemux)){
483 if(stream->subtype == GST_MAKE_FOURCC('v','i','d','e')){
484 float fps = 1. * GST_SECOND / stream->samples[stream->sample_index].duration;
485 if (fps != stream->fps) {
486 gst_props_remove_entry_by_name(stream->caps->properties, "framerate");
487 gst_props_add_entry(stream->caps->properties,
488 gst_props_entry_new("framerate", GST_PROPS_FLOAT(fps)));
490 gst_pad_try_set_caps(stream->pad, stream->caps);
494 GST_BUFFER_TIMESTAMP(buf) = stream->samples[stream->sample_index].timestamp;
495 GST_BUFFER_DURATION(buf) = stream->samples[stream->sample_index].duration;
496 gst_pad_push(stream->pad, GST_DATA (buf));
498 stream->sample_index++;
508 static GstCaps *gst_qtdemux_src_getcaps(GstPad *pad, GstCaps *caps)
511 QtDemuxStream *stream;
514 GST_DEBUG ("gst_qtdemux_src_getcaps");
516 qtdemux = GST_QTDEMUX(gst_pad_get_parent(pad));
518 g_return_val_if_fail(GST_IS_QTDEMUX(qtdemux), NULL);
520 GST_DEBUG ("looking for pad %p in qtdemux %p", pad, qtdemux);
521 GST_DEBUG ("n_streams is %d", qtdemux->n_streams);
522 for(i=0;i<qtdemux->n_streams;i++){
523 stream = qtdemux->streams[i];
524 if(stream->pad == pad){
529 GST_DEBUG ("Couldn't find stream cooresponding to pad\n");
534 static GstPadLinkReturn
535 gst_qtdemux_src_link(GstPad *pad, GstCaps *caps)
538 QtDemuxStream *stream;
541 GST_DEBUG ("gst_qtdemux_src_link");
543 qtdemux = GST_QTDEMUX(gst_pad_get_parent(pad));
545 GST_DEBUG ("looking for pad %p in qtdemux %p", pad, qtdemux);
546 g_return_val_if_fail(GST_IS_QTDEMUX(qtdemux), GST_PAD_LINK_REFUSED);
548 GST_DEBUG ("n_streams is %d", qtdemux->n_streams);
549 for(i=0;i<qtdemux->n_streams;i++){
550 stream = qtdemux->streams[i];
551 GST_DEBUG ("pad[%d] is %p", i, stream->pad);
552 if(stream->pad == pad){
553 return GST_PAD_LINK_OK;
557 GST_DEBUG ("Couldn't find stream cooresponding to pad\n");
559 return GST_PAD_LINK_REFUSED;
562 void gst_qtdemux_add_stream(GstQTDemux *qtdemux, QtDemuxStream *stream)
564 if(stream->subtype == GST_MAKE_FOURCC('v','i','d','e')){
565 stream->pad = gst_pad_new_from_template (videosrctempl,
566 g_strdup_printf ("video_%02d", qtdemux->n_video_streams));
567 stream->fps = 1. * GST_SECOND / stream->samples[0].duration;
569 GstProps *properties = gst_props_intersect(
570 stream->caps->properties,
571 gst_props_new("width",GST_PROPS_INT(stream->width),
572 "height",GST_PROPS_INT(stream->height),
573 "framerate", GST_PROPS_FLOAT(stream->fps), NULL));
574 if (stream->caps->properties != NULL)
575 gst_props_unref (stream->caps->properties);
576 stream->caps->properties = properties;
578 qtdemux->n_video_streams++;
580 stream->pad = gst_pad_new_from_template (audiosrctempl,
581 g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams));
583 GstProps *properties = gst_props_intersect(
584 stream->caps->properties,
585 gst_props_new("rate",GST_PROPS_INT((int)stream->rate),
586 "channels",GST_PROPS_INT(stream->n_channels), NULL));
587 if (stream->caps->properties != NULL)
588 gst_props_unref (stream->caps->properties);
589 stream->caps->properties = properties;
591 qtdemux->n_audio_streams++;
594 gst_pad_set_getcaps_function(stream->pad, gst_qtdemux_src_getcaps);
595 gst_pad_set_link_function(stream->pad, gst_qtdemux_src_link);
597 qtdemux->streams[qtdemux->n_streams] = stream;
598 qtdemux->n_streams++;
599 GST_DEBUG ("n_streams is now %d", qtdemux->n_streams);
601 GST_DEBUG ("adding pad %p to qtdemux %p", stream->pad, qtdemux);
602 gst_element_add_pad(GST_ELEMENT (qtdemux), stream->pad);
604 /* Note: we need to have everything set up before calling try_set_caps */
606 g_print("setting caps to %s\n",gst_caps_to_string(stream->caps));
608 gst_pad_try_set_caps(stream->pad, stream->caps);
613 #define QT_CONTAINER 1
615 #define FOURCC_moov GST_MAKE_FOURCC('m','o','o','v')
616 #define FOURCC_mvhd GST_MAKE_FOURCC('m','v','h','d')
617 #define FOURCC_clip GST_MAKE_FOURCC('c','l','i','p')
618 #define FOURCC_trak GST_MAKE_FOURCC('t','r','a','k')
619 #define FOURCC_udta GST_MAKE_FOURCC('u','d','t','a')
620 #define FOURCC_ctab GST_MAKE_FOURCC('c','t','a','b')
621 #define FOURCC_tkhd GST_MAKE_FOURCC('t','k','h','d')
622 #define FOURCC_crgn GST_MAKE_FOURCC('c','r','g','n')
623 #define FOURCC_matt GST_MAKE_FOURCC('m','a','t','t')
624 #define FOURCC_kmat GST_MAKE_FOURCC('k','m','a','t')
625 #define FOURCC_edts GST_MAKE_FOURCC('e','d','t','s')
626 #define FOURCC_elst GST_MAKE_FOURCC('e','l','s','t')
627 #define FOURCC_load GST_MAKE_FOURCC('l','o','a','d')
628 #define FOURCC_tref GST_MAKE_FOURCC('t','r','e','f')
629 #define FOURCC_imap GST_MAKE_FOURCC('i','m','a','p')
630 #define FOURCC___in GST_MAKE_FOURCC(' ',' ','i','n')
631 #define FOURCC___ty GST_MAKE_FOURCC(' ',' ','t','y')
632 #define FOURCC_mdia GST_MAKE_FOURCC('m','d','i','a')
633 #define FOURCC_mdhd GST_MAKE_FOURCC('m','d','h','d')
634 #define FOURCC_hdlr GST_MAKE_FOURCC('h','d','l','r')
635 #define FOURCC_minf GST_MAKE_FOURCC('m','i','n','f')
636 #define FOURCC_vmhd GST_MAKE_FOURCC('v','m','h','d')
637 #define FOURCC_smhd GST_MAKE_FOURCC('s','m','h','d')
638 #define FOURCC_gmhd GST_MAKE_FOURCC('g','m','h','d')
639 #define FOURCC_gmin GST_MAKE_FOURCC('g','m','i','n')
640 #define FOURCC_dinf GST_MAKE_FOURCC('d','i','n','f')
641 #define FOURCC_dref GST_MAKE_FOURCC('d','r','e','f')
642 #define FOURCC_stbl GST_MAKE_FOURCC('s','t','b','l')
643 #define FOURCC_stsd GST_MAKE_FOURCC('s','t','s','d')
644 #define FOURCC_stts GST_MAKE_FOURCC('s','t','t','s')
645 #define FOURCC_stss GST_MAKE_FOURCC('s','t','s','s')
646 #define FOURCC_stsc GST_MAKE_FOURCC('s','t','s','c')
647 #define FOURCC_stsz GST_MAKE_FOURCC('s','t','s','z')
648 #define FOURCC_stco GST_MAKE_FOURCC('s','t','c','o')
649 #define FOURCC_vide GST_MAKE_FOURCC('v','i','d','e')
650 #define FOURCC_soun GST_MAKE_FOURCC('s','o','u','n')
651 #define FOURCC_co64 GST_MAKE_FOURCC('c','o','6','4')
652 #define FOURCC_cmov GST_MAKE_FOURCC('c','m','o','v')
653 #define FOURCC_dcom GST_MAKE_FOURCC('d','c','o','m')
654 #define FOURCC_cmvd GST_MAKE_FOURCC('c','m','v','d')
657 static void qtdemux_dump_mvhd(GstQTDemux *qtdemux, void *buffer, int depth);
658 static void qtdemux_dump_tkhd(GstQTDemux *qtdemux, void *buffer, int depth);
659 static void qtdemux_dump_elst(GstQTDemux *qtdemux, void *buffer, int depth);
660 static void qtdemux_dump_mdhd(GstQTDemux *qtdemux, void *buffer, int depth);
661 static void qtdemux_dump_hdlr(GstQTDemux *qtdemux, void *buffer, int depth);
662 static void qtdemux_dump_vmhd(GstQTDemux *qtdemux, void *buffer, int depth);
663 static void qtdemux_dump_dref(GstQTDemux *qtdemux, void *buffer, int depth);
664 static void qtdemux_dump_stsd(GstQTDemux *qtdemux, void *buffer, int depth);
665 static void qtdemux_dump_stts(GstQTDemux *qtdemux, void *buffer, int depth);
666 static void qtdemux_dump_stss(GstQTDemux *qtdemux, void *buffer, int depth);
667 static void qtdemux_dump_stsc(GstQTDemux *qtdemux, void *buffer, int depth);
668 static void qtdemux_dump_stsz(GstQTDemux *qtdemux, void *buffer, int depth);
669 static void qtdemux_dump_stco(GstQTDemux *qtdemux, void *buffer, int depth);
670 static void qtdemux_dump_co64(GstQTDemux *qtdemux, void *buffer, int depth);
671 static void qtdemux_dump_dcom(GstQTDemux *qtdemux, void *buffer, int depth);
672 static void qtdemux_dump_cmvd(GstQTDemux *qtdemux, void *buffer, int depth);
674 QtNodeType qt_node_types[] = {
675 { FOURCC_moov, "movie", QT_CONTAINER, },
676 { FOURCC_mvhd, "movie header", 0,
678 { FOURCC_clip, "clipping", QT_CONTAINER, },
679 { FOURCC_trak, "track", QT_CONTAINER, },
680 { FOURCC_udta, "user data", 0, }, /* special container */
681 { FOURCC_ctab, "color table", 0, },
682 { FOURCC_tkhd, "track header", 0,
684 { FOURCC_crgn, "clipping region", 0, },
685 { FOURCC_matt, "track matte", QT_CONTAINER, },
686 { FOURCC_kmat, "compressed matte", 0, },
687 { FOURCC_edts, "edit", QT_CONTAINER, },
688 { FOURCC_elst, "edit list", 0,
690 { FOURCC_load, "track load settings", 0, },
691 { FOURCC_tref, "track reference", QT_CONTAINER, },
692 { FOURCC_imap, "track input map", QT_CONTAINER, },
693 { FOURCC___in, "track input", 0, }, /* special container */
694 { FOURCC___ty, "input type", 0, },
695 { FOURCC_mdia, "media", QT_CONTAINER },
696 { FOURCC_mdhd, "media header", 0,
698 { FOURCC_hdlr, "handler reference", 0,
700 { FOURCC_minf, "media information", QT_CONTAINER },
701 { FOURCC_vmhd, "video media information", 0,
703 { FOURCC_smhd, "sound media information", 0 },
704 { FOURCC_gmhd, "base media information header", 0 },
705 { FOURCC_gmin, "base media info", 0 },
706 { FOURCC_dinf, "data information", QT_CONTAINER },
707 { FOURCC_dref, "data reference", 0,
709 { FOURCC_stbl, "sample table", QT_CONTAINER },
710 { FOURCC_stsd, "sample description", 0,
712 { FOURCC_stts, "time-to-sample", 0,
714 { FOURCC_stss, "sync sample", 0,
716 { FOURCC_stsc, "sample-to-chunk", 0,
718 { FOURCC_stsz, "sample size", 0,
720 { FOURCC_stco, "chunk offset", 0,
722 { FOURCC_co64, "64-bit chunk offset", 0,
724 { FOURCC_vide, "video media", 0 },
725 { FOURCC_cmov, "compressed movie", QT_CONTAINER },
726 { FOURCC_dcom, "compressed data", 0,
728 { FOURCC_cmvd, "compressed movie data", 0,
732 static int n_qt_node_types = sizeof(qt_node_types)/sizeof(qt_node_types[0]);
735 static void *qtdemux_zalloc(void *opaque, unsigned int items, unsigned int size)
737 return g_malloc(items*size);
740 static void qtdemux_zfree(void *opaque, void *addr)
745 static void *qtdemux_inflate(void *z_buffer, int z_length, int length)
751 z = g_new0(z_stream, 1);
752 z->zalloc = qtdemux_zalloc;
753 z->zfree = qtdemux_zfree;
756 z->next_in = z_buffer;
757 z->avail_in = z_length;
759 buffer = g_malloc(length);
760 ret = inflateInit(z);
761 while(z->avail_in > 0){
762 if(z->avail_out == 0){
764 buffer = realloc(buffer, length);
765 z->next_out = buffer + z->total_out;
768 ret = inflate(z,Z_SYNC_FLUSH);
769 if(ret != Z_OK)break;
771 if(ret != Z_STREAM_END){
772 g_warning("inflate() returned %d\n",ret);
779 static void qtdemux_parse_moov(GstQTDemux *qtdemux, void *buffer, int length)
783 qtdemux->moov_node = g_node_new(buffer);
785 qtdemux_parse(qtdemux, qtdemux->moov_node, buffer, length);
787 cmov = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_cmov);
792 dcom = qtdemux_tree_get_child_by_type(cmov, FOURCC_dcom);
793 cmvd = qtdemux_tree_get_child_by_type(cmov, FOURCC_cmvd);
795 if(QTDEMUX_FOURCC_GET(dcom->data+8) == GST_MAKE_FOURCC('z','l','i','b')){
796 int uncompressed_length;
797 int compressed_length;
800 uncompressed_length = QTDEMUX_GUINT32_GET(cmvd->data+8);
801 compressed_length = QTDEMUX_GUINT32_GET(cmvd->data+4) - 12;
802 g_print("length = %d\n",uncompressed_length);
804 buf = qtdemux_inflate(cmvd->data + 12, compressed_length,
805 uncompressed_length);
807 qtdemux->moov_node_compressed = qtdemux->moov_node;
808 qtdemux->moov_node = g_node_new(buf);
810 qtdemux_parse(qtdemux, qtdemux->moov_node, buf, uncompressed_length);
812 g_print("unknown header compression type\n");
817 static void qtdemux_parse(GstQTDemux *qtdemux, GNode *node, void *buffer, int length)
824 //g_print("qtdemux_parse %p %d\n",buffer, length);
826 node_length = QTDEMUX_GUINT32_GET(buffer);
827 fourcc = QTDEMUX_FOURCC_GET(buffer+4);
829 type = qtdemux_type_get(fourcc);
831 /*g_print("parsing '" GST_FOURCC_FORMAT "', length=%d\n",
832 GST_FOURCC_ARGS(fourcc), node_length);*/
834 if(type->flags & QT_CONTAINER){
839 end = buffer + length;
844 /* FIXME: get annoyed */
845 g_print("buffer overrun\n");
847 len = QTDEMUX_GUINT32_GET(buf);
849 child = g_node_new(buf);
850 g_node_append(node, child);
851 qtdemux_parse(qtdemux, child, buf, len);
857 if(fourcc == FOURCC_cmvd){
858 int uncompressed_length;
861 uncompressed_length = QTDEMUX_GUINT32_GET(buffer+8);
862 g_print("length = %d\n",uncompressed_length);
864 buf = qtdemux_inflate(buffer + 12, node_length-12, uncompressed_length);
866 end = buf + uncompressed_length;
872 /* FIXME: get annoyed */
873 g_print("buffer overrun\n");
875 len = QTDEMUX_GUINT32_GET(buf);
877 child = g_node_new(buf);
878 g_node_append(node, child);
879 qtdemux_parse(qtdemux, child, buf, len);
888 static QtNodeType *qtdemux_type_get(guint32 fourcc)
892 for(i=0;i<n_qt_node_types;i++){
893 if(qt_node_types[i].fourcc == fourcc)
894 return qt_node_types+i;
896 return qt_node_types+n_qt_node_types-1;
899 static gboolean qtdemux_node_dump_foreach(GNode *node, gpointer data)
901 void *buffer = node->data;
907 node_length = GUINT32_FROM_BE(*(guint32 *)buffer);
908 fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
910 type = qtdemux_type_get(fourcc);
912 depth = (g_node_depth(node)-1)*2;
913 g_print("%*s'" GST_FOURCC_FORMAT "', [%d], %s\n",
915 GST_FOURCC_ARGS(fourcc),
919 if(type->dump)type->dump(data, buffer, depth);
924 static void qtdemux_node_dump(GstQTDemux *qtdemux, GNode *node)
926 g_node_traverse(qtdemux->moov_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
927 qtdemux_node_dump_foreach, qtdemux);
930 static void qtdemux_dump_mvhd(GstQTDemux *qtdemux, void *buffer, int depth)
932 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
933 g_print("%*s creation time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
934 g_print("%*s modify time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
935 g_print("%*s time scale: 1/%u sec\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20));
936 g_print("%*s duration: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+24));
937 g_print("%*s pref. rate: %g\n", depth, "", QTDEMUX_FP32_GET(buffer+28));
938 g_print("%*s pref. volume: %g\n", depth, "", QTDEMUX_FP16_GET(buffer+32));
939 g_print("%*s preview time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+80));
940 g_print("%*s preview dur.: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+84));
941 g_print("%*s poster time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+88));
942 g_print("%*s select time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+92));
943 g_print("%*s select dur.: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+96));
944 g_print("%*s current time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+100));
945 g_print("%*s next track ID: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+104));
948 static void qtdemux_dump_tkhd(GstQTDemux *qtdemux, void *buffer, int depth)
950 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
951 g_print("%*s creation time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
952 g_print("%*s modify time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
953 g_print("%*s track ID: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20));
954 g_print("%*s duration: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+28));
955 g_print("%*s layer: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+36));
956 g_print("%*s alt group: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+38));
957 g_print("%*s volume: %g\n", depth, "", QTDEMUX_FP16_GET(buffer+44));
958 g_print("%*s track width: %g\n", depth, "", QTDEMUX_FP32_GET(buffer+84));
959 g_print("%*s track height: %g\n", depth, "", QTDEMUX_FP32_GET(buffer+88));
963 static void qtdemux_dump_elst(GstQTDemux *qtdemux, void *buffer, int depth)
968 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
969 g_print("%*s n entries: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
970 n = QTDEMUX_GUINT32_GET(buffer+12);
972 g_print("%*s track dur: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16+i*12));
973 g_print("%*s media time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20+i*12));
974 g_print("%*s media rate: %g\n", depth, "", QTDEMUX_FP32_GET(buffer+24+i*12));
978 static void qtdemux_dump_mdhd(GstQTDemux *qtdemux, void *buffer, int depth)
980 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
981 g_print("%*s creation time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
982 g_print("%*s modify time: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
983 g_print("%*s time scale: 1/%u sec\n", depth, "", QTDEMUX_GUINT32_GET(buffer+20));
984 g_print("%*s duration: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+24));
985 g_print("%*s language: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+28));
986 g_print("%*s quality: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+30));
990 static void qtdemux_dump_hdlr(GstQTDemux *qtdemux, void *buffer, int depth)
992 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
993 g_print("%*s type: " GST_FOURCC_FORMAT "\n", depth, "",
994 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+12)));
995 g_print("%*s subtype: " GST_FOURCC_FORMAT "\n", depth, "",
996 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+16)));
997 g_print("%*s manufacturer: " GST_FOURCC_FORMAT "\n", depth, "",
998 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+20)));
999 g_print("%*s flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+24));
1000 g_print("%*s flags mask: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+28));
1001 g_print("%*s name: %*s\n", depth, "",
1002 QTDEMUX_GUINT8_GET(buffer+32), (char *)(buffer+33));
1006 static void qtdemux_dump_vmhd(GstQTDemux *qtdemux, void *buffer, int depth)
1008 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1009 g_print("%*s mode/color: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
1012 static void qtdemux_dump_dref(GstQTDemux *qtdemux, void *buffer, int depth)
1018 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1019 g_print("%*s n entries: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1020 n = QTDEMUX_GUINT32_GET(buffer+12);
1023 g_print("%*s size: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1024 g_print("%*s type: " GST_FOURCC_FORMAT "\n", depth, "",
1025 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+offset+4)));
1026 offset += QTDEMUX_GUINT32_GET(buffer+offset);
1030 static void qtdemux_dump_stsd(GstQTDemux *qtdemux, void *buffer, int depth)
1036 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1037 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1038 n = QTDEMUX_GUINT32_GET(buffer+12);
1041 g_print("%*s size: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1042 g_print("%*s type: " GST_FOURCC_FORMAT "\n", depth, "",
1043 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+offset+4)));
1044 g_print("%*s data reference:%d\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+14));
1046 g_print("%*s version/rev.: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+16));
1047 g_print("%*s vendor: " GST_FOURCC_FORMAT "\n", depth, "",
1048 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+offset+20)));
1049 g_print("%*s temporal qual: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+24));
1050 g_print("%*s spatial qual: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+28));
1051 g_print("%*s width: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+32));
1052 g_print("%*s height: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+34));
1053 g_print("%*s horiz. resol: %g\n", depth, "", QTDEMUX_FP32_GET(buffer+offset+36));
1054 g_print("%*s vert. resol.: %g\n", depth, "", QTDEMUX_FP32_GET(buffer+offset+40));
1055 g_print("%*s data size: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+44));
1056 g_print("%*s frame count: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+48));
1057 g_print("%*s compressor: %*s\n", depth, "",
1058 QTDEMUX_GUINT8_GET(buffer+offset+49), (char *)(buffer+offset+51));
1059 g_print("%*s depth: %u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+82));
1060 g_print("%*s color table ID:%u\n", depth, "", QTDEMUX_GUINT16_GET(buffer+offset+84));
1062 offset += QTDEMUX_GUINT32_GET(buffer+offset);
1066 static void qtdemux_dump_stts(GstQTDemux *qtdemux, void *buffer, int depth)
1072 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1073 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1074 n = QTDEMUX_GUINT32_GET(buffer+12);
1077 g_print("%*s count: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1078 g_print("%*s duration: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset + 4));
1084 static void qtdemux_dump_stss(GstQTDemux *qtdemux, void *buffer, int depth)
1090 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1091 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1092 n = QTDEMUX_GUINT32_GET(buffer+12);
1095 g_print("%*s sample: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1101 static void qtdemux_dump_stsc(GstQTDemux *qtdemux, void *buffer, int depth)
1107 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1108 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1109 n = QTDEMUX_GUINT32_GET(buffer+12);
1112 g_print("%*s first chunk: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1113 g_print("%*s sample per ch: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+4));
1114 g_print("%*s sample desc id:%08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset+8));
1120 static void qtdemux_dump_stsz(GstQTDemux *qtdemux, void *buffer, int depth)
1127 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1128 g_print("%*s sample size: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1129 sample_size = QTDEMUX_GUINT32_GET(buffer+12);
1130 if(sample_size == 0){
1131 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+16));
1132 n = QTDEMUX_GUINT32_GET(buffer+16);
1135 g_print("%*s sample size: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1142 static void qtdemux_dump_stco(GstQTDemux *qtdemux, void *buffer, int depth)
1148 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1149 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1150 n = QTDEMUX_GUINT32_GET(buffer+12);
1153 g_print("%*s chunk offset: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1159 static void qtdemux_dump_co64(GstQTDemux *qtdemux, void *buffer, int depth)
1165 g_print("%*s version/flags: %08x\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1166 g_print("%*s n entries: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+12));
1167 n = QTDEMUX_GUINT32_GET(buffer+12);
1170 g_print("%*s chunk offset: %" G_GUINT64_FORMAT "\n", depth, "", QTDEMUX_GUINT64_GET(buffer+offset));
1176 static void qtdemux_dump_dcom(GstQTDemux *qtdemux, void *buffer, int depth)
1178 g_print("%*s compression type: " GST_FOURCC_FORMAT "\n", depth, "",
1179 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+8)));
1182 static void qtdemux_dump_cmvd(GstQTDemux *qtdemux, void *buffer, int depth)
1184 g_print("%*s length: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1188 static GNode *qtdemux_tree_get_child_by_type(GNode *node, guint32 fourcc)
1192 guint32 child_fourcc;
1194 for(child = g_node_first_child(node); child; child = g_node_next_sibling(child)){
1195 buffer = child->data;
1197 child_fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
1199 if(child_fourcc == fourcc){
1206 static GNode *qtdemux_tree_get_sibling_by_type(GNode *node, guint32 fourcc)
1210 guint32 child_fourcc;
1212 for(child = g_node_next_sibling(node); child; child = g_node_next_sibling(child)){
1213 buffer = child->data;
1215 child_fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
1217 if(child_fourcc == fourcc){
1224 static void qtdemux_parse_trak(GstQTDemux *qtdemux, GNode *trak);
1226 static void qtdemux_parse_tree(GstQTDemux *qtdemux)
1231 mvhd = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_mvhd);
1233 g_print("No mvhd node found.\n");
1237 qtdemux->timescale = QTDEMUX_GUINT32_GET(mvhd->data + 20);
1238 qtdemux->duration = QTDEMUX_GUINT32_GET(mvhd->data + 24);
1240 g_print("timescale: %d\n", qtdemux->timescale);
1241 g_print("duration: %d\n", qtdemux->duration);
1243 trak = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_trak);
1244 qtdemux_parse_trak(qtdemux, trak);
1246 /* trak = qtdemux_tree_get_sibling_by_type(trak, FOURCC_trak);
1247 if(trak)qtdemux_parse_trak(qtdemux, trak);*/
1249 while ((trak = qtdemux_tree_get_sibling_by_type(trak, FOURCC_trak)) != NULL)
1250 qtdemux_parse_trak(qtdemux, trak);
1253 static void qtdemux_parse_trak(GstQTDemux *qtdemux, GNode *trak)
1269 QtDemuxSample *samples;
1270 int n_samples_per_chunk;
1273 QtDemuxStream *stream;
1279 stream = g_new0(QtDemuxStream,1);
1281 tkhd = qtdemux_tree_get_child_by_type(trak, FOURCC_tkhd);
1284 /* track duration? */
1286 mdia = qtdemux_tree_get_child_by_type(trak, FOURCC_mdia);
1289 mdhd = qtdemux_tree_get_child_by_type(mdia, FOURCC_mdhd);
1292 stream->timescale = QTDEMUX_GUINT32_GET(mdhd->data+20);
1294 hdlr = qtdemux_tree_get_child_by_type(mdia, FOURCC_hdlr);
1297 g_print("track type: " GST_FOURCC_FORMAT "\n",
1298 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(hdlr->data+12)));
1299 g_print("track subtype: " GST_FOURCC_FORMAT "\n",
1300 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(hdlr->data+16)));
1302 stream->subtype = QTDEMUX_FOURCC_GET(hdlr->data+16);
1304 minf = qtdemux_tree_get_child_by_type(mdia, FOURCC_minf);
1307 stbl = qtdemux_tree_get_child_by_type(minf, FOURCC_stbl);
1310 stsd = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsd);
1313 if(stream->subtype == FOURCC_vide){
1315 g_print("st type: " GST_FOURCC_FORMAT "\n",
1316 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(stsd->data+offset+4)));
1318 stream->width = QTDEMUX_GUINT16_GET(stsd->data+offset+32);
1319 stream->height = QTDEMUX_GUINT16_GET(stsd->data+offset+34);
1320 stream->fps = 0.; /* this is filled in later */
1322 g_print("frame count: %u\n", QTDEMUX_GUINT16_GET(stsd->data+offset+48));
1324 stream->caps = qtdemux_video_caps(qtdemux,
1325 QTDEMUX_FOURCC_GET(stsd->data+offset+4));
1326 g_print("caps %s\n",gst_caps_to_string(stream->caps));
1327 }else if(stream->subtype == FOURCC_soun){
1330 g_print("st type: " GST_FOURCC_FORMAT "\n",
1331 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(stsd->data+16+4)));
1334 g_print("version/rev: %08x\n", QTDEMUX_GUINT32_GET(stsd->data+offset));
1335 version = QTDEMUX_GUINT32_GET(stsd->data+offset);
1336 g_print("vendor: %08x\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 4));
1337 g_print("n_channels: %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 8));
1338 stream->n_channels = QTDEMUX_GUINT16_GET(stsd->data+offset + 8);
1339 g_print("sample_size: %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 10));
1340 g_print("compression_id: %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 12));
1341 g_print("packet size: %d\n", QTDEMUX_GUINT16_GET(stsd->data+offset + 14));
1342 g_print("sample rate: %g\n", QTDEMUX_FP32_GET(stsd->data+offset + 16));
1343 stream->rate = QTDEMUX_FP32_GET(stsd->data+offset + 16);
1345 if(version == 0x00010000){
1346 g_print("samples/packet: %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 20));
1347 g_print("bytes/packet: %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 24));
1348 g_print("bytes/frame: %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 28));
1349 g_print("bytes/sample: %d\n", QTDEMUX_GUINT32_GET(stsd->data+offset + 32));
1352 stream->caps = qtdemux_audio_caps(qtdemux,
1353 QTDEMUX_FOURCC_GET(stsd->data+16+4));
1354 g_print("caps %s\n",gst_caps_to_string(stream->caps));
1356 g_print("unknown subtype\n");
1361 gst_caps_ref(stream->caps);
1362 gst_caps_sink(stream->caps);
1365 /* sample to chunk */
1366 stsc = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsc);
1369 stsz = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsz);
1372 stco = qtdemux_tree_get_child_by_type(stbl, FOURCC_stco);
1373 co64 = qtdemux_tree_get_child_by_type(stbl, FOURCC_co64);
1374 g_assert(stco || co64);
1376 stts = qtdemux_tree_get_child_by_type(stbl, FOURCC_stts);
1379 sample_size = QTDEMUX_GUINT32_GET(stsz->data+12);
1380 if(sample_size == 0){
1381 n_samples = QTDEMUX_GUINT32_GET(stsz->data+16);
1382 stream->n_samples = n_samples;
1383 samples = g_malloc(sizeof(QtDemuxSample)*n_samples);
1384 stream->samples = samples;
1386 for(i=0;i<n_samples;i++){
1387 samples[i].size = QTDEMUX_GUINT32_GET(stsz->data + i*4 + 20);
1389 n_samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data+12);
1392 for(i=0;i<n_samples_per_chunk;i++){
1393 int first_chunk, last_chunk;
1394 int samples_per_chunk;
1396 first_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 0) - 1;
1397 if(i==n_samples_per_chunk-1){
1398 last_chunk = INT_MAX;
1400 last_chunk = QTDEMUX_GUINT32_GET(stsc->data +16 + i*12 + 12) - 1;
1402 samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 4);
1404 for(j=first_chunk;j<last_chunk;j++){
1407 chunk_offset = QTDEMUX_GUINT32_GET(stco->data + 16 + j*4);
1409 chunk_offset = QTDEMUX_GUINT64_GET(co64->data + 16 + j*8);
1411 for(k=0;k<samples_per_chunk;k++){
1412 samples[index].chunk = j;
1413 samples[index].offset = chunk_offset;
1414 chunk_offset += samples[index].size;
1416 if(index>=n_samples)goto done;
1422 n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12);
1425 for(i=0;i<n_sample_times;i++){
1430 n = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i);
1431 duration = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i + 4);
1432 time = (GST_SECOND * duration)/stream->timescale;
1434 samples[index].timestamp = timestamp;
1435 samples[index].duration = time;
1443 g_print("treating chunks as samples\n");
1445 /* treat chunks as samples */
1447 n_samples = QTDEMUX_GUINT32_GET(stco->data+12);
1449 n_samples = QTDEMUX_GUINT32_GET(co64->data+12);
1451 stream->n_samples = n_samples;
1452 samples = g_malloc(sizeof(QtDemuxSample)*n_samples);
1453 stream->samples = samples;
1455 sample_width = QTDEMUX_GUINT16_GET(stsd->data+offset + 10) / 8;
1457 n_samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data+12);
1460 for(i=0;i<n_samples_per_chunk;i++){
1461 int first_chunk, last_chunk;
1462 int samples_per_chunk;
1464 first_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 0) - 1;
1466 last_chunk = INT_MAX;
1468 last_chunk = QTDEMUX_GUINT32_GET(stsc->data +16 + i*12 + 12) - 1;
1470 samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 4);
1472 for(j=first_chunk;j<last_chunk;j++){
1475 chunk_offset = QTDEMUX_GUINT32_GET(stco->data + 16 + j*4);
1477 chunk_offset = QTDEMUX_GUINT64_GET(co64->data + 16 + j*8);
1479 samples[j].chunk = j;
1480 samples[j].offset = chunk_offset;
1481 samples[j].size = samples_per_chunk * stream->n_channels * sample_width;
1482 samples[j].sample_index = sample_index;
1483 sample_index += samples_per_chunk;
1484 if(j>=n_samples)goto done2;
1489 n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12);
1490 g_print("n_sample_times = %d\n",n_sample_times);
1494 for(i=0;i<n_sample_times;i++){
1498 sample_index += QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i);
1499 duration = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i + 4);
1500 for(;index < n_samples && samples[index].sample_index < sample_index;index++){
1503 samples[index].timestamp = timestamp;
1504 size = samples[index+1].sample_index - samples[index].sample_index;
1505 time = (GST_SECOND * duration * samples[index].size)/stream->timescale ;
1507 samples[index].duration = time;
1513 for(i=0;i<n_samples;i++){
1514 g_print("%d: %d %d %d %d %" G_GUINT64_FORMAT "\n",i,
1515 samples[i].sample_index,samples[i].chunk,
1516 samples[i].offset, samples[i].size, samples[i].timestamp);
1521 gst_qtdemux_add_stream(qtdemux,stream);
1525 static GstCaps *qtdemux_video_caps(GstQTDemux *qtdemux, guint32 fourcc)
1528 case GST_MAKE_FOURCC('j','p','e','g'):
1530 return GST_CAPS_NEW("jpeg_caps","image/jpeg",
1531 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1532 "width", GST_PROPS_INT_RANGE (16, 4096),
1533 "height", GST_PROPS_INT_RANGE (16, 4096));
1534 case GST_MAKE_FOURCC('m','j','p','a'):
1535 /* Motion-JPEG (format A) */
1536 return GST_CAPS_NEW("mjpa_caps","image/jpeg",
1537 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1538 "width", GST_PROPS_INT_RANGE (16, 4096),
1539 "height", GST_PROPS_INT_RANGE (16, 4096));
1540 case GST_MAKE_FOURCC('m','j','p','b'):
1541 /* Motion-JPEG (format B) */
1542 return GST_CAPS_NEW("mjpb_caps","image/jpeg",
1543 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1544 "width", GST_PROPS_INT_RANGE (16, 4096),
1545 "height", GST_PROPS_INT_RANGE (16, 4096));
1546 case GST_MAKE_FOURCC('S','V','Q','3'):
1547 return GST_CAPS_NEW("SVQ3_caps","video/x-svq",
1548 "svqversion", GST_PROPS_INT(3),
1549 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1550 "width", GST_PROPS_INT_RANGE (16, 4096),
1551 "height", GST_PROPS_INT_RANGE (16, 4096));
1552 case GST_MAKE_FOURCC('s','v','q','i'):
1553 case GST_MAKE_FOURCC('S','V','Q','1'):
1554 return GST_CAPS_NEW("SVQ1_caps","video/x-svq",
1555 "svqversion", GST_PROPS_INT(1),
1556 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1557 "width", GST_PROPS_INT_RANGE (16, 4096),
1558 "height", GST_PROPS_INT_RANGE (16, 4096));
1559 case GST_MAKE_FOURCC('r','a','w',' '):
1560 /* uncompressed RGB */
1561 return GST_CAPS_NEW("raw__caps","video/x-raw-rgb",
1562 "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1563 /*"bpp", GST_PROPS_INT(x),
1564 "depth", GST_PROPS_INT(x),
1565 "red_mask", GST_PROPS_INT(x),
1566 "green_mask", GST_PROPS_INT(x),
1567 "blue_mask", GST_PROPS_INT(x), FIXME! */
1568 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1569 "width", GST_PROPS_INT_RANGE (16, 4096),
1570 "height", GST_PROPS_INT_RANGE (16, 4096));
1571 case GST_MAKE_FOURCC('Y','u','v','2'):
1572 /* uncompressed YUV2 */
1573 return GST_CAPS_NEW("Yuv2_caps","video/x-raw-yuv",
1574 "format",GST_PROPS_FOURCC(GST_MAKE_FOURCC('Y','U','V','2')),
1575 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1576 "width", GST_PROPS_INT_RANGE (16, 4096),
1577 "height", GST_PROPS_INT_RANGE (16, 4096));
1578 case GST_MAKE_FOURCC('m','p','e','g'):
1580 return GST_CAPS_NEW("mpeg_caps","video/mpeg",
1581 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1582 "width", GST_PROPS_INT_RANGE (16, 4096),
1583 "height", GST_PROPS_INT_RANGE (16, 4096),
1584 "systemstream", GST_PROPS_BOOLEAN(FALSE),
1585 "mpegversion", GST_PROPS_INT(1));
1586 case GST_MAKE_FOURCC('g','i','f',' '):
1587 return GST_CAPS_NEW("gif__caps","image/gif",
1588 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1589 "width", GST_PROPS_INT_RANGE (16, 4096),
1590 "height", GST_PROPS_INT_RANGE (16, 4096));
1591 case GST_MAKE_FOURCC('h','2','6','3'):
1593 /* ffmpeg uses the height/width props, don't know why */
1594 return GST_CAPS_NEW("h263_caps","video/x-h263",
1595 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1596 "width", GST_PROPS_INT_RANGE (16, 4096),
1597 "height", GST_PROPS_INT_RANGE (16, 4096));
1598 case GST_MAKE_FOURCC('m','p','4','v'):
1600 return GST_CAPS_NEW("mp4v_caps", "video/mpeg",
1601 "mpegversion",GST_PROPS_INT(4),
1602 "systemstream", GST_PROPS_BOOLEAN(FALSE),
1603 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1604 "width", GST_PROPS_INT_RANGE (16, 4096),
1605 "height", GST_PROPS_INT_RANGE (16, 4096));
1606 case GST_MAKE_FOURCC('3','I','V','1'):
1607 return GST_CAPS_NEW("3IV1_caps", "video/x-3ivx",
1608 "framerate", GST_PROPS_FLOAT_RANGE (0, G_MAXFLOAT),
1609 "width", GST_PROPS_INT_RANGE (16, 4096),
1610 "height", GST_PROPS_INT_RANGE (16, 4096));
1611 case GST_MAKE_FOURCC('r','p','z','a'):
1612 case GST_MAKE_FOURCC('c','v','i','d'):
1614 case GST_MAKE_FOURCC('r','l','e',' '):
1615 /* Run-length encoding */
1616 case GST_MAKE_FOURCC('s','m','c',' '):
1617 case GST_MAKE_FOURCC('k','p','c','d'):
1619 g_print("Don't know how to convert fourcc '" GST_FOURCC_FORMAT
1620 "' to caps\n", GST_FOURCC_ARGS(fourcc));
1625 static GstCaps *qtdemux_audio_caps(GstQTDemux *qtdemux, guint32 fourcc)
1628 case GST_MAKE_FOURCC('N','O','N','E'):
1629 return NULL; /*GST_CAPS_NEW("NONE_caps","audio/raw",NULL);*/
1630 case GST_MAKE_FOURCC('r','a','w',' '):
1632 return GST_CAPS_NEW("raw__caps","audio/x-raw-int",
1633 "width",GST_PROPS_INT(8),
1634 "depth",GST_PROPS_INT(8),
1635 "signed",GST_PROPS_BOOLEAN(FALSE),
1636 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1637 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1638 case GST_MAKE_FOURCC('t','w','o','s'):
1640 return GST_CAPS_NEW("twos_caps","audio/x-raw-int",
1641 "width",GST_PROPS_INT(16),
1642 "depth",GST_PROPS_INT(16),
1643 "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1644 "signed",GST_PROPS_BOOLEAN(TRUE),
1645 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1646 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1647 case GST_MAKE_FOURCC('s','o','w','t'):
1649 return GST_CAPS_NEW("sowt_caps","audio/x-raw-int",
1650 "width",GST_PROPS_INT(16),
1651 "depth",GST_PROPS_INT(16),
1652 "endianness",GST_PROPS_INT(G_LITTLE_ENDIAN),
1653 "signed",GST_PROPS_BOOLEAN(TRUE),
1654 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1655 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1656 case GST_MAKE_FOURCC('f','l','6','4'):
1657 return GST_CAPS_NEW("fl64_caps","audio/x-raw-float",
1658 "width",GST_PROPS_INT (64),
1659 "endianness",GST_PROPS_INT (G_BIG_ENDIAN),
1660 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1661 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1662 case GST_MAKE_FOURCC('f','l','3','2'):
1663 return GST_CAPS_NEW("fl32_caps","audio/x-raw-float",
1664 "width",GST_PROPS_INT (32),
1665 "endianness",GST_PROPS_INT (G_BIG_ENDIAN),
1666 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1667 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1668 case GST_MAKE_FOURCC('i','n','2','4'):
1670 return GST_CAPS_NEW("in24_caps","audio/x-raw-int",
1671 "width",GST_PROPS_INT(24),
1672 "depth",GST_PROPS_INT(32),
1673 "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1674 "signed",GST_PROPS_BOOLEAN(TRUE),
1675 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1676 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1677 case GST_MAKE_FOURCC('i','n','3','2'):
1679 return GST_CAPS_NEW("in32_caps","audio/x-raw-int",
1680 "width",GST_PROPS_INT(24),
1681 "depth",GST_PROPS_INT(32),
1682 "endianness",GST_PROPS_INT(G_BIG_ENDIAN),
1683 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1684 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1685 case GST_MAKE_FOURCC('u','l','a','w'):
1687 return GST_CAPS_NEW("ulaw_caps","audio/x-mulaw",
1688 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1689 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1690 case GST_MAKE_FOURCC('a','l','a','w'):
1692 return GST_CAPS_NEW("alaw_caps","audio/x-alaw",
1693 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1694 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT));
1696 /* Microsoft ADPCM-ACM code 2 */
1697 return GST_CAPS_NEW("msxx_caps","audio/x-adpcm",
1698 "layout", GST_PROPS_STRING("microsoft"),
1699 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1700 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1703 /* FIXME DVI/Intel IMA ADPCM/ACM code 17 */
1704 return GST_CAPS_NEW("msxx_caps","audio/x-adpcm",
1705 "layout", GST_PROPS_STRING("quicktime"),
1706 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1707 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1710 /* MPEG layer 3, CBR only (pre QT4.1) */
1712 case GST_MAKE_FOURCC('.','m','p','3'):
1713 /* MPEG layer 3, CBR & VBR (QT4.1 and later) */
1714 return GST_CAPS_NEW("_mp3_caps","audio/mpeg",
1715 "layer", GST_PROPS_INT(3),
1716 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1717 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1719 case GST_MAKE_FOURCC('M','A','C','3'):
1721 return GST_CAPS_NEW("MAC3_caps","audio/x-mace",
1722 "maceversion",GST_PROPS_INT(3),
1723 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1724 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1726 case GST_MAKE_FOURCC('M','A','C','6'):
1728 return GST_CAPS_NEW("MAC3_caps","audio/x-mace",
1729 "maceversion",GST_PROPS_INT(6),
1730 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1731 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1733 case GST_MAKE_FOURCC('O','g','g','V'):
1735 return GST_CAPS_NEW("OggV_caps","application/ogg",
1736 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1737 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1739 case GST_MAKE_FOURCC('d','v','c','a'):
1741 return GST_CAPS_NEW("dvca_caps","audio/x-dv",
1742 "rate",GST_PROPS_INT_RANGE(1,G_MAXINT),
1743 "channels",GST_PROPS_INT_RANGE(1,G_MAXINT),
1745 case GST_MAKE_FOURCC('m','p','4','a'):
1747 return GST_CAPS_NEW("mp4a_caps", "audio/mpeg",
1748 "mpegversion", GST_PROPS_INT(4),
1749 "rate", GST_PROPS_INT_RANGE(1, G_MAXINT),
1750 "channels", GST_PROPS_INT_RANGE(1, G_MAXINT),
1751 "systemstream", GST_PROPS_BOOLEAN(FALSE), NULL);
1752 case GST_MAKE_FOURCC('q','t','v','r'):
1754 case GST_MAKE_FOURCC('Q','D','M','2'):
1755 /* QDesign music version 2 (no constant) */
1756 case GST_MAKE_FOURCC('Q','D','M','C'):
1758 case GST_MAKE_FOURCC('i','m','a','4'):
1760 case GST_MAKE_FOURCC('Q','c','l','p'):
1761 /* QUALCOMM PureVoice */
1762 case GST_MAKE_FOURCC('a','g','s','m'):
1765 g_print("Don't know how to convert fourcc '" GST_FOURCC_FORMAT
1766 "' to caps\n", GST_FOURCC_ARGS(fourcc));