~ubuntu-branches/ubuntu/lucid/lastfm/lucid

« back to all changes in this revision

Viewing changes to src/mp3transcode/mp3transcode.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Pedro Fragoso
  • Date: 2007-12-31 09:49:54 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20071231094954-ix1amvcsj9pk61ya
Tags: 1:1.4.1.57486.dfsg-1ubuntu1
* Merge from Debian unstable (LP: #180254), remaining changes:
  - debian/rules;
    - Added dh_icons
  - Modify Maintainer value to match Debian-Maintainer-Field Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright (C) 2005 - 2007 by                                          *
3
 
 *      Christian Muehlhaeuser, Last.fm Ltd <chris@last.fm>                *
4
 
 *      Erik Jaelevik, Last.fm Ltd <erik@last.fm>                          *
5
 
 *                                                                         *
6
 
 *   This program is free software; you can redistribute it and/or modify  *
7
 
 *   it under the terms of the GNU General Public License as published by  *
8
 
 *   the Free Software Foundation; either version 2 of the License, or     *
9
 
 *   (at your option) any later version.                                   *
10
 
 *                                                                         *
11
 
 *   This program is distributed in the hope that it will be useful,       *
12
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 
 *   GNU General Public License for more details.                          *
15
 
 *                                                                         *
16
 
 *   You should have received a copy of the GNU General Public License     *
17
 
 *   along with this program; if not, write to the                         *
18
 
 *   Free Software Foundation, Inc.,                                       *
19
 
 *   51 Franklin Steet, Fifth Floor, Boston, MA  02111-1307, USA.          *
20
 
 ***************************************************************************/
21
 
 
22
 
#include <QtGui>
23
 
 
24
 
#include "mp3transcode.h"
25
 
#include "containerutils.h"
26
 
#include "logger.h"
27
 
 
28
 
#define MP3_MIN_BUFFER_SIZE 4096
29
 
 
30
 
struct mpstr_tag mpeg;
31
 
 
32
 
MP3Transcode::MP3Transcode() :
33
 
        m_decodedBufferCapacity( 32 * 1024 ),
34
 
        m_mpegInitialised( false )
35
 
{
36
 
    LOGL( 3, "Initialising MP3 Transcoding" );
37
 
 
38
 
    if ( !InitMP3( &mpeg ) )
39
 
    {
40
 
        LOGL( 1, "Something went wrong when initiliasing mpglib. "
41
 
            " God knows what. Chris can read the \"best documentation "
42
 
            " there is\" to find out. :P" );
43
 
    }
44
 
 
45
 
    // Maybe give these a good start value?  They'll grow as needed anyway.
46
 
    m_decBufSize = 1; // On my machine this grows to about 120K
47
 
    m_encBufSize = 1; // And this grows to about 6K or so.
48
 
    m_encBufReadIndex = m_encBufWriteIndex = 0;
49
 
    m_decBufReadIndex = m_decBufWriteIndex = 0;
50
 
    m_decodedBuffer = (char*)malloc( m_decBufSize );
51
 
    m_encodedBuffer = (char*)malloc( m_encBufSize );
52
 
}
53
 
 
54
 
MP3Transcode::~MP3Transcode()
55
 
{
56
 
    if ( m_decodedBuffer )
57
 
    {
58
 
        free( m_decodedBuffer);
59
 
        m_decodedBuffer = NULL;
60
 
    }
61
 
    if ( m_encodedBuffer )
62
 
    {
63
 
        free( m_encodedBuffer);
64
 
        m_encodedBuffer = NULL;
65
 
    }
66
 
    ExitMP3( &mpeg );
67
 
}
68
 
 
69
 
 
70
 
QStringList
71
 
MP3Transcode::supportedMimeTypes() const
72
 
{
73
 
    return QStringList( "application/x-mp3" );
74
 
}
75
 
 
76
 
QStringList
77
 
MP3Transcode::supportedFileExtensions() const
78
 
{
79
 
    return QStringList( "mp3" );
80
 
}
81
 
 
82
 
void
83
 
MP3Transcode::expandRingBuffer( char** buffer, int& bufSize, int& readIndex, int& writeIndex, int growSize )
84
 
{
85
 
    //qDebug() << "resizing buffer from" << bufSize
86
 
    //         << "to" << bufSize + growSize;
87
 
    char* tmp;
88
 
    tmp = (char*)realloc( *buffer, sizeof(char) * ( bufSize + growSize ) );
89
 
    if ( tmp == NULL )
90
 
    {
91
 
        Q_ASSERT( !"Could not reallocate buffer!" );
92
 
        return;
93
 
    }
94
 
    else
95
 
        *buffer = tmp;
96
 
 
97
 
    // Don't screw up the read order or ugly noises will ensue
98
 
    if ( readIndex > writeIndex )
99
 
    {
100
 
        memmove( *buffer + readIndex + growSize,
101
 
                 *buffer + readIndex,
102
 
                 bufSize - readIndex );
103
 
        readIndex += growSize;
104
 
    }
105
 
    bufSize += growSize;
106
 
}
107
 
 
108
 
 
109
 
bool
110
 
MP3Transcode::processData( const QByteArray &buffer )
111
 
{
112
 
    int length = buffer.size();
113
 
    int cnt;
114
 
    const char* src = buffer.data();
115
 
    int neededSize = getEncodedBufferFilled() + buffer.size();
116
 
 
117
 
    if ( neededSize >= m_encBufSize )
118
 
        expandRingBuffer( &m_encodedBuffer, m_encBufSize,
119
 
                          m_encBufReadIndex, m_encBufWriteIndex,
120
 
                          neededSize - m_encBufSize + 1 );
121
 
 
122
 
    while ( length > 0 )
123
 
    {
124
 
        int wr;
125
 
        cnt = qMin( length, m_encBufSize - m_encBufWriteIndex );
126
 
        memcpy( m_encodedBuffer + m_encBufWriteIndex, src, cnt );
127
 
        wr = (m_encBufWriteIndex + cnt) % m_encBufSize;
128
 
        m_encBufWriteIndex = wr;
129
 
        length -= cnt;
130
 
        src += cnt;
131
 
    }
132
 
 
133
 
    // wait till we got a minimal buffer of data, which we need for mpglib
134
 
    // being able to properly read the audio metadata (samplerate, channels...)
135
 
    if ( getEncodedBufferFilled() <= MP3_MIN_BUFFER_SIZE )
136
 
    {
137
 
        return true;
138
 
    }
139
 
 
140
 
    char tempBuffer[16384];
141
 
    int size;
142
 
    unsigned char inTemp[MP3_MIN_BUFFER_SIZE];
143
 
    length = MP3_MIN_BUFFER_SIZE;
144
 
    int outLen = 0;
145
 
    while ( length > 0 )
146
 
    {
147
 
        int rd;
148
 
        cnt = qMin(length, m_encBufSize - m_encBufReadIndex);
149
 
        memcpy( inTemp + outLen, m_encodedBuffer + m_encBufReadIndex, cnt);
150
 
        rd = (m_encBufReadIndex + cnt) % m_encBufSize;
151
 
        m_encBufReadIndex = rd;
152
 
        length -= cnt;
153
 
        outLen += cnt;
154
 
    }
155
 
 
156
 
 
157
 
    int result = decodeMP3(
158
 
        &mpeg, // handle
159
 
        inTemp, // in-data
160
 
        MP3_MIN_BUFFER_SIZE, // size of in-data
161
 
        tempBuffer, // out-data
162
 
        sizeof( tempBuffer ), // size of out-data
163
 
        &size ); // done size
164
 
 
165
 
    if ( result == MP3_ERR )
166
 
    {
167
 
        LOG( 1, "decodeMP3 failed. result: " << result );
168
 
        return false;
169
 
    }
170
 
 
171
 
    if ( !m_mpegInitialised )
172
 
    {
173
 
        long sampleRate = freqs[mpeg.fr.sampling_frequency];
174
 
        int channels = mpeg.fr.stereo > 0 ? mpeg.fr.stereo : 2;
175
 
 
176
 
        LOGL( 4, "mpegTranscode (Samplerate:" << sampleRate <<
177
 
                 "Channels:" << channels << ")" );
178
 
 
179
 
        // For certain corrupt previews, we get a result of OK, but the sample
180
 
        // rate comes out all wrong. If we let these proceed, things will crash
181
 
        // horribly.
182
 
        if ( sampleRate != 44100 || channels != 2 )
183
 
        {
184
 
            LOGL( 1, "Stream is not 44.1k stereo, aborting" );
185
 
            return false;
186
 
        }
187
 
 
188
 
        m_mpegInitialised = true;
189
 
        emit streamInitialized( sampleRate, channels );
190
 
    }
191
 
 
192
 
    while ( result == MP3_OK )
193
 
    {
194
 
        int length = size;
195
 
        int cnt;
196
 
        const char* src = tempBuffer;
197
 
        int neededSize = getDecodedBufferFilled() + size;
198
 
 
199
 
        if ( neededSize >= m_decBufSize )
200
 
            expandRingBuffer( &m_decodedBuffer, m_decBufSize,
201
 
                              m_decBufReadIndex, m_decBufWriteIndex,
202
 
                              ( neededSize - m_decBufSize + 1 ) );
203
 
 
204
 
        while (length > 0)
205
 
        {
206
 
            int wr;
207
 
            cnt = qMin(length, m_decBufSize - m_decBufWriteIndex);
208
 
            memcpy( m_decodedBuffer + m_decBufWriteIndex, src, cnt);
209
 
            wr = (m_decBufWriteIndex + cnt) % m_decBufSize;
210
 
            m_decBufWriteIndex = wr;
211
 
            length -= cnt;
212
 
            src += cnt;
213
 
        }
214
 
 
215
 
        result = decodeMP3( &mpeg, NULL, 0, tempBuffer, sizeof( tempBuffer ), &size );
216
 
 
217
 
        if ( result == MP3_ERR )
218
 
        {
219
 
            LOGL( 1, "decodeMP3 failed. result: " << result );
220
 
            return false;
221
 
        }
222
 
    }
223
 
    
224
 
    return true;
225
 
}
226
 
 
227
 
 
228
 
void
229
 
MP3Transcode::clearBuffers()
230
 
{
231
 
    ExitMP3( &mpeg );
232
 
 
233
 
    m_decBufReadIndex = m_decBufWriteIndex = 0;
234
 
    m_encBufReadIndex = m_encBufWriteIndex = 0;
235
 
    m_mpegInitialised = false;
236
 
 
237
 
    if ( !InitMP3( &mpeg ) )
238
 
    {
239
 
        LOGL( 1, "Something went wrong when initiliasing mpglib. "
240
 
            " God knows what. Chris can read the \"best documentation "
241
 
            " there is\" to find out. :P" );
242
 
    }
243
 
}
244
 
 
245
 
int
246
 
MP3Transcode::getEncodedBufferFilled()
247
 
{
248
 
    if ( m_encBufWriteIndex >= m_encBufReadIndex )
249
 
    {
250
 
        return m_encBufWriteIndex - m_encBufReadIndex;
251
 
    }
252
 
    return ( m_encBufSize - ( m_encBufReadIndex - m_encBufWriteIndex ) );
253
 
}
254
 
 
255
 
int
256
 
MP3Transcode::getDecodedBufferFilled()
257
 
{
258
 
    if ( m_decBufWriteIndex >= m_decBufReadIndex )
259
 
    {
260
 
        return m_decBufWriteIndex - m_decBufReadIndex;
261
 
    }
262
 
    return ( m_decBufSize - ( m_decBufReadIndex - m_decBufWriteIndex ) );
263
 
}
264
 
 
265
 
bool
266
 
MP3Transcode::needsData()
267
 
{
268
 
    return getDecodedBufferFilled() < m_decodedBufferCapacity;
269
 
}
270
 
 
271
 
 
272
 
bool
273
 
MP3Transcode::hasData()
274
 
{
275
 
    return ( getDecodedBufferFilled() > 0 );
276
 
}
277
 
 
278
 
 
279
 
void
280
 
MP3Transcode::data( QByteArray& fillMe, int numBytes )
281
 
{
282
 
    int length;
283
 
    int cnt;
284
 
    length = qMin( numBytes, ssize_t( getDecodedBufferFilled() ) );
285
 
 
286
 
    while (length > 0)
287
 
    {
288
 
        int rd;
289
 
        cnt = qMin (length, m_decBufSize - m_decBufReadIndex );
290
 
        fillMe.append( QByteArray::fromRawData( m_decodedBuffer + m_decBufReadIndex, cnt ) );
291
 
        rd = ( m_decBufReadIndex + cnt ) % m_decBufSize;
292
 
        m_decBufReadIndex = rd;
293
 
        length -= cnt;
294
 
    }
295
 
}
296
 
 
297
 
 
298
 
Q_EXPORT_PLUGIN2( transcode, MP3Transcode )