1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2010-2015 L-SMASH project
6 * Authors: Takashi Hirata <silverfilain@gmail.com>
7 * Contributors: 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 */
28 #define LSMASH_IMPORTER_INTERNAL
31 /***************************************************************************
32 AMR-NB/WB storage format importer
33 3GPP TS 26.101 V11.0.0 (2012-9)
34 3GPP TS 26.201 V11.0.0 (2012-9)
35 3GPP TS 26.244 V12.3.0 (2014-03)
36 http://www.ietf.org/rfc/rfc3267.txt (Obsoleted)
37 http://www.ietf.org/rfc/rfc4867.txt
38 ***************************************************************************/
41 int wb
; /* 0: AMR-NB, 1: AMR-WB */
42 uint32_t samples_in_frame
;
46 static void remove_amr_importer
48 amr_importer_t
*amr_imp
51 lsmash_free( amr_imp
);
54 static amr_importer_t
*create_amr_importer
59 return (amr_importer_t
*)lsmash_malloc_zero( sizeof(amr_importer_t
) );
62 static void amr_cleanup
67 debug_if( importer
&& importer
->info
)
68 remove_amr_importer( importer
->info
);
71 static int amr_get_accessunit
74 uint32_t track_number
,
75 lsmash_sample_t
**p_sample
79 return LSMASH_ERR_NAMELESS
;
80 if( track_number
!= 1 )
81 return LSMASH_ERR_FUNCTION_PARAM
;
82 amr_importer_t
*amr_imp
= (amr_importer_t
*)importer
->info
;
83 lsmash_bs_t
*bs
= importer
->bs
;
84 if( importer
->status
== IMPORTER_EOF
|| lsmash_bs_is_end( bs
, 0 ) )
87 importer
->status
= IMPORTER_EOF
;
90 /* Each speech frame consists of one speech frame header and one speech data.
91 * At the end of each speech data, octet alignment if needed.
97 * FT: Frame type index
98 * Q : Frame quality indicator
99 * P : Must be set to 0
100 * FT= 9, 10 and 11 for AMR-NB shall not be used in the file format.
101 * FT=12, 13 and 14 for AMR-NB are not defined yet in the file format.
102 * FT=10, 11, 12 and 13 for AMR-WB are not defined yet in the file format.
103 * FT determines the size of the speech frame starting with it.
105 uint8_t FT
= (lsmash_bs_show_byte( bs
, 0 ) >> 3) & 0x0F;
106 const int frame_size
[2][16] =
108 { 13, 14, 16, 18, 20, 21, 27, 32, 6, -1, -1, -1, 0, 0, 0, 1 },
109 { 18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 0, 0, 0, 0, 1, 1 }
111 int read_size
= frame_size
[ amr_imp
->wb
][FT
];
114 lsmash_log( importer
, LSMASH_LOG_ERROR
, "an %s speech frame is detected.\n", read_size
< 0 ? "invalid" : "unknown" );
115 importer
->status
= IMPORTER_ERROR
;
116 return read_size
< 0 ? LSMASH_ERR_INVALID_DATA
: LSMASH_ERR_NAMELESS
;
118 lsmash_sample_t
*sample
= lsmash_create_sample( read_size
);
120 return LSMASH_ERR_MEMORY_ALLOC
;
122 if( lsmash_bs_get_bytes_ex( bs
, read_size
, sample
->data
) != read_size
)
124 lsmash_log( importer
, LSMASH_LOG_WARNING
, "the stream is truncated at the end.\n" );
125 importer
->status
= IMPORTER_EOF
;
126 return LSMASH_ERR_INVALID_DATA
;
128 sample
->length
= read_size
;
129 sample
->dts
= amr_imp
->au_number
++ * amr_imp
->samples_in_frame
;
130 sample
->cts
= sample
->dts
;
131 sample
->prop
.ra_flags
= ISOM_SAMPLE_RANDOM_ACCESS_FLAG_SYNC
;
135 static int amr_check_magic_number
140 #define AMR_STORAGE_MAGIC_LENGTH 6
141 #define AMR_AMRWB_EX_MAGIC_LENGTH 3
142 /* Check the magic number for single-channel AMR-NB/AMR-WB files.
143 * For AMR-NB, "#!AMR\n" (or 0x2321414d520a in hexadecimal).
144 * For AMR-WB, "#!AMR-WB\n" (or 0x2321414d522d57420a in hexadecimal).
145 * Note that AMR-NB and AMR-WB data is stored in the 3GPP/3GPP2 file format according to
146 * the AMR-NB and AMR-WB storage format for single channel header without the AMR magic numbers. */
147 uint8_t buf
[AMR_STORAGE_MAGIC_LENGTH
];
148 if( lsmash_bs_get_bytes_ex( bs
, AMR_STORAGE_MAGIC_LENGTH
, buf
) != AMR_STORAGE_MAGIC_LENGTH
149 || memcmp( buf
, "#!AMR", AMR_STORAGE_MAGIC_LENGTH
- 1 ) )
150 return LSMASH_ERR_INVALID_DATA
;
151 if( buf
[AMR_STORAGE_MAGIC_LENGTH
- 1] == '\n' )
152 /* single-channel AMR-NB file */
154 if( buf
[AMR_STORAGE_MAGIC_LENGTH
- 1] != '-'
155 || lsmash_bs_get_bytes_ex( bs
, AMR_AMRWB_EX_MAGIC_LENGTH
, buf
) != AMR_AMRWB_EX_MAGIC_LENGTH
156 || memcmp( buf
, "WB\n", AMR_AMRWB_EX_MAGIC_LENGTH
) )
157 return LSMASH_ERR_INVALID_DATA
;
158 /* single-channel AMR-WB file */
160 #undef AMR_STORAGE_MAGIC_LENGTH
161 #undef AMR_AMRWB_EX_MAGIC_LENGTH
164 static int amr_create_damr
166 lsmash_audio_summary_t
*summary
,
170 #define AMR_DAMR_LENGTH 17
171 lsmash_bs_t
*bs
= lsmash_bs_create();
173 return LSMASH_ERR_MEMORY_ALLOC
;
174 lsmash_bs_put_be32( bs
, AMR_DAMR_LENGTH
);
175 lsmash_bs_put_be32( bs
, ISOM_BOX_TYPE_DAMR
.fourcc
);
176 /* NOTE: These are specific to each codec vendor, but we're surely not a vendor.
177 * Using dummy data. */
178 lsmash_bs_put_be32( bs
, 0x20202020 ); /* vendor */
179 lsmash_bs_put_byte( bs
, 0 ); /* decoder_version */
180 /* NOTE: Using safe value for these settings, maybe sub-optimal. */
181 lsmash_bs_put_be16( bs
, wb
? 0xC3FF : 0x81FF ); /* mode_set, represents for all possibly existing and supported frame-types. */
182 lsmash_bs_put_byte( bs
, 1 ); /* mode_change_period */
183 lsmash_bs_put_byte( bs
, 1 ); /* frames_per_sample */
184 lsmash_codec_specific_t
*cs
= lsmash_malloc_zero( sizeof(lsmash_codec_specific_t
) );
187 lsmash_bs_cleanup( bs
);
188 return LSMASH_ERR_MEMORY_ALLOC
;
190 cs
->type
= LSMASH_CODEC_SPECIFIC_DATA_TYPE_UNKNOWN
;
191 cs
->format
= LSMASH_CODEC_SPECIFIC_FORMAT_UNSTRUCTURED
;
192 cs
->destruct
= (lsmash_codec_specific_destructor_t
)lsmash_free
;
193 cs
->data
.unstructured
= lsmash_bs_export_data( bs
, &cs
->size
);
194 cs
->size
= AMR_DAMR_LENGTH
;
195 lsmash_bs_cleanup( bs
);
196 if( !cs
->data
.unstructured
197 || lsmash_add_entry( &summary
->opaque
->list
, cs
) < 0 )
199 lsmash_destroy_codec_specific_data( cs
);
200 return LSMASH_ERR_MEMORY_ALLOC
;
203 #undef AMR_DAMR_LENGTH
206 static lsmash_audio_summary_t
*amr_create_summary
208 importer_t
*importer
,
212 /* Establish an audio summary for AMR-NB or AMR-WB stream. */
213 lsmash_audio_summary_t
*summary
= (lsmash_audio_summary_t
*)lsmash_create_summary( LSMASH_SUMMARY_TYPE_AUDIO
);
216 summary
->sample_type
= wb
? ISOM_CODEC_TYPE_SAWB_AUDIO
: ISOM_CODEC_TYPE_SAMR_AUDIO
;
217 summary
->max_au_length
= wb
? 61 : 32;
218 summary
->aot
= MP4A_AUDIO_OBJECT_TYPE_NULL
; /* no effect */
219 summary
->frequency
= (8000 << wb
);
220 summary
->channels
= 1; /* always single channel */
221 summary
->sample_size
= 16;
222 summary
->samples_in_frame
= (160 << wb
);
223 summary
->sbr_mode
= MP4A_AAC_SBR_NOT_SPECIFIED
; /* no effect */
224 if( amr_create_damr( summary
, wb
) < 0
225 || lsmash_add_entry( importer
->summaries
, summary
) < 0 )
227 lsmash_cleanup_summary( (lsmash_summary_t
*)summary
);
239 amr_importer_t
*amr_imp
= create_amr_importer( importer
);
241 return LSMASH_ERR_MEMORY_ALLOC
;
243 int wb
= amr_check_magic_number( importer
->bs
);
249 lsmash_audio_summary_t
*summary
= amr_create_summary( importer
, wb
);
252 err
= LSMASH_ERR_NAMELESS
;
256 amr_imp
->samples_in_frame
= summary
->samples_in_frame
;
257 amr_imp
->au_number
= 0;
258 importer
->info
= amr_imp
;
259 importer
->status
= IMPORTER_OK
;
262 remove_amr_importer( amr_imp
);
266 static uint32_t amr_get_last_delta
268 importer_t
*importer
,
269 uint32_t track_number
272 debug_if( !importer
|| !importer
->info
)
274 amr_importer_t
*amr_imp
= (amr_importer_t
*)importer
->info
;
275 if( !amr_imp
|| track_number
!= 1 )
277 return amr_imp
->samples_in_frame
;
280 const importer_functions amr_importer
=
282 { "AMR", offsetof( importer_t
, log_level
) },