Index: /dsfilters/before-you-ask.txt
===================================================================
--- /dsfilters/before-you-ask.txt	(revision 367)
+++ /dsfilters/before-you-ask.txt	(revision 368)
@@ -10,7 +10,10 @@
 
 Right now the only working filter is the demux_mpc.
-But it does not actually output data. Only analyzes input
-and displays information in property page.
-Internal delivery mechanism and buffering is already implemented.
+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/demux_mpc/src/bits.cpp
===================================================================
--- /dsfilters/demux_mpc/src/bits.cpp	(revision 367)
+++ /dsfilters/demux_mpc/src/bits.cpp	(revision 368)
@@ -115,14 +115,14 @@
 int32 Bitstream::Get_Golomb(int k)
 {
-	int32 len = 0;
-	NeedBits24();
-	while (UGetBits(1) == 1) len++;
-	if (len == 0) return 0;
-	NeedBits24();
-
-	//while (bits 
-
-	int32 val = (1 << len) | UGetBits(len);
-    return val;
+	int32 l=0;
+	NeedBits();
+	while (UBits(8) == 0) {
+		l += 8;
+		DumpBits(8);
+		NeedBits();	
+	}
+	while (UGetBits(1) == 0) l++;
+	NeedBits();
+	return (l << k) | UGetBits(k);
 }
 
Index: /dsfilters/demux_mpc/src/mpc_file.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_file.cpp	(revision 367)
+++ /dsfilters/demux_mpc/src/mpc_file.cpp	(revision 368)
@@ -19,26 +19,16 @@
 	duration_10mhz(0),
 	reader(NULL),
-	packet(NULL),
 	seek_table(NULL),
 	seek_table_position(0)
 {
-	key = 0;
-	packet_max_size = 512 * 1024;			// well. hard to say. but I think this should be enough
-	packet_size = 0;
-	packet = (uint8*)malloc(packet_max_size);
-
-	ASSERT(packet);
+	extradata_max_size = 16*1024;			// way too much..
+	extradata_size = 0;
+	extradata = (uint8*)malloc(extradata_max_size);
 }
 
 CMPCFile::~CMPCFile()
 {
-	if (seek_table) {
-		free(seek_table);
-		seek_table = NULL;
-	}
-	if (packet) {
-		free(packet);
-		packet = NULL;
-	}
+	if (seek_table) { free(seek_table); seek_table = NULL; }
+	if (extradata) { free(extradata); extradata = NULL; }
 }
 
@@ -52,5 +42,4 @@
 	// keep a local copy of the reader
 	this->reader = reader;
-
 
 	// According to stream specification the first 4 bytes should be 'MPCK'
@@ -70,12 +59,24 @@
 
 	// now loop through a few packets
