codecs: Add support of 'UQY2'.
[L-SMASH.git] / codecs / mp4sys.c
blobbedfa6e10073df79f7408dd954cc42eba6d1f6d7
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->head; 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 & 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;
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 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 );
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 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 );
539 /* descriptor size updater */
540 uint32_t mp4sys_update_descriptor_size( void *opaque_descriptor )
542 assert( opaque_descriptor );
543 mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
544 uint64_t size = 0;
545 if( descriptor->write )
547 uint32_t header_size = descriptor->header.size;
548 /* Calculate the size of this descriptor excluding its children with a fake bytestream writer. */
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 );
555 /* Calculate the size including the children if no error. */
556 if( size >= mp4sys_get_descriptor_header_size( header_size ) )
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 );
567 else
569 /* Invalid descriptor */
570 descriptor->header.size = 0;
571 size = 0;
574 else
575 descriptor->header.size = 0;
576 return size;
579 static inline void *mp4sys_construct_descriptor_orig
581 size_t size,
582 mp4sys_descriptor_t *parent,
583 mp4sys_descriptor_destructor_t destructor,
584 mp4sys_descriptor_writer_t writer
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 return descriptor;
598 #define mp4sys_construct_descriptor( size, parent, destructor, writer ) \
599 mp4sys_construct_descriptor_orig \
601 size, \
602 (mp4sys_descriptor_t *)parent, \
603 (mp4sys_descriptor_destructor_t)destructor, \
604 (mp4sys_descriptor_writer_t)writer \
607 #define MP4SYS_CONSTRUCT_DESCRIPTOR( var, descriptor_name, parent, ret ) \
608 mp4sys_##descriptor_name##_t *var = \
609 mp4sys_construct_descriptor \
611 sizeof(mp4sys_##descriptor_name##_t), \
612 parent, \
613 mp4sys_remove_##descriptor_name, \
614 mp4sys_write_##descriptor_name \
615 ); \
616 if( !var ) \
617 return ret
619 static mp4sys_DecoderSpecificInfo_t *mp4sys_add_DecoderSpecificInfo( mp4sys_DecoderConfigDescriptor_t *dcd )
621 if( !dcd )
622 return NULL;
623 MP4SYS_CONSTRUCT_DESCRIPTOR( dsi, DecoderSpecificInfo, dcd, NULL );
624 dsi->header.tag = MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag;
625 if( lsmash_add_entry( &dcd->children, dsi ) < 0 )
627 mp4sys_remove_descriptor( dsi );
628 return NULL;
630 dcd->decSpecificInfo = dsi;
631 return dsi;
635 bufferSizeDB is byte unit, NOT bit unit.
636 avgBitrate is 0 if VBR
638 static mp4sys_DecoderConfigDescriptor_t *mp4sys_add_DecoderConfigDescriptor
640 mp4sys_ES_Descriptor_t *esd
643 if( !esd )
644 return NULL;
645 MP4SYS_CONSTRUCT_DESCRIPTOR( dcd, DecoderConfigDescriptor, esd, NULL );
646 dcd->header.tag = MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag;
647 if( lsmash_add_entry( &esd->children, dcd ) < 0 )
649 mp4sys_remove_descriptor( dcd );
650 return NULL;
652 esd->decConfigDescr = dcd;
653 return dcd;
656 static mp4sys_SLConfigDescriptor_t *mp4sys_add_SLConfigDescriptor( mp4sys_ES_Descriptor_t *esd )
658 if( !esd )
659 return NULL;
660 MP4SYS_CONSTRUCT_DESCRIPTOR( slcd, SLConfigDescriptor, esd, NULL );
661 slcd->header.tag = MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag;
662 if( lsmash_add_entry( &esd->children, slcd ) < 0 )
664 mp4sys_remove_descriptor( slcd );
665 return NULL;
667 esd->slConfigDescr = slcd;
668 return slcd;
671 /* NOTE: This is only for MP4_IOD and MP4_OD, not for ISO Base Media's ObjectDescriptor and InitialObjectDescriptor */
672 static mp4sys_ES_ID_Inc_t *mp4sys_add_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od )
674 if( !od
675 || (od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
676 && od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag) )
677 return NULL;
678 MP4SYS_CONSTRUCT_DESCRIPTOR( es_id_inc, ES_ID_Inc, od, NULL );
679 es_id_inc->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag;
680 if( lsmash_add_entry( &od->children, es_id_inc ) < 0 )
682 mp4sys_remove_descriptor( es_id_inc );
683 return NULL;
685 if( lsmash_add_entry( &od->esDescr, es_id_inc ) < 0 )
687 lsmash_remove_entry_tail( &od->children, mp4sys_remove_ES_ID_Inc );
688 return NULL;
690 return es_id_inc;
693 int mp4sys_create_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od, uint32_t Track_ID )
695 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( od );
696 if( !es_id_inc )
697 return LSMASH_ERR_NAMELESS;
698 es_id_inc->Track_ID = Track_ID;
699 return 0;
702 /* ES_ID of the ES Descriptor is stored as 0 when the ES Descriptor is built into sample descriptions in MP4 file format
703 * 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. */
704 mp4sys_ES_Descriptor_t *mp4sys_create_ES_Descriptor( uint16_t ES_ID )
706 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, NULL, NULL );
707 esd->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
708 esd->ES_ID = ES_ID;
709 return esd;
712 /* NOTE: This is only for MP4_OD, not for ISO Base Media's ObjectDescriptor */
713 mp4sys_ObjectDescriptor_t *mp4sys_create_ObjectDescriptor( uint16_t ObjectDescriptorID )
715 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, NULL, NULL );
716 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag;
717 od->ObjectDescriptorID = ObjectDescriptorID;
718 od->includeInlineProfileLevelFlag = 1; /* 1 as part of reserved flag. */
719 od->ODProfileLevelIndication = MP4SYS_OD_PLI_NONE_REQUIRED;
720 od->sceneProfileLevelIndication = MP4SYS_SCENE_PLI_NONE_REQUIRED;
721 od->audioProfileLevelIndication = MP4A_AUDIO_PLI_NONE_REQUIRED;
722 od->visualProfileLevelIndication = MP4SYS_VISUAL_PLI_NONE_REQUIRED;
723 od->graphicsProfileLevelIndication = MP4SYS_GRAPHICS_PLI_NONE_REQUIRED;
724 return od;
727 /* NOTE: This is only for MP4_IOD, not for Iso Base Media's InitialObjectDescriptor */
728 int mp4sys_to_InitialObjectDescriptor
730 mp4sys_ObjectDescriptor_t *od,
731 uint8_t include_inline_pli,
732 mp4sys_ODProfileLevelIndication od_pli,
733 mp4sys_sceneProfileLevelIndication scene_pli,
734 mp4a_audioProfileLevelIndication audio_pli,
735 mp4sys_visualProfileLevelIndication visual_pli,
736 mp4sys_graphicsProfileLevelIndication graph_pli
739 if( !od )
740 return LSMASH_ERR_NAMELESS;
741 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag;
742 od->includeInlineProfileLevelFlag = include_inline_pli;
743 od->ODProfileLevelIndication = od_pli;
744 od->sceneProfileLevelIndication = scene_pli;
745 od->audioProfileLevelIndication = audio_pli;
746 od->visualProfileLevelIndication = visual_pli;
747 od->graphicsProfileLevelIndication = graph_pli;
748 return 0;
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 LSMASH_ERR_NAMELESS;
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;
1032 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent );
1034 static void mp4sys_get_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
1036 header->tag = lsmash_bs_get_byte( bs );
1037 uint8_t temp = lsmash_bs_get_byte( bs );
1038 int nextByte = temp & 0x80;
1039 uint32_t sizeOfInstance = temp & 0x7F;
1040 while( nextByte )
1042 temp = lsmash_bs_get_byte( bs );
1043 nextByte = temp & 0x80;
1044 sizeOfInstance = (sizeOfInstance << 7) | (temp & 0x7F);
1046 header->size = sizeOfInstance;
1049 static mp4sys_DecoderSpecificInfo_t *mp4sys_get_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1051 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( parent );
1052 if( !dsi )
1053 return NULL;
1054 dsi->header.size = header->size;
1055 if( dsi->header.size )
1057 dsi->data = lsmash_bs_get_bytes( bs, dsi->header.size );
1058 if( !dsi->data )
1060 mp4sys_remove_descriptor( dsi );
1061 return NULL;
1064 return dsi;
1067 static mp4sys_DecoderConfigDescriptor_t *mp4sys_get_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1069 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( parent );
1070 if( !dcd )
1071 return NULL;
1072 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1073 dcd->header.size = header->size;
1074 dcd->objectTypeIndication = lsmash_bs_get_byte( bs );
1075 uint8_t temp = lsmash_bs_get_byte( bs );
1076 dcd->streamType = (temp >> 2) & 0x3F;
1077 dcd->upStream = (temp >> 1) & 0x01;
1078 dcd->reserved = temp & 0x01;
1079 dcd->bufferSizeDB = lsmash_bs_get_be24( bs );
1080 dcd->maxBitrate = lsmash_bs_get_be32( bs );
1081 dcd->avgBitrate = lsmash_bs_get_be32( bs );
1082 while( lsmash_bs_count( bs ) < end_pos )
1084 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, dcd );
1085 if( desc )
1087 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag )
1088 dcd->decSpecificInfo = (mp4sys_DecoderSpecificInfo_t *)desc;
1089 else
1090 mp4sys_remove_descriptor( desc );
1092 else
1093 break;
1095 return dcd;
1098 static mp4sys_SLConfigDescriptor_t *mp4sys_get_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1100 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( parent );
1101 if( !slcd )
1102 return NULL;
1103 slcd->header.size = header->size;
1104 slcd->predefined = lsmash_bs_get_byte( bs );
1105 if( slcd->predefined == 0x00 )
1107 uint8_t temp8 = lsmash_bs_get_byte( bs );
1108 slcd->useAccessUnitStartFlag = (temp8 >> 7) & 0x01;
1109 slcd->useAccessUnitEndFlag = (temp8 >> 6) & 0x01;
1110 slcd->useRandomAccessPointFlag = (temp8 >> 5) & 0x01;
1111 slcd->hasRandomAccessUnitsOnlyFlag = (temp8 >> 4) & 0x01;
1112 slcd->usePaddingFlag = (temp8 >> 3) & 0x01;
1113 slcd->useTimeStampsFlag = (temp8 >> 2) & 0x01;
1114 slcd->useIdleFlag = (temp8 >> 1) & 0x01;
1115 slcd->durationFlag = temp8 & 0x01;
1116 slcd->timeStampResolution = lsmash_bs_get_be32( bs );
1117 slcd->OCRResolution = lsmash_bs_get_be32( bs );
1118 slcd->timeStampLength = lsmash_bs_get_byte( bs );
1119 slcd->OCRLength = lsmash_bs_get_byte( bs );
1120 slcd->AU_Length = lsmash_bs_get_byte( bs );
1121 slcd->instantBitrateLength = lsmash_bs_get_byte( bs );
1122 uint16_t temp16 = lsmash_bs_get_be16( bs );
1123 slcd->degradationPriorityLength = (temp16 >> 12) & 0x0F;
1124 slcd->AU_seqNumLength = (temp16 >> 7) & 0x1F;
1125 slcd->packetSeqNumLength = (temp16 >> 2) & 0x1F;
1126 slcd->reserved = temp16 & 0x03;
1128 else if( slcd->predefined == 0x01 )
1130 slcd->timeStampResolution = 1000;
1131 slcd->timeStampLength = 32;
1133 else if( slcd->predefined == 0x02 )
1134 slcd->useTimeStampsFlag = 1;
1135 if( slcd->durationFlag )
1137 slcd->timeScale = lsmash_bs_get_be32( bs );
1138 slcd->accessUnitDuration = lsmash_bs_get_be16( bs );
1139 slcd->compositionUnitDuration = lsmash_bs_get_be16( bs );
1141 if( !slcd->useTimeStampsFlag )
1143 lsmash_bits_t *bits = lsmash_bits_create( bs );
1144 if( !bits )
1146 mp4sys_remove_descriptor( slcd );
1147 return NULL;
1149 slcd->startDecodingTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1150 slcd->startCompositionTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1151 lsmash_bits_cleanup( bits );
1153 return slcd;
1156 static mp4sys_ES_Descriptor_t *mp4sys_get_ES_Descriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1158 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, parent, NULL );
1159 if( parent && lsmash_add_entry( &((mp4sys_descriptor_t *)parent)->children, esd ) < 0 )
1161 mp4sys_remove_descriptor( esd );
1162 return NULL;
1164 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1165 esd->header = *header;
1166 esd->ES_ID = lsmash_bs_get_be16( bs );
1167 uint8_t temp = lsmash_bs_get_byte( bs );
1168 esd->streamDependenceFlag = (temp >> 7) & 0x01;
1169 esd->URL_Flag = (temp >> 6) & 0x01;
1170 esd->OCRstreamFlag = (temp >> 5) & 0x01;
1171 esd->streamPriority = temp & 0x1F;
1172 if( esd->streamDependenceFlag )
1173 esd->dependsOn_ES_ID = lsmash_bs_get_be16( bs );
1174 if( esd->URL_Flag )
1176 size_t length = lsmash_bs_get_byte( bs );
1177 lsmash_bs_read_data( bs, (uint8_t *)esd->URLstring, &length );
1178 esd->URLlength = length;
1180 if( esd->OCRstreamFlag )
1181 esd->OCR_ES_Id = lsmash_bs_get_be16( bs );
1182 /* DecoderConfigDescriptor and SLConfigDescriptor are mandatory. */
1183 while( lsmash_bs_count( bs ) < end_pos )
1185 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, esd );
1186 if( desc )
1188 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag )
1189 esd->decConfigDescr = (mp4sys_DecoderConfigDescriptor_t *)desc;
1190 else if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag )
1191 esd->slConfigDescr = (mp4sys_SLConfigDescriptor_t *)desc;
1192 else
1193 mp4sys_remove_descriptor( desc );
1195 else
1196 break;
1198 if( !esd->decConfigDescr || !esd->slConfigDescr )
1200 mp4sys_remove_descriptor( esd );
1201 return NULL;
1203 return esd;
1206 static mp4sys_ES_ID_Inc_t *mp4sys_get_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1208 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( parent );
1209 if( !es_id_inc )
1210 return NULL;
1211 es_id_inc->header.size = header->size;
1212 es_id_inc->Track_ID = lsmash_bs_get_be32( bs );
1213 return es_id_inc;
1216 static mp4sys_ObjectDescriptor_t *mp4sys_get_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1218 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, parent, NULL );
1219 if( parent && lsmash_add_entry( &((mp4sys_descriptor_t *)parent)->children, od ) < 0 )
1221 mp4sys_remove_descriptor( od );
1222 return NULL;
1224 od->header = *header;
1225 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1226 uint16_t temp16 = lsmash_bs_get_be16( bs );
1227 od->ObjectDescriptorID = (temp16 >> 6) & 0x03FF;
1228 od->URL_Flag = (temp16 >> 5) & 0x0001;
1229 od->includeInlineProfileLevelFlag = (temp16 >> 4) & 0x0001;
1230 od->reserved = temp16 & 0x000F;
1231 if( od->URL_Flag )
1233 size_t length = lsmash_bs_get_byte( bs );
1234 lsmash_bs_read_data( bs, (uint8_t *)od->URLstring, &length );
1235 od->URLlength = length;
1237 else
1239 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
1240 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
1242 od->ODProfileLevelIndication = lsmash_bs_get_byte( bs );
1243 od->sceneProfileLevelIndication = lsmash_bs_get_byte( bs );
1244 od->audioProfileLevelIndication = lsmash_bs_get_byte( bs );
1245 od->visualProfileLevelIndication = lsmash_bs_get_byte( bs );
1246 od->graphicsProfileLevelIndication = lsmash_bs_get_byte( bs );
1248 const mp4sys_descriptor_tag at_least_one_descriptor_tag
1249 = od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag
1250 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
1251 ? MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag
1252 : MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
1253 while( lsmash_bs_count( bs ) < end_pos && od->esDescr.entry_count < 255 )
1255 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, od );
1256 if( !desc )
1257 break;
1258 if( desc->header.tag != at_least_one_descriptor_tag )
1260 mp4sys_remove_descriptor( desc );
1261 break;
1265 return od;
1268 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent )
1270 mp4sys_descriptor_head_t header;
1271 mp4sys_get_descriptor_header( bs, &header );
1272 mp4sys_descriptor_t *desc;
1273 switch( header.tag )
1275 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
1276 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
1277 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
1278 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
1279 desc = (mp4sys_descriptor_t *)mp4sys_get_ObjectDescriptor( bs, &header, parent );
1280 break;
1281 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
1282 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_Descriptor( bs, &header, parent );
1283 break;
1284 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
1285 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderConfigDescriptor( bs, &header, parent );
1286 break;
1287 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1288 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderSpecificInfo( bs, &header, parent );
1289 break;
1290 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1291 desc = (mp4sys_descriptor_t *)mp4sys_get_SLConfigDescriptor( bs, &header, parent );
1292 break;
1293 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1294 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_ID_Inc( bs, &header, parent );
1295 break;
1296 default :
1297 desc = lsmash_malloc_zero( sizeof(mp4sys_descriptor_t) );
1298 if( desc )
1300 desc->parent = parent;
1301 desc->header = header;
1303 break;
1305 return desc;
1308 static uint8_t *mp4sys_export_DecoderSpecificInfo( mp4sys_ES_Descriptor_t *esd, uint32_t *dsi_payload_length )
1310 if( !esd || !esd->decConfigDescr || !esd->decConfigDescr->decSpecificInfo )
1311 return NULL;
1312 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)esd->decConfigDescr->decSpecificInfo;
1313 uint8_t *dsi_payload = NULL;
1314 /* DecoderSpecificInfo can be absent. */
1315 if( dsi->header.size )
1317 dsi_payload = lsmash_memdup( dsi->data, dsi->header.size );
1318 if( !dsi_payload )
1319 return NULL;
1321 if( dsi_payload_length )
1322 *dsi_payload_length = dsi->header.size;
1323 return dsi_payload;
1326 /* Sumamry is needed to decide ProfileLevelIndication.
1327 * Currently, support audio's only. */
1328 int mp4sys_setup_summary_from_DecoderSpecificInfo( lsmash_audio_summary_t *summary, mp4sys_ES_Descriptor_t *esd )
1330 uint32_t dsi_payload_length = UINT32_MAX; /* arbitrary */
1331 uint8_t *dsi_payload = mp4sys_export_DecoderSpecificInfo( esd, &dsi_payload_length );
1332 if( !dsi_payload && dsi_payload_length )
1333 return LSMASH_ERR_NAMELESS;
1334 int err = 0;
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 )
1341 err = LSMASH_ERR_MEMORY_ALLOC;
1342 goto fail;
1344 lsmash_mp4sys_decoder_parameters_t *params = (lsmash_mp4sys_decoder_parameters_t *)cs->data.structured;
1345 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1346 params->objectTypeIndication = dcd->objectTypeIndication;
1347 params->streamType = dcd->streamType;
1348 params->bufferSizeDB = dcd->bufferSizeDB;
1349 params->maxBitrate = dcd->maxBitrate;
1350 params->avgBitrate = dcd->avgBitrate;
1351 if( (err = mp4a_setup_summary_from_AudioSpecificConfig( summary, dsi_payload, dsi_payload_length )) < 0
1352 || (err = lsmash_set_mp4sys_decoder_specific_info( params, dsi_payload, dsi_payload_length )) < 0
1353 || (err = lsmash_add_entry( &summary->opaque->list, cs )) < 0 )
1355 lsmash_destroy_codec_specific_data( cs );
1356 goto fail;
1359 fail:
1360 lsmash_free( dsi_payload );
1361 return err;
1364 /**** following functions are for facilitation purpose ****/
1366 mp4sys_ES_Descriptor_t *mp4sys_setup_ES_Descriptor( mp4sys_ES_Descriptor_params_t *params )
1368 if( !params )
1369 return NULL;
1370 mp4sys_ES_Descriptor_t *esd = mp4sys_create_ES_Descriptor( params->ES_ID );
1371 if( !esd )
1372 return NULL;
1373 /* DecoderConfigDescriptor */
1374 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( esd );
1375 if( !dcd )
1376 goto fail;
1377 dcd->objectTypeIndication = params->objectTypeIndication;
1378 dcd->streamType = params->streamType;
1379 dcd->upStream = 0;
1380 dcd->reserved = 1;
1381 dcd->bufferSizeDB = params->bufferSizeDB;
1382 dcd->maxBitrate = params->maxBitrate;
1383 dcd->avgBitrate = params->avgBitrate;
1384 /* DecoderSpecificInfo */
1385 if( params->dsi_payload && params->dsi_payload_length != 0 )
1387 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( dcd );
1388 if( !dsi )
1389 goto fail;
1390 dsi->data = lsmash_memdup( params->dsi_payload, params->dsi_payload_length );
1391 if( !dsi->data )
1392 goto fail;
1393 dsi->header.size = params->dsi_payload_length;
1395 /* SLConfigDescriptor */
1397 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( esd );
1398 if( !slcd )
1399 goto fail;
1400 slcd->predefined = 0x02; /* MP4 file which does not use URL_Flag shall have constant value 0x02 */
1401 slcd->useTimeStampsFlag = 1; /* set to 1 if predefined == 2 */
1403 return esd;
1404 fail:
1405 mp4sys_remove_descriptor( esd );
1406 return NULL;
1409 int lsmash_set_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t *payload, uint32_t payload_length )
1411 if( !param || !payload || payload_length == 0 )
1412 return LSMASH_ERR_FUNCTION_PARAM;
1413 if( !param->dsi )
1415 param->dsi = lsmash_malloc_zero( sizeof(lsmash_mp4sys_decoder_specific_info_t) );
1416 if( !param->dsi )
1417 return LSMASH_ERR_MEMORY_ALLOC;
1419 else
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 LSMASH_ERR_MEMORY_ALLOC;
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 LSMASH_ERR_INVALID_DATA;
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 LSMASH_ERR_INVALID_DATA;
1505 data += 4; /* Skip version and flags. */
1506 lsmash_bs_t *bs = lsmash_bs_create();
1507 if( !bs )
1508 return LSMASH_ERR_MEMORY_ALLOC;
1509 int err = lsmash_bs_import_data( bs, data, src->size - (data - src->data.unstructured) );
1510 if( err < 0 )
1512 lsmash_bs_cleanup( bs );
1513 return err;
1515 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)mp4sys_get_descriptor( bs, NULL );
1516 lsmash_bs_cleanup( bs );
1517 if( !esd || esd->header.tag != MP4SYS_DESCRIPTOR_TAG_ES_DescrTag || !esd->decConfigDescr )
1518 return LSMASH_ERR_INVALID_DATA;
1519 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1520 param->objectTypeIndication = dcd->objectTypeIndication;
1521 param->streamType = dcd->streamType;
1522 param->bufferSizeDB = dcd->bufferSizeDB;
1523 param->maxBitrate = dcd->maxBitrate;
1524 param->avgBitrate = dcd->avgBitrate;
1525 mp4sys_DecoderSpecificInfo_t *dsi = dcd->decSpecificInfo;
1526 if( dsi
1527 && dsi->header.size
1528 && dsi->data
1529 && (err = lsmash_set_mp4sys_decoder_specific_info( param, dsi->data, dsi->header.size )) < 0 )
1531 mp4sys_remove_descriptor( esd );
1532 return err;
1534 mp4sys_remove_descriptor( esd );
1535 return 0;
1538 int mp4sys_copy_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1540 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
1541 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
1542 lsmash_mp4sys_decoder_parameters_t *src_data = (lsmash_mp4sys_decoder_parameters_t *)src->data.structured;
1543 lsmash_mp4sys_decoder_parameters_t *dst_data = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1544 lsmash_destroy_mp4sys_decoder_specific_info( dst_data );
1545 *dst_data = *src_data;
1546 dst_data->dsi = NULL;
1547 if( !src_data->dsi || !src_data->dsi->payload || src_data->dsi->payload_length == 0 )
1548 return 0;
1549 return lsmash_set_mp4sys_decoder_specific_info( dst_data, src_data->dsi->payload, src_data->dsi->payload_length );
1552 lsmash_mp4sys_object_type_indication lsmash_mp4sys_get_object_type_indication( lsmash_summary_t *summary )
1554 if( !summary )
1555 return MP4SYS_OBJECT_TYPE_Forbidden;
1556 lsmash_codec_specific_t *orig = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1557 if( !orig )
1558 return MP4SYS_OBJECT_TYPE_Forbidden;
1559 /* Found decoder configuration.
1560 * Let's get objectTypeIndication. */
1561 lsmash_mp4sys_object_type_indication objectTypeIndication;
1562 if( orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1563 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)orig->data.structured)->objectTypeIndication;
1564 else
1566 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( orig, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1567 if( !conv )
1568 return MP4SYS_OBJECT_TYPE_Forbidden;
1569 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)conv->data.structured)->objectTypeIndication;
1570 lsmash_destroy_codec_specific_data( conv );
1572 return objectTypeIndication;
1575 int lsmash_get_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t **payload, uint32_t *payload_length )
1577 if( !param || !payload || !payload_length )
1578 return LSMASH_ERR_FUNCTION_PARAM;
1579 if( !param->dsi || !param->dsi->payload || param->dsi->payload_length == 0 )
1581 *payload = NULL;
1582 *payload_length = 0;
1583 return 0;
1585 uint8_t *temp = lsmash_memdup( param->dsi->payload, param->dsi->payload_length );
1586 if( !temp )
1587 return LSMASH_ERR_MEMORY_ALLOC;
1588 *payload = temp;
1589 *payload_length = param->dsi->payload_length;
1590 return 0;