diff --git a/configure.ac b/configure.ac
index a5cee2ca3..8adebafa0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -234,6 +234,12 @@ AC_ARG_ENABLE(wavpack,
 	enable_wavpack=$enableval,
 	enable_wavpack=yes)
 
+AC_ARG_ENABLE(ffmpeg,
+	AS_HELP_STRING([--disable-ffmpeg],
+		[enable FFMPEG support (default: enable)]),
+	enable_ffmpeg=$enableval,
+	enable_ffmpeg=yes)
+
 AC_ARG_ENABLE(id3,
 	AS_HELP_STRING([--disable-id3],
 		[disable id3 support (default: enable)]),
@@ -672,6 +678,14 @@ fi
 
 AM_CONDITIONAL(HAVE_MIKMOD, test x$enable_mod = xyes)
 
+if test x$enable_ffmpeg = xyes; then
+	PKG_CHECK_MODULES(FFMPEG, [libavcodec libavformat],
+		AC_DEFINE(HAVE_FFMPEG, 1, [Define for FFMPEG support]),
+		enable_ffmpeg=no)
+fi
+
+AM_CONDITIONAL(HAVE_FFMPEG, test x$enable_ffmpeg = xyes)
+
 case $with_zeroconf in
 no|avahi|bonjour)
 	;;
@@ -955,6 +969,12 @@ else
 	echo " MOD support ...................disabled"
 fi
 
+if test x$enable_ffmpeg = xyes; then
+	echo " FFMPEG support ................enabled"
+else
+	echo " FFMPEG support ................disabled"
+fi
+
 if
 	test x$enable_mp3 = xno &&
 	test x$enable_oggvorbis = xno &&
@@ -964,6 +984,7 @@ if
 	test x$enable_aac = xno &&
 	test x$enable_mpc = xno &&
 	test x$enable_wavpack = xno &&
+	test x$enable_ffmpeg = xno &&
 	test x$enable_mod = xno; then
 	AC_MSG_ERROR([No input plugins supported!])
 fi
diff --git a/src/Makefile.am b/src/Makefile.am
index 70222db0c..56360812a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -225,6 +225,10 @@ if HAVE_MIKMOD
 mpd_SOURCES += inputPlugins/mod_plugin.c
 endif
 
+if HAVE_FFMPEG
+mpd_SOURCES += inputPlugins/ffmpeg_plugin.c
+endif
+
 
 if HAVE_ZEROCONF
 mpd_SOURCES += zeroconf.c
@@ -240,6 +244,7 @@ mpd_CPPFLAGS = \
 	$(AUDIOFILE_CFLAGS) $(LIBMIKMOD_CFLAGS) \
 	$(ID3TAG_CFLAGS) \
 	$(MAD_CFLAGS) \
+	$(FFMPEG_CFLAGS) \
 	$(GLIB_CFLAGS)
 mpd_LDADD = $(MPD_LIBS) $(MP4FF_LIB) \
 	$(AO_LIBS) $(ALSA_LIBS) \
@@ -248,6 +253,7 @@ mpd_LDADD = $(MPD_LIBS) $(MP4FF_LIB) \
 	$(AUDIOFILE_LIBS) $(LIBMIKMOD_LIBS) \
 	$(ID3TAG_LIBS) \
 	$(MAD_LIBS) \
+	$(FFMPEG_LIBS) \
 	$(GLIB_LIBS)
 
 DIST_SUBDIRS = mp4ff
diff --git a/src/decoder_list.c b/src/decoder_list.c
index 4aab73bda..252418154 100644
--- a/src/decoder_list.c
+++ b/src/decoder_list.c
@@ -30,6 +30,7 @@ extern struct decoder_plugin aacPlugin;
 extern struct decoder_plugin mpcPlugin;
 extern struct decoder_plugin wavpackPlugin;
 extern struct decoder_plugin modPlugin;
+extern struct decoder_plugin ffmpegPlugin;
 
 static List *inputPlugin_list;
 
@@ -179,6 +180,9 @@ void decoder_plugin_init_all(void)
 #ifdef HAVE_MIKMOD
 	decoder_plugin_load(&modPlugin);
 #endif
+#ifdef HAVE_FFMPEG
+	decoder_plugin_load(&ffmpegPlugin);
+#endif
 }
 
 void decoder_plugin_deinit_all(void)