+	CMPCPacket		packet;
 	do {
-		ret = ReadNextPacket();
+		ret = packet.Load(reader);
 		if (ret < 0) return -1;			// end of file reached before initialization is done ?
 
-		switch (key) {
-		case MPC_KEY('S','H'):	ret = ReadStreamHeader(); break;
-		case MPC_KEY('R','G'):  ret = ReadReplaygain(); break;
-		case MPC_KEY('S','O'):	ret = ReadSeekOffset(); break;
+		switch (packet.key) {
+		case MPC_KEY('S','H'):	
+			ret = ReadStreamHeader(&packet); 
+			StoreExtraDataPacket(&packet);
+			break;
+		case MPC_KEY('R','G'):  
+			ret = ReadReplaygain(&packet); 
+			StoreExtraDataPacket(&packet);
+			break;
+		case MPC_KEY('S','O'):	
+			ret = ReadSeekOffset(&packet); 
+			break;
+		case MPC_KEY('E','I'):
+			StoreExtraDataPacket(&packet);
+			break;
 
 		// audio packet - initialization is over
@@ -89,40 +90,33 @@
 	// if there was a seek table, load it
 	if (seek_table_position != 0) {
-		ret = ReadSeekTable(); 
+		int64 first_ap_pos, avail;
+		reader->GetPosition(&first_ap_pos, &avail);
+
+		reader->Seek(seek_table_position);
+		ret = packet.Load(reader);
+		ret = ReadSeekTable(&packet); 
 		if (ret < 0) return ret;
-	}
-
-	return 0;
-}
-
-int CMPCFile::ReadNextPacket()
-{
-	uint16	key_val;
-	int64	size_val;
-	int32	size_len;
-	int		ret;
-	int64	avail;
-
-	reader->GetPosition(&packet_pos, &avail);
-	ret = reader->GetKey(key_val);					if (ret < 0) return ret;
-	ret = reader->GetSizeElm(size_val, size_len);	if (ret < 0) return ret;
-
-	// if the key is not valid, quit
-	if (!reader->KeyValid(key_val)) return -1;
-	key = key_val;
-
-	// size_val is the total size including key, variable size field and payload
-	packet_size = size_val - 2 - size_len;
-	ASSERT(packet_size <= packet_max_size);
-
-	ret = reader->Read(packet, packet_size);		if (ret < 0) return ret;
-	return 0;
+
+		// seek back to first AP
+		reader->Seek(first_ap_pos);
+	}
+
+	// we're at start
+	current_sample = 0;
+	return 0;
+}
+
+void CMPCFile::StoreExtraDataPacket(CMPCPacket *packet)
+{
+	// we add current packet to extradata
+	uint8	*out = extradata + extradata_size;
+	memcpy(out, packet->packet, packet->packet_size);
+	extradata_size += packet->packet_size;
 }
 
 // parsing packets
-
-int CMPCFile::ReadReplaygain()
-{
-	Bitstream	b(packet);
+int CMPCFile::ReadReplaygain(CMPCPacket *packet)
+{
+	Bitstream	b(packet->payload);
 	b.NeedBits();
 
@@ -139,10 +133,10 @@
 }
 
-int CMPCFile::ReadSeekOffset()
-{
-	Bitstream	b(packet);
+int CMPCFile::ReadSeekOffset(CMPCPacket *packet)
+{
+	Bitstream	b(packet->payload);
 
 	seek_table_position = b.GetMpcSize();
-	seek_table_position += packet_pos;
+	seek_table_position += packet->file_position;
 
 	// success 
@@ -150,18 +144,12 @@
 }
 
-int CMPCFile::ReadSeekTable()
-{
-	reader->Seek(seek_table_position);
-	int ret;
-
-	ret = ReadNextPacket();
-	if (ret < 0) return ret;
-
-	Bitstream	b(packet);
+int CMPCFile::ReadSeekTable(CMPCPacket *packet)
+{
+	Bitstream	b(packet->payload);
 
 	// calculate size as seen in mpc_demux.c
 	int64 tmp = b.GetMpcSize();	b.NeedBits();
 	seek_table_size = tmp;
-	int	seek_pwr = block_pwr + b.UGetBits(4);
+	seek_pwr = block_pwr + b.UGetBits(4);
 	tmp = 2+total_samples / (1152 << seek_pwr);
 	if (tmp < seek_table_size) tmp = seek_table_size;
@@ -188,7 +176,7 @@
 }
 
-int CMPCFile::ReadStreamHeader()
-{
-	Bitstream	b(packet);
+int CMPCFile::ReadStreamHeader(CMPCPacket *packet)
+{
+	Bitstream	b(packet->payload);
 	b.NeedBits();
 
@@ -249,5 +237,5 @@
 
 			// store absolute position of stream header
-			header_position = packet_pos;
+			header_position = packet->file_position -4;
 		}
 		break;
@@ -261,3 +249,136 @@
 }
 
-
+// parsing out packets
+int CMPCFile::ReadAudioPacket(CMPCPacket *packet, int64 *cur_sample)
+{
+	// we just load packets until we face the SE packet. Then we return -1
+	int ret;
+
+	do {
+		ret = packet->Load(reader);
+		if (ret < 0) return ret;
+
+		switch (packet->key) {
+		case MPC_KEY('A','P'):	
+			{
+				// keep track of samples...
+				if (cur_sample) *cur_sample = current_sample;
+				current_sample += (1152*audio_block_frames);
+
+				return 0;			// we got one
+			}
+		case MPC_KEY('S','E'):	return -1;			// end of stream
+		}
+
+		// skip other packets
+	} while (1);
+
+	// unexpected...
+	return 0;
+}
+
+int CMPCFile::Seek(int64 seek_sample)
+{
+	/*
+		This will be a little tricky. I would like to support also 
+		less precise seeking with files that don't have seeking table. 
+		But if there is one, we	would use that one.
+
+		Original implementation also deals with introductory silence.
+		But since I don't know of any dshow filters capable of
+		gapless playback we would ignore this. Of course it can
+		be implemented later.
+
+		It is absolutely okay to do AP-level seeking. The caller
+		knows the exact time it wants to seek to and we will provide
+		the nearest AP. If the requested time is in the middle of AP,
+		the (current_time - requested_time) expression would be negative
+		and decoder will skip samples until positive time values are encountered.
+		This way we can do sample-precise seeking.
+	*/
+
+	// cannot seek
+	if (seek_table == NULL || seek_table_size == 0) return -1;
+
+	int packet_num = seek_sample / (1152*audio_block_frames);
+	int i = (packet_num >> (seek_pwr - block_pwr));
+	if (i >= seek_table_size) {
+		i = seek_table_size-1;
+	}
+
+	// seek to position
+	uint32 pos = seek_table[i] >> 3;
+	reader->Seek(pos);
+
+	// shift back
+	i = i << (seek_pwr - block_pwr);
+	current_sample = i*audio_block_frames;
+
+	return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+//	CMPCPacket
+//
+//-----------------------------------------------------------------------------
+
+CMPCPacket::CMPCPacket() :
+	file_position(0),
+	packet(NULL),
+	payload(NULL),
+	packet_size(0),
+	payload_size(0),
+	key(0)
+{
+}
+
+CMPCPacket::~CMPCPacket()
+{
+	// just let it go
+	Release();
+}
+
+void CMPCPacket::Release()
+{
+	if (packet) { free(packet); packet = NULL; }
+	payload = NULL;
+	packet_size = 0;
+	payload_size = 0;
+	key = 0;
+	file_position = 0;
+}
+
+int CMPCPacket::Load(CMPCReader *reader)
+{
+	uint16	key_val;
+	int64	size_val, avail;
+	int32	size_len;
+	int		ret;
+	Release();
+	reader->GetPosition(&file_position, &avail);
+
+	// end of stream
+	if (file_position >= avail) return -1;
+
+	ret = reader->GetKey(key_val);					if (ret < 0) return ret;
+	ret = reader->GetSizeElm(size_val, size_len);	if (ret < 0) return ret;
+	// if the key is not valid, quit
+	if (!reader->KeyValid(key_val)) return -1;
+	key = key_val;
+
+	// now load the packet
+	packet_size  = size_val;
+	payload_size = size_val - 2 - size_len;
+	packet = (uint8*)malloc(packet_size);
+	payload = packet + 2 + size_len;				// pointer to packet payload
+
+	// roll back the bytes
+	reader->Seek(file_position);
+	ret = reader->Read(packet, packet_size);		if (ret < 0) return ret;
+
+	return 0;
+}
+
+
Index: /dsfilters/demux_mpc/src/mpc_file.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_file.h	(revision 367)
+++ /dsfilters/demux_mpc/src/mpc_file.h	(revision 368)
@@ -9,4 +9,33 @@
 
 class CMPCReader;
+
+//-----------------------------------------------------------------------------
+//
+//	CMPCPacket
+//
+//-----------------------------------------------------------------------------
+
+class CMPCPacket
+{
+public:
+	int64		file_position;				// absolute file position
+
+	uint8		*packet;					// we own this one
+	uint8		*payload;					// just a pointer
+	int32		packet_size;				// whole packet size
+	int32		payload_size;				// only the payload
+
+	uint16		key;						// parsed key value
+
+	REFERENCE_TIME	tStart, tStop;			// to be used later
+
+public:
+	CMPCPacket();
+	virtual ~CMPCPacket();
+
+	// loading packets
+	int Load(CMPCReader *reader);
+	void Release();
+};
 
 
@@ -29,5 +58,4 @@
 	int				block_pwr;				
 	int				seek_pwr;
-	int64			total_samples;
 
 	// replay gain
@@ -43,13 +71,15 @@
 	int64			seek_table_size;
 
+	// current position
+	int64			total_samples;
+	int64			current_sample;
+
 	// internals
 	CMPCReader		*reader;				// file reader interface
 
-	// packet parsing
-	int				key;					// key for current packet
-	uint8			*packet;				// packet payload
-	int				packet_max_size;		// maximum allowed packet size
-	int				packet_size;			// size of currently loaded payload
-	int64			packet_pos;				// absolute position in file
+	// buffer for decoder specific info
+	uint8			*extradata;
+	int				extradata_max_size;		// total size
+	int				extradata_size;			// current size of extradata
 	
 public:
@@ -59,11 +89,15 @@
 	// I/O for MPC file
 	int Open(CMPCReader *reader);
-	int ReadNextPacket();
 
 	// parsing packets
-	int ReadStreamHeader();
-	int ReadReplaygain();
-	int ReadSeekOffset();
-	int ReadSeekTable();
+	int ReadStreamHeader(CMPCPacket *packet);
+	int ReadReplaygain(CMPCPacket *packet);
+	int ReadSeekOffset(CMPCPacket *packet);
+	int ReadSeekTable(CMPCPacket *packet);
+	void StoreExtraDataPacket(CMPCPacket *packet);
+
+	// parsing out packets
+	int ReadAudioPacket(CMPCPacket *packet, int64 *cur_sample);
+	int Seek(int64 seek_sample);
 
 };
Index: /dsfilters/demux_mpc/src/mpc_filter.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_filter.cpp	(revision 367)
+++ /dsfilters/demux_mpc/src/mpc_filter.cpp	(revision 368)
@@ -47,11 +47,18 @@
 CMPCDemux::CMPCDemux(LPUNKNOWN pUnk, HRESULT *phr) :
 	CBaseFilter(_T("MPC Splitter"), pUnk, &lock_filter, CLSID_MusepackDemuxer, phr),
+	CAMThread(),
 	reader(NULL),
 	file(NULL),
-	wnd_prop(NULL)
+	wnd_prop(NULL),
+	rtCurrent(0),
+	rtStop(0xFFFFFFFFFFFFFF),
+	rate(1.0),
+	ev_abort(TRUE)
 {
 	input = new CMPCInputPin(NAME("MPC Input Pin"), this, phr, L"In");
 	output.RemoveAll();
 	retired.RemoveAll();
+
+	ev_abort.Reset();
 }
 
@@ -82,11 +89,8 @@
 	if (riid == IID_IMusepackSplitter) {
 		return GetInterface((IMusepackSplitter*)this, ppv);
-	} else{
-	/*
+	} else
     if (riid == IID_IMediaSeeking) {
-        return GetInterface((IMediaSeeking *)this, ppv);
-    } else 
-	*/
-
+        return GetInterface((IMediaSeeking*)this, ppv);
+	} else {
 		return CBaseFilter::NonDelegatingQueryInterface(riid,ppv);
 	}
@@ -185,4 +189,9 @@
 		}
 
+		HRESULT			hr = NOERROR;
+		CMPCOutputPin	*opin = new CMPCOutputPin(_T("Outpin"), this, &hr, L"Out", 5);
+		ConfigureMediaType(opin);
+		AddOutputPin(opin);
+
 		// refresh property page if there is any
 		if (IsWindow(wnd_prop)) {
@@ -215,4 +224,35 @@
 
 
+HRESULT CMPCDemux::ConfigureMediaType(CMPCOutputPin *pin)
+{
+	CMediaType		mt;
+	mt.majortype = MEDIATYPE_Audio;
+	mt.subtype = MEDIASUBTYPE_MusepackPacket;
+	mt.formattype = FORMAT_WaveFormatEx;
+	mt.lSampleSize = 128*1024;				// should be way enough
+
+	ASSERT(file);
+	int		extrasize = file->extradata_size;
+
+	// let us fill the waveformatex structure
+	WAVEFORMATEX *wfx = (WAVEFORMATEX*)mt.AllocFormatBuffer(sizeof(WAVEFORMATEX) + extrasize);
+	memset(wfx, 0, sizeof(*wfx));
+	wfx->cbSize = extrasize;
+	wfx->wBitsPerSample = 0;
+	wfx->nChannels = file->channels;
+	wfx->nSamplesPerSec = file->sample_rate;
+	wfx->nBlockAlign = 1;
+	wfx->nAvgBytesPerSec = 0;
+	wfx->wFormatTag = 0;
+
+	// Extradata - Stream header + other stuff
+	uint8	*extra = ((uint8*)wfx) + sizeof(WAVEFORMATEX);
+	memcpy(extra, file->extradata, extrasize);
+
+	// the one and only type
+	pin->mt_types.Add(mt);
+	return NOERROR;
+}
+
 HRESULT CMPCDemux::BreakConnect(PIN_DIRECTION Dir, CBasePin *pCaller)
 {
@@ -221,5 +261,5 @@
 	if (Dir == PINDIR_INPUT) {
 		// let's disconnect the output pins
-		//ev_abort.Set();
+		ev_abort.Set();
 		//ev_ready.Set();
 
@@ -238,5 +278,5 @@
 		}
 
-		//ev_abort.Reset();
+		ev_abort.Reset();
 	} else 
 	if (Dir == PINDIR_OUTPUT) {
@@ -271,5 +311,291 @@
 }
 
-
-
-
+DWORD CMPCDemux::ThreadProc()
+{
+	DWORD	cmd, cmd2;
+	while (true) {
+		cmd = GetRequest();
+		switch (cmd) {
+		case CMD_EXIT:	Reply(NOERROR); return 0;
+		case CMD_STOP:	Reply(NOERROR); break;
+		case CMD_RUN:
+			{
+				Reply(NOERROR);
+				if (!file) break;
+
+				CMPCPacket		packet;
+				int32			ret=0;
+				bool			eos=false;
+				HRESULT			hr;
+				int64			current_sample;
+
+				/*
+					With a more complex demultiplexer we would need a mechanism
+					to identify streams. Now we have only one output stream
+					so it's easy.
+				*/
+
+				if (output.GetCount() <= 0) break;
+				if (output[0]->IsConnected() == FALSE) break;
+
+				do {
+
+					// are we supposed to abort ?
+					if (ev_abort.Check()) { 
+						ret = 0; 
+						break; 
+					}
+
+					ret = file->ReadAudioPacket(&packet, &current_sample);
+					if (ret < 0) {
+						// end of stream
+						break;
+					} else {
+						// compute time stamp
+						REFERENCE_TIME	tStart = (current_sample * 10000000) / file->sample_rate;
+						REFERENCE_TIME	tStop  = ((current_sample + 1152*file->audio_block_frames) * 10000000) / file->sample_rate;
+						packet.tStart = tStart;
+						packet.tStop  = tStop;
+
+						// deliver packet
+						output[0]->DeliverPacket(packet);
+					}
+
+				} while (!CheckRequest(&cmd2));
+
+				// end of stream
+				if (ret == -1) {
+					output[0]->DoEndOfStream();
+				}
+
+			}
+			break;
+		default:
+			Reply(E_UNEXPECTED);
+			break;
+		}
+	}
+	return 0;
+}
+
+
+// IMediaSeeking
+
+STDMETHODIMP CMPCDemux::GetCapabilities(DWORD* pCapabilities)
+{
+	return pCapabilities ? *pCapabilities =	
+			AM_SEEKING_CanGetStopPos|AM_SEEKING_CanGetDuration|AM_SEEKING_CanSeekAbsolute|AM_SEEKING_CanSeekForwards|AM_SEEKING_CanSeekBackwards, 
+			S_OK : E_POINTER;
+}
+STDMETHODIMP CMPCDemux::CheckCapabilities(DWORD* pCapabilities)
+{
+	CheckPointer(pCapabilities, E_POINTER);
+	if (*pCapabilities == 0) return S_OK;
+	DWORD caps;
+	GetCapabilities(&caps);
+	if ((caps&*pCapabilities) == 0) return E_FAIL;
+	if (caps == *pCapabilities) return S_OK;
+	return S_FALSE;
+}
+STDMETHODIMP CMPCDemux::IsFormatSupported(const GUID* pFormat) {return !pFormat ? E_POINTER : *pFormat == TIME_FORMAT_MEDIA_TIME ? S_OK : S_FALSE;}
+STDMETHODIMP CMPCDemux::QueryPreferredFormat(GUID* pFormat) {return GetTimeFormat(pFormat);}
+STDMETHODIMP CMPCDemux::GetTimeFormat(GUID* pFormat) {return pFormat ? *pFormat = TIME_FORMAT_MEDIA_TIME, S_OK : E_POINTER;}
+STDMETHODIMP CMPCDemux::IsUsingTimeFormat(const GUID* pFormat) {return IsFormatSupported(pFormat);}
+STDMETHODIMP CMPCDemux::SetTimeFormat(const GUID* pFormat) {return S_OK == IsFormatSupported(pFormat) ? S_OK : E_INVALIDARG;}
+STDMETHODIMP CMPCDemux::GetStopPosition(LONGLONG* pStop) {return this->rtStop; }
+STDMETHODIMP CMPCDemux::GetCurrentPosition(LONGLONG* pCurrent) {return E_NOTIMPL;}
+STDMETHODIMP CMPCDemux::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat) {return E_NOTIMPL;}
+
+STDMETHODIMP CMPCDemux::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
+{
+	return SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
+}
+
+STDMETHODIMP CMPCDemux::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop)
+{
+	if(pCurrent) *pCurrent = rtCurrent;
+	if(pStop) *pStop = rtStop;
+	return S_OK;
+}
+STDMETHODIMP CMPCDemux::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest)
+{
+	if(pEarliest) *pEarliest = 0;
+	return GetDuration(pLatest);
+}
+STDMETHODIMP CMPCDemux::SetRate(double dRate) {return dRate > 0 ? rate = dRate, S_OK : E_INVALIDARG;}
+STDMETHODIMP CMPCDemux::GetRate(double* pdRate) {return pdRate ? *pdRate = rate, S_OK : E_POINTER;}
+STDMETHODIMP CMPCDemux::GetPreroll(LONGLONG* pllPreroll) {return pllPreroll ? *pllPreroll = 0, S_OK : E_POINTER;}
+
+STDMETHODIMP CMPCDemux::GetDuration(LONGLONG* pDuration) 
+{	
+	CheckPointer(pDuration, E_POINTER); 
+	*pDuration = 0;
+
+	if (file) {
+		if (pDuration) *pDuration = file->duration_10mhz;
+	}
+	return S_OK;
+}
+
+STDMETHODIMP CMPCDemux::SetPositionsInternal(int iD, LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
+{
+	// only our first pin can seek
+	if (iD != 0) return NOERROR;
+	CAutoLock cAutoLock(&lock_filter);
+
+	if (!pCurrent && !pStop || (dwCurrentFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning 
+		&& (dwStopFlags&AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning)
+		return S_OK;
+
+	REFERENCE_TIME rtCurrent = this->rtCurrent, rtStop = this->rtStop;
+
+	if (pCurrent) {
+		switch(dwCurrentFlags&AM_SEEKING_PositioningBitsMask) {
+		case AM_SEEKING_NoPositioning: break;
+		case AM_SEEKING_AbsolutePositioning: rtCurrent = *pCurrent; break;
+		case AM_SEEKING_RelativePositioning: rtCurrent = rtCurrent + *pCurrent; break;
+		case AM_SEEKING_IncrementalPositioning: rtCurrent = rtCurrent + *pCurrent; break;
+		}
+	}
+
+	if (pStop) {
+		switch(dwStopFlags&AM_SEEKING_PositioningBitsMask) {
+		case AM_SEEKING_NoPositioning: break;
+		case AM_SEEKING_AbsolutePositioning: rtStop = *pStop; break;
+		case AM_SEEKING_RelativePositioning: rtStop += *pStop; break;
+		case AM_SEEKING_IncrementalPositioning: rtStop = rtCurrent + *pStop; break;
+		}
+	}
+
+	if (this->rtCurrent == rtCurrent && this->rtStop == rtStop) return S_OK;
+
+	this->rtCurrent = rtCurrent;
+	this->rtStop = rtStop;
+
+	// now there are new valid Current and Stop positions
+	HRESULT hr = DoNewSeek();
+	return hr;
+}
+
+HRESULT CMPCDemux::DoNewSeek()
+{
+	// stop first
+	ev_abort.Set();
+	if (reader) reader->BeginFlush();
+
+	for (int i=0; i<output.GetCount(); i++) {
+		CMPCOutputPin	*pin = output[i];
+		if (pin->IsConnected()) {
+			// abort
+			if (m_State != State_Stopped) {
+				if (pin->ThreadExists()) {
+					pin->ev_abort.Set();
+					pin->DeliverBeginFlush();
+					pin->CallWorker(CMD_STOP);
+					pin->FlushQueue();
+				}
+			}
+		}
+	}
+
+	for (int i=0; i<output.GetCount(); i++) {
+		CMPCOutputPin	*pin = output[i];
+		if (pin->IsConnected()) {
+			if (m_State != State_Stopped) {
+				if (pin->ThreadExists()) {
+					pin->ev_abort.Reset();
+					pin->DeliverEndFlush();
+				}
+			}
+			pin->DoNewSegment(rtCurrent, rtStop, rate);
+		}
+	}
+
+	if (ThreadExists()) {
+		CallWorker(CMD_STOP);
+	}
+	if (reader) reader->EndFlush();
+
+	// seek the file
+	if (file) {
+		int64 sample_pos = rtCurrent * file->sample_rate / 10000000;
+		file->Seek(sample_pos);
+	}
+
+	ev_abort.Reset();
+	if (ThreadExists()) {
+		CallWorker(CMD_RUN);
+	}
+
+	for (int i=0; i<output.GetCount(); i++) {
+		CMPCOutputPin	*pin = output[i];
+
+		// we only care about connected pins
+		if (pin->IsConnected()) {
+			if (m_State != State_Stopped) {
+				// spustime aj jeho thread
+				if (pin->ThreadExists()) {
+					pin->CallWorker(CMD_RUN);
+				}
+			}
+		}
+	}
+
+	return NOERROR;
+}
+
+
+STDMETHODIMP CMPCDemux::Pause()
+{
+	CAutoLock	lck(&lock_filter);
+
+	if (m_State == State_Stopped) {
+
+		ev_abort.Reset();
+
+		// activate pins
+		for (int i=0; i<output.GetCount(); i++) output[i]->Active();
+		if (input) input->Active();
+
+		// seekneme na danu poziciu
+		DoNewSeek();
+
+		// pustime parser thread
+		if (!ThreadExists()) {
+			Create();
+			CallWorker(CMD_RUN);
+		}
+	}
+
+	m_State = State_Paused;
+	return NOERROR;
+}
+
+STDMETHODIMP CMPCDemux::Stop()
+{
+	CAutoLock	lock(&lock_filter);
+	HRESULT		hr = NOERROR;
+
+	if (m_State != State_Stopped) {
+
+		// set abort
+		ev_abort.Set();
+		if (reader) reader->BeginFlush();
+
+		// deaktivujeme piny
+		if (input) input->Inactive();
+		for (int i=0; i<output.GetCount(); i++) output[i]->Inactive();
+
+		// zrusime parser thread
+		if (ThreadExists()) {
+			CallWorker(CMD_EXIT);
+			Close();
+		}
+
+		if (reader) reader->EndFlush();
+	}
+
+
+	m_State = State_Stopped;
+	return hr;
+}
Index: /dsfilters/demux_mpc/src/mpc_filter.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_filter.h	(revision 367)
+++ /dsfilters/demux_mpc/src/mpc_filter.h	(revision 368)
@@ -20,6 +20,8 @@
 class CMPCDemux : 
 	public CBaseFilter,
-	public ISpecifyPropertyPages ,
-	public IMusepackSplitter
+	public CAMThread,
+	public ISpecifyPropertyPages,
+	public IMusepackSplitter,
+	public IMediaSeeking
 {
 public:
@@ -32,4 +34,12 @@
 	CMPCFile					*file;
 	HWND						wnd_prop;
+
+	CAMEvent					ev_abort;
+
+	// times
+	REFERENCE_TIME				rtCurrent;
+	REFERENCE_TIME				rtStop;
+	double						rate;
+
 
 public:
@@ -60,5 +70,8 @@
 	virtual HRESULT BreakConnect(PIN_DIRECTION Dir, CBasePin *pCaller);
 	virtual HRESULT CompleteConnect(PIN_DIRECTION Dir, CBasePin *pCaller, IPin *pReceivePin);
+	virtual HRESULT ConfigureMediaType(CMPCOutputPin *pin);
 
+	// Demuxing thread
+	virtual DWORD ThreadProc();
 
 	// IMusepackSplitter
@@ -66,7 +79,9 @@
 	STDMETHODIMP SetPropertyPageWindow(HWND wnd);
 
+	// activate / deactivate filter
+	STDMETHODIMP Pause();
+	STDMETHODIMP Stop();
 
 	// IMediaSeeking
-	/*
 	STDMETHODIMP GetCapabilities(DWORD* pCapabilities);
 	STDMETHODIMP CheckCapabilities(DWORD* pCapabilities);
@@ -86,8 +101,8 @@
 	STDMETHODIMP GetRate(double* pdRate);
 	STDMETHODIMP GetPreroll(LONGLONG* pllPreroll);
+
 	STDMETHODIMP SetPositionsInternal(int iD, LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags);
 
-	// virtual HRESULT DoNewSeek();
-	*/
+	virtual HRESULT DoNewSeek();
 
 };
Index: /dsfilters/demux_mpc/src/mpc_pin.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_pin.cpp	(revision 367)
+++ /dsfilters/demux_mpc/src/mpc_pin.cpp	(revision 368)
@@ -131,4 +131,7 @@
 	ev_can_write.Set();
 	ev_abort.Reset();
+
+	// up to 5 seconds
+	buffer_time_ms = 5000;
 }
 
@@ -141,11 +144,9 @@
 {
 	CheckPointer(ppv, E_POINTER);
-	/*
 	if (riid == IID_IMediaSeeking) {
 		return GetInterface((IMediaSeeking*)this, ppv);
 	} else {
-	*/
 		return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
-	//}
+	}
 }
 
@@ -292,5 +293,4 @@
 }
 
-/*
 // IMediaSeeking
 STDMETHODIMP CMPCOutputPin::GetCapabilities(DWORD* pCapabilities)					{ return demux->GetCapabilities(pCapabilities); }
@@ -315,7 +315,6 @@
 STDMETHODIMP CMPCOutputPin::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
 {
-	return demux->SetPositionsInternal(stream_index, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
-}
-*/
+	return demux->SetPositionsInternal(0, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
+}
 
 int CMPCOutputPin::GetDataPacket(DataPacket **packet)
@@ -342,7 +341,5 @@
 }
 
