r830: Fixed a problem whereby the project interlace setting was not being stored...
[cinelerra_cv/mob.git] / quicktime / mp4a.c
blob7aef0d8d293832b5085343b361319ba36054a446
1 #include <stdint.h>
3 #include "faac.h"
5 // The FAAD includes redefine the same symbols as if they're not intended to
6 // be used by the same program.
7 #undef MAIN
8 #undef SSR
9 #undef LTP
12 #include <faad.h>
13 #include "funcprotos.h"
14 #include "quicktime.h"
17 // Attempts to read more samples than this will crash
18 #define OUTPUT_ALLOCATION 0x100000
19 #define CLAMP(x, y, z) ((x) = ((x) < (y) ? (y) : ((x) > (z) ? (z) : (x))))
22 typedef struct
24 // Decoder objects
25 faacDecHandle decoder_handle;
26 faacDecFrameInfo frame_info;
27 faacDecConfigurationPtr decoder_config;
28 int decoder_initialized;
31 faacEncHandle encoder_handle;
32 faacEncConfigurationPtr encoder_params;
33 // Number of frames
34 int frame_size;
35 int max_frame_bytes;
36 // Interleaved samples
37 float *input_buffer;
38 // Number of frames
39 int input_size;
40 // Number of samples allocated
41 int input_allocated;
42 unsigned char *compressed_buffer;
43 int bitrate;
44 int quantizer_quality;
45 int encoder_initialized;
46 } quicktime_mp4a_codec_t;
53 static int delete_codec(quicktime_audio_map_t *atrack)
55 quicktime_mp4a_codec_t *codec =
56 ((quicktime_codec_t*)atrack->codec)->priv;
58 if(codec->decoder_initialized)
60 faacDecClose(codec->decoder_handle);
63 if(codec->encoder_initialized)
65 faacEncClose(codec->encoder_handle);
66 if(codec->compressed_buffer) free(codec->compressed_buffer);
67 if(codec->input_buffer) free(codec->input_buffer);
70 free(codec);
73 static int decode(quicktime_t *file,
74 int16_t *output_i,
75 float *output_f,
76 long samples,
77 int track,
78 int channel)
80 quicktime_audio_map_t *track_map = &(file->atracks[track]);
81 quicktime_trak_t *trak = track_map->track;
82 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
83 int64_t current_position = track_map->current_position;
84 int64_t end_position = current_position + samples;
85 quicktime_vbr_t *vbr = &track_map->vbr;
88 // Initialize decoder
89 if(!codec->decoder_initialized)
91 uint32_t samplerate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
92 // FAAD needs unsigned char here
93 unsigned char channels = track_map->channels;
94 quicktime_init_vbr(vbr, channels);
95 codec->decoder_handle = faacDecOpen();
96 codec->decoder_config = faacDecGetCurrentConfiguration(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;
101 faacDecSetConfiguration(codec->decoder_handle, codec->decoder_config);
103 quicktime_align_vbr(track_map, samples);
104 quicktime_read_vbr(file, track_map);
105 if(faacDecInit(codec->decoder_handle,
106 quicktime_vbr_input(vbr),
107 quicktime_vbr_input_size(vbr),
108 &samplerate,
109 &channels) < 0)
111 return 1;
113 //printf("decode %d %d\n", samplerate, channels);
114 codec->decoder_initialized = 1;
117 if(quicktime_align_vbr(track_map,
118 samples))
120 return 1;
122 else
124 // Decode until buffer is full
125 while(quicktime_vbr_end(vbr) < end_position)
127 // Fill until min buffer size reached or EOF
129 * while(quicktime_vbr_input_size(vbr) <
130 * FAAD_MIN_STREAMSIZE * track_map->channels)
132 * if(quicktime_read_vbr(file, track_map)) break;
136 if(quicktime_read_vbr(file, track_map)) break;
138 bzero(&codec->frame_info, sizeof(faacDecFrameInfo));
139 float *sample_buffer = faacDecDecode(codec->decoder_handle,
140 &codec->frame_info,
141 quicktime_vbr_input(vbr),
142 quicktime_vbr_input_size(vbr));
144 if (codec->frame_info.error > 0)
146 // printf("decode mp4a: %s\n",
147 // faacDecGetErrorMessage(codec->frame_info.error));
151 * printf("decode 1 %d %d %d\n",
152 * quicktime_vbr_input_size(vbr),
153 * codec->frame_info.bytesconsumed,
154 * codec->frame_info.samples);
156 * static FILE *test = 0;
157 * if(!test) test = fopen("/tmp/test.aac", "w");
158 * fwrite(quicktime_vbr_input(vbr), quicktime_vbr_input_size(vbr), 1, test);
163 * static FILE *test = 0;
164 * if(!test) test = fopen("/hmov/test.pcm", "w");
165 * int i;
166 * for(i = 0; i < codec->frame_info.samples; i++)
168 * int16_t sample = (int)(sample_buffer[i] * 32767);
169 * fwrite(&sample, 2, 1, test);
171 * fflush(test);
174 // quicktime_shift_vbr(track_map, codec->frame_info.bytesconsumed);
175 quicktime_shift_vbr(track_map, quicktime_vbr_input_size(vbr));
176 quicktime_store_vbr_float(track_map,
177 sample_buffer,
178 codec->frame_info.samples / track_map->channels);
182 // Transfer from buffer to output
183 if(output_i)
184 quicktime_copy_vbr_int16(vbr,
185 current_position,
186 samples,
187 output_i,
188 channel);
189 else
190 if(output_f)
191 quicktime_copy_vbr_float(vbr,
192 current_position,
193 samples,
194 output_f,
195 channel);
197 return 0;
201 static int encode(quicktime_t *file,
202 int16_t **input_i,
203 float **input_f,
204 int track,
205 long samples)
207 int result = 0;
208 quicktime_audio_map_t *track_map = &(file->atracks[track]);
209 quicktime_trak_t *trak = track_map->track;
210 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
211 int channels = quicktime_track_channels(file, track);
212 int i, j, k;
214 if(!codec->encoder_initialized)
216 unsigned long input_samples;
217 unsigned long max_output_bytes;
218 int sample_rate = quicktime_sample_rate(file, track);
219 codec->encoder_initialized = 1;
220 codec->encoder_handle = faacEncOpen(quicktime_sample_rate(file, track),
221 channels,
222 &input_samples,
223 &max_output_bytes);
225 codec->frame_size = input_samples / channels;
226 codec->max_frame_bytes = max_output_bytes;
227 codec->compressed_buffer = calloc(1, max_output_bytes);
228 codec->encoder_params = faacEncGetCurrentConfiguration(codec->encoder_handle);
230 // Parameters from ffmpeg
231 codec->encoder_params->aacObjectType = LOW;
232 codec->encoder_params->mpegVersion = MPEG4;
233 codec->encoder_params->useTns = 0;
234 codec->encoder_params->allowMidside = 1;
235 codec->encoder_params->inputFormat = FAAC_INPUT_FLOAT;
236 codec->encoder_params->outputFormat = 0;
237 codec->encoder_params->bitRate = codec->bitrate / channels;
238 codec->encoder_params->quantqual = codec->quantizer_quality;
239 codec->encoder_params->bandWidth = sample_rate / 2;
241 if(!faacEncSetConfiguration(codec->encoder_handle, codec->encoder_params))
243 fprintf(stderr, "encode: unsupported MPEG-4 Audio configuration!@#!@#\n");
244 return 1;
249 // Create esds header
250 unsigned char *buffer;
251 unsigned long buffer_size;
252 faacEncGetDecoderSpecificInfo(codec->encoder_handle,
253 &buffer,
254 &buffer_size);
255 quicktime_set_mpeg4_header(&trak->mdia.minf.stbl.stsd.table[0],
256 buffer,
257 buffer_size);
258 trak->mdia.minf.stbl.stsd.table[0].version = 1;
259 // Quicktime player needs this.
260 trak->mdia.minf.stbl.stsd.table[0].compression_id = 0xfffe;
264 // Stack new audio at end of old audio
265 int new_allocation = codec->input_size + samples;
266 if(new_allocation > codec->input_allocated)
268 codec->input_buffer = realloc(codec->input_buffer,
269 new_allocation *
270 sizeof(float) *
271 channels);
272 codec->input_allocated = new_allocation;
275 float *output = (float*)codec->input_buffer + codec->input_size * channels;
276 if(input_f)
278 for(i = 0; i < samples; i++)
280 for(j = 0; j < channels; j++)
282 *output++ = input_f[j][i] * 32767;
286 else
287 if(input_i)
289 for(i = 0; i < samples; i++)
291 for(j = 0; j < channels; j++)
293 *output++ = (float)input_i[j][i];
298 codec->input_size += samples;
301 for(i = 0; i + codec->frame_size < codec->input_size; i += codec->frame_size)
303 int bytes = faacEncEncode(codec->encoder_handle,
304 (int32_t*)(codec->input_buffer + i * channels),
305 codec->frame_size * channels,
306 codec->compressed_buffer,
307 codec->max_frame_bytes);
309 * printf("encode 1 %lld %d %d\n",
310 * track_map->current_position,
311 * codec->frame_size,
312 * bytes);
314 // Write out the packet
315 if(bytes)
317 quicktime_write_vbr_frame(file,
318 track,
319 codec->compressed_buffer,
320 bytes,
321 codec->frame_size);
325 for(j = i * channels, k = 0; j < codec->input_size * channels; j++, k++)
327 codec->input_buffer[k] = codec->input_buffer[j];
329 codec->input_size -= i;
331 return result;
336 static void flush(quicktime_t *file, int track)
338 quicktime_audio_map_t *track_map = &(file->atracks[track]);
339 quicktime_trak_t *trak = track_map->track;
340 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
341 int channels = quicktime_track_channels(file, track);
342 int i;
343 if(codec->encoder_initialized)
345 for(i = 0;
346 i < codec->input_size &&
347 i + codec->frame_size < codec->input_allocated;
348 i += codec->frame_size)
350 int bytes = faacEncEncode(codec->encoder_handle,
351 (int32_t*)(codec->input_buffer + i * channels),
352 codec->frame_size * channels,
353 codec->compressed_buffer,
354 codec->max_frame_bytes);
357 * printf("flush 1 %d %d %d\n",
358 * codec->encoder_params->bitRate,
359 * bytes,
360 * codec->max_frame_bytes);
362 // Write out the packet
363 if(bytes)
365 quicktime_write_vbr_frame(file,
366 track,
367 codec->compressed_buffer,
368 bytes,
369 codec->frame_size);
376 static int set_parameter(quicktime_t *file,
377 int track,
378 char *key,
379 void *value)
381 quicktime_audio_map_t *atrack = &(file->atracks[track]);
382 char *compressor = quicktime_compressor(atrack->track);
384 if(quicktime_match_32(compressor, QUICKTIME_MP4A))
386 quicktime_mp4a_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
387 if(!strcasecmp(key, "mp4a_bitrate"))
389 codec->bitrate = *(int*)value;
391 else
392 if(!strcasecmp(key, "mp4a_quantqual"))
394 codec->quantizer_quality = *(int*)value;
397 return 0;
402 void quicktime_init_codec_mp4a(quicktime_audio_map_t *atrack)
404 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
405 quicktime_mp4a_codec_t *codec;
406 codec_base->priv = calloc(1, sizeof(quicktime_mp4a_codec_t));
407 codec_base->delete_acodec = delete_codec;
408 codec_base->decode_audio = decode;
409 codec_base->encode_audio = encode;
410 codec_base->set_parameter = set_parameter;
411 codec_base->flush = flush;
412 codec_base->fourcc = "mp4a";
413 codec_base->title = "MPEG4 audio";
414 codec_base->desc = "Audio section of MPEG4 standard";
416 codec = (quicktime_mp4a_codec_t*)codec_base->priv;
417 // Default encoding parameters here
418 codec->bitrate = 256000;
419 codec->quantizer_quality = 100;