summaryrefslogtreecommitdiff
path: root/vdr_decoder_ogg.c
diff options
context:
space:
mode:
Diffstat (limited to 'vdr_decoder_ogg.c')
-rw-r--r--vdr_decoder_ogg.c599
1 files changed, 333 insertions, 266 deletions
diff --git a/vdr_decoder_ogg.c b/vdr_decoder_ogg.c
index 94bd37d..d720c81 100644
--- a/vdr_decoder_ogg.c
+++ b/vdr_decoder_ogg.c
@@ -1,14 +1,13 @@
/*! \file vdr_decoder_ogg.c
* \ingroup vdr
- *
+ *
* The file implements a decoder which is used by the player to decode ogg vorbis audio files.
*
- * Adapted from
+ * Adapted from
* MP3/MPlayer plugin to VDR (C++)
* (C) 2001-2003 Stefan Huelswitt <huels@iname.com>
*/
-
#ifdef HAVE_VORBISFILE
#include "vdr_decoder_ogg.h"
@@ -20,373 +19,441 @@
#include <stdlib.h>
#include <stdio.h>
-#include "mg_content_interface.h"
-
+#include "mg_db.h"
// --- mgOggFile ----------------------------------------------------------------
-class mgOggFile // : public mgFileInfo
+class mgOggFile // : public mgFileInfo
{
- private:
+ private:
+
+ bool m_opened, m_canSeek;
- bool m_opened, m_canSeek;
+ OggVorbis_File vf;
- OggVorbis_File vf;
+ void error (const char *action, const int err);
- void error( const char *action, const int err );
+ std::string m_filename;
- std::string m_filename;
+ public:
- public:
+ mgOggFile (std::string filename);
+ ~mgOggFile ();
- mgOggFile( std::string filename );
- ~mgOggFile();
+ bool open (bool log = true);
- bool open(bool log=true);
+ void close (void);
- void close(void);
+ long long seek (long long posMs = 0, bool relativ = false);
- long long seek(long long posMs=0, bool relativ=false);
+ int stream (short *buffer, int samples);
- int stream(short *buffer, int samples);
-
- bool canSeek() { return m_canSeek; }
+ bool canSeek ()
+ {
+ return m_canSeek;
+ }
- long long indexMs(void);
+ long long indexMs (void);
};
-mgOggFile::mgOggFile( std::string filename ) :
- m_filename( filename )
+mgOggFile::mgOggFile (std::string filename):
+m_filename (filename)
{
- m_canSeek = false;
- m_opened = false;
+ m_canSeek = false;
+ m_opened = false;
}
-mgOggFile::~mgOggFile()
+
+mgOggFile::~mgOggFile ()
{
- close();
+ close ();
}
-bool mgOggFile::open(bool log)
+
+bool mgOggFile::open (bool log)
{
- if( m_opened )
- {
- if( m_canSeek )
- {
- return ( seek() >= 0 );
- }
- return true;
- }
-
- FILE *f = fopen( m_filename.c_str(), "r" );
- if( f )
+ if (m_opened)
{
- int r = ov_open( f, &vf, 0, 0 );
- if( !r )
- {
- m_canSeek = ( ov_seekable( &vf ) !=0 );
- m_opened = true;
- }
- else
- {
- fclose( f );
- if( log )
- {
- error( "open", r );
- }
- }
+ if (m_canSeek)
+ {
+ return (seek () >= 0);
+ }
+ return true;
}
- else
+
+ FILE *
+ f = fopen (m_filename.c_str (), "r");
+ if (f)
+ {
+ int
+ r = ov_open (f, &vf, 0, 0);
+ if (!r)
+ {
+ m_canSeek = (ov_seekable (&vf) != 0);
+ m_opened = true;
+ }
+ else
+ {
+ fclose (f);
+ if (log)
+ {
+ error ("open", r);
+ }
+ }
+ }
+ else
{
- if(log)
- {
- // esyslog("ERROR: failed to open file %s: %s", m_filename.c_str(), strerror(errno) );
- }
+ if (log)
+ {
+// esyslog("ERROR: failed to open file %s: %s", m_filename.c_str(), strerror(errno) );
+ }
}
- return m_opened;
+ return m_opened;
}
-
-void mgOggFile::close()
+
+
+void
+mgOggFile::close ()
{
- if( m_opened )
- {
- ov_clear( &vf );
- m_opened = false;
+ if (m_opened)
+ {
+ ov_clear (&vf);
+ m_opened = false;
}
}
-void mgOggFile::error( const char *action, const int err )
+
+void
+mgOggFile::error (const char *action, const int err)
{
- char *errstr;
- switch(err)
- {
- case OV_FALSE: errstr = "false/no data available"; break;
- case OV_EOF: errstr = "EOF"; break;
- case OV_HOLE: errstr = "missing or corrupted data"; break;
- case OV_EREAD: errstr = "read error"; break;
- case OV_EFAULT: errstr = "internal error"; break;
- case OV_EIMPL: errstr = "unimplemented feature"; break;
- case OV_EINVAL: errstr = "invalid argument"; break;
- case OV_ENOTVORBIS: errstr = "no Ogg Vorbis stream"; break;
- case OV_EBADHEADER: errstr = "corrupted Ogg Vorbis stream"; break;
- case OV_EVERSION: errstr = "unsupported bitstream version"; break;
- case OV_ENOTAUDIO: errstr = "ENOTAUDIO"; break;
- case OV_EBADPACKET: errstr = "EBADPACKET"; break;
- case OV_EBADLINK: errstr = "corrupted link"; break;
- case OV_ENOSEEK: errstr = "stream not seekable"; break;
- default: errstr = "unspecified error"; break;
- }
- // esyslog( "ERROR: vorbisfile %s failed on %s: %s", action, m_filename.c_str(), errstr );
+ char *errstr;
+ switch (err)
+ {
+ case OV_FALSE:
+ errstr = "false/no data available";
+ break;
+ case OV_EOF:
+ errstr = "EOF";
+ break;
+ case OV_HOLE:
+ errstr = "missing or corrupted data";
+ break;
+ case OV_EREAD:
+ errstr = "read error";
+ break;
+ case OV_EFAULT:
+ errstr = "internal error";
+ break;
+ case OV_EIMPL:
+ errstr = "unimplemented feature";
+ break;
+ case OV_EINVAL:
+ errstr = "invalid argument";
+ break;
+ case OV_ENOTVORBIS:
+ errstr = "no Ogg Vorbis stream";
+ break;
+ case OV_EBADHEADER:
+ errstr = "corrupted Ogg Vorbis stream";
+ break;
+ case OV_EVERSION:
+ errstr = "unsupported bitstream version";
+ break;
+ case OV_ENOTAUDIO:
+ errstr = "ENOTAUDIO";
+ break;
+ case OV_EBADPACKET:
+ errstr = "EBADPACKET";
+ break;
+ case OV_EBADLINK:
+ errstr = "corrupted link";
+ break;
+ case OV_ENOSEEK:
+ errstr = "stream not seekable";
+ break;
+ default:
+ errstr = "unspecified error";
+ break;
+ }
+// esyslog( "ERROR: vorbisfile %s failed on %s: %s", action, m_filename.c_str(), errstr );
}
-long long mgOggFile::indexMs(void)
+
+long long
+mgOggFile::indexMs (void)
{
- double p = ov_time_tell(&vf);
- if( p < 0.0 )
+ double p = ov_time_tell (&vf);
+ if (p < 0.0)
{
- p = 0.0;
+ p = 0.0;
}
- return (long long)( p*1000.0 );
+ return (long long) (p * 1000.0);
}
-long long mgOggFile::seek( long long posMs, bool relativ )
+
+long long
+mgOggFile::seek (long long posMs, bool relativ)
{
- if( relativ )
+ if (relativ)
{
- posMs += indexMs();
+ posMs += indexMs ();
}
- int r = ov_time_seek( &vf, (double) posMs/1000.0 );
-
- if(r)
+ int r = ov_time_seek (&vf, (double) posMs / 1000.0);
+
+ if (r)
{
- error( "seek", r );
- return -1;
+ error ("seek", r);
+ return -1;
}
-
- posMs = indexMs();
- return posMs;
+
+ posMs = indexMs ();
+ return posMs;
}
-int mgOggFile::stream( short *buffer, int samples )
+
+int
+mgOggFile::stream (short *buffer, int samples)
{
- int n;
- do
+ int n;
+ do
{
- int stream;
- n = ov_read( &vf, (char *)buffer, samples*2, 0, 2, 1, &stream );
- }
- while( n == OV_HOLE );
-
- if(n < 0)
+ int stream;
+ n = ov_read (&vf, (char *) buffer, samples * 2, 0, 2, 1, &stream);
+ }
+ while (n == OV_HOLE);
+
+ if (n < 0)
{
- error( "read", n );
+ error ("read", n);
}
- return (n/2);
+ return (n / 2);
}
+
// --- mgOggDecoder -------------------------------------------------------------
-mgOggDecoder::mgOggDecoder( mgContentItem *item )
- : mgDecoder( item )
+mgOggDecoder::mgOggDecoder (mgContentItem * item):mgDecoder (item)
{
- m_filename = item->getSourceFile();
- m_file = new mgOggFile( m_filename );
- m_pcm = 0;
- init();
+ m_filename = item->getSourceFile ();
+ m_file = new mgOggFile (m_filename);
+ m_pcm = 0;
+ init ();
}
-mgOggDecoder::~mgOggDecoder()
+
+mgOggDecoder::~mgOggDecoder ()
{
- delete m_file;
- clean();
+ delete m_file;
+ clean ();
}
-bool mgOggDecoder::valid()
+
+bool mgOggDecoder::valid ()
{
- bool res = false;
- if( tryLock() )
- {
- if( m_file->open( false ) )
- {
- res = true;
- }
- unlock();
- }
- return res;
+ bool
+ res = false;
+ if (tryLock ())
+ {
+ if (m_file->open (false))
+ {
+ res = true;
+ }
+ unlock ();
+ }
+ return res;
}
-mgPlayInfo *mgOggDecoder::playInfo(void)
+
+mgPlayInfo *
+mgOggDecoder::playInfo (void)
{
- if( m_playing )
- {
- // m_playinfo.m_index = index/1000;
- // m_playinfo.m_total = info.Total;
+ if (m_playing)
+ {
+// m_playinfo.m_index = index/1000;
+// m_playinfo.m_total = info.Total;
- return &m_playinfo;
- }
+ return &m_playinfo;
+ }
- return 0;
+ return 0;
}
-void mgOggDecoder::init()
+
+void
+mgOggDecoder::init ()
{
- clean();
- m_pcm = new struct mad_pcm;
- m_index = 0;
+ clean ();
+ m_pcm = new struct mad_pcm;
+ m_index = 0;
}
-bool mgOggDecoder::clean()
+
+bool mgOggDecoder::clean ()
{
- m_playing = false;
-
- delete m_pcm;
- m_pcm = 0;
-
- m_file->close();
- return false;
+ m_playing = false;
+
+ delete
+ m_pcm;
+ m_pcm = 0;
+
+ m_file->close ();
+ return false;
}
+
#define SF_SAMPLES (sizeof(m_pcm->samples[0])/sizeof(mad_fixed_t))
-bool mgOggDecoder::start()
+bool mgOggDecoder::start ()
{
- lock(true);
- init();
- m_playing = true;
+ lock (true);
+ init ();
+ m_playing = true;
- if( m_file->open() /*&& info.DoScan(true)*/ )
+ if (m_file->open () /*&& info.DoScan(true) */ )
{
- // obtain from database: rate, channels
- /* d(printf("ogg: open rate=%d channels=%d seek=%d\n",
- info.SampleFreq,info.Channels,file.CanSeek()))
- */
- if( m_item->getChannels() <= 2 )
- {
- unlock();
- return true;
- }
- else
- {
- // esyslog( "ERROR: cannot play ogg file %s: more than 2 channels", m_filename.c_str() );
- }
+// obtain from database: rate, channels
+/* d(printf("ogg: open rate=%d channels=%d seek=%d\n",
+ info.SampleFreq,info.Channels,file.CanSeek()))
+ */
+ if (m_item->getChannels () <= 2)
+ {
+ unlock ();
+ return true;
+ }
+ else
+ {
+// esyslog( "ERROR: cannot play ogg file %s: more than 2 channels", m_filename.c_str() );
+ }
}
-
- clean();
- unlock();
- return false;
+ clean ();
+ unlock ();
+
+ return false;
}
-bool mgOggDecoder::stop(void)
+
+bool mgOggDecoder::stop (void)
{
- lock();
+ lock ();
- if( m_playing )
- {
- clean();
- }
- unlock();
+ if (m_playing)
+ {
+ clean ();
+ }
+ unlock ();
- return true;
+ return true;
}
-struct mgDecode *mgOggDecoder::done(eDecodeStatus status)
+
+struct mgDecode *
+mgOggDecoder::done (eDecodeStatus status)
{
- m_ds.status = status;
- m_ds.index = m_index;
- m_ds.pcm = m_pcm;
+ m_ds.status = status;
+ m_ds.index = m_index;
+ m_ds.pcm = m_pcm;
- unlock(); // release the lock from decode()
+ unlock (); // release the lock from decode()
- return &m_ds;
+ return &m_ds;
}
-struct mgDecode *mgOggDecoder::decode(void)
+
+struct mgDecode *
+mgOggDecoder::decode (void)
{
- lock(); // this is released in Done()
-
- if( m_playing )
- {
- short framebuff[2*SF_SAMPLES];
- int n = m_file->stream( framebuff, SF_SAMPLES );
-
- if( n < 0 )
- {
- return done(dsError);
- }
-
- if( n == 0 )
- {
- return done(dsEof);
- }
-
- // should be done during initialization
- m_pcm->samplerate = m_item->getSampleRate(); // from database
- m_pcm->channels = m_item->getChannels(); // from database
-
- n /= m_pcm->channels;
- m_pcm->length = n;
- m_index = m_file->indexMs();
-
- short *data = framebuff;
- mad_fixed_t *sam0 = m_pcm->samples[0], *sam1 = m_pcm->samples[1];
-
- const int s = MAD_F_FRACBITS + 1 - ( sizeof(short)*8 ); // shift value for mad_fixed conversion
-
- if( m_pcm->channels>1 )
- {
- for(; n > 0 ; n-- )
- {
- *sam0++=(*data++) << s;
- *sam1++=(*data++) << s;
- }
- }
- else
- {
- for(; n>0 ; n--)
- {
- *sam0++=(*data++) << s;
- }
- }
- return done(dsPlay);
- }
- return done(dsError);
+ lock (); // this is released in Done()
+
+ if (m_playing)
+ {
+ short framebuff[2 * SF_SAMPLES];
+ int n = m_file->stream (framebuff, SF_SAMPLES);
+
+ if (n < 0)
+ {
+ return done (dsError);
+ }
+
+ if (n == 0)
+ {
+ return done (dsEof);
+ }
+
+// should be done during initialization
+ // from database
+ m_pcm->samplerate = m_item->getSampleRate ();
+ m_pcm->channels = m_item->getChannels (); // from database
+
+ n /= m_pcm->channels;
+ m_pcm->length = n;
+ m_index = m_file->indexMs ();
+
+ short *data = framebuff;
+ mad_fixed_t *sam0 = m_pcm->samples[0], *sam1 = m_pcm->samples[1];
+
+ // shift value for mad_fixed conversion
+ const int s = MAD_F_FRACBITS + 1 - (sizeof (short) * 8);
+
+ if (m_pcm->channels > 1)
+ {
+ for (; n > 0; n--)
+ {
+ *sam0++ = (*data++) << s;
+ *sam1++ = (*data++) << s;
+ }
+ }
+ else
+ {
+ for (; n > 0; n--)
+ {
+ *sam0++ = (*data++) << s;
+ }
+ }
+ return done (dsPlay);
+ }
+ return done (dsError);
}
-bool mgOggDecoder::skip(int Seconds, int Avail, int Rate)
+
+bool mgOggDecoder::skip (int Seconds, int Avail, int Rate)
{
- lock();
- bool res = false;
+ lock ();
+ bool
+ res = false;
- if( m_playing && m_file->canSeek() )
+ if (m_playing && m_file->canSeek ())
{
- float fsecs = (float)Seconds - ( (float)Avail / (float)(Rate * (16/8 * 2) ) );
- // Byte/s = samplerate * 16 bit * 2 chan
-
- long long newpos = m_file->indexMs() + (long long)(fsecs*1000.0);
-
- if( newpos < 0 )
- {
- newpos=0;
- }
-
- newpos = m_file->seek( newpos, false );
-
- if( newpos >= 0 )
- {
- m_index = m_file->indexMs();
-#ifdef DEBUG
- int i = index/1000;
- printf( "ogg: skipping to %02d:%02d\n", i/60, i%60 );
+ float
+ fsecs =
+ (float) Seconds - ((float) Avail / (float) (Rate * (16 / 8 * 2)));
+// Byte/s = samplerate * 16 bit * 2 chan
+
+ long long
+ newpos = m_file->indexMs () + (long long) (fsecs * 1000.0);
+
+ if (newpos < 0)
+ {
+ newpos = 0;
+ }
+
+ newpos = m_file->seek (newpos, false);
+
+ if (newpos >= 0)
+ {
+ m_index = m_file->indexMs ();
+#ifdef xDEBUG
+ int
+ i = index / 1000;
+ printf ("ogg: skipping to %02d:%02d\n", i / 60, i % 60);
#endif
- res = true;
- }
+ res = true;
+ }
}
- unlock();
- return res;
+ unlock ();
+ return res;
}
-
-#endif //HAVE_VORBISFILE
+#endif //HAVE_VORBISFILE