-/*
-// dorucenie packetu
-HRESULT CMPCOutputPin::DeliverPacket(MP4::Packet &packet)
+HRESULT CMPCOutputPin::DeliverPacket(CMPCPacket &packet)
 {
 	// ziskame novy packet na vystup
@@ -356,17 +353,13 @@
 
 	// spocitame casy
-	outp->rtStart = (packet.pts_100mhz / 10) - rtStart;
-	outp->rtStop  = outp->rtStart + 1;
+	outp->rtStart = packet.tStart;
+	outp->rtStop  = packet.tStop;
 	
-	outp->size	  = packet.size;
+	outp->size	  = packet.packet_size;
 	outp->buf	  = (BYTE*)malloc(outp->size);
-	memcpy(outp->buf, packet.data, packet.size);
-
-	// sync point ?
-	if (packet.flags & PACKET_FLAG_KEYFRAME) {
-		outp->sync_point = TRUE;
-	} else {
-		outp->sync_point = FALSE;
-	}
+	memcpy(outp->buf, packet.packet, packet.packet_size);
+
+	// each packet is sync point
+	outp->sync_point = TRUE;
 
 	// discontinuity ?
@@ -379,15 +372,12 @@
 
 	{
-		// strcime do queue
-		MonoBase::AutoLock		lck(&lock_queue);
+		// insert into queue
+		CAutoLock		lck(&lock_queue);
 		queue.AddTail(outp);
 		ev_can_read.Set();
 
-		// zakazeme dalsie bufferovanie
-		// toto mozeme robit iba pre seekovaci pin
-		if (stream_index == demux->buf_index) {
-			if (GetBufferTime_MS() >= buffer_time_ms) {
-				ev_can_write.Reset();
-			}
+		// we allow buffering for a few seconds (might be usefull for network playback)
+		if (GetBufferTime_MS() >= buffer_time_ms) {
+			ev_can_write.Reset();
 		}
 	}
@@ -395,5 +385,4 @@
 	return NOERROR;
 }
-*/
 
 HRESULT CMPCOutputPin::DoEndOfStream()
