1 /* spek-audio.cc
2  *
3  * Copyright (C) 2010-2013  Alexander Kojevnikov <alexander@kojevnikov.com>
4  *
5  * Spek is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * Spek is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with Spek.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 extern "C" {
20 #define __STDC_CONSTANT_MACROS
21 #include <libavformat/avformat.h>
22 #include <libavcodec/avcodec.h>
23 #include <libavutil/mathematics.h>
24 }
25 
26 #include "spek-audio.h"
27 
28 class AudioFileImpl : public AudioFile
29 {
30 public:
31     AudioFileImpl(
32         AudioError error, AVFormatContext *format_context, int audio_stream,
33         const std::string& codec_name, int bit_rate, int sample_rate, int bits_per_sample,
34         int channels, double duration, bool is_planar, int width, bool fp
35     );
36     ~AudioFileImpl() override;
37     void start(int samples) override;
38     int read() override;
39 
40     AudioError get_error() const override { return this->error; }
41     std::string get_codec_name() const override { return this->codec_name; }
42     int get_bit_rate() const override { return this->bit_rate; }
43     int get_sample_rate() const override { return this->sample_rate; }
44     int get_bits_per_sample() const override { return this->bits_per_sample; }
45     int get_channels() const override { return this->channels; }
46     double get_duration() const override { return this->duration; }
47     int get_width() const override { return this->width; }
48     bool get_fp() const override { return this->fp; }
49     const uint8_t *get_buffer() const override { return this->buffer; }
50     int64_t get_frames_per_interval() const override { return this->frames_per_interval; }
51     int64_t get_error_per_interval() const override { return this->error_per_interval; }
52     int64_t get_error_base() const override { return this->error_base; }
53 
54 private:
55     AudioError error;
56     AVFormatContext *format_context;
57     int audio_stream;
58     std::string codec_name;
59     int bit_rate;
60     int sample_rate;
61     int bits_per_sample;
62     int channels;
63     double duration;
64     bool is_planar;
65     int width;
66     bool fp;
67 
68     AVPacket packet;
69     int offset;
70     AVFrame *frame;
71     int buffer_size;
72     uint8_t *buffer;
73     // TODO: these guys don't belong here, move them somewhere else when revamping the pipeline
74     int64_t frames_per_interval;
75     int64_t error_per_interval;
76     int64_t error_base;
77 };
78 
79 
80 Audio::Audio()
81 {
82     av_register_all();
83 }
84 
85 std::unique_ptr<AudioFile> Audio::open(const std::string& file_name)
86 {
87     AudioError error = AudioError::OK;
88 
89     AVFormatContext *format_context = nullptr;
90     if (avformat_open_input(&format_context, file_name.c_str(), nullptr, nullptr) != 0) {
91         error = AudioError::CANNOT_OPEN_FILE;
92     }
93 
94     if (!error && avformat_find_stream_info(format_context, nullptr) < 0) {
95         // 24-bit APE returns an error but parses the stream info just fine.
96         // TODO: old comment, verify
97         if (format_context->nb_streams <= 0) {
98             error = AudioError::NO_STREAMS;
99         }
100     }
101 
102     int audio_stream = -1;
103     if (!error) {
104         for (unsigned int i = 0; i < format_context->nb_streams; i++) {
105             if (format_context->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
106                 audio_stream = i;
107                 break;
108             }
109         }
110     }
111     if (audio_stream == -1) {
112         error = AudioError::NO_AUDIO;
113     }
114 
115     AVStream *stream = nullptr;
116     AVCodecContext *codec_context = nullptr;
117     AVCodec *codec = nullptr;
118     if (!error) {
119         stream = format_context->streams[audio_stream];
120         codec_context = stream->codec;
121         codec = avcodec_find_decoder(codec_context->codec_id);
122         if (!codec) {
123             error = AudioError::NO_DECODER;
124         }
125     }
126 
127     std::string codec_name;
128     int bit_rate = 0;
129     int sample_rate = 0;
130     int bits_per_sample = 0;
131     int channels = 0;
132     double duration = 0;
133     if (!error) {
134         // We can already fill in the stream info even if the codec won't be able to open it.
135         codec_name = codec->long_name;
136         bit_rate = codec_context->bit_rate;
137         sample_rate = codec_context->sample_rate;
138         bits_per_sample = codec_context->bits_per_raw_sample;
139         if (!bits_per_sample) {
140             // APE uses bpcs, FLAC uses bprs.
141             // TODO: old comment, verify
142             bits_per_sample = codec_context->bits_per_coded_sample;
143         }
144         channels = codec_context->channels;
145 
146         if (stream->duration != AV_NOPTS_VALUE) {
147             duration = stream->duration * av_q2d(stream->time_base);
148         } else if (format_context->duration != AV_NOPTS_VALUE) {
149             duration = format_context->duration / (double) AV_TIME_BASE;
150         } else {
151             error = AudioError::NO_DURATION;
152         }
153 
154         if (!error && channels <= 0) {
155             error = AudioError::NO_CHANNELS;
156         }
157     }
158 
159     if (!error && avcodec_open2(codec_context, codec, nullptr) < 0) {
160         error = AudioError::CANNOT_OPEN_DECODER;
161     }
162 
163     bool is_planar = false;
164     int width = 0;
165     bool fp = false;
166     if (!error) {
167         is_planar = av_sample_fmt_is_planar(codec_context->sample_fmt);
168         width = av_get_bytes_per_sample(codec_context->sample_fmt);
169         AVSampleFormat fmt = codec_context->sample_fmt;
170         if (fmt == AV_SAMPLE_FMT_S16 || fmt == AV_SAMPLE_FMT_S16P ||
171             fmt == AV_SAMPLE_FMT_S32 || fmt == AV_SAMPLE_FMT_S32P) {
172             fp = false;
173         } else if (fmt == AV_SAMPLE_FMT_FLT || fmt == AV_SAMPLE_FMT_FLTP ||
174             fmt == AV_SAMPLE_FMT_DBL || fmt == AV_SAMPLE_FMT_DBLP ) {
175             fp = true;
176         } else {
177             error = AudioError::BAD_SAMPLE_FORMAT;
178         }
179     }
180 
181     return std::unique_ptr<AudioFile>(new AudioFileImpl(
182         error, format_context, audio_stream,
183         codec_name, bit_rate, sample_rate, bits_per_sample,
184         channels, duration, is_planar, width, fp
185     ));
186 }
187 
188 AudioFileImpl::AudioFileImpl(
189     AudioError error, AVFormatContext *format_context, int audio_stream,
190     const std::string& codec_name, int bit_rate, int sample_rate, int bits_per_sample,
191     int channels, double duration, bool is_planar, int width, bool fp
192 ) :
193     error(error), format_context(format_context), audio_stream(audio_stream),
194     codec_name(codec_name), bit_rate(bit_rate),
195     sample_rate(sample_rate), bits_per_sample(bits_per_sample),
196     channels(channels), duration(duration), is_planar(is_planar), width(width), fp(fp)
197 {
198     av_init_packet(&this->packet);
199     this->packet.data = nullptr;
200     this->packet.size = 0;
201     this->offset = 0;
202     this->frame = av_frame_alloc();
203     this->buffer_size = 0;
204     this->buffer = nullptr;
205     this->frames_per_interval = 0;
206     this->error_per_interval = 0;
207     this->error_base = 0;
208 }
209 
210 AudioFileImpl::~AudioFileImpl()
211 {
212     if (this->buffer) {
213         av_freep(&this->buffer);
214     }
215     if (this->frame) {
216         // TODO: Remove this check after Debian switches to libav 9.
217 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(54, 28, 0)
218         av_frame_free(&this->frame);
219 #else
220         av_freep(&this->frame);
221 #endif
222     }
223     if (this->packet.data) {
224         this->packet.data -= this->offset;
225         this->packet.size += this->offset;
226         this->offset = 0;
227         av_packet_unref(&this->packet);
228     }
229     if (this->format_context) {
230         if (this->audio_stream >= 0) {
231             auto codec_context = this->format_context->streams[this->audio_stream]->codec;
232             if (codec_context) {
233                 avcodec_close(codec_context);
234             }
235         }
236         avformat_close_input(&this->format_context);
237     }
238 }
239 
240 void AudioFileImpl::start(int samples)
241 {
242     AVStream *stream = this->format_context->streams[this->audio_stream];
243     int64_t rate = this->sample_rate * (int64_t)stream->time_base.num;
244     int64_t duration = (int64_t)(this->duration * stream->time_base.den / stream->time_base.num);
245     this->error_base = samples * (int64_t)stream->time_base.den;
246     this->frames_per_interval = av_rescale_rnd(duration, rate, this->error_base, AV_ROUND_DOWN);
247     this->error_per_interval = (duration * rate) % this->error_base;
248 }
249 
250 int AudioFileImpl::read()
251 {
252     if (!!this->error) {
253         return -1;
254     }
255 
256     for (;;) {
257         while (this->packet.size > 0) {
258             av_frame_unref(this->frame);
259             auto codec_context = this->format_context->streams[this->audio_stream]->codec;
260             int got_frame = 0;
261             int len = avcodec_decode_audio4(codec_context, this->frame, &got_frame, &this->packet);
262             if (len < 0) {
263                 // Error, skip the frame.
264                 break;
265             }
266             this->packet.data += len;
267             this->packet.size -= len;
268             this->offset += len;
269             if (!got_frame) {
270                 // No data yet, get more frames.
271                 continue;
272             }
273             // We have data, return it and come back for more later.
274             int samples = this->frame->nb_samples;
275             int channels = this->channels;
276             int width = this->width;
277             int buffer_size = samples * channels * width;
278             if (buffer_size > this->buffer_size) {
279                 this->buffer = (uint8_t*)av_realloc(this->buffer, buffer_size);
280                 this->buffer_size = buffer_size;
281             }
282             if (this->is_planar) {
283                 for (int channel = 0; channel < channels; ++channel) {
284                     uint8_t *buffer = this->buffer + channel * width;
285                     uint8_t *data = this->frame->data[channel];
286                     for (int sample = 0; sample < samples; ++sample) {
287                         for (int i = 0; i < width; ++i) {
288                             *buffer++ = *data++;
289                         }
290                         buffer += (channels - 1) * width;
291                     }
292                 }
293             } else {
294                 memcpy(this->buffer, this->frame->data[0], buffer_size);
295             }
296             return buffer_size;
297         }
298         if (this->packet.data) {
299             this->packet.data -= this->offset;
300             this->packet.size += this->offset;
301             this->offset = 0;
302             av_packet_unref(&this->packet);
303         }
304 
305         int res = 0;
306         while ((res = av_read_frame(this->format_context, &this->packet)) >= 0) {
307             if (this->packet.stream_index == this->audio_stream) {
308                 break;
309             }
310             av_packet_unref(&this->packet);
311         }
312         if (res < 0) {
313             // End of file or error.
314             return 0;
315         }
316     }
317 }
318