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