Index: /dsfilters/before-you-ask.txt
===================================================================
--- /dsfilters/before-you-ask.txt	(revision 370)
+++ /dsfilters/before-you-ask.txt	(revision 371)
@@ -10,16 +10,9 @@
 
 
-Recently I've added basic stuff for decoder filter.
-Right now it can not even be created so don't even
-try to register it or you'll get errors.
-I'll update it soon.
+Decoder and Demuxer now can play SV8 files.
+But since there is no filetype detection added
+in the registry, the process of opening a file
+may take a little while in some players.
 
-Demux MPC works quite fine.
-It parses input file, extracts decoder specific information
-and outputs AP packets with proper timestamps. 
-Seeking is implemented using seeking tables.
-Right now there is no way to seek files without seeking table.
-It also contains internal buffering mechanism that should allow network 
-playback in the future.
 
 stay tuned.
Index: /dsfilters/dec_mpc/dec_mpc.vcproj
===================================================================
--- /dsfilters/dec_mpc/dec_mpc.vcproj	(revision 370)
+++ /dsfilters/dec_mpc/dec_mpc.vcproj	(revision 371)
@@ -42,5 +42,5 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
-				AdditionalIncludeDirectories=".\src"
+				AdditionalIncludeDirectories=".\src;..\..\libmpc\trunk\include;..\..\libmpc\trunk\libmpcdec"
 				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;DEC_MPC_EXPORTS"
 				MinimalRebuild="true"
@@ -63,5 +63,5 @@
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="strmbasdu.lib strmiids.lib winmm.lib"
+				AdditionalDependencies="strmbasdu.lib strmiids.lib winmm.lib ..\lib\libmpcdec_d.lib ..\lib\libcommon_d.lib"
 				OutputFile=".\bin\mmmpcdecd.ax"
 				LinkIncremental="2"
@@ -123,5 +123,5 @@
 			<Tool
 				Name="VCCLCompilerTool"
-				AdditionalIncludeDirectories=".\src"
+				AdditionalIncludeDirectories=".\src;..\..\libmpc\trunk\include;..\..\libmpc\trunk\libmpcdec"
 				PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;DEC_MPC_EXPORTS"
 				RuntimeLibrary="2"
@@ -142,5 +142,5 @@
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="strmbaseu.lib strmiids.lib winmm.lib"
+				AdditionalDependencies="strmbaseu.lib strmiids.lib winmm.lib ..\lib\libmpcdec.lib ..\lib\libcommon.lib"
 				OutputFile=".\bin\mmmpcdec.ax"
 				LinkIncremental="1"
Index: /dsfilters/dec_mpc/src/mpc_filter.cpp
===================================================================
--- /dsfilters/dec_mpc/src/mpc_filter.cpp	(revision 370)
+++ /dsfilters/dec_mpc/src/mpc_filter.cpp	(revision 371)
@@ -42,10 +42,17 @@
 CUnknown *CMPCDecoder::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
 {
+	if (phr) *phr = NOERROR;
+
 	return new CMPCDecoder(pUnk, phr);
 }
 
 CMPCDecoder::CMPCDecoder(LPUNKNOWN pUnk, HRESULT *phr) :