diff --git a/src/inputPlugins/ffmpeg_plugin.c b/src/inputPlugins/ffmpeg_plugin.c
new file mode 100644
index 000000000..a9b69f298
--- /dev/null
+++ b/src/inputPlugins/ffmpeg_plugin.c
@@ -0,0 +1,416 @@
+/* the Music Player Daemon (MPD)
+ * Copyright (C) 2008 Viliam Mateicka <viliam.mateicka@gmail.com>
+ * This project's homepage is: http://www.musicpd.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "../decoder_api.h"
+#include "../log.h"
+#include "../utils.h"
+#include "../log.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <avcodec.h>
+#include <avformat.h>
+#include <avio.h>
+
+typedef struct {
+	int audioStream;
+	AVFormatContext *pFormatCtx;
+	AVCodecContext *aCodecCtx;
+	AVCodec *aCodec;
+	struct decoder *decoder;
+	InputStream *input;
+	struct tag *tag;
+} BasePtrs;
+
+typedef struct {
+	struct decoder *decoder;
+	InputStream *input;
+} FopsHelper;
+
+int mpdurl_open(URLContext *h, const char *filename, int flags);
+int mpdurl_read(URLContext *h, unsigned char *buf, int size);
+int64_t mpdurl_seek(URLContext *h, int64_t pos, int whence);
+int mpdurl_close(URLContext *h);
+
+URLProtocol mpdurl_fileops = {
+	.name = "mpd",
+	.url_open = mpdurl_open,
+	.url_read = mpdurl_read,
+	.url_write = NULL,
+	.url_seek = mpdurl_seek,
+	.url_close = mpdurl_close,
+	.next = NULL,
+	.url_read_pause = NULL,
+	.url_read_seek = NULL
+};
+
+
+int mpdurl_open(URLContext *h, const char *filename, int flags)
+{
+	uint32_t ptr;
+	FopsHelper *base;
+	if (strlen(filename) == (8+8)) {
+		errno = 0;
+		ptr = (uint32_t) strtoll(filename + 6, NULL, 16);
+		if (errno == 0 && ptr != 0) {
+			base = (FopsHelper *) ptr;
+			h->priv_data = base;
+			h->is_streamed = (base->input->seekable ? 0 : 1);
+			return 0;
+		}
+	}
+	FATAL("Invalid format %s:%d\n", filename, flags);
+	return -1;
+}
+
+int mpdurl_read(URLContext *h, unsigned char *buf, int size)
+{
+	int ret;
+	FopsHelper *base = (FopsHelper *) h->priv_data;
+	while (1) {
+		ret = readFromInputStream(base->input, (void *)buf, size);
+		if (ret == 0) {
+			DEBUG("ret 0\n");
+			if (inputStreamAtEOF(base->input) ||
+			    (base->decoder &&
+			     decoder_get_command(base->decoder) != DECODE_COMMAND_NONE)) {
+				DEBUG("eof stream\n");
+				return ret;
+			} else {
+				my_usleep(10000);
+			}
+		} else {
+			break;
+		}
+	}
+	return ret;
+}
+
+int64_t mpdurl_seek(URLContext *h, int64_t pos, int whence)
+{
+	FopsHelper *base = (FopsHelper *) h->priv_data;
+	if (whence != AVSEEK_SIZE) { //only ftell
+		(void) seekInputStream(base->input, pos, whence);
+	}
+	return base->input->offset;
+}
+
+int mpdurl_close(URLContext *h)
+{
+	FopsHelper *base = (FopsHelper *) h->priv_data;
+	if (base && base->input->seekable) {
+		(void) seekInputStream(base->input, 0, SEEK_SET);
+	}
+	h->priv_data = 0;
+	return 0;
+}
+
+static int ffmpeg_init(void)
+{
+	av_register_all();
+	register_protocol(&mpdurl_fileops);
+	return 0;
+}
+
+static int ffmpeg_helper(InputStream *input, int (*callback)(BasePtrs *ptrs),
+			 BasePtrs *ptrs)
+{
+	AVFormatContext *pFormatCtx;
+	AVCodecContext *aCodecCtx;
+	AVCodec *aCodec;
+	int ret, audioStream;
+	unsigned i;
+	FopsHelper fopshelp;
+	char url[24];
+
+	fopshelp.input = input;
+	if (ptrs && ptrs->decoder) {
+		fopshelp.decoder = ptrs->decoder; //are we in decoding loop ?
+	} else {
+		fopshelp.decoder = NULL;
+	}
+
+	//ffmpeg works with ours "fileops" helper
+	sprintf(url, "mpd://0x%8x", (unsigned int) &fopshelp);
+
+	if (av_open_input_file(&pFormatCtx, url, NULL, 0, NULL)!=0) {
+		ERROR("Open failed!\n");
+		return -1;
+	}
+
+	if (av_find_stream_info(pFormatCtx)<0) {
+		ERROR("Couldn't find stream info!\n");
+		return -1;
+	}
+
+	audioStream = -1;
+	for(i=0; i<pFormatCtx->nb_streams; i++) {
+		if (pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO &&
+		    audioStream < 0) {
+			audioStream=i;
+		}
+	}
+
+	if(audioStream==-1) {
+		ERROR("No audio stream inside!\n");
+		return -1;
+	}
+
+	aCodecCtx = pFormatCtx->streams[audioStream]->codec;
+	aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
+
+	if (!aCodec) {
+		ERROR("Unsupported audio codec!\n");
+		return -1;
+	}
+
+	if (avcodec_open(aCodecCtx, aCodec)<0) {
+		ERROR("Could not open codec!\n");
+		return -1;
+	}
+
+	if (callback) {
+		ptrs->audioStream = audioStream;
+		ptrs->pFormatCtx = pFormatCtx;
+		ptrs->aCodecCtx = aCodecCtx;
+		ptrs->aCodec = aCodec;
+
+		ret = (*callback)( ptrs );
+	} else {
+		ret = 0;
+		DEBUG("playable\n");
+	}
+
+	avcodec_close(aCodecCtx);
+	av_close_input_file(pFormatCtx);
+
+	return ret;
+}
+
+static bool ffmpeg_try_decode(InputStream *input)
+{
+	int ret;
+	if (input->seekable) {
+		ret = ffmpeg_helper(input, NULL, NULL);
+	} else {
+		ret = 0;
+	}
+	return (ret == -1 ? 0 : 1);
+}
+
+static int ffmpeg_decode_internal(BasePtrs *base)
+{
+	struct decoder *decoder = base->decoder;
+	AVCodecContext *aCodecCtx = base->aCodecCtx;
+	AVFormatContext *pFormatCtx = base->pFormatCtx;
+	AVPacket packet;
+	int len, audio_size;
+	int position;
+	struct audio_format audio_format;
+	int current, total_time;
+	uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];
+
+	total_time = 0;
+
+	DEBUG("decoder_start\n");
+
+	if (aCodecCtx->channels > 2) {
+		aCodecCtx->channels = 2;
+	}
+
+	audio_format.bits = (uint8_t)16;
+	audio_format.sample_rate = (unsigned int)aCodecCtx->sample_rate;
+	audio_format.channels = aCodecCtx->channels;
+
+	//    frame_count = afGetFrameCount(af_fp, AF_DEFAULT_TRACK);
+	//    total_time = ((float)frame_count / (float)audio_format.sample_rate);
+
+	//there is some problem with this on some demux (mp3 at least)
+	if (pFormatCtx->duration != (int)AV_NOPTS_VALUE) {
+		total_time = pFormatCtx->duration / AV_TIME_BASE;
+	}
+
+	DEBUG("ffmpeg sample rate: %dHz %d channels\n",
+	      aCodecCtx->sample_rate, aCodecCtx->channels);
+
+	decoder_initialized(decoder, &audio_format, total_time);
+
+	position = 0;
+
+	DEBUG("duration:%d (%d secs)\n", (int) pFormatCtx->duration,
+	      (int) total_time);
+
+	do {
+
+		if (decoder_get_command(decoder) == DECODE_COMMAND_SEEK) {
+
+			DEBUG("seek\n");
+			decoder_clear(decoder);
+			current = decoder_seek_where(decoder) * AV_TIME_BASE;
+
+			if (av_seek_frame(pFormatCtx, -1, current , 0) < 0) {
+				WARNING("seek to %d failed\n", current);
+			}
+
+			decoder_command_finished(decoder);
+		}
+
+		if (av_read_frame(pFormatCtx, &packet) >= 0) {
+			if(packet.stream_index == base->audioStream) {
+
+				position = av_rescale_q(packet.pts, pFormatCtx->streams[base->audioStream]->time_base,
+							(AVRational){1, 1});
+
+				audio_size = sizeof(audio_buf);
+				len = avcodec_decode_audio2(aCodecCtx,
+							    (int16_t *)audio_buf,
+							    &audio_size,
+							    packet.data,
+							    packet.size);
+
+				if(len >= 0) {
+					if(audio_size >= 0) {
+						// DEBUG("sending data %d/%d\n", audio_size, len);
+
+						decoder_data(decoder, NULL, 1,
+							     audio_buf, audio_size,
+							     position, //(float)current / (float)audio_format.sample_rate,
+							     aCodecCtx->bit_rate / 1000, NULL);
+
+					}
+				} else {
+					WARNING("skiping frame!\n");
+				}
+			}
+			av_free_packet(&packet);
+		} else {
+			//end of file
+			break;
+		}
+	} while (decoder_get_command(decoder) != DECODE_COMMAND_STOP);
+
+	decoder_flush(decoder);
+
+	DEBUG("decoder finish\n");
+
+	return 0;
+}
+
+static int ffmpeg_decode(struct decoder *decoder, InputStream *input)
+{
+	BasePtrs base;
+	int ret;
+
+	DEBUG("decode start\n");
+
+	base.input = input;
+	base.decoder = decoder;
+
+	ret = ffmpeg_helper(input, ffmpeg_decode_internal, &base);
+
+	DEBUG("decode finish\n");
+
+	return ret;
+}
+
+static int ffmpeg_tag_internal(BasePtrs *base)
+{
+	struct tag *tag = (struct tag *) base->tag;
+
+	if (base->pFormatCtx->duration != (int)AV_NOPTS_VALUE) {
+		tag->time = base->pFormatCtx->duration / AV_TIME_BASE;
+	} else {
+		tag->time = 0;
+	}
+	return 0;
+}
+
+//no tag reading in ffmpeg, check if playable
+static struct tag *ffmpeg_tag(char *file)
+{
+	InputStream input;
+	BasePtrs base;
+	int ret;
+	struct tag *tag = NULL;
+
+	if (openInputStream(&input, file) < 0) {
+		ERROR("failed to open %s\n", file);
+		return NULL;
+	}
+
+	tag = tag_new();
+
+	base.tag = tag;
+	ret = ffmpeg_helper(&input, ffmpeg_tag_internal, &base);
+
+	if (ret != 0) {
+		free(tag);
+		tag = NULL;
+	}
+
+	closeInputStream(&input);
+
+	return tag;
+}
+
+/**
+ * ffmpeg can decode almost everything from open codecs
+ * and also some of propietary codecs
+ * its hard to tell what can ffmpeg decode
+ * we can later put this into configure script
+ * to be sure ffmpeg is used to handle
+ * only that files
+ */
+
+static const char *ffmpeg_Suffixes[] = {
+	"wma", "asf", "wmv", "mpeg", "mpg", "avi", "vob", "mov", "qt", "swf", "rm", "swf",
+	"mp1", "mp2", "mp3", "mp4", "m4a", "flac", "ogg", "wav", "au", "aiff", "aif", "ac3", "aac", "mpc",
+	NULL
+};
+
+//not sure if this is correct...
+static const char *ffmpeg_Mimetypes[] = {
+	"video/x-ms-asf",
+	"audio/x-ms-wma",
+	"audio/x-ms-wax",
+	"video/x-ms-wmv",
+	"video/x-ms-wvx",
+	"video/x-ms-wm",
+	"video/x-ms-wmx",
+	"application/x-ms-wmz",
+	"application/x-ms-wmd",
+	"audio/mpeg",
+	NULL
+};
+
+struct decoder_plugin ffmpegPlugin = {
+	.name = "ffmpeg",
+	.init = ffmpeg_init,
+	.try_decode = ffmpeg_try_decode,
+	.stream_decode = ffmpeg_decode,
+	.tag_dup = ffmpeg_tag,
+	.stream_types = INPUT_PLUGIN_STREAM_URL | INPUT_PLUGIN_STREAM_FILE,
+	.suffixes = ffmpeg_Suffixes,
+	.mime_types = ffmpeg_Mimetypes
+};