diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj
index 3248aba4d2..b55c9b4c13 100644
--- a/Core/Core.vcxproj
+++ b/Core/Core.vcxproj
@@ -233,6 +233,7 @@
+
@@ -411,6 +412,7 @@
+
diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters
index caec603430..7172448df5 100644
--- a/Core/Core.vcxproj.filters
+++ b/Core/Core.vcxproj.filters
@@ -430,6 +430,9 @@
HW
+
+ HW
+
@@ -795,6 +798,9 @@
HW
+
+ HW
+
@@ -802,4 +808,4 @@
-
+
\ No newline at end of file
diff --git a/Core/HW/MpegDemux.cpp b/Core/HW/MpegDemux.cpp
new file mode 100644
index 0000000000..91201a3eb7
--- /dev/null
+++ b/Core/HW/MpegDemux.cpp
@@ -0,0 +1,192 @@
+#include "MpegDemux.h"
+
+const int PACKET_START_CODE_MASK = 0xffffff00;
+const int PACKET_START_CODE_PREFIX = 0x00000100;
+
+const int SEQUENCE_START_CODE = 0x000001b3;
+const int EXT_START_CODE = 0x000001b5;
+const int SEQUENCE_END_CODE = 0x000001b7;
+const int GOP_START_CODE = 0x000001b8;
+const int ISO_11172_END_CODE = 0x000001b9;
+const int PACK_START_CODE = 0x000001ba;
+const int SYSTEM_HEADER_START_CODE = 0x000001bb;
+const int PROGRAM_STREAM_MAP = 0x000001bc;
+const int PRIVATE_STREAM_1 = 0x000001bd;
+const int PADDING_STREAM = 0x000001be;
+const int PRIVATE_STREAM_2 = 0x000001bf;
+
+MpegDemux::MpegDemux(u8* buffer, int size, int offset)
+{
+ m_buf = buffer;
+ m_len = size;
+ m_index = offset;
+ m_audioStream = 0;
+ m_audiopos = 0;
+ m_audioChannel = -1;
+ m_readSize = 0;
+}
+
+
+MpegDemux::~MpegDemux(void)
+{
+ if (m_audioStream)
+ delete [] m_audioStream;
+}
+
+void MpegDemux::setReadSize(int readSize)
+{
+ m_readSize = readSize;
+}
+
+int MpegDemux::readPesHeader(PesHeader &pesHeader, int length, int startCode) {
+ int c = 0;
+ while (length > 0) {
+ c = read8();
+ length--;
+ if (c != 0xFF) {
+ break;
+ }
+ }
+ if ((c & 0xC0) == 0x40) {
+ read8();
+ c = read8();
+ length -= 2;
+ }
+ pesHeader.pts = 0;
+ pesHeader.dts = 0;
+ if ((c & 0xE0) == 0x20) {
+ pesHeader.dts = pesHeader.pts = readPts(c);
+ length -= 4;
+ if ((c & 0x10) != 0) {
+ pesHeader.dts = readPts();
+ length -= 5;
+ }
+ } else if ((c & 0xC0) == 0x80) {
+ int flags = read8();
+ int headerLength = read8();
+ length -= 2;
+ length -= headerLength;
+ if ((flags & 0x80) != 0) {
+ pesHeader.dts = pesHeader.pts = readPts();
+ headerLength -= 5;
+ if ((flags & 0x40) != 0) {
+ pesHeader.dts = readPts();
+ headerLength -= 5;
+ }
+ }
+ if ((flags & 0x3F) != 0 && headerLength == 0) {
+ flags &= 0xC0;
+ }
+ if ((flags & 0x01) != 0) {
+ int pesExt = read8();
+ headerLength--;
+ int skip = (pesExt >> 4) & 0x0B;
+ skip += skip & 0x09;
+ if ((pesExt & 0x40) != 0 || skip > headerLength) {
+ pesExt = skip = 0;
+ }
+ this->skip(skip);
+ headerLength -= skip;
+ if ((pesExt & 0x01) != 0) {
+ int ext2Length = read8();
+ headerLength--;
+ if ((ext2Length & 0x7F) != 0) {
+ int idExt = read8();
+ headerLength--;
+ if ((idExt & 0x80) == 0) {
+ startCode = ((startCode & 0xFF) << 8) | idExt;
+ }
+ }
+ }
+ }
+ skip(headerLength);
+ }
+ if (startCode == PRIVATE_STREAM_1) {
+ int channel = read8();
+ pesHeader.channel = channel;
+ length--;
+ if (channel >= 0x80 && channel <= 0xCF) {
+ // Skip audio header
+ skip(3);
+ length -= 3;
+ if (channel >= 0xB0 && channel <= 0xBF) {
+ skip(1);
+ length--;
+ }
+ } else {
+ // PSP audio has additional 3 bytes in header
+ skip(3);
+ length -= 3;
+ }
+ }
+ return length;
+}
+
+int MpegDemux::demuxStream(bool bdemux, int startCode, int channel)
+{
+ int length = read16();
+ if (bdemux) {
+ PesHeader pesHeader(channel);
+ length = readPesHeader(pesHeader, length, startCode);
+ if (pesHeader.channel == channel || channel < 0) {
+ channel = pesHeader.channel;
+ memcpy(m_audioStream + m_audiopos, m_buf + m_index, length);
+ m_audiopos += length;
+ }
+ skip(length);
+ } else {
+ skip(length);
+ }
+ return channel;
+}
+
+void MpegDemux::demux()
+{
+ if (!m_audioStream)
+ m_audioStream = new u8[m_len - m_index];
+ while (m_index < m_len)
+ {
+ if (m_readSize != m_len && m_index + 2048 > m_readSize)
+ return;
+ // Search for start code
+ int startCode = 0xFF;
+ while ((startCode & PACKET_START_CODE_MASK) != PACKET_START_CODE_PREFIX && !isEOF()) {
+ startCode = (startCode << 8) | read8();
+ }
+ switch (startCode) {
+ case PACK_START_CODE: {
+ skip(10);
+ break;
+ }
+ case SYSTEM_HEADER_START_CODE: {
+ skip(14);
+ break;
+ }
+ case PADDING_STREAM:
+ case PRIVATE_STREAM_2: {
+ int length = read16();
+ skip(length);
+ break;
+ }
+ case PRIVATE_STREAM_1: {
+ // Audio stream
+ m_audioChannel = demuxStream(true, startCode, m_audioChannel);
+ break;
+ }
+ case 0x1E0: case 0x1E1: case 0x1E2: case 0x1E3:
+ case 0x1E4: case 0x1E5: case 0x1E6: case 0x1E7:
+ case 0x1E8: case 0x1E9: case 0x1EA: case 0x1EB:
+ case 0x1EC: case 0x1ED: case 0x1EE: case 0x1EF: {
+ // Video Stream
+ demuxStream(false, startCode, -1);
+ break;
+ }
+ }
+ }
+}
+
+int MpegDemux::getaudioStream(u8** audioStream)
+{
+ *audioStream = m_audioStream;
+ return m_audiopos;
+}
\ No newline at end of file
diff --git a/Core/HW/MpegDemux.h b/Core/HW/MpegDemux.h
new file mode 100644
index 0000000000..5d760a6ae6
--- /dev/null
+++ b/Core/HW/MpegDemux.h
@@ -0,0 +1,63 @@
+// This is a simple version MpegDemux that can get media's audio stream.
+// Thanks to JPCSP project.
+
+#pragma once
+
+#include "../../Globals.h"
+
+class MpegDemux
+{
+public:
+ MpegDemux(u8* buffer, int size, int offset);
+ ~MpegDemux(void);
+
+ void setReadSize(int readSize);
+
+ void demux();
+
+ // return it's size
+ int getaudioStream(u8 **audioStream);
+private:
+ struct PesHeader {
+ long pts;
+ long dts;
+ int channel;
+
+ PesHeader(int chan) {
+ pts = 0;
+ dts = 0;
+ channel = chan;
+ }
+ };
+ int read8() {
+ return m_buf[m_index++] & 0xFF;
+ }
+ int read16() {
+ return (read8() << 8) | read8();
+ }
+ long readPts() {
+ return readPts(read8());
+ }
+ long readPts(int c) {
+ return (((long) (c & 0x0E)) << 29) | ((read16() >> 1) << 15) | (read16() >> 1);
+ }
+ bool isEOF() {
+ return m_index >= m_len;
+ }
+ void skip(int n) {
+ if (n > 0) {
+ m_index += n;
+ }
+ }
+ int readPesHeader(PesHeader &pesHeader, int length, int startCode);
+ int demuxStream(bool bdemux, int startCode, int channel);
+private:
+ int m_index;
+ int m_len;
+ u8* m_buf;
+ u8* m_audioStream;
+ int m_audiopos;
+ int m_audioChannel;
+ int m_readSize;
+};
+