1 #include <gst/check/gstcheck.h>
2 #include <gst/base/base.h>
3 #include <gst/isoff/gstisoff.h>
4 
5 #include "isoff.h"
6 
GST_START_TEST(isoff_box_header_minimal)7 GST_START_TEST (isoff_box_header_minimal)
8 {
9   /* INDENT-OFF */
10   static const guint8 data[] = {
11     16, 32, 64, 128,
12     't', 'e', 's', 't'
13   };
14   /* INDENT-ON */
15   GstByteReader reader = GST_BYTE_READER_INIT (data, sizeof (data));
16   guint32 type;
17   guint8 extended_type[16];
18   guint header_size;
19   guint64 size;
20 
21   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
22           &header_size, &size));
23   fail_unless (type == GST_MAKE_FOURCC ('t', 'e', 's', 't'));
24   fail_unless_equals_int (header_size, 8);
25   fail_unless_equals_uint64 (size, 0x10204080);
26 }
27 
28 GST_END_TEST;
29 
GST_START_TEST(isoff_box_header_long_size)30 GST_START_TEST (isoff_box_header_long_size)
31 {
32   /* INDENT-OFF */
33   static const guint8 data[] = {
34     0, 0, 0, 1,
35     't', 'e', 's', 't',
36     1, 2, 4, 8, 16, 32, 64, 128
37   };
38   /* INDENT-ON */
39   GstByteReader reader = GST_BYTE_READER_INIT (data, sizeof (data));
40   guint32 type;
41   guint8 extended_type[16];
42   guint header_size;
43   guint64 size;
44 
45   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
46           &header_size, &size));
47   fail_unless (type == GST_MAKE_FOURCC ('t', 'e', 's', 't'));
48   fail_unless_equals_int (header_size, 16);
49   fail_unless_equals_uint64 (size, G_GUINT64_CONSTANT (0x0102040810204080));
50 }
51 
52 GST_END_TEST;
53 
GST_START_TEST(isoff_box_header_uuid_type)54 GST_START_TEST (isoff_box_header_uuid_type)
55 {
56   /* INDENT-OFF */
57   static const guint8 data[] = {
58     16, 32, 64, 128,
59     'u', 'u', 'i', 'd',
60     'a', 'b', 'c', 'd',
61     'e', 'f', 'g', 'h',
62     'i', 'j', 'k', 'l',
63     'm', 'n', 'o', 'p'
64   };
65   /* INDENT-ON */
66   GstByteReader reader = GST_BYTE_READER_INIT (data, sizeof (data));
67   guint32 type;
68   guint8 extended_type[16];
69   guint header_size;
70   guint64 size;
71 
72   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
73           &header_size, &size));
74   fail_unless (type == GST_MAKE_FOURCC ('u', 'u', 'i', 'd'));
75   fail_unless_equals_int (header_size, 24);
76   fail_unless_equals_uint64 (size, 0x10204080);
77   fail_unless (memcmp (data + 8, extended_type, 16) == 0);
78 }
79 
80 GST_END_TEST;
81 
GST_START_TEST(isoff_box_header_uuid_type_long_size)82 GST_START_TEST (isoff_box_header_uuid_type_long_size)
83 {
84   /* INDENT-OFF */
85   static const guint8 data[] = {
86     0, 0, 0, 1,
87     'u', 'u', 'i', 'd',
88     1, 2, 4, 8, 16, 32, 64, 128,
89     'a', 'b', 'c', 'd',
90     'e', 'f', 'g', 'h',
91     'i', 'j', 'k', 'l',
92     'm', 'n', 'o', 'p'
93   };
94   /* INDENT-ON */
95   GstByteReader reader = GST_BYTE_READER_INIT (data, sizeof (data));
96   guint32 type;
97   guint8 extended_type[16];
98   guint header_size;
99   guint64 size;
100 
101   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
102           &header_size, &size));
103   fail_unless (type == GST_MAKE_FOURCC ('u', 'u', 'i', 'd'));
104   fail_unless_equals_int (header_size, 32);
105   fail_unless_equals_uint64 (size, G_GUINT64_CONSTANT (0x0102040810204080));
106   fail_unless (memcmp (data + 16, extended_type, 16) == 0);
107 }
108 
109 GST_END_TEST;
110 
GST_START_TEST(isoff_moof_parse)111 GST_START_TEST (isoff_moof_parse)
112 {
113   /* INDENT-ON */
114   GstByteReader reader = GST_BYTE_READER_INIT (moof1, sizeof (moof1));
115   guint32 type;
116   guint8 extended_type[16];
117   guint header_size;
118   guint64 size;
119   GstMoofBox *moof;
120   GstTrafBox *traf;
121   GstTrunBox *trun;
122   guint i;
123 
124   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
125           &header_size, &size));
126   fail_unless (type == GST_MAKE_FOURCC ('m', 'o', 'o', 'f'));
127   fail_unless_equals_int (header_size, 8);
128   fail_unless_equals_uint64 (size, sizeof (moof1));
129 
130   moof = gst_isoff_moof_box_parse (&reader);
131   fail_unless (moof != NULL);
132 
133   fail_unless_equals_int (moof->mfhd.sequence_number, 1);
134   fail_unless_equals_int (moof->traf->len, 1);
135 
136   traf = &g_array_index (moof->traf, GstTrafBox, 0);
137   fail_unless_equals_int (traf->tfhd.version, 0);
138   fail_unless_equals_int (traf->tfhd.flags,
139       GST_TFHD_FLAGS_DEFAULT_SAMPLE_DURATION_PRESENT);
140   fail_unless_equals_int (traf->tfhd.track_id, 1);
141   fail_unless_equals_uint64 (traf->tfhd.base_data_offset, 0);
142   fail_unless_equals_int (traf->tfhd.sample_description_index, 0);
143   fail_unless_equals_int (traf->tfhd.default_sample_duration, 8);
144   fail_unless_equals_int (traf->tfhd.default_sample_size, 0);
145   fail_unless_equals_int (traf->tfhd.default_sample_flags, 0);
146 
147   fail_unless_equals_int (traf->trun->len, 1);
148   trun = &g_array_index (traf->trun, GstTrunBox, 0);
149 
150   fail_unless_equals_int (trun->version, 1);
151   fail_unless_equals_int (trun->flags,
152       GST_TRUN_FLAGS_SAMPLE_COMPOSITION_TIME_OFFSETS_PRESENT |
153       GST_TRUN_FLAGS_SAMPLE_FLAGS_PRESENT | GST_TRUN_FLAGS_SAMPLE_SIZE_PRESENT |
154       GST_TRUN_FLAGS_DATA_OFFSET_PRESENT);
155   fail_unless_equals_int (trun->sample_count, 96);
156   fail_unless_equals_int (trun->data_offset, size + header_size);
157   fail_unless_equals_int (trun->first_sample_flags, 0);
158 
159   fail_unless_equals_int (trun->samples->len, 96);
160 
161   for (i = 0; i < 96; i++) {
162     GstTrunSample *sample = &g_array_index (trun->samples, GstTrunSample, i);
163 
164     fail_unless_equals_int (sample->sample_duration, 0);
165     if (i == 0) {
166       /* sample_depends_on = 2 => I-frame */
167       /* sample_is_non_sync_sample = 0 */
168       fail_unless_equals_int (sample->sample_flags, 0x02000000);
169     } else {
170       /* sample_depends_on = 1 => non-I-frame */
171       /* sample_is_non_sync_sample = 1 */
172       fail_unless_equals_int (sample->sample_flags, 0x01010000);
173     }
174 
175     /* sample size and CTO is changing for each sample */
176   }
177 
178   gst_isoff_moof_box_free (moof);
179 }
180 
181 GST_END_TEST;
182 
GST_START_TEST(isoff_moof_parse_with_tfdt)183 GST_START_TEST (isoff_moof_parse_with_tfdt)
184 {
185   /* INDENT-ON */
186   GstByteReader reader = GST_BYTE_READER_INIT (seg_2_m4f, sizeof (seg_2_m4f));
187   guint32 type;
188   guint8 extended_type[16];
189   guint header_size;
190   guint64 size;
191   GstMoofBox *moof;
192   GstTrafBox *traf;
193   GstTrunBox *trun;
194   guint i;
195 
196   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
197           &header_size, &size));
198   fail_unless (type == GST_ISOFF_FOURCC_MOOF);
199   fail_unless_equals_int (header_size, 8);
200   fail_unless_equals_uint64 (size, seg_2_m4f_len);
201 
202   moof = gst_isoff_moof_box_parse (&reader);
203   fail_unless (moof != NULL);
204 
205   fail_unless_equals_int (moof->mfhd.sequence_number, 4);
206   fail_unless_equals_int (moof->traf->len, 1);
207 
208   traf = &g_array_index (moof->traf, GstTrafBox, 0);
209   fail_unless_equals_int (traf->tfhd.version, 0);
210   fail_unless_equals_int (traf->tfhd.flags,
211       GST_TFHD_FLAGS_DEFAULT_BASE_IS_MOOF);
212   fail_unless_equals_int (traf->tfhd.track_id, 2);
213   fail_unless_equals_uint64 (traf->tfhd.base_data_offset, 0);
214   fail_unless_equals_int (traf->tfhd.sample_description_index, 0);
215   fail_unless_equals_int (traf->tfhd.default_sample_duration, 0);
216   fail_unless_equals_int (traf->tfhd.default_sample_size, 0);
217   fail_unless_equals_int (traf->tfhd.default_sample_flags, 0);
218 
219   fail_unless_equals_uint64 (traf->tfdt.decode_time, 132096);
220 
221   fail_unless_equals_int (traf->trun->len, 1);
222   trun = &g_array_index (traf->trun, GstTrunBox, 0);
223 
224   fail_unless_equals_int (trun->version, 0);
225   fail_unless_equals_int (trun->flags,
226       GST_TRUN_FLAGS_SAMPLE_SIZE_PRESENT |
227       GST_TRUN_FLAGS_SAMPLE_DURATION_PRESENT |
228       GST_TRUN_FLAGS_DATA_OFFSET_PRESENT);
229   fail_unless_equals_int (trun->sample_count, 129);
230   fail_unless_equals_int (trun->data_offset, size + header_size);
231   fail_unless_equals_int (trun->first_sample_flags, 0);
232 
233   fail_unless_equals_int (trun->samples->len, 129);
234 
235   for (i = 0; i < 129; i++) {
236     GstTrunSample *sample = &g_array_index (trun->samples, GstTrunSample, i);
237 
238     fail_unless_equals_int (sample->sample_duration, seg_sample_duration);
239     fail_unless_equals_int (sample->sample_flags, 0x00000000);
240     fail_unless_equals_int (sample->sample_size, seg_2_sample_sizes[i]);
241   }
242 
243   gst_isoff_moof_box_free (moof);
244 }
245 
246 GST_END_TEST;
247 
GST_START_TEST(isoff_moof_parse_with_tfxd_tfrf)248 GST_START_TEST (isoff_moof_parse_with_tfxd_tfrf)
249 {
250   GstByteReader reader =
251       GST_BYTE_READER_INIT (Fragments_audio, sizeof (Fragments_audio));
252   guint32 type;
253   guint8 extended_type[16];
254   guint header_size;
255   guint64 size;
256   GstMoofBox *moof;
257   GstTrafBox *traf;
258   GstTfxdBox *tfxd;
259   GstTfrfBox *tfrf;
260   GstTfrfBoxEntry *tfrf_entry;
261 
262   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
263           &header_size, &size));
264   fail_unless (type == GST_ISOFF_FOURCC_MOOF);
265   fail_unless_equals_int (header_size, 8);
266   fail_unless_equals_uint64 (size, Fragments_audio_len);
267 
268   moof = gst_isoff_moof_box_parse (&reader);
269   fail_unless (moof != NULL);
270 
271   fail_unless_equals_int (moof->mfhd.sequence_number, 124);
272   fail_unless_equals_int (moof->traf->len, 1);
273 
274   traf = &g_array_index (moof->traf, GstTrafBox, 0);
275   fail_unless_equals_int (traf->tfhd.version, 0);
276   fail_unless_equals_int (traf->tfhd.flags,
277       GST_TFHD_FLAGS_DEFAULT_SAMPLE_FLAGS_PRESENT);
278   fail_unless_equals_int (traf->tfhd.track_id, 1);
279   fail_unless_equals_uint64 (traf->tfhd.base_data_offset, 0);
280   fail_unless_equals_int (traf->tfhd.sample_description_index, 0);
281   fail_unless_equals_int (traf->tfhd.default_sample_duration, 0);
282   fail_unless_equals_int (traf->tfhd.default_sample_size, 0);
283 
284   tfxd = traf->tfxd;
285   fail_unless (tfxd != NULL);
286   fail_unless_equals_uint64 (tfxd->time, 1188108174758706);
287   fail_unless_equals_uint64 (tfxd->duration, 19969161);
288 
289   tfrf = traf->tfrf;
290   fail_unless (tfrf != NULL);
291   fail_unless_equals_int (tfrf->entries_count, 2);
292   fail_unless_equals_int (tfrf->entries->len, 2);
293 
294   tfrf_entry = &g_array_index (tfrf->entries, GstTfrfBoxEntry, 0);
295   fail_unless (tfrf_entry != NULL);
296   fail_unless_equals_uint64 (tfrf_entry->time, 1188108194727867);
297   fail_unless_equals_uint64 (tfrf_entry->duration, 19969160);
298 
299   tfrf_entry = &g_array_index (tfrf->entries, GstTfrfBoxEntry, 1);
300   fail_unless (tfrf_entry != NULL);
301   fail_unless_equals_uint64 (tfrf_entry->time, 1188108214697027);
302   fail_unless_equals_uint64 (tfrf_entry->duration, 19969162);
303 
304   gst_isoff_moof_box_free (moof);
305 }
306 
307 GST_END_TEST;
308 
GST_START_TEST(isoff_moov_parse)309 GST_START_TEST (isoff_moov_parse)
310 {
311   /* INDENT-ON */
312   GstByteReader reader = GST_BYTE_READER_INIT (init_mp4, sizeof (init_mp4));
313   guint32 type;
314   guint8 extended_type[16];
315   guint header_size;
316   guint64 size;
317   GstMoovBox *moov;
318   GstTrakBox *trak;
319 
320   fail_unless (gst_isoff_parse_box_header (&reader, &type, extended_type,
321           &header_size, &size));
322   fail_unless (type == GST_ISOFF_FOURCC_MOOV);
323   fail_unless_equals_int (header_size, 8);
324   fail_unless_equals_uint64 (size, sizeof (init_mp4));
325 
326   moov = gst_isoff_moov_box_parse (&reader);
327   fail_unless (moov != NULL);
328 
329   fail_unless_equals_int (moov->trak->len, 1);
330 
331   trak = &g_array_index (moov->trak, GstTrakBox, 0);
332   fail_unless_equals_int (trak->tkhd.track_id, 2);
333   fail_unless (trak->mdia.hdlr.handler_type, GST_ISOFF_FOURCC_SOUN);
334   fail_unless_equals_int (trak->mdia.mdhd.timescale, seg_timescale);
335 
336   gst_isoff_moov_box_free (moov);
337 }
338 
339 GST_END_TEST;
340 
341 static Suite *
dash_isoff_suite(void)342 dash_isoff_suite (void)
343 {
344   Suite *s = suite_create ("isoff");
345   TCase *tc_isoff_box = tcase_create ("isoff-box-parsing");
346   TCase *tc_moof = tcase_create ("moof");
347   TCase *tc_moov = tcase_create ("moov");
348 
349   tcase_add_test (tc_isoff_box, isoff_box_header_minimal);
350   tcase_add_test (tc_isoff_box, isoff_box_header_long_size);
351   tcase_add_test (tc_isoff_box, isoff_box_header_uuid_type);
352   tcase_add_test (tc_isoff_box, isoff_box_header_uuid_type_long_size);
353 
354   suite_add_tcase (s, tc_isoff_box);
355 
356   tcase_add_test (tc_moof, isoff_moof_parse);
357   tcase_add_test (tc_moof, isoff_moof_parse_with_tfdt);
358   tcase_add_test (tc_moof, isoff_moof_parse_with_tfxd_tfrf);
359   suite_add_tcase (s, tc_moof);
360 
361   tcase_add_test (tc_moov, isoff_moov_parse);
362   suite_add_tcase (s, tc_moov);
363 
364   return s;
365 }
366 
367 GST_CHECK_MAIN (dash_isoff);
368