Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / quicktime / mp4a.c
blob2ce69692a6fd22f0f7af7a2fc88c436ac233e2b8
1 #include <stdint.h>
2 #include <string.h>
4 #include "faac.h"
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
13 #include <faad.h>
14 #include "funcprotos.h"
15 #include "quicktime.h"
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))))
23 typedef struct
25 // Decoder objects
26 faacDecHandle decoder_handle;
27 faacDecFrameInfo frame_info;
28 faacDecConfigurationPtr decoder_config;
29 int decoder_initialized;
32 faacEncHandle encoder_handle;
33 faacEncConfigurationPtr encoder_params;
34 // Number of frames
35 int frame_size;
36 int max_frame_bytes;
37 // Interleaved samples
38 float *input_buffer;
39 // Number of frames
40 int input_size;
41 // Number of samples allocated
42 int input_allocated;
43 unsigned char *compressed_buffer;
44 int bitrate;
45 int quantizer_quality;
46 int encoder_initialized;
47 } quicktime_mp4a_codec_t;
54 static int delete_codec(quicktime_audio_map_t *atrack)
56 quicktime_mp4a_codec_t *codec =
57 ((quicktime_codec_t*)atrack->codec)->priv;
59 if(codec->decoder_initialized)
61 faacDecClose(codec->decoder_handle);
64 if(codec->encoder_initialized)
66 faacEncClose(codec->encoder_handle);
67 if(codec->compressed_buffer) free(codec->compressed_buffer);
68 if(codec->input_buffer) free(codec->input_buffer);
71 free(codec);
74 static int decode(quicktime_t *file,
75 int16_t *output_i,
76 float *output_f,
77 long samples,
78 int track,
79 int channel)
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;
89 // Initialize decoder
90 if(!codec->decoder_initialized)
92 uint32_t samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
93 // FAAD needs unsigned char here
94 unsigned char channels = track_map->channels;
95 quicktime_init_vbr(vbr, channels);
96 codec->decoder_handle = faacDecOpen();
97 codec->decoder_config = faacDecGetCurrentConfiguration(codec->decoder_handle);
98 codec->decoder_config->outputFormat = FAAD_FMT_FLOAT;
99 // codec->decoder_config->defSampleRate =
100 // trak->mdia.minf.stbl.stsd.table[0].sample_rate;
102 faacDecSetConfiguration(codec->decoder_handle, codec->decoder_config);
104 quicktime_align_vbr(track_map, samples);
105 quicktime_read_vbr(file, track_map);
106 if(faacDecInit(codec->decoder_handle,
107 quicktime_vbr_input(vbr),
108 quicktime_vbr_input_size(vbr),
109 &samplerate,
110 &channels) < 0)
112 return 1;
114 //printf("decode %d %d\n", samplerate, channels);
115 codec->decoder_initialized = 1;
118 if(quicktime_align_vbr(track_map,
119 samples))
121 return 1;
123 else
125 // Decode until buffer is full
126 while(quicktime_vbr_end(vbr) < end_position)
128 // Fill until min buffer size reached or EOF
130 * while(quicktime_vbr_input_size(vbr) <
131 * FAAD_MIN_STREAMSIZE * track_map->channels)
133 * if(quicktime_read_vbr(file, track_map)) break;
137 if(quicktime_read_vbr(file, track_map)) break;
139 bzero(&codec->frame_info, sizeof(faacDecFrameInfo));
140 float *sample_buffer = faacDecDecode(codec->decoder_handle,
141 &codec->frame_info,
142 quicktime_vbr_input(vbr),
143 quicktime_vbr_input_size(vbr));
145 if (codec->frame_info.error > 0)
147 // printf("decode mp4a: %s\n",
148 // faacDecGetErrorMessage(codec->frame_info.error));
152 * printf("decode 1 %d %d %d\n",
153 * quicktime_vbr_input_size(vbr),
154 * codec->frame_info.bytesconsumed,
155 * codec->frame_info.samples);
157 * static FILE *test = 0;
158 * if(!test) test = fopen("/tmp/test.aac", "w");
159 * fwrite(quicktime_vbr_input(vbr), quicktime_vbr_input_size(vbr), 1, test);
164 * static FILE *test = 0;
165 * if(!test) test = fopen("/hmov/test.pcm", "w");
166 * int i;
167 * for(i = 0; i < codec->frame_info.samples; i++)
169 * int16_t sample = (int)(sample_buffer[i] * 32767);
170 * fwrite(&sample, 2, 1, test);
172 * fflush(test);
175 // quicktime_shift_vbr(track_map, codec->frame_info.bytesconsumed);
176 quicktime_shift_vbr(track_map, quicktime_vbr_input_size(vbr));
177 quicktime_store_vbr_float(track_map,
178 sample_buffer,
179 codec->frame_info.samples / track_map->channels);
183 // Transfer from buffer to output
184 if(output_i)
185 quicktime_copy_vbr_int16(vbr,
186 current_position,
187 samples,
188 output_i,
189 channel);
190 else
191 if(output_f)
192 quicktime_copy_vbr_float(vbr,
193 current_position,
194 samples,
195 output_f,
196 channel);
198 return 0;
202 static int encode(quicktime_t *file,
203 int16_t **input_i,
204 float **input_f,
205 int track,
206 long samples)
208 int result = 0;
209 quicktime_audio_map_t *track_map = &(file->atracks[track]);
210 quicktime_trak_t *trak = track_map->track;
211 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
212 int channels = quicktime_track_channels(file, track);
213 int i, j, k;
215 if(!codec->encoder_initialized)
217 unsigned long input_samples;
218 unsigned long max_output_bytes;
219 int sample_rate = quicktime_sample_rate(file, track);
220 codec->encoder_initialized = 1;
221 codec->encoder_handle = faacEncOpen(quicktime_sample_rate(file, track),
222 channels,
223 &input_samples,
224 &max_output_bytes);
226 codec->frame_size = input_samples / channels;
227 codec->max_frame_bytes = max_output_bytes;
228 codec->compressed_buffer = calloc(1, max_output_bytes);
229 codec->encoder_params = faacEncGetCurrentConfiguration(codec->encoder_handle);
231 // Parameters from ffmpeg
232 codec->encoder_params->aacObjectType = LOW;
233 codec->encoder_params->mpegVersion = MPEG4;
234 codec->encoder_params->useTns = 0;
235 codec->encoder_params->allowMidside = 1;
236 codec->encoder_params->inputFormat = FAAC_INPUT_FLOAT;
237 codec->encoder_params->outputFormat = 0;
238 codec->encoder_params->bitRate = codec->bitrate / channels;
239 codec->encoder_params->quantqual = codec->quantizer_quality;
240 codec->encoder_params->bandWidth = sample_rate / 2;
242 if(!faacEncSetConfiguration(codec->encoder_handle, codec->encoder_params))
244 fprintf(stderr, "encode: unsupported MPEG-4 Audio configuration!@#!@#\n");
245 return 1;
250 // Create esds header
251 unsigned char *buffer;
252 unsigned long buffer_size;
253 faacEncGetDecoderSpecificInfo(codec->encoder_handle,
254 &buffer,
255 &buffer_size);
256 quicktime_set_mpeg4_header(&trak->mdia.minf.stbl.stsd.table[0],
257 buffer,
258 buffer_size);
259 trak->mdia.minf.stbl.stsd.table[0].version = 1;
260 // Quicktime player needs this.
261 trak->mdia.minf.stbl.stsd.table[0].compression_id = 0xfffe;
265 // Stack new audio at end of old audio
266 int new_allocation = codec->input_size + samples;
267 if(new_allocation > codec->input_allocated)
269 codec->input_buffer = realloc(codec->input_buffer,
270 new_allocation *
271 sizeof(float) *
272 channels);
273 codec->input_allocated = new_allocation;
276 float *output = (float*)codec->input_buffer + codec->input_size * channels;
277 if(input_f)
279 for(i = 0; i < samples; i++)
281 for(j = 0; j < channels; j++)
283 *output++ = input_f[j][i] * 32767;
287 else
288 if(input_i)
290 for(i = 0; i < samples; i++)
292 for(j = 0; j < channels; j++)
294 *output++ = (float)input_i[j][i];
299 codec->input_size += samples;
302 for(i = 0; i + codec->frame_size < codec->input_size; i += codec->frame_size)
304 int bytes = faacEncEncode(codec->encoder_handle,
305 (int32_t*)(codec->input_buffer + i * channels),
306 codec->frame_size * channels,
307 codec->compressed_buffer,
308 codec->max_frame_bytes);
310 * printf("encode 1 %lld %d %d\n",
311 * track_map->current_position,
312 * codec->frame_size,
313 * bytes);
315 // Write out the packet
316 if(bytes)
318 quicktime_write_vbr_frame(file,
319 track,
320 codec->compressed_buffer,
321 bytes,
322 codec->frame_size);
326 for(j = i * channels, k = 0; j < codec->input_size * channels; j++, k++)
328 codec->input_buffer[k] = codec->input_buffer[j];
330 codec->input_size -= i;
332 return result;
337 static void flush(quicktime_t *file, int track)
339 quicktime_audio_map_t *track_map = &(file->atracks[track]);
340 quicktime_trak_t *trak = track_map->track;
341 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
342 int channels = quicktime_track_channels(file, track);
343 int i;
344 if(codec->encoder_initialized)
346 for(i = 0;
347 i < codec->input_size &&
348 i + codec->frame_size < codec->input_allocated;
349 i += codec->frame_size)
351 int bytes = faacEncEncode(codec->encoder_handle,
352 (int32_t*)(codec->input_buffer + i * channels),
353 codec->frame_size * channels,
354 codec->compressed_buffer,
355 codec->max_frame_bytes);
358 * printf("flush 1 %d %d %d\n",
359 * codec->encoder_params->bitRate,
360 * bytes,
361 * codec->max_frame_bytes);
363 // Write out the packet
364 if(bytes)
366 quicktime_write_vbr_frame(file,
367 track,
368 codec->compressed_buffer,
369 bytes,
370 codec->frame_size);
377 static int set_parameter(quicktime_t *file,
378 int track,
379 char *key,
380 void *value)
382 quicktime_audio_map_t *atrack = &(file->atracks[track]);
383 char *compressor = quicktime_compressor(atrack->track);
385 if(quicktime_match_32(compressor, QUICKTIME_MP4A))
387 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
388 if(!strcasecmp(key, "mp4a_bitrate"))
390 codec->bitrate = *(int*)value;
392 else
393 if(!strcasecmp(key, "mp4a_quantqual"))
395 codec->quantizer_quality = *(int*)value;
398 return 0;
403 void quicktime_init_codec_mp4a(quicktime_audio_map_t *atrack)
405 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
406 quicktime_mp4a_codec_t *codec;
407 codec_base->priv = calloc(1, sizeof(quicktime_mp4a_codec_t));
408 codec_base->delete_acodec = delete_codec;
409 codec_base->decode_audio = decode;
410 codec_base->encode_audio = encode;
411 codec_base->set_parameter = set_parameter;
412 codec_base->flush = flush;
413 codec_base->fourcc = "mp4a";
414 codec_base->title = "MPEG4 audio";
415 codec_base->desc = "Audio section of MPEG4 standard";
417 codec = (quicktime_mp4a_codec_t*)codec_base->priv;
418 // Default encoding parameters here
419 codec->bitrate = 256000;
420 codec->quantizer_quality = 100;