-	CTransformFilter(_T("MPC Decoder"), pUnk, CLSID_MusepackDecoder)
-{
+	CTransformFilter(_T("MPC Decoder"), pUnk, CLSID_MusepackDecoder),
+	demux(NULL),
+	decoder_specific(NULL),
+	decoder_specific_size(0)
+{
+	if (phr) *phr = NOERROR;
+
 	m_pInput = new CTransformInputPin(NAME("Input"), this, phr, L"Input");
 	m_pOutput = new CTransformOutputPin(NAME("Output"), this, phr, L"Output");
@@ -108,5 +115,8 @@
 		if (pmt->formattype != FORMAT_WaveFormatEx) return E_FAIL;
 
-		WAVEFORMATEX *wfx = (WAVEFORMATEX*)pmt->pbFormat;
+		// keep a local copy so our decoder specific info doesn't go away
+		mtIn = *pmt;
+
+		WAVEFORMATEX *wfx = (WAVEFORMATEX*)mtIn.pbFormat;
 
 		// we assemble output format
@@ -116,7 +126,32 @@
 		wfOut.wFormatTag = WAVE_FORMAT_PCM;
 		wfOut.wBitsPerSample = 16;				// currently only 16-bit
+
+		// get hold of decoder specific info
+		decoder_specific = ((BYTE*)wfx) + sizeof(WAVEFORMATEX);
+		decoder_specific_size = wfx->cbSize;
+
+		mpc_demux	*dmx;
+
+		int ret = OpenDemux(&dmx, &stream_info);
+		if (ret < 0) {
+			mpc_demux_exit(dmx);
+			return E_FAIL;
+		}
+
+		// if the stream_info says something different...
+		if (stream_info.sample_freq != wfx->nSamplesPerSec ||
+			stream_info.channels != wfx->nChannels
+			) {
+
+			// update values
+			wfOut.nChannels = stream_info.channels;
+			wfOut.nSamplesPerSec = stream_info.sample_freq;
+		}
+
 		wfOut.nBlockAlign = (wfOut.wBitsPerSample * wfOut.nChannels) >> 3;
 		wfOut.nAvgBytesPerSec = wfOut.nBlockAlign * wfOut.nSamplesPerSec;
 
+		// done with the demuxer
+		mpc_demux_exit(dmx);
 	}
 	return NOERROR;
@@ -133,4 +168,8 @@
 			m_pOutput->Disconnect();
 		}
+
+		// cancel out decoder specific info
+		decoder_specific = NULL;
+		decoder_specific_size = 0;
 	}
 	return __super::BreakConnect(dir);
@@ -195,4 +234,11 @@
 	HRESULT hr = __super::StartStreaming();
 	if (FAILED(hr)) return hr;
+
+	ASSERT(!demux);
+
+	// now let's open the demuxer
+	int ret = OpenDemux(&demux, &stream_info);
+	if (ret < 0) return E_FAIL;
+
 	return hr;
 }
@@ -202,15 +248,294 @@
 	HRESULT hr = __super::StopStreaming();
 	if (FAILED(hr)) return hr;
+
+	// done with demuxer
+	mpc_demux_exit(demux);
+	demux = NULL;
+
 	return hr;
 }
 