@@ -441,5 +430,6 @@
 
 	// we should have enough space in there
-	ASSERT(sample->GetSize() >= packet.size);
+	long lsize = sample->GetSize();
+	ASSERT(lsize >= packet.size);
 
 	BYTE			*buf;
Index: /dsfilters/demux_mpc/src/mpc_pin.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_pin.h	(revision 367)
+++ /dsfilters/demux_mpc/src/mpc_pin.h	(revision 368)
@@ -89,5 +89,5 @@
 class CMPCOutputPin : 
 	public CBaseOutputPin, 
-//	public IMediaSeeking, 
+	public IMediaSeeking, 
 	public CAMThread
 {
@@ -140,5 +140,5 @@
 
 	// packet delivery mechanism
-	//HRESULT DeliverPacket(MP4::Packet &packet);
+	HRESULT DeliverPacket(CMPCPacket &packet);
 	HRESULT DeliverDataPacket(DataPacket &packet);
 	HRESULT DoEndOfStream();
@@ -149,5 +149,4 @@
 	int GetDataPacket(DataPacket **packet);
 
-	/*
 	// IMediaSeeking
 	STDMETHODIMP GetCapabilities(DWORD* pCapabilities);
@@ -168,5 +167,4 @@
 	STDMETHODIMP GetRate(double* pdRate);
 	STDMETHODIMP GetPreroll(LONGLONG* pllPreroll);
-	*/
 
 public:
