~ubuntu-branches/debian/stretch/acoustid-fingerprinter/stretch

« back to all changes in this revision

Viewing changes to .pc/02-CodecID.patch/decoder.h

  • Committer: Package Import Robot
  • Author(s): Jerome Charaoui
  • Date: 2014-08-26 20:30:49 UTC
  • mfrom: (7.1.1 sid)
  • Revision ID: package-import@ubuntu.com-20140826203049-qg3pn0syyg01udl3
Tags: 0.6-4
Make package FFmpeg-friendly (Closes: #758323)
Patch provided by Andreas Cadhalpun.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Chromaprint -- Audio fingerprinting toolkit
 
3
 * Copyright (C) 2010  Lukas Lalinsky <lalinsky@gmail.com>
 
4
 * 
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2.1 of the License, or (at your option) any later version.
 
9
 * 
 
10
 * This library 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 GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 
18
 * USA
 
19
 */
 
20
 
 
21
#ifndef FPSUBMIT_DECODER_H_
 
22
#define FPSUBMIT_DECODER_H_
 
23
 
 
24
#include <QMutex>
 
25
#include <string>
 
26
#include <algorithm>
 
27
#include <stdint.h>
 
28
extern "C" {
 
29
#include <libavcodec/avcodec.h>
 
30
#include <libavformat/avformat.h>
 
31
 
 
32
#define NEW_AVFRAME_API (LIBAVCODEC_VERSION_MAJOR >= 55)
 
33
#if NEW_AVFRAME_API
 
34
#include <libavutil/frame.h>
 
35
#endif
 
36
 
 
37
#ifdef HAVE_AV_AUDIO_CONVERT
 
38
#include "ffmpeg/audioconvert.h"
 
39
#include "ffmpeg/samplefmt.h"
 
40
#endif
 
41
}
 
42
#include "fingerprintcalculator.h"
 
43
 
 
44
class Decoder
 
45
{
 
46
public:
 
47
        Decoder(const std::string &fileName);
 
48
        ~Decoder();
 
49
 
 
50
        bool Open();
 
51
        void Decode(FingerprintCalculator *consumer, int maxLength = 0);
 
52
 
 
53
        int Channels()
 
54
        {
 
55
                return m_codec_ctx->channels;
 
56
        }
 
57
 
 
58
        int SampleRate()
 
59
        {
 
60
                return m_codec_ctx->sample_rate;
 
61
        }
 
62
 
 
63
        std::string LastError()
 
64
        {
 
65
                return m_error;
 
66
        }
 
67
 
 
68
    //static void lock_manager();
 
69
    static void initialize();
 
70
 
 
71
private:
 
72
        uint8_t *m_buffer2;
 
73
        std::string m_file_name;
 
74
        std::string m_error;
 
75
        AVFormatContext *m_format_ctx;
 
76
        AVCodecContext *m_codec_ctx;
 
77
        bool m_codec_open;
 
78
        AVStream *m_stream;
 
79
    static QMutex m_mutex;
 
80
    AVFrame *m_frame;
 
81
#ifdef HAVE_AV_AUDIO_CONVERT
 
82
        AVAudioConvert *m_convert_ctx;
 
83
#endif
 
84
};
 
85
 
 
86
/*inline static void Decoder::lock_manager(void **mutex, enum AVLockOp op)
 
87
{
 
88
    switch (op) {
 
89
    case AV_LOCK_CREATE:
 
90
        *mutex = new QMutex();
 
91
        return 1;
 
92
    case AV_LOCK_DESTROY:
 
93
        delete (QMutex *)(*mutex);
 
94
        return 1;
 
95
    case AV_LOCK_ACQUIRE:
 
96
        ((QMutex *)(*mutex))->lock();
 
97
        return 1;
 
98
    case AV_LOCK_RELEASE:
 
99
        ((QMutex *)(*mutex))->unlock();
 
100
        return 1;
 
101
    }
 
102
    return 0;
 
103
}*/
 
104
 
 
105
inline void Decoder::initialize()
 
106
{
 
107
        av_register_all();
 
108
        av_log_set_level(AV_LOG_ERROR);
 
109
    //av_lockmgr_register(&Decoder::lock_manager)
 
110
}
 
111
 
 
112
inline Decoder::Decoder(const std::string &file_name)
 
113
        : m_file_name(file_name), m_format_ctx(0), m_codec_ctx(0), m_stream(0), m_codec_open(false)
 
114
#ifdef HAVE_AV_AUDIO_CONVERT
 
115
        , m_convert_ctx(0)
 
116
#endif
 
117
{
 
118
#ifdef HAVE_AV_AUDIO_CONVERT
 
119
        m_buffer2 = (uint8_t *)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE * 2 + 16);
 
120
#endif
 
121
 
 
122
#if NEW_AVFRAME_API
 
123
    m_frame = av_frame_alloc();
 
124
#else
 
125
    m_frame = avcodec_alloc_frame();
 
126
#endif
 
127
}
 