+#define FLOAT_CLIP(x)		(x < -1.0 ? -1.0 : x > 1.0 ? 1.0 : x)
+
+static void convert_float_to_int16_c(float *src, short *dst, int count)
+{
+	count -= 8;
+	while (count > 0) {
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		count -= 8;
+	}
+	count += 8;
+
+	// last few must be done one-by-one
+	while (count > 0) {
+		*dst++ = (short)(FLOAT_CLIP(*src) * 16380);	src++;
+		count --;
+	}
+}
+
 HRESULT CMPCDecoder::Receive(IMediaSample *pSample)
 {
 	if (!m_pOutput->IsConnected()) return NOERROR;
 
-	// todo:
-	return NOERROR;
-}
-
-
-
+	// we receive whole AP packets so just decode the frames :D
+	BYTE *pdata = NULL;
+	long lsize  = 0;
+	pSample->GetPointer(&pdata);
+	lsize = pSample->GetActualDataLength();
+
+	// set the reader
+	reader.SetData(pdata, lsize);
+	reader.AppendSE();
+
+	// manually clear the buffer for demuxer
+	demux->bytes_total = 0;
+	demux->bits_reader.buff = demux->buffer;
+	demux->bits_reader.count = 8;
+	demux->block_bits = 0;
+	demux->block_frames = 0;
+
+	// TODO: use some more clever way of doing this.
+	MPC_SAMPLE_FORMAT	samples[1152 * 8];
+	int					dec_samples;
+
+	// handling timestamps
+	REFERENCE_TIME		rtStart, rtStop;
+	__int64				current_sample = 0;
+	__int64				samples_to_skip = 0;
+	bool				has_timestamp = false;
+
+	if (pSample->GetTime(&rtStart, &rtStop) == NOERROR) {
+		has_timestamp = true;
+		// calculate relative sample_time
+		current_sample = (rtStart * stream_info.sample_freq) / 10000000;
+
+		if (current_sample < 0) {
+			samples_to_skip = -current_sample;
+		}
+	}
+
+	// now scan through the frames
+	while (true) {
+
+		//---------------------------------------------------------------------
+		//	Decoding Part
+		//---------------------------------------------------------------------
+
+		mpc_frame_info	frame;
+		mpc_status		err;
+
+		frame.buffer = (MPC_SAMPLE_FORMAT*)samples;
+
+		// decode one frame
+		err = mpc_demux_decode(demux, &frame);
+		if (err != MPC_STATUS_OK) break;
+		if (frame.bits == -1) break;				// done.
+
+		//---------------------------------------------------------------------
+		//	Skipping samples...
+		//---------------------------------------------------------------------
+
+		MPC_SAMPLE_FORMAT	*src_samples = frame.buffer;
+		int					decoded_time_samples = frame.samples;
+
+		if (has_timestamp) {
+			if (samples_to_skip > 0) {
+
+				// skip sample counters
+				__int64 to_skip = min(frame.samples, samples_to_skip);
+				decoded_time_samples -= to_skip;
+				current_sample	 	 += to_skip;
+				src_samples			 += (to_skip * stream_info.channels);
+			}
+		}
+
+		// if there's nothing left, continue
+		if (decoded_time_samples <= 0) continue;
+
+		// total number of decoded samples
+		dec_samples = decoded_time_samples * stream_info.channels;
+
+		//---------------------------------------------------------------------
+		//	Convert and deliver
+		//---------------------------------------------------------------------
+
+		// deliver decoded data
+		IMediaSample	*sample;
+		HRESULT			hr;
+		hr = GetDeliveryBuffer(&sample);
+		if (FAILED(hr)) break;				// perhaps allocator is decommited
+
+		BYTE *outp;
+		sample->GetPointer(&outp);
+
+		// this should definitely be true
+		ASSERT(sample->GetSize() >= (dec_samples * sizeof(short)));
+
+		// do format conversion
+#ifdef MPC_FIXED_POINT
+		// TODO: find ranges in headers somewhere
+#else
+		convert_float_to_int16_c((float*)src_samples, (short*)outp, dec_samples);
+		sample->SetActualDataLength(dec_samples * sizeof(short));
+#endif
+
+		// IMediaSample properties
+		if (has_timestamp) {
+			REFERENCE_TIME	tstart, tstop;
+			tstart = (current_sample * 10000000) / stream_info.sample_freq;
+			tstop  = ((current_sample+decoded_time_samples) * 10000000) / stream_info.sample_freq;
+			sample->SetTime(&tstart, &tstop);
+		}
+		sample->SetSyncPoint(TRUE);
+		sample->SetDiscontinuity(FALSE);
+
+		// advance time
+		current_sample += decoded_time_samples;
+
+		hr = m_pOutput->Deliver(sample);
+		sample->Release();
+
+		// something went wrong. stop decoding.
+		if (FAILED(hr)) break;
+	}
+
+	return NOERROR;
+}
+
+int CMPCDecoder::OpenDemux(mpc_demux **dmx, mpc_streaminfo *si)
+{
+	// some data needed
+	if (!decoder_specific || decoder_specific_size <= 0) return -1;
+
+	reader.SetData(decoder_specific, decoder_specific_size);
+	(*dmx) = mpc_demux_init(&reader.rd);
+	if (!(*dmx)) return -1;
+
+	mpc_demux_get_info((*dmx), si);
+	return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//	CMPCReader class
+//
+//-----------------------------------------------------------------------------
+
+static mpc_int32_t mpc_read_proc(mpc_reader *p_reader, void *ptr, mpc_int32_t size)
+{
+	CMPCReader *instance = (CMPCReader*)p_reader->data;
+	ASSERT(instance);
+	return instance->Read(ptr, size);
+}
+
+static mpc_bool_t mpc_seek_proc(mpc_reader *p_reader, mpc_int32_t offset)
+{
+	CMPCReader *instance = (CMPCReader*)p_reader->data;
+	ASSERT(instance);
+	return instance->Seek(offset);
+}
+
+static mpc_int32_t mpc_tell_proc(mpc_reader *p_reader)
+{
+	CMPCReader *instance = (CMPCReader*)p_reader->data;
+	ASSERT(instance);
+	return instance->Tell();
+}
+
+static mpc_int32_t mpc_get_size_proc(mpc_reader *p_reader)
+{
+	CMPCReader *instance = (CMPCReader*)p_reader->data;
+	ASSERT(instance);
+	return instance->GetSize();
+}
+
+static mpc_bool_t mpc_canseek_proc(mpc_reader *p_reader)
+{
+	CMPCReader *instance = (CMPCReader*)p_reader->data;
+	ASSERT(instance);
+	return instance->CanSeek();
+}
+
+CMPCReader::CMPCReader()
+{
+	buf = (BYTE*)malloc(256*1024);		// 256 KB should be enough
+	size = 0;
+
+	rd.data = (void*)this;
+	rd.read = mpc_read_proc;
+	rd.seek = mpc_seek_proc;
+	rd.tell = mpc_tell_proc;
+	rd.get_size = mpc_get_size_proc;
+	rd.canseek = mpc_canseek_proc;
+}
+
+CMPCReader::~CMPCReader()
+{
+	free(buf);
+}
+
+int CMPCReader::Read(void *buf, int size)
+{
+	// return the number of bytes read
+	int toread_max = min(this->size - this->pos, size);
+	memcpy(buf, this->buf + this->pos, toread_max);
+	this->pos += toread_max;
+	return toread_max;
+}
+
+bool CMPCReader::Seek(int offset)
+{
+	// sorry no seeking here
+	return false;
+}
+
+int CMPCReader::Tell()
+{
+	// that's where we are
+	return pos;
+}
+
+int CMPCReader::GetSize()
+{
+	// size of our supplied buffer
+	return size;
+}
+
+bool CMPCReader::CanSeek()
+{
+	// no. we are not seekable. upstream demuxer is.
+	return false;
+}
+
+void CMPCReader::SetData(BYTE *data, int size)
+{
+	ASSERT(size < 256*1024);
+	memcpy(buf, data, size);
+	this->size = size;
+	this->pos = 0;
+}
+
+void CMPCReader::AppendSE()
+{
+	BYTE *out = buf + size;
+	out[0] = 'S';
+	out[1] = 'E';
+	out[2] = 0x03;
+	size += 3;
+}
+
+
+
+
+
+
+
+
Index: /dsfilters/dec_mpc/src/mpc_filter.h
===================================================================
--- /dsfilters/dec_mpc/src/mpc_filter.h	(revision 370)
+++ /dsfilters/dec_mpc/src/mpc_filter.h	(revision 371)
@@ -11,4 +11,33 @@
 #define CMD_STOP		1
 #define CMD_RUN			2
+
+//-----------------------------------------------------------------------------
+//
+//	CMPCReader class
+//
+//-----------------------------------------------------------------------------
+class CMPCReader
+{
+public:
+	BYTE		*buf;		// out internal buffer
+	int			size;		// also the size
+	int			pos;		// position
+	mpc_reader	rd;			// this is the interface for libmpc
+
+public:
+	CMPCReader();
+	virtual ~CMPCReader();
+
+	// I/O methods
+	int Read(void *buf, int size);		// read data
+	bool Seek(int offset);				// seek to position
+	int Tell();							// tell current position
+	int GetSize();						// get total size
+	bool CanSeek();						// is seekable ?
+
+	// pass buffers to reader
+	void SetData(BYTE *data, int size);
+	void AppendSE();
+};
 
 
@@ -26,4 +55,15 @@
 	CCritSec			lock_filter;
 	WAVEFORMATEX		wfOut;
+
+	// comes in media type
+	CMediaType			mtIn;
+	BYTE				*decoder_specific;
+	int					decoder_specific_size;
+
+	// musepack internals
+	CMPCReader			reader;
+	mpc_streaminfo		stream_info;
+	mpc_bits_reader		bits;
+	mpc_demux			*demux;
 
 public:
@@ -54,8 +94,20 @@
 	// decoding input packets
 	virtual HRESULT Receive(IMediaSample *pSample);
-	//HRESULT DeliverSamples(int16 *input, int time_count);
 	virtual HRESULT GetDeliveryBuffer(IMediaSample **sample);
+
+	// Initialization from decoder_specific
+	int OpenDemux(mpc_demux **dmx, mpc_streaminfo *si);
 
 };
 
 
