== FFMPEG ==
[blender.git] / intern / audaspace / ffmpeg / AUD_FFMPEGReader.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN LGPL LICENSE BLOCK *****
5  *
6  * Copyright 2009 Jörg Hermann Müller
7  *
8  * This file is part of AudaSpace.
9  *
10  * AudaSpace is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * AudaSpace is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with AudaSpace.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * ***** END LGPL LICENSE BLOCK *****
24  */
25
26 // needed for INT64_C
27 #ifndef __STDC_CONSTANT_MACROS
28 #define __STDC_CONSTANT_MACROS
29 #endif
30
31 #include "AUD_FFMPEGReader.h"
32
33 extern "C" {
34 #include <libavcodec/avcodec.h>
35 #include <libavformat/avformat.h>
36 }
37
38 int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer& buffer)
39 {
40         // save packet parameters
41         uint8_t *audio_pkg_data = packet->data;
42         int audio_pkg_size = packet->size;
43
44         int buf_size = buffer.getSize();
45         int buf_pos = 0;
46
47         int read_length, data_size;
48
49         // as long as there is still data in the package
50         while(audio_pkg_size > 0)
51         {
52                 // resize buffer if needed
53                 if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE)
54                 {
55                         buffer.resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true);
56                         buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE;
57                 }
58
59                 // read samples from the packet
60                 data_size = buf_size - buf_pos;
61                 /*read_length = avcodec_decode_audio3(m_codecCtx,
62                         (int16_t*)(((data_t*)buffer.getBuffer())+buf_pos),
63                         &data_size,
64                         packet);*/
65                 read_length = avcodec_decode_audio2(m_codecCtx,
66                                                 (int16_t*)(((data_t*)buffer.getBuffer()) + buf_pos),
67                                                 &data_size,
68                                                 audio_pkg_data,
69                                                 audio_pkg_size);
70
71                 // read error, next packet!
72                 if(read_length < 0)
73                         break;
74
75                 buf_pos += data_size;
76
77                 // move packet parameters
78                 audio_pkg_data += read_length;
79                 audio_pkg_size -= read_length;
80         }
81
82         return buf_pos;
83 }
84
85 static const char* streaminfo_error = "AUD_FFMPEGReader: Stream info couldn't "
86                                                                           "be found.";
87 static const char* noaudio_error = "AUD_FFMPEGReader: File doesn't include an "
88                                                                    "audio stream.";
89 static const char* nodecoder_error = "AUD_FFMPEGReader: No decoder found for "
90                                                                          "the audio stream.";
91 static const char* codecopen_error = "AUD_FFMPEGReader: Codec couldn't be "
92                                                                          "opened.";
93 static const char* format_error = "AUD_FFMPEGReader: Unsupported sample "
94                                                                   "format.";
95
96 void AUD_FFMPEGReader::init()
97 {
98         m_position = 0;
99         m_pkgbuf_left = 0;
100
101         if(av_find_stream_info(m_formatCtx)<0)
102                 AUD_THROW(AUD_ERROR_FFMPEG, streaminfo_error);
103
104         // find audio stream and codec
105         m_stream = -1;
106
107         for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
108         {
109                 if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
110                         && (m_stream < 0))
111                 {
112                         m_stream=i;
113                         break;
114                 }
115         }
116
117         if(m_stream == -1)
118                 AUD_THROW(AUD_ERROR_FFMPEG, noaudio_error);
119
120         m_codecCtx = m_formatCtx->streams[m_stream]->codec;
121
122         // get a decoder and open it
123         AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
124         if(!aCodec)
125                 AUD_THROW(AUD_ERROR_FFMPEG, nodecoder_error);
126
127         if(avcodec_open(m_codecCtx, aCodec)<0)
128                 AUD_THROW(AUD_ERROR_FFMPEG, codecopen_error);
129
130         // XXX this prints file information to stdout:
131         //dump_format(m_formatCtx, 0, NULL, 0);
132
133         m_specs.channels = (AUD_Channels) m_codecCtx->channels;
134
135         switch(m_codecCtx->sample_fmt)
136         {
137         case SAMPLE_FMT_U8:
138                 m_convert = AUD_convert_u8_float;
139                 m_specs.format = AUD_FORMAT_U8;
140                 break;
141         case SAMPLE_FMT_S16:
142                 m_convert = AUD_convert_s16_float;
143                 m_specs.format = AUD_FORMAT_S16;
144                 break;
145         case SAMPLE_FMT_S32:
146                 m_convert = AUD_convert_s32_float;
147                 m_specs.format = AUD_FORMAT_S32;
148                 break;
149         case SAMPLE_FMT_FLT:
150                 m_convert = AUD_convert_copy<float>;
151                 m_specs.format = AUD_FORMAT_FLOAT32;
152                 break;
153         case SAMPLE_FMT_DBL:
154                 m_convert = AUD_convert_double_float;
155                 m_specs.format = AUD_FORMAT_FLOAT64;
156                 break;
157         default:
158                 AUD_THROW(AUD_ERROR_FFMPEG, format_error);
159         }
160
161         m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
162 }
163
164 static const char* fileopen_error = "AUD_FFMPEGReader: File couldn't be "
165                                                                         "opened.";
166
167 AUD_FFMPEGReader::AUD_FFMPEGReader(std::string filename) :
168         m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
169         m_byteiocontext(NULL)
170 {
171         // open file
172         if(av_open_input_file(&m_formatCtx, filename.c_str(), NULL, 0, NULL)!=0)
173                 AUD_THROW(AUD_ERROR_FILE, fileopen_error);
174
175         try
176         {
177                 init();
178         }
179         catch(AUD_Exception&)
180         {
181                 av_close_input_file(m_formatCtx);
182                 throw;
183         }
184 }
185
186 static const char* streamopen_error = "AUD_FFMPEGReader: Stream couldn't be "
187                                                                           "opened.";
188
189 AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer) :
190                 m_pkgbuf(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1),
191                 m_membuffer(buffer)
192 {
193         m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
194
195         if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(),
196                                          buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
197         {
198                 av_free(m_byteiocontext);
199                 AUD_THROW(AUD_ERROR_FILE, fileopen_error);
200         }
201
202         AVProbeData probe_data;
203         probe_data.filename = "";
204         probe_data.buf = (data_t*)buffer.get()->getBuffer();
205         probe_data.buf_size = buffer.get()->getSize();
206         AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
207
208         // open stream
209         if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0)
210         {
211                 av_free(m_byteiocontext);
212                 AUD_THROW(AUD_ERROR_FILE, streamopen_error);
213         }
214
215         try
216         {
217                 init();
218         }
219         catch(AUD_Exception&)
220         {
221                 av_close_input_stream(m_formatCtx);
222                 av_free(m_byteiocontext);
223                 throw;
224         }
225 }
226
227 AUD_FFMPEGReader::~AUD_FFMPEGReader()
228 {
229         avcodec_close(m_codecCtx);
230
231         if(m_byteiocontext)
232         {
233                 av_close_input_stream(m_formatCtx);
234                 av_free(m_byteiocontext);
235         }
236         else
237                 av_close_input_file(m_formatCtx);
238 }
239
240 bool AUD_FFMPEGReader::isSeekable() const
241 {
242         return true;
243 }
244
245 void AUD_FFMPEGReader::seek(int position)
246 {
247         if(position >= 0)
248         {
249                 uint64_t st_time = m_formatCtx->start_time;
250                 uint64_t seek_pos = position * AV_TIME_BASE / m_specs.rate;
251
252                 if (seek_pos < 0) {
253                         seek_pos = 0;
254                 }
255
256                 if (st_time != AV_NOPTS_VALUE) {
257                         seek_pos += st_time;
258                 }
259
260                 double pts_time_base = 
261                         av_q2d(m_formatCtx->streams[m_stream]->time_base);
262                 uint64_t pts_st_time =
263                         ((st_time != AV_NOPTS_VALUE) ? st_time : 0)
264                         / pts_time_base / (uint64_t) AV_TIME_BASE;
265
266                 // a value < 0 tells us that seeking failed
267                 if(av_seek_frame(m_formatCtx, -1, seek_pos,
268                                  AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
269                 {
270                         avcodec_flush_buffers(m_codecCtx);
271                         m_position = position;
272
273                         AVPacket packet;
274                         bool search = true;
275
276                         while(search && av_read_frame(m_formatCtx, &packet) >= 0)
277                         {
278                                 // is it a frame from the audio stream?
279                                 if(packet.stream_index == m_stream)
280                                 {
281                                         // decode the package
282                                         m_pkgbuf_left = decode(&packet, m_pkgbuf);
283                                         search = false;
284
285                                         // check position
286                                         if(packet.pts != AV_NOPTS_VALUE)
287                                         {
288                                                 // calculate real position, and read to frame!
289                                                 m_position = (packet.pts - 
290                                                         pts_st_time) * pts_time_base * m_specs.rate;
291
292                                                 if(m_position < position)
293                                                 {
294                                                         // read until we're at the right position
295                                                         int length = AUD_DEFAULT_BUFFER_SIZE;
296                                                         sample_t* buffer;
297                                                         for(int len = position - m_position;
298                                                                 length == AUD_DEFAULT_BUFFER_SIZE;
299                                                                 len -= AUD_DEFAULT_BUFFER_SIZE)
300                                                         {
301                                                                 if(len < AUD_DEFAULT_BUFFER_SIZE)
302                                                                         length = len;
303                                                                 read(length, buffer);
304                                                         }
305                                                 }
306                                         }
307                                 }
308                                 av_free_packet(&packet);
309                         }
310                 }
311                 else
312                 {
313                         fprintf(stderr, "seeking failed!\n");
314                         // Seeking failed, do nothing.
315                 }
316         }
317 }
318
319 int AUD_FFMPEGReader::getLength() const
320 {
321         // return approximated remaning size
322         return (int)((m_formatCtx->duration * m_codecCtx->sample_rate)
323                                  / AV_TIME_BASE)-m_position;
324 }
325
326 int AUD_FFMPEGReader::getPosition() const
327 {
328         return m_position;
329 }
330
331 AUD_Specs AUD_FFMPEGReader::getSpecs() const
332 {
333         return m_specs.specs;
334 }
335
336 void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
337 {
338         // read packages and decode them
339         AVPacket packet;
340         int data_size = 0;
341         int pkgbuf_pos;
342         int left = length;
343         int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
344
345         // resize output buffer if necessary
346         if(m_buffer.getSize() < length * AUD_SAMPLE_SIZE(m_specs))
347                 m_buffer.resize(length * AUD_SAMPLE_SIZE(m_specs));
348
349         buffer = m_buffer.getBuffer();
350         pkgbuf_pos = m_pkgbuf_left;
351         m_pkgbuf_left = 0;
352
353         // there may still be data in the buffer from the last call
354         if(pkgbuf_pos > 0)
355         {
356                 data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
357                 m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(),
358                                   data_size / AUD_FORMAT_SIZE(m_specs.format));
359                 buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
360                 left -= data_size/sample_size;
361         }
362
363         // for each frame read as long as there isn't enough data already
364         while((left > 0) && (av_read_frame(m_formatCtx, &packet) >= 0))
365         {
366                 // is it a frame from the audio stream?
367                 if(packet.stream_index == m_stream)
368                 {
369                         // decode the package
370                         pkgbuf_pos = decode(&packet, m_pkgbuf);
371
372                         // copy to output buffer
373                         data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
374                         m_convert((data_t*) buffer, (data_t*) m_pkgbuf.getBuffer(),
375                                           data_size / AUD_FORMAT_SIZE(m_specs.format));
376                         buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
377                         left -= data_size/sample_size;
378                 }
379                 av_free_packet(&packet);
380         }
381         // read more data than necessary?
382         if(pkgbuf_pos > data_size)
383         {
384                 m_pkgbuf_left = pkgbuf_pos-data_size;
385                 memmove(m_pkgbuf.getBuffer(),
386                                 ((data_t*)m_pkgbuf.getBuffer())+data_size,
387                                 pkgbuf_pos-data_size);
388         }
389
390         buffer = m_buffer.getBuffer();
391
392         if(left > 0)
393                 length -= left;
394         m_position += length;
395 }