1 /*****************************************************************************
2  * mp4sys.c
3  *****************************************************************************
4  * Copyright (C) 2010-2017 L-SMASH project
5  *
6  * Authors: Takashi Hirata <silverfilain@gmail.com>
7  *          Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8  *
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.
12  *
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  *****************************************************************************/
21 
22 /* This file is available under an ISC license. */
23 
24 #include "common/internal.h" /* must be placed first */
25 
26 #include <stdlib.h>
27 #include <string.h>
28 #include <inttypes.h>
29 
30 #include "core/box.h"
31 
32 #include "description.h"
33 #include "mp4a.h"
34 #define MP4SYS_INTERNAL
35 #include "mp4sys.h"
36 
37 /***************************************************************************
38     MPEG-4 Systems
39 ***************************************************************************/
40 
41 #define ALWAYS_28BITS_LENGTH_CODING 1 // for some weird (but originator's) devices
42 
43 static const lsmash_class_t lsmash_mp4sys_class =
44 {
45     "mp4sys"
46 };
47 
48 /* List of Class Tags for Descriptors */
49 typedef enum
50 {
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 */
86 
87 typedef struct
88 {
89     uint32_t              size; // 2^28 at most
90     mp4sys_descriptor_tag tag;
91 } mp4sys_descriptor_head_t;
92 
93 typedef struct mp4sys_descriptor_tag mp4sys_descriptor_t;
94 
95 typedef void (*mp4sys_descriptor_destructor_t)( void * );
96 typedef int (*mp4sys_descriptor_writer_t)( lsmash_bs_t *, void * );
97 
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
105 
106 struct mp4sys_descriptor_tag
107 {
108     MP4SYS_DESCRIPTOR_COMMON;
109 };
110 
111 typedef struct
112 {
113     MP4SYS_DESCRIPTOR_COMMON;
114 } mp4sys_BaseDescriptor_t;
115 
116 /* DecoderSpecificInfo */
117 /* contents varies depends on ObjectTypeIndication and StreamType. */
118 typedef struct
119 {
120     MP4SYS_DESCRIPTOR_COMMON;
121     uint8_t *data;
122 } mp4sys_DecoderSpecificInfo_t;
123 
124 /* DecoderConfigDescriptor */
125 typedef struct
126 {
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;
142 
143 /* SLConfigDescriptor */
144 typedef struct
145 {
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;
181 
182 /* ES_Descriptor */
183 typedef struct mp4sys_ES_Descriptor_t
184 {
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 */
198     /*
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
207     */
208 } mp4sys_ES_Descriptor_t;
209 
210 /* 14496-14 Object Descriptors (ES_ID_Inc) */
211 typedef struct
212 {
213     MP4SYS_DESCRIPTOR_COMMON;
214     uint32_t Track_ID;
215 } mp4sys_ES_ID_Inc_t;
216 
217 /* 14496-1 ObjectDescriptor / InitialObjectDescriptor */
218 typedef struct
219 {
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;
239 
mp4sys_remove_predefined_descriptor(void * opaque_descriptor,size_t offset_of_descriptor)240 static void mp4sys_remove_predefined_descriptor( void *opaque_descriptor, size_t offset_of_descriptor )
241 {
242     assert( opaque_descriptor );
243     mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
244     if( descriptor->parent )
245     {
246         mp4sys_descriptor_t **p = (mp4sys_descriptor_t **)(((int8_t *)descriptor->parent) + offset_of_descriptor);
247         if( *p == descriptor )
248             *p = NULL;
249     }
250 }
251 
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. */
mp4sys_remove_descriptor_in_predefined_list(void * opaque_descriptor,size_t offset_of_list)254 static void mp4sys_remove_descriptor_in_predefined_list( void *opaque_descriptor, size_t offset_of_list )
255 {
256     assert( opaque_descriptor );
257     mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
258     if( descriptor->parent )
259     {
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 )
263             {
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;
270             }
271     }
272 }
273 
274 static void mp4sys_remove_all_child_descriptors( lsmash_entry_list_t *children );
275 
276 /* Free a descriptor and its children. */
mp4sys_destruct_descriptor(mp4sys_descriptor_t * descriptor)277 static void mp4sys_destruct_descriptor( mp4sys_descriptor_t *descriptor )
278 {
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 );
285 }
286 
mp4sys_remove_all_child_descriptors(lsmash_entry_list_t * children)287 static void mp4sys_remove_all_child_descriptors( lsmash_entry_list_t *children )
288 {
289     lsmash_list_remove_entries( children );
290 }
291 
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. */
mp4sys_remove_descriptor(void * opaque_descriptor)296 void mp4sys_remove_descriptor( void *opaque_descriptor )
297 {
298     if( !opaque_descriptor )
299         return;
300     mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
301     if( descriptor->parent )
302     {
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 )
306             {
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;
311             }
312     }
313     mp4sys_destruct_descriptor( descriptor );
314 }
315 
mp4sys_remove_DecoderSpecificInfo(mp4sys_DecoderSpecificInfo_t * dsi)316 static void mp4sys_remove_DecoderSpecificInfo( mp4sys_DecoderSpecificInfo_t *dsi )
317 {
318     if( !dsi )
319         return;
320     lsmash_free( dsi->data );
321     mp4sys_remove_predefined_descriptor( dsi, offsetof( mp4sys_DecoderConfigDescriptor_t, decSpecificInfo ) );
322 }
323 
mp4sys_remove_DecoderConfigDescriptor(mp4sys_DecoderConfigDescriptor_t * dcd)324 static void mp4sys_remove_DecoderConfigDescriptor( mp4sys_DecoderConfigDescriptor_t *dcd )
325 {
326     if( !dcd )
327         return;
328     mp4sys_remove_predefined_descriptor( dcd, offsetof( mp4sys_ES_Descriptor_t, decConfigDescr ) );
329 }
330 
mp4sys_remove_SLConfigDescriptor(mp4sys_SLConfigDescriptor_t * slcd)331 static void mp4sys_remove_SLConfigDescriptor( mp4sys_SLConfigDescriptor_t *slcd )
332 {
333     if( !slcd )
334         return;
335     mp4sys_remove_predefined_descriptor( slcd, offsetof( mp4sys_ES_Descriptor_t, slConfigDescr ) );
336 }
337 
mp4sys_remove_ES_Descriptor(mp4sys_ES_Descriptor_t * esd)338 static void mp4sys_remove_ES_Descriptor( mp4sys_ES_Descriptor_t *esd )
339 {
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 ) );
344 }
345 
mp4sys_remove_ES_ID_Inc(mp4sys_ES_ID_Inc_t * es_id_inc)346 static void mp4sys_remove_ES_ID_Inc( mp4sys_ES_ID_Inc_t *es_id_inc )
347 {
348     if( !es_id_inc )
349         return;
350     mp4sys_remove_descriptor_in_predefined_list( es_id_inc, offsetof( mp4sys_ObjectDescriptor_t, esDescr ) );
351 }
352 
mp4sys_remove_ObjectDescriptor(mp4sys_ObjectDescriptor_t * od)353 static void mp4sys_remove_ObjectDescriptor( mp4sys_ObjectDescriptor_t *od )
354 {
355 }
356 
mp4sys_get_descriptor_header_size(uint32_t payload_size_in_byte)357 static inline uint32_t mp4sys_get_descriptor_header_size( uint32_t payload_size_in_byte )
358 {
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
368 }
369 
370 /* returns total size of descriptor, including header, 2 at least */
mp4sys_get_descriptor_size(uint32_t payload_size_in_byte)371 static inline uint32_t mp4sys_get_descriptor_size( uint32_t payload_size_in_byte )
372 {
373     return payload_size_in_byte + mp4sys_get_descriptor_header_size( payload_size_in_byte );
374 }
375 
mp4sys_write_descriptor_header(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header)376 static inline void mp4sys_write_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
377 {
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 );
388     }
389 #endif
390     lsmash_bs_put_byte( bs, header->size & 0x7F );
391 }
392 
393 int mp4sys_write_descriptor( lsmash_bs_t *bs, void *opaque_descriptor );
394 
mp4sys_write_DecoderSpecificInfo(lsmash_bs_t * bs,mp4sys_DecoderSpecificInfo_t * dsi)395 static int mp4sys_write_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_DecoderSpecificInfo_t *dsi )
396 {
397     if( dsi->data && dsi->header.size != 0 )
398         lsmash_bs_put_bytes( bs, dsi->header.size, dsi->data );
399     return 0;
400 }
401 
mp4sys_write_DecoderConfigDescriptor(lsmash_bs_t * bs,mp4sys_DecoderConfigDescriptor_t * dcd)402 static int mp4sys_write_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_DecoderConfigDescriptor_t *dcd )
403 {
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;
415 }
416 
mp4sys_write_SLConfigDescriptor(lsmash_bs_t * bs,mp4sys_SLConfigDescriptor_t * slcd)417 static int mp4sys_write_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_SLConfigDescriptor_t *slcd )
418 {
419     lsmash_bs_put_byte( bs, slcd->predefined );
420     if( slcd->predefined == 0x00 )
421     {
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 );
444     }
445     if( slcd->durationFlag )
446     {
447         lsmash_bs_put_be32( bs, slcd->timeScale );
448         lsmash_bs_put_be16( bs, slcd->accessUnitDuration );
449         lsmash_bs_put_be16( bs, slcd->compositionUnitDuration );
450     }
451     if( !slcd->useTimeStampsFlag )
452     {
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 );
460     }
461     return 0;
462 }
463 
mp4sys_write_ES_Descriptor(lsmash_bs_t * bs,mp4sys_ES_Descriptor_t * esd)464 static int mp4sys_write_ES_Descriptor( lsmash_bs_t *bs, mp4sys_ES_Descriptor_t *esd )
465 {
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 )
476     {
477         lsmash_bs_put_byte( bs, esd->URLlength );
478         lsmash_bs_put_bytes( bs, esd->URLlength, esd->URLstring );
479     }
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;
484 }
485 
mp4sys_write_ES_ID_Inc(lsmash_bs_t * bs,mp4sys_ES_ID_Inc_t * es_id_inc)486 static int mp4sys_write_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_ES_ID_Inc_t *es_id_inc )
487 {
488     lsmash_bs_put_be32( bs, es_id_inc->Track_ID );
489     return 0;
490 }
491 
mp4sys_write_ObjectDescriptor(lsmash_bs_t * bs,mp4sys_ObjectDescriptor_t * od)492 static int mp4sys_write_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_ObjectDescriptor_t *od )
493 {
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 )
501     {
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 );
507     }
508     return 0;
509 }
510 
mp4sys_write_children(lsmash_bs_t * bs,mp4sys_descriptor_t * descriptor)511 static int mp4sys_write_children( lsmash_bs_t *bs, mp4sys_descriptor_t *descriptor )
512 {
513     for( lsmash_entry_t *entry = descriptor->children.head; entry; entry = entry->next )
514     {
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;
521     }
522     return 0;
523 }
524 
mp4sys_write_descriptor(lsmash_bs_t * bs,void * opaque_descriptor)525 int mp4sys_write_descriptor( lsmash_bs_t *bs, void *opaque_descriptor )
526 {
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 );
537 }
538 
539 /* descriptor size updater */
mp4sys_update_descriptor_size(void * opaque_descriptor)540 uint32_t mp4sys_update_descriptor_size( void *opaque_descriptor )
541 {
542     assert( opaque_descriptor );
543     mp4sys_descriptor_t *descriptor = (mp4sys_descriptor_t *)opaque_descriptor;
544     uint64_t size = 0;
545     if( descriptor->write )
546     {
547         uint32_t header_size = descriptor->header.size;
548         /* Calculate the size of this descriptor excluding its children with a fake bytestream writer. */
549         {
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 );
554         }
555         /* Calculate the size including the children if no error. */
556         if( size >= mp4sys_get_descriptor_header_size( header_size ) )
557         {
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 );
566         }
567         else
568         {
569             /* Invalid descriptor */
570             descriptor->header.size = 0;
571             size = 0;
572         }
573     }
574     else
575         descriptor->header.size = 0;
576     return size;
577 }
578 
mp4sys_construct_descriptor_orig(size_t size,mp4sys_descriptor_t * parent,mp4sys_descriptor_destructor_t destructor,mp4sys_descriptor_writer_t writer)579 static inline void *mp4sys_construct_descriptor_orig
580 (
581     size_t                         size,
582     mp4sys_descriptor_t           *parent,
583     mp4sys_descriptor_destructor_t destructor,
584     mp4sys_descriptor_writer_t     writer
585 )
586 {
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;
597 }
598 
599 #define mp4sys_construct_descriptor( size, parent, destructor, writer ) \
600         mp4sys_construct_descriptor_orig                                \
601         (                                                               \
602             size,                                                       \
603             (mp4sys_descriptor_t *)parent,                              \
604             (mp4sys_descriptor_destructor_t)destructor,                 \
605             (mp4sys_descriptor_writer_t)writer                          \
606         )
607 
608 #define MP4SYS_CONSTRUCT_DESCRIPTOR( var, descriptor_name, parent, ret ) \
609         mp4sys_##descriptor_name##_t *var =                              \
610             mp4sys_construct_descriptor                                  \
611             (                                                            \
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
619 
mp4sys_add_DecoderSpecificInfo(mp4sys_DecoderConfigDescriptor_t * dcd)620 static mp4sys_DecoderSpecificInfo_t *mp4sys_add_DecoderSpecificInfo( mp4sys_DecoderConfigDescriptor_t *dcd )
621 {
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 )
627     {
628         mp4sys_remove_descriptor( dsi );
629         return NULL;
630     }
631     dcd->decSpecificInfo = dsi;
632     return dsi;
633 }
634 
635 /*
636     bufferSizeDB is byte unit, NOT bit unit.
637     avgBitrate is 0 if VBR
638 */
mp4sys_add_DecoderConfigDescriptor(mp4sys_ES_Descriptor_t * esd)639 static mp4sys_DecoderConfigDescriptor_t *mp4sys_add_DecoderConfigDescriptor
640 (
641     mp4sys_ES_Descriptor_t *esd
642 )
643 {
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 )
649     {
650         mp4sys_remove_descriptor( dcd );
651         return NULL;
652     }
653     esd->decConfigDescr = dcd;
654     return dcd;
655 }
656 
mp4sys_add_SLConfigDescriptor(mp4sys_ES_Descriptor_t * esd)657 static mp4sys_SLConfigDescriptor_t *mp4sys_add_SLConfigDescriptor( mp4sys_ES_Descriptor_t *esd )
658 {
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 )
664     {
665         mp4sys_remove_descriptor( slcd );
666         return NULL;
667     }
668     esd->slConfigDescr = slcd;
669     return slcd;
670 }
671 
672 /* NOTE: This is only for MP4_IOD and MP4_OD, not for ISO Base Media's ObjectDescriptor and InitialObjectDescriptor */
mp4sys_add_ES_ID_Inc(mp4sys_ObjectDescriptor_t * od)673 static mp4sys_ES_ID_Inc_t *mp4sys_add_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od )
674 {
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 )
682     {
683         mp4sys_remove_descriptor( es_id_inc );
684         return NULL;
685     }
686     if( lsmash_list_add_entry( &od->esDescr, es_id_inc ) < 0 )
687     {
688         lsmash_list_remove_entry_tail( &od->children );
689         return NULL;
690     }
691     return es_id_inc;
692 }
693 
mp4sys_create_ES_ID_Inc(mp4sys_ObjectDescriptor_t * od,uint32_t Track_ID)694 int mp4sys_create_ES_ID_Inc( mp4sys_ObjectDescriptor_t *od, uint32_t Track_ID )
695 {
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;
701 }
702 
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. */
mp4sys_create_ES_Descriptor(uint16_t ES_ID)705 mp4sys_ES_Descriptor_t *mp4sys_create_ES_Descriptor( uint16_t ES_ID )
706 {
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;
711 }
712 
713 /* NOTE: This is only for MP4_OD, not for ISO Base Media's ObjectDescriptor */
mp4sys_create_ObjectDescriptor(uint16_t ObjectDescriptorID)714 mp4sys_ObjectDescriptor_t *mp4sys_create_ObjectDescriptor( uint16_t ObjectDescriptorID )
715 {
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;
726 }
727 
728 /* NOTE: This is only for MP4_IOD, not for Iso Base Media's InitialObjectDescriptor */
mp4sys_to_InitialObjectDescriptor(mp4sys_ObjectDescriptor_t * od,uint8_t include_inline_pli,mp4sys_ODProfileLevelIndication od_pli,mp4sys_sceneProfileLevelIndication scene_pli,mp4a_audioProfileLevelIndication audio_pli,mp4sys_visualProfileLevelIndication visual_pli,mp4sys_graphicsProfileLevelIndication graph_pli)729 int mp4sys_to_InitialObjectDescriptor
730 (
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
738 )
739 {
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;
750 }
751 
752 /*
753     bufferSizeDB is byte unit, NOT bit unit.
754     avgBitrate is 0 if VBR
755 */
mp4sys_update_DecoderConfigDescriptor(mp4sys_ES_Descriptor_t * esd,uint32_t bufferSizeDB,uint32_t maxBitrate,uint32_t avgBitrate)756 int mp4sys_update_DecoderConfigDescriptor( mp4sys_ES_Descriptor_t *esd, uint32_t bufferSizeDB, uint32_t maxBitrate, uint32_t avgBitrate )
757 {
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;
765 }
766 
767 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent );
768 
mp4sys_print_descriptor_header(FILE * fp,mp4sys_descriptor_head_t * header,int indent)769 static void mp4sys_print_descriptor_header( FILE *fp, mp4sys_descriptor_head_t *header, int indent )
770 {
771     static const char *descriptor_names_table[256] =
772         {
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"
784         };
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 );
790 }
791 
mp4sys_print_DecoderSpecificInfo(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)792 static void mp4sys_print_DecoderSpecificInfo( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
793 {
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 );
803 }
804 
mp4sys_print_DecoderConfigDescriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)805 static void mp4sys_print_DecoderConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
806 {
807     mp4sys_DecoderConfigDescriptor_t *dcd = (mp4sys_DecoderConfigDescriptor_t *)descriptor;
808     static const char *object_type_indication_descriptions_table[256] =
809         {
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"
855         };
856     static const char *stream_type_descriptions_table[64] =
857         {
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"
872         };
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)" );
886 }
887 
mp4sys_print_SLConfigDescriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)888 static void mp4sys_print_SLConfigDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
889 {
890     mp4sys_SLConfigDescriptor_t *slcd = (mp4sys_SLConfigDescriptor_t *)descriptor;
891     lsmash_ifprintf( fp, indent, "predefined = %"PRIu8"\n", slcd->predefined );
892     if( slcd->predefined == 0 )
893     {
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 );
912     }
913     if( slcd->durationFlag )
914     {
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 );
918     }
919     if( !slcd->useTimeStampsFlag )
920     {
921         lsmash_ifprintf( fp, indent, "startDecodingTimeStamp = %"PRIu64"\n", slcd->startDecodingTimeStamp );
922         lsmash_ifprintf( fp, indent, "startCompositionTimeStamp = %"PRIu64"\n", slcd->startCompositionTimeStamp );
923     }
924 }
925 
mp4sys_print_ES_Descriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)926 static void mp4sys_print_ES_Descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
927 {
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 )
937     {
938         lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", esd->URLlength );
939         lsmash_ifprintf( fp, indent, "URLstring = %s\n", esd->URLstring );
940     }
941     if( esd->OCRstreamFlag )
942         lsmash_ifprintf( fp, indent, "OCR_ES_Id = %"PRIu16"\n", esd->OCR_ES_Id );
943 }
944 
mp4sys_print_ES_ID_Inc(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)945 static void mp4sys_print_ES_ID_Inc( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
946 {
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 );
949 }
950 
mp4sys_print_ObjectDescriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)951 static void mp4sys_print_ObjectDescriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
952 {
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 )
958     {
959         lsmash_ifprintf( fp, indent, "includeInlineProfileLevelFlag = %"PRIu8"\n", od->includeInlineProfileLevelFlag );
960         lsmash_ifprintf( fp, indent, "reserved = 0x%01"PRIx8"\n", od->reserved );
961     }
962     else
963         lsmash_ifprintf( fp, indent, "reserved = 0x%02"PRIx8"\n", od->reserved | (od->includeInlineProfileLevelFlag << 4) );
964     if( od->URL_Flag )
965     {
966         lsmash_ifprintf( fp, indent, "URLlength = %"PRIu8"\n", od->URLlength );
967         lsmash_ifprintf( fp, indent, "URLstring = %s\n", od->URLstring );
968     }
969     else
970     {
971         if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
972          || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
973         {
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 );
979         }
980     }
981 }
982 
mp4sys_print_descriptor(FILE * fp,mp4sys_descriptor_t * descriptor,int indent)983 void mp4sys_print_descriptor( FILE *fp, mp4sys_descriptor_t *descriptor, int indent )
984 {
985     if( !descriptor )
986         return;
987     mp4sys_print_descriptor_header( fp, &descriptor->header, indent++ );
988     switch( descriptor->header.tag )
989     {
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;
1013     }
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 );
1017 }
1018 
mp4sys_print_codec_specific(FILE * fp,lsmash_file_t * file,isom_box_t * box,int level)1019 int mp4sys_print_codec_specific( FILE *fp, lsmash_file_t *file, isom_box_t *box, int level )
1020 {
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;
1031 }
1032 
1033 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent );
1034 
mp4sys_get_descriptor_header(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header)1035 static void mp4sys_get_descriptor_header( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header )
1036 {
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 )
1042     {
1043         temp = lsmash_bs_get_byte( bs );
1044         nextByte = temp & 0x80;
1045         sizeOfInstance = (sizeOfInstance << 7) | (temp & 0x7F);
1046     }
1047     header->size = sizeOfInstance;
1048 }
1049 
mp4sys_get_DecoderSpecificInfo(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1050 static mp4sys_DecoderSpecificInfo_t *mp4sys_get_DecoderSpecificInfo( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1051 {
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 )
1057     {
1058         dsi->data = lsmash_bs_get_bytes( bs, dsi->header.size );
1059         if( !dsi->data )
1060         {
1061             mp4sys_remove_descriptor( dsi );
1062             return NULL;
1063         }
1064     }
1065     return dsi;
1066 }
1067 
mp4sys_get_DecoderConfigDescriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1068 static mp4sys_DecoderConfigDescriptor_t *mp4sys_get_DecoderConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1069 {
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 )
1084     {
1085         mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, dcd );
1086         if( desc )
1087         {
1088             if( desc->header.tag == MP4SYS_DESCRIPTOR_TAG_DecSpecificInfoTag )
1089                 dcd->decSpecificInfo = (mp4sys_DecoderSpecificInfo_t *)desc;
1090             else
1091                 mp4sys_remove_descriptor( desc );
1092         }
1093         else
1094             break;
1095     }
1096     return dcd;
1097 }
1098 
mp4sys_get_SLConfigDescriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1099 static mp4sys_SLConfigDescriptor_t *mp4sys_get_SLConfigDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1100 {
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 )
1107     {
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;
1128     }
1129     else if( slcd->predefined == 0x01 )
1130     {
1131         slcd->timeStampResolution  = 1000;
1132         slcd->timeStampLength      = 32;
1133     }
1134     else if( slcd->predefined == 0x02 )
1135         slcd->useTimeStampsFlag = 1;
1136     if( slcd->durationFlag )
1137     {
1138         slcd->timeScale               = lsmash_bs_get_be32( bs );
1139         slcd->accessUnitDuration      = lsmash_bs_get_be16( bs );
1140         slcd->compositionUnitDuration = lsmash_bs_get_be16( bs );
1141     }
1142     if( !slcd->useTimeStampsFlag )
1143     {
1144         lsmash_bits_t *bits = lsmash_bits_create( bs );
1145         if( !bits )
1146         {
1147             mp4sys_remove_descriptor( slcd );
1148             return NULL;
1149         }
1150         slcd->startDecodingTimeStamp    = lsmash_bits_get( bits, slcd->timeStampLength );
1151         slcd->startCompositionTimeStamp = lsmash_bits_get( bits, slcd->timeStampLength );
1152         lsmash_bits_cleanup( bits );
1153     }
1154     return slcd;
1155 }
1156 
mp4sys_get_ES_Descriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1157 static mp4sys_ES_Descriptor_t *mp4sys_get_ES_Descriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1158 {
1159     MP4SYS_CONSTRUCT_DESCRIPTOR( esd, ES_Descriptor, parent, NULL );
1160     if( parent && lsmash_list_add_entry( &((mp4sys_descriptor_t *)parent)->children, esd ) < 0 )
1161     {
1162         mp4sys_remove_descriptor( esd );
1163         return NULL;
1164     }
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 )
1176     {
1177         size_t length = lsmash_bs_get_byte( bs );
1178         lsmash_bs_read_data( bs, (uint8_t *)esd->URLstring, &length );
1179         esd->URLlength = length;
1180     }
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 )
1185     {
1186         mp4sys_descriptor_t *desc = mp4sys_get_descriptor( bs, esd );
1187         if( desc )
1188         {
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 );
1195         }
1196         else
1197             break;
1198     }
1199     if( !esd->decConfigDescr || !esd->slConfigDescr )
1200     {
1201         mp4sys_remove_descriptor( esd );
1202         return NULL;
1203     }
1204     return esd;
1205 }
1206 
mp4sys_get_ES_ID_Inc(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1207 static mp4sys_ES_ID_Inc_t *mp4sys_get_ES_ID_Inc( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1208 {
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;
1215 }
1216 
mp4sys_get_ObjectDescriptor(lsmash_bs_t * bs,mp4sys_descriptor_head_t * header,void * parent)1217 static mp4sys_ObjectDescriptor_t *mp4sys_get_ObjectDescriptor( lsmash_bs_t *bs, mp4sys_descriptor_head_t *header, void *parent )
1218 {
1219     MP4SYS_CONSTRUCT_DESCRIPTOR( od, ObjectDescriptor, parent, NULL );
1220     if( parent && lsmash_list_add_entry( &((mp4sys_descriptor_t *)parent)->children, od ) < 0 )
1221     {
1222         mp4sys_remove_descriptor( od );
1223         return NULL;
1224     }
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 )
1233     {
1234         size_t length = lsmash_bs_get_byte( bs );
1235         lsmash_bs_read_data( bs, (uint8_t *)od->URLstring, &length );
1236         od->URLlength = length;
1237     }
1238     else
1239     {
1240         if( od->header.tag == MP4SYS_DESCRIPTOR_TAG_InitialObjectDescrTag
1241          || od->header.tag == MP4SYS_DESCRIPTOR_TAG_MP4_IOD_Tag )
1242         {
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 );
1248         }
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 )
1255         {
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 )
1260             {
1261                 mp4sys_remove_descriptor( desc );
1262                 break;
1263             }
1264         }
1265     }
1266     return od;
1267 }
1268 
mp4sys_get_descriptor(lsmash_bs_t * bs,void * parent)1269 mp4sys_descriptor_t *mp4sys_get_descriptor( lsmash_bs_t *bs, void *parent )
1270 {
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 )
1276     {
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 )
1301             {
1302                 desc->parent = parent;
1303                 desc->header = header;
1304             }
1305             break;
1306     }
1307     /* Skip extra bytes if present. */
1308     uint64_t skip_bytes = end_pos - lsmash_bs_count( bs );
1309     if( skip_bytes )
1310     {
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 )
1313         {
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;
1319         }
1320         else
1321             /* The stream is unseekable. So, skip by reading the stream. */
1322             lsmash_bs_skip_bytes_64( bs, skip_bytes );
1323     }
1324     return desc;
1325 }
1326 
mp4sys_export_DecoderSpecificInfo(mp4sys_ES_Descriptor_t * esd,uint32_t * dsi_payload_length)1327 static uint8_t *mp4sys_export_DecoderSpecificInfo( mp4sys_ES_Descriptor_t *esd, uint32_t *dsi_payload_length )
1328 {
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 )
1335     {
1336         dsi_payload = lsmash_memdup( dsi->data, dsi->header.size );
1337         if( !dsi_payload )
1338             return NULL;
1339     }
1340     if( dsi_payload_length )
1341         *dsi_payload_length = dsi->header.size;
1342     return dsi_payload;
1343 }
1344 
1345 /* Sumamry is needed to decide ProfileLevelIndication.
1346  * Currently, support audio's only. */
mp4sys_setup_summary_from_DecoderSpecificInfo(lsmash_audio_summary_t * summary,mp4sys_ES_Descriptor_t * esd)1347 int mp4sys_setup_summary_from_DecoderSpecificInfo( lsmash_audio_summary_t *summary, mp4sys_ES_Descriptor_t *esd )
1348 {
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 )
1355     {
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 )
1359         {
1360             err = LSMASH_ERR_MEMORY_ALLOC;
1361             goto fail;
1362         }
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 )
1373         {
1374             lsmash_destroy_codec_specific_data( cs );
1375             goto fail;
1376         }
1377     }
1378 fail:
1379     lsmash_free( dsi_payload );
1380     return err;
1381 }
1382 
1383 /**** following functions are for facilitation purpose ****/
1384 
mp4sys_setup_ES_Descriptor(mp4sys_ES_Descriptor_params_t * params)1385 mp4sys_ES_Descriptor_t *mp4sys_setup_ES_Descriptor( mp4sys_ES_Descriptor_params_t *params )
1386 {
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 )
1405     {
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;
1413     }
1414     /* SLConfigDescriptor */
1415     {
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 */
1421     }
1422     return esd;
1423 fail:
1424     mp4sys_remove_descriptor( esd );
1425     return NULL;
1426 }
1427 
lsmash_set_mp4sys_decoder_specific_info(lsmash_mp4sys_decoder_parameters_t * param,uint8_t * payload,uint32_t payload_length)1428 int lsmash_set_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t *payload, uint32_t payload_length )
1429 {
1430     if( !param || !payload || payload_length == 0 )
1431         return LSMASH_ERR_FUNCTION_PARAM;
1432     if( !param->dsi )
1433     {
1434         param->dsi = lsmash_malloc_zero( sizeof(lsmash_mp4sys_decoder_specific_info_t) );
1435         if( !param->dsi )
1436             return LSMASH_ERR_MEMORY_ALLOC;
1437     }
1438     else
1439     {
1440         lsmash_freep( &param->dsi->payload );
1441         param->dsi->payload_length = 0;
1442     }
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;
1448 }
1449 
lsmash_destroy_mp4sys_decoder_specific_info(lsmash_mp4sys_decoder_parameters_t * param)1450 void lsmash_destroy_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param )
1451 {
1452     if( !param || !param->dsi )
1453         return;
1454     lsmash_free( param->dsi->payload );
1455     lsmash_freep( &param->dsi );
1456 }
1457 
mp4sys_destruct_decoder_config(void * data)1458 void mp4sys_destruct_decoder_config( void *data )
1459 {
1460     if( !data )
1461         return;
1462     lsmash_destroy_mp4sys_decoder_specific_info( data );
1463     lsmash_free( data );
1464 }
1465 
lsmash_create_mp4sys_decoder_config(lsmash_mp4sys_decoder_parameters_t * param,uint32_t * data_length)1466 uint8_t *lsmash_create_mp4sys_decoder_config( lsmash_mp4sys_decoder_parameters_t *param, uint32_t *data_length )
1467 {
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 )
1480     {
1481         esd_param.dsi_payload        = param->dsi->payload;
1482         esd_param.dsi_payload_length = param->dsi->payload_length;
1483     }
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 )
1489     {
1490         mp4sys_remove_descriptor( esd );
1491         return NULL;
1492     }
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;
1506 }
1507 
mp4sys_construct_decoder_config(lsmash_codec_specific_t * dst,lsmash_codec_specific_t * src)1508 int mp4sys_construct_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1509 {
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 )
1518     {
1519         size = LSMASH_GET_BE64( data );
1520         data += 8;
1521     }
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 )
1530     {
1531         lsmash_bs_cleanup( bs );
1532         return err;
1533     }
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 )
1549     {
1550         mp4sys_remove_descriptor( esd );
1551         return err;
1552     }
1553     mp4sys_remove_descriptor( esd );
1554     return 0;
1555 }
1556 
mp4sys_copy_decoder_config(lsmash_codec_specific_t * dst,lsmash_codec_specific_t * src)1557 int mp4sys_copy_decoder_config( lsmash_codec_specific_t *dst, lsmash_codec_specific_t *src )
1558 {
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 );
1569 }
1570 
lsmash_mp4sys_get_object_type_indication(lsmash_summary_t * summary)1571 lsmash_mp4sys_object_type_indication lsmash_mp4sys_get_object_type_indication( lsmash_summary_t *summary )
1572 {
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
1584     {
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 );
1590     }
1591     return objectTypeIndication;
1592 }
1593 
lsmash_get_mp4sys_decoder_specific_info(lsmash_mp4sys_decoder_parameters_t * param,uint8_t ** payload,uint32_t * payload_length)1594 int lsmash_get_mp4sys_decoder_specific_info( lsmash_mp4sys_decoder_parameters_t *param, uint8_t **payload, uint32_t *payload_length )
1595 {
1596     if( !param || !payload || !payload_length )
1597         return LSMASH_ERR_FUNCTION_PARAM;
1598     if( !param->dsi || !param->dsi->payload || param->dsi->payload_length == 0 )
1599     {
1600         *payload = NULL;
1601         *payload_length = 0;
1602         return 0;
1603     }
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;
1610 }
1611