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