isom: Evaluate return value properly.
[L-SMASH.git] / codecs / mp4sys.c
bloba9a21f958c16a93d343bbcfc3be3ef3e6f4381b7
1 /*****************************************************************************
2 * mp4sys.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2014 L-SMASH project
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
7 * Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
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.
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 *****************************************************************************/
22 /* This file is available under an ISC license. */
24 #include "common/internal.h" /* must be placed first */
26 #include <stdlib.h>
27 #include <string.h>
28 #include <inttypes.h>
30 #include "core/box.h"
32 #include "description.h"
33 #include "mp4a.h"
34 #define MP4SYS_INTERNAL
35 #include "mp4sys.h"
37 /***************************************************************************
38 MPEG-4 Systems
39 ***************************************************************************/
41 #define ALWAYS_28BITS_LENGTH_CODING 1 // for some weird (but originator's) devices
43 static const lsmash_class_t lsmash_mp4sys_class =
45 "mp4sys"
48 /* List of Class Tags for Descriptors */
49 typedef enum
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 */
87 typedef struct
89 uint32_t size; // 2^28 at most
90 mp4sys_descriptor_tag tag;
91 } mp4sys_descriptor_head_t;
93 typedef struct mp4sys_descriptor_tag mp4sys_descriptor_t;
95 typedef void (*mp4sys_descriptor_destructor_t)( void * );
96 typedef int (*mp4sys_descriptor_writer_t)( lsmash_bs_t *, void * );
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
106 struct mp4sys_descriptor_tag
108 MP4SYS_DESCRIPTOR_COMMON;
111 typedef struct
113 MP4SYS_DESCRIPTOR_COMMON;
114 } mp4sys_BaseDescriptor_t;
116 /* DecoderSpecificInfo */
117 /* contents varies depends on ObjectTypeIndication and StreamType. */
118 typedef struct
120 MP4SYS_DESCRIPTOR_COMMON;
121 uint8_t *data;
122 } mp4sys_DecoderSpecificInfo_t;
124 /* DecoderConfigDescriptor */
125 typedef struct
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;
143 /* SLConfigDescriptor */
144 typedef struct
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;
182 /* ES_Descriptor */
183 typedef struct mp4sys_ES_Descriptor_t
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 */
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
208 } mp4sys_ES_Descriptor_t;
210 /* 14496-14 Object Descriptors (ES_ID_Inc) */
211 typedef struct
213 MP4SYS_DESCRIPTOR_COMMON;
214 uint32_t Track_ID;
215 } mp4sys_ES_ID_Inc_t;
217 /* 14496-1 ObjectDescriptor / InitialObjectDescriptor */
218 typedef struct
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;
240 static void mp4sys_remove_predefined_descriptor( void *opaque_descriptor, size_t offset_of_descriptor )
242 assert( opaque_descriptor );
243 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
244 if( descriptor->parent )
246 mp4sys_descriptor_t **p = (mp4sys_descriptor_t **)(((int8_t *)descriptor->parent) + offset_of_descriptor);
247 if( *p == descriptor )
248 *p = NULL;
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. */
254 static void mp4sys_remove_descriptor_in_predefined_list( void *opaque_descriptor, size_t offset_of_list )
256 assert( opaque_descriptor );
257 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
258 if( descriptor->parent )
260 lsmash_entry_list_t *list = (lsmash_entry_list_t *)(((int8_t *)descriptor->parent) + offset_of_list);
261 for( lsmash_entry_t *entry = list ? list->head : NULL; entry; entry = entry->next )
262 if( descriptor == entry->data )
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_remove_entry_direct( list, entry, NULL );
269 break;
274 static void mp4sys_remove_all_child_descriptors( lsmash_entry_list_t *children );
276 /* Free a descriptor and its children. */
277 static void mp4sys_destruct_descriptor( mp4sys_descriptor_t *descriptor )
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 );
287 static void mp4sys_remove_all_child_descriptors( lsmash_entry_list_t *children )
289 lsmash_remove_entries( children, mp4sys_destruct_descriptor );
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. */
296 void mp4sys_remove_descriptor( void *opaque_descriptor )
298 if( !opaque_descriptor )
299 return;
300 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
301 if( descriptor->parent )
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 )
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_remove_entry_direct( &parent->children, entry, mp4sys_destruct_descriptor );
310 return;
313 mp4sys_destruct_descriptor( descriptor );
316 static void mp4sys_remove_DecoderSpecificInfo( mp4sys_DecoderSpecificInfo_t *dsi )
318 if( !dsi )
319 return;
320 lsmash_free( dsi->data );
321 mp4sys_remove_predefined_descriptor( dsi, offsetof( mp4sys_DecoderConfigDescriptor_t, decSpecificInfo ) );
324 static void mp4sys_remove_DecoderConfigDescriptor( mp4sys_DecoderConfigDescriptor_t *dcd )
326 if( !dcd )
327 return;
328 mp4sys_remove_predefined_descriptor( dcd, offsetof( mp4sys_ES_Descriptor_t, decConfigDescr ) );
331 static void mp4sys_remove_SLConfigDescriptor( mp4sys_SLConfigDescriptor_t *slcd )
333 if( !slcd )
334 return;
335 mp4sys_remove_predefined_descriptor( slcd, offsetof( mp4sys_ES_Descriptor_t, slConfigDescr ) );
338 static void mp4sys_remove_ES_Descriptor( mp4sys_ES_Descriptor_t *esd )
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 ) );
346 static void mp4sys_remove_ES_ID_Inc( mp4sys_ES_ID_Inc_t *es_id_inc )
348 if( !es_id_inc )
349 return;
350 mp4sys_remove_descriptor_in_predefined_list( es_id_inc, offsetof( mp4sys_ObjectDescriptor_t, esDescr ) );
353 static void mp4sys_remove_ObjectDescriptor( mp4sys_ObjectDescriptor_t *od )
357 static inline uint32_t mp4sys_get_descriptor_header_size( uint32_t payload_size_in_byte )
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
370 /* returns total size of descriptor, including header, 2 at least */
371 static inline uint32_t mp4sys_get_descriptor_size( uint32_t payload_size_in_byte )
373 return payload_size_in_byte + mp4sys_get_descriptor_header_size( payload_size_in_byte );
376 static inline void mp4sys_write_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
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 );
389 #endif
390 lsmash_bs_put_byte( bs, header->size & 0x7F );
393 int mp4sys_write_descriptor( lsmash_bs_t *bs, void *opaque_descriptor );
395 static int mp4sys_write_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_DecoderSpecificInfo_t *dsi )
397 if( dsi->data && dsi->header.size != 0 )
398 lsmash_bs_put_bytes( bs, dsi->header.size, dsi->data );
399 return 0;
402 static int mp4sys_write_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_DecoderConfigDescriptor_t *dcd )
404 lsmash_bs_put_byte( bs, dcd->objectTypeIndication );
405 uint8_t temp;
406 temp = (dcd->streamType << 2) & 0x3F;
407 temp |= (dcd->upStream << 1) & 0x01;
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;
417 static int mp4sys_write_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_SLConfigDescriptor_t *slcd )
419 lsmash_bs_put_byte( bs, slcd->predefined );
420 if( slcd->predefined == 0x00 )
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 );
445 if( slcd->durationFlag )
447 lsmash_bs_put_be32( bs, slcd->timeScale );
448 lsmash_bs_put_be16( bs, slcd->accessUnitDuration );
449 lsmash_bs_put_be16( bs, slcd->compositionUnitDuration );
451 if( !slcd->useTimeStampsFlag )
453 lsmash_bits_t *bits = lsmash_bits_create( bs );
454 if( !bits )
455 return -1;
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 );
461 return 0;
464 static int mp4sys_write_ES_Descriptor( lsmash_bs_t *bs, mp4sys_ES_Descriptor_t *esd )
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 )
477 lsmash_bs_put_byte( bs, esd->URLlength );
478 lsmash_bs_put_bytes( bs, esd->URLlength, esd->URLstring );
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;
486 static int mp4sys_write_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_ES_ID_Inc_t *es_id_inc )
488 lsmash_bs_put_be32( bs, es_id_inc->Track_ID );
489 return 0;
492 static int mp4sys_write_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_ObjectDescriptor_t *od )
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 )
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 );
508 return 0;
511 static int mp4sys_write_children( lsmash_bs_t *bs, mp4sys_descriptor_t *descriptor )
513 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
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;
522 return 0;
525 int mp4sys_write_descriptor( lsmash_bs_t *bs, void *opaque_descriptor )
527 if( !bs || !opaque_descriptor )
528 return -1;
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 if( descriptor->write( bs, descriptor ) < 0 )
534 return -1;
535 return mp4sys_write_children( bs, descriptor );
538 /* descriptor size updater */
539 uint32_t mp4sys_update_descriptor_size( void *opaque_descriptor )
541 assert( opaque_descriptor );
542 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
543 uint64_t size = 0;
544 if( descriptor->write )
546 uint32_t header_size = descriptor->header.size;
547 /* Calculate the size of this descriptor excluding its children with a fake bytestream writer. */
549 lsmash_bs_t fake_bs = { NULL };
550 mp4sys_write_descriptor_header( &fake_bs, &descriptor->header );
551 if( descriptor->write( &fake_bs, descriptor ) == 0 )
552 size = lsmash_bs_get_valid_data_size( &fake_bs );
554 /* Calculate the size including the children if no error. */
555 if( size >= mp4sys_get_descriptor_header_size( header_size ) )
557 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
558 if( entry->data )
559 size += mp4sys_update_descriptor_size( entry->data );
560 /* Calculate the size of this descriptor excluding its header. */
561 size -= mp4sys_get_descriptor_header_size( header_size );
562 descriptor->header.size = size;
563 /* Now, we get the actual size of this descriptor. */
564 size += mp4sys_get_descriptor_header_size( size );
566 else
568 /* Invalid descriptor */
569 descriptor->header.size = 0;
570 size = 0;
573 else
574 descriptor->header.size = 0;
575 return size;
578 static inline void *mp4sys_construct_descriptor_orig
580 size_t size,
581 mp4sys_descriptor_t *parent,
582 mp4sys_descriptor_destructor_t destructor,
583 mp4sys_descriptor_writer_t writer
586 assert( size >= sizeof(mp4sys_BaseDescriptor_t) );
587 mp4sys_descriptor_t *descriptor = lsmash_malloc_zero( size );
588 if( !descriptor )
589 return NULL;
590 descriptor->class = &lsmash_mp4sys_class;
591 descriptor->parent = parent;
592 descriptor->destruct = destructor;
593 descriptor->write = writer;
594 return descriptor;
597 #define mp4sys_construct_descriptor( size, parent, destructor, writer ) \
598 mp4sys_construct_descriptor_orig \
600 size, \
601 (mp4sys_descriptor_t *)parent, \
602 (mp4sys_descriptor_destructor_t)destructor, \
603 (mp4sys_descriptor_writer_t)writer \
606 #define MP4SYS_CONSTRUCT_DESCRIPTOR( var, descriptor_name, parent, ret ) \
607 mp4sys_##descriptor_name##_t *var = \
608 mp4sys_construct_descriptor \
610 sizeof(mp4sys_##descriptor_name##_t), \
611 parent, \
612 mp4sys_remove_##descriptor_name, \
613 mp4sys_write_##descriptor_name \
614 ); \
615 if( !var ) \
616 return ret
618 static mp4sys_DecoderSpecificInfo_t *mp4sys_add_DecoderSpecificInfo( mp4sys_DecoderConfigDescriptor_t *dcd )
620 if( !dcd )
621 return NULL;
622 MP4SYS_CONSTRUCT_DESCRIPTOR( dsi, DecoderSpecificInfo, dcd, NULL );
623 dsi->header.tag = MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag;
624 if( lsmash_add_entry( &dcd->children, dsi ) < 0 )
626 mp4sys_remove_descriptor( dsi );
627 return NULL;
629 dcd->decSpecificInfo = dsi;
630 return dsi;
634 bufferSizeDB is byte unit, NOT bit unit.
635 avgBitrate is 0 if VBR
637 static mp4sys_DecoderConfigDescriptor_t *mp4sys_add_DecoderConfigDescriptor
639 mp4sys_ES_Descriptor_t *esd
642 if( !esd )
643 return NULL;
644 MP4SYS_CONSTRUCT_DESCRIPTOR( dcd, DecoderConfigDescriptor, esd, NULL );
645 dcd->header.tag = MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag;
646 if( lsmash_add_entry( &esd->children, dcd ) < 0 )
648 mp4sys_remove_descriptor( dcd );
649 return NULL;
651 esd->decConfigDescr = dcd;
652 return dcd;
655 static mp4sys_SLConfigDescriptor_t *mp4sys_add_SLConfigDescriptor( mp4sys_ES_Descriptor_t *esd )
657 if( !esd )
658 return NULL;
659 MP4SYS_CONSTRUCT_DESCRIPTOR( slcd, SLConfigDescriptor, esd, NULL );
660 slcd->header.tag = MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag;
661 if( lsmash_add_entry( &esd->children, slcd ) < 0 )
663 mp4sys_remove_descriptor( slcd );
664 return NULL;
666 esd->slConfigDescr = slcd;
667 return slcd;
670 /* NOTE: This is only for MP4_IOD and MP4_OD, not for ISO Base Media's ObjectDescriptor and InitialObjectDescriptor */
671 static mp4sys_ES_ID_Inc_t *mp4sys_add_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od )
673 if( !od
674 || (od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
675 && od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag) )
676 return NULL;
677 MP4SYS_CONSTRUCT_DESCRIPTOR( es_id_inc, ES_ID_Inc, od, NULL );
678 es_id_inc->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag;
679 if( lsmash_add_entry( &od->children, es_id_inc ) < 0 )
681 mp4sys_remove_descriptor( es_id_inc );
682 return NULL;
684 if( lsmash_add_entry( &od->esDescr, es_id_inc ) < 0 )
686 lsmash_remove_entry_tail( &od->children, mp4sys_remove_ES_ID_Inc );
687 return NULL;
689 return es_id_inc;
692 int mp4sys_create_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od, uint32_t Track_ID )
694 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( od );
695 if( !es_id_inc )
696 return -1;
697 es_id_inc->Track_ID = Track_ID;
698 return 0;
701 /* ES_ID of the ES Descriptor is stored as 0 when the ES Descriptor is built into sample descriptions in MP4 file format
702 * 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. */
703 mp4sys_ES_Descriptor_t *mp4sys_create_ES_Descriptor( uint16_t ES_ID )
705 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, NULL, NULL );
706 esd->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
707 esd->ES_ID = ES_ID;
708 return esd;
711 /* NOTE: This is only for MP4_OD, not for ISO Base Media's ObjectDescriptor */
712 mp4sys_ObjectDescriptor_t *mp4sys_create_ObjectDescriptor( uint16_t ObjectDescriptorID )
714 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, NULL, NULL );
715 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag;
716 od->ObjectDescriptorID = ObjectDescriptorID;
717 od->includeInlineProfileLevelFlag = 1; /* 1 as part of reserved flag. */
718 od->ODProfileLevelIndication = MP4SYS_OD_PLI_NONE_REQUIRED;
719 od->sceneProfileLevelIndication = MP4SYS_SCENE_PLI_NONE_REQUIRED;
720 od->audioProfileLevelIndication = MP4A_AUDIO_PLI_NONE_REQUIRED;
721 od->visualProfileLevelIndication = MP4SYS_VISUAL_PLI_NONE_REQUIRED;
722 od->graphicsProfileLevelIndication = MP4SYS_GRAPHICS_PLI_NONE_REQUIRED;
723 return od;
726 /* NOTE: This is only for MP4_IOD, not for Iso Base Media's InitialObjectDescriptor */
727 int mp4sys_to_InitialObjectDescriptor
729 mp4sys_ObjectDescriptor_t *od,
730 uint8_t include_inline_pli,
731 mp4sys_ODProfileLevelIndication od_pli,
732 mp4sys_sceneProfileLevelIndication scene_pli,
733 mp4a_audioProfileLevelIndication audio_pli,
734 mp4sys_visualProfileLevelIndication visual_pli,
735 mp4sys_graphicsProfileLevelIndication graph_pli
738 if( !od )
739 return -1;
740 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag;
741 od->includeInlineProfileLevelFlag = include_inline_pli;
742 od->ODProfileLevelIndication = od_pli;
743 od->sceneProfileLevelIndication = scene_pli;
744 od->audioProfileLevelIndication = audio_pli;
745 od->visualProfileLevelIndication = visual_pli;
746 od->graphicsProfileLevelIndication = graph_pli;
747 return 0;
750 #ifdef LSMASH_DEMUXER_ENABLED
752 bufferSizeDB is byte unit, NOT bit unit.
753 avgBitrate is 0 if VBR
755 int mp4sys_update_DecoderConfigDescriptor( mp4sys_ES_Descriptor_t *esd, uint32_t bufferSizeDB, uint32_t maxBitrate, uint32_t avgBitrate )
757 if( !esd || !esd->decConfigDescr )
758 return -1;
759 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
760 dcd->bufferSizeDB = bufferSizeDB;
761 dcd->maxBitrate = maxBitrate;
762 dcd->avgBitrate = avgBitrate;
763 return 0;
766 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent );
768 static void mp4sys_print_descriptor_header( FILE *fp, mp4sys_descriptor_head_t *header, int indent )
770 static const char *descriptor_names_table[256] =
772 "Forbidden",
773 "ObjectDescriptor",
774 "InitialObjectDescriptor",
775 "ES_Descriptor",
776 "DecoderConfigDescriptor",
777 "DecoderSpecificInfo",
778 "SLConfigDescriptor",
779 [0x0E] = "ES_ID_Inc",
780 [0x0F] = "ES_ID_Ref",
781 [0x10] = "MP4_IOD",
782 [0x11] = "MP4_OD"
784 if( descriptor_names_table[ header->tag ] )
785 lsmash_ifprintf( fp, indent, "[tag = 0x%02"PRIx8": %s]\n", header->tag, descriptor_names_table[ header->tag ] );
786 else
787 lsmash_ifprintf( fp, indent, "[tag = 0x%02"PRIx8"]\n", header->tag );
788 lsmash_ifprintf( fp, ++indent, "expandableClassSize = %"PRIu32"\n", header->size );
791 static void mp4sys_print_DecoderSpecificInfo( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
793 extern void mp4a_print_AudioSpecificConfig( FILE *, uint8_t *, uint32_t, int );
794 if( !descriptor->parent || descriptor->parent->header.tag != MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag )
795 return;
796 mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor->parent;
797 if( dcd->streamType != MP4SYS_STREAM_TYPE_AudioStream
798 || dcd->objectTypeIndication != MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3 )
799 return; /* We support only AudioSpecificConfig here currently. */
800 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)descriptor;
801 mp4a_print_AudioSpecificConfig( fp, dsi->data, dsi->header.size, indent );
804 static void mp4sys_print_DecoderConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
806 mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor;
807 static const char *object_type_indication_descriptions_table[256] =
809 "Forbidden",
810 "Systems ISO/IEC 14496-1 (a)",
811 "Systems ISO/IEC 14496-1 (b)",
812 "Interaction Stream",
813 "Systems ISO/IEC 14496-1 Extended BIFS Configuration",
814 "Systems ISO/IEC 14496-1 AFX",
815 "Font Data Stream",
816 "Synthesized Texture Stream",
817 "Streaming Text Stream",
818 "LASeR Stream",
819 "Simple Aggregation Format (SAF) Stream",
820 [0x20] = "Visual ISO/IEC 14496-2",
821 [0x21] = "Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10",
822 [0x22] = "Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10",
823 [0x40] = "Audio ISO/IEC 14496-3",
824 [0x60] = "Visual ISO/IEC 13818-2 Simple Profile",
825 [0x61] = "Visual ISO/IEC 13818-2 Main Profile",
826 [0x62] = "Visual ISO/IEC 13818-2 SNR Profile",
827 [0x63] = "Visual ISO/IEC 13818-2 Spatial Profile",
828 [0x64] = "Visual ISO/IEC 13818-2 High Profile",
829 [0x65] = "Visual ISO/IEC 13818-2 422 Profile",
830 [0x66] = "Audio ISO/IEC 13818-7 Main Profile",
831 [0x67] = "Audio ISO/IEC 13818-7 LowComplexity Profile",
832 [0x68] = "Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile",
833 [0x69] = "Audio ISO/IEC 13818-3",
834 [0x6A] = "Visual ISO/IEC 11172-2",
835 [0x6B] = "Audio ISO/IEC 11172-3",
836 [0x6C] = "Visual ISO/IEC 10918-1",
837 [0x6D] = "Portable Network Graphics",
838 [0x6E] = "Visual ISO/IEC 15444-1 (JPEG 2000)",
839 [0xA0] = "EVRC Voice",
840 [0xA1] = "SMV Voice",
841 [0xA2] = "3GPP2 Compact Multimedia Format (CMF)",
842 [0xA3] = "SMPTE VC-1 Video",
843 [0xA4] = "Dirac Video Coder",
844 [0xA5] = "AC-3 Audio",
845 [0xA6] = "Enhanced AC-3 audio",
846 [0xA7] = "DRA Audio",
847 [0xA8] = "ITU G.719 Audio",
848 [0xA9] = "DTS Coherent Acoustics audio",
849 [0xAA] = "DTS-HD High Resolution Audio",
850 [0xAB] = "DTS-HD Master Audio",
851 [0xAC] = "DTS Express low bit rate audio",
852 [0xE1] = "13K Voice",
853 [0xFF] = "no object type specified"
855 static const char *stream_type_descriptions_table[64] =
857 "Forbidden",
858 "ObjectDescriptorStream",
859 "ClockReferenceStream",
860 "SceneDescriptionStream",
861 "VisualStream",
862 "AudioStream",
863 "MPEG7Stream",
864 "IPMPStream",
865 "ObjectContentInfoStream",
866 "MPEGJStream",
867 "Interaction Stream",
868 "IPMPToolStream",
869 "FontDataStream",
870 "StreamingText"
872 if( object_type_indication_descriptions_table[ dcd->objectTypeIndication ] )
873 lsmash_ifprintf( fp, indent, "objectTypeIndication = 0x%02"PRIx8" (%s)\n", dcd->objectTypeIndication, object_type_indication_descriptions_table[ dcd->objectTypeIndication ] );
874 else
875 lsmash_ifprintf( fp, indent, "objectTypeIndication = 0x%02"PRIx8"\n", dcd->objectTypeIndication );
876 if( stream_type_descriptions_table[ dcd->streamType ] )
877 lsmash_ifprintf( fp, indent, "streamType = 0x%02"PRIx8" (%s)\n", dcd->streamType, stream_type_descriptions_table[ dcd->streamType ] );
878 else
879 lsmash_ifprintf( fp, indent, "streamType = 0x%02"PRIx8"\n", dcd->streamType );
880 lsmash_ifprintf( fp, indent, "upStream = %"PRIu8"\n", dcd->upStream );
881 lsmash_ifprintf( fp, indent, "reserved = %"PRIu8"\n", dcd->reserved );
882 lsmash_ifprintf( fp, indent, "bufferSizeDB = %"PRIu32"\n", dcd->bufferSizeDB );
883 lsmash_ifprintf( fp, indent, "maxBitrate = %"PRIu32"\n", dcd->maxBitrate );
884 lsmash_ifprintf( fp, indent, "avgBitrate = %"PRIu32"%s\n", dcd->avgBitrate, dcd->avgBitrate ? "" : " (variable bitrate)" );
887 static void mp4sys_print_SLConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
889 mp4sys_SLConfigDescriptor_t *slcd = (mp4sys_SLConfigDescriptor_t *)descriptor;
890 lsmash_ifprintf( fp, indent, "predefined = %"PRIu8"\n", slcd->predefined );
891 if( slcd->predefined == 0 )
893 lsmash_ifprintf( fp, indent, "useAccessUnitStartFlag = %"PRIu8"\n", slcd->useAccessUnitStartFlag );
894 lsmash_ifprintf( fp, indent, "useAccessUnitEndFlag = %"PRIu8"\n", slcd->useAccessUnitEndFlag );
895 lsmash_ifprintf( fp, indent, "useRandomAccessPointFlag = %"PRIu8"\n", slcd->useRandomAccessPointFlag );
896 lsmash_ifprintf( fp, indent, "hasRandomAccessUnitsOnlyFlag = %"PRIu8"\n", slcd->hasRandomAccessUnitsOnlyFlag );
897 lsmash_ifprintf( fp, indent, "usePaddingFlag = %"PRIu8"\n", slcd->usePaddingFlag );
898 lsmash_ifprintf( fp, indent, "useTimeStampsFlag = %"PRIu8"\n", slcd->useTimeStampsFlag );
899 lsmash_ifprintf( fp, indent, "useIdleFlag = %"PRIu8"\n", slcd->useIdleFlag );
900 lsmash_ifprintf( fp, indent, "durationFlag = %"PRIu8"\n", slcd->durationFlag );
901 lsmash_ifprintf( fp, indent, "timeStampResolution = %"PRIu32"\n", slcd->timeStampResolution );
902 lsmash_ifprintf( fp, indent, "OCRResolution = %"PRIu32"\n", slcd->OCRResolution );
903 lsmash_ifprintf( fp, indent, "timeStampLength = %"PRIu8"\n", slcd->timeStampLength );
904 lsmash_ifprintf( fp, indent, "OCRLength = %"PRIu8"\n", slcd->OCRLength );
905 lsmash_ifprintf( fp, indent, "AU_Length = %"PRIu8"\n", slcd->AU_Length );
906 lsmash_ifprintf( fp, indent, "instantBitrateLength = %"PRIu8"\n", slcd->instantBitrateLength );
907 lsmash_ifprintf( fp, indent, "degradationPriorityLength = %"PRIu8"\n", slcd->degradationPriorityLength );
908 lsmash_ifprintf( fp, indent, "AU_seqNumLength = %"PRIu8"\n", slcd->AU_seqNumLength );
909 lsmash_ifprintf( fp, indent, "packetSeqNumLength = %"PRIu8"\n", slcd->packetSeqNumLength );
910 lsmash_ifprintf( fp, indent, "reserved = 0x%01"PRIx8"\n", slcd->reserved );
912 if( slcd->durationFlag )
914 lsmash_ifprintf( fp, indent, "timeScale = %"PRIu32"\n", slcd->timeScale );
915 lsmash_ifprintf( fp, indent, "accessUnitDuration = %"PRIu16"\n", slcd->accessUnitDuration );
916 lsmash_ifprintf( fp, indent, "compositionUnitDuration = %"PRIu16"\n", slcd->compositionUnitDuration );
918 if( !slcd->useTimeStampsFlag )
920 lsmash_ifprintf( fp, indent, "startDecodingTimeStamp = %"PRIu64"\n", slcd->startDecodingTimeStamp );
921 lsmash_ifprintf( fp, indent, "startCompositionTimeStamp = %"PRIu64"\n", slcd->startCompositionTimeStamp );
925 static void mp4sys_print_ES_Descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
927 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)descriptor;
928 lsmash_ifprintf( fp, indent, "ES_ID = %"PRIu16"\n", esd->ES_ID );
929 lsmash_ifprintf( fp, indent, "streamDependenceFlag = %"PRIu8"\n", esd->streamDependenceFlag );
930 lsmash_ifprintf( fp, indent, "URL_Flag = %"PRIu8"\n", esd->URL_Flag );
931 lsmash_ifprintf( fp, indent, "OCRstreamFlag = %"PRIu8"\n", esd->OCRstreamFlag );
932 lsmash_ifprintf( fp, indent, "streamPriority = %"PRIu8"\n", esd->streamPriority );
933 if( esd->streamDependenceFlag )
934 lsmash_ifprintf( fp, indent, "dependsOn_ES_ID = %"PRIu16"\n", esd->dependsOn_ES_ID );
935 if( esd->URL_Flag )
937 lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", esd->URLlength );
938 lsmash_ifprintf( fp, indent, "URLstring = %s\n", esd->URLstring );
940 if( esd->OCRstreamFlag )
941 lsmash_ifprintf( fp, indent, "OCR_ES_Id = %"PRIu16"\n", esd->OCR_ES_Id );
944 static void mp4sys_print_ES_ID_Inc( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
946 mp4sys_ES_ID_Inc_t *es_id_inc = (mp4sys_ES_ID_Inc_t *)descriptor;
947 lsmash_ifprintf( fp, indent, "Track_ID = %"PRIu32"\n", es_id_inc->Track_ID );
950 static void mp4sys_print_ObjectDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
952 mp4sys_ObjectDescriptor_t *od = (mp4sys_ObjectDescriptor_t *)descriptor;
953 lsmash_ifprintf( fp, indent, "ObjectDescriptorID = %"PRIu16"\n", od->ObjectDescriptorID );
954 lsmash_ifprintf( fp, indent, "URL_Flag = %"PRIu8"\n", od->URL_Flag );
955 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
956 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
958 lsmash_ifprintf( fp, indent, "includeInlineProfileLevelFlag = %"PRIu8"\n", od->includeInlineProfileLevelFlag );
959 lsmash_ifprintf( fp, indent, "reserved = 0x%01"PRIx8"\n", od->reserved );
961 else
962 lsmash_ifprintf( fp, indent, "reserved = 0x%02"PRIx8"\n", od->reserved | (od->includeInlineProfileLevelFlag << 4) );
963 if( od->URL_Flag )
965 lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", od->URLlength );
966 lsmash_ifprintf( fp, indent, "URLstring = %s\n", od->URLstring );
968 else
970 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
971 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
973 lsmash_ifprintf( fp, indent, "ODProfileLevelIndication = 0x%02"PRIx8"\n", od->ODProfileLevelIndication );
974 lsmash_ifprintf( fp, indent, "sceneProfileLevelIndication = 0x%02"PRIx8"\n", od->sceneProfileLevelIndication );
975 lsmash_ifprintf( fp, indent, "audioProfileLevelIndication = 0x%02"PRIx8"\n", od->audioProfileLevelIndication );
976 lsmash_ifprintf( fp, indent, "visualProfileLevelIndication = 0x%02"PRIx8"\n", od->visualProfileLevelIndication );
977 lsmash_ifprintf( fp, indent, "graphicsProfileLevelIndication = 0x%02"PRIx8"\n", od->graphicsProfileLevelIndication );
982 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
984 if( !descriptor )
985 return;
986 mp4sys_print_descriptor_header( fp, &descriptor->header, indent++ );
987 switch( descriptor->header.tag )
989 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
990 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
991 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
992 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
993 mp4sys_print_ObjectDescriptor( fp, descriptor, indent );
994 break;
995 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
996 mp4sys_print_ES_Descriptor( fp, descriptor, indent );
997 break;
998 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
999 mp4sys_print_DecoderConfigDescriptor( fp, descriptor, indent );
1000 break;
1001 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1002 mp4sys_print_DecoderSpecificInfo( fp, descriptor, indent );
1003 break;
1004 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1005 mp4sys_print_SLConfigDescriptor( fp, descriptor, indent );
1006 break;
1007 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1008 mp4sys_print_ES_ID_Inc( fp, descriptor, indent );
1009 break;
1010 default :
1011 break;
1013 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
1014 if( entry->data )
1015 mp4sys_print_descriptor( fp, entry->data, indent );
1018 int mp4sys_print_codec_specific( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1020 assert( fp && file && box && !(box->manager & LSMASH_BINARY_CODED_BOX) );
1021 isom_esds_t *esds = (isom_esds_t *)box;
1022 int indent = level;
1023 lsmash_ifprintf( fp, indent++, "[%s: Elemental Stream Descriptor Box]\n", isom_4cc2str( esds->type.fourcc ) );
1024 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", esds->pos );
1025 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", esds->size );
1026 lsmash_ifprintf( fp, indent, "version = %"PRIu8"\n", esds->version );
1027 lsmash_ifprintf( fp, indent, "flags = 0x%06"PRIx32"\n", esds->flags & 0x00ffffff );
1028 mp4sys_print_descriptor( fp, (mp4sys_descriptor_t *)esds->ES, indent );
1029 return 0;
1031 #endif /* LSMASH_DEMUXER_ENABLED */
1033 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent );
1035 static void mp4sys_get_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
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 )
1043 temp = lsmash_bs_get_byte( bs );
1044 nextByte = temp & 0x80;
1045 sizeOfInstance = (sizeOfInstance << 7) | (temp & 0x7F);
1047 header->size = sizeOfInstance;
1050 static mp4sys_DecoderSpecificInfo_t *mp4sys_get_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
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 )
1058 dsi->data = lsmash_bs_get_bytes( bs, dsi->header.size );
1059 if( !dsi->data )
1061 mp4sys_remove_descriptor( dsi );
1062 return NULL;
1065 return dsi;
1068 static mp4sys_DecoderConfigDescriptor_t *mp4sys_get_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
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 )
1085 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, dcd );
1086 if( desc )
1088 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag )
1089 dcd->decSpecificInfo = (mp4sys_DecoderSpecificInfo_t *)desc;
1090 else
1091 mp4sys_remove_descriptor( desc );
1093 else
1094 break;
1096 return dcd;
1099 static mp4sys_SLConfigDescriptor_t *mp4sys_get_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
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 )
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;
1129 else if( slcd->predefined == 0x01 )
1131 slcd->timeStampResolution = 1000;
1132 slcd->timeStampLength = 32;
1134 else if( slcd->predefined == 0x02 )
1135 slcd->useTimeStampsFlag = 1;
1136 if( slcd->durationFlag )
1138 slcd->timeScale = lsmash_bs_get_be32( bs );
1139 slcd->accessUnitDuration = lsmash_bs_get_be16( bs );
1140 slcd->compositionUnitDuration = lsmash_bs_get_be16( bs );
1142 if( !slcd->useTimeStampsFlag )
1144 lsmash_bits_t *bits = lsmash_bits_create( bs );
1145 if( !bits )
1147 mp4sys_remove_descriptor( slcd );
1148 return NULL;
1150 slcd->startDecodingTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1151 slcd->startCompositionTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1152 lsmash_bits_cleanup( bits );
1154 return slcd;
1157 static mp4sys_ES_Descriptor_t *mp4sys_get_ES_Descriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1159 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, parent, NULL );
1160 if( parent && lsmash_add_entry( &((mp4sys_descriptor_t *)parent)->children, esd ) < 0 )
1162 mp4sys_remove_descriptor( esd );
1163 return NULL;
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 )
1177 size_t length = lsmash_bs_get_byte( bs );
1178 lsmash_bs_read_data( bs, (uint8_t *)esd->URLstring, &length );
1179 esd->URLlength = length;
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 )
1186 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, esd );
1187 if( desc )
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 );
1196 else
1197 break;
1199 if( !esd->decConfigDescr || !esd->slConfigDescr )
1201 mp4sys_remove_descriptor( esd );
1202 return NULL;
1204 return esd;
1207 static mp4sys_ES_ID_Inc_t *mp4sys_get_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
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;
1217 static mp4sys_ObjectDescriptor_t *mp4sys_get_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1219 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, parent, NULL );
1220 if( parent && lsmash_add_entry( &((mp4sys_descriptor_t *)parent)->children, od ) < 0 )
1222 mp4sys_remove_descriptor( od );
1223 return NULL;
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 )
1234 size_t length = lsmash_bs_get_byte( bs );
1235 lsmash_bs_read_data( bs, (uint8_t *)od->URLstring, &length );
1236 od->URLlength = length;
1238 else
1240 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
1241 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
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 );
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 )
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 )
1261 mp4sys_remove_descriptor( desc );
1262 break;
1266 return od;
1269 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent )
1271 mp4sys_descriptor_head_t header;
1272 mp4sys_get_descriptor_header( bs, &header );
1273 mp4sys_descriptor_t *desc;
1274 switch( header.tag )
1276 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
1277 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
1278 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
1279 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
1280 desc = (mp4sys_descriptor_t *)mp4sys_get_ObjectDescriptor( bs, &header, parent );
1281 break;
1282 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
1283 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_Descriptor( bs, &header, parent );
1284 break;
1285 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
1286 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderConfigDescriptor( bs, &header, parent );
1287 break;
1288 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1289 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderSpecificInfo( bs, &header, parent );
1290 break;
1291 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1292 desc = (mp4sys_descriptor_t *)mp4sys_get_SLConfigDescriptor( bs, &header, parent );
1293 break;
1294 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1295 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_ID_Inc( bs, &header, parent );
1296 break;
1297 default :
1298 desc = lsmash_malloc_zero( sizeof(mp4sys_descriptor_t) );
1299 if( desc )
1301 desc->parent = parent;
1302 desc->header = header;
1304 break;
1306 return desc;
1309 static uint8_t *mp4sys_export_DecoderSpecificInfo( mp4sys_ES_Descriptor_t *esd, uint32_t *dsi_payload_length )
1311 if( !esd || !esd->decConfigDescr || !esd->decConfigDescr->decSpecificInfo )
1312 return NULL;
1313 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)esd->decConfigDescr->decSpecificInfo;
1314 uint8_t *dsi_payload = NULL;
1315 /* DecoderSpecificInfo can be absent. */
1316 if( dsi->header.size )
1318 dsi_payload = lsmash_memdup( dsi->data, dsi->header.size );
1319 if( !dsi_payload )
1320 return NULL;
1322 if( dsi_payload_length )
1323 *dsi_payload_length = dsi->header.size;
1324 return dsi_payload;
1327 /* Sumamry is needed to decide ProfileLevelIndication.
1328 * Currently, support audio's only. */
1329 int mp4sys_setup_summary_from_DecoderSpecificInfo( lsmash_audio_summary_t *summary, mp4sys_ES_Descriptor_t *esd )
1331 uint32_t dsi_payload_length = UINT32_MAX; /* arbitrary */
1332 uint8_t *dsi_payload = mp4sys_export_DecoderSpecificInfo( esd, &dsi_payload_length );
1333 if( !dsi_payload && dsi_payload_length )
1334 return -1;
1335 if( dsi_payload_length )
1337 lsmash_codec_specific_t *cs = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG,
1338 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1339 if( !cs )
1340 goto fail;
1341 lsmash_mp4sys_decoder_parameters_t *params = (lsmash_mp4sys_decoder_parameters_t *)cs->data.structured;
1342 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1343 params->objectTypeIndication = dcd->objectTypeIndication;
1344 params->streamType = dcd->streamType;
1345 params->bufferSizeDB = dcd->bufferSizeDB;
1346 params->maxBitrate = dcd->maxBitrate;
1347 params->avgBitrate = dcd->avgBitrate;
1348 if( mp4a_setup_summary_from_AudioSpecificConfig( summary, dsi_payload, dsi_payload_length ) < 0
1349 || lsmash_set_mp4sys_decoder_specific_info( params, dsi_payload, dsi_payload_length ) < 0
1350 || lsmash_add_entry( &summary->opaque->list, cs ) < 0 )
1352 lsmash_destroy_codec_specific_data( cs );
1353 goto fail;
1356 lsmash_free( dsi_payload );
1357 return 0;
1358 fail:
1359 lsmash_free( dsi_payload );
1360 return -1;
1363 /**** following functions are for facilitation purpose ****/
1365 mp4sys_ES_Descriptor_t *mp4sys_setup_ES_Descriptor( mp4sys_ES_Descriptor_params_t *params )
1367 if( !params )
1368 return NULL;
1369 mp4sys_ES_Descriptor_t *esd = mp4sys_create_ES_Descriptor( params->ES_ID );
1370 if( !esd )
1371 return NULL;
1372 /* DecoderConfigDescriptor */
1373 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( esd );
1374 if( !dcd )
1375 goto fail;
1376 dcd->objectTypeIndication = params->objectTypeIndication;
1377 dcd->streamType = params->streamType;
1378 dcd->upStream = 0;
1379 dcd->reserved = 1;
1380 dcd->bufferSizeDB = params->bufferSizeDB;
1381 dcd->maxBitrate = params->maxBitrate;
1382 dcd->avgBitrate = params->avgBitrate;
1383 /* DecoderSpecificInfo */
1384 if( params->dsi_payload && params->dsi_payload_length != 0 )
1386 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( dcd );
1387 if( !dsi )
1388 goto fail;
1389 dsi->data = lsmash_memdup( params->dsi_payload, params->dsi_payload_length );
1390 if( !dsi->data )
1391 goto fail;
1392 dsi->header.size = params->dsi_payload_length;
1394 /* SLConfigDescriptor */
1396 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( esd );
1397 if( !slcd )
1398 goto fail;
1399 slcd->predefined = 0x02; /* MP4 file which does not use URL_Flag shall have constant value 0x02 */
1400 slcd->useTimeStampsFlag = 1; /* set to 1 if predefined == 2 */
1402 return esd;
1403 fail:
1404 mp4sys_remove_descriptor( esd );
1405 return NULL;
1408 int lsmash_set_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t *payload, uint32_t payload_length )
1410 if( !param || !payload || payload_length == 0 )
1411 return -1;
1412 if( !param->dsi )
1414 param->dsi = lsmash_malloc_zero( sizeof(lsmash_mp4sys_decoder_specific_info_t) );
1415 if( !param->dsi )
1416 return -1;
1418 else
1420 if( param->dsi->payload )
1421 lsmash_freep( &param->dsi->payload );
1422 param->dsi->payload_length = 0;
1424 param->dsi->payload = lsmash_memdup( payload, payload_length );
1425 if( !param->dsi->payload )
1426 return -1;
1427 param->dsi->payload_length = payload_length;
1428 return 0;
1431 void lsmash_destroy_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param )
1433 if( !param || !param->dsi )
1434 return;
1435 lsmash_free( param->dsi->payload );
1436 lsmash_freep( &param->dsi );
1439 void mp4sys_destruct_decoder_config( void *data )
1441 if( !data )
1442 return;
1443 lsmash_destroy_mp4sys_decoder_specific_info( data );
1444 lsmash_free( data );
1447 uint8_t *lsmash_create_mp4sys_decoder_config( lsmash_mp4sys_decoder_parameters_t *param, uint32_t *data_length )
1449 if( !param || !data_length )
1450 return NULL;
1451 mp4sys_ES_Descriptor_params_t esd_param = { 0 };
1452 esd_param.ES_ID = 0; /* Within sample description, ES_ID is stored as 0. */
1453 esd_param.objectTypeIndication = param->objectTypeIndication;
1454 esd_param.streamType = param->streamType;
1455 esd_param.bufferSizeDB = param->bufferSizeDB;
1456 esd_param.maxBitrate = param->maxBitrate;
1457 esd_param.avgBitrate = param->avgBitrate;
1458 if( param->dsi
1459 && param->dsi->payload
1460 && param->dsi->payload_length )
1462 esd_param.dsi_payload = param->dsi->payload;
1463 esd_param.dsi_payload_length = param->dsi->payload_length;
1465 mp4sys_ES_Descriptor_t *esd = mp4sys_setup_ES_Descriptor( &esd_param );
1466 if( !esd )
1467 return NULL;
1468 lsmash_bs_t *bs = lsmash_bs_create();
1469 if( !bs )
1471 mp4sys_remove_descriptor( esd );
1472 return NULL;
1474 lsmash_bs_put_be32( bs, 0 ); /* update later */
1475 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_ESDS.fourcc );
1476 lsmash_bs_put_be32( bs, 0 );
1477 mp4sys_update_descriptor_size( esd );
1478 mp4sys_write_descriptor( bs, esd );
1479 mp4sys_remove_descriptor( esd );
1480 uint8_t *data = lsmash_bs_export_data( bs, data_length );
1481 lsmash_bs_cleanup( bs );
1482 if( !data )
1483 return NULL;
1484 /* Update box size. */
1485 LSMASH_SET_BE32( data, *data_length );
1486 return data;
1489 int mp4sys_construct_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1491 assert( dst && dst->data.structured && src && src->data.unstructured );
1492 if( src->size < ISOM_FULLBOX_COMMON_SIZE + 23 )
1493 return -1;
1494 lsmash_mp4sys_decoder_parameters_t *param = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1495 uint8_t *data = src->data.unstructured;
1496 uint64_t size = LSMASH_GET_BE32( data );
1497 data += ISOM_BASEBOX_COMMON_SIZE;
1498 if( size == 1 )
1500 size = LSMASH_GET_BE64( data );
1501 data += 8;
1503 if( size != src->size )
1504 return -1;
1505 data += 4; /* Skip version and flags. */
1506 lsmash_bs_t *bs = lsmash_bs_create();
1507 if( !bs )
1508 return -1;
1509 if( lsmash_bs_import_data( bs, data, src->size - (data - src->data.unstructured) ) )
1511 lsmash_bs_cleanup( bs );
1512 return -1;
1514 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)mp4sys_get_descriptor( bs, NULL );
1515 lsmash_bs_cleanup( bs );
1516 if( !esd || esd->header.tag != MP4SYS_DESCRIPTOR_TAG_ES_DescrTag || !esd->decConfigDescr )
1517 return -1;
1518 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1519 param->objectTypeIndication = dcd->objectTypeIndication;
1520 param->streamType = dcd->streamType;
1521 param->bufferSizeDB = dcd->bufferSizeDB;
1522 param->maxBitrate = dcd->maxBitrate;
1523 param->avgBitrate = dcd->avgBitrate;
1524 mp4sys_DecoderSpecificInfo_t *dsi = dcd->decSpecificInfo;
1525 if( dsi
1526 && dsi->header.size
1527 && dsi->data
1528 && lsmash_set_mp4sys_decoder_specific_info( param, dsi->data, dsi->header.size ) )
1530 mp4sys_remove_descriptor( esd );
1531 return -1;
1533 mp4sys_remove_descriptor( esd );
1534 return 0;
1537 int mp4sys_copy_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1539 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
1540 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
1541 lsmash_mp4sys_decoder_parameters_t *src_data = (lsmash_mp4sys_decoder_parameters_t *)src->data.structured;
1542 lsmash_mp4sys_decoder_parameters_t *dst_data = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1543 lsmash_destroy_mp4sys_decoder_specific_info( dst_data );
1544 *dst_data = *src_data;
1545 dst_data->dsi = NULL;
1546 if( !src_data->dsi || !src_data->dsi->payload || src_data->dsi->payload_length == 0 )
1547 return 0;
1548 return lsmash_set_mp4sys_decoder_specific_info( dst_data, src_data->dsi->payload, src_data->dsi->payload_length );
1551 lsmash_mp4sys_object_type_indication lsmash_mp4sys_get_object_type_indication( lsmash_summary_t *summary )
1553 if( !summary )
1554 return MP4SYS_OBJECT_TYPE_Forbidden;
1555 lsmash_codec_specific_t *orig = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1556 if( !orig )
1557 return MP4SYS_OBJECT_TYPE_Forbidden;
1558 /* Found decoder configuration.
1559 * Let's get objectTypeIndication. */
1560 lsmash_mp4sys_object_type_indication objectTypeIndication;
1561 if( orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1562 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)orig->data.structured)->objectTypeIndication;
1563 else
1565 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( orig, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1566 if( !conv )
1567 return MP4SYS_OBJECT_TYPE_Forbidden;
1568 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)conv->data.structured)->objectTypeIndication;
1569 lsmash_destroy_codec_specific_data( conv );
1571 return objectTypeIndication;
1574 int lsmash_get_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t **payload, uint32_t *payload_length )
1576 if( !param || !payload || !payload_length )
1577 return -1;
1578 if( !param->dsi || !param->dsi->payload || param->dsi->payload_length == 0 )
1580 *payload = NULL;
1581 *payload_length = 0;
1582 return 0;
1584 uint8_t *temp = lsmash_memdup( param->dsi->payload, param->dsi->payload_length );
1585 if( !temp )
1586 return -1;
1587 *payload = temp;
1588 *payload_length = param->dsi->payload_length;
1589 return 0;