list: Decide the entry eliminator of list at its initialization.
[L-SMASH.git] / codecs / mp4sys.c
blob487960d85b6a6f8c3302b8847d3b0ea1469e7144
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_list_remove_entry_direct( list, entry );
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_list_remove_entries( children );
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_list_remove_entry_direct( &parent->children, entry );
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 lsmash_list_init( &descriptor->children, mp4sys_destruct_descriptor );
596 return descriptor;
599 #define mp4sys_construct_descriptor( size, parent, destructor, writer ) \
600 mp4sys_construct_descriptor_orig \
602 size, \
603 (mp4sys_descriptor_t *)parent, \
604 (mp4sys_descriptor_destructor_t)destructor, \
605 (mp4sys_descriptor_writer_t)writer \
608 #define MP4SYS_CONSTRUCT_DESCRIPTOR( var, descriptor_name, parent, ret ) \
609 mp4sys_##descriptor_name##_t *var = \
610 mp4sys_construct_descriptor \
612 sizeof(mp4sys_##descriptor_name##_t), \
613 parent, \
614 mp4sys_remove_##descriptor_name, \
615 mp4sys_write_##descriptor_name \
616 ); \
617 if( !var ) \
618 return ret
620 static mp4sys_DecoderSpecificInfo_t *mp4sys_add_DecoderSpecificInfo( mp4sys_DecoderConfigDescriptor_t *dcd )
622 if( !dcd )
623 return NULL;
624 MP4SYS_CONSTRUCT_DESCRIPTOR( dsi, DecoderSpecificInfo, dcd, NULL );
625 dsi->header.tag = MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag;
626 if( lsmash_list_add_entry( &dcd->children, dsi ) < 0 )
628 mp4sys_remove_descriptor( dsi );
629 return NULL;
631 dcd->decSpecificInfo = dsi;
632 return dsi;
636 bufferSizeDB is byte unit, NOT bit unit.
637 avgBitrate is 0 if VBR
639 static mp4sys_DecoderConfigDescriptor_t *mp4sys_add_DecoderConfigDescriptor
641 mp4sys_ES_Descriptor_t *esd
644 if( !esd )
645 return NULL;
646 MP4SYS_CONSTRUCT_DESCRIPTOR( dcd, DecoderConfigDescriptor, esd, NULL );
647 dcd->header.tag = MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag;
648 if( lsmash_list_add_entry( &esd->children, dcd ) < 0 )
650 mp4sys_remove_descriptor( dcd );
651 return NULL;
653 esd->decConfigDescr = dcd;
654 return dcd;
657 static mp4sys_SLConfigDescriptor_t *mp4sys_add_SLConfigDescriptor( mp4sys_ES_Descriptor_t *esd )
659 if( !esd )
660 return NULL;
661 MP4SYS_CONSTRUCT_DESCRIPTOR( slcd, SLConfigDescriptor, esd, NULL );
662 slcd->header.tag = MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag;
663 if( lsmash_list_add_entry( &esd->children, slcd ) < 0 )
665 mp4sys_remove_descriptor( slcd );
666 return NULL;
668 esd->slConfigDescr = slcd;
669 return slcd;
672 /* NOTE: This is only for MP4_IOD and MP4_OD, not for ISO Base Media's ObjectDescriptor and InitialObjectDescriptor */
673 static mp4sys_ES_ID_Inc_t *mp4sys_add_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od )
675 if( !od
676 || (od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
677 && od->header.tag != MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag) )
678 return NULL;
679 MP4SYS_CONSTRUCT_DESCRIPTOR( es_id_inc, ES_ID_Inc, od, NULL );
680 es_id_inc->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag;
681 if( lsmash_list_add_entry( &od->children, es_id_inc ) < 0 )
683 mp4sys_remove_descriptor( es_id_inc );
684 return NULL;
686 if( lsmash_list_add_entry( &od->esDescr, es_id_inc ) < 0 )
688 lsmash_list_remove_entry_tail( &od->children );
689 return NULL;
691 return es_id_inc;
694 int mp4sys_create_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od, uint32_t Track_ID )
696 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( od );
697 if( !es_id_inc )
698 return LSMASH_ERR_NAMELESS;
699 es_id_inc->Track_ID = Track_ID;
700 return 0;
703 /* ES_ID of the ES Descriptor is stored as 0 when the ES Descriptor is built into sample descriptions in MP4 file format
704 * since the lower 16 bits of the track_ID is used, instead of ES_ID, for the identifier of the elemental stream within the track. */
705 mp4sys_ES_Descriptor_t *mp4sys_create_ES_Descriptor( uint16_t ES_ID )
707 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, NULL, NULL );
708 esd->header.tag = MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
709 esd->ES_ID = ES_ID;
710 return esd;
713 /* NOTE: This is only for MP4_OD, not for ISO Base Media's ObjectDescriptor */
714 mp4sys_ObjectDescriptor_t *mp4sys_create_ObjectDescriptor( uint16_t ObjectDescriptorID )
716 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, NULL, NULL );
717 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag;
718 od->ObjectDescriptorID = ObjectDescriptorID;
719 od->includeInlineProfileLevelFlag = 1; /* 1 as part of reserved flag. */
720 od->ODProfileLevelIndication = MP4SYS_OD_PLI_NONE_REQUIRED;
721 od->sceneProfileLevelIndication = MP4SYS_SCENE_PLI_NONE_REQUIRED;
722 od->audioProfileLevelIndication = MP4A_AUDIO_PLI_NONE_REQUIRED;
723 od->visualProfileLevelIndication = MP4SYS_VISUAL_PLI_NONE_REQUIRED;
724 od->graphicsProfileLevelIndication = MP4SYS_GRAPHICS_PLI_NONE_REQUIRED;
725 return od;
728 /* NOTE: This is only for MP4_IOD, not for Iso Base Media's InitialObjectDescriptor */
729 int mp4sys_to_InitialObjectDescriptor
731 mp4sys_ObjectDescriptor_t *od,
732 uint8_t include_inline_pli,
733 mp4sys_ODProfileLevelIndication od_pli,
734 mp4sys_sceneProfileLevelIndication scene_pli,
735 mp4a_audioProfileLevelIndication audio_pli,
736 mp4sys_visualProfileLevelIndication visual_pli,
737 mp4sys_graphicsProfileLevelIndication graph_pli
740 if( !od )
741 return LSMASH_ERR_NAMELESS;
742 od->header.tag = MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag;
743 od->includeInlineProfileLevelFlag = include_inline_pli;
744 od->ODProfileLevelIndication = od_pli;
745 od->sceneProfileLevelIndication = scene_pli;
746 od->audioProfileLevelIndication = audio_pli;
747 od->visualProfileLevelIndication = visual_pli;
748 od->graphicsProfileLevelIndication = graph_pli;
749 return 0;
753 bufferSizeDB is byte unit, NOT bit unit.
754 avgBitrate is 0 if VBR
756 int mp4sys_update_DecoderConfigDescriptor( mp4sys_ES_Descriptor_t *esd, uint32_t bufferSizeDB, uint32_t maxBitrate, uint32_t avgBitrate )
758 if( !esd || !esd->decConfigDescr )
759 return LSMASH_ERR_NAMELESS;
760 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
761 dcd->bufferSizeDB = bufferSizeDB;
762 dcd->maxBitrate = maxBitrate;
763 dcd->avgBitrate = avgBitrate;
764 return 0;
767 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent );
769 static void mp4sys_print_descriptor_header( FILE *fp, mp4sys_descriptor_head_t *header, int indent )
771 static const char *descriptor_names_table[256] =
773 "Forbidden",
774 "ObjectDescriptor",
775 "InitialObjectDescriptor",
776 "ES_Descriptor",
777 "DecoderConfigDescriptor",
778 "DecoderSpecificInfo",
779 "SLConfigDescriptor",
780 [0x0E] = "ES_ID_Inc",
781 [0x0F] = "ES_ID_Ref",
782 [0x10] = "MP4_IOD",
783 [0x11] = "MP4_OD"
785 if( descriptor_names_table[ header->tag ] )
786 lsmash_ifprintf( fp, indent, "[tag = 0x%02"PRIx8": %s]\n", header->tag, descriptor_names_table[ header->tag ] );
787 else
788 lsmash_ifprintf( fp, indent, "[tag = 0x%02"PRIx8"]\n", header->tag );
789 lsmash_ifprintf( fp, ++indent, "expandableClassSize = %"PRIu32"\n", header->size );
792 static void mp4sys_print_DecoderSpecificInfo( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
794 extern void mp4a_print_AudioSpecificConfig( FILE *, uint8_t *, uint32_t, int );
795 if( !descriptor->parent || descriptor->parent->header.tag != MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag )
796 return;
797 mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor->parent;
798 if( dcd->streamType != MP4SYS_STREAM_TYPE_AudioStream
799 || dcd->objectTypeIndication != MP4SYS_OBJECT_TYPE_Audio_ISO_14496_3 )
800 return; /* We support only AudioSpecificConfig here currently. */
801 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)descriptor;
802 mp4a_print_AudioSpecificConfig( fp, dsi->data, dsi->header.size, indent );
805 static void mp4sys_print_DecoderConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
807 mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor;
808 static const char *object_type_indication_descriptions_table[256] =
810 "Forbidden",
811 "Systems ISO/IEC 14496-1 (a)",
812 "Systems ISO/IEC 14496-1 (b)",
813 "Interaction Stream",
814 "Systems ISO/IEC 14496-1 Extended BIFS Configuration",
815 "Systems ISO/IEC 14496-1 AFX",
816 "Font Data Stream",
817 "Synthesized Texture Stream",
818 "Streaming Text Stream",
819 "LASeR Stream",
820 "Simple Aggregation Format (SAF) Stream",
821 [0x20] = "Visual ISO/IEC 14496-2",
822 [0x21] = "Visual ITU-T Recommendation H.264 | ISO/IEC 14496-10",
823 [0x22] = "Parameter Sets for ITU-T Recommendation H.264 | ISO/IEC 14496-10",
824 [0x40] = "Audio ISO/IEC 14496-3",
825 [0x60] = "Visual ISO/IEC 13818-2 Simple Profile",
826 [0x61] = "Visual ISO/IEC 13818-2 Main Profile",
827 [0x62] = "Visual ISO/IEC 13818-2 SNR Profile",
828 [0x63] = "Visual ISO/IEC 13818-2 Spatial Profile",
829 [0x64] = "Visual ISO/IEC 13818-2 High Profile",
830 [0x65] = "Visual ISO/IEC 13818-2 422 Profile",
831 [0x66] = "Audio ISO/IEC 13818-7 Main Profile",
832 [0x67] = "Audio ISO/IEC 13818-7 LowComplexity Profile",
833 [0x68] = "Audio ISO/IEC 13818-7 Scaleable Sampling Rate Profile",
834 [0x69] = "Audio ISO/IEC 13818-3",
835 [0x6A] = "Visual ISO/IEC 11172-2",
836 [0x6B] = "Audio ISO/IEC 11172-3",
837 [0x6C] = "Visual ISO/IEC 10918-1",
838 [0x6D] = "Portable Network Graphics",
839 [0x6E] = "Visual ISO/IEC 15444-1 (JPEG 2000)",
840 [0xA0] = "EVRC Voice",
841 [0xA1] = "SMV Voice",
842 [0xA2] = "3GPP2 Compact Multimedia Format (CMF)",
843 [0xA3] = "SMPTE VC-1 Video",
844 [0xA4] = "Dirac Video Coder",
845 [0xA5] = "AC-3 Audio",
846 [0xA6] = "Enhanced AC-3 audio",
847 [0xA7] = "DRA Audio",
848 [0xA8] = "ITU G.719 Audio",
849 [0xA9] = "DTS Coherent Acoustics audio",
850 [0xAA] = "DTS-HD High Resolution Audio",
851 [0xAB] = "DTS-HD Master Audio",
852 [0xAC] = "DTS Express low bit rate audio",
853 [0xE1] = "13K Voice",
854 [0xFF] = "no object type specified"
856 static const char *stream_type_descriptions_table[64] =
858 "Forbidden",
859 "ObjectDescriptorStream",
860 "ClockReferenceStream",
861 "SceneDescriptionStream",
862 "VisualStream",
863 "AudioStream",
864 "MPEG7Stream",
865 "IPMPStream",
866 "ObjectContentInfoStream",
867 "MPEGJStream",
868 "Interaction Stream",
869 "IPMPToolStream",
870 "FontDataStream",
871 "StreamingText"
873 if( object_type_indication_descriptions_table[ dcd->objectTypeIndication ] )
874 lsmash_ifprintf( fp, indent, "objectTypeIndication = 0x%02"PRIx8" (%s)\n", dcd->objectTypeIndication, object_type_indication_descriptions_table[ dcd->objectTypeIndication ] );
875 else
876 lsmash_ifprintf( fp, indent, "objectTypeIndication = 0x%02"PRIx8"\n", dcd->objectTypeIndication );
877 if( stream_type_descriptions_table[ dcd->streamType ] )
878 lsmash_ifprintf( fp, indent, "streamType = 0x%02"PRIx8" (%s)\n", dcd->streamType, stream_type_descriptions_table[ dcd->streamType ] );
879 else
880 lsmash_ifprintf( fp, indent, "streamType = 0x%02"PRIx8"\n", dcd->streamType );
881 lsmash_ifprintf( fp, indent, "upStream = %"PRIu8"\n", dcd->upStream );
882 lsmash_ifprintf( fp, indent, "reserved = %"PRIu8"\n", dcd->reserved );
883 lsmash_ifprintf( fp, indent, "bufferSizeDB = %"PRIu32"\n", dcd->bufferSizeDB );
884 lsmash_ifprintf( fp, indent, "maxBitrate = %"PRIu32"\n", dcd->maxBitrate );
885 lsmash_ifprintf( fp, indent, "avgBitrate = %"PRIu32"%s\n", dcd->avgBitrate, dcd->avgBitrate ? "" : " (variable bitrate)" );
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 );
945 static void mp4sys_print_ES_ID_Inc( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
947 mp4sys_ES_ID_Inc_t *es_id_inc = (mp4sys_ES_ID_Inc_t *)descriptor;
948 lsmash_ifprintf( fp, indent, "Track_ID = %"PRIu32"\n", es_id_inc->Track_ID );
951 static void mp4sys_print_ObjectDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
953 mp4sys_ObjectDescriptor_t *od = (mp4sys_ObjectDescriptor_t *)descriptor;
954 lsmash_ifprintf( fp, indent, "ObjectDescriptorID = %"PRIu16"\n", od->ObjectDescriptorID );
955 lsmash_ifprintf( fp, indent, "URL_Flag = %"PRIu8"\n", od->URL_Flag );
956 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
957 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
959 lsmash_ifprintf( fp, indent, "includeInlineProfileLevelFlag = %"PRIu8"\n", od->includeInlineProfileLevelFlag );
960 lsmash_ifprintf( fp, indent, "reserved = 0x%01"PRIx8"\n", od->reserved );
962 else
963 lsmash_ifprintf( fp, indent, "reserved = 0x%02"PRIx8"\n", od->reserved | (od->includeInlineProfileLevelFlag << 4) );
964 if( od->URL_Flag )
966 lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", od->URLlength );
967 lsmash_ifprintf( fp, indent, "URLstring = %s\n", od->URLstring );
969 else
971 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
972 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
974 lsmash_ifprintf( fp, indent, "ODProfileLevelIndication = 0x%02"PRIx8"\n", od->ODProfileLevelIndication );
975 lsmash_ifprintf( fp, indent, "sceneProfileLevelIndication = 0x%02"PRIx8"\n", od->sceneProfileLevelIndication );
976 lsmash_ifprintf( fp, indent, "audioProfileLevelIndication = 0x%02"PRIx8"\n", od->audioProfileLevelIndication );
977 lsmash_ifprintf( fp, indent, "visualProfileLevelIndication = 0x%02"PRIx8"\n", od->visualProfileLevelIndication );
978 lsmash_ifprintf( fp, indent, "graphicsProfileLevelIndication = 0x%02"PRIx8"\n", od->graphicsProfileLevelIndication );
983 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
985 if( !descriptor )
986 return;
987 mp4sys_print_descriptor_header( fp, &descriptor->header, indent++ );
988 switch( descriptor->header.tag )
990 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
991 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
992 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
993 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
994 mp4sys_print_ObjectDescriptor( fp, descriptor, indent );
995 break;
996 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
997 mp4sys_print_ES_Descriptor( fp, descriptor, indent );
998 break;
999 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
1000 mp4sys_print_DecoderConfigDescriptor( fp, descriptor, indent );
1001 break;
1002 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1003 mp4sys_print_DecoderSpecificInfo( fp, descriptor, indent );
1004 break;
1005 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1006 mp4sys_print_SLConfigDescriptor( fp, descriptor, indent );
1007 break;
1008 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1009 mp4sys_print_ES_ID_Inc( fp, descriptor, indent );
1010 break;
1011 default :
1012 break;
1014 for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
1015 if( entry->data )
1016 mp4sys_print_descriptor( fp, entry->data, indent );
1019 int mp4sys_print_codec_specific( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1021 assert( !(box->manager & LSMASH_BINARY_CODED_BOX) );
1022 isom_esds_t *esds = (isom_esds_t *)box;
1023 int indent = level;
1024 lsmash_ifprintf( fp, indent++, "[%s: Elemental Stream Descriptor Box]\n", isom_4cc2str( esds->type.fourcc ) );
1025 lsmash_ifprintf( fp, indent, "position = %"PRIu64"\n", esds->pos );
1026 lsmash_ifprintf( fp, indent, "size = %"PRIu64"\n", esds->size );
1027 lsmash_ifprintf( fp, indent, "version = %"PRIu8"\n", esds->version );
1028 lsmash_ifprintf( fp, indent, "flags = 0x%06"PRIx32"\n", esds->flags & 0x00ffffff );
1029 mp4sys_print_descriptor( fp, (mp4sys_descriptor_t *)esds->ES, indent );
1030 return 0;
1033 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent );
1035 static void mp4sys_get_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
1037 header->tag = lsmash_bs_get_byte( bs );
1038 uint8_t temp = lsmash_bs_get_byte( bs );
1039 int nextByte = temp & 0x80;
1040 uint32_t sizeOfInstance = temp & 0x7F;
1041 while( nextByte )
1043 temp = lsmash_bs_get_byte( bs );
1044 nextByte = temp & 0x80;
1045 sizeOfInstance = (sizeOfInstance << 7) | (temp & 0x7F);
1047 header->size = sizeOfInstance;
1050 static mp4sys_DecoderSpecificInfo_t *mp4sys_get_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1052 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( parent );
1053 if( !dsi )
1054 return NULL;
1055 dsi->header.size = header->size;
1056 if( dsi->header.size )
1058 dsi->data = lsmash_bs_get_bytes( bs, dsi->header.size );
1059 if( !dsi->data )
1061 mp4sys_remove_descriptor( dsi );
1062 return NULL;
1065 return dsi;
1068 static mp4sys_DecoderConfigDescriptor_t *mp4sys_get_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1070 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( parent );
1071 if( !dcd )
1072 return NULL;
1073 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1074 dcd->header.size = header->size;
1075 dcd->objectTypeIndication = lsmash_bs_get_byte( bs );
1076 uint8_t temp = lsmash_bs_get_byte( bs );
1077 dcd->streamType = (temp >> 2) & 0x3F;
1078 dcd->upStream = (temp >> 1) & 0x01;
1079 dcd->reserved = temp & 0x01;
1080 dcd->bufferSizeDB = lsmash_bs_get_be24( bs );
1081 dcd->maxBitrate = lsmash_bs_get_be32( bs );
1082 dcd->avgBitrate = lsmash_bs_get_be32( bs );
1083 while( lsmash_bs_count( bs ) < end_pos )
1085 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, dcd );
1086 if( desc )
1088 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag )
1089 dcd->decSpecificInfo = (mp4sys_DecoderSpecificInfo_t *)desc;
1090 else
1091 mp4sys_remove_descriptor( desc );
1093 else
1094 break;
1096 return dcd;
1099 static mp4sys_SLConfigDescriptor_t *mp4sys_get_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1101 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( parent );
1102 if( !slcd )
1103 return NULL;
1104 slcd->header.size = header->size;
1105 slcd->predefined = lsmash_bs_get_byte( bs );
1106 if( slcd->predefined == 0x00 )
1108 uint8_t temp8 = lsmash_bs_get_byte( bs );
1109 slcd->useAccessUnitStartFlag = (temp8 >> 7) & 0x01;
1110 slcd->useAccessUnitEndFlag = (temp8 >> 6) & 0x01;
1111 slcd->useRandomAccessPointFlag = (temp8 >> 5) & 0x01;
1112 slcd->hasRandomAccessUnitsOnlyFlag = (temp8 >> 4) & 0x01;
1113 slcd->usePaddingFlag = (temp8 >> 3) & 0x01;
1114 slcd->useTimeStampsFlag = (temp8 >> 2) & 0x01;
1115 slcd->useIdleFlag = (temp8 >> 1) & 0x01;
1116 slcd->durationFlag = temp8 & 0x01;
1117 slcd->timeStampResolution = lsmash_bs_get_be32( bs );
1118 slcd->OCRResolution = lsmash_bs_get_be32( bs );
1119 slcd->timeStampLength = lsmash_bs_get_byte( bs );
1120 slcd->OCRLength = lsmash_bs_get_byte( bs );
1121 slcd->AU_Length = lsmash_bs_get_byte( bs );
1122 slcd->instantBitrateLength = lsmash_bs_get_byte( bs );
1123 uint16_t temp16 = lsmash_bs_get_be16( bs );
1124 slcd->degradationPriorityLength = (temp16 >> 12) & 0x0F;
1125 slcd->AU_seqNumLength = (temp16 >> 7) & 0x1F;
1126 slcd->packetSeqNumLength = (temp16 >> 2) & 0x1F;
1127 slcd->reserved = temp16 & 0x03;
1129 else if( slcd->predefined == 0x01 )
1131 slcd->timeStampResolution = 1000;
1132 slcd->timeStampLength = 32;
1134 else if( slcd->predefined == 0x02 )
1135 slcd->useTimeStampsFlag = 1;
1136 if( slcd->durationFlag )
1138 slcd->timeScale = lsmash_bs_get_be32( bs );
1139 slcd->accessUnitDuration = lsmash_bs_get_be16( bs );
1140 slcd->compositionUnitDuration = lsmash_bs_get_be16( bs );
1142 if( !slcd->useTimeStampsFlag )
1144 lsmash_bits_t *bits = lsmash_bits_create( bs );
1145 if( !bits )
1147 mp4sys_remove_descriptor( slcd );
1148 return NULL;
1150 slcd->startDecodingTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1151 slcd->startCompositionTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1152 lsmash_bits_cleanup( bits );
1154 return slcd;
1157 static mp4sys_ES_Descriptor_t *mp4sys_get_ES_Descriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1159 MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, parent, NULL );
1160 if( parent && lsmash_list_add_entry( &((mp4sys_descriptor_t *)parent)->children, esd ) < 0 )
1162 mp4sys_remove_descriptor( esd );
1163 return NULL;
1165 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1166 esd->header = *header;
1167 esd->ES_ID = lsmash_bs_get_be16( bs );
1168 uint8_t temp = lsmash_bs_get_byte( bs );
1169 esd->streamDependenceFlag = (temp >> 7) & 0x01;
1170 esd->URL_Flag = (temp >> 6) & 0x01;
1171 esd->OCRstreamFlag = (temp >> 5) & 0x01;
1172 esd->streamPriority = temp & 0x1F;
1173 if( esd->streamDependenceFlag )
1174 esd->dependsOn_ES_ID = lsmash_bs_get_be16( bs );
1175 if( esd->URL_Flag )
1177 size_t length = lsmash_bs_get_byte( bs );
1178 lsmash_bs_read_data( bs, (uint8_t *)esd->URLstring, &length );
1179 esd->URLlength = length;
1181 if( esd->OCRstreamFlag )
1182 esd->OCR_ES_Id = lsmash_bs_get_be16( bs );
1183 /* DecoderConfigDescriptor and SLConfigDescriptor are mandatory. */
1184 while( lsmash_bs_count( bs ) < end_pos )
1186 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, esd );
1187 if( desc )
1189 if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag )
1190 esd->decConfigDescr = (mp4sys_DecoderConfigDescriptor_t *)desc;
1191 else if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag )
1192 esd->slConfigDescr = (mp4sys_SLConfigDescriptor_t *)desc;
1193 else
1194 mp4sys_remove_descriptor( desc );
1196 else
1197 break;
1199 if( !esd->decConfigDescr || !esd->slConfigDescr )
1201 mp4sys_remove_descriptor( esd );
1202 return NULL;
1204 return esd;
1207 static mp4sys_ES_ID_Inc_t *mp4sys_get_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1209 mp4sys_ES_ID_Inc_t *es_id_inc = mp4sys_add_ES_ID_Inc( parent );
1210 if( !es_id_inc )
1211 return NULL;
1212 es_id_inc->header.size = header->size;
1213 es_id_inc->Track_ID = lsmash_bs_get_be32( bs );
1214 return es_id_inc;
1217 static mp4sys_ObjectDescriptor_t *mp4sys_get_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1219 MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, parent, NULL );
1220 if( parent && lsmash_list_add_entry( &((mp4sys_descriptor_t *)parent)->children, od ) < 0 )
1222 mp4sys_remove_descriptor( od );
1223 return NULL;
1225 od->header = *header;
1226 uint64_t end_pos = header->size + lsmash_bs_count( bs );
1227 uint16_t temp16 = lsmash_bs_get_be16( bs );
1228 od->ObjectDescriptorID = (temp16 >> 6) & 0x03FF;
1229 od->URL_Flag = (temp16 >> 5) & 0x0001;
1230 od->includeInlineProfileLevelFlag = (temp16 >> 4) & 0x0001;
1231 od->reserved = temp16 & 0x000F;
1232 if( od->URL_Flag )
1234 size_t length = lsmash_bs_get_byte( bs );
1235 lsmash_bs_read_data( bs, (uint8_t *)od->URLstring, &length );
1236 od->URLlength = length;
1238 else
1240 if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
1241 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
1243 od->ODProfileLevelIndication = lsmash_bs_get_byte( bs );
1244 od->sceneProfileLevelIndication = lsmash_bs_get_byte( bs );
1245 od->audioProfileLevelIndication = lsmash_bs_get_byte( bs );
1246 od->visualProfileLevelIndication = lsmash_bs_get_byte( bs );
1247 od->graphicsProfileLevelIndication = lsmash_bs_get_byte( bs );
1249 const mp4sys_descriptor_tag at_least_one_descriptor_tag
1250 = od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag
1251 || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag
1252 ? MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag
1253 : MP4SYS_DESCRIPTOR_TAG_ES_DescrTag;
1254 while( lsmash_bs_count( bs ) < end_pos && od->esDescr.entry_count < 255 )
1256 mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, od );
1257 if( !desc )
1258 break;
1259 if( desc->header.tag != at_least_one_descriptor_tag )
1261 mp4sys_remove_descriptor( desc );
1262 break;
1266 return od;
1269 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent )
1271 mp4sys_descriptor_head_t header;
1272 mp4sys_get_descriptor_header( bs, &header );
1273 uint64_t end_pos = header.size + lsmash_bs_count( bs );
1274 mp4sys_descriptor_t *desc;
1275 switch( header.tag )
1277 case MP4SYS_DESCRIPTOR_TAG_ObjectDescrTag :
1278 case MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag :
1279 case MP4SYS_DESCRIPTOR_TAG_MP4_OD_Tag :
1280 case MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag :
1281 desc = (mp4sys_descriptor_t *)mp4sys_get_ObjectDescriptor( bs, &header, parent );
1282 break;
1283 case MP4SYS_DESCRIPTOR_TAG_ES_DescrTag :
1284 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_Descriptor( bs, &header, parent );
1285 break;
1286 case MP4SYS_DESCRIPTOR_TAG_DecoderConfigDescrTag :
1287 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderConfigDescriptor( bs, &header, parent );
1288 break;
1289 case MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag :
1290 desc = (mp4sys_descriptor_t *)mp4sys_get_DecoderSpecificInfo( bs, &header, parent );
1291 break;
1292 case MP4SYS_DESCRIPTOR_TAG_SLConfigDescrTag :
1293 desc = (mp4sys_descriptor_t *)mp4sys_get_SLConfigDescriptor( bs, &header, parent );
1294 break;
1295 case MP4SYS_DESCRIPTOR_TAG_ES_ID_IncTag :
1296 desc = (mp4sys_descriptor_t *)mp4sys_get_ES_ID_Inc( bs, &header, parent );
1297 break;
1298 default :
1299 desc = lsmash_malloc_zero( sizeof(mp4sys_descriptor_t) );
1300 if( desc )
1302 desc->parent = parent;
1303 desc->header = header;
1305 break;
1307 /* Skip extra bytes if present. */
1308 uint64_t skip_bytes = end_pos - lsmash_bs_count( bs );
1309 if( skip_bytes )
1311 fprintf( stderr, "[MPEG-4 Systems Descriptor Tag = 0x%02"PRIx8"] has more bytes than expected: %"PRId64"\n", header.tag, skip_bytes );
1312 if( !bs->unseekable )
1314 /* The stream is seekable. So, skip by seeking the stream. */
1315 uint64_t start = lsmash_bs_get_stream_pos( bs );
1316 lsmash_bs_read_seek( bs, skip_bytes, SEEK_CUR );
1317 uint64_t end = lsmash_bs_get_stream_pos( bs );
1318 bs->buffer.count += end - start;
1320 else
1321 /* The stream is unseekable. So, skip by reading the stream. */
1322 lsmash_bs_skip_bytes_64( bs, skip_bytes );
1324 return desc;
1327 static uint8_t *mp4sys_export_DecoderSpecificInfo( mp4sys_ES_Descriptor_t *esd, uint32_t *dsi_payload_length )
1329 if( !esd || !esd->decConfigDescr || !esd->decConfigDescr->decSpecificInfo )
1330 return NULL;
1331 mp4sys_DecoderSpecificInfo_t *dsi = (mp4sys_DecoderSpecificInfo_t *)esd->decConfigDescr->decSpecificInfo;
1332 uint8_t *dsi_payload = NULL;
1333 /* DecoderSpecificInfo can be absent. */
1334 if( dsi->header.size )
1336 dsi_payload = lsmash_memdup( dsi->data, dsi->header.size );
1337 if( !dsi_payload )
1338 return NULL;
1340 if( dsi_payload_length )
1341 *dsi_payload_length = dsi->header.size;
1342 return dsi_payload;
1345 /* Sumamry is needed to decide ProfileLevelIndication.
1346 * Currently, support audio's only. */
1347 int mp4sys_setup_summary_from_DecoderSpecificInfo( lsmash_audio_summary_t *summary, mp4sys_ES_Descriptor_t *esd )
1349 uint32_t dsi_payload_length = UINT32_MAX; /* arbitrary */
1350 uint8_t *dsi_payload = mp4sys_export_DecoderSpecificInfo( esd, &dsi_payload_length );
1351 if( !dsi_payload && dsi_payload_length )
1352 return LSMASH_ERR_NAMELESS;
1353 int err = 0;
1354 if( dsi_payload_length )
1356 lsmash_codec_specific_t *cs = lsmash_create_codec_specific_data( LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG,
1357 LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1358 if( !cs )
1360 err = LSMASH_ERR_MEMORY_ALLOC;
1361 goto fail;
1363 lsmash_mp4sys_decoder_parameters_t *params = (lsmash_mp4sys_decoder_parameters_t *)cs->data.structured;
1364 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1365 params->objectTypeIndication = dcd->objectTypeIndication;
1366 params->streamType = dcd->streamType;
1367 params->bufferSizeDB = dcd->bufferSizeDB;
1368 params->maxBitrate = dcd->maxBitrate;
1369 params->avgBitrate = dcd->avgBitrate;
1370 if( (err = mp4a_setup_summary_from_AudioSpecificConfig( summary, dsi_payload, dsi_payload_length )) < 0
1371 || (err = lsmash_set_mp4sys_decoder_specific_info( params, dsi_payload, dsi_payload_length )) < 0
1372 || (err = lsmash_list_add_entry( &summary->opaque->list, cs )) < 0 )
1374 lsmash_destroy_codec_specific_data( cs );
1375 goto fail;
1378 fail:
1379 lsmash_free( dsi_payload );
1380 return err;
1383 /**** following functions are for facilitation purpose ****/
1385 mp4sys_ES_Descriptor_t *mp4sys_setup_ES_Descriptor( mp4sys_ES_Descriptor_params_t *params )
1387 if( !params )
1388 return NULL;
1389 mp4sys_ES_Descriptor_t *esd = mp4sys_create_ES_Descriptor( params->ES_ID );
1390 if( !esd )
1391 return NULL;
1392 /* DecoderConfigDescriptor */
1393 mp4sys_DecoderConfigDescriptor_t *dcd = mp4sys_add_DecoderConfigDescriptor( esd );
1394 if( !dcd )
1395 goto fail;
1396 dcd->objectTypeIndication = params->objectTypeIndication;
1397 dcd->streamType = params->streamType;
1398 dcd->upStream = 0;
1399 dcd->reserved = 1;
1400 dcd->bufferSizeDB = params->bufferSizeDB;
1401 dcd->maxBitrate = params->maxBitrate;
1402 dcd->avgBitrate = params->avgBitrate;
1403 /* DecoderSpecificInfo */
1404 if( params->dsi_payload && params->dsi_payload_length != 0 )
1406 mp4sys_DecoderSpecificInfo_t *dsi = mp4sys_add_DecoderSpecificInfo( dcd );
1407 if( !dsi )
1408 goto fail;
1409 dsi->data = lsmash_memdup( params->dsi_payload, params->dsi_payload_length );
1410 if( !dsi->data )
1411 goto fail;
1412 dsi->header.size = params->dsi_payload_length;
1414 /* SLConfigDescriptor */
1416 mp4sys_SLConfigDescriptor_t *slcd = mp4sys_add_SLConfigDescriptor( esd );
1417 if( !slcd )
1418 goto fail;
1419 slcd->predefined = 0x02; /* MP4 file which does not use URL_Flag shall have constant value 0x02 */
1420 slcd->useTimeStampsFlag = 1; /* set to 1 if predefined == 2 */
1422 return esd;
1423 fail:
1424 mp4sys_remove_descriptor( esd );
1425 return NULL;
1428 int lsmash_set_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t *payload, uint32_t payload_length )
1430 if( !param || !payload || payload_length == 0 )
1431 return LSMASH_ERR_FUNCTION_PARAM;
1432 if( !param->dsi )
1434 param->dsi = lsmash_malloc_zero( sizeof(lsmash_mp4sys_decoder_specific_info_t) );
1435 if( !param->dsi )
1436 return LSMASH_ERR_MEMORY_ALLOC;
1438 else
1440 lsmash_freep( &param->dsi->payload );
1441 param->dsi->payload_length = 0;
1443 param->dsi->payload = lsmash_memdup( payload, payload_length );
1444 if( !param->dsi->payload )
1445 return LSMASH_ERR_MEMORY_ALLOC;
1446 param->dsi->payload_length = payload_length;
1447 return 0;
1450 void lsmash_destroy_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param )
1452 if( !param || !param->dsi )
1453 return;
1454 lsmash_free( param->dsi->payload );
1455 lsmash_freep( &param->dsi );
1458 void mp4sys_destruct_decoder_config( void *data )
1460 if( !data )
1461 return;
1462 lsmash_destroy_mp4sys_decoder_specific_info( data );
1463 lsmash_free( data );
1466 uint8_t *lsmash_create_mp4sys_decoder_config( lsmash_mp4sys_decoder_parameters_t *param, uint32_t *data_length )
1468 if( !param || !data_length )
1469 return NULL;
1470 mp4sys_ES_Descriptor_params_t esd_param = { 0 };
1471 esd_param.ES_ID = 0; /* Within sample description, ES_ID is stored as 0. */
1472 esd_param.objectTypeIndication = param->objectTypeIndication;
1473 esd_param.streamType = param->streamType;
1474 esd_param.bufferSizeDB = param->bufferSizeDB;
1475 esd_param.maxBitrate = param->maxBitrate;
1476 esd_param.avgBitrate = param->avgBitrate;
1477 if( param->dsi
1478 && param->dsi->payload
1479 && param->dsi->payload_length )
1481 esd_param.dsi_payload = param->dsi->payload;
1482 esd_param.dsi_payload_length = param->dsi->payload_length;
1484 mp4sys_ES_Descriptor_t *esd = mp4sys_setup_ES_Descriptor( &esd_param );
1485 if( !esd )
1486 return NULL;
1487 lsmash_bs_t *bs = lsmash_bs_create();
1488 if( !bs )
1490 mp4sys_remove_descriptor( esd );
1491 return NULL;
1493 lsmash_bs_put_be32( bs, 0 ); /* update later */
1494 lsmash_bs_put_be32( bs, ISOM_BOX_TYPE_ESDS.fourcc );
1495 lsmash_bs_put_be32( bs, 0 );
1496 mp4sys_update_descriptor_size( esd );
1497 mp4sys_write_descriptor( bs, esd );
1498 mp4sys_remove_descriptor( esd );
1499 uint8_t *data = lsmash_bs_export_data( bs, data_length );
1500 lsmash_bs_cleanup( bs );
1501 if( !data )
1502 return NULL;
1503 /* Update box size. */
1504 LSMASH_SET_BE32( data, *data_length );
1505 return data;
1508 int mp4sys_construct_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1510 assert( dst && dst->data.structured && src && src->data.unstructured );
1511 if( src->size < ISOM_FULLBOX_COMMON_SIZE + 23 )
1512 return LSMASH_ERR_INVALID_DATA;
1513 lsmash_mp4sys_decoder_parameters_t *param = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1514 uint8_t *data = src->data.unstructured;
1515 uint64_t size = LSMASH_GET_BE32( data );
1516 data += ISOM_BASEBOX_COMMON_SIZE;
1517 if( size == 1 )
1519 size = LSMASH_GET_BE64( data );
1520 data += 8;
1522 if( size != src->size )
1523 return LSMASH_ERR_INVALID_DATA;
1524 data += 4; /* Skip version and flags. */
1525 lsmash_bs_t *bs = lsmash_bs_create();
1526 if( !bs )
1527 return LSMASH_ERR_MEMORY_ALLOC;
1528 int err = lsmash_bs_import_data( bs, data, src->size - (data - src->data.unstructured) );
1529 if( err < 0 )
1531 lsmash_bs_cleanup( bs );
1532 return err;
1534 mp4sys_ES_Descriptor_t *esd = (mp4sys_ES_Descriptor_t *)mp4sys_get_descriptor( bs, NULL );
1535 lsmash_bs_cleanup( bs );
1536 if( !esd || esd->header.tag != MP4SYS_DESCRIPTOR_TAG_ES_DescrTag || !esd->decConfigDescr )
1537 return LSMASH_ERR_INVALID_DATA;
1538 mp4sys_DecoderConfigDescriptor_t *dcd = esd->decConfigDescr;
1539 param->objectTypeIndication = dcd->objectTypeIndication;
1540 param->streamType = dcd->streamType;
1541 param->bufferSizeDB = dcd->bufferSizeDB;
1542 param->maxBitrate = dcd->maxBitrate;
1543 param->avgBitrate = dcd->avgBitrate;
1544 mp4sys_DecoderSpecificInfo_t *dsi = dcd->decSpecificInfo;
1545 if( dsi
1546 && dsi->header.size
1547 && dsi->data
1548 && (err = lsmash_set_mp4sys_decoder_specific_info( param, dsi->data, dsi->header.size )) < 0 )
1550 mp4sys_remove_descriptor( esd );
1551 return err;
1553 mp4sys_remove_descriptor( esd );
1554 return 0;
1557 int mp4sys_copy_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1559 assert( src && src->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && src->data.structured );
1560 assert( dst && dst->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED && dst->data.structured );
1561 lsmash_mp4sys_decoder_parameters_t *src_data = (lsmash_mp4sys_decoder_parameters_t *)src->data.structured;
1562 lsmash_mp4sys_decoder_parameters_t *dst_data = (lsmash_mp4sys_decoder_parameters_t *)dst->data.structured;
1563 lsmash_destroy_mp4sys_decoder_specific_info( dst_data );
1564 *dst_data = *src_data;
1565 dst_data->dsi = NULL;
1566 if( !src_data->dsi || !src_data->dsi->payload || src_data->dsi->payload_length == 0 )
1567 return 0;
1568 return lsmash_set_mp4sys_decoder_specific_info( dst_data, src_data->dsi->payload, src_data->dsi->payload_length );
1571 lsmash_mp4sys_object_type_indication lsmash_mp4sys_get_object_type_indication( lsmash_summary_t *summary )
1573 if( !summary )
1574 return MP4SYS_OBJECT_TYPE_Forbidden;
1575 lsmash_codec_specific_t *orig = isom_get_codec_specific( summary->opaque, LSMASH_CODEC_SPECIFIC_DATA_TYPE_MP4SYS_DECODER_CONFIG );
1576 if( !orig )
1577 return MP4SYS_OBJECT_TYPE_Forbidden;
1578 /* Found decoder configuration.
1579 * Let's get objectTypeIndication. */
1580 lsmash_mp4sys_object_type_indication objectTypeIndication;
1581 if( orig->format == LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED )
1582 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)orig->data.structured)->objectTypeIndication;
1583 else
1585 lsmash_codec_specific_t *conv = lsmash_convert_codec_specific_format( orig, LSMASH_CODEC_SPECIFIC_FORMAT_STRUCTURED );
1586 if( !conv )
1587 return MP4SYS_OBJECT_TYPE_Forbidden;
1588 objectTypeIndication = ((lsmash_mp4sys_decoder_parameters_t *)conv->data.structured)->objectTypeIndication;
1589 lsmash_destroy_codec_specific_data( conv );
1591 return objectTypeIndication;
1594 int lsmash_get_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t **payload, uint32_t *payload_length )
1596 if( !param || !payload || !payload_length )
1597 return LSMASH_ERR_FUNCTION_PARAM;
1598 if( !param->dsi || !param->dsi->payload || param->dsi->payload_length == 0 )
1600 *payload = NULL;
1601 *payload_length = 0;
1602 return 0;
1604 uint8_t *temp = lsmash_memdup( param->dsi->payload, param->dsi->payload_length );
1605 if( !temp )
1606 return LSMASH_ERR_MEMORY_ALLOC;
1607 *payload = temp;
1608 *payload_length = param->dsi->payload_length;
1609 return 0;