/* * * $Id$ * Copyright (C) 2003 Sebastian Trueg * * This file is part of the K3b project. * Copyright (C) 1998-2007 Sebastian Trueg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * See the file "COPYING" for the exact licensing terms. */ // // Some notes on mp3: // A mp3 Frame is always samples/samplerate seconds in length // // // // What we need are raw 16 bit stereo samples at 44100 Hz which results in 588 samples // per block (2352 bytes: 32*588 bit). 1 second are 75 blocks. // #include #include "k3bmaddecoder.h" #include "k3bmad.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_TAGLIB #include #include #endif K_EXPORT_COMPONENT_FACTORY( libk3bmaddecoder, K3bPluginFactory( "k3bmaddecoder" ) ) int K3bMadDecoder::MaxAllowedRecoverableErrors = 10; class K3bMadDecoder::MadDecoderPrivate { public: MadDecoderPrivate() : outputBuffer(0), outputPointer(0), outputBufferEnd(0) { mad_header_init( &firstHeader ); } K3bMad* handle; TQValueVector seekPositions; bool bOutputFinished; char* outputBuffer; char* outputPointer; char* outputBufferEnd; // the first frame header for technical info mad_header firstHeader; bool vbr; }; K3bMadDecoder::K3bMadDecoder( TQObject* parent, const char* name ) : K3bAudioDecoder( parent, name ) { d = new MadDecoderPrivate(); d->handle = new K3bMad(); } K3bMadDecoder::~K3bMadDecoder() { cleanup(); delete d->handle; delete d; } TQString K3bMadDecoder::metaInfo( MetaDataField f ) { #ifdef HAVE_TAGLIB TagLib::MPEG::File file( TQFile::encodeName( filename() ).data() ); if ( file.tag() ) { switch( f ) { case META_TITLE: return TStringToQString( file.tag()->title() ); case META_ARTIST: return TStringToQString( file.tag()->artist() ); case META_COMMENT: return TStringToQString( file.tag()->comment() ); default: return TQString(); } } else { return TQString(); } #else return K3bAudioDecoder::metaInfo( f ); #endif } bool K3bMadDecoder::analyseFileInternal( K3b::Msf& frames, int& samplerate, int& ch ) { initDecoderInternal(); frames = countFrames(); if( frames > 0 ) { // we convert mono to stereo all by ourselves. :) ch = 2; samplerate = d->firstHeader.samplerate; return true; } else return false; } bool K3bMadDecoder::initDecoderInternal() { cleanup(); d->bOutputFinished = false; if( !d->handle->open( filename() ) ) return false; if( !d->handle->skipTag() ) return false; if( !d->handle->seekFirstHeader() ) return false; return true; } unsigned long K3bMadDecoder::countFrames() { kdDebug() << "(K3bMadDecoder::countFrames)" << endl; unsigned long frames = 0; bool error = false; d->vbr = false; bool bFirstHeaderSaved = false; d->seekPositions.clear(); while( !error && d->handle->findNextHeader() ) { if( !bFirstHeaderSaved ) { bFirstHeaderSaved = true; d->firstHeader = d->handle->madFrame->header; } else if( d->handle->madFrame->header.bitrate != d->firstHeader.bitrate ) d->vbr = true; // // position in stream: postion in file minus the not yet used buffer // unsigned long long seekPos = d->handle->inputPos() - (d->handle->madStream->bufend - d->handle->madStream->this_frame + 1); // save the number of bytes to be read to decode i-1 frames at position i // in other words: when seeking to seekPos the next decoded frame will be i d->seekPositions.append( seekPos ); } if( !d->handle->inputError() && !error ) { // we need the length of the track to be multiple of frames (1/75 second) float seconds = (float)d->handle->madTimer->seconds + (float)d->handle->madTimer->fraction/(float)MAD_TIMER_RESOLUTION; frames = (unsigned long)ceil(seconds * 75.0); kdDebug() << "(K3bMadDecoder) length of track " << seconds << endl; } cleanup(); kdDebug() << "(K3bMadDecoder::countFrames) end" << endl; return frames; } int K3bMadDecoder::decodeInternal( char* _data, int maxLen ) { d->outputBuffer = _data; d->outputBufferEnd = d->outputBuffer + maxLen; d->outputPointer = d->outputBuffer; bool bOutputBufferFull = false; while( !bOutputBufferFull && d->handle->fillStreamBuffer() ) { // a mad_synth contains of the data of one mad_frame // one mad_frame represents a mp3-frame which is always 1152 samples // for us that means we need 4*1152 bytes of output buffer for every frame // since one sample has 16 bit if( d->outputBufferEnd - d->outputPointer < 4*1152 ) { bOutputBufferFull = true; } else if( d->handle->decodeNextFrame() ) { // // Once decoded the frame is synthesized to PCM samples. No errors // are reported by mad_synth_frame(); // mad_synth_frame( d->handle->madSynth, d->handle->madFrame ); // this fills the output buffer if( !createPcmSamples( d->handle->madSynth ) ) { return -1; } } else if( d->handle->inputError() ) { return -1; } } // flush the output buffer size_t buffersize = d->outputPointer - d->outputBuffer; return buffersize; } unsigned short K3bMadDecoder::linearRound( mad_fixed_t fixed ) { // round fixed += (1L << ( MAD_F_FRACBITS - 16 )); // clip if( fixed >= MAD_F_ONE - 1 ) fixed = MAD_F_ONE - 1; else if( fixed < -MAD_F_ONE ) fixed = -MAD_F_ONE; // quatisize return fixed >> (MAD_F_FRACBITS + 1 - 16 ); } bool K3bMadDecoder::createPcmSamples( mad_synth* synth ) { unsigned short nsamples = synth->pcm.length; // this should not happen since we only decode if the // output buffer has enough free space if( d->outputBufferEnd - d->outputPointer < nsamples*4 ) { kdDebug() << "(K3bMadDecoder) buffer overflow!" << endl; return false; } // now create the output for( int i = 0; i < nsamples; i++ ) { /* Left channel */ unsigned short sample = linearRound( synth->pcm.samples[0][i] ); *(d->outputPointer++) = (sample >> 8) & 0xff; *(d->outputPointer++) = sample & 0xff; /* Right channel. If the decoded stream is monophonic then * the right output channel is the same as the left one. */ if( synth->pcm.channels == 2 ) sample = linearRound( synth->pcm.samples[1][i] ); *(d->outputPointer++) = (sample >> 8) & 0xff; *(d->outputPointer++) = sample & 0xff; } // pcm conversion return true; } void K3bMadDecoder::cleanup() { d->handle->cleanup(); } bool K3bMadDecoder::seekInternal( const K3b::Msf& pos ) { // // we need to reset the complete mad stuff // if( !initDecoderInternal() ) return false; // // search a position // This is all hacking, I don't really know what I am doing here... ;) // double mp3FrameSecs = static_cast(d->firstHeader.duration.seconds) + static_cast(d->firstHeader.duration.fraction) / static_cast(MAD_TIMER_RESOLUTION); double posSecs = static_cast(pos.totalFrames()) / 75.0; // seekPosition to seek after frame i unsigned int frame = static_cast( posSecs / mp3FrameSecs ); // Rob said: 29 frames is the theoretically max frame reservoir limit (whatever that means...) // it seems that mad needs at most 29 frames to get ready unsigned int frameReservoirProtect = ( frame > 29 ? 29 : frame ); frame -= frameReservoirProtect; // seek in the input file behind the already decoded data d->handle->inputSeek( d->seekPositions[frame] ); kdDebug() << "(K3bMadDecoder) Seeking to frame " << frame << " with " << frameReservoirProtect << " reservoir frames." << endl; // decode some frames ignoring MAD_ERROR_BADDATAPTR errors unsigned int i = 1; while( i <= frameReservoirProtect ) { d->handle->fillStreamBuffer(); if( mad_frame_decode( d->handle->madFrame, d->handle->madStream ) ) { if( MAD_RECOVERABLE( d->handle->madStream->error ) ) { if( d->handle->madStream->error == MAD_ERROR_BUFLEN ) continue; else if( d->handle->madStream->error != MAD_ERROR_BADDATAPTR ) { kdDebug() << "(K3bMadDecoder) Seeking: recoverable mad error (" << mad_stream_errorstr(d->handle->madStream) << ")" << endl; continue; } else { kdDebug() << "(K3bMadDecoder) Seeking: ignoring (" << mad_stream_errorstr(d->handle->madStream) << ")" << endl; } } else return false; } if( i == frameReservoirProtect ) // synth only the last frame (Rob said so ;) mad_synth_frame( d->handle->madSynth, d->handle->madFrame ); ++i; } return true; } TQString K3bMadDecoder::fileType() const { switch( d->firstHeader.layer ) { case MAD_LAYER_I: return "MPEG1 Layer I"; case MAD_LAYER_II: return "MPEG1 Layer II"; case MAD_LAYER_III: return "MPEG1 Layer III"; default: return "Mp3"; } } TQStringList K3bMadDecoder::supportedTechnicalInfos() const { return TQStringList::split( ";", i18n("Channels") + ";" + i18n("Sampling Rate") + ";" + i18n("Bitrate") + ";" + i18n("Layer") + ";" + i18n("Emphasis") + ";" + i18n("Copyright") + ";" + i18n("Original") + ";" + i18n("CRC") ); } TQString K3bMadDecoder::technicalInfo( const TQString& name ) const { if( name == i18n("Channels") ) { switch( d->firstHeader.mode ) { case MAD_MODE_SINGLE_CHANNEL: return i18n("Mono"); case MAD_MODE_DUAL_CHANNEL: return i18n("Dual"); case MAD_MODE_JOINT_STEREO: return i18n("Joint Stereo"); case MAD_MODE_STEREO: return i18n("Stereo"); default: return "?"; } } else if( name == i18n("Sampling Rate") ) return i18n("%1 Hz").arg(d->firstHeader.samplerate); else if( name == i18n("Bitrate") ) { if( d->vbr ) return i18n("VBR"); else return i18n("%1 bps").arg(d->firstHeader.bitrate); } else if( name == i18n("Layer") ){ switch( d->firstHeader.layer ) { case MAD_LAYER_I: return "I"; case MAD_LAYER_II: return "II"; case MAD_LAYER_III: return "III"; default: return "?"; } } else if( name == i18n("Emphasis") ) { switch( d->firstHeader.emphasis ) { case MAD_EMPHASIS_NONE: return i18n("None"); case MAD_EMPHASIS_50_15_US: return i18n("50/15 ms"); case MAD_EMPHASIS_CCITT_J_17: return i18n("CCITT J.17"); default: return i18n("Unknown"); } } else if( name == i18n("Copyright") ) return ( d->firstHeader.flags & MAD_FLAG_COPYRIGHT ? i18n("Yes") : i18n("No") ); else if( name == i18n("Original") ) return ( d->firstHeader.flags & MAD_FLAG_ORIGINAL ? i18n("Yes") : i18n("No") ); else if( name == i18n("CRC") ) return ( d->firstHeader.flags & MAD_FLAG_PROTECTION ? i18n("Yes") : i18n("No") ); else return TQString(); } K3bMadDecoderFactory::K3bMadDecoderFactory( TQObject* parent, const char* name ) : K3bAudioDecoderFactory( parent, name ) { } K3bMadDecoderFactory::~K3bMadDecoderFactory() { } K3bAudioDecoder* K3bMadDecoderFactory::createDecoder( TQObject* parent, const char* name ) const { return new K3bMadDecoder( parent, name ); } bool K3bMadDecoderFactory::canDecode( const KURL& url ) { // // HACK: // // I am simply no good at this and this detection code is no good as well // It always takes waves for mp3 files so we introduce this hack to // filter out wave files. :( // TQFile f( url.path() ); if( !f.open( IO_ReadOnly ) ) return false; char buffer[12]; if( f.readBlock( buffer, 12 ) != 12 ) return false; if( !tqstrncmp( buffer, "RIFF", 4 ) && !tqstrncmp( buffer + 8, "WAVE", 4 ) ) return false; f.close(); K3bMad handle; if( !handle.open( url.path() ) ) return false; handle.skipTag(); if( !handle.seekFirstHeader() ) return false; if( handle.findNextHeader() ) { int c = MAD_NCHANNELS( &handle.madFrame->header ); int layer = handle.madFrame->header.layer; unsigned int s = handle.madFrame->header.samplerate; // // find 4 more mp3 headers (random value since 2 was not enough) // This way we get most of the mp3 files while sorting out // for example wave files. // int cnt = 1; while( handle.findNextHeader() ) { // compare the found headers if( MAD_NCHANNELS( &handle.madFrame->header ) == c && handle.madFrame->header.layer == layer && handle.madFrame->header.samplerate == s ) { // only support layer III for now since otherwise some wave files // are taken for layer I if( ++cnt >= 5 ) { kdDebug() << "(K3bMadDecoder) valid mpeg 1 layer " << layer << " file with " << c << " channels and a samplerate of " << s << endl; return ( layer == MAD_LAYER_III ); } } else break; } } kdDebug() << "(K3bMadDecoder) unsupported format: " << url.path() << endl; return false; } #include "k3bmaddecoder.moc"