box: Add member offset in parent box struct.
[L-SMASH.git] / codecs / mp4sys.c
blob4ff3464b7d1dafab6a20154f9e06eeb8a39f9320
1 /*****************************************************************************
2 * mp4sys.c
3 *****************************************************************************
4 * Copyright (C) 2010-2017 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( !(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 uint64_t end_pos = header.size + lsmash_bs_count( bs );
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 /* Skip extra bytes if present. */
1307 uint64_t skip_bytes = end_pos - lsmash_bs_count( bs );
1308 if( skip_bytes )
1310 fprintf( stderr, "[MPEG-4 Systems Descriptor Tag = 0x%02"PRIx8"] has more bytes than expected: %"PRId64"\n", header.tag, skip_bytes );
1311 if( !bs->unseekable )
1313 /* The stream is seekable. So, skip by seeking the stream. */
1314 uint64_t start = lsmash_bs_get_stream_pos( bs );
1315 lsmash_bs_read_seek( bs, skip_bytes, SEEK_CUR );
1316 uint64_t end = lsmash_bs_get_stream_pos( bs );
1317 bs->buffer.count += end - start;
1319 else
1320 /* The stream is unseekable. So, skip by reading the stream. */
1321 lsmash_bs_skip_bytes_64( bs, skip_bytes );
1323 return desc;
1326 static uint8_t *mp4sys_export_DecoderSpecificInfo( mp4sys_ES_Descriptor_t *esd, uint32_t *dsi_payload_length )
1328 if( !esd || !esd->decConfigDescr || !esd->decConfigDescr->decSpecificInfo )
1329 return NULL;
1330 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)esd->decConfigDescr->decSpecificInfo;
1331 uint8_t *dsi_payload = NULL;
1332 /* DecoderSpecificInfo can be absent. */
1333 if( dsi->header.size )
1335 dsi_payload = lsmash_memdup( dsi->data, dsi->header.size );
1336 if( !dsi_payload )
1337 return NULL;
1339 if( dsi_payload_length )
1340 *dsi_payload_length = dsi->header.size;
1341 return dsi_payload;
1344 /* Sumamry is needed to decide ProfileLevelIndication.
1345 * Currently, support audio's only. */
1346 int mp4sys_setup_summary_from_DecoderSpecificInfo( lsmash_audio_summary_t *summary, mp4sys_ES_Descriptor_t *esd )
1348 uint32_t dsi_payload_length = UINT32_MAX; /* arbitrary */
1349 uint8_t *dsi_payload = mp4sys_export_DecoderSpecificInfo( esd, &dsi_payload_length );
1350 if( !dsi_payload && dsi_payload_length )
1351 return LSMASH_ERR_NAMELESS;
1352 int err = 0;
1353 if( dsi_payload_length )
1355 lsmash_codec_specific_t *cs = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG,
1356 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1357 if( !cs )
1359 err = LSMASH_ERR_MEMORY_ALLOC;
1360 goto fail;
1362 lsmash_mp4sys_decoder_parameters_t *params = (lsmash_mp4sys_decoder_parameters_t *)cs->data.structured;
1363 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1364 params->objectTypeIndication = dcd->objectTypeIndication;
1365 params->streamType = dcd->streamType;
1366 params->bufferSizeDB = dcd->bufferSizeDB;
1367 params->maxBitrate = dcd->maxBitrate;
1368 params->avgBitrate = dcd->avgBitrate;
1369 if( (err = mp4a_setup_summary_from_AudioSpecificConfig( summary, dsi_payload, dsi_payload_length )) < 0
1370 || (err = lsmash_set_mp4sys_decoder_specific_info( params, dsi_payload, dsi_payload_length )) < 0
1371 || (err = lsmash_add_entry( &summary->opaque->list, cs )) < 0 )
1373 lsmash_destroy_codec_specific_data( cs );
1374 goto fail;
1377 fail:
1378 lsmash_free( dsi_payload );
1379 return err;
1382 /**** following functions are for facilitation purpose ****/
1384 mp4sys_ES_Descriptor_t *mp4sys_setup_ES_Descriptor( mp4sys_ES_Descriptor_params_t *params )
1386 if( !params )
1387 return NULL;
1388 mp4sys_ES_Descriptor_t *esd = mp4sys_create_ES_Descriptor( params->ES_ID );
1389 if( !esd )
1390 return NULL;
1391 /* DecoderConfigDescriptor */
1392 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( esd );
1393 if( !dcd )
1394 goto fail;
1395 dcd->objectTypeIndication = params->objectTypeIndication;
1396 dcd->streamType = params->streamType;
1397 dcd->upStream = 0;
1398 dcd->reserved = 1;
1399 dcd->bufferSizeDB = params->bufferSizeDB;
1400 dcd->maxBitrate = params->maxBitrate;
1401 dcd->avgBitrate = params->avgBitrate;
1402 /* DecoderSpecificInfo */
1403 if( params->dsi_payload && params->dsi_payload_length != 0 )
1405 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( dcd );
1406 if( !dsi )
1407 goto fail;
1408 dsi->data = lsmash_memdup( params->dsi_payload, params->dsi_payload_length );
1409 if( !dsi->data )
1410 goto fail;
1411 dsi->header.size = params->dsi_payload_length;
1413 /* SLConfigDescriptor */
1415 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( esd );
1416 if( !slcd )
1417 goto fail;
1418 slcd->predefined = 0x02; /* MP4 file which does not use URL_Flag shall have constant value 0x02 */
1419 slcd->useTimeStampsFlag = 1; /* set to 1 if predefined == 2 */
1421 return esd;
1422 fail:
1423 mp4sys_remove_descriptor( esd );
1424 return NULL;
1427 int lsmash_set_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t *payload, uint32_t payload_length )
1429 if( !param || !payload || payload_length == 0 )
1430 return LSMASH_ERR_FUNCTION_PARAM;
1431 if( !param->dsi )
1433 param->dsi = lsmash_malloc_zero( sizeof(lsmash_mp4sys_decoder_specific_info_t) );
1434 if( !param->dsi )
1435 return LSMASH_ERR_MEMORY_ALLOC;
1437 else
1439 lsmash_freep( &param->dsi->payload );
1440 param->dsi->payload_length = 0;
1442 param->dsi->payload = lsmash_memdup( payload, payload_length );
1443 if( !param->dsi->payload )
1444 return LSMASH_ERR_MEMORY_ALLOC;
1445 param->dsi->payload_length = payload_length;
1446 return 0;
1449 void lsmash_destroy_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param )
1451 if( !param || !param->dsi )
1452 return;
1453 lsmash_free( param->dsi->payload );
1454 lsmash_freep( &param->dsi );
1457 void mp4sys_destruct_decoder_config( void *data )
1459 if( !data )
1460 return;
1461 lsmash_destroy_mp4sys_decoder_specific_info( data );
1462 lsmash_free( data );
1465 uint8_t *lsmash_create_mp4sys_decoder_config( lsmash_mp4sys_decoder_parameters_t *param, uint32_t *data_length )
1467 if( !param || !data_length )
1468 return NULL;
1469 mp4sys_ES_Descriptor_params_t esd_param = { 0 };
1470 esd_param.ES_ID = 0; /* Within sample description, ES_ID is stored as 0. */
1471 esd_param.objectTypeIndication = param->objectTypeIndication;
1472 esd_param.streamType = param->streamType;
1473 esd_param.bufferSizeDB = param->bufferSizeDB;
1474 esd_param.maxBitrate = param->maxBitrate;
1475 esd_param.avgBitrate = param->avgBitrate;
1476 if( param->dsi
1477 && param->dsi->payload
1478 && param->dsi->payload_length )
1480 esd_param.dsi_payload = param->dsi->payload;
1481 esd_param.dsi_payload_length = param->dsi->payload_length;
1483 mp4sys_ES_Descriptor_t *esd = mp4sys_setup_ES_Descriptor( &esd_param );
1484 if( !esd )
1485 return NULL;
1486 lsmash_bs_t *bs = lsmash_bs_create();
1487 if( !bs )
1489 mp4sys_remove_descriptor( esd );
1490 return NULL;
1492 lsmash_bs_put_be32( bs, 0 ); /* update later */
1493 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_ESDS.fourcc );
1494 lsmash_bs_put_be32( bs, 0 );
1495 mp4sys_update_descriptor_size( esd );
1496 mp4sys_write_descriptor( bs, esd );
1497 mp4sys_remove_descriptor( esd );
1498 uint8_t *data = lsmash_bs_export_data( bs, data_length );
1499 lsmash_bs_cleanup( bs );
1500 if( !data )
1501 return NULL;
1502 /* Update box size. */
1503 LSMASH_SET_BE32( data, *data_length );
1504 return data;
1507 int mp4sys_construct_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1509 assert( dst && dst->data.structured && src && src->data.unstructured );
1510 if( src->size < ISOM_FULLBOX_COMMON_SIZE + 23 )
1511 return LSMASH_ERR_INVALID_DATA;
1512 lsmash_mp4sys_decoder_parameters_t *param = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1513 uint8_t *data = src->data.unstructured;
1514 uint64_t size = LSMASH_GET_BE32( data );
1515 data += ISOM_BASEBOX_COMMON_SIZE;
1516 if( size == 1 )
1518 size = LSMASH_GET_BE64( data );
1519 data += 8;
1521 if( size != src->size )
1522 return LSMASH_ERR_INVALID_DATA;
1523 data += 4; /* Skip version and flags. */
1524 lsmash_bs_t *bs = lsmash_bs_create();
1525 if( !bs )
1526 return LSMASH_ERR_MEMORY_ALLOC;
1527 int err = lsmash_bs_import_data( bs, data, src->size - (data - src->data.unstructured) );
1528 if( err < 0 )
1530 lsmash_bs_cleanup( bs );
1531 return err;
1533 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)mp4sys_get_descriptor( bs, NULL );
1534 lsmash_bs_cleanup( bs );
1535 if( !esd || esd->header.tag != MP4SYS_DESCRIPTOR_TAG_ES_DescrTag || !esd->decConfigDescr )
1536 return LSMASH_ERR_INVALID_DATA;
1537 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1538 param->objectTypeIndication = dcd->objectTypeIndication;
1539 param->streamType = dcd->streamType;
1540 param->bufferSizeDB = dcd->bufferSizeDB;
1541 param->maxBitrate = dcd->maxBitrate;
1542 param->avgBitrate = dcd->avgBitrate;
1543 mp4sys_DecoderSpecificInfo_t *dsi = dcd->decSpecificInfo;
1544 if( dsi
1545 && dsi->header.size
1546 && dsi->data
1547 && (err = lsmash_set_mp4sys_decoder_specific_info( param, dsi->data, dsi->header.size )) < 0 )
1549 mp4sys_remove_descriptor( esd );
1550 return err;
1552 mp4sys_remove_descriptor( esd );
1553 return 0;
1556 int mp4sys_copy_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1558 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
1559 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
1560 lsmash_mp4sys_decoder_parameters_t *src_data = (lsmash_mp4sys_decoder_parameters_t *)src->data.structured;
1561 lsmash_mp4sys_decoder_parameters_t *dst_data = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1562 lsmash_destroy_mp4sys_decoder_specific_info( dst_data );
1563 *dst_data = *src_data;
1564 dst_data->dsi = NULL;
1565 if( !src_data->dsi || !src_data->dsi->payload || src_data->dsi->payload_length == 0 )
1566 return 0;
1567 return lsmash_set_mp4sys_decoder_specific_info( dst_data, src_data->dsi->payload, src_data->dsi->payload_length );
1570 lsmash_mp4sys_object_type_indication lsmash_mp4sys_get_object_type_indication( lsmash_summary_t *summary )
1572 if( !summary )
1573 return MP4SYS_OBJECT_TYPE_Forbidden;
1574 lsmash_codec_specific_t *orig = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1575 if( !orig )
1576 return MP4SYS_OBJECT_TYPE_Forbidden;
1577 /* Found decoder configuration.
1578 * Let's get objectTypeIndication. */
1579 lsmash_mp4sys_object_type_indication objectTypeIndication;
1580 if( orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1581 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)orig->data.structured)->objectTypeIndication;
1582 else
1584 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( orig, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1585 if( !conv )
1586 return MP4SYS_OBJECT_TYPE_Forbidden;
1587 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)conv->data.structured)->objectTypeIndication;
1588 lsmash_destroy_codec_specific_data( conv );
1590 return objectTypeIndication;
1593 int lsmash_get_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t **payload, uint32_t *payload_length )
1595 if( !param || !payload || !payload_length )
1596 return LSMASH_ERR_FUNCTION_PARAM;
1597 if( !param->dsi || !param->dsi->payload || param->dsi->payload_length == 0 )
1599 *payload = NULL;
1600 *payload_length = 0;
1601 return 0;
1603 uint8_t *temp = lsmash_memdup( param->dsi->payload, param->dsi->payload_length );
1604 if( !temp )
1605 return LSMASH_ERR_MEMORY_ALLOC;
1606 *payload = temp;
1607 *payload_length = param->dsi->payload_length;
1608 return 0;