summaryrefslogtreecommitdiffstats
path: root/plugins/decoder/ffmpeg
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
commit50b48aec6ddd451a6d1709c0942477b503457663 (patch)
treea9ece53ec06fd0a2819de7a2a6de997193566626 /plugins/decoder/ffmpeg
downloadk3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz
k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'plugins/decoder/ffmpeg')
-rw-r--r--plugins/decoder/ffmpeg/Makefile.am15
-rw-r--r--plugins/decoder/ffmpeg/configure.in.bot25
-rw-r--r--plugins/decoder/ffmpeg/configure.in.in68
-rw-r--r--plugins/decoder/ffmpeg/k3bffmpegdecoder.cpp155
-rw-r--r--plugins/decoder/ffmpeg/k3bffmpegdecoder.h67
-rw-r--r--plugins/decoder/ffmpeg/k3bffmpegdecoder.plugin9
-rw-r--r--plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp375
-rw-r--r--plugins/decoder/ffmpeg/k3bffmpegwrapper.h85
8 files changed, 799 insertions, 0 deletions
diff --git a/plugins/decoder/ffmpeg/Makefile.am b/plugins/decoder/ffmpeg/Makefile.am
new file mode 100644
index 0000000..b4c46e2
--- /dev/null
+++ b/plugins/decoder/ffmpeg/Makefile.am
@@ -0,0 +1,15 @@
+AM_CPPFLAGS = -I$(srcdir)/../../../libk3b/core -I$(srcdir)/../../../libk3b/plugin -I$(srcdir)/../../../libk3bdevice $(all_includes)
+KDE_CXXFLAGS = -D__STDC_CONSTANT_MACROS
+
+kde_module_LTLIBRARIES = libk3bffmpegdecoder.la
+
+libk3bffmpegdecoder_la_SOURCES = k3bffmpegdecoder.cpp k3bffmpegwrapper.cpp
+
+libk3bffmpegdecoder_la_LIBADD = ../../../libk3b/libk3b.la $(LIB_KDEUI) -lavcodec -lavformat
+libk3bffmpegdecoder_la_LDFLAGS = -avoid-version -module -no-undefined $(all_libraries)
+
+pluginsdir = $(kde_datadir)/k3b/plugins
+plugins_DATA = k3bffmpegdecoder.plugin
+
+METASOURCES = AUTO
+
diff --git a/plugins/decoder/ffmpeg/configure.in.bot b/plugins/decoder/ffmpeg/configure.in.bot
new file mode 100644
index 0000000..3d24645
--- /dev/null
+++ b/plugins/decoder/ffmpeg/configure.in.bot
@@ -0,0 +1,25 @@
+echo ""
+
+echo "K3b - FFMpeg decoder plugin (decodes wma and others):"
+if test x$have_ffmpeg = xyes; then
+ echo "K3b - yes"
+ if test x$enable_ffmpeg_all_codecs = xyes; then
+ echo "K3b - WARNING: You enabled all codecs in the ffmpeg decoder plugin."
+ echo "K3b - Be aware that most are not tested and track lengths"
+ echo "K3b - will be wrong in many cases."
+ fi
+else
+ echo "K3b - no"
+if test "$ac_cv_use_ffmpeg" = "yes"; then
+ if test "$ffmpeg_compiles" = "yes"; then
+ echo "K3b - You are missing the ffmpeg libraries."
+ echo "K3b - Make sure ffmpeg has been configured as a"
+ echo "K3b - shared library (which is not the default)."
+ else
+ echo "K3b - You are missing the ffmpeg headers and libraries"
+ echo "K3b - version 0.4.9 or higher."
+ fi
+ echo "K3b - The ffmpeg audio decoding plugin (decodes wma and"
+ echo "K3b - others) won't be compiled."
+fi
+fi
diff --git a/plugins/decoder/ffmpeg/configure.in.in b/plugins/decoder/ffmpeg/configure.in.in
new file mode 100644
index 0000000..84b345a
--- /dev/null
+++ b/plugins/decoder/ffmpeg/configure.in.in
@@ -0,0 +1,68 @@
+dnl --------------- FFMPEG CHECK ---------------------------------
+
+AC_ARG_WITH(
+ ffmpeg,
+ AS_HELP_STRING(
+ [--without-ffmpeg],
+ [build K3b without ffmpeg audio decoder support (default=no)]),
+ [ac_cv_use_ffmpeg=$withval],
+ [ac_cv_use_ffmpeg=yes]
+)
+
+#
+# The ffmpeg decoder plugin needs ffmpeg 0.4.9 or higher
+#
+have_ffmpeg=no
+if test "$ac_cv_use_ffmpeg" = "yes"; then
+ k3b_cxxflags_save="$CXXFLAGS"
+ CXXFLAGS="$CXXFLAGS -D__STDC_CONSTANT_MACROS"
+ AC_MSG_CHECKING(for ffmpeg >= 0.4.9)
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ AC_COMPILE_IFELSE(
+ extern "C" {
+ #include <libavformat/avformat.h>
+ #include <libavcodec/avcodec.h>
+ }
+
+ int main() {
+ AVFormatContext* fc = 0;
+ AVPacket* p = 0;
+ av_register_all();
+ return av_read_frame( fc, p );
+ },
+ [ffmpeg_compiles=yes], [ffmpeg_compiles=no] )
+ OLD_LIBS=$LIBS
+ LIBS="-lavformat -lavcodec $LIBS"
+ AC_LINK_IFELSE(
+ extern "C" {
+ #include <libavformat/avformat.h>
+ #include <libavcodec/avcodec.h>
+ }
+
+ int main() {
+ AVFormatContext* fc = 0;
+ AVPacket* p = 0;
+ av_register_all();
+ return av_read_frame( fc, p );
+ },
+ [ffmpeg_links=yes], [ffmpeg_links=no] )
+ AC_LANG_RESTORE
+ LIBS=$OLD_LIBS
+ have_ffmpeg=$ffmpeg_links
+ AC_MSG_RESULT($have_ffmpeg)
+ CXXFLAGS=$k3b_cxxflags_save
+fi
+AM_CONDITIONAL(include_FFMPEG, [test x$have_ffmpeg = xyes])
+
+dnl --------------- FFMPEG CHECK END ------------------------------
+
+AC_ARG_ENABLE(
+ ffmpeg-all-codecs,
+ AS_HELP_STRING(
+ [--enable-ffmpeg-all-codecs],
+ [Build K3b's ffmeg decoder plugin with all audio codecs enabled (default=disabled)]),
+ [AC_DEFINE(K3B_FFMPEG_ALL_CODECS, 1, [Defined if all ffmpeg codecs should be allowed])
+ enable_ffmpeg_all_codecs=yes],
+ [enable_ffmpeg_all_codecs=no]
+)
diff --git a/plugins/decoder/ffmpeg/k3bffmpegdecoder.cpp b/plugins/decoder/ffmpeg/k3bffmpegdecoder.cpp
new file mode 100644
index 0000000..fd47c52
--- /dev/null
+++ b/plugins/decoder/ffmpeg/k3bffmpegdecoder.cpp
@@ -0,0 +1,155 @@
+/*
+ *
+ * $Id: k3bffmpegdecoder.cpp 641798 2007-03-12 16:07:10Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ */
+
+#include <config.h>
+
+#include "k3bffmpegdecoder.h"
+#include "k3bffmpegwrapper.h"
+
+#include <kdebug.h>
+#include <k3bpluginfactory.h>
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+#include <math.h>
+
+
+K_EXPORT_COMPONENT_FACTORY( libk3bffmpegdecoder, K3bPluginFactory<K3bFFMpegDecoderFactory>( "k3bffmpegdecoder" ) )
+
+
+K3bFFMpegDecoderFactory::K3bFFMpegDecoderFactory( QObject* parent, const char* name )
+ : K3bAudioDecoderFactory( parent, name )
+{
+}
+
+
+K3bFFMpegDecoderFactory::~K3bFFMpegDecoderFactory()
+{
+}
+
+
+K3bAudioDecoder* K3bFFMpegDecoderFactory::createDecoder( QObject* parent,
+ const char* name ) const
+{
+ return new K3bFFMpegDecoder( parent, name );
+}
+
+
+bool K3bFFMpegDecoderFactory::canDecode( const KURL& url )
+{
+ K3bFFMpegFile* file = K3bFFMpegWrapper::instance()->open( url.path() );
+ if( file ) {
+ delete file;
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+
+
+
+
+
+K3bFFMpegDecoder::K3bFFMpegDecoder( QObject* parent, const char* name )
+ : K3bAudioDecoder( parent, name ),
+ m_file(0)
+{
+}
+
+
+K3bFFMpegDecoder::~K3bFFMpegDecoder()
+{
+}
+
+
+QString K3bFFMpegDecoder::fileType() const
+{
+ return m_type;
+}
+
+
+bool K3bFFMpegDecoder::analyseFileInternal( K3b::Msf& frames, int& samplerate, int& ch )
+{
+ m_file = K3bFFMpegWrapper::instance()->open( filename() );
+ if( m_file ) {
+
+ // TODO: call addTechnicalInfo
+
+ addMetaInfo( META_TITLE, m_file->title() );
+ addMetaInfo( META_ARTIST, m_file->author() );
+ addMetaInfo( META_COMMENT, m_file->comment() );
+
+ samplerate = m_file->sampleRate();
+ ch = m_file->channels();
+ m_type = m_file->typeComment();
+ frames = m_file->length();
+
+ // ffmpeg's length information is not reliable at all
+ // so we have to decode the whole file in order to get the correct length
+// char buffer[10*2048];
+// int len = 0;
+// unsigned long long bytes = 0;
+// while( ( len = m_file->read( buffer, 10*2048 ) ) > 0 )
+// bytes += len;
+
+// frames = (unsigned long)ceil((double)bytes/2048.0);
+
+ // cleanup;
+ delete m_file;
+ m_file = 0;
+
+ return true;
+ }
+ else
+ return false;
+}
+
+
+bool K3bFFMpegDecoder::initDecoderInternal()
+{
+ if( !m_file )
+ m_file = K3bFFMpegWrapper::instance()->open( filename() );
+
+ return (m_file != 0);
+}
+
+
+void K3bFFMpegDecoder::cleanup()
+{
+ delete m_file;
+ m_file = 0;
+}
+
+
+bool K3bFFMpegDecoder::seekInternal( const K3b::Msf& msf )
+{
+ if( msf == 0 )
+ return initDecoderInternal();
+ else
+ return m_file->seek( msf );
+}
+
+
+int K3bFFMpegDecoder::decodeInternal( char* _data, int maxLen )
+{
+ return m_file->read( _data, maxLen );
+}
+
+
+#include "k3bffmpegdecoder.moc"
diff --git a/plugins/decoder/ffmpeg/k3bffmpegdecoder.h b/plugins/decoder/ffmpeg/k3bffmpegdecoder.h
new file mode 100644
index 0000000..1c21827
--- /dev/null
+++ b/plugins/decoder/ffmpeg/k3bffmpegdecoder.h
@@ -0,0 +1,67 @@
+/*
+ *
+ * $Id: k3bffmpegdecoder.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ */
+
+#ifndef _K3B_FFMPEG_DECODER_H_
+#define _K3B_FFMPEG_DECODER_H_
+
+#include <k3baudiodecoder.h>
+
+class K3bFFMpegFile;
+
+
+class K3bFFMpegDecoderFactory : public K3bAudioDecoderFactory
+{
+ Q_OBJECT
+
+ public:
+ K3bFFMpegDecoderFactory( QObject* parent = 0, const char* name = 0 );
+ ~K3bFFMpegDecoderFactory();
+
+ bool canDecode( const KURL& filename );
+
+ int pluginSystemVersion() const { return 3; }
+
+ bool multiFormatDecoder() const { return true; }
+
+ K3bAudioDecoder* createDecoder( QObject* parent = 0,
+ const char* name = 0 ) const;
+};
+
+
+class K3bFFMpegDecoder : public K3bAudioDecoder
+{
+ Q_OBJECT
+
+ public:
+ K3bFFMpegDecoder( QObject* parent = 0, const char* name = 0 );
+ ~K3bFFMpegDecoder();
+
+ QString fileType() const;
+
+ void cleanup();
+
+ protected:
+ bool analyseFileInternal( K3b::Msf& frames, int& samplerate, int& ch );
+ bool initDecoderInternal();
+ bool seekInternal( const K3b::Msf& );
+
+ int decodeInternal( char* _data, int maxLen );
+
+ private:
+ K3bFFMpegFile* m_file;
+ QString m_type;
+};
+
+#endif
diff --git a/plugins/decoder/ffmpeg/k3bffmpegdecoder.plugin b/plugins/decoder/ffmpeg/k3bffmpegdecoder.plugin
new file mode 100644
index 0000000..3592388
--- /dev/null
+++ b/plugins/decoder/ffmpeg/k3bffmpegdecoder.plugin
@@ -0,0 +1,9 @@
+[K3b Plugin]
+Lib=libk3bffmpegdecoder
+Group=AudioDecoder
+Name=K3b FFMpeg Decoder
+Author=Sebastian Trueg
+Email=trueg@k3b.org
+Version=0.9.1
+Comment=Decoding module to decode wma files
+License=GPL
diff --git a/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp b/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp
new file mode 100644
index 0000000..514fd67
--- /dev/null
+++ b/plugins/decoder/ffmpeg/k3bffmpegwrapper.cpp
@@ -0,0 +1,375 @@
+/*
+ *
+ * $Id: k3bffmpegwrapper.cpp 641819 2007-03-12 17:29:23Z trueg $
+ * Copyright (C) 2004-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ */
+
+#include <config.h>
+
+#include "k3bffmpegwrapper.h"
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+}
+
+#include <string.h>
+
+#include <klocale.h>
+
+
+#if LIBAVFORMAT_BUILD < 4629
+#define FFMPEG_BUILD_PRE_4629
+#endif
+
+
+K3bFFMpegWrapper* K3bFFMpegWrapper::s_instance = 0;
+
+
+class K3bFFMpegFile::Private
+{
+public:
+ AVFormatContext* formatContext;
+ AVCodec* codec;
+
+ K3b::Msf length;
+
+ // for decoding
+ char outputBuffer[AVCODEC_MAX_AUDIO_FRAME_SIZE];
+ char* outputBufferPos;
+ int outputBufferSize;
+ AVPacket packet;
+ Q_UINT8* packetData;
+ int packetSize;
+};
+
+
+K3bFFMpegFile::K3bFFMpegFile( const QString& filename )
+ : m_filename(filename)
+{
+ d = new Private;
+ d->formatContext = 0;
+ d->codec = 0;
+}
+
+
+K3bFFMpegFile::~K3bFFMpegFile()
+{
+ close();
+ delete d;
+}
+
+
+bool K3bFFMpegFile::open()
+{
+ close();
+
+ // open the file
+ int err = av_open_input_file( &d->formatContext, m_filename.local8Bit(), 0, 0, 0 );
+ if( err < 0 ) {
+ kdDebug() << "(K3bFFMpegFile) unable to open " << m_filename << " with error " << err << endl;
+ return false;
+ }
+
+ // analyze the streams
+ av_find_stream_info( d->formatContext );
+
+ // we only handle files containing one audio stream
+ if( d->formatContext->nb_streams != 1 ) {
+ kdDebug() << "(K3bFFMpegFile) more than one stream in " << m_filename << endl;
+ return false;
+ }
+
+ // urgh... ugly
+#ifdef FFMPEG_BUILD_PRE_4629
+ AVCodecContext* codecContext = &d->formatContext->streams[0]->codec;
+#else
+ AVCodecContext* codecContext = d->formatContext->streams[0]->codec;
+#endif
+ if( codecContext->codec_type != CODEC_TYPE_AUDIO ) {
+ kdDebug() << "(K3bFFMpegFile) not a simple audio stream: " << m_filename << endl;
+ return false;
+ }
+
+ // get the codec
+ d->codec = avcodec_find_decoder(codecContext->codec_id);
+ if( !d->codec ) {
+ kdDebug() << "(K3bFFMpegFile) no codec found for " << m_filename << endl;
+ return false;
+ }
+
+ // open the codec on our context
+ kdDebug() << "(K3bFFMpegFile) found codec for " << m_filename << endl;
+ if( avcodec_open( codecContext, d->codec ) < 0 ) {
+ kdDebug() << "(K3bFFMpegDecoderFactory) could not open codec." << endl;
+ return false;
+ }
+
+ // determine the length of the stream
+ d->length = K3b::Msf::fromSeconds( (double)d->formatContext->duration / (double)AV_TIME_BASE );
+
+ if( d->length == 0 ) {
+ kdDebug() << "(K3bFFMpegDecoderFactory) invalid length." << endl;
+ return false;
+ }
+
+ // dump some debugging info
+ dump_format( d->formatContext, 0, m_filename.local8Bit(), 0 );
+
+ return true;
+}
+
+
+void K3bFFMpegFile::close()
+{
+ d->outputBufferSize = 0;
+ d->packetSize = 0;
+ d->packetData = 0;
+
+ if( d->codec ) {
+#ifdef FFMPEG_BUILD_PRE_4629
+ avcodec_close( &d->formatContext->streams[0]->codec );
+#else
+ avcodec_close( d->formatContext->streams[0]->codec );
+#endif
+ d->codec = 0;
+ }
+
+ if( d->formatContext ) {
+ av_close_input_file( d->formatContext );
+ d->formatContext = 0;
+ }
+}
+
+
+K3b::Msf K3bFFMpegFile::length() const
+{
+ return d->length;
+}
+
+
+int K3bFFMpegFile::sampleRate() const
+{
+#ifdef FFMPEG_BUILD_PRE_4629
+ return d->formatContext->streams[0]->codec.sample_rate;
+#else
+ return d->formatContext->streams[0]->codec->sample_rate;
+#endif
+}
+
+
+int K3bFFMpegFile::channels() const
+{
+#ifdef FFMPEG_BUILD_PRE_4629
+ return d->formatContext->streams[0]->codec.channels;
+#else
+ return d->formatContext->streams[0]->codec->channels;
+#endif
+}
+
+
+int K3bFFMpegFile::type() const
+{
+#ifdef FFMPEG_BUILD_PRE_4629
+ return d->formatContext->streams[0]->codec.codec_id;
+#else
+ return d->formatContext->streams[0]->codec->codec_id;
+#endif
+}
+
+
+QString K3bFFMpegFile::typeComment() const
+{
+ switch( type() ) {
+ case CODEC_ID_WMAV1:
+ return i18n("Windows Media v1");
+ case CODEC_ID_WMAV2:
+ return i18n("Windows Media v2");
+ case CODEC_ID_MP3:
+ return i18n("MPEG 1 Layer III");
+ case CODEC_ID_AAC:
+ return i18n("Advanced Audio Coding (AAC)");
+ default:
+ return QString::fromLocal8Bit( d->codec->name );
+ }
+}
+
+
+QString K3bFFMpegFile::title() const
+{
+ // FIXME: is this UTF8 or something??
+ if( d->formatContext->title[0] != '\0' )
+ return QString::fromLocal8Bit( d->formatContext->title );
+ else
+ return QString::null;
+}
+
+
+QString K3bFFMpegFile::author() const
+{
+ // FIXME: is this UTF8 or something??
+ if( d->formatContext->author[0] != '\0' )
+ return QString::fromLocal8Bit( d->formatContext->author );
+ else
+ return QString::null;
+}
+
+
+QString K3bFFMpegFile::comment() const
+{
+ // FIXME: is this UTF8 or something??
+ if( d->formatContext->comment[0] != '\0' )
+ return QString::fromLocal8Bit( d->formatContext->comment );
+ else
+ return QString::null;
+}
+
+
+int K3bFFMpegFile::read( char* buf, int bufLen )
+{
+ if( fillOutputBuffer() > 0 ) {
+ int len = QMIN(bufLen, d->outputBufferSize);
+ ::memcpy( buf, d->outputBufferPos, len );
+
+ // TODO: only swap if needed
+ for( int i = 0; i < len-1; i+=2 ) {
+ char a = buf[i];
+ buf[i] = buf[i+1];
+ buf[i+1] = a;
+ }
+
+ d->outputBufferPos += len;
+ d->outputBufferSize -= len;
+ return len;
+ }
+ else
+ return 0;
+}
+
+
+// fill d->packetData with data to decode
+int K3bFFMpegFile::readPacket()
+{
+ if( d->packetSize <= 0 ) {
+ av_init_packet( &d->packet );
+
+ if( av_read_frame( d->formatContext, &d->packet ) < 0 ) {
+ return 0;
+ }
+
+ d->packetSize = d->packet.size;
+ d->packetData = d->packet.data;
+ }
+
+ return d->packetSize;
+}
+
+
+// decode data in d->packetData and fill d->outputBuffer
+int K3bFFMpegFile::fillOutputBuffer()
+{
+ // decode if the output buffer is empty
+ if( d->outputBufferSize <= 0 ) {
+
+ // make sure we have data to decode
+ if( readPacket() == 0 ) {
+ return 0;
+ }
+
+ d->outputBufferPos = d->outputBuffer;
+
+#ifdef FFMPEG_BUILD_PRE_4629
+ int len = avcodec_decode_audio2( &d->formatContext->streams[0]->codec,
+#else
+ int len = avcodec_decode_audio2( d->formatContext->streams[0]->codec,
+#endif
+ (short*)d->outputBuffer, &d->outputBufferSize,
+ d->packetData, d->packetSize );
+
+ d->packetSize -= len;
+ d->packetData += len;
+
+ if( d->packetSize <= 0 )
+ av_free_packet( &d->packet );
+ }
+
+ // if it is still empty try again
+ if( d->outputBufferSize <= 0 )
+ return fillOutputBuffer();
+ else
+ return d->outputBufferSize;
+}
+
+
+bool K3bFFMpegFile::seek( const K3b::Msf& msf )
+{
+ d->outputBufferSize = 0;
+ d->packetSize = 0;
+
+ double seconds = (double)msf.totalFrames()/75.0;
+ Q_UINT64 timestamp = (Q_UINT64)(seconds * (double)AV_TIME_BASE);
+
+ // FIXME: do we really need the start_time and why?
+#if LIBAVFORMAT_BUILD >= 4619
+ return ( av_seek_frame( d->formatContext, -1, timestamp + d->formatContext->start_time, 0 ) >= 0 );
+#else
+ return ( av_seek_frame( d->formatContext, -1, timestamp + d->formatContext->start_time ) >= 0 );
+#endif
+}
+
+
+
+
+
+
+K3bFFMpegWrapper::K3bFFMpegWrapper()
+{
+ av_register_all();
+}
+
+
+K3bFFMpegWrapper::~K3bFFMpegWrapper()
+{
+ s_instance = 0;
+}
+
+
+K3bFFMpegWrapper* K3bFFMpegWrapper::instance()
+{
+ if( !s_instance ) {
+ s_instance = new K3bFFMpegWrapper();
+ }
+
+ return s_instance;
+}
+
+
+K3bFFMpegFile* K3bFFMpegWrapper::open( const QString& filename ) const
+{
+ K3bFFMpegFile* file = new K3bFFMpegFile( filename );
+ if( file->open() ) {
+#ifndef K3B_FFMPEG_ALL_CODECS
+ //
+ // only allow tested formats. ffmpeg seems not to be too reliable with every format.
+ // mp3 being one of them sadly. Most importantly: allow the libsndfile decoder to do
+ // its thing.
+ //
+ if( file->type() == CODEC_ID_WMAV1 ||
+ file->type() == CODEC_ID_WMAV2 ||
+ file->type() == CODEC_ID_AAC )
+#endif
+ return file;
+ }
+
+ delete file;
+ return 0;
+}
diff --git a/plugins/decoder/ffmpeg/k3bffmpegwrapper.h b/plugins/decoder/ffmpeg/k3bffmpegwrapper.h
new file mode 100644
index 0000000..63b5f58
--- /dev/null
+++ b/plugins/decoder/ffmpeg/k3bffmpegwrapper.h
@@ -0,0 +1,85 @@
+/*
+ *
+ * $Id: k3bffmpegwrapper.h 619556 2007-01-03 17:38:12Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * 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.
+ */
+
+#ifndef _K3B_FFMPEG_WRAPPER_H_
+#define _K3B_FFMPEG_WRAPPER_H_
+
+#include <k3bmsf.h>
+
+
+
+/**
+ * Create with K3bFFMpegWrapper::open
+ */
+class K3bFFMpegFile
+{
+ friend class K3bFFMpegWrapper;
+
+ public:
+ ~K3bFFMpegFile();
+
+ const QString& filename() const { return m_filename; }
+
+ bool open();
+ void close();
+
+ K3b::Msf length() const;
+ int sampleRate() const;
+ int channels() const;
+
+ /**
+ * ffmpeg internal enumeration
+ */
+ int type() const;
+ QString typeComment() const;
+
+ QString title() const;
+ QString author() const;
+ QString comment() const;
+
+ int read( char* buf, int bufLen );
+ bool seek( const K3b::Msf& );
+
+ private:
+ K3bFFMpegFile( const QString& filename );
+ int readPacket();
+ int fillOutputBuffer();
+
+ QString m_filename;
+
+ class Private;
+ Private* d;
+};
+
+
+class K3bFFMpegWrapper
+{
+ public:
+ ~K3bFFMpegWrapper();
+
+ /**
+ * returns 0 on failure.
+ */
+ K3bFFMpegFile* open( const QString& filename ) const;
+
+ static K3bFFMpegWrapper* instance();
+
+ private:
+ K3bFFMpegWrapper();
+
+ static K3bFFMpegWrapper* s_instance;
+};
+
+#endif