+
+
+
+
+
+
+
+
+
+
Index: /dsfilters/dec_mpc/src/stdafx.h
===================================================================
--- /dsfilters/dec_mpc/src/stdafx.h	(revision 370)
+++ /dsfilters/dec_mpc/src/stdafx.h	(revision 371)
@@ -53,4 +53,13 @@
 #include <dvdmedia.h>
 
+// These are from libmpc
+#include "mpc\mpc_types.h"
+#include "mpc\mpcdec.h"
+#include "mpc\reader.h"
+#include "mpc\streaminfo.h"
+#include "internal.h"
+
+
+
 //#include "bits.h"
 #include "mpc_types.h"
Index: /dsfilters/demux_mpc/demux_mpc.rc
===================================================================
--- /dsfilters/demux_mpc/demux_mpc.rc	(revision 370)
+++ /dsfilters/demux_mpc/demux_mpc.rc	(revision 371)
@@ -87,8 +87,8 @@
 FONT 8, "MS Shell Dlg", 0, 0, 0x0
 BEGIN
-    CTEXT           "This free software is released under the GNU GPL license.",IDC_STATIC,6,150,120,18
+    CTEXT           "This free software is released under the GNU LGPL license.",IDC_STATIC,6,150,120,18
     CTEXT           "http://www.musepack.net",IDC_STATIC,6,174,120,8
