Make FloatAutos::get_values() always use a PLAY_FORWARD direction.
[cinelerra_cv/pmdumuid.git] / quicktime / wma.c
blob6ceefe5c911ea3e436b7c97da5fe7ec319d787af
1 #include "avcodec.h"
2 #include "funcprotos.h"
3 #include "quicktime.h"
4 #include <string.h>
5 #include "wma.h"
7 /* McRowesoft media player audio */
8 /* WMA derivatives */
10 typedef struct
12 // Sample output
13 char *work_buffer;
14 // Number of first sample in output relative to file
15 int64_t output_position;
16 // Number of samples in output buffer
17 long output_size;
18 // Number of samples allocated in output buffer
19 long output_allocated;
20 char *packet_buffer;
21 int packet_allocated;
22 // Current reading position in file
23 int64_t chunk;
27 int ffmpeg_id;
28 AVCodec *decoder;
29 AVCodecContext *decoder_context;
30 int decode_initialized;
31 } quicktime_wma_codec_t;
35 // Default number of samples to allocate in work buffer
36 #define OUTPUT_ALLOCATION 0x100000
38 static int delete_codec(quicktime_audio_map_t *atrack)
40 quicktime_wma_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
42 if(codec->decode_initialized)
44 pthread_mutex_lock(&ffmpeg_lock);
45 avcodec_close(codec->decoder_context);
46 free(codec->decoder_context);
47 pthread_mutex_unlock(&ffmpeg_lock);
48 codec->decode_initialized = 0;
51 if(codec->work_buffer)
52 free(codec->work_buffer);
53 if(codec->packet_buffer)
54 free(codec->packet_buffer);
55 free(codec);
60 static int init_decode(quicktime_audio_map_t *track_map,
61 quicktime_wma_codec_t *codec)
63 if(!codec->decode_initialized)
65 quicktime_trak_t *trak = track_map->track;
66 pthread_mutex_lock(&ffmpeg_lock);
67 if(!ffmpeg_initialized)
69 ffmpeg_initialized = 1;
70 avcodec_init();
71 avcodec_register_all();
74 codec->decoder = avcodec_find_decoder(codec->ffmpeg_id);
75 if(!codec->decoder)
77 printf("init_decode: avcodec_find_decoder returned NULL.\n");
78 return 1;
80 codec->decoder_context = avcodec_alloc_context();
81 codec->decoder_context->sample_rate = trak->mdia.minf.stbl.stsd.table[0].sample_rate;
82 codec->decoder_context->channels = track_map->channels;
83 if(avcodec_open(codec->decoder_context, codec->decoder) < 0)
85 printf("init_decode: avcodec_open failed.\n");
86 return 1;
88 pthread_mutex_unlock(&ffmpeg_lock);
90 codec->work_buffer = malloc(2 * track_map->channels * OUTPUT_ALLOCATION);
91 codec->output_allocated = OUTPUT_ALLOCATION;
93 return 0;
96 static int decode(quicktime_t *file,
97 int16_t *output_i,
98 float *output_f,
99 long samples,
100 int track,
101 int channel)
103 quicktime_audio_map_t *track_map = &(file->atracks[track]);
104 quicktime_wma_codec_t *codec = ((quicktime_codec_t*)track_map->codec)->priv;
105 quicktime_trak_t *trak = track_map->track;
106 long current_position = track_map->current_position;
107 long end_position = current_position + samples;
108 int try = 0;
109 int result = 0;
110 int i, j;
111 int sample_size = 2 * track_map->channels;
113 if(output_i) bzero(output_i, sizeof(int16_t) * samples);
114 if(output_f) bzero(output_f, sizeof(float) * samples);
116 if(samples > OUTPUT_ALLOCATION)
117 printf("decode: can't read more than %d samples at a time.\n", OUTPUT_ALLOCATION);
119 result = init_decode(track_map, codec);
120 if(result) return 1;
122 // Seeked outside output buffer's range or not initialized: restart
123 if(current_position < codec->output_position ||
124 current_position > codec->output_position + codec->output_size ||
125 !codec->decode_initialized)
127 quicktime_chunk_of_sample(&codec->output_position,
128 &codec->chunk,
129 trak,
130 current_position);
132 //printf("decode 1 %lld %d\n", codec->output_position, codec->chunk);
133 // We know the first mp3 packet in the chunk has a pcm_offset from the encoding.
134 codec->output_size = 0;
135 codec->decode_initialized = 1;
138 // Decode chunks until output buffer covers requested range
139 while(codec->output_position + codec->output_size <
140 current_position + samples &&
141 try < 256)
143 // Load chunk into work buffer
144 int64_t chunk_offset = 0;
145 int chunk_samples = quicktime_chunk_samples(trak, codec->chunk);
146 int chunk_size = quicktime_chunk_bytes(file,
147 &chunk_offset,
148 codec->chunk,
149 trak);
150 // Getting invalid numbers for this
151 // int max_samples = chunk_samples * 2;
152 int max_samples = 32768;
153 int max_bytes = max_samples * sample_size;
154 int bytes_decoded = 0;
155 printf("decode 2 %x %llx %llx\n", chunk_size, chunk_offset, chunk_offset + chunk_size);
157 // Allocate packet buffer
158 if(codec->packet_allocated < chunk_size &&
159 codec->packet_buffer)
161 free(codec->packet_buffer);
162 codec->packet_buffer = 0;
165 if(!codec->packet_buffer)
167 codec->packet_buffer = calloc(1, chunk_size);
168 codec->packet_allocated = chunk_size;
171 // Allocate work buffer
172 if(max_bytes + codec->output_size * sample_size > codec->output_allocated * sample_size)
174 char *new_output = calloc(1, max_bytes + codec->output_size * sample_size);
175 if(codec->work_buffer)
177 memcpy(new_output, codec->work_buffer, codec->output_size * sample_size);
178 free(codec->work_buffer);
180 codec->work_buffer = new_output;
181 codec->output_allocated = max_bytes + codec->output_size * sample_size;
184 quicktime_set_position(file, chunk_offset);
185 result = !quicktime_read_data(file, codec->packet_buffer, chunk_size);
186 if(result) break;
188 // Decode chunk into work buffer.
189 pthread_mutex_lock(&ffmpeg_lock);
190 result = avcodec_decode_audio(codec->decoder_context,
191 (int16_t*)(codec->work_buffer + codec->output_size * sample_size),
192 &bytes_decoded,
193 codec->packet_buffer,
194 chunk_size);
195 pthread_mutex_unlock(&ffmpeg_lock);
196 if(bytes_decoded <= 0)
198 try++;
200 else
202 if(codec->output_size * sample_size + bytes_decoded > codec->output_allocated * sample_size)
203 printf("decode: FYI: bytes_decoded=%d is greater than output_allocated=%d\n",
204 codec->output_size * sample_size + bytes_decoded,
205 codec->output_allocated);
206 codec->output_size += bytes_decoded / sample_size;
207 try = 0;
209 codec->chunk++;
212 //printf("decode 15 %d %lld %d\n", try, codec->output_position, codec->output_size);
213 // Transfer to output
214 if(output_i)
216 int16_t *pcm_ptr = (int16_t*)codec->work_buffer +
217 (current_position - codec->output_position) * track_map->channels +
218 channel;
219 for(i = current_position - codec->output_position, j = 0;
220 j < samples && i < codec->output_size;
221 j++, i++)
223 output_i[j] = *pcm_ptr;
224 pcm_ptr += track_map->channels;
227 else
228 if(output_f)
230 int16_t *pcm_ptr = (int16_t*)codec->work_buffer +
231 (current_position - codec->output_position) * track_map->channels +
232 channel;
233 for(i = current_position - codec->output_position, j = 0;
234 j < samples && i < codec->output_size;
235 j++, i++)
237 output_i[j] = (float)*pcm_ptr / (float)32767;
238 pcm_ptr += track_map->channels;
242 // Delete excess output
243 if(codec->output_size > OUTPUT_ALLOCATION)
245 int sample_diff = codec->output_size - OUTPUT_ALLOCATION;
246 int byte_diff = sample_diff * sample_size;
247 memcpy(codec->work_buffer,
248 codec->work_buffer + byte_diff,
249 OUTPUT_ALLOCATION * sample_size);
250 codec->output_size -= sample_diff;
251 codec->output_position += sample_diff;
254 return 0;
263 static void init_codec_common(quicktime_audio_map_t *atrack)
265 quicktime_wma_codec_t *codec;
266 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
268 /* Init public items */
269 codec_base->delete_acodec = delete_codec;
270 codec_base->decode_audio = decode;
273 /* Init private items */
274 codec = codec_base->priv = calloc(1, sizeof(quicktime_wma_codec_t));
278 void quicktime_init_codec_wmav1(quicktime_audio_map_t *atrack)
280 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
281 quicktime_wma_codec_t *codec;
282 init_codec_common(atrack);
284 codec = codec_base->priv;
285 codec_base->fourcc = QUICKTIME_WMA;
286 codec_base->title = "Win Media Audio 1";
287 codec_base->desc = "Win Media Audio 1";
288 codec_base->wav_id = 0x160;
289 codec->ffmpeg_id = CODEC_ID_WMAV1;
293 void quicktime_init_codec_wmav2(quicktime_audio_map_t *atrack)
295 quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
296 quicktime_wma_codec_t *codec;
297 init_codec_common(atrack);
299 codec = codec_base->priv;
300 codec_base->fourcc = QUICKTIME_WMA;
301 codec_base->title = "Win Media Audio 2";
302 codec_base->desc = "Win Media Audio 2";
303 codec_base->wav_id = 0x161;
304 codec->ffmpeg_id = CODEC_ID_WMAV2;