=== Custom Transform Orientation ===
[blender.git] / source / blender / src / hddaudio.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * Contributor(s): Peter Schlaile <peter [at] schlaile [dot] de> 2005
24  *
25  * ***** END GPL/BL DUAL LICENSE BLOCK *****
26  */
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <math.h>
31 #include <string.h>
32 #include <fcntl.h>
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #ifdef WITH_FFMPEG
39 #include <ffmpeg/avformat.h>
40 #include <ffmpeg/avcodec.h>
41 #include <ffmpeg/rational.h>
42 #if LIBAVFORMAT_VERSION_INT < (49 << 16)
43 #define FFMPEG_OLD_FRAME_RATE 1
44 #else
45 #define FFMPEG_CODEC_IS_POINTER 1
46 #endif
47 #endif
48
49 #include "MEM_guardedalloc.h"
50
51 #include "BIF_editsound.h"
52
53 #include "blendef.h"
54
55 #ifdef WITH_FFMPEG
56 extern void do_init_ffmpeg();
57 #endif
58
59 struct hdaudio {
60         int sample_rate;
61         int channels;
62         int audioStream;
63
64 #ifdef WITH_FFMPEG
65         char * filename;
66         AVCodec *pCodec;
67         AVFormatContext *pFormatCtx;
68         AVCodecContext *pCodecCtx;
69         int frame_position;
70         int frame_duration;
71         int frame_alloc_duration;
72         int decode_pos;
73         int frame_size;
74         short * decode_cache;
75         short * decode_cache_zero;
76         short * resample_cache;
77         int decode_cache_size;
78         int target_channels;
79         int target_rate;
80         int resample_samples_written;
81         int resample_samples_in;
82         ReSampleContext *resampler;
83 #else
84         
85
86 #endif
87 };
88
89 #ifdef WITH_FFMPEG
90 #ifdef FFMPEG_CODEC_IS_POINTER
91 static AVCodecContext* get_codec_from_stream(AVStream* stream)
92 {
93         return stream->codec;
94 }
95 #else
96 static AVCodecContext* get_codec_from_stream(AVStream* stream)
97 {
98         return &stream->codec;
99 }
100 #endif
101 #endif
102
103 struct hdaudio * sound_open_hdaudio(char * filename)
104 {
105 #ifdef WITH_FFMPEG
106         struct hdaudio * rval;
107         int            i, audioStream;
108
109         AVCodec *pCodec;
110         AVFormatContext *pFormatCtx;
111         AVCodecContext *pCodecCtx;
112
113         do_init_ffmpeg();
114
115         if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0) {
116                 return 0;
117         }
118
119         if(av_find_stream_info(pFormatCtx)<0) {
120                 av_close_input_file(pFormatCtx);
121                 return 0;
122         }
123
124         dump_format(pFormatCtx, 0, filename, 0);
125
126
127         /* Find the first audio stream */
128         audioStream=-1;
129         for(i=0; i<pFormatCtx->nb_streams; i++)
130                 if(get_codec_from_stream(pFormatCtx->streams[i])
131                    ->codec_type == CODEC_TYPE_AUDIO)
132                 {
133                         audioStream=i;
134                         break;
135                 }
136
137         if(audioStream == -1) {
138                 av_close_input_file(pFormatCtx);
139                 return 0;
140         }
141
142         pCodecCtx = get_codec_from_stream(pFormatCtx->streams[audioStream]);
143
144         /* Find the decoder for the audio stream */
145         pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
146         if(pCodec == NULL) {
147                 av_close_input_file(pFormatCtx);
148                 return 0;
149         }
150
151         if(avcodec_open(pCodecCtx, pCodec)<0) {
152                 av_close_input_file(pFormatCtx);
153                 return 0;
154         }
155
156         rval = (struct hdaudio *)MEM_mallocN(sizeof(struct hdaudio), 
157                                              "hdaudio struct");
158
159         rval->filename = strdup(filename);
160         rval->sample_rate = pCodecCtx->sample_rate;
161         rval->channels = pCodecCtx->channels;
162
163         rval->pFormatCtx = pFormatCtx;
164         rval->pCodecCtx = pCodecCtx;
165         rval->pCodec = pCodec;
166         rval->audioStream = audioStream;
167         rval->frame_position = -10;
168
169         rval->frame_duration = AV_TIME_BASE / 10;
170         rval->frame_alloc_duration = AV_TIME_BASE;
171         rval->decode_cache_size = 
172                 (long long) rval->sample_rate * rval->channels
173                 * rval->frame_alloc_duration / AV_TIME_BASE
174                 * 2;
175
176         rval->decode_cache = (short*) MEM_mallocN(
177                 rval->decode_cache_size * sizeof(short)
178                 + AVCODEC_MAX_AUDIO_FRAME_SIZE, 
179                 "hdaudio decode cache");
180         rval->decode_cache_zero = rval->decode_cache;
181         rval->decode_pos = 0;
182         rval->target_channels = -1;
183         rval->target_rate = -1;
184         rval->resampler = 0;
185         rval->resample_cache = 0;
186         rval->resample_samples_written = 0;
187         rval->resample_samples_in = 0;
188         return rval;
189 #else
190         return 0;
191 #endif
192 }
193
194 struct hdaudio * sound_copy_hdaudio(struct hdaudio * c)
195 {
196 #ifdef WITH_FFMPEG
197         return sound_open_hdaudio(c->filename);
198 #else
199         return 0;
200 #endif
201 }
202
203 long sound_hdaudio_get_duration(struct hdaudio * hdaudio, double frame_rate)
204 {
205 #ifdef WITH_FFMPEG
206         return hdaudio->pFormatCtx->duration * frame_rate / AV_TIME_BASE;
207 #else
208         return 0;
209 #endif
210 }
211
212 #ifdef WITH_FFMPEG
213 static void sound_hdaudio_extract_small_block(
214         struct hdaudio * hdaudio, 
215         short * target_buffer,
216         int sample_position /* units of target_rate */,
217         int target_rate,
218         int target_channels,
219         int nb_samples /* in target */)
220 {
221         AVPacket packet;
222         int frame_position;
223         int frame_size = (long long) target_rate 
224                 * hdaudio->frame_duration / AV_TIME_BASE;
225         int in_frame_size = (long long) hdaudio->sample_rate
226                 * hdaudio->frame_duration / AV_TIME_BASE;
227         int rate_conversion = 
228                 (target_rate != hdaudio->sample_rate) 
229                 || (target_channels != hdaudio->channels);
230         int sample_ofs = target_channels * (sample_position % frame_size);
231
232         frame_position = sample_position / frame_size; 
233
234         if (hdaudio == 0) return;
235
236         if (rate_conversion) {
237                 if (hdaudio->resampler && 
238                     (hdaudio->target_rate != target_rate
239                      || hdaudio->target_channels != target_channels)) {
240                         audio_resample_close(hdaudio->resampler);
241                         hdaudio->resampler = 0;
242                 }
243                 if (!hdaudio->resampler) {
244                         hdaudio->resampler = audio_resample_init(
245                                 target_channels, hdaudio->channels,
246                                 target_rate, hdaudio->sample_rate);
247                         hdaudio->target_rate = target_rate;
248                         hdaudio->target_channels = target_channels;
249                         if (hdaudio->resample_cache) {
250                                 MEM_freeN(hdaudio->resample_cache);
251                         }
252                         
253
254                         hdaudio->resample_cache = (short*) MEM_mallocN(
255                                 (long long) 
256                                 hdaudio->target_channels 
257                                 * frame_size * 2
258                                 * sizeof(short), 
259                                 "hdaudio resample cache");
260                         if (frame_position == hdaudio->frame_position) {
261                                 hdaudio->resample_samples_in = 
262                                         in_frame_size * 7 / 4;
263                                 hdaudio->resample_samples_written
264                                         = audio_resample(
265                                                 hdaudio->resampler,
266                                                 hdaudio->resample_cache,
267                                                 hdaudio->decode_cache_zero,
268                                                 in_frame_size * 7 / 4);
269                         }
270                 }
271         }
272
273         if (frame_position == hdaudio->frame_position + 1
274             && in_frame_size * hdaudio->channels <= hdaudio->decode_pos) {
275                 int bl_size = in_frame_size * hdaudio->channels;
276                 int decode_pos = hdaudio->decode_pos;
277                
278                 hdaudio->frame_position = frame_position;
279
280                 memmove(hdaudio->decode_cache,
281                         hdaudio->decode_cache + bl_size,
282                         (decode_pos - bl_size) * sizeof(short));
283                 
284                 decode_pos -= bl_size;
285
286                 memset(hdaudio->decode_cache + decode_pos, 0,
287                        (hdaudio->decode_cache_size - decode_pos) 
288                        * sizeof(short));
289                        
290
291                 while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) {
292                         int data_size;
293                         int len;
294                         uint8_t *audio_pkt_data;
295                         int audio_pkt_size;
296
297                         if(packet.stream_index != hdaudio->audioStream) {
298                                 av_free_packet(&packet);
299                                 continue;
300                         }
301
302                         audio_pkt_data = packet.data;
303                         audio_pkt_size = packet.size;
304
305                         while (audio_pkt_size > 0) {
306                                 len = avcodec_decode_audio(
307                                         hdaudio->pCodecCtx, 
308                                         hdaudio->decode_cache 
309                                         + decode_pos, 
310                                         &data_size, 
311                                         audio_pkt_data, 
312                                         audio_pkt_size);
313                                 if (len <= 0) {
314                                         audio_pkt_size = 0;
315                                         break;
316                                 }
317                                 
318                                 audio_pkt_size -= len;
319                                 audio_pkt_data += len;
320
321                                 if (data_size <= 0) {
322                                         continue;
323                                 }
324                                 
325                                 decode_pos += data_size / sizeof(short);
326                                 if (decode_pos + data_size
327                                     / sizeof(short)
328                                     > hdaudio->decode_cache_size) {
329                                         break;
330                                 }
331                         }
332                         av_free_packet(&packet);
333
334                         if (decode_pos + data_size / sizeof(short)
335                             > hdaudio->decode_cache_size) {
336                                 break;
337                         }
338                 }
339
340                 if (rate_conversion) {
341                         int written = hdaudio->resample_samples_written
342                                 * target_channels;
343                         int ofs = target_channels * frame_size;
344                         int recycle = written - ofs;
345                         int next_in = in_frame_size 
346                                 + (3.0/4.0 
347                                    - (double) recycle / (double) 
348                                    (frame_size * target_channels)
349                                         ) * in_frame_size;
350
351                         memmove(hdaudio->resample_cache,
352                                 hdaudio->resample_cache + ofs,
353                                 recycle * sizeof(short));
354
355                         hdaudio->resample_samples_written
356                                = audio_resample(
357                                        hdaudio->resampler,
358                                        hdaudio->resample_cache + recycle,
359                                        hdaudio->decode_cache_zero
360                                        + hdaudio->resample_samples_in
361                                        * hdaudio->channels
362                                        - bl_size,
363                                        next_in)
364                                 + recycle / target_channels;
365
366                         hdaudio->resample_samples_in = next_in;
367                 }
368
369                 hdaudio->decode_pos = decode_pos;
370         }
371
372         if (frame_position != hdaudio->frame_position) { 
373                 long decode_pos = 0;
374                 long long st_time = hdaudio->pFormatCtx
375                         ->streams[hdaudio->audioStream]->start_time;
376                 double time_base = 
377                         av_q2d(hdaudio->pFormatCtx
378                                ->streams[hdaudio->audioStream]->time_base);
379                 long long pos = (long long) frame_position * AV_TIME_BASE
380                         * hdaudio->frame_duration / AV_TIME_BASE;
381
382                 long long seek_pos;
383
384                 hdaudio->frame_position = frame_position;
385
386                 if (st_time == AV_NOPTS_VALUE) {
387                         st_time = 0;
388                 }
389
390                 pos += st_time * AV_TIME_BASE * time_base;
391
392                 /* seek a little bit before the target position,
393                    (ffmpeg seek algorithm doesn't seem to work always as
394                    specified...)
395                 */
396
397                 seek_pos = pos - (AV_TIME_BASE
398                                  * hdaudio->frame_duration 
399                                   / AV_TIME_BASE / 10);
400                 if (seek_pos < 0) {
401                         seek_pos = pos;
402                 }
403
404                 av_seek_frame(hdaudio->pFormatCtx, -1, 
405                               seek_pos, 
406                               AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD);
407                 avcodec_flush_buffers(hdaudio->pCodecCtx);
408
409                 memset(hdaudio->decode_cache, 0,
410                        hdaudio->decode_cache_size * sizeof(short));
411
412                 hdaudio->decode_cache_zero = hdaudio->decode_cache;
413
414                 while(av_read_frame(hdaudio->pFormatCtx, &packet) >= 0) {
415                         int data_size;
416                         int len;
417                         uint8_t *audio_pkt_data;
418                         int audio_pkt_size;
419
420                         if(packet.stream_index != hdaudio->audioStream) {
421                                 av_free_packet(&packet);
422                                 continue;
423                         }
424
425                         audio_pkt_data = packet.data;
426                         audio_pkt_size = packet.size;
427
428                         if (!hdaudio->decode_cache_zero 
429                             && audio_pkt_size > 0) { 
430                                 long long diff;
431
432                                 if (packet.pts == AV_NOPTS_VALUE) {
433                                         fprintf(stderr,
434                                                 "hdaudio: audio "
435                                                 "pts=NULL audio "
436                                                 "distortion!\n");
437                                         diff = 0;
438                                 } else {
439                                         long long pts = packet.pts;
440                                         long long spts = (long long) (
441                                                 pos / time_base / AV_TIME_BASE 
442                                                 + 0.5);
443                                         diff = spts - pts;
444                                         if (diff < 0) {
445                                                 fprintf(stderr,
446                                                         "hdaudio: "
447                                                         "negative seek: "
448                                                         "%lld < %lld "
449                                                         "(pos=%lld) "
450                                                         "audio distortion!!\n",
451                                                         spts, pts, pos);
452                                                 diff = 0;
453                                         }
454                                 }
455
456
457                                 diff *= hdaudio->sample_rate * time_base;
458                                 diff *= hdaudio->channels;
459
460                                 if (diff > hdaudio->decode_cache_size / 2) {
461                                         fprintf(stderr,
462                                                 "hdaudio: audio "
463                                                 "diff too large!!\n");
464                                         diff = 0;
465                                 }
466
467                                 hdaudio->decode_cache_zero
468                                         = hdaudio->decode_cache + diff;
469                         }
470
471                         while (audio_pkt_size > 0) {
472                                 len = avcodec_decode_audio(
473                                         hdaudio->pCodecCtx, 
474                                         hdaudio->decode_cache 
475                                         + decode_pos, 
476                                         &data_size, 
477                                         audio_pkt_data, 
478                                         audio_pkt_size);
479                                 if (len <= 0) {
480                                         audio_pkt_size = 0;
481                                         break;
482                                 }
483                                 
484                                 audio_pkt_size -= len;
485                                 audio_pkt_data += len;
486
487                                 if (data_size <= 0) {
488                                         continue;
489                                 }
490                                 
491                                 decode_pos += data_size / sizeof(short);
492                                 if (decode_pos + data_size
493                                     / sizeof(short)
494                                     > hdaudio->decode_cache_size) {
495                                         break;
496                                 }
497                         }
498         
499                         av_free_packet(&packet);
500
501                         if (decode_pos + data_size / sizeof(short)
502                             > hdaudio->decode_cache_size) {
503                                 break;
504                         }
505                 }
506                 if (rate_conversion) {
507                         hdaudio->resample_samples_written
508                                 = audio_resample(hdaudio->resampler,
509                                                  hdaudio->resample_cache,
510                                                  hdaudio->decode_cache_zero,
511                                                  in_frame_size * 7 / 4);
512                         hdaudio->resample_samples_in = 
513                                 in_frame_size * 7 / 4;
514                 }
515                 hdaudio->decode_pos = decode_pos;
516         }
517
518         memcpy(target_buffer, (rate_conversion 
519                                ? hdaudio->resample_cache 
520                                : hdaudio->decode_cache_zero) + sample_ofs, 
521                nb_samples * target_channels * sizeof(short));
522 }
523 #endif
524
525
526 void sound_hdaudio_extract(struct hdaudio * hdaudio, 
527                            short * target_buffer,
528                            int sample_position /* units of target_rate */,
529                            int target_rate,
530                            int target_channels,
531                            int nb_samples /* in target */)
532 {
533 #ifdef WITH_FFMPEG
534         long long max_samples = (long long) target_rate 
535                 * hdaudio->frame_duration / AV_TIME_BASE / 4;
536
537         while (nb_samples > max_samples) {
538                 sound_hdaudio_extract_small_block(hdaudio, target_buffer,
539                                                   sample_position,
540                                                   target_rate,
541                                                   target_channels,
542                                                   max_samples);
543                 target_buffer += max_samples * target_channels;
544                 sample_position += max_samples;
545                 nb_samples -= max_samples;
546         }
547         if (nb_samples > 0) {
548                 sound_hdaudio_extract_small_block(hdaudio, target_buffer,
549                                                   sample_position,
550                                                   target_rate,
551                                                   target_channels,
552                                                   nb_samples);
553         }
554 #else
555
556 #endif  
557 }
558                            
559 void sound_close_hdaudio(struct hdaudio * hdaudio)
560 {
561 #ifdef WITH_FFMPEG
562
563         if (hdaudio) {
564                 avcodec_close(hdaudio->pCodecCtx);
565                 av_close_input_file(hdaudio->pFormatCtx);
566                 MEM_freeN (hdaudio->decode_cache);
567                 if (hdaudio->resample_cache) {
568                         MEM_freeN(hdaudio->resample_cache);
569                 }
570                 free(hdaudio->filename);
571                 MEM_freeN (hdaudio);
572         }
573 #else
574
575 #endif
576 }
577