128
 
 
129
inline Decoder::~Decoder()
 
130
{
 
131
        if (m_codec_ctx && m_codec_open) {
 
132
        QMutexLocker locker(&m_mutex); 
 
133
                avcodec_close(m_codec_ctx);
 
134
        }
 
135
        if (m_format_ctx) {
 
136
                avformat_close_input(&m_format_ctx);
 
137
        }
 
138
#ifdef HAVE_AV_AUDIO_CONVERT
 
139
        if (m_convert_ctx) {
 
140
                av_audio_convert_free(m_convert_ctx);
 
141
        }
 
142
        av_free(m_buffer2);
 
143
#endif
 
144
 
 
145
#if NEW_AVFRAME_API
 
146
    av_frame_free(&m_frame);
 
147
#else
 
148
    av_freep(&m_frame);
 
149
#endif
 
150
}
 
151
 
 
152
inline bool Decoder::Open()
 
153
{
 
154
    QMutexLocker locker(&m_mutex); 
 
155
 
 
156
        if (avformat_open_input(&m_format_ctx, m_file_name.c_str(), NULL, NULL) != 0) {
 
157
                m_error = "Couldn't open the file." + m_file_name;
 
158
                return false;
 
159
        }
 
160
 
 
161
        if (avformat_find_stream_info(m_format_ctx, NULL) < 0) {
 
162
                m_error = "Couldn't find stream information in the file.";
 
163
                return false;
 
164
        }
 
165
 
 
166
        //dump_format(m_format_ctx, 0, m_file_name.c_str(), 0);
 
167
 
 
168
        for (int i = 0; i < m_format_ctx->nb_streams; i++) {
 
169
                AVCodecContext *avctx = m_format_ctx->streams[i]->codec;
 
170
                if (avctx && avctx->codec_type == AVMEDIA_TYPE_AUDIO) {
 
171
                        m_stream = m_format_ctx->streams[i];
 
172
                        m_codec_ctx = avctx;
 
173
                        break;
 
174
                }
 
175
        }
 
176
        if (!m_codec_ctx) {
 
177
                m_error = "Couldn't find any audio stream in the file.";
 
178
                return false;
 
179
        }
 
180
 
 
181
        AVCodec *codec = avcodec_find_decoder(m_codec_ctx->codec_id);
 
182
        if (!codec) {
 
183
                m_error = "Unknown codec.";
 
184
                return false;
 
185
        }
 
186
 
 
187
        if (avcodec_open2(m_codec_ctx, codec, NULL) < 0) {
 
188
        m_error = "Couldn't open the codec.";
 
189
        return false;
 
190
    }
 
191
        m_codec_open = true;
 
192
 
 
193
        if (m_codec_ctx->sample_fmt != AV_SAMPLE_FMT_S16) {
 
194
#ifdef HAVE_AV_AUDIO_CONVERT
 
195
                m_convert_ctx = av_audio_convert_alloc(AV_SAMPLE_FMT_S16, m_codec_ctx->channels,
 
196
                                                       (AVSampleFormat)m_codec_ctx->sample_fmt, m_codec_ctx->channels, NULL, 0);
 
197
                if (!m_convert_ctx) {
 
198
                        m_error = "Couldn't create sample format converter.";
 
199
                        return false;
 
200
                }
 
201
#else
 
202
                m_error = "Unsupported sample format.";
 
203
                return false;
 
204
#endif
 
205
        }
 
206
 
 
207
        if (Channels() <= 0) {
 
208
                m_error = "Invalid audio stream (no channels).";
 
209
                return false;
 
210
        }
 
211
 
 
212
        if (SampleRate() <= 0) {
 
213
                m_error = "Invalid sample rate.";
 
214
                return false;
 
215
        }
 
216
 
 
217
        return true;
 
218
}
 