-    CTEXT           "DirectShow filter implemented by RadScorpion",IDC_STATIC,150,150,120,18
-    CTEXT           "http://blog.monogram.sk/janos",IDC_STATIC,150,174,120,8
+    CTEXT           "DirectShow filter implemented by Igor Janos",IDC_STATIC,156,150,114,18
+    CTEXT           "http://blog.monogram.sk/janos",IDC_STATIC,156,174,114,8
     CONTROL         "",IDC_LIST_CONTENT,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_TABSTOP,6,36,264,108,WS_EX_CLIENTEDGE
     CONTROL         101,IDC_STATIC,"Static",SS_BITMAP,0,0,280,30
Index: /dsfilters/demux_mpc/src/mpc_file.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_file.cpp	(revision 370)
+++ /dsfilters/demux_mpc/src/mpc_file.cpp	(revision 371)
@@ -57,4 +57,11 @@
 
 	done = false;
+
+	// init extradata
+	extradata[0] = 'M';
+	extradata[1] = 'P';
+	extradata[2] = 'C';
+	extradata[3] = 'K';
+	extradata_size = 4;
 
 	// now loop through a few packets
@@ -88,4 +95,11 @@
 	} while (!done);
 
+	// insert a dummy AP packet
+	uint8 *out = extradata + extradata_size;
+	out[0] = 'A';
+	out[1] = 'P';
+	out[2] = 0x03;
+	extradata_size += 3;
+
 	// if there was a seek table, load it
 	if (seek_table_position != 0) {
