allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / wma.c
1 #include <string.h>
2
3 #include "funcprotos.h"
4 #include "quicktime.h"
5 #include "qtffmpeg.h"
6 #include "wma.h"
7
8 /* McRowesoft media player audio */
9 /* WMA derivatives */
10
11 typedef struct
12 {
13 // Sample output
14         char *work_buffer;
15 // Number of first sample in output relative to file
16         int64_t output_position;
17 // Number of samples in output buffer
18         long output_size;
19 // Number of samples allocated in output buffer
20         long output_allocated;
21         char *packet_buffer;
22         int packet_allocated;
23 // Current reading position in file
24         int64_t chunk;
25
26
27
28         int ffmpeg_id;
29     AVCodec *decoder;
30         AVCodecContext *decoder_context;
31         int decode_initialized;
32 } quicktime_wma_codec_t;
33
34
35
36 // Default number of samples to allocate in work buffer
37 #define OUTPUT_ALLOCATION 0x100000
38
39 static void delete_codec(quicktime_audio_map_t *atrack)
40 {
41         quicktime_wma_codec_t *codec = ((quicktime_codec_t*)atrack->codec)->priv;
42
43         if(codec->decode_initialized)
44         {
45                 pthread_mutex_lock(&ffmpeg_lock);
46                 avcodec_close(codec->decoder_context);
47                 free(codec->decoder_context);
48                 pthread_mutex_unlock(&ffmpeg_lock);
49                 codec->decode_initialized = 0;
50         }
51
52         if(codec->work_buffer)
53                 free(codec->work_buffer);
54         if(codec->packet_buffer)
55                 free(codec->packet_buffer);
56         free(codec);
57 }
58
59
60
61 static int init_decode(quicktime_audio_map_t *track_map,
62         quicktime_wma_codec_t *codec)
63 {
64         if(!codec->decode_initialized)
65         {
66                 quicktime_trak_t *trak = track_map->track;
67                 pthread_mutex_lock(&ffmpeg_lock);
68                 if(!ffmpeg_initialized)
69                 {
70                         ffmpeg_initialized = 1;
71                         av_register_all();
72                 }
73
74                 codec->decoder = avcodec_find_decoder(codec->ffmpeg_id);
75                 if(!codec->decoder)
76                 {
77                         printf("init_decode: avcodec_find_decoder returned NULL.\n");
78                         return 1;
79                 }
80                 codec->decoder_context = avcodec_alloc_context3(codec->decoder);
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_open2(codec->decoder_context, codec->decoder, 0) < 0)
84                 {
85                         printf("init_decode: avcodec_open failed.\n");
86                         return 1;
87                 }
88                 pthread_mutex_unlock(&ffmpeg_lock);
89
90                 codec->work_buffer = malloc(2 * track_map->channels * OUTPUT_ALLOCATION);
91                 codec->output_allocated = OUTPUT_ALLOCATION;
92         }
93         return 0;
94 }
95
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)
102 {
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         int try = 0;
108         int result = 0;
109         int i, j;
110         int sample_size = 2 * track_map->channels;
111
112         if(output_i) bzero(output_i, sizeof(int16_t) * samples);
113         if(output_f) bzero(output_f, sizeof(float) * samples);
114
115         if(samples > OUTPUT_ALLOCATION)
116                 printf("decode: can't read more than %d samples at a time.\n", OUTPUT_ALLOCATION);
117
118         result = init_decode(track_map, codec);
119         if(result) return 1;
120
121 // Seeked outside output buffer's range or not initialized: restart
122         if(current_position < codec->output_position ||
123                 current_position > codec->output_position + codec->output_size ||
124                 !codec->decode_initialized)
125         {
126                 quicktime_chunk_of_sample(&codec->output_position,
127                         &codec->chunk,
128                         trak,
129                         current_position);
130
131 //printf("decode 1 %lld %d\n", codec->output_position, codec->chunk);
132 // We know the first mp3 packet in the chunk has a pcm_offset from the encoding.
133                 codec->output_size = 0;
134                 codec->decode_initialized = 1;
135         }
136
137 // Decode chunks until output buffer covers requested range
138         while(codec->output_position + codec->output_size <
139                 current_position + samples &&
140                 try < 256)
141         {
142 // Load chunk into work buffer
143                 int64_t chunk_offset = 0;
144 //              int chunk_samples = quicktime_chunk_samples(trak, codec->chunk);
145                 int chunk_size = quicktime_chunk_bytes(file,
146                         &chunk_offset,
147                         codec->chunk,
148                         trak);
149 // Getting invalid numbers for this
150 //              int max_samples = chunk_samples * 2;
151                 int max_samples = 32768;
152                 int max_bytes = max_samples * sample_size;
153                 int bytes_decoded = 0;
154 //printf("decode 2 %x %jx %jx\n", chunk_size, chunk_offset, chunk_offset + chunk_size);
155
156 // Allocate packet buffer
157                 if(codec->packet_allocated < chunk_size &&
158                         codec->packet_buffer)
159                 {
160                         free(codec->packet_buffer);
161                         codec->packet_buffer = 0;
162                 }
163
164                 if(!codec->packet_buffer)
165                 {
166                         codec->packet_buffer = calloc(1, chunk_size);
167                         codec->packet_allocated = chunk_size;
168                 }
169
170 // Allocate work buffer
171                 if(max_bytes + codec->output_size * sample_size > codec->output_allocated * sample_size)
172                 {
173                         char *new_output = calloc(1, max_bytes + codec->output_size * sample_size);
174                         if(codec->work_buffer)
175                         {
176                                 memcpy(new_output, codec->work_buffer, codec->output_size * sample_size);
177                                 free(codec->work_buffer);
178                         }
179                         codec->work_buffer = new_output;
180                         codec->output_allocated = max_bytes + codec->output_size * sample_size;
181                 }
182
183                 quicktime_set_position(file, chunk_offset);
184                 result = !quicktime_read_data(file, codec->packet_buffer, chunk_size);
185                 if(result) break;
186
187 // Decode chunk into work buffer.
188                 pthread_mutex_lock(&ffmpeg_lock);
189 #if 0
190 #if LIBAVCODEC_VERSION_INT < ((52<<16)+(0<<8)+0)
191                 result = avcodec_decode_audio(codec->decoder_context,
192                         (int16_t*)(codec->work_buffer + codec->output_size * sample_size),
193                         &bytes_decoded,
194                         codec->packet_buffer,
195                         chunk_size);
196 #else
197                 bytes_decoded = OUTPUT_ALLOCATION;
198                 result = avcodec_decode_audio2(codec->decoder_context,
199                         (int16_t*)(codec->work_buffer + codec->output_size * sample_size),
200                         &bytes_decoded, codec->packet_buffer, chunk_size);
201 #endif
202 #else
203                 AVPacket avpkt;
204                 av_init_packet(&avpkt);
205                 avpkt.data = (unsigned char *)codec->packet_buffer;
206                 avpkt.size = chunk_size;
207                 bytes_decoded = OUTPUT_ALLOCATION;
208                 result = quicktime_decode_audio3(codec->decoder_context,
209                         (int16_t*)(codec->work_buffer + codec->output_size * sample_size),
210                         &bytes_decoded, &avpkt);
211 #endif
212
213                 pthread_mutex_unlock(&ffmpeg_lock);
214                 if(bytes_decoded <= 0)
215                 {
216                         try++;
217                 }
218                 else
219                 {
220                         if(codec->output_size * sample_size + bytes_decoded > codec->output_allocated * sample_size)
221                                 printf("decode: FYI: bytes_decoded=%ld is greater than output_allocated=%ld\n",
222                                         codec->output_size * sample_size + bytes_decoded,
223                                         codec->output_allocated);
224                         codec->output_size += bytes_decoded / sample_size;
225                         try = 0;
226                 }
227                 codec->chunk++;
228         }
229
230 //printf("decode 15 %d %lld %d\n", try, codec->output_position, codec->output_size);
231 // Transfer to output
232         if(output_i)
233         {
234                 int16_t *pcm_ptr = (int16_t*)codec->work_buffer +
235                         (current_position - codec->output_position) * track_map->channels +
236                         channel;
237                 for(i = current_position - codec->output_position, j = 0;
238                         j < samples && i < codec->output_size;
239                         j++, i++)
240                 {
241                         output_i[j] = *pcm_ptr;
242                         pcm_ptr += track_map->channels;
243                 }
244         }
245         else
246         if(output_f)
247         {
248                 int16_t *pcm_ptr = (int16_t*)codec->work_buffer +
249                         (current_position - codec->output_position) * track_map->channels +
250                         channel;
251                 for(i = current_position - codec->output_position, j = 0;
252                         j < samples && i < codec->output_size;
253                         j++, i++)
254                 {
255                         output_i[j] = (float)*pcm_ptr / (float)32767;
256                         pcm_ptr += track_map->channels;
257                 }
258         }
259
260 // Delete excess output
261         if(codec->output_size > OUTPUT_ALLOCATION)
262         {
263                 int sample_diff = codec->output_size - OUTPUT_ALLOCATION;
264                 int byte_diff = sample_diff * sample_size;
265                 memcpy(codec->work_buffer,
266                         codec->work_buffer + byte_diff,
267                         OUTPUT_ALLOCATION * sample_size);
268                 codec->output_size -= sample_diff;
269                 codec->output_position += sample_diff;
270         }
271
272         return 0;
273 }
274
275
276
277
278
279
280
281 static void init_codec_common(quicktime_audio_map_t *atrack)
282 {
283         quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
284
285 /* Init public items */
286         codec_base->delete_acodec = delete_codec;
287         codec_base->decode_audio = decode;
288
289
290 /* Init private items */
291 //      quicktime_wma_codec_t *codec =
292         codec_base->priv = calloc(1, sizeof(quicktime_wma_codec_t));
293 }
294
295
296 void quicktime_init_codec_wmav1(quicktime_audio_map_t *atrack)
297 {
298         quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
299         quicktime_wma_codec_t *codec;
300         init_codec_common(atrack);
301
302         codec = codec_base->priv;
303         codec_base->fourcc = QUICKTIME_WMA;
304         codec_base->title = "Win Media Audio 1";
305         codec_base->desc = "Win Media Audio 1";
306         codec_base->wav_id = 0x160;
307         codec->ffmpeg_id = CODEC_ID_WMAV1;
308 }
309
310
311 void quicktime_init_codec_wmav2(quicktime_audio_map_t *atrack)
312 {
313         quicktime_codec_t *codec_base = (quicktime_codec_t*)atrack->codec;
314         quicktime_wma_codec_t *codec;
315         init_codec_common(atrack);
316
317         codec = codec_base->priv;
318         codec_base->fourcc = QUICKTIME_WMA;
319         codec_base->title = "Win Media Audio 2";
320         codec_base->desc = "Win Media Audio 2";
321         codec_base->wav_id = 0x161;
322         codec->ffmpeg_id = CODEC_ID_WMAV2;
323 }