1 /*****************************************************************************
2 * mp4sys.c
3 *****************************************************************************
4 * Copyright (C) 2010-2017 L-SMASH project
5 *
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
7 * Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 *
9 * Permission to use, copy, modify, and/or distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *****************************************************************************/
21
22 /* This file is available under an ISC license. */
23
24 #include "common/internal.h" /* must be placed first */
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <inttypes.h>
29
30 #include "core/box.h"
31
32 #include "description.h"
33 #include "mp4a.h"
34 #define MP4SYS_INTERNAL
35 #include "mp4sys.h"
36
37 /***************************************************************************
38 MPEG-4 Systems
39 ***************************************************************************/
40
41 #define ALWAYS_28BITS_LENGTH_CODING 1 // for some weird (but originator's) devices
42
43 static const lsmash_class_t lsmash_mp4sys_class =
44 {
45 "mp4sys"
46 };
47
48 /* List of Class Tags for Descriptors */
49 typedef enum
50 {
51 MP4SYS_DESCRIPTOR_TAG_Forbidden = 0x00, /* Forbidden */
52 MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag = 0x01, /* ObjectDescrTag */
53 MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag = 0x02, /* InitialObjectDescrTag */
54 MP4SYS_DESCRIPTOR_TAG_ES_DescrTag = 0x03, /* ES_DescrTag */
55 MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag = 0x04, /* DecoderConfigDescrTag */
56 MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag = 0x05, /* DecSpecificInfoTag */
57 MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag = 0x06, /* SLConfigDescrTag */
58 MP4SYS_DESCRIPTOR_TAG_ContentIdentDescrTag = 0x07, /* ContentIdentDescrTag */
59 MP4SYS_DESCRIPTOR_TAG_SupplContentIdentDescrTag = 0x08, /* SupplContentIdentDescrTag */
60 MP4SYS_DESCRIPTOR_TAG_IPI_DescrPointerTag = 0x09, /* IPI_DescrPointerTag */
61 MP4SYS_DESCRIPTOR_TAG_IPMP_DescrPointerTag = 0x0A, /* IPMP_DescrPointerTag */
62 MP4SYS_DESCRIPTOR_TAG_IPMP_DescrTag = 0x0B, /* IPMP_DescrTag */
63 MP4SYS_DESCRIPTOR_TAG_QoS_DescrTag = 0x0C, /* QoS_DescrTag */
64 MP4SYS_DESCRIPTOR_TAG_RegistrationDescrTag = 0x0D, /* RegistrationDescrTag */
65 MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag = 0x0E, /* ES_ID_IncTag */
66 MP4SYS_DESCRIPTOR_TAG_ES_ID_RefTag = 0x0F, /* ES_ID_RefTag */
67 MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag = 0x10, /* MP4_IOD_Tag, InitialObjectDescriptor for MP4 */
68 MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag = 0x11, /* MP4_OD_Tag, ObjectDescriptor for MP4 */
69 MP4SYS_DESCRIPTOR_TAG_IPI_DescrPointerRefTag = 0x12, /* IPI_DescrPointerRefTag */
70 MP4SYS_DESCRIPTOR_TAG_ExtendedProfileLevelDescrTag = 0x13, /* ExtendedProfileLevelDescrTag */
71 MP4SYS_DESCRIPTOR_TAG_profileLevelIndicationIndexDescrTag = 0x14, /* profileLevelIndicationIndexDescrTag */
72 MP4SYS_DESCRIPTOR_TAG_ContentClassificationDescrTag = 0x40, /* ContentClassificationDescrTag */
73 MP4SYS_DESCRIPTOR_TAG_KeyWordDescrTag = 0x41, /* KeyWordDescrTag */
74 MP4SYS_DESCRIPTOR_TAG_RatingDescrTag = 0x42, /* RatingDescrTag */
75 MP4SYS_DESCRIPTOR_TAG_LanguageDescrTag = 0x43, /* LanguageDescrTag */
76 MP4SYS_DESCRIPTOR_TAG_ShortTextualDescrTag = 0x44, /* ShortTextualDescrTag */
77 MP4SYS_DESCRIPTOR_TAG_ExpandedTextualDescrTag = 0x45, /* ExpandedTextualDescrTag */
78 MP4SYS_DESCRIPTOR_TAG_ContentCreatorNameDescrTag = 0x46, /* ContentCreatorNameDescrTag */
79 MP4SYS_DESCRIPTOR_TAG_ContentCreationDateDescrTag = 0x47, /* ContentCreationDateDescrTag */
80 MP4SYS_DESCRIPTOR_TAG_OCICreatorNameDescrTag = 0x48, /* OCICreatorNameDescrTag */
81 MP4SYS_DESCRIPTOR_TAG_OCICreationDateDescrTag = 0x49, /* OCICreationDateDescrTag */
82 MP4SYS_DESCRIPTOR_TAG_SmpteCameraPositionDescrTag = 0x4A, /* SmpteCameraPositionDescrTag */
83 MP4SYS_DESCRIPTOR_TAG_Forbidden1 = 0xFF, /* Forbidden */
84 } mp4sys_descriptor_tag;
85 // MP4SYS_DESCRIPTOR_TAG_ES_DescrRemoveRefTag = 0x07, /* FIXME: (command tag), see 14496-14 Object Descriptors */
86
87 typedef struct
88 {
89 uint32_t size; // 2^28 at most
90 mp4sys_descriptor_tag tag;
91 } mp4sys_descriptor_head_t;
92
93 typedef struct mp4sys_descriptor_tag mp4sys_descriptor_t;
94
95 typedef void (*mp4sys_descriptor_destructor_t)( void * );
96 typedef int (*mp4sys_descriptor_writer_t)( lsmash_bs_t *, void * );
97
98 #define MP4SYS_DESCRIPTOR_COMMON \
99 const lsmash_class_t *class; \
100 mp4sys_descriptor_t *parent; \
101 mp4sys_descriptor_destructor_t destruct; \
102 mp4sys_descriptor_writer_t write; \
103 mp4sys_descriptor_head_t header; \
104 lsmash_entry_list_t children
105
106 struct mp4sys_descriptor_tag
107 {
108 MP4SYS_DESCRIPTOR_COMMON;
109 };
110
111 typedef struct
112 {
113 MP4SYS_DESCRIPTOR_COMMON;
114 } mp4sys_BaseDescriptor_t;
115
116 /* DecoderSpecificInfo */
117 /* contents varies depends on ObjectTypeIndication and StreamType. */
118 typedef struct
119 {
120 MP4SYS_DESCRIPTOR_COMMON;
121 uint8_t *data;
122 } mp4sys_DecoderSpecificInfo_t;
123
124 /* DecoderConfigDescriptor */
125 typedef struct
126 {
127 MP4SYS_DESCRIPTOR_COMMON;
128 lsmash_mp4sys_object_type_indication objectTypeIndication;
129 lsmash_mp4sys_stream_type streamType;
130 uint8_t upStream; /* bit(1), always 0 in this muxer, used for interactive contents. */
131 uint8_t reserved; /* const bit(1), always 1. */
132 uint32_t bufferSizeDB; /* maybe CPB size in bytes, NOT bits. */
133 uint32_t maxBitrate;
134 uint32_t avgBitrate; /* 0 if VBR */
135 mp4sys_DecoderSpecificInfo_t *decSpecificInfo; /* can be NULL. */
136 /* 14496-1 seems to say if we are in IOD(InitialObjectDescriptor), we might use this.
137 * See ExtensionProfileLevelDescr, The Initial Object Descriptor.
138 * But I don't think this is mandatory despite 14496-1, because 14496-14 says, in OD or IOD,
139 * we have to use ES_ID_Inc instead of ES_Descriptor, which does not have DecoderConfigDescriptor. */
140 // profileLevelIndicationIndexDescriptor profileLevelIndicationIndexDescr [0..255];
141 } mp4sys_DecoderConfigDescriptor_t;
142
143 /* SLConfigDescriptor */
144 typedef struct
145 {
146 MP4SYS_DESCRIPTOR_COMMON;
147 uint8_t predefined; /* default the values from a set of predefined parameter sets as detailed below.
148 * 0x00 : Custom
149 * 0x01 : null SL packet header
150 * 0x02 : Reserved for use in MP4 files
151 * 0x03 - 0xFF : Reserved for ISO use
152 * MP4 file that does not use URL_Flag shall have constant value 0x02. */
153 /* Custom values
154 * The following fields are placed if predefined == 0x00. */
155 unsigned useAccessUnitStartFlag : 1;
156 unsigned useAccessUnitEndFlag : 1;
157 unsigned useRandomAccessPointFlag : 1;
158 unsigned hasRandomAccessUnitsOnlyFlag : 1;
159 unsigned usePaddingFlag : 1;
160 unsigned useTimeStampsFlag : 1;
161 unsigned useIdleFlag : 1;
162 unsigned durationFlag : 1;
163 uint32_t timeStampResolution;
164 uint32_t OCRResolution;
165 uint8_t timeStampLength;
166 uint8_t OCRLength;
167 uint8_t AU_Length;
168 uint8_t instantBitrateLength;
169 unsigned degradationPriorityLength : 4;
170 unsigned AU_seqNumLength : 5;
171 unsigned packetSeqNumLength : 5;
172 unsigned reserved : 2;
173 /* The following fields are placed if durationFlag is true. */
174 uint32_t timeScale;
175 uint16_t accessUnitDuration;
176 uint16_t compositionUnitDuration;
177 /* The following fields are placed if useTimeStampsFlag is false. */
178 uint64_t startDecodingTimeStamp;
179 uint64_t startCompositionTimeStamp;
180 } mp4sys_SLConfigDescriptor_t;
181
182 /* ES_Descriptor */
183 typedef struct mp4sys_ES_Descriptor_t
184 {
185 MP4SYS_DESCRIPTOR_COMMON;
186 uint16_t ES_ID;
187 unsigned streamDependenceFlag : 1; /* no stream depencies between streams in this muxer, ES_ID of another elementary stream */
188 unsigned URL_Flag : 1; /* no external URL referencing stream in MP4 */
189 unsigned OCRstreamFlag : 1; /* no Object Clock Reference stream in this muxer (shall be false in MP4, useful if we're importing from MPEG-2?) */
190 unsigned streamPriority : 5; /* no priority among streams in this muxer, higher is important */
191 uint16_t dependsOn_ES_ID;
192 uint8_t URLlength;
193 char URLstring[256];
194 uint16_t OCR_ES_Id;
195 mp4sys_DecoderConfigDescriptor_t *decConfigDescr; /* cannot be NULL. */
196 mp4sys_SLConfigDescriptor_t *slConfigDescr;
197 /* descriptors below are not mandatory, I think Language Descriptor may somewhat useful */
198 /*
199 IPI_DescrPointer ipiPtr[0 .. 1]; // used to indicate using other ES's IP_IdentificationDataSet
200 IP_IdentificationDataSet ipIDS[0 .. 255]; // abstract class, actually ContentIdentificationDescriptor(for commercial contents management),
201 // or SupplementaryContentIdentificationDescriptor(for embedding titles)
202 IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255]; // used to intellectual property / protection management
203 LanguageDescriptor langDescr[0 .. 255]; // used to identify the language of the audio/speech or text object
204 QoS_Descriptor qosDescr[0 .. 1]; // used to achieve QoS
205 RegistrationDescriptor regDescr[0 .. 1]; // used to carry elementary streams with data whose format is not recognized by ISO/IEC 14496-1
206 ExtensionDescriptor extDescr[0 .. 255]; // abstract class, actually defined no subclass, maybe useless
207 */
208 } mp4sys_ES_Descriptor_t;
209
210 /* 14496-14 Object Descriptors (ES_ID_Inc) */
211 typedef struct
212 {
213 MP4SYS_DESCRIPTOR_COMMON;
214 uint32_t Track_ID;
215 } mp4sys_ES_ID_Inc_t;
216
217 /* 14496-1 ObjectDescriptor / InitialObjectDescriptor */
218 typedef struct
219 {
220 MP4SYS_DESCRIPTOR_COMMON;
221 unsigned ObjectDescriptorID : 10;
222 unsigned URL_Flag : 1;
223 unsigned includeInlineProfileLevelFlag : 1; /* for OD, reserved and set to 1 */
224 unsigned reserved : 4; /* 0b1111 */
225 uint8_t URLlength;
226 char URLstring[256];
227 /* IOD only */
228 mp4sys_ODProfileLevelIndication ODProfileLevelIndication;
229 mp4sys_sceneProfileLevelIndication sceneProfileLevelIndication;
230 mp4a_audioProfileLevelIndication audioProfileLevelIndication;
231 mp4sys_visualProfileLevelIndication visualProfileLevelIndication;
232 mp4sys_graphicsProfileLevelIndication graphicsProfileLevelIndication;
233 /* */
234 lsmash_entry_list_t esDescr; /* List of ES_ID_Inc, not ES_Descriptor defined in 14496-1. 14496-14 overrides. */
235 // OCI_Descriptor ociDescr[0 .. 255];
236 // IPMP_DescriptorPointer ipmpDescrPtr[0 .. 255];
237 // ExtensionDescriptor extDescr[0 .. 255];
238 } mp4sys_ObjectDescriptor_t;
239
mp4sys_remove_predefined_descriptor(void * opaque_descriptor,size_t offset_of_descriptor)240 static void mp4sys_remove_predefined_descriptor( void *opaque_descriptor, size_t offset_of_descriptor )
241 {
242 assert( opaque_descriptor );
243 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
244 if( descriptor->parent )
245 {
246 mp4sys_descriptor_t **p = (mp4sys_descriptor_t **)(((int8_t *)descriptor->parent) + offset_of_descriptor);
247 if( *p == descriptor )
248 *p = NULL;
249 }
250 }
251
252 /* We always free descriptors through the children list of the parent descriptor.
253 * Therefore, don't free descriptors through any list other than the children list. */
mp4sys_remove_descriptor_in_predefined_list(void * opaque_descriptor,size_t offset_of_list)254 static void mp4sys_remove_descriptor_in_predefined_list( void *opaque_descriptor, size_t offset_of_list )
255 {
256 assert( opaque_descriptor );
257 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
258 if( descriptor->parent )
259 {
260 lsmash_entry_list_t *list = (lsmash_entry_list_t *)(((int8_t *)descriptor->parent) + offset_of_list);
261 for( lsmash_entry_t *entry = list->head; entry; entry = entry->next )
262 if( descriptor == entry->data )
263 {
264 /* We don't free this descriptor here.
265 * Because of freeing an entry of the list here, don't pass the list to free this descriptor.
266 * Or double free. */
267 entry->data = NULL;
268 lsmash_list_remove_entry_direct( list, entry );
269 break;
270 }
271 }
272 }
273
274 static void mp4sys_remove_all_child_descriptors( lsmash_entry_list_t *children );
275
276 /* Free a descriptor and its children. */
mp4sys_destruct_descriptor(mp4sys_descriptor_t * descriptor)277 static void mp4sys_destruct_descriptor( mp4sys_descriptor_t *descriptor )
278 {
279 if( !descriptor )
280 return;
281 if( descriptor->destruct )
282 descriptor->destruct( descriptor );
283 mp4sys_remove_all_child_descriptors( &descriptor->children );
284 lsmash_free( descriptor );
285 }
286
mp4sys_remove_all_child_descriptors(lsmash_entry_list_t * children)287 static void mp4sys_remove_all_child_descriptors( lsmash_entry_list_t *children )
288 {
289 lsmash_list_remove_entries( children );
290 }
291
292 /* Remove a descriptor by the pointer containing its address.
293 * In addition, remove from the children list of the parent descriptor if possible.
294 * Don't call this function within a function freeing one or more entries of any children list because of double free.
295 * Basically, don't use this function as a callback function. */
mp4sys_remove_descriptor(void * opaque_descriptor)296 void mp4sys_remove_descriptor( void *opaque_descriptor )
297 {
298 if( !opaque_descriptor )
299 return;
300 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
301 if( descriptor->parent )
302 {
303 mp4sys_descriptor_t *parent = descriptor->parent;
304 for( lsmash_entry_t *entry = parent->children.head; entry; entry = entry->next )
305 if( descriptor == entry->data )
306 {
307 /* Free the corresponding entry here, therefore don't call this function as a callback function
308 * if a function frees the same entry later and calls this function. */
309 lsmash_list_remove_entry_direct( &parent->children, entry );
310 return;
311 }
312 }
313 mp4sys_destruct_descriptor( descriptor );
314 }
315
mp4sys_remove_DecoderSpecificInfo(mp4sys_DecoderSpecificInfo_t * dsi)316 static void mp4sys_remove_DecoderSpecificInfo( mp4sys_DecoderSpecificInfo_t *dsi )
317 {
318 if( !dsi )
319 return;
320 lsmash_free( dsi->data );
321 mp4sys_remove_predefined_descriptor( dsi, offsetof( mp4sys_DecoderConfigDescriptor_t, decSpecificInfo ) );
322 }
323
mp4sys_remove_DecoderConfigDescriptor(mp4sys_DecoderConfigDescriptor_t * dcd)324 static void mp4sys_remove_DecoderConfigDescriptor( mp4sys_DecoderConfigDescriptor_t *dcd )
325 {
326 if( !dcd )
327 return;
328 mp4sys_remove_predefined_descriptor( dcd, offsetof( mp4sys_ES_Descriptor_t, decConfigDescr ) );
329 }
330
mp4sys_remove_SLConfigDescriptor(mp4sys_SLConfigDescriptor_t * slcd)331 static void mp4sys_remove_SLConfigDescriptor( mp4sys_SLConfigDescriptor_t *slcd )
332 {
333 if( !slcd )
334 return;
335 mp4sys_remove_predefined_descriptor( slcd, offsetof( mp4sys_ES_Descriptor_t, slConfigDescr ) );
336 }
337
mp4sys_remove_ES_Descriptor(mp4sys_ES_Descriptor_t * esd)338 static void mp4sys_remove_ES_Descriptor( mp4sys_ES_Descriptor_t *esd )
339 {
340 if( !esd || (esd->parent && (esd->parent->header.tag == MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag
341 || esd->parent->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag)) )
342 return;
343 mp4sys_remove_descriptor_in_predefined_list( esd, offsetof( mp4sys_ObjectDescriptor_t, esDescr ) );
344 }
345
mp4sys_remove_ES_ID_Inc(mp4sys_ES_ID_Inc_t * es_id_inc)346 static void mp4sys_remove_ES_ID_Inc( mp4sys_ES_ID_Inc_t *es_id_inc )
347 {
348 if( !es_id_inc )
349 return;
350 mp4sys_remove_descriptor_in_predefined_list( es_id_inc, offsetof( mp4sys_ObjectDescriptor_t, esDescr ) );
351 }
352
mp4sys_remove_ObjectDescriptor(mp4sys_ObjectDescriptor_t * od)353 static void mp4sys_remove_ObjectDescriptor( mp4sys_ObjectDescriptor_t *od )
354 {
355 }
356
mp4sys_get_descriptor_header_size(uint32_t payload_size_in_byte)357 static inline uint32_t mp4sys_get_descriptor_header_size( uint32_t payload_size_in_byte )
358 {
359 #if ALWAYS_28BITS_LENGTH_CODING
360 return 4 + 1; /* +4 means 28bits length coding, +1 means tag's space */
361 #else
362 /* descriptor length will be split into 7bits
363 * see 14496-1 Expandable classes and Length encoding of descriptors and commands */
364 uint32_t i;
365 for( i = 1; payload_size_in_byte >> ( 7 * i ); i++ );
366 return i + 1; /* +1 means tag's space */
367 #endif
368 }
369
370 /* returns total size of descriptor, including header, 2 at least */
mp4sys_get_descriptor_size(uint32_t payload_size_in_byte)371 static inline uint32_t mp4sys_get_descriptor_size( uint32_t payload_size_in_byte )
372 {
373 return payload_size_in_byte + mp4sys_get_descriptor_header_size( payload_size_in_byte );
374 }
375
mp4sys_write_descriptor_header(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header)376 static inline void mp4sys_write_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
377 {
378 lsmash_bs_put_byte( bs, header->tag );
379 /* Descriptor length will be splitted into 7bits.
380 * See 14496-1 Expandable classes and Length encoding of descriptors and commands */
381 #if ALWAYS_28BITS_LENGTH_CODING
382 lsmash_bs_put_byte( bs, ( header->size >> 21 ) | 0x80 );
383 lsmash_bs_put_byte( bs, ( header->size >> 14 ) | 0x80 );
384 lsmash_bs_put_byte( bs, ( header->size >> 7 ) | 0x80 );
385 #else
386 for( uint32_t i = mp4sys_get_descriptor_size( header->size ) - header->size - 2; i; i-- ){
387 lsmash_bs_put_byte( bs, ( header->size >> ( 7 * i ) ) | 0x80 );
388 }
389 #endif
390 lsmash_bs_put_byte( bs, header->size & 0x7F );
391 }
392
393 int mp4sys_write_descriptor( lsmash_bs_t *bs, void *opaque_descriptor );
394
mp4sys_write_DecoderSpecificInfo(lsmash_bs_t * bs,mp4sys_DecoderSpecificInfo_t * dsi)395 static int mp4sys_write_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_DecoderSpecificInfo_t *dsi )
396 {
397 if( dsi->data && dsi->header.size != 0 )
398 lsmash_bs_put_bytes( bs, dsi->header.size, dsi->data );
399 return 0;
400 }
401
mp4sys_write_DecoderConfigDescriptor(lsmash_bs_t * bs,mp4sys_DecoderConfigDescriptor_t * dcd)402 static int mp4sys_write_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_DecoderConfigDescriptor_t *dcd )
403 {
404 lsmash_bs_put_byte( bs, dcd->objectTypeIndication );
405 uint8_t temp;
406 temp = (dcd->streamType & 0x3F) << 2;
407 temp |= (dcd->upStream & 0x01) << 1;
408 temp |= dcd->reserved & 0x01;
409 lsmash_bs_put_byte( bs, temp );
410 lsmash_bs_put_be24( bs, dcd->bufferSizeDB );
411 lsmash_bs_put_be32( bs, dcd->maxBitrate );
412 lsmash_bs_put_be32( bs, dcd->avgBitrate );
413 /* Here, profileLevelIndicationIndexDescriptor is omitted. */
414 return 0;
415 }
416
mp4sys_write_SLConfigDescriptor(lsmash_bs_t * bs,mp4sys_SLConfigDescriptor_t * slcd)417 static int mp4sys_write_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_SLConfigDescriptor_t *slcd )
418 {
419 lsmash_bs_put_byte( bs, slcd->predefined );
420 if( slcd->predefined == 0x00 )
421 {
422 uint8_t temp8;
423 temp8 = slcd->useAccessUnitStartFlag << 7;
424 temp8 |= slcd->useAccessUnitEndFlag << 6;
425 temp8 |= slcd->useRandomAccessPointFlag << 5;
426 temp8 |= slcd->hasRandomAccessUnitsOnlyFlag << 4;
427 temp8 |= slcd->usePaddingFlag << 3;
428 temp8 |= slcd->useTimeStampsFlag << 2;
429 temp8 |= slcd->useIdleFlag << 1;
430 temp8 |= slcd->durationFlag;
431 lsmash_bs_put_byte( bs, temp8 );
432 lsmash_bs_put_be32( bs, slcd->timeStampResolution );
433 lsmash_bs_put_be32( bs, slcd->OCRResolution );
434 lsmash_bs_put_byte( bs, slcd->timeStampLength );
435 lsmash_bs_put_byte( bs, slcd->OCRLength );
436 lsmash_bs_put_byte( bs, slcd->AU_Length );
437 lsmash_bs_put_byte( bs, slcd->instantBitrateLength );
438 uint16_t temp16;
439 temp16 = slcd->degradationPriorityLength << 12;
440 temp16 |= slcd->AU_seqNumLength << 7;
441 temp16 |= slcd->packetSeqNumLength << 2;
442 temp16 |= slcd->reserved;
443 lsmash_bs_put_be16( bs, temp16 );
444 }
445 if( slcd->durationFlag )
446 {
447 lsmash_bs_put_be32( bs, slcd->timeScale );
448 lsmash_bs_put_be16( bs, slcd->accessUnitDuration );
449 lsmash_bs_put_be16( bs, slcd->compositionUnitDuration );
450 }
451 if( !slcd->useTimeStampsFlag )
452 {
453 lsmash_bits_t *bits = lsmash_bits_create( bs );
454 if( !bits )
455 return LSMASH_ERR_MEMORY_ALLOC;
456 lsmash_bits_put( bits, slcd->timeStampLength, slcd->startDecodingTimeStamp );
457 lsmash_bits_put( bits, slcd->timeStampLength, slcd->startCompositionTimeStamp );
458 lsmash_bits_put_align( bits );
459 lsmash_bits_cleanup( bits );
460 }
461 return 0;
462 }
463
mp4sys_write_ES_Descriptor(lsmash_bs_t * bs,mp4sys_ES_Descriptor_t * esd)464 static int mp4sys_write_ES_Descriptor( lsmash_bs_t *bs, mp4sys_ES_Descriptor_t *esd )
465 {
466 lsmash_bs_put_be16( bs, esd->ES_ID );
467 uint8_t temp;
468 temp = esd->streamDependenceFlag << 7;
469 temp |= esd->URL_Flag << 6;
470 temp |= esd->OCRstreamFlag << 5;
471 temp |= esd->streamPriority;
472 lsmash_bs_put_byte( bs, temp );
473 if( esd->streamDependenceFlag )
474 lsmash_bs_put_be16( bs, esd->dependsOn_ES_ID );
475 if( esd->URL_Flag )
476 {
477 lsmash_bs_put_byte( bs, esd->URLlength );
478 lsmash_bs_put_bytes( bs, esd->URLlength, esd->URLstring );
479 }
480 if( esd->OCRstreamFlag )
481 lsmash_bs_put_be16( bs, esd->OCR_ES_Id );
482 /* Here, some syntax elements are omitted due to previous flags (all 0). */
483 return 0;
484 }
485
mp4sys_write_ES_ID_Inc(lsmash_bs_t * bs,mp4sys_ES_ID_Inc_t * es_id_inc)486 static int mp4sys_write_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_ES_ID_Inc_t *es_id_inc )
487 {
488 lsmash_bs_put_be32( bs, es_id_inc->Track_ID );
489 return 0;
490 }
491
mp4sys_write_ObjectDescriptor(lsmash_bs_t * bs,mp4sys_ObjectDescriptor_t * od)492 static int mp4sys_write_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_ObjectDescriptor_t *od )
493 {
494 uint16_t temp = (od->ObjectDescriptorID << 6);
495 // temp |= (0x0 << 5); /* URL_Flag */
496 temp |= (od->includeInlineProfileLevelFlag << 4); /* if MP4_OD, includeInlineProfileLevelFlag is 0x1. */
497 temp |= 0xF; /* reserved */
498 lsmash_bs_put_be16( bs, temp );
499 /* here, since we don't support URL_Flag, we put ProfileLevelIndications */
500 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
501 {
502 lsmash_bs_put_byte( bs, od->ODProfileLevelIndication );
503 lsmash_bs_put_byte( bs, od->sceneProfileLevelIndication );
504 lsmash_bs_put_byte( bs, od->audioProfileLevelIndication );
505 lsmash_bs_put_byte( bs, od->visualProfileLevelIndication );
506 lsmash_bs_put_byte( bs, od->graphicsProfileLevelIndication );
507 }
508 return 0;
509 }
510
mp4sys_write_children(lsmash_bs_t * bs,mp4sys_descriptor_t * descriptor)511 static int mp4sys_write_children( lsmash_bs_t *bs, mp4sys_descriptor_t *descriptor )
512 {
513 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
514 {
515 mp4sys_descriptor_t *child = (mp4sys_descriptor_t *)entry->data;
516 if( !child )
517 continue;
518 int ret = mp4sys_write_descriptor( bs, child );
519 if( ret < 0 )
520 return ret;
521 }
522 return 0;
523 }
524
mp4sys_write_descriptor(lsmash_bs_t * bs,void * opaque_descriptor)525 int mp4sys_write_descriptor( lsmash_bs_t *bs, void *opaque_descriptor )
526 {
527 if( !bs || !opaque_descriptor )
528 return LSMASH_ERR_NAMELESS;
529 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
530 mp4sys_write_descriptor_header( bs, &descriptor->header );
531 if( !descriptor->write )
532 return 0;
533 int err = descriptor->write( bs, descriptor );
534 if( err < 0 )
535 return err;
536 return mp4sys_write_children( bs, descriptor );
537 }
538
539 /* descriptor size updater */
mp4sys_update_descriptor_size(void * opaque_descriptor)540 uint32_t mp4sys_update_descriptor_size( void *opaque_descriptor )
541 {
542 assert( opaque_descriptor );
543 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
544 uint64_t size = 0;
545 if( descriptor->write )
546 {
547 uint32_t header_size = descriptor->header.size;
548 /* Calculate the size of this descriptor excluding its children with a fake bytestream writer. */
549 {
550 lsmash_bs_t fake_bs = { NULL };
551 mp4sys_write_descriptor_header( &fake_bs, &descriptor->header );
552 if( descriptor->write( &fake_bs, descriptor ) == 0 )
553 size = lsmash_bs_get_valid_data_size( &fake_bs );
554 }
555 /* Calculate the size including the children if no error. */
556 if( size >= mp4sys_get_descriptor_header_size( header_size ) )
557 {
558 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
559 if( entry->data )
560 size += mp4sys_update_descriptor_size( entry->data );
561 /* Calculate the size of this descriptor excluding its header. */
562 size -= mp4sys_get_descriptor_header_size( header_size );
563 descriptor->header.size = size;
564 /* Now, we get the actual size of this descriptor. */
565 size += mp4sys_get_descriptor_header_size( size );
566 }
567 else
568 {
569 /* Invalid descriptor */
570 descriptor->header.size = 0;
571 size = 0;
572 }
573 }
574 else
575 descriptor->header.size = 0;
576 return size;
577 }
578
mp4sys_construct_descriptor_orig(size_t size,mp4sys_descriptor_t * parent,mp4sys_descriptor_destructor_t destructor,mp4sys_descriptor_writer_t writer)579 static inline void *mp4sys_construct_descriptor_orig
580 (
581 size_t size,
582 mp4sys_descriptor_t *parent,
583 mp4sys_descriptor_destructor_t destructor,
584 mp4sys_descriptor_writer_t writer
585 )
586 {
587 assert( size >= sizeof(mp4sys_BaseDescriptor_t) );
588 mp4sys_descriptor_t *descriptor = lsmash_malloc_zero( size );
589 if( !descriptor )
590 return NULL;
591 descriptor->class = &lsmash_mp4sys_class;
592 descriptor->parent = parent;
593 descriptor->destruct = destructor;
594 descriptor->write = writer;
595 lsmash_list_init( &descriptor->children, mp4sys_destruct_descriptor );
596 return descriptor;
597 }
598
599 #define mp4sys_construct_descriptor( size, parent, destructor, writer ) \
600 mp4sys_construct_descriptor_orig \
601 ( \
602 size, \
603 (mp4sys_descriptor_t *)parent, \
604 (mp4sys_descriptor_destructor_t)destructor, \
605 (mp4sys_descriptor_writer_t)writer \
606 )
607
608 #define MP4SYS_CONSTRUCT_DESCRIPTOR( var, descriptor_name, parent, ret ) \
609 mp4sys_##descriptor_name##_t *var = \
610 mp4sys_construct_descriptor \
611 ( \
612 sizeof(mp4sys_##descriptor_name##_t), \
613 parent, \
614 mp4sys_remove_##descriptor_name, \
615 mp4sys_write_##descriptor_name \
616 ); \
617 if( !var ) \
618 return ret
619
mp4sys_add_DecoderSpecificInfo(mp4sys_DecoderConfigDescriptor_t * dcd)620 static mp4sys_DecoderSpecificInfo_t *mp4sys_add_DecoderSpecificInfo( mp4sys_DecoderConfigDescriptor_t *dcd )
621 {
622 if( !dcd )
623 return NULL;
624 MP4SYS_CONSTRUCT_DESCRIPTOR( dsi, DecoderSpecificInfo, dcd, NULL );
625 dsi->header.tag = MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag;
626 if( lsmash_list_add_entry( &dcd->children, dsi ) < 0 )
627 {
628 mp4sys_remove_descriptor( dsi );
629 return NULL;
630 }
631 dcd->decSpecificInfo = dsi;
632 return dsi;
633 }
634
635 /*
636 bufferSizeDB is byte unit, NOT bit unit.
637 avgBitrate is 0 if VBR
638 */
mp4sys_add_DecoderConfigDescriptor(mp4sys_ES_Descriptor_t * esd)639 static mp4sys_DecoderConfigDescriptor_t *mp4sys_add_DecoderConfigDescriptor
640 (
641 mp4sys_ES_Descriptor_t *esd
642 )
643 {
644 if( !esd )
645 return NULL;
646 MP4SYS_CONSTRUCT_DESCRIPTOR( dcd, DecoderConfigDescriptor, esd, NULL );
647 dcd->header.tag = MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag;
648 if( lsmash_list_add_entry( &esd->children, dcd ) < 0 )
649 {
650 mp4sys_remove_descriptor( dcd );
651 return NULL;
652 }
653 esd->decConfigDescr = dcd;
654 return dcd;
655 }
656
mp4sys_add_SLConfigDescriptor(mp4sys_ES_Descriptor_t * esd)657 static mp4sys_SLConfigDescriptor_t *mp4sys_add_SLConfigDescriptor( mp4sys_ES_Descriptor_t *esd )
658 {
659 if( !esd )
660 return NULL;
661 MP4SYS_CONSTRUCT_DESCRIPTOR( slcd, SLConfigDescriptor, esd, NULL );
662 slcd->header.tag = MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag;
663 if( lsmash_list_add_entry( &esd->children, slcd ) < 0 )
664 {
665 mp4sys_remove_descriptor( slcd );
666 return NULL;
667 }
668 esd->slConfigDescr = slcd;
669 return slcd;
670 }
671
672 /* NOTE: This is only for MP4_IOD and MP4_OD, not for ISO Base Media's ObjectDescriptor and InitialObjectDescriptor */
mp4sys_add_ES_ID_Inc(mp4sys_ObjectDescriptor_t * od)673 static mp4sys_ES_ID_Inc_t *mp4sys_add_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od )
674 {
675 if( !od
676 || (od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
677 && od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag) )
678 return NULL;
679 MP4SYS_CONSTRUCT_DESCRIPTOR( es_id_inc, ES_ID_Inc, od, NULL );
680 es_id_inc->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag;
681 if( lsmash_list_add_entry( &od->children, es_id_inc ) < 0 )
682 {
683 mp4sys_remove_descriptor( es_id_inc );
684 return NULL;
685 }
686 if( lsmash_list_add_entry( &od->esDescr, es_id_inc ) < 0 )
687 {
688 lsmash_list_remove_entry_tail( &od->children );
689 return NULL;
690 }
691 return es_id_inc;
692 }
693
mp4sys_create_ES_ID_Inc(mp4sys_ObjectDescriptor_t * od,uint32_t Track_ID)694 int mp4sys_create_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od, uint32_t Track_ID )
695 {
696 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( od );
697 if( !es_id_inc )
698 return LSMASH_ERR_NAMELESS;
699 es_id_inc->Track_ID = Track_ID;
700 return 0;
701 }
702
703 /* ES_ID of the ES Descriptor is stored as 0 when the ES Descriptor is built into sample descriptions in MP4 file format
704 * since the lower 16 bits of the track_ID is used, instead of ES_ID, for the identifier of the elemental stream within the track. */
mp4sys_create_ES_Descriptor(uint16_t ES_ID)705 mp4sys_ES_Descriptor_t *mp4sys_create_ES_Descriptor( uint16_t ES_ID )
706 {
707 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, NULL, NULL );
708 esd->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
709 esd->ES_ID = ES_ID;
710 return esd;
711 }
712
713 /* NOTE: This is only for MP4_OD, not for ISO Base Media's ObjectDescriptor */
mp4sys_create_ObjectDescriptor(uint16_t ObjectDescriptorID)714 mp4sys_ObjectDescriptor_t *mp4sys_create_ObjectDescriptor( uint16_t ObjectDescriptorID )
715 {
716 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, NULL, NULL );
717 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag;
718 od->ObjectDescriptorID = ObjectDescriptorID;
719 od->includeInlineProfileLevelFlag = 1; /* 1 as part of reserved flag. */
720 od->ODProfileLevelIndication = MP4SYS_OD_PLI_NONE_REQUIRED;
721 od->sceneProfileLevelIndication = MP4SYS_SCENE_PLI_NONE_REQUIRED;
722 od->audioProfileLevelIndication = MP4A_AUDIO_PLI_NONE_REQUIRED;
723 od->visualProfileLevelIndication = MP4SYS_VISUAL_PLI_NONE_REQUIRED;
724 od->graphicsProfileLevelIndication = MP4SYS_GRAPHICS_PLI_NONE_REQUIRED;
725 return od;
726 }
727
728 /* NOTE: This is only for MP4_IOD, not for Iso Base Media's InitialObjectDescriptor */
mp4sys_to_InitialObjectDescriptor(mp4sys_ObjectDescriptor_t * od,uint8_t include_inline_pli,mp4sys_ODProfileLevelIndication od_pli,mp4sys_sceneProfileLevelIndication scene_pli,mp4a_audioProfileLevelIndication audio_pli,mp4sys_visualProfileLevelIndication visual_pli,mp4sys_graphicsProfileLevelIndication graph_pli)729 int mp4sys_to_InitialObjectDescriptor
730 (
731 mp4sys_ObjectDescriptor_t *od,
732 uint8_t include_inline_pli,
733 mp4sys_ODProfileLevelIndication od_pli,
734 mp4sys_sceneProfileLevelIndication scene_pli,
735 mp4a_audioProfileLevelIndication audio_pli,
736 mp4sys_visualProfileLevelIndication visual_pli,
737 mp4sys_graphicsProfileLevelIndication graph_pli
738 )
739 {
740 if( !od )
741 return LSMASH_ERR_NAMELESS;
742 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag;
743 od->includeInlineProfileLevelFlag = include_inline_pli;
744 od->ODProfileLevelIndication = od_pli;
745 od->sceneProfileLevelIndication = scene_pli;
746 od->audioProfileLevelIndication = audio_pli;
747 od->visualProfileLevelIndication = visual_pli;
748 od->graphicsProfileLevelIndication = graph_pli;
749 return 0;
750 }
751
752 /*
753 bufferSizeDB is byte unit, NOT bit unit.
754 avgBitrate is 0 if VBR
755 */
mp4sys_update_DecoderConfigDescriptor(mp4sys_ES_Descriptor_t * esd,uint32_t bufferSizeDB,uint32_t maxBitrate,uint32_t avgBitrate)756 int mp4sys_update_DecoderConfigDescriptor( mp4sys_ES_Descriptor_t *esd, uint32_t bufferSizeDB, uint32_t maxBitrate, uint32_t avgBitrate )
757 {
758 if( !esd || !esd->decConfigDescr )
759 return LSMASH_ERR_NAMELESS;
760 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
761 dcd->bufferSizeDB = bufferSizeDB;
762 dcd->maxBitrate = maxBitrate;
763 dcd->avgBitrate = avgBitrate;
764 return 0;
765 }
766
767 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent );
768
mp4sys_print_descriptor_header(FILE * fp,mp4sys_descriptor_head_t * header,int indent)769 static void mp4sys_print_descriptor_header( FILE *fp, mp4sys_descriptor_head_t *header, int indent )
770 {
771 static const char *descriptor_names_table[256] =
772 {
773 "Forbidden",
774 "ObjectDescriptor",
775 "InitialObjectDescriptor",
776 "ES_Descriptor",
777 "DecoderConfigDescriptor",
778 "DecoderSpecificInfo",
779 "SLConfigDescriptor",
780 [0x0E] = "ES_ID_Inc",
781 [0x0F] = "ES_ID_Ref",
782 [0x10] = "MP4_IOD",
783 [0x11] = "MP4_OD"
784 };
785 if( descriptor_names_table[ header->tag ] )
786 lsmash_ifprintf( fp, indent, "[tag = 0x%02"PRIx8": %s]\n", header->tag, descriptor_names_table[ header->tag ] );
787 else
788 lsmash_ifprintf( fp, indent, "[tag = 0x%02"PRIx8"]\n", header->tag );
789 lsmash_ifprintf( fp, ++indent, "expandableClassSize = %"PRIu32"\n", header->size );
790 }
791
mp4sys_print_DecoderSpecificInfo(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)792 static void mp4sys_print_DecoderSpecificInfo( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
793 {
794 extern void mp4a_print_AudioSpecificConfig( FILE *, uint8_t *, uint32_t, int );
795 if( !descriptor->parent || descriptor->parent->header.tag != MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag )
796 return;
797 mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor->parent;
798 if( dcd->streamType != MP4SYS_STREAM_TYPE_AudioStream
799 || dcd->objectTypeIndication != MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3 )
800 return; /* We support only AudioSpecificConfig here currently. */
801 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)descriptor;
802 mp4a_print_AudioSpecificConfig( fp, dsi->data, dsi->header.size, indent );
803 }
804
mp4sys_print_DecoderConfigDescriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)805 static void mp4sys_print_DecoderConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
806 {
807 mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor;
808 static const char *object_type_indication_descriptions_table[256] =
809 {
810 "Forbidden",
811 "Systems ISO/IEC 14496-1 (a)",
812 "Systems ISO/IEC 14496-1 (b)",
813 "Interaction Stream",
814 "Systems ISO/IEC 14496-1 Extended BIFS Configuration",
815 "Systems ISO/IEC 14496-1 AFX",
816 "Font Data Stream",
817 "Synthesized Texture Stream",
818 "Streaming Text Stream",
819 "LASeR Stream",
820 "Simple Aggregation Format (SAF) Stream",
821 [0x20] = "Visual ISO/IEC 14496-2",
822 [0x21] = "Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10",
823 [0x22] = "Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10",
824 [0x40] = "Audio ISO/IEC 14496-3",
825 [0x60] = "Visual ISO/IEC 13818-2 Simple Profile",
826 [0x61] = "Visual ISO/IEC 13818-2 Main Profile",
827 [0x62] = "Visual ISO/IEC 13818-2 SNR Profile",
828 [0x63] = "Visual ISO/IEC 13818-2 Spatial Profile",
829 [0x64] = "Visual ISO/IEC 13818-2 High Profile",
830 [0x65] = "Visual ISO/IEC 13818-2 422 Profile",
831 [0x66] = "Audio ISO/IEC 13818-7 Main Profile",
832 [0x67] = "Audio ISO/IEC 13818-7 LowComplexity Profile",
833 [0x68] = "Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile",
834 [0x69] = "Audio ISO/IEC 13818-3",
835 [0x6A] = "Visual ISO/IEC 11172-2",
836 [0x6B] = "Audio ISO/IEC 11172-3",
837 [0x6C] = "Visual ISO/IEC 10918-1",
838 [0x6D] = "Portable Network Graphics",
839 [0x6E] = "Visual ISO/IEC 15444-1 (JPEG 2000)",
840 [0xA0] = "EVRC Voice",
841 [0xA1] = "SMV Voice",
842 [0xA2] = "3GPP2 Compact Multimedia Format (CMF)",
843 [0xA3] = "SMPTE VC-1 Video",
844 [0xA4] = "Dirac Video Coder",
845 [0xA5] = "AC-3 Audio",
846 [0xA6] = "Enhanced AC-3 audio",
847 [0xA7] = "DRA Audio",
848 [0xA8] = "ITU G.719 Audio",
849 [0xA9] = "DTS Coherent Acoustics audio",
850 [0xAA] = "DTS-HD High Resolution Audio",
851 [0xAB] = "DTS-HD Master Audio",
852 [0xAC] = "DTS Express low bit rate audio",
853 [0xE1] = "13K Voice",
854 [0xFF] = "no object type specified"
855 };
856 static const char *stream_type_descriptions_table[64] =
857 {
858 "Forbidden",
859 "ObjectDescriptorStream",
860 "ClockReferenceStream",
861 "SceneDescriptionStream",
862 "VisualStream",
863 "AudioStream",
864 "MPEG7Stream",
865 "IPMPStream",
866 "ObjectContentInfoStream",
867 "MPEGJStream",
868 "Interaction Stream",
869 "IPMPToolStream",
870 "FontDataStream",
871 "StreamingText"
872 };
873 if( object_type_indication_descriptions_table[ dcd->objectTypeIndication ] )
874 lsmash_ifprintf( fp, indent, "objectTypeIndication = 0x%02"PRIx8" (%s)\n", dcd->objectTypeIndication, object_type_indication_descriptions_table[ dcd->objectTypeIndication ] );
875 else
876 lsmash_ifprintf( fp, indent, "objectTypeIndication = 0x%02"PRIx8"\n", dcd->objectTypeIndication );
877 if( stream_type_descriptions_table[ dcd->streamType ] )
878 lsmash_ifprintf( fp, indent, "streamType = 0x%02"PRIx8" (%s)\n", dcd->streamType, stream_type_descriptions_table[ dcd->streamType ] );
879 else
880 lsmash_ifprintf( fp, indent, "streamType = 0x%02"PRIx8"\n", dcd->streamType );
881 lsmash_ifprintf( fp, indent, "upStream = %"PRIu8"\n", dcd->upStream );
882 lsmash_ifprintf( fp, indent, "reserved = %"PRIu8"\n", dcd->reserved );
883 lsmash_ifprintf( fp, indent, "bufferSizeDB = %"PRIu32"\n", dcd->bufferSizeDB );
884 lsmash_ifprintf( fp, indent, "maxBitrate = %"PRIu32"\n", dcd->maxBitrate );
885 lsmash_ifprintf( fp, indent, "avgBitrate = %"PRIu32"%s\n", dcd->avgBitrate, dcd->avgBitrate ? "" : " (variable bitrate)" );
886 }
887
mp4sys_print_SLConfigDescriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)888 static void mp4sys_print_SLConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
889 {
890 mp4sys_SLConfigDescriptor_t *slcd = (mp4sys_SLConfigDescriptor_t *)descriptor;
891 lsmash_ifprintf( fp, indent, "predefined = %"PRIu8"\n", slcd->predefined );
892 if( slcd->predefined == 0 )
893 {
894 lsmash_ifprintf( fp, indent, "useAccessUnitStartFlag = %"PRIu8"\n", slcd->useAccessUnitStartFlag );
895 lsmash_ifprintf( fp, indent, "useAccessUnitEndFlag = %"PRIu8"\n", slcd->useAccessUnitEndFlag );
896 lsmash_ifprintf( fp, indent, "useRandomAccessPointFlag = %"PRIu8"\n", slcd->useRandomAccessPointFlag );
897 lsmash_ifprintf( fp, indent, "hasRandomAccessUnitsOnlyFlag = %"PRIu8"\n", slcd->hasRandomAccessUnitsOnlyFlag );
898 lsmash_ifprintf( fp, indent, "usePaddingFlag = %"PRIu8"\n", slcd->usePaddingFlag );
899 lsmash_ifprintf( fp, indent, "useTimeStampsFlag = %"PRIu8"\n", slcd->useTimeStampsFlag );
900 lsmash_ifprintf( fp, indent, "useIdleFlag = %"PRIu8"\n", slcd->useIdleFlag );
901 lsmash_ifprintf( fp, indent, "durationFlag = %"PRIu8"\n", slcd->durationFlag );
902 lsmash_ifprintf( fp, indent, "timeStampResolution = %"PRIu32"\n", slcd->timeStampResolution );
903 lsmash_ifprintf( fp, indent, "OCRResolution = %"PRIu32"\n", slcd->OCRResolution );
904 lsmash_ifprintf( fp, indent, "timeStampLength = %"PRIu8"\n", slcd->timeStampLength );
905 lsmash_ifprintf( fp, indent, "OCRLength = %"PRIu8"\n", slcd->OCRLength );
906 lsmash_ifprintf( fp, indent, "AU_Length = %"PRIu8"\n", slcd->AU_Length );
907 lsmash_ifprintf( fp, indent, "instantBitrateLength = %"PRIu8"\n", slcd->instantBitrateLength );
908 lsmash_ifprintf( fp, indent, "degradationPriorityLength = %"PRIu8"\n", slcd->degradationPriorityLength );
909 lsmash_ifprintf( fp, indent, "AU_seqNumLength = %"PRIu8"\n", slcd->AU_seqNumLength );
910 lsmash_ifprintf( fp, indent, "packetSeqNumLength = %"PRIu8"\n", slcd->packetSeqNumLength );
911 lsmash_ifprintf( fp, indent, "reserved = 0x%01"PRIx8"\n", slcd->reserved );
912 }
913 if( slcd->durationFlag )
914 {
915 lsmash_ifprintf( fp, indent, "timeScale = %"PRIu32"\n", slcd->timeScale );
916 lsmash_ifprintf( fp, indent, "accessUnitDuration = %"PRIu16"\n", slcd->accessUnitDuration );
917 lsmash_ifprintf( fp, indent, "compositionUnitDuration = %"PRIu16"\n", slcd->compositionUnitDuration );
918 }
919 if( !slcd->useTimeStampsFlag )
920 {
921 lsmash_ifprintf( fp, indent, "startDecodingTimeStamp = %"PRIu64"\n", slcd->startDecodingTimeStamp );
922 lsmash_ifprintf( fp, indent, "startCompositionTimeStamp = %"PRIu64"\n", slcd->startCompositionTimeStamp );
923 }
924 }
925
mp4sys_print_ES_Descriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)926 static void mp4sys_print_ES_Descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
927 {
928 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)descriptor;
929 lsmash_ifprintf( fp, indent, "ES_ID = %"PRIu16"\n", esd->ES_ID );
930 lsmash_ifprintf( fp, indent, "streamDependenceFlag = %"PRIu8"\n", esd->streamDependenceFlag );
931 lsmash_ifprintf( fp, indent, "URL_Flag = %"PRIu8"\n", esd->URL_Flag );
932 lsmash_ifprintf( fp, indent, "OCRstreamFlag = %"PRIu8"\n", esd->OCRstreamFlag );
933 lsmash_ifprintf( fp, indent, "streamPriority = %"PRIu8"\n", esd->streamPriority );
934 if( esd->streamDependenceFlag )
935 lsmash_ifprintf( fp, indent, "dependsOn_ES_ID = %"PRIu16"\n", esd->dependsOn_ES_ID );
936 if( esd->URL_Flag )
937 {
938 lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", esd->URLlength );
939 lsmash_ifprintf( fp, indent, "URLstring = %s\n", esd->URLstring );
940 }
941 if( esd->OCRstreamFlag )
942 lsmash_ifprintf( fp, indent, "OCR_ES_Id = %"PRIu16"\n", esd->OCR_ES_Id );
943 }
944
mp4sys_print_ES_ID_Inc(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)945 static void mp4sys_print_ES_ID_Inc( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
946 {
947 mp4sys_ES_ID_Inc_t *es_id_inc = (mp4sys_ES_ID_Inc_t *)descriptor;
948 lsmash_ifprintf( fp, indent, "Track_ID = %"PRIu32"\n", es_id_inc->Track_ID );
949 }
950
mp4sys_print_ObjectDescriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)951 static void mp4sys_print_ObjectDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
952 {
953 mp4sys_ObjectDescriptor_t *od = (mp4sys_ObjectDescriptor_t *)descriptor;
954 lsmash_ifprintf( fp, indent, "ObjectDescriptorID = %"PRIu16"\n", od->ObjectDescriptorID );
955 lsmash_ifprintf( fp, indent, "URL_Flag = %"PRIu8"\n", od->URL_Flag );
956 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
957 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
958 {
959 lsmash_ifprintf( fp, indent, "includeInlineProfileLevelFlag = %"PRIu8"\n", od->includeInlineProfileLevelFlag );
960 lsmash_ifprintf( fp, indent, "reserved = 0x%01"PRIx8"\n", od->reserved );
961 }
962 else
963 lsmash_ifprintf( fp, indent, "reserved = 0x%02"PRIx8"\n", od->reserved | (od->includeInlineProfileLevelFlag << 4) );
964 if( od->URL_Flag )
965 {
966 lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", od->URLlength );
967 lsmash_ifprintf( fp, indent, "URLstring = %s\n", od->URLstring );
968 }
969 else
970 {
971 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
972 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
973 {
974 lsmash_ifprintf( fp, indent, "ODProfileLevelIndication = 0x%02"PRIx8"\n", od->ODProfileLevelIndication );
975 lsmash_ifprintf( fp, indent, "sceneProfileLevelIndication = 0x%02"PRIx8"\n", od->sceneProfileLevelIndication );
976 lsmash_ifprintf( fp, indent, "audioProfileLevelIndication = 0x%02"PRIx8"\n", od->audioProfileLevelIndication );
977 lsmash_ifprintf( fp, indent, "visualProfileLevelIndication = 0x%02"PRIx8"\n", od->visualProfileLevelIndication );
978 lsmash_ifprintf( fp, indent, "graphicsProfileLevelIndication = 0x%02"PRIx8"\n", od->graphicsProfileLevelIndication );
979 }
980 }
981 }
982
mp4sys_print_descriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)983 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
984 {
985 if( !descriptor )
986 return;
987 mp4sys_print_descriptor_header( fp, &descriptor->header, indent++ );
988 switch( descriptor->header.tag )
989 {
990 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
991 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
992 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
993 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
994 mp4sys_print_ObjectDescriptor( fp, descriptor, indent );
995 break;
996 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
997 mp4sys_print_ES_Descriptor( fp, descriptor, indent );
998 break;
999 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
1000 mp4sys_print_DecoderConfigDescriptor( fp, descriptor, indent );
1001 break;
1002 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1003 mp4sys_print_DecoderSpecificInfo( fp, descriptor, indent );
1004 break;
1005 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1006 mp4sys_print_SLConfigDescriptor( fp, descriptor, indent );
1007 break;
1008 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1009 mp4sys_print_ES_ID_Inc( fp, descriptor, indent );
1010 break;
1011 default :
1012 break;
1013 }
1014 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
1015 if( entry->data )
1016 mp4sys_print_descriptor( fp, entry->data, indent );
1017 }
1018
mp4sys_print_codec_specific(FILE * fp,lsmash_file_t * file,isom_box_t * box,int level)1019 int mp4sys_print_codec_specific( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1020 {
1021 assert( !(box->manager & LSMASH_BINARY_CODED_BOX) );
1022 isom_esds_t *esds = (isom_esds_t *)box;
1023 int indent = level;
1024 lsmash_ifprintf( fp, indent++, "[%s: Elemental Stream Descriptor Box]\n", isom_4cc2str( esds->type.fourcc ) );
1025 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", esds->pos );
1026 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", esds->size );
1027 lsmash_ifprintf( fp, indent, "version = %"PRIu8"\n", esds->version );
1028 lsmash_ifprintf( fp, indent, "flags = 0x%06"PRIx32"\n", esds->flags & 0x00ffffff );
1029 mp4sys_print_descriptor( fp, (mp4sys_descriptor_t *)esds->ES, indent );
1030 return 0;
1031 }
1032
1033 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent );
1034
mp4sys_get_descriptor_header(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header)1035 static void mp4sys_get_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
1036 {
1037 header->tag = lsmash_bs_get_byte( bs );
1038 uint8_t temp = lsmash_bs_get_byte( bs );
1039 int nextByte = temp & 0x80;
1040 uint32_t sizeOfInstance = temp & 0x7F;
1041 while( nextByte )
1042 {
1043 temp = lsmash_bs_get_byte( bs );
1044 nextByte = temp & 0x80;
1045 sizeOfInstance = (sizeOfInstance << 7) | (temp & 0x7F);
1046 }
1047 header->size = sizeOfInstance;
1048 }
1049
mp4sys_get_DecoderSpecificInfo(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1050 static mp4sys_DecoderSpecificInfo_t *mp4sys_get_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1051 {
1052 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( parent );
1053 if( !dsi )
1054 return NULL;
1055 dsi->header.size = header->size;
1056 if( dsi->header.size )
1057 {
1058 dsi->data = lsmash_bs_get_bytes( bs, dsi->header.size );
1059 if( !dsi->data )
1060 {
1061 mp4sys_remove_descriptor( dsi );
1062 return NULL;
1063 }
1064 }
1065 return dsi;
1066 }
1067
mp4sys_get_DecoderConfigDescriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1068 static mp4sys_DecoderConfigDescriptor_t *mp4sys_get_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1069 {
1070 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( parent );
1071 if( !dcd )
1072 return NULL;
1073 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1074 dcd->header.size = header->size;
1075 dcd->objectTypeIndication = lsmash_bs_get_byte( bs );
1076 uint8_t temp = lsmash_bs_get_byte( bs );
1077 dcd->streamType = (temp >> 2) & 0x3F;
1078 dcd->upStream = (temp >> 1) & 0x01;
1079 dcd->reserved = temp & 0x01;
1080 dcd->bufferSizeDB = lsmash_bs_get_be24( bs );
1081 dcd->maxBitrate = lsmash_bs_get_be32( bs );
1082 dcd->avgBitrate = lsmash_bs_get_be32( bs );
1083 while( lsmash_bs_count( bs ) < end_pos )
1084 {
1085 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, dcd );
1086 if( desc )
1087 {
1088 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag )
1089 dcd->decSpecificInfo = (mp4sys_DecoderSpecificInfo_t *)desc;
1090 else
1091 mp4sys_remove_descriptor( desc );
1092 }
1093 else
1094 break;
1095 }
1096 return dcd;
1097 }
1098
mp4sys_get_SLConfigDescriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1099 static mp4sys_SLConfigDescriptor_t *mp4sys_get_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1100 {
1101 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( parent );
1102 if( !slcd )
1103 return NULL;
1104 slcd->header.size = header->size;
1105 slcd->predefined = lsmash_bs_get_byte( bs );
1106 if( slcd->predefined == 0x00 )
1107 {
1108 uint8_t temp8 = lsmash_bs_get_byte( bs );
1109 slcd->useAccessUnitStartFlag = (temp8 >> 7) & 0x01;
1110 slcd->useAccessUnitEndFlag = (temp8 >> 6) & 0x01;
1111 slcd->useRandomAccessPointFlag = (temp8 >> 5) & 0x01;
1112 slcd->hasRandomAccessUnitsOnlyFlag = (temp8 >> 4) & 0x01;
1113 slcd->usePaddingFlag = (temp8 >> 3) & 0x01;
1114 slcd->useTimeStampsFlag = (temp8 >> 2) & 0x01;
1115 slcd->useIdleFlag = (temp8 >> 1) & 0x01;
1116 slcd->durationFlag = temp8 & 0x01;
1117 slcd->timeStampResolution = lsmash_bs_get_be32( bs );
1118 slcd->OCRResolution = lsmash_bs_get_be32( bs );
1119 slcd->timeStampLength = lsmash_bs_get_byte( bs );
1120 slcd->OCRLength = lsmash_bs_get_byte( bs );
1121 slcd->AU_Length = lsmash_bs_get_byte( bs );
1122 slcd->instantBitrateLength = lsmash_bs_get_byte( bs );
1123 uint16_t temp16 = lsmash_bs_get_be16( bs );
1124 slcd->degradationPriorityLength = (temp16 >> 12) & 0x0F;
1125 slcd->AU_seqNumLength = (temp16 >> 7) & 0x1F;
1126 slcd->packetSeqNumLength = (temp16 >> 2) & 0x1F;
1127 slcd->reserved = temp16 & 0x03;
1128 }
1129 else if( slcd->predefined == 0x01 )
1130 {
1131 slcd->timeStampResolution = 1000;
1132 slcd->timeStampLength = 32;
1133 }
1134 else if( slcd->predefined == 0x02 )
1135 slcd->useTimeStampsFlag = 1;
1136 if( slcd->durationFlag )
1137 {
1138 slcd->timeScale = lsmash_bs_get_be32( bs );
1139 slcd->accessUnitDuration = lsmash_bs_get_be16( bs );
1140 slcd->compositionUnitDuration = lsmash_bs_get_be16( bs );
1141 }
1142 if( !slcd->useTimeStampsFlag )
1143 {
1144 lsmash_bits_t *bits = lsmash_bits_create( bs );
1145 if( !bits )
1146 {
1147 mp4sys_remove_descriptor( slcd );
1148 return NULL;
1149 }
1150 slcd->startDecodingTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1151 slcd->startCompositionTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1152 lsmash_bits_cleanup( bits );
1153 }
1154 return slcd;
1155 }
1156
mp4sys_get_ES_Descriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1157 static mp4sys_ES_Descriptor_t *mp4sys_get_ES_Descriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1158 {
1159 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, parent, NULL );
1160 if( parent && lsmash_list_add_entry( &((mp4sys_descriptor_t *)parent)->children, esd ) < 0 )
1161 {
1162 mp4sys_remove_descriptor( esd );
1163 return NULL;
1164 }
1165 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1166 esd->header = *header;
1167 esd->ES_ID = lsmash_bs_get_be16( bs );
1168 uint8_t temp = lsmash_bs_get_byte( bs );
1169 esd->streamDependenceFlag = (temp >> 7) & 0x01;
1170 esd->URL_Flag = (temp >> 6) & 0x01;
1171 esd->OCRstreamFlag = (temp >> 5) & 0x01;
1172 esd->streamPriority = temp & 0x1F;
1173 if( esd->streamDependenceFlag )
1174 esd->dependsOn_ES_ID = lsmash_bs_get_be16( bs );
1175 if( esd->URL_Flag )
1176 {
1177 size_t length = lsmash_bs_get_byte( bs );
1178 lsmash_bs_read_data( bs, (uint8_t *)esd->URLstring, &length );
1179 esd->URLlength = length;
1180 }
1181 if( esd->OCRstreamFlag )
1182 esd->OCR_ES_Id = lsmash_bs_get_be16( bs );
1183 /* DecoderConfigDescriptor and SLConfigDescriptor are mandatory. */
1184 while( lsmash_bs_count( bs ) < end_pos )
1185 {
1186 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, esd );
1187 if( desc )
1188 {
1189 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag )
1190 esd->decConfigDescr = (mp4sys_DecoderConfigDescriptor_t *)desc;
1191 else if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag )
1192 esd->slConfigDescr = (mp4sys_SLConfigDescriptor_t *)desc;
1193 else
1194 mp4sys_remove_descriptor( desc );
1195 }
1196 else
1197 break;
1198 }
1199 if( !esd->decConfigDescr || !esd->slConfigDescr )
1200 {
1201 mp4sys_remove_descriptor( esd );
1202 return NULL;
1203 }
1204 return esd;
1205 }
1206
mp4sys_get_ES_ID_Inc(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1207 static mp4sys_ES_ID_Inc_t *mp4sys_get_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1208 {
1209 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( parent );
1210 if( !es_id_inc )
1211 return NULL;
1212 es_id_inc->header.size = header->size;
1213 es_id_inc->Track_ID = lsmash_bs_get_be32( bs );
1214 return es_id_inc;
1215 }
1216
mp4sys_get_ObjectDescriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1217 static mp4sys_ObjectDescriptor_t *mp4sys_get_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1218 {
1219 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, parent, NULL );
1220 if( parent && lsmash_list_add_entry( &((mp4sys_descriptor_t *)parent)->children, od ) < 0 )
1221 {
1222 mp4sys_remove_descriptor( od );
1223 return NULL;
1224 }
1225 od->header = *header;
1226 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1227 uint16_t temp16 = lsmash_bs_get_be16( bs );
1228 od->ObjectDescriptorID = (temp16 >> 6) & 0x03FF;
1229 od->URL_Flag = (temp16 >> 5) & 0x0001;
1230 od->includeInlineProfileLevelFlag = (temp16 >> 4) & 0x0001;
1231 od->reserved = temp16 & 0x000F;
1232 if( od->URL_Flag )
1233 {
1234 size_t length = lsmash_bs_get_byte( bs );
1235 lsmash_bs_read_data( bs, (uint8_t *)od->URLstring, &length );
1236 od->URLlength = length;
1237 }
1238 else
1239 {
1240 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
1241 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
1242 {
1243 od->ODProfileLevelIndication = lsmash_bs_get_byte( bs );
1244 od->sceneProfileLevelIndication = lsmash_bs_get_byte( bs );
1245 od->audioProfileLevelIndication = lsmash_bs_get_byte( bs );
1246 od->visualProfileLevelIndication = lsmash_bs_get_byte( bs );
1247 od->graphicsProfileLevelIndication = lsmash_bs_get_byte( bs );
1248 }
1249 const mp4sys_descriptor_tag at_least_one_descriptor_tag
1250 = od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag
1251 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
1252 ? MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag
1253 : MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
1254 while( lsmash_bs_count( bs ) < end_pos && od->esDescr.entry_count < 255 )
1255 {
1256 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, od );
1257 if( !desc )
1258 break;
1259 if( desc->header.tag != at_least_one_descriptor_tag )
1260 {
1261 mp4sys_remove_descriptor( desc );
1262 break;
1263 }
1264 }
1265 }
1266 return od;
1267 }
1268
mp4sys_get_descriptor(lsmash_bs_t * bs,void * parent)1269 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent )
1270 {
1271 mp4sys_descriptor_head_t header;
1272 mp4sys_get_descriptor_header( bs, &header );
1273 uint64_t end_pos = header.size + lsmash_bs_count( bs );
1274 mp4sys_descriptor_t *desc;
1275 switch( header.tag )
1276 {
1277 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
1278 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
1279 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
1280 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
1281 desc = (mp4sys_descriptor_t *)mp4sys_get_ObjectDescriptor( bs, &header, parent );
1282 break;
1283 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
1284 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_Descriptor( bs, &header, parent );
1285 break;
1286 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
1287 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderConfigDescriptor( bs, &header, parent );
1288 break;
1289 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1290 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderSpecificInfo( bs, &header, parent );
1291 break;
1292 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1293 desc = (mp4sys_descriptor_t *)mp4sys_get_SLConfigDescriptor( bs, &header, parent );
1294 break;
1295 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1296 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_ID_Inc( bs, &header, parent );
1297 break;
1298 default :
1299 desc = lsmash_malloc_zero( sizeof(mp4sys_descriptor_t) );
1300 if( desc )
1301 {
1302 desc->parent = parent;
1303 desc->header = header;
1304 }
1305 break;
1306 }
1307 /* Skip extra bytes if present. */
1308 uint64_t skip_bytes = end_pos - lsmash_bs_count( bs );
1309 if( skip_bytes )
1310 {
1311 fprintf( stderr, "[MPEG-4 Systems Descriptor Tag = 0x%02"PRIx8"] has more bytes than expected: %"PRId64"\n", header.tag, skip_bytes );
1312 if( !bs->unseekable )
1313 {
1314 /* The stream is seekable. So, skip by seeking the stream. */
1315 uint64_t start = lsmash_bs_get_stream_pos( bs );
1316 lsmash_bs_read_seek( bs, skip_bytes, SEEK_CUR );
1317 uint64_t end = lsmash_bs_get_stream_pos( bs );
1318 bs->buffer.count += end - start;
1319 }
1320 else
1321 /* The stream is unseekable. So, skip by reading the stream. */
1322 lsmash_bs_skip_bytes_64( bs, skip_bytes );
1323 }
1324 return desc;
1325 }
1326
mp4sys_export_DecoderSpecificInfo(mp4sys_ES_Descriptor_t * esd,uint32_t * dsi_payload_length)1327 static uint8_t *mp4sys_export_DecoderSpecificInfo( mp4sys_ES_Descriptor_t *esd, uint32_t *dsi_payload_length )
1328 {
1329 if( !esd || !esd->decConfigDescr || !esd->decConfigDescr->decSpecificInfo )
1330 return NULL;
1331 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)esd->decConfigDescr->decSpecificInfo;
1332 uint8_t *dsi_payload = NULL;
1333 /* DecoderSpecificInfo can be absent. */
1334 if( dsi->header.size )
1335 {
1336 dsi_payload = lsmash_memdup( dsi->data, dsi->header.size );
1337 if( !dsi_payload )
1338 return NULL;
1339 }
1340 if( dsi_payload_length )
1341 *dsi_payload_length = dsi->header.size;
1342 return dsi_payload;
1343 }
1344
1345 /* Sumamry is needed to decide ProfileLevelIndication.
1346 * Currently, support audio's only. */
mp4sys_setup_summary_from_DecoderSpecificInfo(lsmash_audio_summary_t * summary,mp4sys_ES_Descriptor_t * esd)1347 int mp4sys_setup_summary_from_DecoderSpecificInfo( lsmash_audio_summary_t *summary, mp4sys_ES_Descriptor_t *esd )
1348 {
1349 uint32_t dsi_payload_length = UINT32_MAX; /* arbitrary */
1350 uint8_t *dsi_payload = mp4sys_export_DecoderSpecificInfo( esd, &dsi_payload_length );
1351 if( !dsi_payload && dsi_payload_length )
1352 return LSMASH_ERR_NAMELESS;
1353 int err = 0;
1354 if( dsi_payload_length )
1355 {
1356 lsmash_codec_specific_t *cs = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG,
1357 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1358 if( !cs )
1359 {
1360 err = LSMASH_ERR_MEMORY_ALLOC;
1361 goto fail;
1362 }
1363 lsmash_mp4sys_decoder_parameters_t *params = (lsmash_mp4sys_decoder_parameters_t *)cs->data.structured;
1364 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1365 params->objectTypeIndication = dcd->objectTypeIndication;
1366 params->streamType = dcd->streamType;
1367 params->bufferSizeDB = dcd->bufferSizeDB;
1368 params->maxBitrate = dcd->maxBitrate;
1369 params->avgBitrate = dcd->avgBitrate;
1370 if( (err = mp4a_setup_summary_from_AudioSpecificConfig( summary, dsi_payload, dsi_payload_length )) < 0
1371 || (err = lsmash_set_mp4sys_decoder_specific_info( params, dsi_payload, dsi_payload_length )) < 0
1372 || (err = lsmash_list_add_entry( &summary->opaque->list, cs )) < 0 )
1373 {
1374 lsmash_destroy_codec_specific_data( cs );
1375 goto fail;
1376 }
1377 }
1378 fail:
1379 lsmash_free( dsi_payload );
1380 return err;
1381 }
1382
1383 /**** following functions are for facilitation purpose ****/
1384
mp4sys_setup_ES_Descriptor(mp4sys_ES_Descriptor_params_t * params)1385 mp4sys_ES_Descriptor_t *mp4sys_setup_ES_Descriptor( mp4sys_ES_Descriptor_params_t *params )
1386 {
1387 if( !params )
1388 return NULL;
1389 mp4sys_ES_Descriptor_t *esd = mp4sys_create_ES_Descriptor( params->ES_ID );
1390 if( !esd )
1391 return NULL;
1392 /* DecoderConfigDescriptor */
1393 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( esd );
1394 if( !dcd )
1395 goto fail;
1396 dcd->objectTypeIndication = params->objectTypeIndication;
1397 dcd->streamType = params->streamType;
1398 dcd->upStream = 0;
1399 dcd->reserved = 1;
1400 dcd->bufferSizeDB = params->bufferSizeDB;
1401 dcd->maxBitrate = params->maxBitrate;
1402 dcd->avgBitrate = params->avgBitrate;
1403 /* DecoderSpecificInfo */
1404 if( params->dsi_payload && params->dsi_payload_length != 0 )
1405 {
1406 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( dcd );
1407 if( !dsi )
1408 goto fail;
1409 dsi->data = lsmash_memdup( params->dsi_payload, params->dsi_payload_length );
1410 if( !dsi->data )
1411 goto fail;
1412 dsi->header.size = params->dsi_payload_length;
1413 }
1414 /* SLConfigDescriptor */
1415 {
1416 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( esd );
1417 if( !slcd )
1418 goto fail;
1419 slcd->predefined = 0x02; /* MP4 file which does not use URL_Flag shall have constant value 0x02 */
1420 slcd->useTimeStampsFlag = 1; /* set to 1 if predefined == 2 */
1421 }
1422 return esd;
1423 fail:
1424 mp4sys_remove_descriptor( esd );
1425 return NULL;
1426 }
1427
lsmash_set_mp4sys_decoder_specific_info(lsmash_mp4sys_decoder_parameters_t * param,uint8_t * payload,uint32_t payload_length)1428 int lsmash_set_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t *payload, uint32_t payload_length )
1429 {
1430 if( !param || !payload || payload_length == 0 )
1431 return LSMASH_ERR_FUNCTION_PARAM;
1432 if( !param->dsi )
1433 {
1434 param->dsi = lsmash_malloc_zero( sizeof(lsmash_mp4sys_decoder_specific_info_t) );
1435 if( !param->dsi )
1436 return LSMASH_ERR_MEMORY_ALLOC;
1437 }
1438 else
1439 {
1440 lsmash_freep( ¶m->dsi->payload );
1441 param->dsi->payload_length = 0;
1442 }
1443 param->dsi->payload = lsmash_memdup( payload, payload_length );
1444 if( !param->dsi->payload )
1445 return LSMASH_ERR_MEMORY_ALLOC;
1446 param->dsi->payload_length = payload_length;
1447 return 0;
1448 }
1449
lsmash_destroy_mp4sys_decoder_specific_info(lsmash_mp4sys_decoder_parameters_t * param)1450 void lsmash_destroy_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param )
1451 {
1452 if( !param || !param->dsi )
1453 return;
1454 lsmash_free( param->dsi->payload );
1455 lsmash_freep( ¶m->dsi );
1456 }
1457
mp4sys_destruct_decoder_config(void * data)1458 void mp4sys_destruct_decoder_config( void *data )
1459 {
1460 if( !data )
1461 return;
1462 lsmash_destroy_mp4sys_decoder_specific_info( data );
1463 lsmash_free( data );
1464 }
1465
lsmash_create_mp4sys_decoder_config(lsmash_mp4sys_decoder_parameters_t * param,uint32_t * data_length)1466 uint8_t *lsmash_create_mp4sys_decoder_config( lsmash_mp4sys_decoder_parameters_t *param, uint32_t *data_length )
1467 {
1468 if( !param || !data_length )
1469 return NULL;
1470 mp4sys_ES_Descriptor_params_t esd_param = { 0 };
1471 esd_param.ES_ID = 0; /* Within sample description, ES_ID is stored as 0. */
1472 esd_param.objectTypeIndication = param->objectTypeIndication;
1473 esd_param.streamType = param->streamType;
1474 esd_param.bufferSizeDB = param->bufferSizeDB;
1475 esd_param.maxBitrate = param->maxBitrate;
1476 esd_param.avgBitrate = param->avgBitrate;
1477 if( param->dsi
1478 && param->dsi->payload
1479 && param->dsi->payload_length )
1480 {
1481 esd_param.dsi_payload = param->dsi->payload;
1482 esd_param.dsi_payload_length = param->dsi->payload_length;
1483 }
1484 mp4sys_ES_Descriptor_t *esd = mp4sys_setup_ES_Descriptor( &esd_param );
1485 if( !esd )
1486 return NULL;
1487 lsmash_bs_t *bs = lsmash_bs_create();
1488 if( !bs )
1489 {
1490 mp4sys_remove_descriptor( esd );
1491 return NULL;
1492 }
1493 lsmash_bs_put_be32( bs, 0 ); /* update later */
1494 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_ESDS.fourcc );
1495 lsmash_bs_put_be32( bs, 0 );
1496 mp4sys_update_descriptor_size( esd );
1497 mp4sys_write_descriptor( bs, esd );
1498 mp4sys_remove_descriptor( esd );
1499 uint8_t *data = lsmash_bs_export_data( bs, data_length );
1500 lsmash_bs_cleanup( bs );
1501 if( !data )
1502 return NULL;
1503 /* Update box size. */
1504 LSMASH_SET_BE32( data, *data_length );
1505 return data;
1506 }
1507
mp4sys_construct_decoder_config(lsmash_codec_specific_t * dst,lsmash_codec_specific_t * src)1508 int mp4sys_construct_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1509 {
1510 assert( dst && dst->data.structured && src && src->data.unstructured );
1511 if( src->size < ISOM_FULLBOX_COMMON_SIZE + 23 )
1512 return LSMASH_ERR_INVALID_DATA;
1513 lsmash_mp4sys_decoder_parameters_t *param = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1514 uint8_t *data = src->data.unstructured;
1515 uint64_t size = LSMASH_GET_BE32( data );
1516 data += ISOM_BASEBOX_COMMON_SIZE;
1517 if( size == 1 )
1518 {
1519 size = LSMASH_GET_BE64( data );
1520 data += 8;
1521 }
1522 if( size != src->size )
1523 return LSMASH_ERR_INVALID_DATA;
1524 data += 4; /* Skip version and flags. */
1525 lsmash_bs_t *bs = lsmash_bs_create();
1526 if( !bs )
1527 return LSMASH_ERR_MEMORY_ALLOC;
1528 int err = lsmash_bs_import_data( bs, data, src->size - (data - src->data.unstructured) );
1529 if( err < 0 )
1530 {
1531 lsmash_bs_cleanup( bs );
1532 return err;
1533 }
1534 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)mp4sys_get_descriptor( bs, NULL );
1535 lsmash_bs_cleanup( bs );
1536 if( !esd || esd->header.tag != MP4SYS_DESCRIPTOR_TAG_ES_DescrTag || !esd->decConfigDescr )
1537 return LSMASH_ERR_INVALID_DATA;
1538 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1539 param->objectTypeIndication = dcd->objectTypeIndication;
1540 param->streamType = dcd->streamType;
1541 param->bufferSizeDB = dcd->bufferSizeDB;
1542 param->maxBitrate = dcd->maxBitrate;
1543 param->avgBitrate = dcd->avgBitrate;
1544 mp4sys_DecoderSpecificInfo_t *dsi = dcd->decSpecificInfo;
1545 if( dsi
1546 && dsi->header.size
1547 && dsi->data
1548 && (err = lsmash_set_mp4sys_decoder_specific_info( param, dsi->data, dsi->header.size )) < 0 )
1549 {
1550 mp4sys_remove_descriptor( esd );
1551 return err;
1552 }
1553 mp4sys_remove_descriptor( esd );
1554 return 0;
1555 }
1556
mp4sys_copy_decoder_config(lsmash_codec_specific_t * dst,lsmash_codec_specific_t * src)1557 int mp4sys_copy_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1558 {
1559 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
1560 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
1561 lsmash_mp4sys_decoder_parameters_t *src_data = (lsmash_mp4sys_decoder_parameters_t *)src->data.structured;
1562 lsmash_mp4sys_decoder_parameters_t *dst_data = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1563 lsmash_destroy_mp4sys_decoder_specific_info( dst_data );
1564 *dst_data = *src_data;
1565 dst_data->dsi = NULL;
1566 if( !src_data->dsi || !src_data->dsi->payload || src_data->dsi->payload_length == 0 )
1567 return 0;
1568 return lsmash_set_mp4sys_decoder_specific_info( dst_data, src_data->dsi->payload, src_data->dsi->payload_length );
1569 }
1570
lsmash_mp4sys_get_object_type_indication(lsmash_summary_t * summary)1571 lsmash_mp4sys_object_type_indication lsmash_mp4sys_get_object_type_indication( lsmash_summary_t *summary )
1572 {
1573 if( !summary )
1574 return MP4SYS_OBJECT_TYPE_Forbidden;
1575 lsmash_codec_specific_t *orig = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1576 if( !orig )
1577 return MP4SYS_OBJECT_TYPE_Forbidden;
1578 /* Found decoder configuration.
1579 * Let's get objectTypeIndication. */
1580 lsmash_mp4sys_object_type_indication objectTypeIndication;
1581 if( orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1582 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)orig->data.structured)->objectTypeIndication;
1583 else
1584 {
1585 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( orig, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1586 if( !conv )
1587 return MP4SYS_OBJECT_TYPE_Forbidden;
1588 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)conv->data.structured)->objectTypeIndication;
1589 lsmash_destroy_codec_specific_data( conv );
1590 }
1591 return objectTypeIndication;
1592 }
1593
lsmash_get_mp4sys_decoder_specific_info(lsmash_mp4sys_decoder_parameters_t * param,uint8_t ** payload,uint32_t * payload_length)1594 int lsmash_get_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t **payload, uint32_t *payload_length )
1595 {
1596 if( !param || !payload || !payload_length )
1597 return LSMASH_ERR_FUNCTION_PARAM;
1598 if( !param->dsi || !param->dsi->payload || param->dsi->payload_length == 0 )
1599 {
1600 *payload = NULL;
1601 *payload_length = 0;
1602 return 0;
1603 }
1604 uint8_t *temp = lsmash_memdup( param->dsi->payload, param->dsi->payload_length );
1605 if( !temp )
1606 return LSMASH_ERR_MEMORY_ALLOC;
1607 *payload = temp;
1608 *payload_length = param->dsi->payload_length;
1609 return 0;
1610 }
1611