vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / media / plugins / ape_reader / MAClib / APECompressCore.cpp
blobf260d3c9b0318ac6d824fe6b7050155a0c2f2d3e
1 #include "All.h"
2 #include "APECompressCore.h"
4 #include "BitArray.h"
5 #include "Prepare.h"
6 #include "NewPredictor.h"
8 CAPECompressCore::CAPECompressCore(CIO * pIO, const WAVEFORMATEX * pwfeInput, int nMaxFrameBlocks, int nCompressionLevel)
10 m_spBitArray.Assign(new CBitArray(pIO));
11 m_spDataX.Assign(new int [nMaxFrameBlocks], TRUE);
12 m_spDataY.Assign(new int [nMaxFrameBlocks], TRUE);
13 m_spTempData.Assign(new int [nMaxFrameBlocks], TRUE);
14 m_spPrepare.Assign(new CPrepare);
15 m_spPredictorX.Assign(new CPredictorCompressNormal(nCompressionLevel));
16 m_spPredictorY.Assign(new CPredictorCompressNormal(nCompressionLevel));
18 memcpy(&m_wfeInput, pwfeInput, sizeof(WAVEFORMATEX));
19 m_nPeakLevel = 0;
22 CAPECompressCore::~CAPECompressCore()
26 int CAPECompressCore::EncodeFrame(const void * pInputData, int nInputBytes)
28 // variables
29 const int nInputBlocks = nInputBytes / m_wfeInput.nBlockAlign;
30 int nSpecialCodes = 0;
32 // always start a new frame on a byte boundary
33 m_spBitArray->AdvanceToByteBoundary();
35 // do the preparation stage
36 RETURN_ON_ERROR(Prepare(pInputData, nInputBytes, &nSpecialCodes))
38 m_spPredictorX->Flush();
39 m_spPredictorY->Flush();
41 m_spBitArray->FlushState(m_BitArrayStateX);
42 m_spBitArray->FlushState(m_BitArrayStateY);
44 m_spBitArray->FlushBitArray();
46 if (m_wfeInput.nChannels == 2)
48 BOOL bEncodeX = TRUE;
49 BOOL bEncodeY = TRUE;
51 if ((nSpecialCodes & SPECIAL_FRAME_LEFT_SILENCE) &&
52 (nSpecialCodes & SPECIAL_FRAME_RIGHT_SILENCE))
54 bEncodeX = FALSE;
55 bEncodeY = FALSE;
58 if (nSpecialCodes & SPECIAL_FRAME_PSEUDO_STEREO)
60 bEncodeY = FALSE;
63 if (bEncodeX && bEncodeY)
65 int nLastX = 0;
66 for (int z = 0; z < nInputBlocks; z++)
68 m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z], nLastX), m_BitArrayStateY);
69 m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z], m_spDataY[z]), m_BitArrayStateX);
71 nLastX = m_spDataX[z];
74 else if (bEncodeX)
76 for (int z = 0; z < nInputBlocks; z++)
78 RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
81 else if (bEncodeY)
83 for (int z = 0; z < nInputBlocks; z++)
85 RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorY->CompressValue(m_spDataY[z]), m_BitArrayStateY))
89 else if (m_wfeInput.nChannels == 1)
91 if (!(nSpecialCodes & SPECIAL_FRAME_MONO_SILENCE))
93 for (int z = 0; z < nInputBlocks; z++)
95 RETURN_ON_ERROR(m_spBitArray->EncodeValue(m_spPredictorX->CompressValue(m_spDataX[z]), m_BitArrayStateX))
100 m_spBitArray->Finalize();
102 // return success
103 return 0;
106 int CAPECompressCore::Prepare(const void * pInputData, int nInputBytes, int * pSpecialCodes)
108 // variable declares
109 *pSpecialCodes = 0;
110 unsigned int nCRC = 0;
112 // do the preparation
113 RETURN_ON_ERROR(m_spPrepare->Prepare((unsigned char *) pInputData, nInputBytes, &m_wfeInput, m_spDataX, m_spDataY,
114 &nCRC, pSpecialCodes, &m_nPeakLevel))
116 // store the CRC
117 RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(nCRC))
119 // store any special codes
120 if (*pSpecialCodes != 0)
122 RETURN_ON_ERROR(m_spBitArray->EncodeUnsignedLong(*pSpecialCodes))
125 return 0;