219
 
 
220
#include <stdio.h>
 
221
 
 
222
inline void Decoder::Decode(FingerprintCalculator *consumer, int max_length)
 
223
{
 
224
        AVPacket packet, packet_temp;
 
225
 
 
226
        int remaining = max_length * SampleRate() * Channels();
 
227
        int stop = 0;
 
228
 
 
229
        av_init_packet(&packet);
 
230
        av_init_packet(&packet_temp);
 
231
        while (!stop) {
 
232
                if (av_read_frame(m_format_ctx, &packet) < 0) {
 
233
        //              consumer->Flush();      
 
234
                        break;
 
235
                }
 
236
 
 
237
                packet_temp.data = packet.data;
 
238
                packet_temp.size = packet.size;
 
239
                while (packet_temp.size > 0) {
 
240
            int got_output;
 
241
            int consumed = avcodec_decode_audio4(m_codec_ctx, m_frame,
 
242
                                                 &got_output, &packet_temp);
 
243
                        if (consumed < 0) {
 
244
                                break;
 
245
                        }
 
246
 
 
247
                        packet_temp.data += consumed;
 
248
                        packet_temp.size -= consumed;
 
249
 
 
250
                        if (!got_output) {
 
251
                                continue;
 
252
                        }
 
253
 
 
254
                        int16_t *audio_buffer;
 
255
#ifdef HAVE_AV_AUDIO_CONVERT
 
256
                        if (m_convert_ctx) {
 
257
                                const void *ibuf[6] = { m_frame->data[0] };
 
258
                                void *obuf[6] = { m_buffer2 };
 
259
                                int istride[6] = { av_get_bytes_per_sample(m_codec_ctx->sample_fmt) };
 
260
                                int ostride[6] = { 2 };
 
261
                                int len = m_frame->nb_samples;
 
262
                                if (av_audio_convert(m_convert_ctx, obuf, ostride, ibuf, istride, len) < 0) {
 
263
                                        break;
 
264
                                }
 
265
                                audio_buffer = (int16_t *)m_buffer2;
 
266
                        }
 
267
                        else {
 
268
                                audio_buffer = (int16_t *)m_frame->data[0];
 
269
                        }
 
270
#else
 
271
                        audio_buffer = (int16_t *)m_frame->data[0];
 
272
#endif
 
273
 
 
274
                        int length = m_frame->nb_samples;
 
275
                        if (max_length) {
 
276
                                length = std::min(remaining, length);
 
277
                        }
 
278
 
 
279
                        consumer->feed(audio_buffer, length);
 
280
 
 
281
                        if (max_length) {
 
282
                                remaining -= length;
 
283
                                if (remaining <= 0) {
 
284
                                        stop = 1;
 
285
                                        break;
 
286
                                }
 
287
                        }
 
288
                }
 
289
 
 
290
                if (packet.data) {
 
291
                        av_free_packet(&packet);
 
292
                }
 
293
        }
 
294
}
 
295
 
 
296
#endif