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> *
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. *
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. *
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
***************************************************************************/
24
#include "mp3transcode.h"
25
#include "containerutils.h"
28
#define MP3_MIN_BUFFER_SIZE 4096
30
struct mpstr_tag mpeg;
32
MP3Transcode::MP3Transcode() :
33
m_decodedBufferCapacity( 32 * 1024 ),
34
m_mpegInitialised( false )
36
LOGL( 3, "Initialising MP3 Transcoding" );
38
if ( !InitMP3( &mpeg ) )
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" );
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 );
54
MP3Transcode::~MP3Transcode()
56
if ( m_decodedBuffer )
58
free( m_decodedBuffer);
59
m_decodedBuffer = NULL;
61
if ( m_encodedBuffer )
63
free( m_encodedBuffer);
64
m_encodedBuffer = NULL;
71
MP3Transcode::supportedMimeTypes() const
73
return QStringList( "application/x-mp3" );
77
MP3Transcode::supportedFileExtensions() const
79
return QStringList( "mp3" );
83
MP3Transcode::expandRingBuffer( char** buffer, int& bufSize, int& readIndex, int& writeIndex, int growSize )
85
//qDebug() << "resizing buffer from" << bufSize
86
// << "to" << bufSize + growSize;
88
tmp = (char*)realloc( *buffer, sizeof(char) * ( bufSize + growSize ) );
91
Q_ASSERT( !"Could not reallocate buffer!" );
97
// Don't screw up the read order or ugly noises will ensue
98
if ( readIndex > writeIndex )
100
memmove( *buffer + readIndex + growSize,
102
bufSize - readIndex );
103
readIndex += growSize;
110
MP3Transcode::processData( const QByteArray &buffer )
112
int length = buffer.size();
114
const char* src = buffer.data();
115
int neededSize = getEncodedBufferFilled() + buffer.size();
117
if ( neededSize >= m_encBufSize )
118
expandRingBuffer( &m_encodedBuffer, m_encBufSize,
119
m_encBufReadIndex, m_encBufWriteIndex,
120
neededSize - m_encBufSize + 1 );
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;
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 )
140
char tempBuffer[16384];
142
unsigned char inTemp[MP3_MIN_BUFFER_SIZE];
143
length = MP3_MIN_BUFFER_SIZE;
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;
157
int result = decodeMP3(
160
MP3_MIN_BUFFER_SIZE, // size of in-data
161
tempBuffer, // out-data
162
sizeof( tempBuffer ), // size of out-data
163
&size ); // done size
165
if ( result == MP3_ERR )
167
LOG( 1, "decodeMP3 failed. result: " << result );
171
if ( !m_mpegInitialised )
173
long sampleRate = freqs[mpeg.fr.sampling_frequency];
174
int channels = mpeg.fr.stereo > 0 ? mpeg.fr.stereo : 2;
176
LOGL( 4, "mpegTranscode (Samplerate:" << sampleRate <<
177
"Channels:" << channels << ")" );
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
182
if ( sampleRate != 44100 || channels != 2 )
184
LOGL( 1, "Stream is not 44.1k stereo, aborting" );
188
m_mpegInitialised = true;
189
emit streamInitialized( sampleRate, channels );
192
while ( result == MP3_OK )
196
const char* src = tempBuffer;
197
int neededSize = getDecodedBufferFilled() + size;
199
if ( neededSize >= m_decBufSize )
200
expandRingBuffer( &m_decodedBuffer, m_decBufSize,
201
m_decBufReadIndex, m_decBufWriteIndex,
202
( neededSize - m_decBufSize + 1 ) );
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;
215
result = decodeMP3( &mpeg, NULL, 0, tempBuffer, sizeof( tempBuffer ), &size );
217
if ( result == MP3_ERR )
219
LOGL( 1, "decodeMP3 failed. result: " << result );
229
MP3Transcode::clearBuffers()
233
m_decBufReadIndex = m_decBufWriteIndex = 0;
234
m_encBufReadIndex = m_encBufWriteIndex = 0;
235
m_mpegInitialised = false;
237
if ( !InitMP3( &mpeg ) )
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" );
246
MP3Transcode::getEncodedBufferFilled()
248
if ( m_encBufWriteIndex >= m_encBufReadIndex )
250
return m_encBufWriteIndex - m_encBufReadIndex;
252
return ( m_encBufSize - ( m_encBufReadIndex - m_encBufWriteIndex ) );
256
MP3Transcode::getDecodedBufferFilled()
258
if ( m_decBufWriteIndex >= m_decBufReadIndex )
260
return m_decBufWriteIndex - m_decBufReadIndex;
262
return ( m_decBufSize - ( m_decBufReadIndex - m_decBufWriteIndex ) );
266
MP3Transcode::needsData()
268
return getDecodedBufferFilled() < m_decodedBufferCapacity;
273
MP3Transcode::hasData()
275
return ( getDecodedBufferFilled() > 0 );
280
MP3Transcode::data( QByteArray& fillMe, int numBytes )
284
length = qMin( numBytes, ssize_t( getDecodedBufferFilled() ) );
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;
298
Q_EXPORT_PLUGIN2( transcode, MP3Transcode )