copy of docs from 2.4x for python modules that have been kept
[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 #define __STDC_CONSTANT_MACROS
28
29 #include "AUD_FFMPEGReader.h"
30 #include "AUD_Buffer.h"
31
32 extern "C" {
33 #include <libavcodec/avcodec.h>
34 #include <libavformat/avformat.h>
35 }
36
37 int AUD_FFMPEGReader::decode(AVPacket* packet, AUD_Buffer* buffer)
38 {
39         // save packet parameters
40         uint8_t *audio_pkg_data = packet->data;
41         int audio_pkg_size = packet->size;
42
43         int buf_size = buffer->getSize();
44         int buf_pos = 0;
45
46         int read_length, data_size;
47
48         // as long as there is still data in the package
49         while(audio_pkg_size > 0)
50         {
51                 // resize buffer if needed
52                 if(buf_size - buf_pos < AVCODEC_MAX_AUDIO_FRAME_SIZE)
53                 {
54                         buffer->resize(buf_size + AVCODEC_MAX_AUDIO_FRAME_SIZE, true);
55                         buf_size += AVCODEC_MAX_AUDIO_FRAME_SIZE;
56                 }
57
58                 // read samples from the packet
59                 data_size = buf_size - buf_pos;
60                 /*read_length = avcodec_decode_audio3(m_codecCtx,
61                         (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
62                         &data_size,
63                         packet);*/
64                 read_length = avcodec_decode_audio2(m_codecCtx,
65                         (int16_t*)(((data_t*)buffer->getBuffer())+buf_pos),
66                         &data_size,
67                         audio_pkg_data,
68                         audio_pkg_size);
69
70                 buf_pos += data_size;
71
72                 // read error, next packet!
73                 if(read_length < 0)
74                         break;
75
76                 // move packet parameters
77                 audio_pkg_data += read_length;
78                 audio_pkg_size -= read_length;
79         }
80
81         return buf_pos;
82 }
83
84 void AUD_FFMPEGReader::init()
85 {
86         m_position = 0;
87         m_pkgbuf_left = 0;
88
89         if(av_find_stream_info(m_formatCtx)<0)
90                 AUD_THROW(AUD_ERROR_FFMPEG);
91
92         // find audio stream and codec
93         m_stream = -1;
94
95         for(unsigned int i = 0; i < m_formatCtx->nb_streams; i++)
96                 if((m_formatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO)
97                         && (m_stream < 0))
98                 {
99                         m_stream=i;
100                         break;
101                 }
102         if(m_stream == -1)
103                 AUD_THROW(AUD_ERROR_FFMPEG);
104
105         m_codecCtx = m_formatCtx->streams[m_stream]->codec;
106
107         // get a decoder and open it
108         AVCodec *aCodec = avcodec_find_decoder(m_codecCtx->codec_id);
109         if(!aCodec)
110                 AUD_THROW(AUD_ERROR_FFMPEG);
111
112         if(avcodec_open(m_codecCtx, aCodec)<0)
113                 AUD_THROW(AUD_ERROR_FFMPEG);
114
115         // XXX this prints file information to stdout:
116         //dump_format(m_formatCtx, 0, NULL, 0);
117
118         m_specs.channels = (AUD_Channels) m_codecCtx->channels;
119
120         switch(m_codecCtx->sample_fmt)
121         {
122         case SAMPLE_FMT_U8:
123                 m_convert = AUD_convert_u8_float;
124                 m_specs.format = AUD_FORMAT_U8;
125                 break;
126         case SAMPLE_FMT_S16:
127                 m_convert = AUD_convert_s16_float;
128                 m_specs.format = AUD_FORMAT_S16;
129                 break;
130         case SAMPLE_FMT_S32:
131                 m_convert = AUD_convert_s32_float;
132                 m_specs.format = AUD_FORMAT_S32;
133                 break;
134         case SAMPLE_FMT_FLT:
135                 m_convert = AUD_convert_copy<float>;
136                 m_specs.format = AUD_FORMAT_FLOAT32;
137                 break;
138         case SAMPLE_FMT_DBL:
139                 m_convert = AUD_convert_double_float;
140                 m_specs.format = AUD_FORMAT_FLOAT64;
141                 break;
142         default:
143                 AUD_THROW(AUD_ERROR_FILE);
144         }
145
146         m_specs.rate = (AUD_SampleRate) m_codecCtx->sample_rate;
147
148         // last but not least if there hasn't been any error, create the buffers
149         m_buffer = new AUD_Buffer(); AUD_NEW("buffer")
150         m_pkgbuf = new AUD_Buffer(AVCODEC_MAX_AUDIO_FRAME_SIZE<<1);
151         AUD_NEW("buffer")
152 }
153
154 AUD_FFMPEGReader::AUD_FFMPEGReader(const char* filename)
155 {
156         m_byteiocontext = NULL;
157
158         // open file
159         if(av_open_input_file(&m_formatCtx, filename, NULL, 0, NULL)!=0)
160                 AUD_THROW(AUD_ERROR_FILE);
161
162         try
163         {
164                 init();
165         }
166         catch(AUD_Exception)
167         {
168                 av_close_input_file(m_formatCtx);
169                 throw;
170         }
171 }
172
173 AUD_FFMPEGReader::AUD_FFMPEGReader(AUD_Reference<AUD_Buffer> buffer)
174 {
175         m_byteiocontext = (ByteIOContext*)av_mallocz(sizeof(ByteIOContext));
176         AUD_NEW("byteiocontext")
177         m_membuffer = buffer;
178
179         if(init_put_byte(m_byteiocontext, (data_t*)buffer.get()->getBuffer(),
180                                          buffer.get()->getSize(), 0, NULL, NULL, NULL, NULL) != 0)
181                 AUD_THROW(AUD_ERROR_FILE);
182
183         AVProbeData probe_data;
184         probe_data.filename = "";
185         probe_data.buf = (data_t*)buffer.get()->getBuffer();
186         probe_data.buf_size = buffer.get()->getSize();
187         AVInputFormat* fmt = av_probe_input_format(&probe_data, 1);
188
189         // open stream
190         if(av_open_input_stream(&m_formatCtx, m_byteiocontext, "", fmt, NULL)!=0)
191                 AUD_THROW(AUD_ERROR_FILE);
192
193         try
194         {
195                 init();
196         }
197         catch(AUD_Exception)
198         {
199                 av_close_input_stream(m_formatCtx);
200                 av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
201                 throw;
202         }
203 }
204
205 AUD_FFMPEGReader::~AUD_FFMPEGReader()
206 {
207         avcodec_close(m_codecCtx);
208
209         if(m_byteiocontext)
210         {
211                 av_close_input_stream(m_formatCtx);
212                 av_free(m_byteiocontext); AUD_DELETE("byteiocontext")
213         }
214         else
215                 av_close_input_file(m_formatCtx);
216
217         delete m_buffer; AUD_DELETE("buffer")
218         delete m_pkgbuf; AUD_DELETE("buffer")
219 }
220
221 bool AUD_FFMPEGReader::isSeekable()
222 {
223         return true;
224 }
225
226 void AUD_FFMPEGReader::seek(int position)
227 {
228         if(position >= 0)
229         {
230                 // a value < 0 tells us that seeking failed
231                 if(av_seek_frame(m_formatCtx,
232                                                  -1,
233                                                  (uint64_t)(((uint64_t)position *
234                                                                          (uint64_t)AV_TIME_BASE) /
235                                                                         (uint64_t)m_specs.rate),
236                                                  AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_ANY) >= 0)
237                 {
238                         avcodec_flush_buffers(m_codecCtx);
239                         m_position = position;
240
241                         AVPacket packet;
242                         bool search = true;
243
244                         while(search && av_read_frame(m_formatCtx, &packet) >= 0)
245                         {
246                                 // is it a frame from the audio stream?
247                                 if(packet.stream_index == m_stream)
248                                 {
249                                         // decode the package
250                                         m_pkgbuf_left = decode(&packet, m_pkgbuf);
251                                         search = false;
252
253                                         // check position
254                                         if(packet.pts != AV_NOPTS_VALUE)
255                                         {
256                                                 // calculate real position, and read to frame!
257                                                 m_position = packet.pts *
258                                                         av_q2d(m_formatCtx->streams[m_stream]->time_base) *
259                                                         m_specs.rate;
260
261                                                 if(m_position < position)
262                                                 {
263                                                         sample_t* buf;
264                                                         int length = position - m_position;
265                                                         read(length, buf);
266                                                 }
267                                         }
268                                 }
269                                 av_free_packet(&packet);
270                         }
271                 }
272                 else
273                 {
274                         // Seeking failed, do nothing.
275                 }
276         }
277 }
278
279 int AUD_FFMPEGReader::getLength()
280 {
281         // return approximated remaning size
282         return (int)((m_formatCtx->duration * m_codecCtx->sample_rate)
283                                  / AV_TIME_BASE)-m_position;
284 }
285
286 int AUD_FFMPEGReader::getPosition()
287 {
288         return m_position;
289 }
290
291 AUD_Specs AUD_FFMPEGReader::getSpecs()
292 {
293         return m_specs.specs;
294 }
295
296 AUD_ReaderType AUD_FFMPEGReader::getType()
297 {
298         return AUD_TYPE_STREAM;
299 }
300
301 bool AUD_FFMPEGReader::notify(AUD_Message &message)
302 {
303         return false;
304 }
305
306 void AUD_FFMPEGReader::read(int & length, sample_t* & buffer)
307 {
308         // read packages and decode them
309         AVPacket packet;
310         int data_size = 0;
311         int pkgbuf_pos;
312         int left = length;
313         int sample_size = AUD_DEVICE_SAMPLE_SIZE(m_specs);
314
315         // resize output buffer if necessary
316         if(m_buffer->getSize() < length * AUD_SAMPLE_SIZE(m_specs))
317                 m_buffer->resize(length * AUD_SAMPLE_SIZE(m_specs));
318
319         buffer = m_buffer->getBuffer();
320         pkgbuf_pos = m_pkgbuf_left;
321         m_pkgbuf_left = 0;
322
323         // there may still be data in the buffer from the last call
324         if(pkgbuf_pos > 0)
325         {
326                 data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
327                 m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
328                                   data_size / AUD_FORMAT_SIZE(m_specs.format));
329                 buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
330                 left -= data_size/sample_size;
331         }
332
333         // for each frame read as long as there isn't enough data already
334         while((left > 0) && (av_read_frame(m_formatCtx, &packet) >= 0))
335         {
336                 // is it a frame from the audio stream?
337                 if(packet.stream_index == m_stream)
338                 {
339                         // decode the package
340                         pkgbuf_pos = decode(&packet, m_pkgbuf);
341
342                         // copy to output buffer
343                         data_size = AUD_MIN(pkgbuf_pos, left * sample_size);
344                         m_convert((data_t*) buffer, (data_t*) m_pkgbuf->getBuffer(),
345                                           data_size / AUD_FORMAT_SIZE(m_specs.format));
346                         buffer += data_size / AUD_FORMAT_SIZE(m_specs.format);
347                         left -= data_size/sample_size;
348                 }
349                 av_free_packet(&packet);
350         }
351         // read more data than necessary?
352         if(pkgbuf_pos > data_size)
353         {
354                 m_pkgbuf_left = pkgbuf_pos-data_size;
355                 memmove(m_pkgbuf->getBuffer(),
356                                 ((data_t*)m_pkgbuf->getBuffer())+data_size,
357                                 pkgbuf_pos-data_size);
358         }
359
360         buffer = m_buffer->getBuffer();
361
362         if(left > 0)
363                 length -= left;
364         m_position += length;
365 }