Index: /dsfilters/before-you-ask.txt
===================================================================
--- /dsfilters/before-you-ask.txt (revision 366)
+++ /dsfilters/before-you-ask.txt (revision 366)
@@ -0,0 +1,18 @@
+This package is developed with Visual Studio 2005.
+If you get an error like
+
+"Application cannot start"
+
+or similar, go to microsoft.com
+and download Visual C++ 2005 SP1 Redistributable Package.
+It's about 2.6 MB large and contains required DLLs.
+In time I'll try to get a VC++ 2003 and build.
+
+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.
+
+stay tuned.
+
+Igor.
Index: /dsfilters/demux_mpc/demux_mpc.def
===================================================================
--- /dsfilters/demux_mpc/demux_mpc.def (revision 366)
+++ /dsfilters/demux_mpc/demux_mpc.def (revision 366)
@@ -0,0 +1,6 @@
+LIBRARY mmmpcdmx.ax
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE
Index: /dsfilters/demux_mpc/demux_mpc.rc
===================================================================
--- /dsfilters/demux_mpc/demux_mpc.rc (revision 366)
+++ /dsfilters/demux_mpc/demux_mpc.rc (revision 366)
@@ -0,0 +1,130 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Slovak resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SKY)
+#ifdef _WIN32
+LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT
+#pragma code_page(1250)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Bitmap
+//
+
+IDB_BMP_LOGO BITMAP "bitmap_logo.bmp"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_PAGE_DEMUX "Musepack File"
+END
+
+#endif // Slovak resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_PAGE_DEMUX DIALOGEX 0, 0, 280, 194
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD
+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 "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
+ 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
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_PAGE_DEMUX, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 273
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 187
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
Index: /dsfilters/demux_mpc/demux_mpc.sln
===================================================================
--- /dsfilters/demux_mpc/demux_mpc.sln (revision 366)
+++ /dsfilters/demux_mpc/demux_mpc.sln (revision 366)
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "demux_mpc", "demux_mpc.vcproj", "{17662646-020C-4374-AB81-BA2434AD8260}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {17662646-020C-4374-AB81-BA2434AD8260}.Debug|Win32.ActiveCfg = Debug|Win32
+ {17662646-020C-4374-AB81-BA2434AD8260}.Debug|Win32.Build.0 = Debug|Win32
+ {17662646-020C-4374-AB81-BA2434AD8260}.Release|Win32.ActiveCfg = Release|Win32
+ {17662646-020C-4374-AB81-BA2434AD8260}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
Index: /dsfilters/demux_mpc/demux_mpc.vcproj
===================================================================
--- /dsfilters/demux_mpc/demux_mpc.vcproj (revision 366)
+++ /dsfilters/demux_mpc/demux_mpc.vcproj (revision 366)
@@ -0,0 +1,269 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: /dsfilters/demux_mpc/resource.h
===================================================================
--- /dsfilters/demux_mpc/resource.h (revision 366)
+++ /dsfilters/demux_mpc/resource.h (revision 366)
@@ -0,0 +1,19 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by demux_mpc.rc
+//
+#define IDB_BMP_LOGO 101
+#define IDS_PAGE_DEMUX 102
+#define IDD_PAGE_DEMUX 105
+#define IDC_LIST_CONTENT 1001
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 103
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1002
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
Index: /dsfilters/demux_mpc/src/bits.cpp
===================================================================
--- /dsfilters/demux_mpc/src/bits.cpp (revision 366)
+++ /dsfilters/demux_mpc/src/bits.cpp (revision 366)
@@ -0,0 +1,114 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#include "stdafx.h"
+
+//-----------------------------------------------------------------------------
+//
+// Bitstream class
+//
+// podporuje citanie bitstreamu
+//
+//----------------------------------------------------------------------------
+
+const int32 Bitstream::EXP_GOLOMB_MAP[2][48] =
+{
+ {
+ 47, 31, 15, 0, 23, 27, 29, 30,
+ 7, 11, 13, 14, 39, 43, 45, 46,
+ 16, 3, 5, 10, 12, 19, 21, 26,
+ 28, 35, 37, 42, 44, 1, 2, 4,
+ 8, 17, 18, 20, 24, 6, 9, 22,
+ 25, 32, 33, 34, 36, 40, 38, 41
+ },
+ {
+ 0, 16, 1, 2, 4, 8, 32, 3,
+ 5, 10, 12, 15, 47, 7, 11, 13,
+ 14, 6, 9, 31, 35, 37, 42, 44,
+ 33, 34, 36, 40, 39, 43, 45, 46,
+ 17, 18, 20, 24, 19, 21, 26, 28,
+ 23, 27, 29, 30, 22, 25, 38, 41
+ }
+};
+
+const int32 Bitstream::EXP_GOLOMB_MAP_INV[2][48] =
+{
+ {
+ 3, 29, 30, 17, 31, 18, 37, 8,
+ 32, 38, 19, 9, 20, 10, 11, 2,
+ 16, 33, 34, 21, 35, 22, 39, 4,
+ 36, 40, 23, 5, 24, 6, 7, 1,
+ 41, 42, 43, 25, 44, 26, 46, 12,
+ 45, 47, 27, 13, 28, 14, 15, 0
+ },
+ {
+ 0, 2, 3, 7, 4, 8, 17, 13,
+ 5, 18, 9, 14, 10, 15, 16, 11,
+ 1, 32, 33, 36, 34, 37, 44, 40,
+ 35, 45, 38, 41, 39, 42, 43, 19,
+ 6, 24, 25, 20, 26, 21, 46, 28,
+ 27, 47, 22, 29, 23, 30, 31, 12
+ }
+};
+
+
+// Exp-Golomb Codes
+
+const int32 Bitstream::EXP_GOLOMB_SIZE[255] =
+{
+ 1, 3, 3, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15
+};
+
+uint32 Bitstream::Get_UE()
+{
+ int32 len = 0;
+ NeedBits24();
+ while (!UGetBits(1)) len++;
+ NeedBits24();
+ return (len == 0 ? 0 : (1<>1) : (val>>1);
+}
+
+int32 Bitstream::Get_ME(int32 mode)
+{
+ // nacitame UE a potom podla mapovacej tabulky
+ int32 codeNum = Get_UE();
+ if (codeNum >= 48) return -1; // chyba
+ return EXP_GOLOMB_MAP[mode][codeNum];
+}
+
+int32 Bitstream::Get_TE(int32 range)
+{
+ /* ISO/IEC 14496-10 - Section 9.1 */
+ if (range > 1) {
+ return Get_UE();
+ } else {
+ return (!UGetBits(1))&0x01;
+ }
+}
+
Index: /dsfilters/demux_mpc/src/bits.h
===================================================================
--- /dsfilters/demux_mpc/src/bits.h (revision 366)
+++ /dsfilters/demux_mpc/src/bits.h (revision 366)
@@ -0,0 +1,106 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+// well.. I just like those
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+typedef unsigned __int64 uint64;
+typedef signed char int8;
+typedef signed short int16;
+typedef signed int int32;
+typedef signed __int64 int64;
+
+//-------------------------------------------------------------------------
+//
+// Bitstream class
+//
+//-------------------------------------------------------------------------
+
+class Bitstream
+{
+public:
+ uint32 bitbuf; // bitbuffer
+ uint8 *buf; // byte buffer
+ int32 bits; // pocet bitov v bitbufferi
+
+public:
+ static const int32 EXP_GOLOMB_MAP[2][48];
+ static const int32 EXP_GOLOMB_MAP_INV[2][48];
+ static const int32 EXP_GOLOMB_SIZE[255];
+
+public:
+
+ // Konstruktory
+ Bitstream() : bitbuf(0), buf(NULL), bits(0) { };
+ Bitstream(uint8 *b) : bitbuf(0), buf(b), bits(0) { };
+ Bitstream(const Bitstream &b) : bitbuf(b.bitbuf), buf(b.buf), bits(b.bits) { };
+
+ // Operator priradenia = kopia stavu bitstreamu
+ Bitstream &operator =(const Bitstream &b) { bitbuf = b.bitbuf; buf = b.buf; bits = b.bits; return *this; };
+ Bitstream &operator =(const uint8 *b) { bitbuf = 0; buf = (uint8*)b; bits = 0; return *this; };
+ Bitstream &operator =(uint8 *b) { bitbuf = 0; buf = b; bits = 0; return *this; };
+
+ // Resetovanie stavu
+ inline void Init(const uint8 *b) { bitbuf = 0; buf = (uint8*)b; bits = 0; };
+ inline void Init(uint8 *b) { bitbuf = 0; buf = b; bits = 0; };
+
+ // Zistenie stavu bitstreamu
+ inline int32 BitsLeft() { return bits; };
+ inline uint32 BitBuf() { return bitbuf; };
+ inline uint8 *Position() { return buf - (bits/8); };
+
+ // Citanie z bitstreamu
+ inline void DumpBits(int32 n) { bitbuf <<= n; bits -= n; };
+ inline uint32 UBits(int32 n) { return (uint32)(bitbuf >> (32-n)); };
+ inline uint32 UGetBits(int32 n) { uint32 val = (uint32)(bitbuf >> (32-n)); bitbuf <<= n; bits -= n; return val; };
+ inline int32 SBits(int32 n) { return (int32)(bitbuf >> (32-n)); };
+ inline int32 SGetBits(int32 n) { int32 val = (int32)(bitbuf >> (32-n)); bitbuf <<= n; bits -= n; return val; };
+ inline void Markerbit() { DumpBits(1); }
+
+ // Reading variable length size field
+ inline int64 GetMpcSize() {
+ int64 ret=0;
+ uint8 tmp;
+ do {
+ NeedBits();
+ tmp = UGetBits(8);
+ ret = (ret<<7) | (tmp&0x7f);
+ } while (tmp&0x80);
+ return ret;
+ }
+
+ // Zarovnavanie na byty
+ inline int32 IsByteAligned() { return !(bits&0x07); };
+ inline void ByteAlign() { if (bits&0x07) DumpBits(bits&0x07); };
+
+ // Exp-Golomb Codes
+ uint32 Get_UE();
+ int32 Get_SE();
+ int32 Get_ME(int32 mode);
+ int32 Get_TE(int32 range);
+
+ inline int32 Size_UE(uint32 val)
+ {
+ if (val<255) return EXP_GOLOMB_SIZE[val];
+ int32 isize=0;
+ val++;
+ if (val >= 0x10000) { isize+= 32; val = (val >> 16)-1; }
+ if (val >= 0x100) { isize+= 16; val = (val >> 8)-1; }
+ return EXP_GOLOMB_SIZE[val] + isize;
+ }
+
+ inline int32 Size_SE(int32 val) { return Size_UE(val <= 0 ? -val*2 : val*2 - 1); }
+ inline int32 Size_TE(int32 range, int32 v) { if (range == 1) return 1; return Size_UE(v); }
+
+ // Loadovanie bitov do bitbufferu
+ inline void NeedBits() { if (bits < 16) { bitbuf |= ((buf[0] << 8) | (buf[1])) << (16-bits); bits += 16; buf += 2; } };
+ inline void NeedBits24() { while (bits<24) { bitbuf |= (buf[0] << (24-bits)); buf++; bits+= 8; } };
+ inline void NeedBits32() { while (bits<32) { bitbuf |= (buf[0] << (24-bits)); buf++; bits+= 8; } };
+};
Index: /dsfilters/demux_mpc/src/mpc_file.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_file.cpp (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_file.cpp (revision 366)
@@ -0,0 +1,195 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#include "stdafx.h"
+
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCFile class
+//
+//-----------------------------------------------------------------------------
+
+CMPCFile::CMPCFile() :
+ duration_10mhz(0),
+ reader(NULL),
+ packet(NULL)
+{
+ 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);
+}
+
+CMPCFile::~CMPCFile()
+{
+ if (packet) {
+ free(packet);
+ packet = NULL;
+ }
+}
+
+// I/O for MPC file
+int CMPCFile::Open(CMPCReader *reader)
+{
+ HRESULT hr;
+ int ret;
+
+ // keep a local copy of the reader
+ this->reader = reader;
+
+
+ /*
+ According to stream specification the first 4 bytes should be 'MPCK'
+ */
+ uint32 magick;
+ reader->Seek(0);
+ ret = reader->GetMagick(magick); if (ret < 0) return ret;
+ if (magick != 0x4d50434b) {
+ // not a Musepack file
+ return -1;
+ }
+
+ // now loop through a few packets
+ do {
+ int ret = ReadNextPacket();
+ 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;
+
+ // TODO: Seek Table
+
+ // audio packet - initialization is over
+ case MPC_KEY('A','P'): return 0;
+ }
+
+ // if parsing failed we quit
+ if (ret < 0) return ret;
+ } while (1);
+
+ return 0;
+}
+
+int CMPCFile::ReadNextPacket()
+{
+ uint16 key_val;
+ int64 size_val;
+ int32 size_len;
+ int ret;
+
+ 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;
+}
+
+// parsing packets
+
+int CMPCFile::ReadReplaygain()
+{
+ Bitstream b(packet);
+ b.NeedBits();
+
+ int version = b.UGetBits(8);
+ if (version != 1) return 0; // unsupported RG version. not critical to us...
+
+ int16 val;
+ b.NeedBits(); val = b.SGetBits(16); gain_title_db = val / 256.0;
+ b.NeedBits(); val = b.SGetBits(16); gain_title_peak_db = val / 256.0;
+ b.NeedBits(); val = b.SGetBits(16); gain_album_db = val / 256.0;
+ b.NeedBits(); val = b.SGetBits(16); gain_album_peak_db = val / 256.0;
+
+ return 0;
+}
+
+int CMPCFile::ReadStreamHeader()
+{
+ Bitstream b(packet);
+ b.NeedBits();
+
+ // let's do some reading
+ uint32 crc;
+ crc = b.UGetBits(16); b.NeedBits();
+ crc <<= 16;
+ crc |= b.UGetBits(16);
+
+ // TODO: CRC checking.
+ b.NeedBits();
+ stream_version = b.UGetBits(8);
+
+ switch (stream_version) {
+ case 7:
+ {
+ //-----------------------------------------------------------------
+ // Stream Version 7
+ //-----------------------------------------------------------------
+
+ // since we don't do any actual decoding here, we can only look
+ // for the fields of our interest
+
+ // TODO: later. now we want SV8
+
+ }
+ break;
+ case 8:
+ {
+ //-----------------------------------------------------------------
+ // Stream Version 8
+ //-----------------------------------------------------------------
+ int64 samples = b.GetMpcSize();
+ int64 silence = b.GetMpcSize();
+
+ b.NeedBits();
+ uint8 freq = b.UGetBits(3);
+ switch (freq) {
+ case 0: sample_rate = 44100; break;
+ case 1: sample_rate = 48000; break;
+ case 2: sample_rate = 37800; break;
+ case 3: sample_rate = 32000; break;
+ default:
+ // invalid value
+ return -1;
+ }
+
+ // let's calculate duration
+ duration_10mhz = (samples * 10000000) / sample_rate;
+
+ b.DumpBits(5); // bands
+ channels = b.UGetBits(4)+1; // channels
+
+ b.NeedBits();
+ b.DumpBits(1); // mid side
+ int exp = b.UGetBits(3);
+ audio_block_frames = 1 << (2*exp);
+ }
+ break;
+ default:
+ // stream version not supported
+ return -2;
+ }
+
+ // everything is okay
+ return 0;
+}
+
+
Index: /dsfilters/demux_mpc/src/mpc_file.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_file.h (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_file.h (revision 366)
@@ -0,0 +1,57 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+class CMPCReader;
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCFile class
+//
+//-----------------------------------------------------------------------------
+
+class CMPCFile
+{
+public:
+
+ // stream header
+ __int64 duration_10mhz; // total file duration
+ int stream_version; // 7, 8 are supported
+ int sample_rate;
+ int channels;
+ int audio_block_frames;
+
+ // replay gain
+ float gain_title_db;
+ float gain_title_peak_db;
+ float gain_album_db;
+ float gain_album_peak_db;
+
+ // 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
+
+public:
+ CMPCFile();
+ virtual ~CMPCFile();
+
+ // I/O for MPC file
+ int Open(CMPCReader *reader);
+ int ReadNextPacket();
+
+ // parsing packets
+ int ReadStreamHeader();
+ int ReadReplaygain();
+
+};
Index: /dsfilters/demux_mpc/src/mpc_filter.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_filter.cpp (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_filter.cpp (revision 366)
@@ -0,0 +1,275 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#include "stdafx.h"
+
+
+void MakeNiceSpeed(__int64 bps, CString &v)
+{
+ int r=0;
+ __int64 c=bps;
+ LPCTSTR rady[] = {
+ _T("bps"),
+ _T("kbps"),
+ _T("mbps"),
+ _T("gbps"),
+ _T("tbps")
+ };
+
+ // spocitame rad
+ while (c > 1000 && r<4) {
+ r++;
+ c = c / 1000;
+ }
+
+ c=bps;
+ for (int i=1; icElems = 1;
+ pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
+ if (pPages->pElems == NULL) {
+ return E_OUTOFMEMORY;
+ }
+
+ *(pPages->pElems) = CLSID_MusepackDemuxPage;
+ return NOERROR;
+
+} // GetPages
+
+int CMPCDemux::GetPinCount()
+{
+ // return pin count
+ CAutoLock Lock(&lock_filter);
+ return ((input ? 1 : 0) + output.GetCount());
+}
+
+CBasePin *CMPCDemux::GetPin(int n)
+{
+ CAutoLock Lock(&lock_filter);
+ if (n == 0) return input;
+ n -= 1;
+ int l = output.GetCount();
+
+ // return the requested output pin
+ if (n >= l) return NULL;
+ return output[n];
+}
+
+HRESULT CMPCDemux::CheckConnect(PIN_DIRECTION Dir, IPin *pPin)
+{
+ return NOERROR;
+}
+
+HRESULT CMPCDemux::CheckInputType(const CMediaType* mtIn)
+{
+ if (mtIn->majortype == MEDIATYPE_Stream) {
+
+ // we are sure we can accept this type
+ if (mtIn->subtype == MEDIASUBTYPE_MusepackStream) return NOERROR;
+
+ // and we may accept unknown type as well
+ if (mtIn->subtype == MEDIASUBTYPE_None ||
+ mtIn->subtype == MEDIASUBTYPE_NULL ||
+ mtIn->subtype == GUID_NULL
+ ) return NOERROR;
+ } else
+ if (mtIn->majortype == GUID_NULL) {
+ return NOERROR;
+ }
+
+ // sorry.. nothing else
+ return E_FAIL;
+}
+
+HRESULT CMPCDemux::CompleteConnect(PIN_DIRECTION Dir, CBasePin *pCaller, IPin *pReceivePin)
+{
+ if (Dir == PINDIR_INPUT) {
+ // when our input pin gets connected we have to scan
+ // the input file if it is really musepack.
+ ASSERT(input && input->Reader());
+ ASSERT(!reader);
+ ASSERT(!file);
+
+ //---------------------------------------------------------------------
+ //
+ // Analyse the source file
+ //
+ //---------------------------------------------------------------------
+ reader = new CMPCReader(input->Reader());
+ file = new CMPCFile();
+
+ // try to open the file
+ int ret = file->Open(reader);
+ if (ret < 0) {
+ delete file; file = NULL;
+ delete reader; reader = NULL;
+ return E_FAIL;
+ }
+
+ // refresh property page if there is any
+ if (IsWindow(wnd_prop)) {
+ PostMessage(wnd_prop, WM_UPDATE_VISUALS, 0, 0);
+ }
+
+ } else {
+ }
+ return NOERROR;
+}
+
+
+HRESULT CMPCDemux::RemoveOutputPins()
+{
+ CAutoLock Lck(&lock_filter);
+ if (m_State != State_Stopped) return VFW_E_NOT_STOPPED;
+
+ // we retire all current output pins
+ for (int i=0; iIsConnected()) {
+ pin->GetConnected()->Disconnect();
+ pin->Disconnect();
+ }
+ retired.Add(pin);
+ }
+ output.RemoveAll();
+ return NOERROR;
+}
+
+
+HRESULT CMPCDemux::BreakConnect(PIN_DIRECTION Dir, CBasePin *pCaller)
+{
+ ASSERT(m_State == State_Stopped);
+
+ if (Dir == PINDIR_INPUT) {
+ // let's disconnect the output pins
+ //ev_abort.Set();
+ //ev_ready.Set();
+
+ HRESULT hr = RemoveOutputPins();
+ if (FAILED(hr)) return hr;
+
+ // destroy input file
+ if (file) { delete file; file = NULL; }
+
+ // destroy reader
+ if (reader) { delete reader; reader = NULL; }
+
+ // refresh property page if there is any
+ if (IsWindow(wnd_prop)) {
+ PostMessage(wnd_prop, WM_UPDATE_VISUALS, 0, 0);
+ }
+
+ //ev_abort.Reset();
+ } else
+ if (Dir == PINDIR_OUTPUT) {
+ // nothing yet
+ }
+ return NOERROR;
+}
+
+
+// Output pins
+HRESULT CMPCDemux::AddOutputPin(CMPCOutputPin *pPin)
+{
+ CAutoLock lck(&lock_filter);
+ output.Add(pPin);
+ return NOERROR;
+}
+
+STDMETHODIMP CMPCDemux::GetFileInfo(MPC_File_Info *info)
+{
+ CAutoLock lck(&lock_filter);
+ if (!info) return E_POINTER;
+ if (!file) return E_FAIL;
+
+ // fill in the struct
+ info->duration = file->duration_10mhz / 10000000.0;
+ info->stream_version = file->stream_version;
+ info->channels = file->channels;
+ info->sample_rate = file->sample_rate;
+ info->block_frames = file->audio_block_frames;
+
+ return NOERROR;
+}
+
+
+
+
Index: /dsfilters/demux_mpc/src/mpc_filter.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_filter.h (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_filter.h (revision 366)
@@ -0,0 +1,95 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+#define CMD_EXIT 0
+#define CMD_STOP 1
+#define CMD_RUN 2
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCDemux class
+//
+//-----------------------------------------------------------------------------
+class CMPCDemux :
+ public CBaseFilter,
+ public ISpecifyPropertyPages ,
+ public IMusepackSplitter
+{
+public:
+
+ CCritSec lock_filter;
+ CMPCInputPin *input;
+ CArray output;
+ CArray retired;
+ CMPCReader *reader;
+ CMPCFile *file;
+ HWND wnd_prop;
+
+public:
+ // constructor
+ CMPCDemux(LPUNKNOWN pUnk, HRESULT *phr);
+ virtual ~CMPCDemux();
+ static CUnknown * WINAPI CreateInstance(LPUNKNOWN pUnk, HRESULT *phr);
+
+ // override this to publicise our interfaces
+ DECLARE_IUNKNOWN;
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
+
+ // ISpecifyPropertyPages interface
+ STDMETHODIMP GetPages(CAUUID *pPages);
+
+ // CBaseFilter
+ virtual int GetPinCount();
+ virtual CBasePin *GetPin(int n);
+
+ // Output pins
+ HRESULT AddOutputPin(CMPCOutputPin *pPin);
+ virtual HRESULT RemoveOutputPins();
+ CMPCOutputPin *FindStream(int stream_no);
+
+ // check that we can support this input type
+ virtual HRESULT CheckInputType(const CMediaType* mtIn);
+ virtual HRESULT CheckConnect(PIN_DIRECTION Dir, IPin *pPin);
+ virtual HRESULT BreakConnect(PIN_DIRECTION Dir, CBasePin *pCaller);
+ virtual HRESULT CompleteConnect(PIN_DIRECTION Dir, CBasePin *pCaller, IPin *pReceivePin);
+
+
+ // IMusepackSplitter
+ STDMETHODIMP GetFileInfo(MPC_File_Info *info);
+ STDMETHODIMP SetPropertyPageWindow(HWND wnd);
+
+
+ // IMediaSeeking
+ /*
+ STDMETHODIMP GetCapabilities(DWORD* pCapabilities);
+ STDMETHODIMP CheckCapabilities(DWORD* pCapabilities);
+ STDMETHODIMP IsFormatSupported(const GUID* pFormat);
+ STDMETHODIMP QueryPreferredFormat(GUID* pFormat);
+ STDMETHODIMP GetTimeFormat(GUID* pFormat);
+ STDMETHODIMP IsUsingTimeFormat(const GUID* pFormat);
+ STDMETHODIMP SetTimeFormat(const GUID* pFormat);
+ STDMETHODIMP GetDuration(LONGLONG* pDuration);
+ STDMETHODIMP GetStopPosition(LONGLONG* pStop);
+ STDMETHODIMP GetCurrentPosition(LONGLONG* pCurrent);
+ STDMETHODIMP ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat);
+ STDMETHODIMP SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags);
+ STDMETHODIMP GetPositions(LONGLONG* pCurrent, LONGLONG* pStop);
+ STDMETHODIMP GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest);
+ STDMETHODIMP SetRate(double dRate);
+ STDMETHODIMP GetRate(double* pdRate);
+ STDMETHODIMP GetPreroll(LONGLONG* pllPreroll);
+ STDMETHODIMP SetPositionsInternal(int iD, LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags);
+
+ // virtual HRESULT DoNewSeek();
+ */
+
+};
+
+
Index: /dsfilters/demux_mpc/src/mpc_pin.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_pin.cpp (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_pin.cpp (revision 366)
@@ -0,0 +1,747 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#include "stdafx.h"
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCInputPin class
+//
+//-----------------------------------------------------------------------------
+
+CMPCInputPin::CMPCInputPin(TCHAR *pObjectName, CMPCDemux *pDemux, HRESULT *phr, LPCWSTR pName) :
+ CBaseInputPin(pObjectName, pDemux, &pDemux->lock_filter, phr, pName),
+ reader(NULL)
+{
+ // assign the splitter filter
+ demux = pDemux;
+}
+
+CMPCInputPin::~CMPCInputPin()
+{
+ if (reader) { reader->Release(); reader = NULL; }
+}
+
+// this is a pull mode pin - these can not happen
+
+STDMETHODIMP CMPCInputPin::EndOfStream() { return E_UNEXPECTED; }
+STDMETHODIMP CMPCInputPin::BeginFlush() { return E_UNEXPECTED; }
+STDMETHODIMP CMPCInputPin::EndFlush() { return E_UNEXPECTED; }
+STDMETHODIMP CMPCInputPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate) { return E_UNEXPECTED; }
+
+// we don't support this kind of transport
+STDMETHODIMP CMPCInputPin::Receive(IMediaSample * pSample) { return E_UNEXPECTED; }
+
+// check for input type
+HRESULT CMPCInputPin::CheckConnect(IPin *pPin)
+{
+ HRESULT hr = demux->CheckConnect(PINDIR_INPUT, pPin);
+ if (FAILED(hr)) return hr;
+
+ return CBaseInputPin::CheckConnect(pPin);
+}
+
+HRESULT CMPCInputPin::BreakConnect()
+{
+ // Can't disconnect unless stopped
+ ASSERT(IsStopped());
+
+ demux->BreakConnect(PINDIR_INPUT, this);
+
+ // release the reader
+ if (reader) reader->Release(); reader = NULL;
+ return CBaseInputPin::BreakConnect();
+}
+
+HRESULT CMPCInputPin::CompleteConnect(IPin *pReceivePin)
+{
+ // make sure there is a pin
+ ASSERT(pReceivePin);
+
+ if (reader) reader->Release(); reader = NULL;
+
+ // and make sure it supports IAsyncReader
+ HRESULT hr = pReceivePin->QueryInterface(IID_IAsyncReader, (void **)&reader);
+ if (FAILED(hr)) return hr;
+
+ // we're done here
+ hr = demux->CompleteConnect(PINDIR_INPUT, this, pReceivePin);
+ if (FAILED(hr)) return hr;
+
+ return CBaseInputPin::CompleteConnect(pReceivePin);
+}
+
+HRESULT CMPCInputPin::CheckMediaType(const CMediaType* pmt)
+{
+ // make sure we have a type
+ ASSERT(pmt);
+
+ // ask the splitter
+ return demux->CheckInputType(pmt);
+}
+
+HRESULT CMPCInputPin::SetMediaType(const CMediaType* pmt)
+{
+ // let the baseclass know
+ if (FAILED(CheckMediaType(pmt))) return E_FAIL;
+
+ HRESULT hr = CBasePin::SetMediaType(pmt);
+ if (FAILED(hr)) return hr;
+
+ return NOERROR;
+}
+
+HRESULT CMPCInputPin::Inactive()
+{
+ HRESULT hr = CBaseInputPin::Inactive();
+ if (hr == VFW_E_NO_ALLOCATOR) hr = NOERROR;
+ if (FAILED(hr)) return hr;
+
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+//
+// CMPCOutputPin class
+//
+//-----------------------------------------------------------------------------
+
+CMPCOutputPin::CMPCOutputPin(TCHAR *pObjectName, CMPCDemux *pDemux, HRESULT *phr, LPCWSTR pName, int iBuffers) :
+ CBaseOutputPin(pObjectName, pDemux, &pDemux->lock_filter, phr, pName),
+ CAMThread(),
+ demux(pDemux),
+ buffers(iBuffers),
+ active(false),
+ rtStart(0),
+ rtStop(0xffffffffffff),
+ rate(1.0),
+ ev_can_read(TRUE),
+ ev_can_write(TRUE),
+ ev_abort(TRUE)
+{
+ discontinuity = true;
+ eos_delivered = false;
+
+ ev_can_read.Reset();
+ ev_can_write.Set();
+ ev_abort.Reset();
+}
+
+CMPCOutputPin::~CMPCOutputPin()
+{
+ // nothing yet
+}
+
+STDMETHODIMP CMPCOutputPin::NonDelegatingQueryInterface(REFIID riid, void **ppv)
+{
+ CheckPointer(ppv, E_POINTER);
+ /*
+ if (riid == IID_IMediaSeeking) {
+ return GetInterface((IMediaSeeking*)this, ppv);
+ } else {
+ */
+ return CBaseOutputPin::NonDelegatingQueryInterface(riid, ppv);
+ //}
+}
+
+HRESULT CMPCOutputPin::CheckMediaType(const CMediaType *mtOut)
+{
+ for (int i=0; i= mt_types.GetCount()) return VFW_S_NO_MORE_ITEMS;
+
+ *pmt = mt_types[iPosition];
+ return NOERROR;
+}
+
+HRESULT CMPCOutputPin::DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp)
+{
+ ASSERT(pAlloc);
+ ASSERT(pProp);
+ HRESULT hr = NOERROR;
+
+ pProp->cBuffers = max(buffers, 1);
+ pProp->cbBuffer = max(m_mt.lSampleSize, 1);
+ ALLOCATOR_PROPERTIES Actual;
+ hr = pAlloc->SetProperties(pProp, &Actual);
+ if (FAILED(hr)) return hr;
+
+ ASSERT(Actual.cBuffers >= pProp->cBuffers);
+ return NOERROR;
+}
+
+HRESULT CMPCOutputPin::BreakConnect()
+{
+ ASSERT(IsStopped());
+ demux->BreakConnect(PINDIR_OUTPUT, this);
+ discontinuity = true;
+ return CBaseOutputPin::BreakConnect();
+}
+
+HRESULT CMPCOutputPin::CompleteConnect(IPin *pReceivePin)
+{
+ // let the parent know
+ HRESULT hr = demux->CompleteConnect(PINDIR_OUTPUT, this, pReceivePin);
+ if (FAILED(hr)) return hr;
+
+ discontinuity = true;
+ // okey
+ return CBaseOutputPin::CompleteConnect(pReceivePin);
+}
+
+STDMETHODIMP CMPCOutputPin::Notify(IBaseFilter *pSender, Quality q)
+{
+ return S_FALSE;
+}
+
+HRESULT CMPCOutputPin::Inactive()
+{
+ if (!active) return NOERROR;
+ active = FALSE;
+
+ // destroy everything
+ ev_abort.Set();
+ HRESULT hr = CBaseOutputPin::Inactive();
+ ASSERT(SUCCEEDED(hr));
+
+ if (ThreadExists()) {
+ CallWorker(CMD_EXIT);
+ Close();
+ }
+ FlushQueue();
+ ev_abort.Reset();
+
+ return NOERROR;
+}
+
+
+HRESULT CMPCOutputPin::Active()
+{
+ if (active) return NOERROR;
+
+ FlushQueue();
+ if (!IsConnected()) return VFW_E_NOT_CONNECTED;
+
+ ev_abort.Reset();
+
+ // vytvorime novu queue
+ if (!ThreadExists()) {
+ Create();
+ CallWorker(CMD_RUN);
+ }
+
+ HRESULT hr = CBaseOutputPin::Active();
+ if (FAILED(hr)) {
+ active = FALSE;
+ return hr;
+ }
+
+ // new segment
+ DoNewSegment(rtStart, rtStop, rate);
+ active = TRUE;
+ return hr;
+}
+
+
+HRESULT CMPCOutputPin::DoNewSegment(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double dRate)
+{
+ DataPacket *packet;
+ int ret = GetDataPacket(&packet);
+ if (ret < 0 || !packet) return E_FAIL;
+
+ // queue the EOS packet
+ this->rtStart = rtStart;
+ this->rtStop = rtStop;
+ this->rate = dRate;
+ eos_delivered = false;
+
+ {
+ CAutoLock lck(&lock_queue);
+ packet->type = DataPacket::PACKET_TYPE_NEW_SEGMENT;
+ packet->rtStart = rtStart;
+ packet->rtStop = rtStop;
+ packet->rate = rate;
+ queue.AddTail(packet);
+ ev_can_read.Set();
+ discontinuity = true;
+ }
+
+ return NOERROR;
+}
+
+/*
+// IMediaSeeking
+STDMETHODIMP CMPCOutputPin::GetCapabilities(DWORD* pCapabilities) { return demux->GetCapabilities(pCapabilities); }
+STDMETHODIMP CMPCOutputPin::CheckCapabilities(DWORD* pCapabilities) { return demux->CheckCapabilities(pCapabilities); }
+STDMETHODIMP CMPCOutputPin::IsFormatSupported(const GUID* pFormat) { return demux->IsFormatSupported(pFormat); }
+STDMETHODIMP CMPCOutputPin::QueryPreferredFormat(GUID* pFormat) { return demux->QueryPreferredFormat(pFormat); }
+STDMETHODIMP CMPCOutputPin::GetTimeFormat(GUID* pFormat) { return demux->GetTimeFormat(pFormat); }
+STDMETHODIMP CMPCOutputPin::IsUsingTimeFormat(const GUID* pFormat) { return demux->IsUsingTimeFormat(pFormat); }
+STDMETHODIMP CMPCOutputPin::SetTimeFormat(const GUID* pFormat) { return demux->SetTimeFormat(pFormat); }
+STDMETHODIMP CMPCOutputPin::GetDuration(LONGLONG* pDuration) { return demux->GetDuration(pDuration); }
+STDMETHODIMP CMPCOutputPin::GetStopPosition(LONGLONG* pStop) { return demux->GetStopPosition(pStop); }
+STDMETHODIMP CMPCOutputPin::GetCurrentPosition(LONGLONG* pCurrent) { return demux->GetCurrentPosition(pCurrent); }
+STDMETHODIMP CMPCOutputPin::GetPositions(LONGLONG* pCurrent, LONGLONG* pStop) { return demux->GetPositions(pCurrent, pStop); }
+STDMETHODIMP CMPCOutputPin::GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest) { return demux->GetAvailable(pEarliest, pLatest); }
+STDMETHODIMP CMPCOutputPin::SetRate(double dRate) { return demux->SetRate(dRate); }
+STDMETHODIMP CMPCOutputPin::GetRate(double* pdRate) { return demux->GetRate(pdRate); }
+STDMETHODIMP CMPCOutputPin::GetPreroll(LONGLONG* pllPreroll) { return demux->GetPreroll(pllPreroll); }
+STDMETHODIMP CMPCOutputPin::ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat)
+{
+ return demux->ConvertTimeFormat(pTarget, pTargetFormat, Source, pSourceFormat);
+}
+STDMETHODIMP CMPCOutputPin::SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags)
+{
+ return demux->SetPositionsInternal(stream_index, pCurrent, dwCurrentFlags, pStop, dwStopFlags);
+}
+*/
+
+int CMPCOutputPin::GetDataPacket(DataPacket **packet)
+{
+ // this method may blokc
+ HANDLE events[] = { ev_can_write, ev_abort };
+ DWORD ret;
+
+ do {
+ // if the abort event is set, quit
+ if (ev_abort.Check()) return -1;
+
+ ret = WaitForMultipleObjects(2, events, FALSE, 10);
+ if (ret == WAIT_OBJECT_0) {
+ // return new packet
+ *packet = new DataPacket();
+ return 0;
+ }
+
+ } while (1);
+
+ // unexpected
+ return -1;
+}
+
+/*
+// dorucenie packetu
+HRESULT CMPCOutputPin::DeliverPacket(MP4::Packet &packet)
+{
+ // ziskame novy packet na vystup
+ DataPacket *outp = NULL;
+ int ret = GetDataPacket(&outp);
+ if (ret < 0 || !outp) return E_FAIL;
+
+ REFERENCE_TIME start, stop;
+
+ outp->type = DataPacket::PACKET_TYPE_DATA;
+
+ // spocitame casy
+ outp->rtStart = (packet.pts_100mhz / 10) - rtStart;
+ outp->rtStop = outp->rtStart + 1;
+
+ outp->size = 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;
+ }
+
+ // discontinuity ?
+ if (discontinuity) {
+ outp->discontinuity = TRUE;
+ discontinuity = false;
+ } else {
+ outp->discontinuity = FALSE;
+ }
+
+ {
+ // strcime do queue
+ MonoBase::AutoLock 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();
+ }
+ }
+ }
+
+ return NOERROR;
+}
+*/
+
+HRESULT CMPCOutputPin::DoEndOfStream()
+{
+ DataPacket *packet;
+ int ret = GetDataPacket(&packet);
+ if (ret < 0 || !packet) return E_FAIL;
+
+ // naqueueujeme EOS
+ {
+ CAutoLock lck(&lock_queue);
+ packet->type = DataPacket::PACKET_TYPE_EOS;
+ queue.AddTail(packet);
+ ev_can_read.Set();
+ }
+ eos_delivered = true;
+
+ return NOERROR;
+}
+
+void CMPCOutputPin::FlushQueue()
+{
+ CAutoLock lck(&lock_queue);
+ while (queue.GetCount() > 0) {
+ DataPacket *packet = queue.RemoveHead();
+ if (packet) delete packet;
+ }
+ ev_can_read.Reset();
+ ev_can_write.Set();
+
+ // we return buffer level only for the first pin
+ /*
+ if (stream_index == demux->buf_index) {
+ //MonoBase::AutoLock lck2(&demux->lock_info);
+ demux->buf_size_ms = GetBufferTime_MS();
+ }
+ */
+}
+
+HRESULT CMPCOutputPin::DeliverDataPacket(DataPacket &packet)
+{
+ IMediaSample *sample;
+ HRESULT hr = GetDeliveryBuffer(&sample, NULL, NULL, 0);
+ if (FAILED(hr)) return E_FAIL;
+
+ // we should have enough space in there
+ ASSERT(sample->GetSize() >= packet.size);
+
+ BYTE *buf;
+ sample->GetPointer(&buf);
+
+ //*************************************************************************
+ //
+ // data
+ //
+ //*************************************************************************
+
+ memcpy(buf, packet.buf, packet.size);
+ sample->SetActualDataLength(packet.size);
+
+ // sync point, discontinuity ?
+ if (packet.sync_point) { sample->SetSyncPoint(TRUE); } else { sample->SetSyncPoint(FALSE); }
+ if (packet.discontinuity) { sample->SetDiscontinuity(TRUE); } else { sample->SetDiscontinuity(FALSE); }
+
+ // do we have a time stamp ?
+ if (packet.has_time) { sample->SetTime(&packet.rtStart, &packet.rtStop); }
+
+ // dorucime
+ hr = Deliver(sample);
+ sample->Release();
+ return hr;
+}
+
+__int64 CMPCOutputPin::GetBufferTime_MS()
+{
+ CAutoLock lck(&lock_queue);
+ if (queue.IsEmpty()) return 0;
+
+ DataPacket *pfirst;
+ DataPacket *plast;
+ __int64 tstart, tstop;
+ POSITION posf, posl;
+
+ tstart = -1;
+ tstop = -1;
+
+ posf = queue.GetHeadPosition();
+ while (posf) {
+ pfirst = queue.GetNext(posf);
+ if (pfirst->type == DataPacket::PACKET_TYPE_DATA && pfirst->rtStart != -1) {
+ tstart = pfirst->rtStart;
+ break;
+ }
+ }
+
+ posl = queue.GetTailPosition();
+ while (posl) {
+ plast = queue.GetPrev(posl);
+ if (plast->type == DataPacket::PACKET_TYPE_DATA && plast->rtStart != -1) {
+ tstop = plast->rtStart;
+ break;
+ }
+ }
+
+ if (tstart == -1 || tstop == -1) return 0;
+
+ // calculate time in milliseconds
+ return (tstop - tstart) / 10000;
+}
+
+// vlakno na output
+DWORD CMPCOutputPin::ThreadProc()
+{
+ while (true) {
+ DWORD cmd = GetRequest();
+ switch (cmd) {
+ case CMD_EXIT: Reply(0); return 0; break;
+ case CMD_STOP: Reply(0); break;
+ case CMD_RUN:
+ {
+ Reply(0);
+ if (!IsConnected()) break;
+
+ // deliver packets
+ DWORD cmd2;
+ BOOL is_first = true;
+ DataPacket *packet;
+ HRESULT hr;
+
+ do {
+ if (ev_abort.Check()) break;
+ hr = NOERROR;
+
+ HANDLE events[] = { ev_can_read, ev_abort};
+ DWORD ret = WaitForMultipleObjects(2, events, FALSE, 10);
+
+ if (ret == WAIT_OBJECT_0) {
+ // look for new packet in queue
+ {
+ CAutoLock lck(&lock_queue);
+ packet = queue.RemoveHead();
+ if (queue.IsEmpty()) ev_can_read.Reset();
+
+ // allow buffering
+ if (GetBufferTime_MS() < buffer_time_ms) ev_can_write.Set();
+ }
+
+ // bud dorucime End Of Stream, alebo packet
+ if (packet->type == DataPacket::PACKET_TYPE_EOS) {
+ DeliverEndOfStream();
+ } else
+ if (packet->type == DataPacket::PACKET_TYPE_DATA) {
+ hr = DeliverDataPacket(*packet);
+ if (SUCCEEDED(hr)) {
+
+ /*
+ if (stream_index == demux->buf_index) {
+ int size = GetBufferTime_MS();
+ {
+ MonoBase::AutoLock lck2(&demux->lock_info);
+ demux->buf_size_ms = size;
+ demux->NotifyEvent(EC_BUFFER_STATE, size, demux->internal_buffer_size); // v milisekundach
+ }
+ demux->UpdatePage(1);
+
+ // posleme notifikaciu, ze data boli dorucene
+ if (is_first) {
+ is_first = false;
+ demux->NotifyEvent(EC_FRAME_READY, 0, 0);
+ }
+
+ // starvation
+ if (size < 0.05*demux->internal_buffer_size && !eos_delivered &&
+ demux->ev_ready.Check() == TRUE
+ ) {
+ demux->NotifyStarvation();
+ }
+ }
+ */
+ }
+ }
+
+ delete packet;
+
+ if (FAILED(hr)) {
+ break;
+ }
+ }
+ } while (!CheckRequest(&cmd2));
+ }
+ break;
+ default:
+ Reply(E_UNEXPECTED);
+ break;
+ }
+ }
+ return 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCReader class
+//
+//-----------------------------------------------------------------------------
+CMPCReader::CMPCReader(IAsyncReader *rd)
+{
+ ASSERT(rd);
+
+ reader = rd;
+ reader->AddRef();
+ pos = 0;
+}
+
+CMPCReader::~CMPCReader()
+{
+ if (reader) {
+ reader->Release();
+ reader = NULL;
+ }
+}
+
+int CMPCReader::GetSize(__int64 *avail, __int64 *total)
+{
+ // vraciame velkost
+ HRESULT hr = reader->Length(total, avail);
+ if (FAILED(hr)) return -1;
+ return 0;
+}
+
+int CMPCReader::GetPosition(__int64 *pos, __int64 *avail)
+{
+ HRESULT hr;
+ __int64 total;
+ hr = reader->Length(&total, avail);
+ if (FAILED(hr)) return -1;
+
+ // aktualna pozicia
+ if (pos) *pos = this->pos;
+ return 0;
+}
+
+int CMPCReader::Seek(__int64 pos)
+{
+ __int64 avail, total;
+ GetSize(&avail, &total);
+ if (pos < 0 || pos >= total) return -1;
+
+ // seekneme
+ this->pos = pos;
+ return 0;
+}
+
+int CMPCReader::Read(void *buf, int size)
+{
+ __int64 avail, total;
+ GetSize(&avail, &total);
+ if (pos + size > avail) return -1;
+
+ // TODO: Caching here !!!!
+
+ HRESULT hr = reader->SyncRead(pos, size, (BYTE*)buf);
+ if (FAILED(hr)) return -2;
+
+ // update position
+ pos += size;
+ return 0;
+}
+
+// reading syntax elements
+int CMPCReader::GetMagick(uint32 &elm)
+{
+ uint8 buf[4];
+ int ret = Read(buf, sizeof(buf));
+ if (ret < 0) return ret;
+
+ // network byte order
+ elm = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3]);
+ return 0;
+}
+
+int CMPCReader::GetKey(uint16 &key)
+{
+ uint8 buf[2];
+ int ret = Read(buf, sizeof(buf));
+ if (ret < 0) return ret;
+
+ // network byte order
+ key = (buf[0] << 8) | (buf[1]);
+ return 0;
+}
+
+int CMPCReader::GetSizeElm(int64 &size, int32 &size_len)
+{
+ int ret;
+ size = 0;
+ size_len = 1;
+
+ while (true) {
+ uint8 val;
+ ret = Read(&val, 1); if (ret < 0) return ret;
+
+ // this is the last one
+ if (!(val&0x80)) { size |= val&0x7f; return 0; }
+
+ // not the last one
+ size |= (val&0x7f);
+ size <<= 7;
+ size_len ++;
+ }
+ return 0;
+}
+
+bool CMPCReader::KeyValid(uint16 key)
+{
+ // according to the specs keys can only take specific values.
+ if (((key>>8)&0xff) < 65 || ((key>>8)&0xff) > 90) return false;
+ if ((key&0xff) < 65 || (key&0xff) > 90) return false;
+ return true;
+}
+
+
+DataPacket::DataPacket() :
+ type(PACKET_TYPE_EOS),
+ rtStart(0),
+ rtStop(0),
+ sync_point(FALSE),
+ discontinuity(FALSE),
+ buf(NULL),
+ size(0)
+{
+}
+
+DataPacket::~DataPacket()
+{
+ if (buf) {
+ free(buf);
+ buf = NULL;
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
Index: /dsfilters/demux_mpc/src/mpc_pin.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_pin.h (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_pin.h (revision 366)
@@ -0,0 +1,217 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+
+class CMPCDemux;
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCInputPin class
+//
+//-----------------------------------------------------------------------------
+class CMPCInputPin : public CBaseInputPin
+{
+public:
+
+ // parent splitter
+ CMPCDemux *demux;
+ IAsyncReader *reader;
+
+public:
+ CMPCInputPin(TCHAR *pObjectName, CMPCDemux *pDemux, HRESULT *phr, LPCWSTR pName);
+ virtual ~CMPCInputPin();
+
+ // Get hold of IAsyncReader interface
+ HRESULT CompleteConnect(IPin *pReceivePin);
+ HRESULT CheckConnect(IPin *pPin);
+ HRESULT BreakConnect();
+ HRESULT CheckMediaType(const CMediaType *pmt);
+ HRESULT SetMediaType(const CMediaType *pmt);
+
+ // IMemInputPIn
+ STDMETHODIMP Receive(IMediaSample *pSample);
+ STDMETHODIMP EndOfStream(void);
+ STDMETHODIMP BeginFlush();
+ STDMETHODIMP EndFlush();
+ STDMETHODIMP NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double rate);
+
+ HRESULT Inactive();
+public:
+ // Helpers
+ CMediaType &CurrentMediaType() { return m_mt; }
+ IAsyncReader *Reader() { return reader; }
+};
+
+//-----------------------------------------------------------------------------
+//
+// DataPacket class
+//
+//-----------------------------------------------------------------------------
+class DataPacket
+{
+public:
+ int type;
+
+ enum {
+ PACKET_TYPE_EOS = 0,
+ PACKET_TYPE_DATA = 1,
+ PACKET_TYPE_NEW_SEGMENT = 2
+ };
+
+ REFERENCE_TIME rtStart, rtStop;
+ double rate;
+ bool has_time;
+ BOOL sync_point;
+ BOOL discontinuity;
+ BYTE *buf;
+ int size;
+
+public:
+ DataPacket();
+ virtual ~DataPacket();
+
+};
+
+typedef CArray CMediaTypes;
+
+//-----------------------------------------------------------------------------
+//
+// CMPCOutputPin class
+//
+//-----------------------------------------------------------------------------
+class CMPCOutputPin :
+ public CBaseOutputPin,
+// public IMediaSeeking,
+ public CAMThread
+{
+public:
+
+ // parser
+ CMPCDemux *demux;
+ int stream_index;
+ CMediaTypes mt_types;
+
+ // buffer queue
+ int buffers;
+ CList queue;
+ CCritSec lock_queue;
+ CAMEvent ev_can_read;
+ CAMEvent ev_can_write;
+ CAMEvent ev_abort;
+ int buffer_time_ms;
+
+ // time stamps
+ REFERENCE_TIME rtStart;
+ REFERENCE_TIME rtStop;
+ double rate;
+ bool active;
+ bool discontinuity;
+ bool eos_delivered;
+
+public:
+ CMPCOutputPin(TCHAR *pObjectName, CMPCDemux *pDemux, HRESULT *phr, LPCWSTR pName, int iBuffers);
+ virtual ~CMPCOutputPin();
+
+ // IUNKNOWN
+ DECLARE_IUNKNOWN;
+ STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv);
+
+ // MediaType stuff
+ HRESULT CheckMediaType(const CMediaType *pmt);
+ HRESULT SetMediaType(const CMediaType *pmt);
+ HRESULT GetMediaType(int iPosition, CMediaType *pmt);
+ HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp);
+ HRESULT BreakConnect();
+ HRESULT CompleteConnect(IPin *pReceivePin);
+
+ // Activation/Deactivation
+ HRESULT Active();
+ HRESULT Inactive();
+ HRESULT DoNewSegment(REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, double dRate);
+
+ STDMETHODIMP Notify(IBaseFilter *pSender, Quality q);
+
+ // packet delivery mechanism
+ //HRESULT DeliverPacket(MP4::Packet &packet);
+ HRESULT DeliverDataPacket(DataPacket &packet);
+ HRESULT DoEndOfStream();
+
+ // delivery thread
+ virtual DWORD ThreadProc();
+ void FlushQueue();
+ int GetDataPacket(DataPacket **packet);
+
+ /*
+ // IMediaSeeking
+ STDMETHODIMP GetCapabilities(DWORD* pCapabilities);
+ STDMETHODIMP CheckCapabilities(DWORD* pCapabilities);
+ STDMETHODIMP IsFormatSupported(const GUID* pFormat);
+ STDMETHODIMP QueryPreferredFormat(GUID* pFormat);
+ STDMETHODIMP GetTimeFormat(GUID* pFormat);
+ STDMETHODIMP IsUsingTimeFormat(const GUID* pFormat);
+ STDMETHODIMP SetTimeFormat(const GUID* pFormat);
+ STDMETHODIMP GetDuration(LONGLONG* pDuration);
+ STDMETHODIMP GetStopPosition(LONGLONG* pStop);
+ STDMETHODIMP GetCurrentPosition(LONGLONG* pCurrent);
+ STDMETHODIMP ConvertTimeFormat(LONGLONG* pTarget, const GUID* pTargetFormat, LONGLONG Source, const GUID* pSourceFormat);
+ STDMETHODIMP SetPositions(LONGLONG* pCurrent, DWORD dwCurrentFlags, LONGLONG* pStop, DWORD dwStopFlags);
+ STDMETHODIMP GetPositions(LONGLONG* pCurrent, LONGLONG* pStop);
+ STDMETHODIMP GetAvailable(LONGLONG* pEarliest, LONGLONG* pLatest);
+ STDMETHODIMP SetRate(double dRate);
+ STDMETHODIMP GetRate(double* pdRate);
+ STDMETHODIMP GetPreroll(LONGLONG* pllPreroll);
+ */
+
+public:
+ CMediaType &CurrentMediaType() { return m_mt; }
+ IMemAllocator *Allocator() { return m_pAllocator; }
+ REFERENCE_TIME CurrentStart() { return rtStart; }
+ REFERENCE_TIME CurrentStop() { return rtStop; }
+ double CurrentRate() { return rate; }
+ __int64 GetBufferTime_MS();
+};
+
+//-----------------------------------------------------------------------------
+//
+// CMPCReader class
+//
+// Todo: caching...
+//
+//-----------------------------------------------------------------------------
+
+#define MPC_KEY(k1,k2) ((k1<<8)|(k2))
+
+class CMPCReader
+{
+protected:
+ IAsyncReader *reader;
+ __int64 pos;
+
+public:
+ CMPCReader(IAsyncReader *rd);
+ virtual ~CMPCReader();
+
+ virtual int GetSize(__int64 *avail, __int64 *total);
+ virtual int GetPosition(__int64 *pos, __int64 *avail);
+ virtual int Seek(__int64 pos);
+ virtual int Read(void *buf, int size);
+
+ void BeginFlush() { if (reader) reader->BeginFlush(); }
+ void EndFlush() { if (reader) reader->EndFlush(); }
+
+ // reading syntax elements - in network byte order
+ int GetMagick(uint32 &elm);
+ int GetKey(uint16 &key);
+ int GetSizeElm(int64 &size, int32 &size_len);
+ bool KeyValid(uint16 key);
+
+};
+
+
Index: /dsfilters/demux_mpc/src/mpc_prop.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_prop.cpp (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_prop.cpp (revision 366)
@@ -0,0 +1,160 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#include "stdafx.h"
+
+#include "..\resource.h"
+
+
+// minimalny a maximalny cas, ktory je mozne navolit v property pagese
+#define MIN_TIME 1
+#define MAX_TIME 10
+#define ITEM(x) GetDlgItem(m_Dlg, x)
+
+void MakeNiceTime(int time_ms, CString &v)
+{
+ int ms = time_ms%1000;
+ time_ms -= ms;
+ time_ms /= 1000;
+
+ int h, m, s;
+ h = time_ms / 3600; time_ms -= h*3600;
+ m = time_ms / 60; time_ms -= m*60;
+ s = time_ms;
+
+ v.Format(_T("%.2d:%.2d:%.2d,%.3d"), h, m, s, ms);
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// CMPCPropertyPage class
+//
+//-----------------------------------------------------------------------------
+
+CUnknown *CMPCPropertyPage::CreateInstance(LPUNKNOWN lpUnk, HRESULT *phr)
+{
+ return new CMPCPropertyPage(lpUnk, phr);
+}
+
+CMPCPropertyPage::CMPCPropertyPage(LPUNKNOWN lpUnk, HRESULT *phr) :
+ CBasePropertyPage(NAME("MPC Property Page"), lpUnk, IDD_PAGE_DEMUX, IDS_PAGE_DEMUX),
+ demux(NULL)
+{
+}
+
+CMPCPropertyPage::~CMPCPropertyPage()
+{
+}
+
+HRESULT CMPCPropertyPage::OnConnect(IUnknown *pUnknown)
+{
+ // hold a pointer
+ ASSERT(!demux);
+
+ HRESULT hr = pUnknown->QueryInterface(IID_IMusepackSplitter, (void**)&demux);
+ if (FAILED(hr)) return hr;
+
+ // okej
+ return NOERROR;
+}
+
+HRESULT CMPCPropertyPage::OnDisconnect()
+{
+ if (demux) {
+ demux->Release(); demux = NULL;
+ }
+
+ return NOERROR;
+}
+
+HRESULT CMPCPropertyPage::OnActivate()
+{
+ demux->SetPropertyPageWindow(m_Dlg);
+
+ // initialize out controls
+ LVCOLUMN col;
+ col.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
+
+ col.pszText = _T("Name"); col.cx = 150; col.iSubItem = 0;
+ ListView_InsertColumn(ITEM(IDC_LIST_CONTENT), 0, &col);
+
+ col.pszText = _T("Value"); col.cx = 200; col.iSubItem = 1;
+ ListView_InsertColumn(ITEM(IDC_LIST_CONTENT), 1, &col);
+
+ UpdateList();
+ return NOERROR;
+}
+
+HRESULT CMPCPropertyPage::OnDeactivate()
+{
+ demux->SetPropertyPageWindow(NULL);
+ return NOERROR;
+}
+
+void CMPCPropertyPage::UpdateList()
+{
+ // first reset everything
+ ListView_DeleteAllItems(ITEM(IDC_LIST_CONTENT));
+
+ // now check for the file
+ MPC_File_Info info;
+ HRESULT hr = demux->GetFileInfo(&info);
+ if (FAILED(hr)) return ;
+
+ // now fill in the values
+ CString name, val;
+ LVITEM i;
+ int item;
+
+ i.mask = LVIF_TEXT;
+ i.iSubItem = 0;
+
+ // Duration
+ i.pszText = _T("Duration"); i.iItem = 0;
+ MakeNiceTime(info.duration * 1000, val);
+ item = ListView_InsertItem(ITEM(IDC_LIST_CONTENT), &i);
+ ListView_SetItemText(ITEM(IDC_LIST_CONTENT), item, 1, val.GetBuffer());
+
+ // Stream version
+ i.pszText = _T("Stream version"); i.iItem = 1;
+ val.Format(_T("%d"), info.stream_version);
+ item = ListView_InsertItem(ITEM(IDC_LIST_CONTENT), &i);
+ ListView_SetItemText(ITEM(IDC_LIST_CONTENT), item, 1, val.GetBuffer());
+
+ // Stream version
+ i.pszText = _T("Sample rate"); i.iItem = 2;
+ val.Format(_T("%d Hz"), info.sample_rate);
+ item = ListView_InsertItem(ITEM(IDC_LIST_CONTENT), &i);
+ ListView_SetItemText(ITEM(IDC_LIST_CONTENT), item, 1, val.GetBuffer());
+
+ // Channels
+ i.pszText = _T("Channels"); i.iItem = 3;
+ val.Format(_T("%d"), info.channels);
+ item = ListView_InsertItem(ITEM(IDC_LIST_CONTENT), &i);
+ ListView_SetItemText(ITEM(IDC_LIST_CONTENT), item, 1, val.GetBuffer());
+
+ if (info.stream_version == 8) {
+
+ // Channels
+ i.pszText = _T("Frames per packet"); i.iItem = 4;
+ val.Format(_T("%d"), info.block_frames);
+ item = ListView_InsertItem(ITEM(IDC_LIST_CONTENT), &i);
+ ListView_SetItemText(ITEM(IDC_LIST_CONTENT), item, 1, val.GetBuffer());
+
+ }
+}
+
+
+INT_PTR CMPCPropertyPage::OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (uMsg) {
+ case WM_UPDATE_VISUALS: UpdateList(); break;
+ }
+ return __super::OnReceiveMessage(hwnd, uMsg, wParam, lParam);
+}
+
Index: /dsfilters/demux_mpc/src/mpc_prop.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_prop.h (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_prop.h (revision 366)
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+
+#define WM_UPDATE_VISUALS (WM_USER + 1003)
+
+//-----------------------------------------------------------------------------
+//
+// CMPCPropertyPage class
+//
+//-----------------------------------------------------------------------------
+class CMPCPropertyPage : public CBasePropertyPage
+{
+public:
+
+ IMusepackSplitter *demux;
+
+ void UpdateList();
+public:
+ CMPCPropertyPage(LPUNKNOWN lpUnk, HRESULT *phr);
+ virtual ~CMPCPropertyPage();
+ static CUnknown *WINAPI CreateInstance(LPUNKNOWN lpUnk, HRESULT *phr);
+
+ // CBasePropertyPage
+ HRESULT OnConnect(IUnknown *pUnknown);
+ HRESULT OnDisconnect();
+ HRESULT OnActivate();
+ HRESULT OnDeactivate();
+
+ // message
+ INT_PTR OnReceiveMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+};
+
+
Index: /dsfilters/demux_mpc/src/mpc_reg.cpp
===================================================================
--- /dsfilters/demux_mpc/src/mpc_reg.cpp (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_reg.cpp (revision 366)
@@ -0,0 +1,106 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#include "stdafx.h"
+
+#pragma warning(disable: 4996)
+
+//-----------------------------------------------------------------------------
+//
+// Registry Information
+//
+//-----------------------------------------------------------------------------
+
+
+const AMOVIESETUP_MEDIATYPE sudPinTypes[] =
+ {
+ {
+ &MEDIATYPE_Stream,
+ &MEDIASUBTYPE_None
+ },
+ {
+ &MEDIATYPE_Stream,
+ &MEDIASUBTYPE_MusepackStream
+ },
+ {
+ &MEDIATYPE_Audio,
+ &MEDIASUBTYPE_MusepackPacket
+ }
+ };
+
+const AMOVIESETUP_PIN psudPins[] =
+ {
+ {
+ L"Input",
+ FALSE, // bRendered
+ FALSE, // bOutput
+ FALSE, // bZero
+ FALSE, // bMany
+ &CLSID_NULL, // clsConnectsToFilter
+ NULL, // strConnectsToPin
+ 2, // nTypes
+ &sudPinTypes[0] // lpTypes
+ }
+ ,
+ {
+ L"Output", // strName
+ FALSE, // bRendered
+ TRUE, // bOutput
+ FALSE, // bZero
+ TRUE, // bMany
+ &CLSID_NULL, // clsConnectsToFilter
+ NULL, // strConnectsToPin
+ 1, // nTypes
+ &sudPinTypes[2] // lpTypes
+ }
+ };
+
+
+const AMOVIESETUP_FILTER sudMPCDemuxer =
+ {
+ &CLSID_MusepackDemuxer, // clsID
+ L"MONOGRAM Musepack Splitter", // strName
+ MERIT_NORMAL, // dwMerit
+ 2, // nPins
+ psudPins // lpPin
+ };
+
+CFactoryTemplate g_Templates[]=
+ {
+ {
+ L"MONOGRAM Musepack Splitter",
+ &CLSID_MusepackDemuxer,
+ CMPCDemux::CreateInstance,
+ NULL,
+ &sudMPCDemuxer
+ },
+ {
+ L"MONOGRAM Musepack Splitter",
+ &CLSID_MusepackDemuxPage,
+ CMPCPropertyPage::CreateInstance
+ }
+ };
+
+int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
+
+
+//-----------------------------------------------------------------------------
+//
+// DLL Entry Points
+//
+//-----------------------------------------------------------------------------
+
+STDAPI DllRegisterServer()
+{
+ return AMovieDllRegisterServer2(TRUE);
+}
+
+STDAPI DllUnregisterServer()
+{
+ return AMovieDllRegisterServer2(FALSE);
+}
+
Index: /dsfilters/demux_mpc/src/mpc_types.h
===================================================================
--- /dsfilters/demux_mpc/src/mpc_types.h (revision 366)
+++ /dsfilters/demux_mpc/src/mpc_types.h (revision 366)
@@ -0,0 +1,70 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+
+// {C3E2E983-0198-4f73-9E5C-8365BB4C4131}
+static const GUID CLSID_MusepackDemuxer =
+{ 0xc3e2e983, 0x198, 0x4f73, { 0x9e, 0x5c, 0x83, 0x65, 0xbb, 0x4c, 0x41, 0x31 } };
+
+// {7E563A5E-12F1-45c1-A29F-032E21C2F7FC}
+static const GUID CLSID_MusepackDemuxPage =
+{ 0x7e563a5e, 0x12f1, 0x45c1, { 0xa2, 0x9f, 0x3, 0x2e, 0x21, 0xc2, 0xf7, 0xfc } };
+
+
+//-----------------------------------------------------------------------------
+//
+// Custom Media Types
+//
+//-----------------------------------------------------------------------------
+
+/*
+ The demuxer may connect with pull-mode source filters that may have
+ mechanism to identify file type. File Source (Async.) can do this
+ so we use MEDIATYPE_Stream/MEDIASUBTYPE_MusepackStream in such cases.
+ We will also accept unknown streams.
+
+ Demuxer itself must specify output type so the decoder can connect
+ properly. For output pin the demuxer will use
+ MEDIATYPE_Audio/MEDIASUBTYPE_MusepackPacket.
+*/
+
+// {0D2657B6-13B3-4c9b-AC9F-2EE055C51755}
+static const GUID MEDIASUBTYPE_MusepackPacket =
+{ 0xd2657b6, 0x13b3, 0x4c9b, { 0xac, 0x9f, 0x2e, 0xe0, 0x55, 0xc5, 0x17, 0x55 } };
+
+// {229F9AD7-2F4D-4b45-B858-A3F434E7179A}
+static const GUID MEDIASUBTYPE_MusepackStream =
+{ 0x229f9ad7, 0x2f4d, 0x4b45, { 0xb8, 0x58, 0xa3, 0xf4, 0x34, 0xe7, 0x17, 0x9a } };
+
+// {5751D1E7-D444-4c19-812C-A47352EDE8D2}
+static const GUID IID_IMusepackSplitter =
+{ 0x5751d1e7, 0xd444, 0x4c19, { 0x81, 0x2c, 0xa4, 0x73, 0x52, 0xed, 0xe8, 0xd2 } };
+
+
+struct MPC_File_Info
+{
+ int stream_version; // 7, 8
+ double duration; // in seconds
+ int sample_rate;
+ int channels;
+ int block_frames; // frames per audio packet
+};
+
+
+
+DECLARE_INTERFACE_(IMusepackSplitter, IUnknown)
+{
+ STDMETHOD(GetFileInfo)(MPC_File_Info *info) PURE;
+ STDMETHOD(SetPropertyPageWindow)(HWND wnd) PURE;
+};
+
+
+
+
+
Index: /dsfilters/demux_mpc/src/stdafx.h
===================================================================
--- /dsfilters/demux_mpc/src/stdafx.h (revision 366)
+++ /dsfilters/demux_mpc/src/stdafx.h (revision 366)
@@ -0,0 +1,61 @@
+//-----------------------------------------------------------------------------
+//
+// Musepack Demuxer
+//
+// Author : Igor Janos
+//
+//-----------------------------------------------------------------------------
+#pragma once
+
+#pragma warning(disable: 4996)
+
+// Modify the following defines if you have to target a platform prior to the ones specified below.
+// Refer to MSDN for the latest info on corresponding values for different platforms.
+#ifndef WINVER // Allow use of features specific to Windows XP or later.
+#define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
+#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
+#endif
+
+#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
+#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
+#endif
+
+#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
+#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
+#endif
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
+#endif
+
+#include
+#include // MFC core and standard components
+#include // MFC extensions
+#ifndef _AFX_NO_OLE_SUPPORT
+#include // MFC support for Internet Explorer 4 Common Controls
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include // MFC support for Windows Common Controls
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include "bits.h"
+#include "mpc_types.h"
+#include "mpc_file.h"
+#include "mpc_pin.h"
+#include "mpc_filter.h"
+#include "mpc_prop.h"
+
Index: /dsfilters/how-to-compile.txt
===================================================================
--- /dsfilters/how-to-compile.txt (revision 366)
+++ /dsfilters/how-to-compile.txt (revision 366)
@@ -0,0 +1,16 @@
+These filters have been developed under Visual Studio 2005 SP1.
+With installed Vista Platform SDK which contains baseclasses
+for DirectShow filters.
+
+All filters link against 2 libraries which need to be compiled first
+from platform SDK:
+1. strmbasdu.lib - debug version of baseclasses. compiled with unicode support.
+2. strmbaseu.lib - release version of baseclasses. also compiled with unicode support.
+
+I have decided to include the libs I use, which also have
+patched support for MFC.
+
+In time I will add patched files as well as projects for VS 2003.
+
+
+Igor.