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",
245 static gboolean gst_qtdemux_handle_sink_event (GstQTDemux *qtdemux)
251 gst_bytestream_get_status(qtdemux->bs, &remaining, &event);
253 type = event ? GST_EVENT_TYPE(event) : GST_EVENT_UNKNOWN;
254 GST_DEBUG ("qtdemux: event %p %d", event, type);
258 gst_bytestream_flush(qtdemux->bs, remaining);
259 gst_pad_event_default(qtdemux->sinkpad, event);
261 case GST_EVENT_FLUSH:
262 g_warning("flush event");
264 case GST_EVENT_DISCONTINUOUS:
265 GST_DEBUG ("discontinuous event\n");
266 //gst_bytestream_flush_fast(qtdemux->bs, remaining);
269 g_warning("unhandled event %d",type);
273 gst_event_unref(event);
277 static GstElementStateReturn gst_qtdemux_change_state(GstElement *element)
279 GstQTDemux *qtdemux = GST_QTDEMUX(element);
281 switch(GST_STATE_TRANSITION(element)){
282 case GST_STATE_NULL_TO_READY:
284 case GST_STATE_READY_TO_PAUSED:
285 qtdemux->bs = gst_bytestream_new(qtdemux->sinkpad);
286 qtdemux->state = QTDEMUX_STATE_HEADER;
289 case GST_STATE_PAUSED_TO_PLAYING:
291 case GST_STATE_PLAYING_TO_PAUSED:
293 case GST_STATE_PAUSED_TO_READY:
294 gst_bytestream_destroy(qtdemux->bs);
296 case GST_STATE_READY_TO_NULL:
302 return GST_ELEMENT_CLASS(parent_class)->change_state(element);
305 static void gst_qtdemux_loop_header (GstElement *element)
307 GstQTDemux *qtdemux = GST_QTDEMUX(element);
317 /* FIXME _tell gets the offset wrong */
318 //cur_offset = gst_bytestream_tell(qtdemux->bs);
320 cur_offset = qtdemux->offset;
321 GST_DEBUG ("loop at position %d",cur_offset);
323 switch(qtdemux->state){
324 case QTDEMUX_STATE_HEADER:
327 ret = gst_bytestream_peek_bytes(qtdemux->bs, &data, 16);
329 if(!gst_qtdemux_handle_sink_event(qtdemux)){
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));
343 length = gst_bytestream_length(qtdemux->bs) - cur_offset;
346 guint32 length1, length2;
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);
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'):
363 case GST_MAKE_FOURCC('m','o','o','v'):
368 ret = gst_bytestream_read(qtdemux->bs, &moov, length);
370 GST_DEBUG ("read failed (%d < %d)",ret,length);
371 if(!gst_qtdemux_handle_sink_event(qtdemux)){
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;
387 g_print("unknown %08x '" GST_FOURCC_FORMAT "' at %d\n",
388 fourcc, GST_FOURCC_ARGS(fourcc), cur_offset);
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);
398 case QTDEMUX_STATE_SEEKING_EOS:
403 ret = gst_bytestream_peek_bytes(qtdemux->bs, &data, 1);
405 if(!gst_qtdemux_handle_sink_event(qtdemux)){
412 gst_element_set_eos(element);
414 qtdemux->state = QTDEMUX_STATE_EOS;
417 case QTDEMUX_STATE_EOS:
418 g_warning("spinning in EOS\n");
420 case QTDEMUX_STATE_MOVIE:
422 QtDemuxStream *stream;
427 min_time = G_MAXUINT64;
428 for(i=0;i<qtdemux->n_streams;i++){
429 stream = qtdemux->streams[i];
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;
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)));
443 ret = gst_bytestream_seek(qtdemux->bs, 0, GST_SEEK_METHOD_END);
444 GST_DEBUG ("seek returned %d",ret);
446 qtdemux->state = QTDEMUX_STATE_SEEKING_EOS;
450 stream = qtdemux->streams[index];
452 offset = stream->samples[stream->sample_index].offset;
453 size = stream->samples[stream->sample_index].size;
455 GST_DEBUG ("pushing from stream %d, sample_index=%d offset=%d size=%d",
456 index, stream->sample_index, offset, size);
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);
466 GST_DEBUG ("reading %d bytes\n",size);
469 ret = gst_bytestream_read(qtdemux->bs, &buf, size);
471 GST_DEBUG ("read failed (%d < %d)",ret,size);
472 if(!gst_qtdemux_handle_sink_event(qtdemux)){
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)));
489 gst_pad_try_set_caps(stream->pad, stream->caps);
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));
497 stream->sample_index++;
507 static GstCaps *gst_qtdemux_src_getcaps(GstPad *pad, GstCaps *caps)
510 QtDemuxStream *stream;
513 GST_DEBUG ("gst_qtdemux_src_getcaps");
515 qtdemux = GST_QTDEMUX(gst_pad_get_parent(pad));
517 g_return_val_if_fail(GST_IS_QTDEMUX(qtdemux), NULL);
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){
528 GST_DEBUG ("Couldn't find stream cooresponding to pad\n");
533 static GstPadLinkReturn
534 gst_qtdemux_src_link(GstPad *pad, GstCaps *caps)
537 QtDemuxStream *stream;
540 GST_DEBUG ("gst_qtdemux_src_link");
542 qtdemux = GST_QTDEMUX(gst_pad_get_parent(pad));
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);
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;
556 GST_DEBUG ("Couldn't find stream cooresponding to pad\n");
558 return GST_PAD_LINK_REFUSED;
561 void gst_qtdemux_add_stream(GstQTDemux *qtdemux, QtDemuxStream *stream)
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;
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;
577 qtdemux->n_video_streams++;
579 stream->pad = gst_pad_new_from_template (audiosrctempl,
580 g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams));
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;
590 qtdemux->n_audio_streams++;
593 gst_pad_set_getcaps_function(stream->pad, gst_qtdemux_src_getcaps);
594 gst_pad_set_link_function(stream->pad, gst_qtdemux_src_link);
596 qtdemux->streams[qtdemux->n_streams] = stream;
597 qtdemux->n_streams++;
598 GST_DEBUG ("n_streams is now %d", qtdemux->n_streams);
600 GST_DEBUG ("adding pad %p to qtdemux %p", stream->pad, qtdemux);
601 gst_element_add_pad(GST_ELEMENT (qtdemux), stream->pad);
603 /* Note: we need to have everything set up before calling try_set_caps */
605 g_print("setting caps to %s\n",gst_caps_to_string(stream->caps));
607 gst_pad_try_set_caps(stream->pad, stream->caps);
612 #define QT_CONTAINER 1
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')
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);
673 QtNodeType qt_node_types[] = {
674 { FOURCC_moov, "movie", QT_CONTAINER, },
675 { FOURCC_mvhd, "movie header", 0,
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,
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,
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,
697 { FOURCC_hdlr, "handler reference", 0,
699 { FOURCC_minf, "media information", QT_CONTAINER },
700 { FOURCC_vmhd, "video media information", 0,
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,
708 { FOURCC_stbl, "sample table", QT_CONTAINER },
709 { FOURCC_stsd, "sample description", 0,
711 { FOURCC_stts, "time-to-sample", 0,
713 { FOURCC_stss, "sync sample", 0,
715 { FOURCC_stsc, "sample-to-chunk", 0,
717 { FOURCC_stsz, "sample size", 0,
719 { FOURCC_stco, "chunk offset", 0,
721 { FOURCC_co64, "64-bit chunk offset", 0,
723 { FOURCC_vide, "video media", 0 },
724 { FOURCC_cmov, "compressed movie", QT_CONTAINER },
725 { FOURCC_dcom, "compressed data", 0,
727 { FOURCC_cmvd, "compressed movie data", 0,
731 static int n_qt_node_types = sizeof(qt_node_types)/sizeof(qt_node_types[0]);
734 static void *qtdemux_zalloc(void *opaque, unsigned int items, unsigned int size)
736 return g_malloc(items*size);
739 static void qtdemux_zfree(void *opaque, void *addr)
744 static void *qtdemux_inflate(void *z_buffer, int z_length, int length)
750 z = g_new0(z_stream, 1);
751 z->zalloc = qtdemux_zalloc;
752 z->zfree = qtdemux_zfree;
755 z->next_in = z_buffer;
756 z->avail_in = z_length;
758 buffer = g_malloc(length);
759 ret = inflateInit(z);
760 while(z->avail_in > 0){
761 if(z->avail_out == 0){
763 buffer = realloc(buffer, length);
764 z->next_out = buffer + z->total_out;
767 ret = inflate(z,Z_SYNC_FLUSH);
768 if(ret != Z_OK)break;
770 if(ret != Z_STREAM_END){
771 g_warning("inflate() returned %d\n",ret);
778 static void qtdemux_parse_moov(GstQTDemux *qtdemux, void *buffer, int length)
782 qtdemux->moov_node = g_node_new(buffer);
784 qtdemux_parse(qtdemux, qtdemux->moov_node, buffer, length);
786 cmov = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_cmov);
791 dcom = qtdemux_tree_get_child_by_type(cmov, FOURCC_dcom);
792 cmvd = qtdemux_tree_get_child_by_type(cmov, FOURCC_cmvd);
794 if(QTDEMUX_FOURCC_GET(dcom->data+8) == GST_MAKE_FOURCC('z','l','i','b')){
795 int uncompressed_length;
796 int compressed_length;
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);
803 buf = qtdemux_inflate(cmvd->data + 12, compressed_length,
804 uncompressed_length);
806 qtdemux->moov_node_compressed = qtdemux->moov_node;
807 qtdemux->moov_node = g_node_new(buf);
809 qtdemux_parse(qtdemux, qtdemux->moov_node, buf, uncompressed_length);
811 g_print("unknown header compression type\n");
816 static void qtdemux_parse(GstQTDemux *qtdemux, GNode *node, void *buffer, int length)
823 //g_print("qtdemux_parse %p %d\n",buffer, length);
825 node_length = QTDEMUX_GUINT32_GET(buffer);
826 fourcc = QTDEMUX_FOURCC_GET(buffer+4);
828 type = qtdemux_type_get(fourcc);
830 /*g_print("parsing '" GST_FOURCC_FORMAT "', length=%d\n",
831 GST_FOURCC_ARGS(fourcc), node_length);*/
833 if(type->flags & QT_CONTAINER){
838 end = buffer + length;
843 /* FIXME: get annoyed */
844 g_print("buffer overrun\n");
846 len = QTDEMUX_GUINT32_GET(buf);
848 child = g_node_new(buf);
849 g_node_append(node, child);
850 qtdemux_parse(qtdemux, child, buf, len);
856 if(fourcc == FOURCC_cmvd){
857 int uncompressed_length;
860 uncompressed_length = QTDEMUX_GUINT32_GET(buffer+8);
861 g_print("length = %d\n",uncompressed_length);
863 buf = qtdemux_inflate(buffer + 12, node_length-12, uncompressed_length);
865 end = buf + uncompressed_length;
871 /* FIXME: get annoyed */
872 g_print("buffer overrun\n");
874 len = QTDEMUX_GUINT32_GET(buf);
876 child = g_node_new(buf);
877 g_node_append(node, child);
878 qtdemux_parse(qtdemux, child, buf, len);
887 static QtNodeType *qtdemux_type_get(guint32 fourcc)
891 for(i=0;i<n_qt_node_types;i++){
892 if(qt_node_types[i].fourcc == fourcc)
893 return qt_node_types+i;
895 return qt_node_types+n_qt_node_types-1;
898 static gboolean qtdemux_node_dump_foreach(GNode *node, gpointer data)
900 void *buffer = node->data;
906 node_length = GUINT32_FROM_BE(*(guint32 *)buffer);
907 fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
909 type = qtdemux_type_get(fourcc);
911 depth = (g_node_depth(node)-1)*2;
912 g_print("%*s'" GST_FOURCC_FORMAT "', [%d], %s\n",
914 GST_FOURCC_ARGS(fourcc),
918 if(type->dump)type->dump(data, buffer, depth);
923 static void qtdemux_node_dump(GstQTDemux *qtdemux, GNode *node)
925 g_node_traverse(qtdemux->moov_node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
926 qtdemux_node_dump_foreach, qtdemux);
929 static void qtdemux_dump_mvhd(GstQTDemux *qtdemux, void *buffer, int depth)
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));
947 static void qtdemux_dump_tkhd(GstQTDemux *qtdemux, void *buffer, int depth)
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));
962 static void qtdemux_dump_elst(GstQTDemux *qtdemux, void *buffer, int depth)
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);
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));
977 static void qtdemux_dump_mdhd(GstQTDemux *qtdemux, void *buffer, int depth)
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));
989 static void qtdemux_dump_hdlr(GstQTDemux *qtdemux, void *buffer, int depth)
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));
1005 static void qtdemux_dump_vmhd(GstQTDemux *qtdemux, void *buffer, int depth)
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));
1011 static void qtdemux_dump_dref(GstQTDemux *qtdemux, void *buffer, int depth)
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);
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);
1029 static void qtdemux_dump_stsd(GstQTDemux *qtdemux, void *buffer, int depth)
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);
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));
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));
1061 offset += QTDEMUX_GUINT32_GET(buffer+offset);
1065 static void qtdemux_dump_stts(GstQTDemux *qtdemux, void *buffer, int depth)
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);
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));
1083 static void qtdemux_dump_stss(GstQTDemux *qtdemux, void *buffer, int depth)
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);
1094 g_print("%*s sample: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1100 static void qtdemux_dump_stsc(GstQTDemux *qtdemux, void *buffer, int depth)
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);
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));
1119 static void qtdemux_dump_stsz(GstQTDemux *qtdemux, void *buffer, int depth)
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);
1134 g_print("%*s sample size: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1141 static void qtdemux_dump_stco(GstQTDemux *qtdemux, void *buffer, int depth)
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);
1152 g_print("%*s chunk offset: %u\n", depth, "", QTDEMUX_GUINT32_GET(buffer+offset));
1158 static void qtdemux_dump_co64(GstQTDemux *qtdemux, void *buffer, int depth)
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);
1169 g_print("%*s chunk offset: %" G_GUINT64_FORMAT "\n", depth, "", QTDEMUX_GUINT64_GET(buffer+offset));
1175 static void qtdemux_dump_dcom(GstQTDemux *qtdemux, void *buffer, int depth)
1177 g_print("%*s compression type: " GST_FOURCC_FORMAT "\n", depth, "",
1178 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(buffer+8)));
1181 static void qtdemux_dump_cmvd(GstQTDemux *qtdemux, void *buffer, int depth)
1183 g_print("%*s length: %d\n", depth, "", QTDEMUX_GUINT32_GET(buffer+8));
1187 static GNode *qtdemux_tree_get_child_by_type(GNode *node, guint32 fourcc)
1191 guint32 child_fourcc;
1193 for(child = g_node_first_child(node); child; child = g_node_next_sibling(child)){
1194 buffer = child->data;
1196 child_fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
1198 if(child_fourcc == fourcc){
1205 static GNode *qtdemux_tree_get_sibling_by_type(GNode *node, guint32 fourcc)
1209 guint32 child_fourcc;
1211 for(child = g_node_next_sibling(node); child; child = g_node_next_sibling(child)){
1212 buffer = child->data;
1214 child_fourcc = GUINT32_FROM_LE(*(guint32 *)(buffer+4));
1216 if(child_fourcc == fourcc){
1223 static void qtdemux_parse_trak(GstQTDemux *qtdemux, GNode *trak);
1225 static void qtdemux_parse_tree(GstQTDemux *qtdemux)
1230 mvhd = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_mvhd);
1232 g_print("No mvhd node found.\n");
1236 qtdemux->timescale = QTDEMUX_GUINT32_GET(mvhd->data + 20);
1237 qtdemux->duration = QTDEMUX_GUINT32_GET(mvhd->data + 24);
1239 g_print("timescale: %d\n", qtdemux->timescale);
1240 g_print("duration: %d\n", qtdemux->duration);
1242 trak = qtdemux_tree_get_child_by_type(qtdemux->moov_node, FOURCC_trak);
1243 qtdemux_parse_trak(qtdemux, trak);
1245 /* trak = qtdemux_tree_get_sibling_by_type(trak, FOURCC_trak);
1246 if(trak)qtdemux_parse_trak(qtdemux, trak);*/
1248 while ((trak = qtdemux_tree_get_sibling_by_type(trak, FOURCC_trak)) != NULL)
1249 qtdemux_parse_trak(qtdemux, trak);
1252 static void qtdemux_parse_trak(GstQTDemux *qtdemux, GNode *trak)
1268 QtDemuxSample *samples;
1269 int n_samples_per_chunk;
1272 QtDemuxStream *stream;
1278 stream = g_new0(QtDemuxStream,1);
1280 tkhd = qtdemux_tree_get_child_by_type(trak, FOURCC_tkhd);
1283 /* track duration? */
1285 mdia = qtdemux_tree_get_child_by_type(trak, FOURCC_mdia);
1288 mdhd = qtdemux_tree_get_child_by_type(mdia, FOURCC_mdhd);
1291 stream->timescale = QTDEMUX_GUINT32_GET(mdhd->data+20);
1293 hdlr = qtdemux_tree_get_child_by_type(mdia, FOURCC_hdlr);
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)));
1301 stream->subtype = QTDEMUX_FOURCC_GET(hdlr->data+16);
1303 minf = qtdemux_tree_get_child_by_type(mdia, FOURCC_minf);
1306 stbl = qtdemux_tree_get_child_by_type(minf, FOURCC_stbl);
1309 stsd = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsd);
1312 if(stream->subtype == FOURCC_vide){
1314 g_print("st type: " GST_FOURCC_FORMAT "\n",
1315 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(stsd->data+offset+4)));
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 */
1321 g_print("frame count: %u\n", QTDEMUX_GUINT16_GET(stsd->data+offset+48));
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){
1329 g_print("st type: " GST_FOURCC_FORMAT "\n",
1330 GST_FOURCC_ARGS(QTDEMUX_FOURCC_GET(stsd->data+16+4)));
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);
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));
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));
1355 g_print("unknown subtype\n");
1360 gst_caps_ref(stream->caps);
1361 gst_caps_sink(stream->caps);
1364 /* sample to chunk */
1365 stsc = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsc);
1368 stsz = qtdemux_tree_get_child_by_type(stbl, FOURCC_stsz);
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);
1375 stts = qtdemux_tree_get_child_by_type(stbl, FOURCC_stts);
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;
1385 for(i=0;i<n_samples;i++){
1386 samples[i].size = QTDEMUX_GUINT32_GET(stsz->data + i*4 + 20);
1388 n_samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data+12);
1391 for(i=0;i<n_samples_per_chunk;i++){
1392 int first_chunk, last_chunk;
1393 int samples_per_chunk;
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;
1399 last_chunk = QTDEMUX_GUINT32_GET(stsc->data +16 + i*12 + 12) - 1;
1401 samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 4);
1403 for(j=first_chunk;j<last_chunk;j++){
1406 chunk_offset = QTDEMUX_GUINT32_GET(stco->data + 16 + j*4);
1408 chunk_offset = QTDEMUX_GUINT64_GET(co64->data + 16 + j*8);
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;
1415 if(index>=n_samples)goto done;
1421 n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12);
1424 for(i=0;i<n_sample_times;i++){
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;
1433 samples[index].timestamp = timestamp;
1434 samples[index].duration = time;
1442 g_print("treating chunks as samples\n");
1444 /* treat chunks as samples */
1446 n_samples = QTDEMUX_GUINT32_GET(stco->data+12);
1448 n_samples = QTDEMUX_GUINT32_GET(co64->data+12);
1450 stream->n_samples = n_samples;
1451 samples = g_malloc(sizeof(QtDemuxSample)*n_samples);
1452 stream->samples = samples;
1454 sample_width = QTDEMUX_GUINT16_GET(stsd->data+offset + 10) / 8;
1456 n_samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data+12);
1459 for(i=0;i<n_samples_per_chunk;i++){
1460 int first_chunk, last_chunk;
1461 int samples_per_chunk;
1463 first_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 0) - 1;
1465 last_chunk = INT_MAX;
1467 last_chunk = QTDEMUX_GUINT32_GET(stsc->data +16 + i*12 + 12) - 1;
1469 samples_per_chunk = QTDEMUX_GUINT32_GET(stsc->data + 16 + i*12 + 4);
1471 for(j=first_chunk;j<last_chunk;j++){
1474 chunk_offset = QTDEMUX_GUINT32_GET(stco->data + 16 + j*4);
1476 chunk_offset = QTDEMUX_GUINT64_GET(co64->data + 16 + j*8);
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;
1488 n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12);
1489 g_print("n_sample_times = %d\n",n_sample_times);
1493 for(i=0;i<n_sample_times;i++){
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++){
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 ;
1506 samples[index].duration = time;
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);
1520 gst_qtdemux_add_stream(qtdemux,stream);
1524 static GstCaps *qtdemux_video_caps(GstQTDemux *qtdemux, guint32 fourcc)
1527 case GST_MAKE_FOURCC('j','p','e','g'):
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'):
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'):
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'):
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'):
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'):
1618 g_print("Don't know how to convert fourcc '" GST_FOURCC_FORMAT
1619 "' to caps\n", GST_FOURCC_ARGS(fourcc));
1624 static GstCaps *qtdemux_audio_caps(GstQTDemux *qtdemux, guint32 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',' '):
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'):
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'):
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'):
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'):
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'):
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'):
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));
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),
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),
1709 /* MPEG layer 3, CBR only (pre QT4.1) */
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),
1718 case GST_MAKE_FOURCC('M','A','C','3'):
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),
1725 case GST_MAKE_FOURCC('M','A','C','6'):
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),
1732 case GST_MAKE_FOURCC('O','g','g','V'):
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),
1738 case GST_MAKE_FOURCC('d','v','c','a'):
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),
1744 case GST_MAKE_FOURCC('m','p','4','a'):
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'):
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'):
1757 case GST_MAKE_FOURCC('i','m','a','4'):
1759 case GST_MAKE_FOURCC('Q','c','l','p'):
1760 /* QUALCOMM PureVoice */
1761 case GST_MAKE_FOURCC('a','g','s','m'):
1764 g_print("Don't know how to convert fourcc '" GST_FOURCC_FORMAT
1765 "' to caps\n", GST_FOURCC_ARGS(fourcc));