1 #include "funcprotos.h"
8 extern int ffmpeg_initialized;
9 extern pthread_mutex_t ffmpeg_lock;
14 int decoder_initialized;
16 AVCodecContext *decoder_context;
21 // Input samples interleaved
22 int16_t *input_buffer;
23 // Number of samples allocated
25 // Last sample decoded in the input buffer + 1
27 // Total samples in input buffer
29 // Current write offset in input buffer
32 unsigned char *compressed_buffer;
34 int compressed_allocated;
37 // Next chunk to decode sequentially
38 int64_t current_chunk;
39 } quicktime_qdm2_codec_t;
41 #define MAX(x, y) ((x) > (y) ? (x) : (y))
42 // Default number of samples to allocate in work buffer
43 #define OUTPUT_ALLOCATION 0x100000
49 static void delete_codec(quicktime_audio_map_t *atrack)
51 quicktime_qdm2_codec_t *codec =
52 ((quicktime_codec_t*)atrack->codec)->priv;
54 if(codec->decoder_initialized)
56 avcodec_close(codec->decoder_context);
57 free(codec->decoder_context);
60 if(codec->input_buffer) free(codec->input_buffer);
61 if(codec->compressed_buffer) free(codec->compressed_buffer);
62 if(codec->temp_buffer) free(codec->temp_buffer);
67 void allocate_compressed(quicktime_qdm2_codec_t *codec, int size)
69 if(size > codec->compressed_allocated)
71 codec->compressed_buffer = realloc(codec->compressed_buffer, size);
72 codec->compressed_allocated = size;
76 static int decode(quicktime_t *file,
83 quicktime_audio_map_t *track_map = &(file->atracks[track]);
84 quicktime_trak_t *trak = track_map->track;
85 quicktime_qdm2_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
86 quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
87 int64_t current_position = track_map->current_position;
88 int64_t end_position = current_position + samples;
89 quicktime_frma_t *frma = &stsd_table->frma;
90 int channels = track_map->channels;
98 if(!codec->decoder_initialized)
100 pthread_mutex_lock(&ffmpeg_lock);
101 if(!ffmpeg_initialized)
103 ffmpeg_initialized = 1;
107 codec->decoder = avcodec_find_decoder(CODEC_ID_QDM2);
110 printf("qdm2.c: decode: no ffmpeg decoder found.\n");
114 // allocate the codec and fill in header
115 AVCodecContext *context = avcodec_alloc_context3(codec->decoder);
116 codec->decoder_context = context;
117 codec->decoder_context->sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
118 codec->decoder_context->channels = track_map->channels;
120 if(frma->data && frma->data_size)
122 context->extradata = (unsigned char *)frma->data;
123 context->extradata_size = frma->data_size;
128 // avcodec_thread_init(context, file->cpus);
129 context->thread_count = file->cpus;
132 if(avcodec_open2(context, codec->decoder, 0) < 0)
134 printf("qdm2.c: decode: avcodec_open failed.\n");
137 pthread_mutex_unlock(&ffmpeg_lock);
139 codec->input_buffer = calloc(sizeof(int16_t),
140 track_map->channels * OUTPUT_ALLOCATION);
141 codec->input_allocated = OUTPUT_ALLOCATION;
144 codec->decoder_initialized = 1;
148 if(samples > OUTPUT_ALLOCATION)
150 printf("qdm2: decode: can't decode more than 0x%x samples at a time.\n",
157 printf("qdm2 decode: current_position=%jd end_position=%jd input_size=%d input_end=%jd\n",
158 current_position, end_position, codec->input_size, codec->input_end);
161 // printf("qdm2 decode: current_position=%lld end_position=%lld chunk_sample=%lld chunk=%lld\n",
168 if(current_position < codec->input_end - codec->input_size ||
169 current_position > codec->input_end)
171 // Desired start point is outside existing range. Reposition buffer pointer
172 // to start time of nearest chunk and start over.
173 quicktime_chunk_of_sample(&chunk_sample,
174 &codec->current_chunk,
177 codec->input_size = 0;
178 codec->input_ptr = 0;
179 codec->input_end = chunk_sample;
182 // Decode complete chunks until samples is reached
183 int total_chunks = trak->mdia.minf.stbl.stco.total_entries;
184 while(codec->input_end < end_position)
186 int64_t offset = quicktime_chunk_to_offset(file,
188 codec->current_chunk);
189 int64_t max_offset = quicktime_chunk_to_offset(file,
191 codec->current_chunk + 1);
192 quicktime_set_position(file, offset);
193 allocate_compressed(codec, 3);
197 printf("qdm2 decode: input_end=%jd chunk=%jd offset=0x%jx\n",
198 codec->input_end, codec->current_chunk, offset);
201 // Read fragments of chunk
204 // Hit next chunk of audio
205 if(max_offset > offset && quicktime_position(file) >= max_offset) break;
206 if(!quicktime_read_data(file,
207 (char*)codec->compressed_buffer + codec->compressed_size,
210 if(codec->compressed_buffer[codec->compressed_size] != 0x82)
212 // printf("qdm2: decode: position=0x%llx\n", quicktime_position(file));
215 int fragment_size = 3 + ((codec->compressed_buffer[codec->compressed_size + 1] << 8) |
216 codec->compressed_buffer[codec->compressed_size + 2]);
218 if(fragment_size > OUTPUT_ALLOCATION) break;
219 // Expand compressed buffer
220 allocate_compressed(codec,
221 codec->compressed_size + fragment_size + 1024);
222 if(!quicktime_read_data(file,
223 (char*)codec->compressed_buffer + codec->compressed_size + 3,
227 codec->compressed_size += fragment_size;
230 av_init_packet(&avpkt);
231 avpkt.data = codec->compressed_buffer;
232 avpkt.size = codec->compressed_size;
235 // Repeat this sequence until ffmpeg stops outputting samples
238 if(!codec->temp_buffer)
239 codec->temp_buffer = calloc(sizeof(int16_t), OUTPUT_ALLOCATION);
240 int bytes_decoded = OUTPUT_ALLOCATION * sizeof(int16_t);
241 int result = quicktime_decode_audio3(codec->decoder_context,
242 codec->temp_buffer, &bytes_decoded, &avpkt);
244 // Shift compressed buffer
247 avpkt.size -= result;
248 avpkt.data += result;
252 //printf("avcodec_decode_audio result=%d bytes_decoded=%d fragment_size=%d codec->compressed_size=%d\n",
253 //result, bytes_decoded, fragment_size, codec->compressed_size);
255 * static FILE *test = 0;
256 * if(!test) test = fopen("/tmp/debug", "w");
257 * fwrite(codec->temp_buffer, 1, bytes_decoded, test);
260 for(i = 0; i < bytes_decoded / channels / sizeof(int16_t); i++)
262 for(j = 0; j < channels; j++)
263 codec->input_buffer[codec->input_ptr * channels + j] =
264 codec->temp_buffer[i * channels + j];
266 if(codec->input_ptr >= codec->input_allocated)
267 codec->input_ptr = 0;
269 codec->input_end += bytes_decoded / channels / sizeof(int16_t);
270 codec->input_size += bytes_decoded / channels / sizeof(int16_t);
272 if(bytes_decoded <= 0) break;
276 memcpy(codec->compressed_buffer,
277 codec->compressed_buffer + count,
278 codec->compressed_size -= count);
282 codec->current_chunk++;
283 if(codec->current_chunk >= total_chunks) break;
286 // Transfer from buffer to output
287 int input_ptr = codec->input_ptr - (codec->input_end - current_position);
288 if(input_ptr < 0) input_ptr += codec->input_allocated;
291 for(i = 0; i < samples; i++)
293 output_i[i] = codec->input_buffer[input_ptr * channels + channel];
295 if(input_ptr >= codec->input_allocated) input_ptr = 0;
301 for(i = 0; i < samples; i++)
303 output_f[i] = (float)codec->input_buffer[input_ptr * channels + channel] / 32768.0;
305 if(input_ptr >= codec->input_allocated) input_ptr = 0;
315 void quicktime_init_codec_qdm2(quicktime_audio_map_t *atrack)
317 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
318 codec_base->priv = calloc(1, sizeof(quicktime_qdm2_codec_t));
319 codec_base->delete_acodec = delete_codec;
320 codec_base->decode_audio = decode;
321 codec_base->encode_audio = 0;
322 codec_base->set_parameter = 0;
323 codec_base->flush = 0;
324 codec_base->fourcc = "QDM2";
325 codec_base->title = "QDesign Music 2";
326 codec_base->desc = "QDesign Music 2";