initial commit
[goodguy/history.git] / cinelerra-5.0 / quicktime / mp4a.c
1 #include <stdint.h>
2 #include <string.h>
3
4 #include "faac.h"
5
6 // The FAAD includes redefine the same symbols as if they're not intended to
7 // be used by the same program.
8 #undef MAIN
9 #undef SSR
10 #undef LTP
11
12
13 #include "funcprotos.h"
14 #include "neaacdec.h"
15 #include "quicktime.h"
16
17
18 // Attempts to read more samples than this will crash
19 #define OUTPUT_ALLOCATION 0x100000
20 #define CLAMP(x, y, z) ((x) = ((x) <  (y) ? (y) : ((x) > (z) ? (z) : (x))))
21
22
23 typedef struct
24 {
25 // Decoder objects
26         NeAACDecHandle decoder_handle;
27         NeAACDecFrameInfo frame_info;
28         NeAACDecConfigurationPtr decoder_config;
29         int decoder_initialized;
30
31         faacEncHandle encoder_handle;
32         faacEncConfigurationPtr encoder_params;
33 // Number of first sample in output relative to file
34         int64_t output_position;
35 // Number of frames
36         int frame_size;
37         int max_frame_bytes;
38 // Interleaved samples
39         float *input_buffer;
40 // Number of frames
41         int input_size;
42 // Number of samples allocated
43         int input_allocated;
44         unsigned char *compressed_buffer;
45
46 // Encoding objects
47         int bitrate;
48         int quantizer_quality;
49         int encoder_initialized;
50 } quicktime_mp4a_codec_t;
51
52
53
54
55
56
57 static void delete_codec(quicktime_audio_map_t *atrack)
58 {
59         quicktime_mp4a_codec_t *codec = 
60                 ((quicktime_codec_t*)atrack->codec)->priv;
61
62         if(codec->decoder_initialized)
63         {
64                 NeAACDecClose(codec->decoder_handle);
65         }
66
67         if(codec->encoder_initialized)
68         {
69                 faacEncClose(codec->encoder_handle);
70                 if(codec->compressed_buffer) free(codec->compressed_buffer);
71                 if(codec->input_buffer) free(codec->input_buffer);
72         }
73
74         free(codec);
75 }
76
77 static int decode(quicktime_t *file, 
78                 int16_t *output_i, float *output_f, 
79                 long samples, int track, int channel)
80 {
81         quicktime_audio_map_t *track_map = &(file->atracks[track]);
82         quicktime_trak_t *trak = track_map->track;
83         quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
84         int64_t current_position = track_map->current_position;
85         int64_t end_position = current_position + samples;
86         quicktime_vbr_t *vbr = &track_map->vbr;
87         if( quicktime_limit_samples(samples) ) return 1;
88
89 // Initialize decoder
90         if( !codec->decoder_initialized ) {
91                 unsigned long samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
92 // FAAD needs unsigned char here
93                 uint8_t channels = track_map->channels;
94                 quicktime_init_vbr(vbr, channels);
95                 codec->decoder_handle = NeAACDecOpen();
96                 codec->decoder_config = NeAACDecGetCurrentConfiguration(codec->decoder_handle);
97                 codec->decoder_config->outputFormat = FAAD_FMT_FLOAT;
98 //              codec->decoder_config->defSampleRate = 
99 //                      trak->mdia.minf.stbl.stsd.table[0].sample_rate;
100
101                 NeAACDecSetConfiguration(codec->decoder_handle, codec->decoder_config);
102
103
104                 char *mp4_hdr = trak->mdia.minf.stbl.stsd.table[0].esds.mpeg4_header;
105                 int hdr_len = trak->mdia.minf.stbl.stsd.table[0].esds.mpeg4_header_size;
106                 if( !mp4_hdr || !hdr_len ) {
107                         quicktime_seek_vbr(track_map, 0, 0);
108                         quicktime_read_vbr(file, track_map);
109
110                         if( NeAACDecInit(codec->decoder_handle,
111                                 quicktime_vbr_input(vbr), quicktime_vbr_input_size(vbr),
112                                 &samplerate, &channels) < 0 ) return 1;
113                 }
114                 else {
115                         if( NeAACDecInit2(codec->decoder_handle,
116                                 (unsigned char *)mp4_hdr, hdr_len,
117                                 &samplerate, &channels) < 0 ) return 1;
118                 }
119 //printf("decode %d samplerate=%d channels=%d\n", __LINE__, samplerate, channels);
120                 codec->decoder_initialized = 1;
121         }
122
123         if( quicktime_align_vbr(track_map, current_position) ||
124             codec->output_position != quicktime_vbr_output_end(vbr) ) {
125                 quicktime_seek_vbr(track_map, current_position, 1);
126                 codec->output_position = quicktime_vbr_output_end(vbr);
127         }
128
129 // Decode until buffer is full
130         while( quicktime_vbr_output_end(vbr) < end_position ) {
131                 if(quicktime_read_vbr(file, track_map)) break;
132
133                 bzero(&codec->frame_info, sizeof(NeAACDecFrameInfo));
134                 float *sample_buffer = NeAACDecDecode(codec->decoder_handle, &codec->frame_info,
135                         quicktime_vbr_input(vbr), quicktime_vbr_input_size(vbr));
136
137                 quicktime_shift_vbr(track_map, quicktime_vbr_input_size(vbr));
138                 int result = codec->frame_info.samples / track_map->channels;
139                 quicktime_store_vbr_float(track_map, sample_buffer, result);
140                 codec->output_position += result;
141         }
142
143 // Transfer from buffer to output
144         if(output_i)
145                 quicktime_copy_vbr_int16(vbr, current_position, 
146                         samples, output_i, channel);
147         else if(output_f)
148                 quicktime_copy_vbr_float(vbr, current_position, 
149                         samples, output_f, channel);
150
151         return 0;
152 }
153
154
155 static int encode(quicktime_t *file, 
156         int16_t **input_i, 
157         float **input_f, 
158         int track, 
159         long samples)
160 {
161         int result = 0;
162         quicktime_audio_map_t *track_map = &(file->atracks[track]);
163         quicktime_trak_t *trak = track_map->track;
164         quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
165         int channels = quicktime_track_channels(file, track);
166         int i, j, k;
167
168         if(!codec->encoder_initialized)
169         {
170                 unsigned long input_samples;
171                 unsigned long max_output_bytes;
172                 int sample_rate = quicktime_sample_rate(file, track);
173                 codec->encoder_initialized = 1;
174                 codec->encoder_handle = faacEncOpen(quicktime_sample_rate(file, track), 
175                         channels,
176             &input_samples, 
177                         &max_output_bytes);
178
179                 codec->frame_size = input_samples / channels;
180                 codec->max_frame_bytes = max_output_bytes;
181                 codec->compressed_buffer = calloc(1, max_output_bytes);
182                 codec->encoder_params = faacEncGetCurrentConfiguration(codec->encoder_handle);
183
184 // Parameters from ffmpeg
185                 codec->encoder_params->aacObjectType = LOW;
186                 codec->encoder_params->mpegVersion = MPEG4;
187                 codec->encoder_params->useTns = 0;
188                 codec->encoder_params->allowMidside = 1;
189                 codec->encoder_params->inputFormat = FAAC_INPUT_FLOAT;
190                 codec->encoder_params->outputFormat = 0;
191                 codec->encoder_params->bitRate = codec->bitrate / channels;
192                 codec->encoder_params->quantqual = codec->quantizer_quality;
193                 codec->encoder_params->bandWidth = sample_rate / 2;
194
195                 if(!faacEncSetConfiguration(codec->encoder_handle, codec->encoder_params))
196                 {
197                         fprintf(stderr, "encode: unsupported MPEG-4 Audio configuration!@#!@#\n");
198                         return 1;
199                 }
200
201
202
203 // Create esds header
204                 unsigned char *buffer;
205                 unsigned long buffer_size;
206                 faacEncGetDecoderSpecificInfo(codec->encoder_handle, 
207                         &buffer,
208                         &buffer_size);
209                 quicktime_set_mpeg4_header(&trak->mdia.minf.stbl.stsd.table[0],
210                         buffer, 
211                         buffer_size);
212 //breaks android player
213                 //trak->mdia.minf.stbl.stsd.table[0].version = 1;
214 // Quicktime player needs this.
215                 trak->mdia.minf.stbl.stsd.table[0].compression_id = 0xfffe;
216         }
217
218
219 // Stack new audio at end of old audio
220         int new_allocation = codec->input_size + samples;
221         if(new_allocation > codec->input_allocated)
222         {
223                 codec->input_buffer = realloc(codec->input_buffer, 
224                         new_allocation * 
225                         sizeof(float) * 
226                         channels);
227                 codec->input_allocated = new_allocation;
228         }
229
230         float *output = (float*)codec->input_buffer + codec->input_size * channels;
231         if(input_f)
232         {
233                 for(i = 0; i < samples; i++)
234                 {
235                         for(j = 0; j < channels; j++)
236                         {
237                                 *output++ = input_f[j][i] * 32767;
238                         }
239                 }
240         }
241         else
242         if(input_i)
243         {
244                 for(i = 0; i < samples; i++)
245                 {
246                         for(j = 0; j < channels; j++)
247                         {
248                                 *output++ = (float)input_i[j][i];
249                         }
250                 }
251         }
252
253         codec->input_size += samples;
254
255
256         for(i = 0; i + codec->frame_size < codec->input_size; i += codec->frame_size)
257         {
258                 int bytes = faacEncEncode(codec->encoder_handle,
259                 (int32_t*)(codec->input_buffer + i * channels),
260                 codec->frame_size * channels,
261                 codec->compressed_buffer,
262                 codec->max_frame_bytes);
263 /*
264  * printf("encode 1 %lld %d %d\n", 
265  * track_map->current_position,
266  * codec->frame_size, 
267  * bytes);
268  */
269 // Write out the packet
270                 if(bytes)
271                 {
272                         quicktime_write_vbr_frame(file, track,
273                                 (char*)codec->compressed_buffer, bytes,
274                                 codec->frame_size);
275                 }
276         }
277
278         for(j = i * channels, k = 0; j < codec->input_size * channels; j++, k++)
279         {
280                 codec->input_buffer[k] = codec->input_buffer[j];
281         }
282         codec->input_size -= i;  
283
284         return result;
285 }
286
287
288
289 static void flush(quicktime_t *file, int track)
290 {
291         quicktime_audio_map_t *track_map = &(file->atracks[track]);
292         quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
293         int channels = quicktime_track_channels(file, track);
294         int i;
295         if(codec->encoder_initialized)
296         {
297                 for(i = 0; 
298                         i < codec->input_size && 
299                                 i + codec->frame_size < codec->input_allocated; 
300                         i += codec->frame_size)
301                 {
302                         int bytes = faacEncEncode(codec->encoder_handle,
303                         (int32_t*)(codec->input_buffer + i * channels),
304                         codec->frame_size * channels,
305                         codec->compressed_buffer,
306                         codec->max_frame_bytes);
307
308 /*
309  * printf("flush 1 %d %d %d\n", 
310  * codec->encoder_params->bitRate, 
311  * bytes, 
312  * codec->max_frame_bytes);
313  */
314 // Write out the packet
315                         if(bytes)
316                         {
317                                 quicktime_write_vbr_frame(file, track,
318                                         (char*)codec->compressed_buffer, bytes,
319                                         codec->frame_size);
320                         }
321                 }
322         }
323 }
324
325
326 static int set_parameter(quicktime_t *file, 
327         int track, 
328         char *key, 
329         void *value)
330 {
331         quicktime_audio_map_t *atrack = &(file->atracks[track]);
332         char *compressor = quicktime_compressor(atrack->track);
333
334         if(quicktime_match_32(compressor, QUICKTIME_MP4A))
335         {
336                 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
337                 if(!strcasecmp(key, "mp4a_bitrate"))
338                 {
339                         codec->bitrate = *(int*)value;
340                 }
341                 else
342                 if(!strcasecmp(key, "mp4a_quantqual"))
343                 {
344                         codec->quantizer_quality = *(int*)value;
345                 }
346         }
347         return 0;
348 }
349
350
351
352 void quicktime_init_codec_mp4a(quicktime_audio_map_t *atrack)
353 {
354         quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
355         quicktime_mp4a_codec_t *codec;
356         codec_base->priv = calloc(1, sizeof(quicktime_mp4a_codec_t));
357         codec_base->delete_acodec = delete_codec;
358         codec_base->decode_audio = decode;
359         codec_base->encode_audio = encode;
360         codec_base->set_parameter = set_parameter;
361         codec_base->flush = flush;
362         codec_base->fourcc = QUICKTIME_MP4A;
363         codec_base->title = "MPEG4 audio";
364         codec_base->desc = "Audio section of MPEG4 standard";
365
366         codec = (quicktime_mp4a_codec_t*)codec_base->priv;
367 // Default encoding parameters here
368         codec->bitrate = 256000;
369         codec->quantizer_quality = 100;
370 }
371
372
373
374