1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) 2009 Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) <2009> STEricsson <benjamin.gaignard@stericsson.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "qtdemux_debug.h"
23 #include "qtdemux_types.h"
24 #include "qtdemux_dump.h"
25 #include "fourcc.h"
26 
27 #include "qtatomparser.h"
28 
29 #include <string.h>
30 
31 #define GST_CAT_DEFAULT qtdemux_debug
32 
33 #define GET_UINT8(data)   gst_byte_reader_get_uint8_unchecked(data)
34 #define GET_UINT16(data)  gst_byte_reader_get_uint16_be_unchecked(data)
35 #define GET_UINT32(data)  gst_byte_reader_get_uint32_be_unchecked(data)
36 #define GET_UINT64(data)  gst_byte_reader_get_uint64_be_unchecked(data)
37 #define GET_FP32(data)   (gst_byte_reader_get_uint32_be_unchecked(data)/65536.0)
38 #define GET_FP16(data)   (gst_byte_reader_get_uint16_be_unchecked(data)/256.0)
39 #define GET_FOURCC(data)  qt_atom_parser_get_fourcc_unchecked(data)
40 
41 gboolean
qtdemux_dump_mvhd(GstQTDemux * qtdemux,GstByteReader * data,int depth)42 qtdemux_dump_mvhd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
43 {
44   guint32 version = 0;
45 
46   if (!qt_atom_parser_has_remaining (data, 100))
47     return FALSE;
48 
49   version = GET_UINT32 (data);
50   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
51 
52   version = version >> 24;
53   if (version == 0) {
54     GST_LOG ("%*s  creation time: %u", depth, "", GET_UINT32 (data));
55     GST_LOG ("%*s  modify time:   %u", depth, "", GET_UINT32 (data));
56     GST_LOG ("%*s  time scale:    1/%u sec", depth, "", GET_UINT32 (data));
57     GST_LOG ("%*s  duration:      %u", depth, "", GET_UINT32 (data));
58   } else if (version == 1) {
59     GST_LOG ("%*s  creation time: %" G_GUINT64_FORMAT,
60         depth, "", GET_UINT64 (data));
61     GST_LOG ("%*s  modify time:   %" G_GUINT64_FORMAT,
62         depth, "", GET_UINT64 (data));
63     GST_LOG ("%*s  time scale:    1/%u sec", depth, "", GET_UINT32 (data));
64     GST_LOG ("%*s  duration:      %" G_GUINT64_FORMAT,
65         depth, "", GET_UINT64 (data));
66   } else
67     return FALSE;
68 
69   GST_LOG ("%*s  pref. rate:    %g", depth, "", GET_FP32 (data));
70   GST_LOG ("%*s  pref. volume:  %g", depth, "", GET_FP16 (data));
71   gst_byte_reader_skip_unchecked (data, 46);
72   GST_LOG ("%*s  preview time:  %u", depth, "", GET_UINT32 (data));
73   GST_LOG ("%*s  preview dur.:  %u", depth, "", GET_UINT32 (data));
74   GST_LOG ("%*s  poster time:   %u", depth, "", GET_UINT32 (data));
75   GST_LOG ("%*s  select time:   %u", depth, "", GET_UINT32 (data));
76   GST_LOG ("%*s  select dur.:   %u", depth, "", GET_UINT32 (data));
77   GST_LOG ("%*s  current time:  %u", depth, "", GET_UINT32 (data));
78   GST_LOG ("%*s  next track ID: %d", depth, "", GET_UINT32 (data));
79   return TRUE;
80 }
81 
82 gboolean
qtdemux_dump_tkhd(GstQTDemux * qtdemux,GstByteReader * data,int depth)83 qtdemux_dump_tkhd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
84 {
85   guint64 duration, ctime, mtime;
86   guint32 version = 0, track_id = 0, iwidth = 0, iheight = 0;
87   guint16 layer = 0, alt_group = 0, ivol = 0;
88   guint value_size;
89 
90   if (!gst_byte_reader_get_uint32_be (data, &version))
91     return FALSE;
92 
93   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
94 
95   value_size = ((version >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
96 
97   if (qt_atom_parser_get_offset (data, value_size, &ctime) &&
98       qt_atom_parser_get_offset (data, value_size, &mtime) &&
99       gst_byte_reader_get_uint32_be (data, &track_id) &&
100       gst_byte_reader_skip (data, 4) &&
101       qt_atom_parser_get_offset (data, value_size, &duration) &&
102       gst_byte_reader_skip (data, 4) &&
103       gst_byte_reader_get_uint16_be (data, &layer) &&
104       gst_byte_reader_get_uint16_be (data, &alt_group) &&
105       gst_byte_reader_skip (data, 4) &&
106       gst_byte_reader_get_uint16_be (data, &ivol) &&
107       gst_byte_reader_skip (data, 2 + (9 * 4)) &&
108       gst_byte_reader_get_uint32_be (data, &iwidth) &&
109       gst_byte_reader_get_uint32_be (data, &iheight)) {
110     GST_LOG ("%*s  creation time: %" G_GUINT64_FORMAT, depth, "", ctime);
111     GST_LOG ("%*s  modify time:   %" G_GUINT64_FORMAT, depth, "", mtime);
112     GST_LOG ("%*s  track ID:      %u", depth, "", track_id);
113     GST_LOG ("%*s  duration:      %" G_GUINT64_FORMAT, depth, "", duration);
114     GST_LOG ("%*s  layer:         %u", depth, "", layer);
115     GST_LOG ("%*s  alt group:     %u", depth, "", alt_group);
116     GST_LOG ("%*s  volume:        %g", depth, "", ivol / 256.0);
117     GST_LOG ("%*s  track width:   %g", depth, "", iwidth / 65536.0);
118     GST_LOG ("%*s  track height:  %g", depth, "", iheight / 65536.0);
119     return TRUE;
120   }
121 
122   return FALSE;
123 }
124 
125 gboolean
qtdemux_dump_elst(GstQTDemux * qtdemux,GstByteReader * data,int depth)126 qtdemux_dump_elst (GstQTDemux * qtdemux, GstByteReader * data, int depth)
127 {
128   guint32 ver_flags = 0, num_entries = 0, i;
129 
130   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
131       !gst_byte_reader_get_uint32_be (data, &num_entries))
132     return FALSE;
133 
134   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
135   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
136 
137   if (!qt_atom_parser_has_chunks (data, num_entries, 4 + 4 + 4))
138     return FALSE;
139 
140   for (i = 0; i < num_entries; i++) {
141     GST_LOG ("%*s    track dur:     %u", depth, "", GET_UINT32 (data));
142     GST_LOG ("%*s    media time:    %u", depth, "", GET_UINT32 (data));
143     GST_LOG ("%*s    media rate:    %g", depth, "", GET_FP32 (data));
144   }
145   return TRUE;
146 }
147 
148 gboolean
qtdemux_dump_mdhd(GstQTDemux * qtdemux,GstByteReader * data,int depth)149 qtdemux_dump_mdhd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
150 {
151   guint32 version = 0;
152   guint64 duration, ctime, mtime;
153   guint32 time_scale = 0;
154   guint16 language = 0, quality = 0;
155   guint value_size;
156 
157   if (!gst_byte_reader_get_uint32_be (data, &version))
158     return FALSE;
159 
160   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
161 
162   value_size = ((version >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
163 
164   if (qt_atom_parser_get_offset (data, value_size, &ctime) &&
165       qt_atom_parser_get_offset (data, value_size, &mtime) &&
166       gst_byte_reader_get_uint32_be (data, &time_scale) &&
167       qt_atom_parser_get_offset (data, value_size, &duration) &&
168       gst_byte_reader_get_uint16_be (data, &language) &&
169       gst_byte_reader_get_uint16_be (data, &quality)) {
170     GST_LOG ("%*s  creation time: %" G_GUINT64_FORMAT, depth, "", ctime);
171     GST_LOG ("%*s  modify time:   %" G_GUINT64_FORMAT, depth, "", mtime);
172     GST_LOG ("%*s  time scale:    1/%u sec", depth, "", time_scale);
173     GST_LOG ("%*s  duration:      %" G_GUINT64_FORMAT, depth, "", duration);
174     GST_LOG ("%*s  language:      %u", depth, "", language);
175     GST_LOG ("%*s  quality:       %u", depth, "", quality);
176     return TRUE;
177   }
178 
179   return FALSE;
180 }
181 
182 gboolean
qtdemux_dump_hdlr(GstQTDemux * qtdemux,GstByteReader * data,int depth)183 qtdemux_dump_hdlr (GstQTDemux * qtdemux, GstByteReader * data, int depth)
184 {
185   guint32 version, type, subtype, manufacturer;
186   const gchar *name;
187 
188   if (!qt_atom_parser_has_remaining (data, 4 + 4 + 4 + 4 + 4 + 4))
189     return FALSE;
190 
191   version = GET_UINT32 (data);
192   type = GET_FOURCC (data);
193   subtype = GET_FOURCC (data);
194   manufacturer = GET_FOURCC (data);
195 
196   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
197   GST_LOG ("%*s  type:          %" GST_FOURCC_FORMAT, depth, "",
198       GST_FOURCC_ARGS (type));
199   GST_LOG ("%*s  subtype:       %" GST_FOURCC_FORMAT, depth, "",
200       GST_FOURCC_ARGS (subtype));
201   GST_LOG ("%*s  manufacturer:  %" GST_FOURCC_FORMAT, depth, "",
202       GST_FOURCC_ARGS (manufacturer));
203   GST_LOG ("%*s  flags:         %08x", depth, "", GET_UINT32 (data));
204   GST_LOG ("%*s  flags mask:    %08x", depth, "", GET_UINT32 (data));
205 
206   /* quicktime uses pascal string, mp4 zero-terminated string */
207   if (gst_byte_reader_peek_string (data, &name)) {
208     GST_LOG ("%*s  name:          %s", depth, "", name);
209   } else {
210     gchar buf[256];
211     guint8 len;
212 
213     if (gst_byte_reader_get_uint8 (data, &len)
214         && qt_atom_parser_has_remaining (data, len)) {
215       memcpy (buf, gst_byte_reader_peek_data_unchecked (data), len);
216       buf[len] = '\0';
217       GST_LOG ("%*s  name:          %s", depth, "", buf);
218     }
219   }
220   return TRUE;
221 }
222 
223 gboolean
qtdemux_dump_vmhd(GstQTDemux * qtdemux,GstByteReader * data,int depth)224 qtdemux_dump_vmhd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
225 {
226   if (!qt_atom_parser_has_remaining (data, 4 + 4))
227     return FALSE;
228 
229   GST_LOG ("%*s  version/flags: %08x", depth, "", GET_UINT32 (data));
230   GST_LOG ("%*s  mode/color:    %08x", depth, "", GET_UINT32 (data));
231   return TRUE;
232 }
233 
234 gboolean
qtdemux_dump_dref(GstQTDemux * qtdemux,GstByteReader * data,int depth)235 qtdemux_dump_dref (GstQTDemux * qtdemux, GstByteReader * data, int depth)
236 {
237   guint32 ver_flags = 0, num_entries = 0, i;
238 
239   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
240       !gst_byte_reader_get_uint32_be (data, &num_entries))
241     return FALSE;
242 
243   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
244   GST_LOG ("%*s  n entries:     %u", depth, "", num_entries);
245   for (i = 0; i < num_entries; i++) {
246     guint32 size = 0, fourcc;
247 
248     if (!gst_byte_reader_get_uint32_be (data, &size) ||
249         !qt_atom_parser_get_fourcc (data, &fourcc) || size < 8 ||
250         !gst_byte_reader_skip (data, size - 8))
251       return FALSE;
252 
253     GST_LOG ("%*s    size:          %u", depth, "", size);
254     GST_LOG ("%*s    type:          %" GST_FOURCC_FORMAT, depth, "",
255         GST_FOURCC_ARGS (fourcc));
256   }
257   return TRUE;
258 }
259 
260 static gboolean
qtdemux_dump_stsd_avc1(GstQTDemux * qtdemux,GstByteReader * data,guint size,int depth)261 qtdemux_dump_stsd_avc1 (GstQTDemux * qtdemux, GstByteReader * data, guint size,
262     int depth)
263 {
264   guint32 fourcc;
265 
266   /* Size of avc1 = 78 bytes */
267   if (size < (6 + 2 + 4 + 4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 2 + 1 + 31 + 2 + 2))
268     return FALSE;
269 
270   gst_byte_reader_skip_unchecked (data, 6);
271   GST_LOG_OBJECT (qtdemux, "%*s    data reference:%d", depth, "",
272       GET_UINT16 (data));
273   GST_LOG_OBJECT (qtdemux, "%*s    version/rev.:  %08x", depth, "",
274       GET_UINT32 (data));
275   fourcc = GET_FOURCC (data);
276   GST_LOG_OBJECT (qtdemux, "%*s    vendor:        %" GST_FOURCC_FORMAT, depth,
277       "", GST_FOURCC_ARGS (fourcc));
278   GST_LOG_OBJECT (qtdemux, "%*s    temporal qual: %u", depth, "",
279       GET_UINT32 (data));
280   GST_LOG_OBJECT (qtdemux, "%*s    spatial qual:  %u", depth, "",
281       GET_UINT32 (data));
282   GST_LOG_OBJECT (qtdemux, "%*s    width:         %u", depth, "",
283       GET_UINT16 (data));
284   GST_LOG_OBJECT (qtdemux, "%*s    height:        %u", depth, "",
285       GET_UINT16 (data));
286   GST_LOG_OBJECT (qtdemux, "%*s    horiz. resol:  %g", depth, "",
287       GET_FP32 (data));
288   GST_LOG_OBJECT (qtdemux, "%*s    vert. resol.:  %g", depth, "",
289       GET_FP32 (data));
290   GST_LOG_OBJECT (qtdemux, "%*s    data size:     %u", depth, "",
291       GET_UINT32 (data));
292   GST_LOG_OBJECT (qtdemux, "%*s    frame count:   %u", depth, "",
293       GET_UINT16 (data));
294   /* something is not right with this, it's supposed to be a string but it's
295    * not apparently, so just skip this for now */
296   gst_byte_reader_skip_unchecked (data, 1 + 31);
297   GST_LOG_OBJECT (qtdemux, "%*s    compressor:    (skipped)", depth, "");
298   GST_LOG_OBJECT (qtdemux, "%*s    depth:         %u", depth, "",
299       GET_UINT16 (data));
300   GST_LOG_OBJECT (qtdemux, "%*s    color table ID:%u", depth, "",
301       GET_UINT16 (data));
302 
303   return TRUE;
304 }
305 
306 
307 static gboolean
qtdemux_dump_stsd_av01(GstQTDemux * qtdemux,GstByteReader * data,guint size,int depth)308 qtdemux_dump_stsd_av01 (GstQTDemux * qtdemux, GstByteReader * data, guint size,
309     int depth)
310 {
311   guint compressor_len;
312   char compressor_name[32];
313 
314   /* Size of av01 = 78 bytes */
315   if (size < (6 + 2 + 4 + 12 + 2 + 2 + 4 + 4 + 4 + 2 + 1 + 31 + 2 + 2))
316     return FALSE;
317 
318   gst_byte_reader_skip_unchecked (data, 6);
319   GST_LOG_OBJECT (qtdemux, "%*s    data reference:%d", depth, "",
320       GET_UINT16 (data));
321   GST_LOG_OBJECT (qtdemux, "%*s    version/rev.:  %08x", depth, "",
322       GET_UINT32 (data));
323   gst_byte_reader_skip_unchecked (data, 12);    /* pre-defined & reserved */
324   GST_LOG_OBJECT (qtdemux, "%*s    width:         %u", depth, "",
325       GET_UINT16 (data));
326   GST_LOG_OBJECT (qtdemux, "%*s    height:        %u", depth, "",
327       GET_UINT16 (data));
328   GST_LOG_OBJECT (qtdemux, "%*s    horiz. resol:  %g", depth, "",
329       GET_FP32 (data));
330   GST_LOG_OBJECT (qtdemux, "%*s    vert. resol.:  %g", depth, "",
331       GET_FP32 (data));
332   GST_LOG_OBJECT (qtdemux, "%*s    data size:     %u", depth, "",
333       GET_UINT32 (data));
334   GST_LOG_OBJECT (qtdemux, "%*s    frame count:   %u", depth, "",
335       GET_UINT16 (data));
336   /* something is not right with this, it's supposed to be a string but it's
337    * not apparently, so just skip this for now */
338   compressor_len = MAX (GET_UINT8 (data), 31);
339   memcpy (compressor_name, gst_byte_reader_get_data_unchecked (data, 31), 31);
340   compressor_name[compressor_len] = 0;
341   GST_LOG_OBJECT (qtdemux, "%*s    compressor:    %s", depth, "",
342       compressor_name);
343   GST_LOG_OBJECT (qtdemux, "%*s    depth:         %u", depth, "",
344       GET_UINT16 (data));
345   GST_LOG_OBJECT (qtdemux, "%*s    color table ID:%u", depth, "",
346       GET_UINT16 (data));
347 
348   return TRUE;
349 }
350 
351 gboolean
qtdemux_dump_stsd(GstQTDemux * qtdemux,GstByteReader * data,int depth)352 qtdemux_dump_stsd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
353 {
354   guint32 ver_flags = 0, num_entries = 0, i;
355 
356   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
357       !gst_byte_reader_get_uint32_be (data, &num_entries))
358     return FALSE;
359 
360   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
361   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
362 
363   for (i = 0; i < num_entries; i++) {
364     GstByteReader sub;
365     guint32 size, remain;
366     guint32 fourcc;
367 
368     if (!gst_byte_reader_get_uint32_be (data, &size) ||
369         !qt_atom_parser_get_fourcc (data, &fourcc))
370       return FALSE;
371 
372     GST_LOG_OBJECT (qtdemux, "%*s    size:          %u", depth, "", size);
373     GST_LOG_OBJECT (qtdemux, "%*s    type:          %" GST_FOURCC_FORMAT, depth,
374         "", GST_FOURCC_ARGS (fourcc));
375 
376     remain = gst_byte_reader_get_remaining (data);
377     /* Size includes the 8 bytes we just read: len & fourcc, then 8 bytes
378      * version, flags, entries_count */
379     if (size > remain + 8) {
380       GST_LOG_OBJECT (qtdemux,
381           "Not enough data left for this atom (have %u need %u)", remain, size);
382       return FALSE;
383     }
384 
385     qt_atom_parser_peek_sub (data, 0, size, &sub);
386     switch (fourcc) {
387       case FOURCC_avc1:
388         if (!qtdemux_dump_stsd_avc1 (qtdemux, &sub, size, depth + 1))
389           return FALSE;
390         break;
391       case FOURCC_fLaC:
392         /* will be dumped by node_dump_foreach */
393         break;
394       case FOURCC_mp4s:
395         if (!gst_byte_reader_get_uint32_be (&sub, &ver_flags) ||
396             !gst_byte_reader_get_uint32_be (&sub, &num_entries))
397           return FALSE;
398         if (!qtdemux_dump_unknown (qtdemux, &sub, depth + 1))
399           return FALSE;
400         break;
401       case FOURCC_av01:
402         if (!qtdemux_dump_stsd_av01 (qtdemux, &sub, size, depth + 1))
403           return FALSE;
404         break;
405       default:
406         /* Unknown stsd data, dump the bytes */
407         if (!qtdemux_dump_unknown (qtdemux, &sub, depth + 1))
408           return FALSE;
409         break;
410     }
411 
412     if (!gst_byte_reader_skip (data, size - (4 + 4)))
413       return FALSE;
414   }
415   return TRUE;
416 }
417 
418 gboolean
qtdemux_dump_stts(GstQTDemux * qtdemux,GstByteReader * data,int depth)419 qtdemux_dump_stts (GstQTDemux * qtdemux, GstByteReader * data, int depth)
420 {
421   guint32 ver_flags = 0, num_entries = 0, i;
422 
423   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
424       !gst_byte_reader_get_uint32_be (data, &num_entries))
425     return FALSE;
426 
427   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
428   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
429 
430   if (!qt_atom_parser_has_chunks (data, num_entries, 4 + 4))
431     return FALSE;
432 
433   for (i = 0; i < num_entries; i++) {
434     GST_LOG ("%*s    count:         %u", depth, "", GET_UINT32 (data));
435     GST_LOG ("%*s    duration:      %u", depth, "", GET_UINT32 (data));
436   }
437   return TRUE;
438 }
439 
440 gboolean
qtdemux_dump_stps(GstQTDemux * qtdemux,GstByteReader * data,int depth)441 qtdemux_dump_stps (GstQTDemux * qtdemux, GstByteReader * data, int depth)
442 {
443   guint32 ver_flags = 0, num_entries = 0, i;
444 
445   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
446       !gst_byte_reader_get_uint32_be (data, &num_entries))
447     return FALSE;
448 
449   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
450   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
451 
452   if (!qt_atom_parser_has_chunks (data, num_entries, 4))
453     return FALSE;
454 
455   for (i = 0; i < num_entries; i++) {
456     GST_LOG ("%*s    sample:        %u", depth, "", GET_UINT32 (data));
457   }
458   return TRUE;
459 }
460 
461 gboolean
qtdemux_dump_stss(GstQTDemux * qtdemux,GstByteReader * data,int depth)462 qtdemux_dump_stss (GstQTDemux * qtdemux, GstByteReader * data, int depth)
463 {
464   guint32 ver_flags = 0, num_entries = 0, i;
465 
466   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
467       !gst_byte_reader_get_uint32_be (data, &num_entries))
468     return FALSE;
469 
470   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
471   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
472 
473   if (!qt_atom_parser_has_chunks (data, num_entries, 4))
474     return FALSE;
475 
476   for (i = 0; i < num_entries; i++) {
477     GST_LOG ("%*s    sample:        %u", depth, "", GET_UINT32 (data));
478   }
479   return TRUE;
480 }
481 
482 gboolean
qtdemux_dump_stsc(GstQTDemux * qtdemux,GstByteReader * data,int depth)483 qtdemux_dump_stsc (GstQTDemux * qtdemux, GstByteReader * data, int depth)
484 {
485   guint32 ver_flags = 0, num_entries = 0, i;
486 
487   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
488       !gst_byte_reader_get_uint32_be (data, &num_entries))
489     return FALSE;
490 
491   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
492   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
493 
494   if (!qt_atom_parser_has_chunks (data, num_entries, 4 + 4 + 4))
495     return FALSE;
496 
497   for (i = 0; i < num_entries; i++) {
498     GST_LOG ("%*s    first chunk:   %u", depth, "", GET_UINT32 (data));
499     GST_LOG ("%*s    sample per ch: %u", depth, "", GET_UINT32 (data));
500     GST_LOG ("%*s    sample desc id:%08x", depth, "", GET_UINT32 (data));
501   }
502   return TRUE;
503 }
504 
505 gboolean
qtdemux_dump_stsz(GstQTDemux * qtdemux,GstByteReader * data,int depth)506 qtdemux_dump_stsz (GstQTDemux * qtdemux, GstByteReader * data, int depth)
507 {
508   guint32 ver_flags = 0, sample_size = 0, num_entries = 0, i;
509 
510   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
511       !gst_byte_reader_get_uint32_be (data, &sample_size))
512     return FALSE;
513 
514   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
515   GST_LOG ("%*s  sample size:   %d", depth, "", sample_size);
516 
517   if (sample_size == 0) {
518     if (!gst_byte_reader_get_uint32_be (data, &num_entries))
519       return FALSE;
520 
521     GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
522     if (!qt_atom_parser_has_chunks (data, num_entries, 4))
523       return FALSE;
524     for (i = 0; i < num_entries; i++) {
525       GST_TRACE ("%*s    sample size:   %u", depth, "", GET_UINT32 (data));
526     }
527   }
528   return TRUE;
529 }
530 
531 gboolean
qtdemux_dump_stco(GstQTDemux * qtdemux,GstByteReader * data,int depth)532 qtdemux_dump_stco (GstQTDemux * qtdemux, GstByteReader * data, int depth)
533 {
534   guint32 ver_flags = 0, num_entries = 0, i;
535 
536   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
537       !gst_byte_reader_get_uint32_be (data, &num_entries))
538     return FALSE;
539 
540   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
541   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
542 
543   if (!qt_atom_parser_has_chunks (data, num_entries, 4))
544     return FALSE;
545 
546   for (i = 0; i < num_entries; i++) {
547     GST_LOG ("%*s    chunk offset:  %u", depth, "", GET_UINT32 (data));
548   }
549   return TRUE;
550 }
551 
552 gboolean
qtdemux_dump_ctts(GstQTDemux * qtdemux,GstByteReader * data,int depth)553 qtdemux_dump_ctts (GstQTDemux * qtdemux, GstByteReader * data, int depth)
554 {
555   guint32 ver_flags = 0, num_entries = 0, i, count;
556   gint32 offset;
557 
558 
559   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
560       !gst_byte_reader_get_uint32_be (data, &num_entries))
561     return FALSE;
562 
563   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
564   GST_LOG ("%*s  n entries:     %u", depth, "", num_entries);
565 
566   if (!qt_atom_parser_has_chunks (data, num_entries, 4 + 4))
567     return FALSE;
568 
569   for (i = 0; i < num_entries; i++) {
570     count = GET_UINT32 (data);
571     offset = GET_UINT32 (data);
572     GST_LOG ("%*s    sample count :%8d offset: %8d", depth, "", count, offset);
573   }
574   return TRUE;
575 }
576 
577 gboolean
qtdemux_dump_cslg(GstQTDemux * qtdemux,GstByteReader * data,int depth)578 qtdemux_dump_cslg (GstQTDemux * qtdemux, GstByteReader * data, int depth)
579 {
580   guint32 ver_flags = 0, shift = 0;
581   gint32 least_offset = 0, start_time = 0, end_time = 0;
582 
583   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
584       !gst_byte_reader_get_uint32_be (data, &shift) ||
585       !gst_byte_reader_get_int32_be (data, &least_offset) ||
586       !gst_byte_reader_get_int32_be (data, &start_time) ||
587       !gst_byte_reader_get_int32_be (data, &end_time))
588     return FALSE;
589 
590   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
591   GST_LOG ("%*s  shift:         %u", depth, "", shift);
592   GST_LOG ("%*s  least offset:  %d", depth, "", least_offset);
593   GST_LOG ("%*s  start time:    %d", depth, "", start_time);
594   GST_LOG ("%*s  end time:      %d", depth, "", end_time);
595 
596   return TRUE;
597 }
598 
599 gboolean
qtdemux_dump_co64(GstQTDemux * qtdemux,GstByteReader * data,int depth)600 qtdemux_dump_co64 (GstQTDemux * qtdemux, GstByteReader * data, int depth)
601 {
602   guint32 ver_flags = 0, num_entries = 0, i;
603 
604   if (!gst_byte_reader_get_uint32_be (data, &ver_flags) ||
605       !gst_byte_reader_get_uint32_be (data, &num_entries))
606     return FALSE;
607 
608   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
609   GST_LOG ("%*s  n entries:     %d", depth, "", num_entries);
610 
611   if (!qt_atom_parser_has_chunks (data, num_entries, 8))
612     return FALSE;
613 
614   for (i = 0; i < num_entries; i++) {
615     GST_LOG ("%*s    chunk offset:  %" G_GUINT64_FORMAT, depth, "",
616         GET_UINT64 (data));
617   }
618   return TRUE;
619 }
620 
621 gboolean
qtdemux_dump_dcom(GstQTDemux * qtdemux,GstByteReader * data,int depth)622 qtdemux_dump_dcom (GstQTDemux * qtdemux, GstByteReader * data, int depth)
623 {
624   if (!qt_atom_parser_has_remaining (data, 4))
625     return FALSE;
626 
627   GST_LOG ("%*s  compression type: %" GST_FOURCC_FORMAT, depth, "",
628       GST_FOURCC_ARGS (GET_FOURCC (data)));
629   return TRUE;
630 }
631 
632 gboolean
qtdemux_dump_cmvd(GstQTDemux * qtdemux,GstByteReader * data,int depth)633 qtdemux_dump_cmvd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
634 {
635   if (!qt_atom_parser_has_remaining (data, 4))
636     return FALSE;
637 
638   GST_LOG ("%*s  length: %d", depth, "", GET_UINT32 (data));
639   return TRUE;
640 }
641 
642 gboolean
qtdemux_dump_mfro(GstQTDemux * qtdemux,GstByteReader * data,int depth)643 qtdemux_dump_mfro (GstQTDemux * qtdemux, GstByteReader * data, int depth)
644 {
645   if (!qt_atom_parser_has_remaining (data, 4))
646     return FALSE;
647 
648   GST_LOG ("%*s  version/flags: %08x", depth, "", GET_UINT32 (data));
649   GST_LOG ("%*s  size: %d", depth, "", GET_UINT32 (data));
650   return TRUE;
651 }
652 
653 gboolean
qtdemux_dump_mfhd(GstQTDemux * qtdemux,GstByteReader * data,int depth)654 qtdemux_dump_mfhd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
655 {
656   if (!qt_atom_parser_has_remaining (data, 4))
657     return FALSE;
658 
659   GST_LOG ("%*s  version/flags: %08x", depth, "", GET_UINT32 (data));
660   GST_LOG ("%*s  sequence_number: %d", depth, "", GET_UINT32 (data));
661   return TRUE;
662 }
663 
664 gboolean
qtdemux_dump_tfra(GstQTDemux * qtdemux,GstByteReader * data,int depth)665 qtdemux_dump_tfra (GstQTDemux * qtdemux, GstByteReader * data, int depth)
666 {
667   guint64 time = 0, moof_offset = 0;
668   guint32 len = 0, num_entries = 0, ver_flags = 0, track_id = 0, i;
669   guint value_size, traf_size, trun_size, sample_size;
670 
671   if (!gst_byte_reader_get_uint32_be (data, &ver_flags))
672     return FALSE;
673 
674   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
675 
676   if (!gst_byte_reader_get_uint32_be (data, &track_id) ||
677       !gst_byte_reader_get_uint32_be (data, &len) ||
678       !gst_byte_reader_get_uint32_be (data, &num_entries))
679     return FALSE;
680 
681   GST_LOG ("%*s  track ID:      %u", depth, "", track_id);
682   GST_LOG ("%*s  length:        0x%x", depth, "", len);
683   GST_LOG ("%*s  n entries:     %u", depth, "", num_entries);
684 
685   value_size = ((ver_flags >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
686   sample_size = (len & 3) + 1;
687   trun_size = ((len & 12) >> 2) + 1;
688   traf_size = ((len & 48) >> 4) + 1;
689 
690   if (!qt_atom_parser_has_chunks (data, num_entries,
691           value_size + value_size + traf_size + trun_size + sample_size))
692     return FALSE;
693 
694   for (i = 0; i < num_entries; i++) {
695     qt_atom_parser_get_offset (data, value_size, &time);
696     qt_atom_parser_get_offset (data, value_size, &moof_offset);
697     GST_LOG ("%*s    time:          %" G_GUINT64_FORMAT, depth, "", time);
698     GST_LOG ("%*s    moof_offset:   %" G_GUINT64_FORMAT,
699         depth, "", moof_offset);
700     GST_LOG ("%*s    traf_number:   %u", depth, "",
701         qt_atom_parser_get_uint_with_size_unchecked (data, traf_size));
702     GST_LOG ("%*s    trun_number:   %u", depth, "",
703         qt_atom_parser_get_uint_with_size_unchecked (data, trun_size));
704     GST_LOG ("%*s    sample_number: %u", depth, "",
705         qt_atom_parser_get_uint_with_size_unchecked (data, sample_size));
706   }
707 
708   return TRUE;
709 }
710 
711 gboolean
qtdemux_dump_tfhd(GstQTDemux * qtdemux,GstByteReader * data,int depth)712 qtdemux_dump_tfhd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
713 {
714   guint32 flags = 0, n = 0, track_id = 0;
715   guint64 base_data_offset = 0;
716 
717   if (!gst_byte_reader_skip (data, 1) ||
718       !gst_byte_reader_get_uint24_be (data, &flags))
719     return FALSE;
720   GST_LOG ("%*s  flags: %08x", depth, "", flags);
721 
722   if (!gst_byte_reader_get_uint32_be (data, &track_id))
723     return FALSE;
724   GST_LOG ("%*s  track_id: %u", depth, "", track_id);
725 
726   if (flags & TF_BASE_DATA_OFFSET) {
727     if (!gst_byte_reader_get_uint64_be (data, &base_data_offset))
728       return FALSE;
729     GST_LOG ("%*s    base-data-offset: %" G_GUINT64_FORMAT,
730         depth, "", base_data_offset);
731   }
732 
733   if (flags & TF_SAMPLE_DESCRIPTION_INDEX) {
734     if (!gst_byte_reader_get_uint32_be (data, &n))
735       return FALSE;
736     GST_LOG ("%*s    sample-description-index: %u", depth, "", n);
737   }
738 
739   if (flags & TF_DEFAULT_SAMPLE_DURATION) {
740     if (!gst_byte_reader_get_uint32_be (data, &n))
741       return FALSE;
742     GST_LOG ("%*s    default-sample-duration:  %u", depth, "", n);
743   }
744 
745   if (flags & TF_DEFAULT_SAMPLE_SIZE) {
746     if (!gst_byte_reader_get_uint32_be (data, &n))
747       return FALSE;
748     GST_LOG ("%*s    default-sample-size:  %u", depth, "", n);
749   }
750 
751   if (flags & TF_DEFAULT_SAMPLE_FLAGS) {
752     if (!gst_byte_reader_get_uint32_be (data, &n))
753       return FALSE;
754     GST_LOG ("%*s    default-sample-flags:  %u", depth, "", n);
755   }
756 
757   GST_LOG ("%*s    duration-is-empty:     %s", depth, "",
758       flags & TF_DURATION_IS_EMPTY ? "yes" : "no");
759 
760   return TRUE;
761 }
762 
763 gboolean
qtdemux_dump_trun(GstQTDemux * qtdemux,GstByteReader * data,int depth)764 qtdemux_dump_trun (GstQTDemux * qtdemux, GstByteReader * data, int depth)
765 {
766   guint32 flags = 0, samples_count = 0, data_offset = 0, first_sample_flags = 0;
767   guint32 sample_duration = 0, sample_size = 0, sample_flags =
768       0, composition_time_offsets = 0;
769   int i = 0;
770 
771   if (!gst_byte_reader_skip (data, 1) ||
772       !gst_byte_reader_get_uint24_be (data, &flags))
773     return FALSE;
774 
775   GST_LOG ("%*s  flags: %08x", depth, "", flags);
776 
777   if (!gst_byte_reader_get_uint32_be (data, &samples_count))
778     return FALSE;
779   GST_LOG ("%*s  samples_count: %u", depth, "", samples_count);
780 
781   if (flags & TR_DATA_OFFSET) {
782     if (!gst_byte_reader_get_uint32_be (data, &data_offset))
783       return FALSE;
784     GST_LOG ("%*s    data-offset: %u", depth, "", data_offset);
785   }
786 
787   if (flags & TR_FIRST_SAMPLE_FLAGS) {
788     if (!gst_byte_reader_get_uint32_be (data, &first_sample_flags))
789       return FALSE;
790     GST_LOG ("%*s    first-sample-flags: %u", depth, "", first_sample_flags);
791   }
792 
793   for (i = 0; i < samples_count; i++) {
794     if (flags & TR_SAMPLE_DURATION) {
795       if (!gst_byte_reader_get_uint32_be (data, &sample_duration))
796         return FALSE;
797       GST_TRACE ("%*s    sample-duration:  %u", depth, "", sample_duration);
798     }
799 
800     if (flags & TR_SAMPLE_SIZE) {
801       if (!gst_byte_reader_get_uint32_be (data, &sample_size))
802         return FALSE;
803       GST_TRACE ("%*s    sample-size:  %u", depth, "", sample_size);
804     }
805 
806     if (flags & TR_SAMPLE_FLAGS) {
807       if (!gst_byte_reader_get_uint32_be (data, &sample_flags))
808         return FALSE;
809       GST_TRACE ("%*s    sample-flags:  %u", depth, "", sample_flags);
810     }
811 
812     if (flags & TR_COMPOSITION_TIME_OFFSETS) {
813       if (!gst_byte_reader_get_uint32_be (data, &composition_time_offsets))
814         return FALSE;
815       GST_TRACE ("%*s    composition_time_offsets:  %u", depth, "",
816           composition_time_offsets);
817     }
818   }
819 
820   return TRUE;
821 }
822 
823 gboolean
qtdemux_dump_trex(GstQTDemux * qtdemux,GstByteReader * data,int depth)824 qtdemux_dump_trex (GstQTDemux * qtdemux, GstByteReader * data, int depth)
825 {
826   if (!qt_atom_parser_has_remaining (data, 4 + 4 + 4 + 4 + 4 + 4))
827     return FALSE;
828 
829   GST_LOG ("%*s  version/flags: %08x", depth, "", GET_UINT32 (data));
830   GST_LOG ("%*s  track ID:      %08x", depth, "", GET_UINT32 (data));
831   GST_LOG ("%*s  default sample desc. index: %08x", depth, "",
832       GET_UINT32 (data));
833   GST_LOG ("%*s  default sample duration:    %08x", depth, "",
834       GET_UINT32 (data));
835   GST_LOG ("%*s  default sample size:        %08x", depth, "",
836       GET_UINT32 (data));
837   GST_LOG ("%*s  default sample flags:       %08x", depth, "",
838       GET_UINT32 (data));
839 
840   return TRUE;
841 }
842 
843 gboolean
qtdemux_dump_mehd(GstQTDemux * qtdemux,GstByteReader * data,int depth)844 qtdemux_dump_mehd (GstQTDemux * qtdemux, GstByteReader * data, int depth)
845 {
846   guint32 version = 0;
847   guint64 fragment_duration;
848   guint value_size;
849 
850   if (!gst_byte_reader_get_uint32_be (data, &version))
851     return FALSE;
852 
853   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
854 
855   value_size = ((version >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
856   if (qt_atom_parser_get_offset (data, value_size, &fragment_duration)) {
857     GST_LOG ("%*s  fragment duration: %" G_GUINT64_FORMAT,
858         depth, "", fragment_duration);
859     return TRUE;
860   }
861 
862   return FALSE;
863 }
864 
865 gboolean
qtdemux_dump_tfdt(GstQTDemux * qtdemux,GstByteReader * data,int depth)866 qtdemux_dump_tfdt (GstQTDemux * qtdemux, GstByteReader * data, int depth)
867 {
868   guint32 version = 0;
869   guint64 decode_time;
870   guint value_size;
871 
872   if (!gst_byte_reader_get_uint32_be (data, &version))
873     return FALSE;
874 
875   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
876 
877   value_size = ((version >> 24) == 1) ? sizeof (guint64) : sizeof (guint32);
878   if (qt_atom_parser_get_offset (data, value_size, &decode_time)) {
879     GST_LOG ("%*s  Track fragment decode time: %" G_GUINT64_FORMAT,
880         depth, "", decode_time);
881     return TRUE;
882   }
883 
884   return FALSE;
885 }
886 
887 gboolean
qtdemux_dump_sdtp(GstQTDemux * qtdemux,GstByteReader * data,int depth)888 qtdemux_dump_sdtp (GstQTDemux * qtdemux, GstByteReader * data, int depth)
889 {
890   guint32 version;
891   guint8 val;
892   guint i = 1;
893 
894   version = GET_UINT32 (data);
895   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
896 
897   /* the sample_count is specified in the stsz or stz2 box.
898    * the information for a sample is stored in a single byte,
899    * so we read until there are no remaining bytes */
900   while (qt_atom_parser_has_remaining (data, 1)) {
901     val = GET_UINT8 (data);
902     GST_LOG ("%*s     sample number: %d", depth, "", i);
903     GST_LOG ("%*s     sample_depends_on: %d", depth, "",
904         ((guint16) (val)) & 0x3);
905     GST_LOG ("%*s     sample_is_depended_on: %d", depth, "",
906         ((guint16) (val >> 2)) & 0x3);
907     GST_LOG ("%*s     sample_has_redundancy: %d", depth, "",
908         ((guint16) (val >> 4)) & 0x3);
909     GST_LOG ("%*s     early display: %d", depth, "",
910         ((guint16) (val >> 6)) & 0x1);
911     ++i;
912   }
913   return TRUE;
914 }
915 
916 gboolean
qtdemux_dump_svmi(GstQTDemux * qtdemux,GstByteReader * data,int depth)917 qtdemux_dump_svmi (GstQTDemux * qtdemux, GstByteReader * data, int depth)
918 {
919   guint32 version;
920   guint stereo_mono_change_count;
921   guint i;
922 
923   version = GET_UINT32 (data);
924   GST_LOG ("%*s  version/flags: %08x", depth, "", version);
925 
926   if (!version) {
927     /* stereoscopic visual type information */
928     GST_LOG ("%*s     stereo_composition_type: %d", depth, "",
929         GET_UINT8 (data));
930     GST_LOG ("%*s     is_left_first: %d", depth, "",
931         ((guint8) GET_UINT8 (data)) & 0x01);
932 
933     /* stereo_mono_change information */
934     stereo_mono_change_count = GET_UINT32 (data);
935     GST_LOG ("%*s     stereo_mono_change_count: %d", depth, "",
936         stereo_mono_change_count);
937     for (i = 1; i <= stereo_mono_change_count; i++) {
938       GST_LOG ("%*s     sample_count: %d", depth, "", GET_UINT32 (data));
939       GST_LOG ("%*s     stereo_flag: %d", depth, "",
940           ((guint8) GET_UINT8 (data)) & 0x01);
941     }
942   }
943   return TRUE;
944 }
945 
946 gboolean
qtdemux_dump_dfLa(GstQTDemux * qtdemux,GstByteReader * data,int depth)947 qtdemux_dump_dfLa (GstQTDemux * qtdemux, GstByteReader * data, int depth)
948 {
949   const gchar *block_types[] = {
950     "STREAMINFO", "PADDING", "APPLICATION", "SEEKTABLE", "VORBIS_COMMENT",
951     "CUESHEET", "PICTURE", "UNKNOWN", "INVALID"
952   };
953 
954   guint32 ver_flags, block_header, block_size;
955   gint8 block_type;
956   gboolean isLast = FALSE;
957 
958   if (!gst_byte_reader_get_uint32_be (data, &ver_flags))
959     return FALSE;
960 
961   GST_LOG ("%*s  version/flags: %08x", depth, "", ver_flags);
962 
963   do {
964     if (!gst_byte_reader_get_uint32_be (data, &block_header))
965       break;
966 
967     isLast = (block_header >> 31) & 1;
968     block_type = (block_header >> 24) & 0x7F;
969     block_size = block_header & 0xFFFFFF;
970 
971     if (block_type == 127)
972       block_type = 8;
973     else if (block_type > 6)
974       block_type = 7;
975 
976     GST_LOG ("%*s  block_type:      %s", depth, "", block_types[block_type]);
977     GST_LOG ("%*s  last-block-flag: %s", depth, "", isLast ? "true" : "false");
978     GST_LOG ("%*s  length:          %d", depth, "", block_size);
979 
980     if (!gst_byte_reader_skip (data, block_size))
981       break;
982   } while (!isLast);
983 
984   return TRUE;
985 }
986 
987 gboolean
qtdemux_dump_fLaC(GstQTDemux * qtdemux,GstByteReader * data,int depth)988 qtdemux_dump_fLaC (GstQTDemux * qtdemux, GstByteReader * data, int depth)
989 {
990   guint16 data_ref_id, n_channels, sample_size;
991   guint32 sample_rate;
992 
993   if (!gst_byte_reader_skip (data, 6) ||
994       !gst_byte_reader_get_uint16_be (data, &data_ref_id) ||
995       !gst_byte_reader_skip (data, 8) ||
996       !gst_byte_reader_get_uint16_be (data, &n_channels) ||
997       !gst_byte_reader_get_uint16_be (data, &sample_size) ||
998       !gst_byte_reader_skip (data, 4) ||
999       !gst_byte_reader_get_uint32_be (data, &sample_rate))
1000     return FALSE;
1001 
1002   GST_LOG ("%*s  data reference: %d", depth, "", data_ref_id);
1003   GST_LOG ("%*s  channel count:  %d", depth, "", n_channels);
1004   GST_LOG ("%*s  sample size:    %d", depth, "", sample_size);
1005   GST_LOG ("%*s  sample rate:    %d", depth, "", (sample_rate >> 16));
1006 
1007   return TRUE;
1008 }
1009 
1010 gboolean
qtdemux_dump_gmin(GstQTDemux * qtdemux,GstByteReader * data,int depth)1011 qtdemux_dump_gmin (GstQTDemux * qtdemux, GstByteReader * data, int depth)
1012 {
1013   guint32 ver_flags;
1014   guint16 graphics_mode, opc_r, opc_g, opc_b, balance;
1015 
1016   if (!gst_byte_reader_get_uint32_be (data, &ver_flags))
1017     return FALSE;
1018 
1019   GST_LOG ("%*s  version/flags : %08x", depth, "", ver_flags);
1020   if (!gst_byte_reader_get_uint16_be (data, &graphics_mode) ||
1021       !gst_byte_reader_get_uint16_be (data, &opc_r) ||
1022       !gst_byte_reader_get_uint16_be (data, &opc_g) ||
1023       !gst_byte_reader_get_uint16_be (data, &opc_b) ||
1024       !gst_byte_reader_get_uint16_be (data, &balance))
1025     return FALSE;
1026 
1027   GST_LOG ("%*s  graphics mode : 0x%x", depth, "", graphics_mode);
1028   GST_LOG ("%*s  opcolor :       r:0x%x g:0x%x b:0x%x", depth, "", opc_r, opc_g,
1029       opc_b);
1030   GST_LOG ("%*s  balance :       %d", depth, "", balance);
1031 
1032   return TRUE;
1033 }
1034 
1035 gboolean
qtdemux_dump_unknown(GstQTDemux * qtdemux,GstByteReader * data,int depth)1036 qtdemux_dump_unknown (GstQTDemux * qtdemux, GstByteReader * data, int depth)
1037 {
1038   int len;
1039 
1040   len = gst_byte_reader_get_remaining (data);
1041   GST_LOG ("%*s  length: %d", depth, "", len);
1042 
1043   GST_MEMDUMP_OBJECT (qtdemux, "unknown atom data",
1044       gst_byte_reader_peek_data_unchecked (data), len);
1045   return TRUE;
1046 }
1047 
1048 static gboolean
qtdemux_node_dump_foreach(GNode * node,gpointer qtdemux)1049 qtdemux_node_dump_foreach (GNode * node, gpointer qtdemux)
1050 {
1051   GstByteReader parser;
1052   guint8 *buffer = (guint8 *) node->data;       /* FIXME: move to byte reader */
1053   guint32 node_length;
1054   guint32 fourcc;
1055   const QtNodeType *type;
1056   int depth;
1057 
1058   node_length = GST_READ_UINT32_BE (buffer);
1059   fourcc = GST_READ_UINT32_LE (buffer + 4);
1060 
1061   g_warn_if_fail (node_length >= 8);
1062 
1063   gst_byte_reader_init (&parser, buffer + 8, node_length - 8);
1064 
1065   type = qtdemux_type_get (fourcc);
1066 
1067   depth = (g_node_depth (node) - 1) * 2;
1068   GST_LOG ("%*s'%" GST_FOURCC_FORMAT "', [%d], %s",
1069       depth, "", GST_FOURCC_ARGS (fourcc), node_length, type->name);
1070 
1071   if (type->dump) {
1072     gboolean ret;
1073 
1074     ret = type->dump (GST_QTDEMUX_CAST (qtdemux), &parser, depth);
1075 
1076     if (!ret) {
1077       GST_WARNING ("%*s  not enough data parsing atom %" GST_FOURCC_FORMAT,
1078           depth, "", GST_FOURCC_ARGS (fourcc));
1079     }
1080   }
1081 
1082   return FALSE;
1083 }
1084 
1085 gboolean
qtdemux_node_dump(GstQTDemux * qtdemux,GNode * node)1086 qtdemux_node_dump (GstQTDemux * qtdemux, GNode * node)
1087 {
1088 #ifndef GST_DISABLE_GST_DEBUG
1089   /* Only traverse/dump if we know it will be outputted in the end */
1090   if (qtdemux_debug->threshold < GST_LEVEL_LOG)
1091     return TRUE;
1092 
1093   g_node_traverse (node, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
1094       qtdemux_node_dump_foreach, qtdemux);
1095 #endif
1096   return TRUE;
1097 }
1098