1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2012-2017 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "common/internal.h" /* must be placed first */
31 #define ALAC_SPECIFIC_BOX_LENGTH 36
33 uint8_t *lsmash_create_alac_specific_info( lsmash_alac_specific_parameters_t
*param
, uint32_t *data_length
)
35 uint8_t buffer
[ALAC_SPECIFIC_BOX_LENGTH
];
36 lsmash_bs_t bs
= { 0 };
37 bs
.buffer
.data
= buffer
;
38 bs
.buffer
.alloc
= ALAC_SPECIFIC_BOX_LENGTH
;
39 lsmash_bs_put_be32( &bs
, ALAC_SPECIFIC_BOX_LENGTH
); /* box size */
40 lsmash_bs_put_be32( &bs
, ISOM_BOX_TYPE_ALAC
.fourcc
); /* box type: 'alac' */
41 lsmash_bs_put_be32( &bs
, 0 ); /* version + flags */
42 lsmash_bs_put_be32( &bs
, param
->frameLength
);
43 lsmash_bs_put_byte( &bs
, 0 ); /* compatibleVersion */
44 lsmash_bs_put_byte( &bs
, param
->bitDepth
);
45 lsmash_bs_put_byte( &bs
, 40 ); /* pb */
46 lsmash_bs_put_byte( &bs
, 14 ); /* mb */
47 lsmash_bs_put_byte( &bs
, 10 ); /* kb */
48 lsmash_bs_put_byte( &bs
, param
->numChannels
);
49 lsmash_bs_put_be16( &bs
, 255 ); /* maxRun */
50 lsmash_bs_put_be32( &bs
, param
->maxFrameBytes
);
51 lsmash_bs_put_be32( &bs
, param
->avgBitrate
);
52 lsmash_bs_put_be32( &bs
, param
->sampleRate
);
53 return lsmash_bs_export_data( &bs
, data_length
);
56 int alac_construct_specific_parameters( lsmash_codec_specific_t
*dst
, lsmash_codec_specific_t
*src
)
58 assert( dst
&& dst
->data
.structured
&& src
&& src
->data
.unstructured
);
59 if( src
->size
< ALAC_SPECIFIC_BOX_LENGTH
)
60 return LSMASH_ERR_INVALID_DATA
;
61 lsmash_alac_specific_parameters_t
*param
= (lsmash_alac_specific_parameters_t
*)dst
->data
.structured
;
62 uint8_t *data
= src
->data
.unstructured
;
63 uint64_t size
= LSMASH_GET_BE32( data
);
64 data
+= ISOM_BASEBOX_COMMON_SIZE
;
67 size
= LSMASH_GET_BE64( data
);
70 if( size
!= src
->size
)
71 return LSMASH_ERR_INVALID_DATA
;
72 data
+= 4; /* Skip version and flags. */
73 param
->frameLength
= LSMASH_GET_BE32( &data
[0] );
74 param
->bitDepth
= LSMASH_GET_BYTE( &data
[5] );
75 param
->numChannels
= LSMASH_GET_BYTE( &data
[9] );
76 param
->maxFrameBytes
= LSMASH_GET_BE32( &data
[12] );
77 param
->avgBitrate
= LSMASH_GET_BE32( &data
[16] );
78 param
->sampleRate
= LSMASH_GET_BE32( &data
[20] );
82 int alac_print_codec_specific( FILE *fp
, lsmash_file_t
*file
, isom_box_t
*box
, int level
)
84 assert( box
->manager
& LSMASH_BINARY_CODED_BOX
);
86 lsmash_ifprintf( fp
, indent
++, "[%s: ALAC Specific Box]\n", isom_4cc2str( box
->type
.fourcc
) );
87 lsmash_ifprintf( fp
, indent
, "position = %"PRIu64
"\n", box
->pos
);
88 lsmash_ifprintf( fp
, indent
, "size = %"PRIu64
"\n", box
->size
);
89 if( box
->size
< ALAC_SPECIFIC_BOX_LENGTH
)
90 return LSMASH_ERR_INVALID_DATA
;
91 uint8_t *data
= box
->binary
;
92 isom_skip_box_common( &data
);
93 lsmash_ifprintf( fp
, indent
, "version = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[0] ) );
94 lsmash_ifprintf( fp
, indent
, "flags = 0x%06"PRIx32
"\n", LSMASH_GET_BE24( &data
[1] ) );
96 lsmash_ifprintf( fp
, indent
, "frameLength = %"PRIu32
"\n", LSMASH_GET_BE32( &data
[0] ) );
97 lsmash_ifprintf( fp
, indent
, "compatibleVersion = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[4] ) );
98 lsmash_ifprintf( fp
, indent
, "bitDepth = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[5] ) );
99 lsmash_ifprintf( fp
, indent
, "pb = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[6] ) );
100 lsmash_ifprintf( fp
, indent
, "mb = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[7] ) );
101 lsmash_ifprintf( fp
, indent
, "kb = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[8] ) );
102 lsmash_ifprintf( fp
, indent
, "numChannels = %"PRIu8
"\n", LSMASH_GET_BYTE( &data
[9] ) );
103 lsmash_ifprintf( fp
, indent
, "maxRun = %"PRIu16
"\n", LSMASH_GET_BE16( &data
[10] ) );
104 lsmash_ifprintf( fp
, indent
, "maxFrameBytes = %"PRIu32
"\n", LSMASH_GET_BE32( &data
[12] ) );
105 lsmash_ifprintf( fp
, indent
, "avgBitrate = %"PRIu32
"\n", LSMASH_GET_BE32( &data
[16] ) );
106 lsmash_ifprintf( fp
, indent
, "sampleRate = %"PRIu32
"\n", LSMASH_GET_BE32( &data
[20] ) );
110 int alac_update_bitrate( isom_stbl_t
*stbl
, isom_mdhd_t
*mdhd
, uint32_t sample_description_index
)
112 isom_audio_entry_t
*alac
= (isom_audio_entry_t
*)lsmash_get_entry_data( &stbl
->stsd
->list
, sample_description_index
);
113 if( LSMASH_IS_NON_EXISTING_BOX( alac
) )
114 return LSMASH_ERR_INVALID_DATA
;
115 uint8_t *exdata
= NULL
;
116 uint32_t exdata_size
= 0;
117 isom_box_t
*alac_ext
= isom_get_extension_box( &alac
->extensions
, QT_BOX_TYPE_WAVE
);
118 if( LSMASH_IS_EXISTING_BOX( alac_ext
) )
120 /* Apple Lossless Audio inside QuickTime file format
121 * Though average bitrate field we found is always set to 0 apparently,
122 * we set up maxFrameBytes and avgBitRate fields. */
123 if( alac_ext
->manager
& LSMASH_BINARY_CODED_BOX
)
124 exdata
= isom_get_child_box_position( alac_ext
->binary
, alac_ext
->size
, QT_BOX_TYPE_ALAC
, &exdata_size
);
127 isom_wave_t
*wave
= (isom_wave_t
*)alac_ext
;
128 isom_box_t
*wave_ext
= isom_get_extension_box( &wave
->extensions
, QT_BOX_TYPE_ALAC
);
129 if( !(wave_ext
->manager
& LSMASH_BINARY_CODED_BOX
) )
130 return LSMASH_ERR_INVALID_DATA
;
131 exdata
= wave_ext
->binary
;
132 exdata_size
= wave_ext
->size
;
137 /* Apple Lossless Audio inside ISO Base Media file format */
138 isom_box_t
*ext
= isom_get_extension_box( &alac
->extensions
, ISOM_BOX_TYPE_ALAC
);
139 if( !(ext
->manager
& LSMASH_BINARY_CODED_BOX
) )
140 return LSMASH_ERR_INVALID_DATA
;
141 exdata
= ext
->binary
;
142 exdata_size
= ext
->size
;
144 if( !exdata
|| exdata_size
< 36 )
145 return LSMASH_ERR_INVALID_DATA
;
146 uint32_t bufferSizeDB
;
149 int err
= isom_calculate_bitrate_description( stbl
, mdhd
, &bufferSizeDB
, &maxBitrate
, &avgBitrate
, sample_description_index
);
154 LSMASH_SET_BE32( &exdata
[0], bufferSizeDB
);
156 LSMASH_SET_BE32( &exdata
[4], avgBitrate
);
160 #undef ALAC_SPECIFIC_BOX_LENGTH