diff options
Diffstat (limited to 'ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP')
-rw-r--r-- | ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP | 586 |
1 files changed, 586 insertions, 0 deletions
diff --git a/ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP b/ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP new file mode 100644 index 0000000..03b418f --- /dev/null +++ b/ports/MSVC++/CMP3Stream/SOURCE/SourceFilter_MP3Stream.CPP @@ -0,0 +1,586 @@ +// ------------------------------------------------------------------------------------------------ + +#include <IIEP_Def.H> + +#include <CORE/SourceFilter_MP3.H> + +// ------------------------------------------------------------------------------------------------ + +extern BYTE g_ucWaveHeader[WAVE_HEADER_LENGTH]; + +// ------------------------------------------------------------------------------------------------ +// name: CMP3Stream() +// desc: +// ------------------------------------------------------------------------------------------------ + +static size_t read_sub(int fd, void *pBuf, size_t nSize) +{ + if (fd) + { + IIEP::CMP3Stream *pcoStream = (IIEP::CMP3Stream *) fd; + + return pcoStream -> ReadFile(pBuf, nSize); + } + + return 0; +} + +// ------------------------------------------------------------------------------------------------ +// name: CMP3Stream() +// desc: +// ------------------------------------------------------------------------------------------------ + +static off_t seek_sub(int fd, off_t nOffset, int iOrigin) +{ + if (fd) + { + IIEP::CMP3Stream *pcoStream = (IIEP::CMP3Stream *) fd; + + return pcoStream -> SeekFile(nOffset, iOrigin); + } + + return 0; +} + +// ------------------------------------------------------------------------------------------------ +// name: CMP3Stream() +// desc: +// ------------------------------------------------------------------------------------------------ + +IIEP::CMP3Stream::CMP3Stream(void) +{ + m_dwKBPerSec = INFINITE; + m_dwTimeStart = 0; + + m_pcoMH = 0; + + m_dwTotalBlocks = 0; + m_dwAlignment = 4; + + m_dwLength = 0; + m_dwPosition = 0; + + memcpy(m_ucHeader, g_ucWaveHeader, WAVE_HEADER_LENGTH); + + m_dwDataBufPos = 0; + m_dwDataBufLen = 0; + + m_bSeekFlag = false; +} + +// ------------------------------------------------------------------------------------------------ +// name: ~CMP3Stream() +// desc: +// ------------------------------------------------------------------------------------------------ + +IIEP::CMP3Stream::~CMP3Stream(void) +{ + Close(); +} + +// ------------------------------------------------------------------------------------------------ +// name: SetSeekFlag() +// desc: called by IIEP::CPlayer::SetMediaPosition(QWORD qwPosition) +// ------------------------------------------------------------------------------------------------ + +void IIEP::CMP3Stream::SetSeekFlag(void) +{ + m_bSeekFlag = true; +} + +// ------------------------------------------------------------------------------------------------ +// name: Open() +// desc: +// ------------------------------------------------------------------------------------------------ + +bool IIEP::CMP3Stream::Open(const WORD *pcwsFileName, CMediaType &coMT, DWORD dwKBPerSec) +{ + Close(); + + // + + if (MPG123_OK != mpg123_init()) + { + goto OPEN_FAIL; + } + + m_pcoMH = mpg123_new(NULL, NULL); + + if (0 == m_pcoMH) + { + goto OPEN_FAIL; + } + + if (false == OpenFile(pcwsFileName)) + { + goto OPEN_FAIL; + } + + if (MPG123_OK != mpg123_replace_reader(m_pcoMH, read_sub, seek_sub)) + { + goto OPEN_FAIL; + } + + if (MPG123_OK != mpg123_open_fd(m_pcoMH, (int) this)) + { + goto OPEN_FAIL; + } + + long nRate; + int iChannels; + int iEncoding; + + if (MPG123_OK != mpg123_getformat(m_pcoMH, &nRate, &iChannels, &iEncoding)) + { + goto OPEN_FAIL; + } + + // Ensure that this output format will not change (it could, when we allow it) + + mpg123_format_none(m_pcoMH); + mpg123_format(m_pcoMH, nRate, iChannels, iEncoding); + + // scan & get total samples + + mpg123_scan(m_pcoMH); + + off_t nOff = mpg123_length(m_pcoMH); + + if (nOff < 0) + { + goto OPEN_FAIL; + } + + m_dwTotalBlocks = (DWORD) nOff; + + // set other format + + m_dwAlignment = iChannels * 2; + + if (0 == m_dwAlignment) + { + m_dwAlignment = 4; + } + + m_dwLength = m_dwTotalBlocks * m_dwAlignment + WAVE_HEADER_LENGTH; + + WORD wChannels = (WORD ) iChannels; + DWORD dwSamplesPerSec = (DWORD) nRate; + DWORD dwAvgBytesPerSec = m_dwAlignment * dwSamplesPerSec; + WORD wBlockAlign = (WORD ) m_dwAlignment; + WORD wBitsPerSample = 16; + + PWORD pwData; + PDWORD pdwData; + + pdwData = (PDWORD) &m_ucHeader[0x04]; + *pdwData = m_dwTotalBlocks * m_dwAlignment + WAVE_HEADER_LENGTH - 8; + + pwData = (PWORD) &m_ucHeader[0x16]; + *pwData = wChannels; + + pdwData = (PDWORD) &m_ucHeader[0x18]; + *pdwData = dwSamplesPerSec; + + pdwData = (PDWORD) &m_ucHeader[0x1C]; + *pdwData = dwAvgBytesPerSec; + + pwData = (PWORD) &m_ucHeader[0x20]; + *pwData = wBlockAlign; + + pwData = (PWORD) &m_ucHeader[0x22]; + *pwData = wBitsPerSample; + + pdwData = (PDWORD) &m_ucHeader[0x28]; + *pdwData = m_dwTotalBlocks * m_dwAlignment; + + coMT.majortype = MEDIATYPE_Stream; + coMT.subtype = MEDIASUBTYPE_WAVE; + + SetPointer(0); + + m_dwTimeStart = ::timeGetTime(); + + return true; + +OPEN_FAIL: + + Close(); + + return false; +} + +// ------------------------------------------------------------------------------------------------ +// name: Close() +// desc: +// ------------------------------------------------------------------------------------------------ + +void IIEP::CMP3Stream::Close(void) +{ + m_coFileIn.Close(); + + if (m_pcoMH) + { + mpg123_close (m_pcoMH); + mpg123_delete(m_pcoMH); + + m_pcoMH = 0; + } + + mpg123_exit(); + + m_dwTimeStart = 0; + m_dwTotalBlocks = 0; + + m_dwLength = 0; + m_dwPosition = 0; + + m_bSeekFlag = false; + + m_nDataBegin = 0; + m_nDataTotal = 0; +} + +// ------------------------------------------------------------------------------------------------ +// name: SetPointer() +// desc: +// ------------------------------------------------------------------------------------------------ + +HRESULT IIEP::CMP3Stream::SetPointer(LONGLONG llPos) +{ + if (llPos < 0 || llPos > (LONGLONG) m_dwLength) + { + return S_FALSE; + } + + m_dwPosition = (DWORD) llPos; + + if (llPos < WAVE_HEADER_LENGTH) + { + mpg123_seek(m_pcoMH, 0, SEEK_SET); + + m_dwDataBufLen = 0; + } + else + { + if (m_bSeekFlag && m_dwAlignment > 0) + { + m_bSeekFlag = false; + + mpg123_seek(m_pcoMH, (long) (m_dwPosition - WAVE_HEADER_LENGTH) / m_dwAlignment, SEEK_SET); + + m_dwDataBufLen = 0; + } + } + + return S_OK; +} + +// ------------------------------------------------------------------------------------------------ +// name: Read() +// desc: +// ------------------------------------------------------------------------------------------------ + +HRESULT IIEP::CMP3Stream::Read(PBYTE pucBuffer, + DWORD dwBytesToRead, + BOOL bAlign, + LPDWORD pdwBytesRead) +{ + if (0 == m_pcoMH) return S_FALSE; + + CAutoLock lck(&m_csLock); + + DWORD dwReadLength; + + // wait until the bytes are here + + DWORD dwTime = ::timeGetTime(); + + if (m_dwPosition + dwBytesToRead > m_dwLength) + { + dwReadLength = m_dwLength - m_dwPosition; + } + else + { + dwReadLength = dwBytesToRead; + } + + DWORD dwTimeToArrive = (m_dwPosition + dwReadLength) / m_dwKBPerSec; + + if (dwTime - m_dwTimeStart < dwTimeToArrive) + { + ::Sleep(dwTimeToArrive - dwTime + m_dwTimeStart); + } + + // read data + + DWORD dwRead = 0; + + if (m_dwPosition < WAVE_HEADER_LENGTH) + { + DWORD dwPatchLen = WAVE_HEADER_LENGTH - m_dwPosition; + + if (dwReadLength < dwPatchLen) + { + dwPatchLen = dwReadLength; + } + + memcpy(pucBuffer, m_ucHeader + m_dwPosition, dwPatchLen); + + m_dwPosition += dwPatchLen; + dwReadLength -= dwPatchLen; + + pucBuffer += dwPatchLen; + dwRead += dwPatchLen; + } + + if (dwReadLength > 0) + { + while (m_dwDataBufLen < dwReadLength) + { + if (m_dwDataBufLen > 0) + { + memcpy(pucBuffer, m_ucDataBuffer + m_dwDataBufPos, m_dwDataBufLen); + + dwRead += m_dwDataBufLen; + + dwReadLength -= m_dwDataBufLen; + + pucBuffer += m_dwDataBufLen; + m_dwDataBufPos += m_dwDataBufLen; + m_dwDataBufLen = 0; + } + + if (DecodeFrame() == false) break; + } + + if (dwReadLength > 0) + { + if (m_dwDataBufLen >= dwReadLength) + { + memcpy(pucBuffer, m_ucDataBuffer + m_dwDataBufPos, dwReadLength); + + dwRead += dwReadLength; + + m_dwDataBufPos += dwReadLength; + m_dwDataBufLen -= dwReadLength; + } + } + } + + m_dwPosition += dwRead; + *pdwBytesRead = dwRead; + + return S_OK; +} + +// ------------------------------------------------------------------------------------------------ +// name: Size() +// desc: +// ------------------------------------------------------------------------------------------------ + +LONGLONG IIEP::CMP3Stream::Size(LONGLONG *pSizeAvailable) +{ +// LONGLONG llCurrentAvailable = Int32x32To64((::timeGetTime() - m_dwTimeStart), m_dwKBPerSec); + LONGLONG llLength = (LONGLONG) m_dwTotalBlocks * m_dwAlignment + WAVE_HEADER_LENGTH; + + if (pSizeAvailable) + { +// *pSizeAvailable = min(llLength, llCurrentAvailable); + *pSizeAvailable = llLength; + } + + return llLength; +} + +// ------------------------------------------------------------------------------------------------ +// name: Alignment() +// desc: +// ------------------------------------------------------------------------------------------------ + +DWORD IIEP::CMP3Stream::Alignment(void) +{ + return m_dwAlignment; +} + +// ------------------------------------------------------------------------------------------------ +// name: Lock() +// desc: +// ------------------------------------------------------------------------------------------------ + +void IIEP::CMP3Stream::Lock(void) +{ + m_csLock.Lock(); +} + +// ------------------------------------------------------------------------------------------------ +// name: Unlock() +// desc: +// ------------------------------------------------------------------------------------------------ + +void IIEP::CMP3Stream::Unlock(void) +{ + m_csLock.Unlock(); +} + +// ------------------------------------------------------------------------------------------------ +// name: DecodeFrame() +// desc: +// ------------------------------------------------------------------------------------------------ + +bool IIEP::CMP3Stream::DecodeFrame(void) +{ + if (0 == m_dwDataBufLen) + { + m_dwDataBufPos = 0; + } + + if (m_dwDataBufPos + m_dwDataBufLen + MP3_DECODE_LEN > MP3_DECODE_BUF_LEN) + { + return true; + } + + size_t nBytesRead = 0; + + mpg123_read(m_pcoMH, m_ucDataBuffer + m_dwDataBufPos + m_dwDataBufLen, MP3_DECODE_LEN, &nBytesRead); + + m_dwDataBufLen += (DWORD) nBytesRead; + + return (m_dwDataBufLen > 0); +} + +// ------------------------------------------------------------------------------------------------ +// name: OpenFile() +// desc: +// ------------------------------------------------------------------------------------------------ + +bool IIEP::CMP3Stream::OpenFile(const WORD *pcwsFileName) +{ + if (m_coFileIn.Open(pcwsFileName)) + { + m_nDataBegin = 0; + m_nDataTotal = m_coFileIn.GetFileSize(); + + // check ID3 Tag V2.x + + BYTE ucBuffer[8]; + bool bFound; + +TRY_ID3_AGAIN: + + bFound = false; + + if (6 == m_coFileIn.Read(ucBuffer, 6)) + { + if (ucBuffer[0] == 'I' && + ucBuffer[1] == 'D' && + ucBuffer[2] == '3') + { + bFound = true; + + DWORD dwHeaderSize; + + if (m_coFileIn.ReadInverseDW(dwHeaderSize)) + { + dwHeaderSize = ((dwHeaderSize & 0x7F000000) >> 3) + + ((dwHeaderSize & 0x007F0000) >> 2) + + ((dwHeaderSize & 0x00007F00) >> 1) + + ((dwHeaderSize & 0x0000007F) ); + + dwHeaderSize += 10; + + m_nDataBegin += dwHeaderSize; + m_nDataTotal -= dwHeaderSize; + + if (ucBuffer[3] >= 0x03) // ID3 Tag version >= 2.3 + { + if (ucBuffer[5] & 0x40) // has extended header + { + if (m_coFileIn.ReadInverseDW(dwHeaderSize)) + { + dwHeaderSize = ((dwHeaderSize & 0x7F000000) >> 3) + + ((dwHeaderSize & 0x007F0000) >> 2) + + ((dwHeaderSize & 0x00007F00) >> 1) + + ((dwHeaderSize & 0x0000007F) ); + + dwHeaderSize += 4; + + m_nDataBegin += dwHeaderSize; + m_nDataTotal -= dwHeaderSize; + } + } + } + } + } + } + + SeekFile(0, SEEK_SET); + + if (bFound) + { + goto TRY_ID3_AGAIN; + } +/* + m_coFileIn.Read(ucBuffer, 2); + + if (ucBuffer[0] != 0xFF || ucBuffer[1] < 0xF0) + { + m_nDataBegin ++; + m_nDataTotal --; + + SeekFile(0, SEEK_SET); + + goto TRY_ID3_AGAIN; + } + + SeekFile(0, SEEK_SET); +*/ + return true; + } + + return false; +} + +// ------------------------------------------------------------------------------------------------ +// name: ReadFile() +// desc: +// ------------------------------------------------------------------------------------------------ + +DWORD IIEP::CMP3Stream::ReadFile(PVOID pBuf, DWORD dwLen) +{ + return m_coFileIn.Read(pBuf, dwLen); +} + +// ------------------------------------------------------------------------------------------------ +// name: SeekFile() +// desc: +// ------------------------------------------------------------------------------------------------ + +long IIEP::CMP3Stream::SeekFile(long nOffset, int iOrigin) +{ + switch (iOrigin) + { + case SEEK_SET: + if (nOffset < 0 || nOffset >= m_nDataTotal) return -1; + break; + + case SEEK_CUR: + nOffset += (m_coFileIn.GetReadPosition() - m_nDataBegin); + if (nOffset < 0 || nOffset >= m_nDataTotal) return -1; + break; + + case SEEK_END: + nOffset = m_nDataTotal - 1 + nOffset; + if (nOffset < 0 || nOffset >= m_nDataTotal) return -1; + break; + } + + if (m_coFileIn.Seek(nOffset + m_nDataBegin, SEEK_SET)) + { + return nOffset; + } + + return -1; +} + +// ------------------------------------------------------------------------------------------------
\ No newline at end of file |