mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-28 04:31:06 +00:00
c1a4db611b
Original commit message from CVS: Add monkeyaudio plugin
245 lines
6.4 KiB
C++
245 lines
6.4 KiB
C++
#include "All.h"
|
|
#include "APECompress.h"
|
|
#include IO_HEADER_FILE
|
|
#include "APECompressCreate.h"
|
|
#include "WAVInputSource.h"
|
|
|
|
CAPECompress::CAPECompress()
|
|
{
|
|
m_nBufferHead = 0;
|
|
m_nBufferTail = 0;
|
|
m_nBufferSize = 0;
|
|
m_bBufferLocked = FALSE;
|
|
m_bOwnsOutputIO = FALSE;
|
|
m_pioOutput = NULL;
|
|
|
|
m_spAPECompressCreate.Assign(new CAPECompressCreate());
|
|
|
|
m_pBuffer = NULL;
|
|
}
|
|
|
|
CAPECompress::~CAPECompress()
|
|
{
|
|
SAFE_ARRAY_DELETE(m_pBuffer)
|
|
|
|
if (m_bOwnsOutputIO)
|
|
{
|
|
SAFE_DELETE(m_pioOutput)
|
|
}
|
|
}
|
|
|
|
int CAPECompress::Start(const char * pOutputFilename, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const unsigned char * pHeaderData, int nHeaderBytes)
|
|
{
|
|
m_pioOutput = new IO_CLASS_NAME;
|
|
m_bOwnsOutputIO = TRUE;
|
|
|
|
if (m_pioOutput->Create(pOutputFilename) != 0)
|
|
{
|
|
return ERROR_INVALID_OUTPUT_FILE;
|
|
}
|
|
|
|
m_spAPECompressCreate->Start(m_pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel,
|
|
pHeaderData, nHeaderBytes);
|
|
|
|
SAFE_ARRAY_DELETE(m_pBuffer)
|
|
m_nBufferSize = m_spAPECompressCreate->GetFullFrameBytes();
|
|
m_pBuffer = new unsigned char [m_nBufferSize];
|
|
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CAPECompress::StartEx(CIO * pioOutput, const WAVEFORMATEX * pwfeInput, int nMaxAudioBytes, int nCompressionLevel, const unsigned char * pHeaderData, int nHeaderBytes)
|
|
{
|
|
m_pioOutput = pioOutput;
|
|
m_bOwnsOutputIO = FALSE;
|
|
|
|
m_spAPECompressCreate->Start(m_pioOutput, pwfeInput, nMaxAudioBytes, nCompressionLevel,
|
|
pHeaderData, nHeaderBytes);
|
|
|
|
SAFE_ARRAY_DELETE(m_pBuffer)
|
|
m_nBufferSize = m_spAPECompressCreate->GetFullFrameBytes();
|
|
m_pBuffer = new unsigned char [m_nBufferSize];
|
|
memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CAPECompress::GetBufferBytesAvailable()
|
|
{
|
|
return m_nBufferSize - m_nBufferTail;
|
|
}
|
|
|
|
int CAPECompress::UnlockBuffer(int nBytesAdded, BOOL bProcess)
|
|
{
|
|
if (m_bBufferLocked == FALSE)
|
|
return -1;
|
|
|
|
m_nBufferTail += nBytesAdded;
|
|
m_bBufferLocked = FALSE;
|
|
|
|
if (bProcess)
|
|
{
|
|
int nRetVal = ProcessBuffer();
|
|
if (nRetVal != 0) { return nRetVal; }
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned char * CAPECompress::LockBuffer(int * pBytesAvailable)
|
|
{
|
|
if (m_pBuffer == NULL) { return NULL; }
|
|
|
|
if (m_bBufferLocked)
|
|
return NULL;
|
|
|
|
m_bBufferLocked = TRUE;
|
|
|
|
if (pBytesAvailable)
|
|
*pBytesAvailable = GetBufferBytesAvailable();
|
|
|
|
return &m_pBuffer[m_nBufferTail];
|
|
}
|
|
|
|
int CAPECompress::AddData(unsigned char * pData, int nBytes)
|
|
{
|
|
if (m_pBuffer == NULL) return ERROR_INSUFFICIENT_MEMORY;
|
|
|
|
int nBytesDone = 0;
|
|
|
|
while (nBytesDone < nBytes)
|
|
{
|
|
// lock the buffer
|
|
int nBytesAvailable = 0;
|
|
unsigned char * pBuffer = LockBuffer(&nBytesAvailable);
|
|
if (pBuffer == NULL || nBytesAvailable <= 0)
|
|
return -1;
|
|
|
|
// calculate how many bytes to copy and add that much to the buffer
|
|
int nBytesToProcess = min(nBytesAvailable, nBytes - nBytesDone);
|
|
memcpy(pBuffer, &pData[nBytesDone], nBytesToProcess);
|
|
|
|
// unlock the buffer (fail if not successful)
|
|
int nRetVal = UnlockBuffer(nBytesToProcess);
|
|
if (nRetVal != ERROR_SUCCESS)
|
|
return nRetVal;
|
|
|
|
// update our progress
|
|
nBytesDone += nBytesToProcess;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
int CAPECompress::Finish(unsigned char * pTerminatingData, int nTerminatingBytes, int nWAVTerminatingBytes)
|
|
{
|
|
RETURN_ON_ERROR(ProcessBuffer(TRUE))
|
|
return m_spAPECompressCreate->Finish(pTerminatingData, nTerminatingBytes, nWAVTerminatingBytes);
|
|
}
|
|
|
|
int CAPECompress::Kill()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int CAPECompress::ProcessBuffer(BOOL bFinalize)
|
|
{
|
|
if (m_pBuffer == NULL) { return -1; }
|
|
|
|
try
|
|
{
|
|
// process as much as possible
|
|
int nThreshold = (bFinalize) ? 0 : m_spAPECompressCreate->GetFullFrameBytes();
|
|
|
|
while ((m_nBufferTail - m_nBufferHead) >= nThreshold)
|
|
{
|
|
int nFrameBytes = min(m_spAPECompressCreate->GetFullFrameBytes(), m_nBufferTail - m_nBufferHead);
|
|
|
|
if (nFrameBytes == 0)
|
|
break;
|
|
|
|
int nRetVal = m_spAPECompressCreate->EncodeFrame(&m_pBuffer[m_nBufferHead], nFrameBytes);
|
|
if (nRetVal != 0) { return nRetVal; }
|
|
|
|
m_nBufferHead += nFrameBytes;
|
|
}
|
|
|
|
// shift the buffer
|
|
if (m_nBufferHead != 0)
|
|
{
|
|
int nBytesLeft = m_nBufferTail - m_nBufferHead;
|
|
|
|
if (nBytesLeft != 0)
|
|
memmove(m_pBuffer, &m_pBuffer[m_nBufferHead], nBytesLeft);
|
|
|
|
m_nBufferTail -= m_nBufferHead;
|
|
m_nBufferHead = 0;
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int CAPECompress::AddDataFromInputSource(CInputSource * pInputSource, int nMaxBytes, int * pBytesAdded)
|
|
{
|
|
// error check the parameters
|
|
if (pInputSource == NULL) return ERROR_BAD_PARAMETER;
|
|
|
|
// initialize
|
|
if (pBytesAdded) *pBytesAdded = 0;
|
|
|
|
// lock the buffer
|
|
int nBytesAvailable = 0;
|
|
unsigned char * pBuffer = LockBuffer(&nBytesAvailable);
|
|
if ((pBuffer == NULL) || (nBytesAvailable == 0))
|
|
return ERROR_INSUFFICIENT_MEMORY;
|
|
|
|
// calculate the 'ideal' number of bytes
|
|
unsigned int nBytesRead = 0;
|
|
|
|
int nIdealBytes = m_spAPECompressCreate->GetFullFrameBytes() - (m_nBufferTail - m_nBufferHead);
|
|
if (nIdealBytes > 0)
|
|
{
|
|
// get the data
|
|
int nBytesToAdd = nBytesAvailable;
|
|
|
|
if (nMaxBytes > 0)
|
|
{
|
|
if (nBytesToAdd > nMaxBytes) nBytesToAdd = nMaxBytes;
|
|
}
|
|
|
|
if (nBytesToAdd > nIdealBytes) nBytesToAdd = nIdealBytes;
|
|
|
|
// always make requests along block boundaries
|
|
while ((nBytesToAdd % m_wfeInput.nBlockAlign) != 0)
|
|
nBytesToAdd--;
|
|
|
|
int nBlocksToAdd = nBytesToAdd / m_wfeInput.nBlockAlign;
|
|
|
|
// get data
|
|
int nBlocksAdded = 0;
|
|
int nRetVal = pInputSource->GetData(pBuffer, nBlocksToAdd, &nBlocksAdded);
|
|
if (nRetVal != 0)
|
|
return ERROR_IO_READ;
|
|
else
|
|
nBytesRead = (nBlocksAdded * m_wfeInput.nBlockAlign);
|
|
|
|
// store the bytes read
|
|
if (pBytesAdded)
|
|
*pBytesAdded = nBytesRead;
|
|
}
|
|
|
|
// unlock the data and process
|
|
int nRetVal = UnlockBuffer(nBytesRead, TRUE);
|
|
if (nRetVal != 0)
|
|
{
|
|
return nRetVal;
|
|
}
|
|
|
|
return 0;
|
|
}
|