1 //*@@@+++@@@@******************************************************************
2 //
3 // Copyright � Microsoft Corp.
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 //
9 // � Redistributions of source code must retain the above copyright notice,
10 //   this list of conditions and the following disclaimer.
11 // � Redistributions in binary form must reproduce the above copyright notice,
12 //   this list of conditions and the following disclaimer in the documentation
13 //   and/or other materials provided with the distribution.
14 //
15 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 // POSSIBILITY OF SUCH DAMAGE.
26 //
27 //*@@@---@@@@******************************************************************
28 #include "strcodec.h"
29 #include "perfTimer.h"
30 
31 #ifdef MEM_TRACE
32 #define TRACE_MALLOC    1
33 #define TRACE_NEW       0
34 #define TRACE_HEAP      0
35 #include "memtrace.h"
36 #endif
37 
38 //================================================================
39 // Quantization index tables
40 //================================================================
41 const int blkOffset[16] = {0, 64, 16, 80, 128, 192, 144, 208, 32, 96, 48, 112, 160, 224, 176, 240};
42 const int blkOffsetUV[4] = {0, 32, 16, 48};
43 const int blkOffsetUV_422[8] = {0, 64, 16, 80, 32, 96, 48, 112};
44 
45 const int dctIndex[3][16] = { /** permutation matrix tailored to the transform, nothing to do with ZZS **/
46     {0,5,1,6, 10,12,8,14, 2,4,3,7, 9,13,11,15}, //AC 444
47     {0,5,1,6, 10,12,8,14, 2,4,3,7, 9,13,11,15}, //AC 420
48     {0,128,64,208, 32,240,48,224, 16,192,80,144, 112,176,96,160 }, //DC 444
49 };
50 
51 //================================================================
52 // Color conversion index table
53 //================================================================
54 const U8 idxCC[16][16] =
55 {
56     {0x00, 0x01, 0x05, 0x04,  0x40, 0x41, 0x45, 0x44,  0x80, 0x81, 0x85, 0x84,  0xc0, 0xc1, 0xc5, 0xc4, },
57     {0x02, 0x03, 0x07, 0x06,  0x42, 0x43, 0x47, 0x46,  0x82, 0x83, 0x87, 0x86,  0xc2, 0xc3, 0xc7, 0xc6, },
58     {0x0a, 0x0b, 0x0f, 0x0e,  0x4a, 0x4b, 0x4f, 0x4e,  0x8a, 0x8b, 0x8f, 0x8e,  0xca, 0xcb, 0xcf, 0xce, },
59     {0x08, 0x09, 0x0d, 0x0c,  0x48, 0x49, 0x4d, 0x4c,  0x88, 0x89, 0x8d, 0x8c,  0xc8, 0xc9, 0xcd, 0xcc, },
60 
61     {0x10, 0x11, 0x15, 0x14,  0x50, 0x51, 0x55, 0x54,  0x90, 0x91, 0x95, 0x94,  0xd0, 0xd1, 0xd5, 0xd4, },
62     {0x12, 0x13, 0x17, 0x16,  0x52, 0x53, 0x57, 0x56,  0x92, 0x93, 0x97, 0x96,  0xd2, 0xd3, 0xd7, 0xd6, },
63     {0x1a, 0x1b, 0x1f, 0x1e,  0x5a, 0x5b, 0x5f, 0x5e,  0x9a, 0x9b, 0x9f, 0x9e,  0xda, 0xdb, 0xdf, 0xde, },
64     {0x18, 0x19, 0x1d, 0x1c,  0x58, 0x59, 0x5d, 0x5c,  0x98, 0x99, 0x9d, 0x9c,  0xd8, 0xd9, 0xdd, 0xdc, },
65 
66     {0x20, 0x21, 0x25, 0x24,  0x60, 0x61, 0x65, 0x64,  0xa0, 0xa1, 0xa5, 0xa4,  0xe0, 0xe1, 0xe5, 0xe4, },
67     {0x22, 0x23, 0x27, 0x26,  0x62, 0x63, 0x67, 0x66,  0xa2, 0xa3, 0xa7, 0xa6,  0xe2, 0xe3, 0xe7, 0xe6, },
68     {0x2a, 0x2b, 0x2f, 0x2e,  0x6a, 0x6b, 0x6f, 0x6e,  0xaa, 0xab, 0xaf, 0xae,  0xea, 0xeb, 0xef, 0xee, },
69     {0x28, 0x29, 0x2d, 0x2c,  0x68, 0x69, 0x6d, 0x6c,  0xa8, 0xa9, 0xad, 0xac,  0xe8, 0xe9, 0xed, 0xec, },
70 
71     {0x30, 0x31, 0x35, 0x34,  0x70, 0x71, 0x75, 0x74,  0xb0, 0xb1, 0xb5, 0xb4,  0xf0, 0xf1, 0xf5, 0xf4, },
72     {0x32, 0x33, 0x37, 0x36,  0x72, 0x73, 0x77, 0x76,  0xb2, 0xb3, 0xb7, 0xb6,  0xf2, 0xf3, 0xf7, 0xf6, },
73     {0x3a, 0x3b, 0x3f, 0x3e,  0x7a, 0x7b, 0x7f, 0x7e,  0xba, 0xbb, 0xbf, 0xbe,  0xfa, 0xfb, 0xff, 0xfe, },
74     {0x38, 0x39, 0x3d, 0x3c,  0x78, 0x79, 0x7d, 0x7c,  0xb8, 0xb9, 0xbd, 0xbc,  0xf8, 0xf9, 0xfd, 0xfc, },
75 };
76 
77 const U8 idxCC_420[8][8] =
78 {
79     {0x00, 0x01, 0x05, 0x04,  0x20, 0x21, 0x25, 0x24, },
80     {0x02, 0x03, 0x07, 0x06,  0x22, 0x23, 0x27, 0x26, },
81     {0x0a, 0x0b, 0x0f, 0x0e,  0x2a, 0x2b, 0x2f, 0x2e, },
82     {0x08, 0x09, 0x0d, 0x0c,  0x28, 0x29, 0x2d, 0x2c, },
83 
84     {0x10, 0x11, 0x15, 0x14,  0x30, 0x31, 0x35, 0x34, },
85     {0x12, 0x13, 0x17, 0x16,  0x32, 0x33, 0x37, 0x36, },
86     {0x1a, 0x1b, 0x1f, 0x1e,  0x3a, 0x3b, 0x3f, 0x3e, },
87     {0x18, 0x19, 0x1d, 0x1c,  0x38, 0x39, 0x3d, 0x3c, },
88 };
89 
90 /*************************************************************************
91     gGDISignature
92 *************************************************************************/
93 const Char gGDISignature[] = {'W', 'M', 'P', 'H', 'O', 'T', 'O', '\0'};
94 
95 // check if enough memory allocated for the image buffer
checkImageBuffer(CWMImageStrCodec * pSC,size_t cWidth,size_t cRows)96 Int checkImageBuffer(CWMImageStrCodec * pSC, size_t cWidth, size_t cRows)
97 {
98     const BITDEPTH_BITS bd = pSC->WMISCP.bYUVData ?
99         BD_32S : pSC->WMII.bdBitDepth;
100     const COLORFORMAT cf = pSC->WMISCP.bYUVData ?
101         pSC->m_param.cfColorFormat : pSC->WMII.cfColorFormat;
102     size_t cBytes;
103     Bool bLessThan64Bit = sizeof(void *) < 8;
104 
105     if(cf == YUV_420)
106         cRows = (cRows + 1) / 2;
107     if(cRows > pSC->WMIBI.cLine)
108         return ICERR_ERROR;
109 
110     if(cf == YUV_422 || cf == YUV_420)
111         cWidth = (cWidth + 1) / 2;
112 
113     if (bLessThan64Bit && (cWidth >> ((sizeof(size_t) * 8 - 5)))) {
114         /** potential overflow - 32 bit pointers insufficient to address cache **/
115         /** this uses 2 macroblock row constraint, which is tighter than ensuring rollover doesn't occur below **/
116         return ICERR_ERROR;
117     }
118 
119     cBytes = pSC->WMISCP.bYUVData ? cWidth * sizeof(PixelI) *
120         (cf == YUV_420 ? 6 : (cf == YUV_422 ? 4 : (cf == YUV_444 ? 3 : 1))) :
121         (bd == BD_1 ? (pSC->WMII.cBitsPerUnit * cWidth + 7) / 8 : (pSC->WMII.cBitsPerUnit + 7) / 8 * cWidth);
122 
123     return (cBytes > pSC->WMIBI.cbStride ? ICERR_ERROR : ICERR_OK);
124 }
125 
writeQPIndex(BitIOInfo * pIO,U8 uiIndex,U32 cBits)126 Void writeQPIndex(BitIOInfo * pIO, U8 uiIndex, U32 cBits)
127 {
128     if(uiIndex == 0)
129         putBit16(pIO, 1, 1); // default QP
130     else{
131         putBit16(pIO, 0, 1); // non default QP
132         putBit16(pIO, uiIndex - 1, cBits);
133     }
134 }
135 
readQPIndex(BitIOInfo * pIO,U32 cBits)136 U8 readQPIndex(BitIOInfo * pIO, U32 cBits)
137 {
138     if(getBit16(pIO, 1))
139         return 0; // default QP
140 
141     return (U8) getBit16(pIO, cBits) + 1;
142 }
143 
getTilePos(CWMImageStrCodec * pSC,size_t mbX,size_t mbY)144 Void getTilePos(CWMImageStrCodec* pSC, size_t mbX, size_t mbY)
145 {
146     if(mbX == 0){ // left image boundary
147         pSC->cTileColumn = 0;
148     }
149     else if(pSC->cTileColumn < pSC->WMISCP.cNumOfSliceMinus1V && mbX == pSC->WMISCP.uiTileX[pSC->cTileColumn + 1]){ // left tile boundary
150         pSC->cTileColumn ++;
151     }
152 
153     if(mbY == 0){ // top image boundary
154         pSC->cTileRow = 0;
155     }
156     else if(pSC->cTileRow < pSC->WMISCP.cNumOfSliceMinus1H && mbY == pSC->WMISCP.uiTileY[pSC->cTileRow + 1]){ // top tile boundary
157         pSC->cTileRow ++;
158     }
159 
160     pSC->m_bCtxLeft = (mbX == pSC->WMISCP.uiTileX[pSC->cTileColumn]);
161     pSC->m_bCtxTop  = (mbY == pSC->WMISCP.uiTileY[pSC->cTileRow]);
162 
163     pSC->m_bResetContext = pSC->m_bResetRGITotals = (((mbX - pSC->WMISCP.uiTileX[pSC->cTileColumn]) & 0xf) == 0);
164     if(pSC->cTileColumn == pSC->WMISCP.cNumOfSliceMinus1V){ // last tile column
165         if(mbX + 1 == pSC->cmbWidth)
166             pSC->m_bResetContext = TRUE;
167     }
168     else if(mbX + 1 == pSC->WMISCP.uiTileX[pSC->cTileColumn + 1])
169         pSC->m_bResetContext = TRUE;
170 }
171 
172 //================================================================
173 // utility functions for 2 macro block rows
174 //================================================================
initMRPtr(CWMImageStrCodec * pSC)175 Void initMRPtr(CWMImageStrCodec* pSC)
176 {
177     size_t j, jend = (pSC->m_pNextSC != NULL);
178 
179     for (j = 0; j <= jend; j++) {
180         memcpy (pSC->p0MBbuffer, pSC->a0MBbuffer, sizeof (pSC->p0MBbuffer));
181         memcpy (pSC->p1MBbuffer, pSC->a1MBbuffer, sizeof (pSC->p1MBbuffer));
182         pSC = pSC->m_pNextSC;
183     }
184 }
185 
advanceMRPtr(CWMImageStrCodec * pSC)186 Void advanceMRPtr(CWMImageStrCodec* pSC)
187 {
188     const COLORFORMAT cf = pSC->m_param.cfColorFormat;
189     const int cpChroma = cblkChromas[cf] * 16;
190     size_t i, j, jend = (pSC->m_pNextSC != NULL);
191 
192     assert(pSC->m_bSecondary == FALSE);
193     for (j = 0; j <= jend; j++) {
194         int cpStride = 16 * 16;
195         for (i = 0; i < pSC->m_param.cNumChannels; i++) {
196             pSC->pPlane[i] = pSC->p0MBbuffer[i];
197 
198             pSC->p0MBbuffer[i] += cpStride;
199             pSC->p1MBbuffer[i] += cpStride;
200 
201             cpStride = cpChroma;
202         }
203         pSC = pSC->m_pNextSC;
204     }
205 }
206 
207 /* advance to next MB row */
advanceOneMBRow(CWMImageStrCodec * pSC)208 Void advanceOneMBRow(CWMImageStrCodec *pSC)
209 {
210     size_t i, j, jend = (pSC->m_pNextSC != NULL);
211     CWMIPredInfo *pPredInfo;
212 
213     for (j = 0; j <= jend; j++) {
214         for(i = 0; i < pSC->m_param.cNumChannels; i ++){  // swap current row and previous row
215             pPredInfo = pSC->PredInfo[i];
216             pSC->PredInfo[i] = pSC->PredInfoPrevRow[i];
217             pSC->PredInfoPrevRow[i] = pPredInfo;
218         }
219         pSC = pSC->m_pNextSC;
220     }
221 }
222 
swapMRPtr(CWMImageStrCodec * pSC)223 Void swapMRPtr(CWMImageStrCodec* pSC)
224 {
225     PixelI *pTemp[MAX_CHANNELS];
226     size_t j, jend = (pSC->m_pNextSC != NULL);
227 
228     for (j = 0; j <= jend; j++) {
229         memcpy (pTemp, pSC->a0MBbuffer, sizeof (pSC->a0MBbuffer));
230         memcpy (pSC->a0MBbuffer, pSC->a1MBbuffer, sizeof (pSC->a0MBbuffer));
231         memcpy (pSC->a1MBbuffer, pTemp, sizeof (pSC->a0MBbuffer));
232         pSC = pSC->m_pNextSC;
233     }
234 }
235 
236 //================================================================
237 // Empty function to fill slot
238 //================================================================
IDPEmpty(CWMImageStrCodec * pSC)239 Int IDPEmpty(CWMImageStrCodec* pSC)
240 {
241     UNREFERENCED_PARAMETER( pSC );
242 
243     return ICERR_OK;
244 }
245 
WMPAlloc(void ** ppv,size_t cb)246 ERR WMPAlloc(void** ppv, size_t cb)
247 {
248     *ppv = calloc(1, cb);
249     return *ppv ? WMP_errSuccess : WMP_errOutOfMemory;
250 }
251 
WMPFree(void ** ppv)252 ERR WMPFree(void** ppv)
253 {
254     if (*ppv)
255     {
256         free(*ppv);
257         *ppv = NULL;
258     }
259 
260     return WMP_errSuccess;
261 }
262 
263 //================================================================
264 // Streaming I/O functions
265 //================================================================
CreateWS_File(struct WMPStream ** ppWS,const char * szFilename,const char * szMode)266 ERR CreateWS_File(struct WMPStream** ppWS, const char* szFilename, const char* szMode)
267 {
268     ERR err = WMP_errSuccess;
269     struct WMPStream* pWS = NULL;
270 
271     Call(WMPAlloc((void** )ppWS, sizeof(**ppWS)));
272     pWS = *ppWS;
273 
274     pWS->Close = CloseWS_File;
275     pWS->EOS = EOSWS_File;
276 
277     pWS->Read = ReadWS_File;
278     pWS->Write = WriteWS_File;
279     //pWS->GetLine = GetLineWS_File;
280 
281     pWS->SetPos = SetPosWS_File;
282     pWS->GetPos = GetPosWS_File;
283 
284 #if defined(WIN32) && !defined(__MINGW32__)
285     FailIf(0 != fopen_s(&pWS->state.file.pFile, szFilename, szMode), WMP_errFileIO);
286 #else
287     pWS->state.file.pFile = fopen(szFilename, szMode);
288     FailIf(NULL == pWS->state.file.pFile, WMP_errFileIO);
289 #endif
290 
291 Cleanup:
292     return err;
293 }
294 
CloseWS_File(struct WMPStream ** ppWS)295 ERR CloseWS_File(struct WMPStream** ppWS)
296 {
297     ERR err = WMP_errSuccess;
298     struct WMPStream* pWS = *ppWS;
299 
300     fclose(pWS->state.file.pFile);
301     Call(WMPFree((void**)ppWS));
302 
303 Cleanup:
304     return err;
305 }
306 
EOSWS_File(struct WMPStream * pWS)307 Bool EOSWS_File(struct WMPStream* pWS)
308 {
309     return feof(pWS->state.file.pFile);
310 }
311 
ReadWS_File(struct WMPStream * pWS,void * pv,size_t cb)312 ERR ReadWS_File(struct WMPStream* pWS, void* pv, size_t cb)
313 {
314     // ERR err = WMP_errSuccess;
315 
316     return (fread(pv, cb, 1, pWS->state.file.pFile) == 1) ? WMP_errSuccess : WMP_errFileIO;
317 }
318 
WriteWS_File(struct WMPStream * pWS,const void * pv,size_t cb)319 ERR WriteWS_File(struct WMPStream* pWS, const void* pv, size_t cb)
320 {
321     ERR err = WMP_errSuccess;
322 
323     if(0 != cb)
324     {
325         FailIf(1 != fwrite(pv, cb, 1, pWS->state.file.pFile), WMP_errFileIO);
326     }
327 
328 Cleanup:
329     return err;
330 }
331 
SetPosWS_File(struct WMPStream * pWS,size_t offPos)332 ERR SetPosWS_File(struct WMPStream* pWS, size_t offPos)
333 {
334     ERR err = WMP_errSuccess;
335 
336     FailIf(0 != fseek(pWS->state.file.pFile, (long)offPos, SEEK_SET), WMP_errFileIO);
337 
338 Cleanup:
339     return err;
340 }
341 
GetPosWS_File(struct WMPStream * pWS,size_t * poffPos)342 ERR GetPosWS_File(struct WMPStream* pWS, size_t* poffPos)
343 {
344     ERR err = WMP_errSuccess;
345     long lOff = 0;
346 
347     FailIf(-1 == (lOff = ftell(pWS->state.file.pFile)), WMP_errFileIO);
348     *poffPos = (size_t)lOff;
349 
350 Cleanup:
351     return err;
352 }
353 
354 //----------------------------------------------------------------
CreateWS_Memory(struct WMPStream ** ppWS,void * pv,size_t cb)355 ERR CreateWS_Memory(struct WMPStream** ppWS, void* pv, size_t cb)
356 {
357     ERR err = WMP_errSuccess;
358     struct WMPStream* pWS = NULL;
359 
360     Call(WMPAlloc((void** )ppWS, sizeof(**ppWS)));
361     pWS = *ppWS;
362 
363     pWS->state.buf.pbBuf = pv;
364     pWS->state.buf.cbBuf = cb;
365     pWS->state.buf.cbCur = 0;
366 
367     pWS->Close = CloseWS_Memory;
368     pWS->EOS = EOSWS_Memory;
369 
370     pWS->Read = ReadWS_Memory;
371     pWS->Write = WriteWS_Memory;
372 
373     pWS->SetPos = SetPosWS_Memory;
374     pWS->GetPos = GetPosWS_Memory;
375 
376 Cleanup:
377     return err;
378 }
379 
CloseWS_Memory(struct WMPStream ** ppWS)380 ERR CloseWS_Memory(struct WMPStream** ppWS)
381 {
382     ERR err = WMP_errSuccess;
383 
384     Call(WMPFree((void**)ppWS));
385 
386 Cleanup:
387     return err;
388 }
389 
EOSWS_Memory(struct WMPStream * pWS)390 Bool EOSWS_Memory(struct WMPStream* pWS)
391 {
392     return pWS->state.buf.cbBuf <= pWS->state.buf.cbCur;
393 }
394 
ReadWS_Memory(struct WMPStream * pWS,void * pv,size_t cb)395 ERR ReadWS_Memory(struct WMPStream* pWS, void* pv, size_t cb)
396 {
397     ERR err = WMP_errSuccess;
398 
399 //    FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur, WMP_errBufferOverflow);
400     if(pWS->state.buf.cbBuf < pWS->state.buf.cbCur)
401         return err;
402 
403     FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
404     if (pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb)
405     {
406         cb = pWS->state.buf.cbBuf - pWS->state.buf.cbCur;
407     }
408 
409     memcpy(pv, pWS->state.buf.pbBuf + pWS->state.buf.cbCur, cb);
410     pWS->state.buf.cbCur += cb;
411 
412 Cleanup:
413     return err;
414 }
415 
WriteWS_Memory(struct WMPStream * pWS,const void * pv,size_t cb)416 ERR WriteWS_Memory(struct WMPStream* pWS, const void* pv, size_t cb)
417 {
418     ERR err = WMP_errSuccess;
419 
420     FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
421     FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb, WMP_errBufferOverflow);
422 
423     memcpy(pWS->state.buf.pbBuf + pWS->state.buf.cbCur, pv, cb);
424     pWS->state.buf.cbCur += cb;
425 
426 Cleanup:
427     return err;
428 }
429 
SetPosWS_Memory(struct WMPStream * pWS,size_t offPos)430 ERR SetPosWS_Memory(struct WMPStream* pWS, size_t offPos)
431 {
432     ERR err = WMP_errSuccess;
433 
434     //While the following condition is possibly useful, failure occurs
435     //at the end of a file since packets beyond the end may be accessed
436     //FailIf(pWS->state.buf.cbBuf < offPos, WMP_errBufferOverflow);
437     pWS->state.buf.cbCur = offPos;
438 
439 //Cleanup:
440     return err;
441 }
442 
GetPosWS_Memory(struct WMPStream * pWS,size_t * poffPos)443 ERR GetPosWS_Memory(struct WMPStream* pWS, size_t* poffPos)
444 {
445     *poffPos = pWS->state.buf.cbCur;
446 
447     return WMP_errSuccess;
448 }
449 
450 //=================================================================
451 // Linked list based WMPStream
452 // - for indefinite size, multiple stream out
453 // - reads not supported in this mode
454 //=================================================================
CreateWS_List(struct WMPStream ** ppWS)455 ERR CreateWS_List(struct WMPStream** ppWS)
456 {
457     ERR err = WMP_errSuccess;
458     struct WMPStream* pWS = NULL;
459 
460     Call(WMPAlloc((void** )ppWS, sizeof(**ppWS) + PACKETLENGTH + sizeof(void *)));
461     pWS = *ppWS;
462 
463     pWS->state.buf.pbBuf = (U8 *)pWS + sizeof(**ppWS) + sizeof(void *); // first buffer points here
464 
465     memset(pWS->state.buf.pbBuf - sizeof(void *), 0, sizeof(void *));
466     pWS->state.buf.cbBuf = PACKETLENGTH;
467     pWS->state.buf.cbCur = 0;
468     pWS->state.buf.cbBufCount = 0;
469 
470     pWS->Close = CloseWS_List;
471     pWS->EOS = NULL; // doesn't get called
472 
473     pWS->Read = ReadWS_List;
474     pWS->Write = WriteWS_List;
475 
476     pWS->SetPos = SetPosWS_List;
477     pWS->GetPos = GetPosWS_List;
478 
479     //printf ("create buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
480 
481 Cleanup:
482     return err;
483 }
484 
CloseWS_List(struct WMPStream ** ppWS)485 ERR CloseWS_List(struct WMPStream** ppWS)
486 {
487     ERR err = WMP_errSuccess;
488 
489     if (ppWS) {
490         U8 *pBuf = (U8 *)(ppWS[0] + 1); // pointer to buffer
491         U8 *pNext = (U8 *)(((void **)pBuf)[0]);
492         while (pNext) {
493 //struct WMPStream *pWS = ppWS[0];
494             pBuf = pNext;
495             pNext = (U8 *)(((void **)(pBuf))[0]);
496 //printf ("delete buffer    %x\n", pBuf);
497             Call(WMPFree((void**)&pBuf));
498         }
499     }
500     Call(WMPFree((void**)ppWS));
501 
502 Cleanup:
503     return err;
504 }
505 
ReadWS_List(struct WMPStream * pWS,void * pv,size_t cb)506 ERR ReadWS_List(struct WMPStream* pWS, void* pv, size_t cb)
507 {
508     ERR err = WMP_errSuccess;
509 
510     FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
511     if (pWS->state.buf.cbBuf < pWS->state.buf.cbCur + PACKETLENGTH * pWS->state.buf.cbBufCount + cb)
512     {
513         cb = pWS->state.buf.cbBuf - pWS->state.buf.cbCur - PACKETLENGTH * pWS->state.buf.cbBufCount;
514     }
515 
516     while (cb) {
517         size_t cl = PACKETLENGTH - pWS->state.buf.cbCur;
518         if (cl > cb)
519             cl = cb;
520         memcpy(pv, pWS->state.buf.pbBuf + pWS->state.buf.cbCur, cl);
521         pWS->state.buf.cbCur += cl;
522         pv = (void *)((U8 *)pv + cl);
523         cb -= cl;
524         if (pWS->state.buf.cbCur == PACKETLENGTH) {
525             pWS->state.buf.pbBuf = (U8 *)((void **)(pWS->state.buf.pbBuf - sizeof(void *)))[0] + sizeof(void *);
526             pWS->state.buf.cbCur = 0;
527             pWS->state.buf.cbBufCount++;
528 
529     //printf ("read buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
530         }
531     }
532 
533 Cleanup:
534     return err;
535 }
536 
WriteWS_List(struct WMPStream * pWS,const void * pv,size_t cb)537 ERR WriteWS_List(struct WMPStream* pWS, const void* pv, size_t cb)
538 {
539     ERR err = WMP_errSuccess;
540 
541     FailIf(pWS->state.buf.cbCur + cb < pWS->state.buf.cbCur, WMP_errBufferOverflow);
542     FailIf(pWS->state.buf.cbBuf < pWS->state.buf.cbCur + cb, WMP_errBufferOverflow);
543 
544     while (cb) {
545         size_t cl = PACKETLENGTH - pWS->state.buf.cbCur;
546         if (cl > cb)
547             cl = cb;
548         memcpy(pWS->state.buf.pbBuf + pWS->state.buf.cbCur, pv, cl);
549         pWS->state.buf.cbCur += cl;
550         pv = (const void *)((U8 *)pv + cl);
551         cb -= cl;
552         if (pWS->state.buf.cbCur == PACKETLENGTH) { // allocate next packet in list
553             U8 *pBuf  = NULL;
554             void **pPtrLoc = (void **)(pWS->state.buf.pbBuf - sizeof(void *));
555             Call(WMPAlloc((void **)&pBuf, PACKETLENGTH + sizeof(void *)));
556             pPtrLoc[0] = (void *)pBuf;
557             pWS->state.buf.pbBuf = pBuf + sizeof(void *);
558             pWS->state.buf.cbBuf += PACKETLENGTH;
559             memset(pBuf, 0, sizeof(void *));
560             pWS->state.buf.cbCur = 0;
561             pWS->state.buf.cbBufCount++;
562 
563     //printf ("create buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
564         }
565     }
566 
567 Cleanup:
568     return err;
569 }
570 
SetPosWS_List(struct WMPStream * pWS,size_t offPos)571 ERR SetPosWS_List(struct WMPStream* pWS, size_t offPos)
572 {
573     ERR err = WMP_errSuccess;
574 
575     // get the first buffer
576     U8 *pBuf = (U8 *)(pWS + 1); // pointer to buffer
577     pWS->state.buf.cbCur = 0;
578     pWS->state.buf.cbBufCount = 0;
579 
580     while (offPos >= PACKETLENGTH && pBuf != NULL) {
581         pBuf = (U8 *)(((void **)pBuf)[0]);
582         offPos -= PACKETLENGTH;
583         pWS->state.buf.cbBufCount++;
584     }
585 
586     if (pBuf == NULL)
587         goto Cleanup;
588 
589     pWS->state.buf.cbCur = offPos;
590     pWS->state.buf.pbBuf = pBuf + sizeof(void *);
591     //printf ("seek buffer %d: %x\n", pWS->state.buf.cbBufCount, pWS->state.buf.pbBuf);
592 
593 Cleanup:
594     return err;
595 }
596 
GetPosWS_List(struct WMPStream * pWS,size_t * poffPos)597 ERR GetPosWS_List(struct WMPStream* pWS, size_t* poffPos)
598 {
599     *poffPos = pWS->state.buf.cbCur + PACKETLENGTH * pWS->state.buf.cbBufCount;
600 
601     return WMP_errSuccess;
602 }
603 
604 //================================================================
605 // Simple BitIO access functions
606 //================================================================
607 // init SimpleBitIO
attach_SB(SimpleBitIO * pSB,struct WMPStream * pWS)608 ERR attach_SB(SimpleBitIO* pSB, struct WMPStream* pWS)
609 {
610     pSB->pWS = pWS;
611     pSB->cbRead = 0;
612     pSB->bAccumulator = 0;
613     pSB->cBitLeft = 0;
614 
615     return WMP_errSuccess;
616 }
617 
618 // extract upto 32bit from input stream
getBit32_SB(SimpleBitIO * pSB,U32 cBits)619 U32 getBit32_SB(SimpleBitIO* pSB, U32 cBits)
620 {
621     U32 rc = 0;
622 
623     while (pSB->cBitLeft < cBits)
624     {
625         rc <<= pSB->cBitLeft;
626         rc |= pSB->bAccumulator >> (8 - pSB->cBitLeft);
627 
628         cBits -= pSB->cBitLeft;
629 
630         pSB->pWS->Read(pSB->pWS, &pSB->bAccumulator, 1);
631         pSB->cbRead++;
632         pSB->cBitLeft = 8;
633     }
634 
635     rc <<= cBits;
636     rc |= pSB->bAccumulator >> (8 - cBits);
637     pSB->bAccumulator <<= cBits;
638     pSB->cBitLeft -= cBits;
639 
640     return rc;
641 }
642 
643 // ignore input to byte boundary
flushToByte_SB(SimpleBitIO * pSB)644 Void flushToByte_SB(SimpleBitIO* pSB)
645 {
646     pSB->bAccumulator = 0;
647     pSB->cBitLeft = 0;
648 }
649 
650 // return read byte count
getByteRead_SB(SimpleBitIO * pSB)651 U32 getByteRead_SB(SimpleBitIO* pSB)
652 {
653     return pSB->cbRead;
654 }
655 
detach_SB(SimpleBitIO * pSB)656 ERR detach_SB(SimpleBitIO* pSB)
657 {
658     assert(0 == pSB->cBitLeft);
659     pSB->pWS = NULL;
660 
661     return WMP_errSuccess;
662 }
663 
664 //================================================================
665 // Memory access functions
666 //================================================================
667 #if (defined(WIN32) && !defined(UNDER_CE) && (!defined(__MINGW32__) || defined(__MINGW64_TOOLCHAIN__))) || (defined(UNDER_CE) && defined(_ARM_))
668 // WinCE ARM and Desktop x86
669 #else
670 // other platform
671 #ifdef _BIG__ENDIAN_
672 #define _byteswap_ulong(x)  (x)
673 #else // _BIG__ENDIAN_
_byteswap_ulong(U32 bits)674 U32 _byteswap_ulong(U32 bits)
675 {
676     U32 r = (bits & 0xffu) << 24;
677     r |= (bits << 8) & 0xff0000u;
678     r |= ((bits >> 8) & 0xff00u);
679     r |= ((bits >> 24) & 0xffu);
680 
681     return r;
682 }
683 #endif // _BIG__ENDIAN_
684 #endif
685 
load4BE(void * pv)686 U32 load4BE(void* pv)
687 {
688 #ifdef _BIG__ENDIAN_
689     return (*(U32*)pv);
690 #else // _BIG__ENDIAN_
691 #if defined(_M_IA64) || defined(_ARM_)
692     U32  v;
693     v = ((U16 *) pv)[0];
694     v |= ((U32)((U16 *) pv)[1]) << 16;
695     return _byteswap_ulong(v);
696 #else // _M_IA64
697     return _byteswap_ulong(*(U32*)pv);
698 #endif // _M_IA64
699 #endif // _BIG__ENDIAN_
700 }
701 
702 #define LOAD16 load4BE
703 
704 #ifdef _BIG__ENDIAN_
705 #define WRITESWAP_ENDIAN(a) ((a)>>16)
706 #else // _BIG__ENDIAN_
707 #define WRITESWAP_ENDIAN(a)	_byteswap_ulong(a)
708 #endif // _BIG__ENDIAN_
709 
710 //================================================================
711 // Bit I/O functions
712 //================================================================
allocateBitIOInfo(CWMImageStrCodec * pSC)713 Int allocateBitIOInfo(CWMImageStrCodec* pSC)
714 {
715     U32 cNumBitIO;
716     SUBBAND sbSubband = pSC->WMISCP.sbSubband;
717 
718     pSC->cSB = (sbSubband == SB_DC_ONLY ? 1 : (sbSubband == SB_NO_HIGHPASS ? 2 : (sbSubband == SB_NO_FLEXBITS ? 3 : 4)));
719 
720     // # of additional BitIOs other than pSC->pIOHeader
721     if (!pSC->m_param.bIndexTable) { // pure streaming mode, no index table, no additional BitIO!
722         assert (pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V == 0);
723         cNumBitIO = 0;
724     }
725     else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL)
726         cNumBitIO = pSC->WMISCP.cNumOfSliceMinus1V + 1;
727     else
728         cNumBitIO = (pSC->WMISCP.cNumOfSliceMinus1V + 1) * pSC->cSB;
729 
730     if(cNumBitIO > MAX_TILES * 4)
731         return ICERR_ERROR;
732 
733     // allocate additional BitIos
734     if(cNumBitIO > 0){
735         U32 i = 0;
736         size_t cb = sizeof(BitIOInfo) * cNumBitIO + (PACKETLENGTH * 4 - 1) + PACKETLENGTH * 4 * cNumBitIO;
737         U8* pb = (U8*)malloc(cb);
738 
739         if (NULL == pb) return ICERR_ERROR;
740         memset(pb, 0, cb);
741 
742         pSC->m_ppBitIO = (BitIOInfo**)pb;
743         pb += sizeof(BitIOInfo) * cNumBitIO;
744 
745         pb = (U8*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2;
746         for (i = 0; i < cNumBitIO; ++i){
747             pSC->m_ppBitIO[i] = (BitIOInfo*)pb;
748             pb += PACKETLENGTH * 4;
749         }
750 
751         // allocate index table
752         if(cNumBitIO > MAX_TILES * 4 || pSC->WMISCP.cNumOfSliceMinus1H >= MAX_TILES)
753             return ICERR_ERROR;
754         pSC->pIndexTable = malloc(cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1) * sizeof(size_t));
755         if(NULL == pSC->pIndexTable) return ICERR_ERROR;
756     }
757 
758     pSC->cNumBitIO = cNumBitIO;
759 
760     return ICERR_OK;
761 }
762 
setBitIOPointers(CWMImageStrCodec * pSC)763 Int setBitIOPointers(CWMImageStrCodec* pSC)
764 {
765     if(pSC->cNumBitIO > 0){
766         U32 i;
767 
768         for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
769             CCodingContext * pContext = &pSC->m_pCodingContext[i];
770             if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
771                 pContext->m_pIODC = pContext->m_pIOLP = pContext->m_pIOAC = pContext->m_pIOFL = pSC->m_ppBitIO[i];
772             }
773             else{
774                 U32 j = pSC->cSB;
775 
776                 pContext->m_pIODC = pSC->m_ppBitIO[i * j];
777                 if(j > 1)
778                     pContext->m_pIOLP = pSC->m_ppBitIO[i * j + 1];
779                 if(j > 2)
780                     pContext->m_pIOAC = pSC->m_ppBitIO[i * j + 2];
781                 if(j > 3)
782                     pContext->m_pIOFL = pSC->m_ppBitIO[i * j + 3];
783             }
784         }
785     }
786     else{ // streamimg mode
787         CCodingContext * pContext = &pSC->m_pCodingContext[0];
788         pContext->m_pIODC = pContext->m_pIOLP = pContext->m_pIOAC = pContext->m_pIOFL = pSC->pIOHeader;
789     }
790 
791     return ICERR_OK;
792 }
793 
allocateTileInfo(CWMImageStrCodec * pSC)794 Int allocateTileInfo(CWMImageStrCodec * pSC)
795 {
796     size_t i;
797 
798     if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES)
799         return ICERR_ERROR;
800     pSC->pTile = (CWMITile *)malloc((pSC->WMISCP.cNumOfSliceMinus1V + 1) * sizeof(CWMITile));
801     if(pSC->pTile == NULL)
802         return ICERR_ERROR;
803     memset(pSC->pTile, 0, (pSC->WMISCP.cNumOfSliceMinus1V + 1) * sizeof(CWMITile));
804 
805     for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++)
806         pSC->pTile[i].cNumQPHP = pSC->pTile[i].cNumQPLP = 1, pSC->pTile[i].cBitsHP = pSC->pTile[i].cBitsLP = 0;
807 
808     return ICERR_OK;
809 }
810 
freeTileInfo(CWMImageStrCodec * pSC)811 Void freeTileInfo(CWMImageStrCodec * pSC)
812 {
813     size_t iTile;
814 
815     if((pSC->m_param.uQPMode & 1) != 0) // not DC uniform
816         for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
817             freeQuantizer(pSC->pTile[iTile].pQuantizerDC);
818     else
819         freeQuantizer(pSC->pTile[0].pQuantizerDC);
820 
821     if(pSC->WMISCP.sbSubband != SB_DC_ONLY)
822         if((pSC->m_param.uQPMode & 2) != 0) // not LP uniform
823             for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
824                 freeQuantizer(pSC->pTile[iTile].pQuantizerLP);
825         else
826             freeQuantizer(pSC->pTile[0].pQuantizerLP);
827 
828     if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)
829         if((pSC->m_param.uQPMode & 4) != 0) // not HP uniform
830             for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
831                 freeQuantizer(pSC->pTile[iTile].pQuantizerHP);
832         else
833             freeQuantizer(pSC->pTile[0].pQuantizerHP);
834 
835     if(pSC->pTile != NULL)
836         free(pSC->pTile);
837 }
838 
allocateQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS],size_t cChannel,size_t cQP)839 Int allocateQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], size_t cChannel, size_t cQP)
840 {
841     size_t iCh;
842 
843     if(cQP > 16 || cChannel > MAX_CHANNELS)
844         return ICERR_ERROR;
845     pQuantizer[0] = (CWMIQuantizer *)malloc(cQP * sizeof(CWMIQuantizer) * cChannel);
846     if(pQuantizer[0] == NULL)
847         return ICERR_ERROR;
848 
849     for(iCh = 1; iCh < cChannel; iCh ++)
850         pQuantizer[iCh] = pQuantizer[iCh - 1] + cQP;
851 
852     return ICERR_OK;
853 }
854 
freeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS])855 Void freeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS])
856 {
857     if(pQuantizer[0] != NULL)
858         free(pQuantizer[0]);
859 }
860 
formatQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS],U8 cChMode,size_t cCh,size_t iPos,Bool bShiftedUV,Bool bScaledArith)861 Void formatQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], U8 cChMode, size_t cCh, size_t iPos, Bool bShiftedUV,
862                      Bool bScaledArith)
863 {
864     size_t iCh;
865 
866     for(iCh = 0; iCh < cCh; iCh ++){
867         if(iCh > 0)
868             if(cChMode == 0) // uniform
869                 pQuantizer[iCh][iPos] = pQuantizer[0][iPos];
870             else if(cChMode == 1) // mixed
871                 pQuantizer[iCh][iPos] = pQuantizer[1][iPos];
872         remapQP(pQuantizer[iCh] + iPos, (iCh > 0 && bShiftedUV == TRUE) ? SHIFTZERO - 1 : SHIFTZERO, bScaledArith);
873     }
874 }
875 
setUniformQuantizer(CWMImageStrCodec * pSC,size_t sb)876 Void setUniformQuantizer(CWMImageStrCodec * pSC, size_t sb)
877 {
878     size_t iCh, iTile;
879 
880     for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
881         for(iTile = 1; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
882             if(sb == 0) // DC
883                 pSC->pTile[iTile].pQuantizerDC[iCh] = pSC->pTile[0].pQuantizerDC[iCh];
884             else if(sb == 1) // LP
885                 pSC->pTile[iTile].pQuantizerLP[iCh] = pSC->pTile[0].pQuantizerLP[iCh];
886             else // HP
887                 pSC->pTile[iTile].pQuantizerHP[iCh] = pSC->pTile[0].pQuantizerHP[iCh];
888 }
889 
useDCQuantizer(CWMImageStrCodec * pSC,size_t iTile)890 Void useDCQuantizer(CWMImageStrCodec * pSC, size_t iTile)
891 {
892    size_t iCh;
893 
894     for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
895         pSC->pTile[iTile].pQuantizerLP[iCh][0] = *pSC->pTile[iTile].pQuantizerDC[iCh];
896 }
897 
useLPQuantizer(CWMImageStrCodec * pSC,size_t cQP,size_t iTile)898 Void useLPQuantizer(CWMImageStrCodec * pSC, size_t cQP, size_t iTile)
899 {
900    size_t iCh, iQP;
901 
902     for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
903         for(iQP = 0; iQP < cQP; iQP ++)
904             pSC->pTile[iTile].pQuantizerHP[iCh][iQP] = pSC->pTile[iTile].pQuantizerLP[iCh][iQP];
905 }
906 
dquantBits(U8 cQP)907 U8 dquantBits(U8 cQP)
908 {
909     return (cQP < 2 ? 0 : (cQP < 4 ? 1 : (cQP < 6 ? 2 : (cQP < 10 ? 3 : 4))));
910 }
911 
912 #ifndef ARMOPT_BITIO
peekBit16(BitIOInfo * pIO,U32 cBits)913 U32 peekBit16(BitIOInfo* pIO, U32 cBits)
914 {
915     PEEKBIT16(pIO, cBits);
916 }
917 
flushBit16(BitIOInfo * pIO,U32 cBits)918 U32 flushBit16(BitIOInfo* pIO, U32 cBits)
919 {
920     FLUSHBIT16(pIO, cBits);
921 }
922 
getBit16(BitIOInfo * pIO,U32 cBits)923 U32 getBit16(BitIOInfo* pIO, U32 cBits)
924 {
925     U32 uiRet = peekBit16(pIO, cBits);
926     flushBit16(pIO, cBits);
927 
928     return uiRet;
929 }
930 
getBool16(BitIOInfo * pIO)931 U32 getBool16(BitIOInfo* pIO)
932 {
933     U32 uiRet = peekBit16(pIO, 1);
934     flushBit16(pIO, 1);
935     return uiRet;
936 }
937 
938 /** this function returns cBits if zero is read, or a signed value if first cBits are not all zero **/
getBit16s(BitIOInfo * pIO,U32 cBits)939 I32 getBit16s(BitIOInfo* pIO, U32 cBits)
940 {
941     U32 uiRet = peekBit16(pIO, cBits + 1);
942     if (uiRet < 2) {
943         flushBit16(pIO, cBits);
944         return 0;
945     }
946     else {
947         flushBit16(pIO, cBits + 1);
948         if (uiRet & 1)
949             return (-(I32)(uiRet >> 1));
950         else
951             return (I32)(uiRet >> 1);
952     }
953 }
954 
getBit32(BitIOInfo * pIO,U32 cBits)955 U32 getBit32(BitIOInfo* pIO, U32 cBits)
956 {
957     U32 uiRet = 0;
958 
959     assert(0 <= (I32)cBits && cBits <= 32);
960 
961     if (16 < cBits)
962     {
963         uiRet = getBit16(pIO, 16);
964         cBits -= 16;
965         uiRet <<= cBits;
966     }
967 
968     uiRet |= getBit16(pIO, cBits);
969 
970     return uiRet;
971 }
972 
flushToByte(BitIOInfo * pIO)973 U32 flushToByte(BitIOInfo* pIO)
974 {
975     return flushBit16(pIO, (16 - pIO->cBitsUsed) & 7);
976 }
977 #endif  // ARMOPT_BITIO
978 
979 //----------------------------------------------------------------
putBit16z(BitIOInfo * pIO,U32 uiBits,U32 cBits)980 Void putBit16z(BitIOInfo* pIO, U32 uiBits, U32 cBits)
981 {
982     assert(cBits <= 16);
983     assert(0 == uiBits >> cBits);
984 
985     pIO->uiAccumulator = (pIO->uiAccumulator << cBits) | uiBits;
986     pIO->cBitsUsed += cBits;
987 
988     *(U16*)pIO->pbCurrent = (U16)WRITESWAP_ENDIAN(pIO->uiAccumulator << (32 - pIO->cBitsUsed));
989 
990     pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3) & 2), pIO->iMask);
991     pIO->cBitsUsed &= 16 - 1;
992 }
993 
putBit16(BitIOInfo * pIO,U32 uiBits,U32 cBits)994 Void putBit16(BitIOInfo* pIO, U32 uiBits, U32 cBits)
995 {
996     assert(cBits <= 16);
997 
998     uiBits &= ~(-1 << cBits);
999     putBit16z(pIO, uiBits, cBits);
1000 }
1001 
putBit32(BitIOInfo * pIO,U32 uiBits,U32 cBits)1002 Void putBit32(BitIOInfo* pIO, U32 uiBits, U32 cBits)
1003 {
1004     assert(0 <= (I32)cBits && cBits <= 32);
1005 
1006     if (16 < cBits)
1007     {
1008         putBit16(pIO, uiBits >> (cBits - 16), 16);
1009         cBits -= 16;
1010     }
1011 
1012     putBit16(pIO, uiBits, cBits);
1013 }
1014 
fillToByte(BitIOInfo * pIO)1015 Void fillToByte(BitIOInfo* pIO)
1016 {
1017     putBit16z(pIO, 0, (16 - pIO->cBitsUsed) & 7);
1018 }
1019 
1020 //----------------------------------------------------------------
getBit16_S(CWMImageStrCodec * pSC,BitIOInfo * pIO,U32 cBits)1021 U32 getBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 cBits)
1022 {
1023     U32 rc = getBit16(pIO, cBits);
1024     readIS_L1(pSC, pIO);
1025 
1026     return rc;
1027 }
1028 
putBit16_S(CWMImageStrCodec * pSC,BitIOInfo * pIO,U32 uiBits,U32 cBits)1029 U32 putBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 uiBits, U32 cBits)
1030 {
1031     putBit16(pIO, uiBits, cBits);
1032     writeIS_L1(pSC, pIO);
1033 
1034     return 0;
1035 }
1036 
1037 
1038 //----------------------------------------------------------------
1039 // Query buffered data size held in BitIOInfo
1040 // Write() for Enc, Read() for Dec
1041 //----------------------------------------------------------------
getSizeRead(BitIOInfo * pIO)1042 U32 getSizeRead(BitIOInfo* pIO)
1043 {
1044     return (U32)(UINTPTR_T)(pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8;
1045 }
1046 
getSizeWrite(BitIOInfo * pIO)1047 U32 getSizeWrite(BitIOInfo* pIO)
1048 {
1049     return (U32)(UINTPTR_T)(pIO->pbCurrent + (pIO->pbStart <= pIO->pbCurrent ? 0 : PACKETLENGTH * 2) - pIO->pbStart) + pIO->cBitsUsed / 8;
1050 }
1051 
1052 //----------------------------------------------------------------
1053 // Query stream offset from attached BitIO object for dec
1054 //----------------------------------------------------------------
getPosRead(BitIOInfo * pIO)1055 U32 getPosRead(BitIOInfo* pIO)
1056 {
1057     size_t cbCached = (pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8;
1058     return (U32)(pIO->offRef - cbCached);
1059 }
1060 
1061 //================================================================
1062 // Block I/O functions
1063 //================================================================
1064 #ifndef ARMOPT_BITIO
attachISRead(BitIOInfo * pIO,struct WMPStream * pWS,CWMImageStrCodec * pSC)1065 ERR attachISRead(BitIOInfo* pIO, struct WMPStream* pWS, CWMImageStrCodec* pSC)
1066 {
1067     UNREFERENCED_PARAMETER( pSC );
1068 
1069     pWS->GetPos(pWS, &pIO->offRef);
1070 
1071     pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2;
1072     pIO->pbCurrent = pIO->pbStart;
1073 
1074     PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1075     pWS->SetPos(pWS, pIO->offRef);
1076     pWS->Read(pWS, pIO->pbStart, PACKETLENGTH * 2);
1077     PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1078     pIO->offRef += PACKETLENGTH * 2;
1079 
1080     pIO->uiAccumulator = load4BE(pIO->pbStart);
1081 
1082     pIO->cBitsUsed = 0;
1083     pIO->iMask = ~(PACKETLENGTH * 2);
1084     pIO->iMask &= ~1;
1085 
1086     pIO->pWS = pWS;
1087     return WMP_errSuccess;
1088 }
1089 
readIS(CWMImageStrCodec * pSC,BitIOInfo * pIO)1090 ERR readIS(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1091 {
1092     ERR err = WMP_errSuccess;
1093 
1094     UNREFERENCED_PARAMETER( pSC );
1095 
1096     if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH))
1097     {
1098         struct WMPStream *pWS = pIO->pWS;
1099 
1100         PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1101         //Call(0 != pIO->pWS->Read(pIO->pWS, pIO->pbStart, PACKETLENGTH));
1102         // TODO: add error checking code
1103         pWS->SetPos(pWS, pIO->offRef);
1104         pWS->Read(pWS, pIO->pbStart, PACKETLENGTH);
1105         pIO->offRef += PACKETLENGTH;
1106         PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1107 
1108         // make shadow copy for first 4B
1109         pIO->uiShadow = *(U32*)pIO->pbStart;
1110 
1111         // reposition pbPacket pointer
1112         pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask);
1113     }
1114 
1115 //Cleanup:
1116     return err;
1117 }
1118 
detachISRead(CWMImageStrCodec * pSC,BitIOInfo * pIO)1119 ERR detachISRead(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1120 {
1121     ERR err = WMP_errSuccess;
1122 
1123     struct WMPStream* pWS = pIO->pWS;
1124     size_t cbRemain = 0;
1125 
1126     // we can ONLY detach IStream at byte boundary
1127     flushToByte(pIO);
1128     assert(0 == (pIO->cBitsUsed % 8));
1129     Call(readIS_L1(pSC, pIO));
1130 
1131     // set stream to right offset, undo buffering
1132     cbRemain = (pIO->pbStart + PACKETLENGTH * 2) - (pIO->pbCurrent + pIO->cBitsUsed / 8);
1133     pWS->SetPos(pWS, pIO->offRef - cbRemain);
1134 
1135     pIO->pWS = NULL;
1136 Cleanup:
1137     return err;
1138 }
1139 #endif  // ARMOPT_BITIO
1140 
1141 //----------------------------------------------------------------
attachISWrite(BitIOInfo * pIO,struct WMPStream * pWS)1142 ERR attachISWrite(BitIOInfo* pIO, struct WMPStream* pWS)
1143 {
1144     pWS->GetPos(pWS, &pIO->offRef);
1145 
1146     pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2;
1147     pIO->pbCurrent = pIO->pbStart;
1148 
1149     pIO->uiAccumulator = 0;
1150     pIO->cBitsUsed = 0;
1151     pIO->iMask = ~(PACKETLENGTH * 2);
1152 
1153     pIO->pWS = pWS;
1154     return WMP_errSuccess;
1155 }
1156 
1157 // write out packet if we have >=1 packet data filled
writeIS(CWMImageStrCodec * pSC,BitIOInfo * pIO)1158 ERR writeIS(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1159 {
1160     ERR err = WMP_errSuccess;
1161 
1162     UNREFERENCED_PARAMETER( pSC );
1163 
1164     if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH))
1165     {
1166         PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1167         err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, PACKETLENGTH);
1168         PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1169         Call(err);
1170 
1171         // reposition pbStart pointer
1172         pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask);
1173     }
1174 
1175 Cleanup:
1176     return err;
1177 }
1178 
1179 // write out partially filled buffer and detach bitIO from IStream
detachISWrite(CWMImageStrCodec * pSC,BitIOInfo * pIO)1180 ERR detachISWrite(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1181 {
1182     ERR err = WMP_errSuccess;
1183 
1184     // we can ONLY detach IStream at byte boundary
1185     assert(0 == (pIO->cBitsUsed % 8));
1186     Call(writeIS_L1(pSC, pIO));
1187 
1188     PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1189     err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, pIO->pbCurrent + pIO->cBitsUsed / 8 - pIO->pbStart);
1190     PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1191     Call(err);
1192 
1193     pIO->pWS = NULL;
1194 Cleanup:
1195     return err;
1196 }
1197 
1198 //=========================
1199 // Performance Measurement
1200 //=========================
1201 #ifndef DISABLE_PERF_MEASUREMENT
1202 
OutputIndivPerfTimer(struct PERFTIMERSTATE * pPerfTimer,char * pszTimerName,char * pszDescription,float fltMegaPixels)1203 void OutputIndivPerfTimer(struct PERFTIMERSTATE *pPerfTimer,
1204                           char *pszTimerName,
1205                           char *pszDescription,
1206                           float fltMegaPixels)
1207 {
1208     PERFTIMERRESULTS    rResults;
1209     Bool                fResult;
1210 
1211     fResult = FALSE;
1212     printf("%s (%s): ", pszTimerName, pszDescription);
1213     if (pPerfTimer)
1214     {
1215         fResult = PerfTimerGetResults(pPerfTimer, &rResults);
1216         if (fResult)
1217         {
1218             printf("%.3f milliseconds, %.6f MP/sec\n", (float)rResults.iElapsedTime / 1000000,
1219                 1000000000 * fltMegaPixels / rResults.iElapsedTime);
1220             if (rResults.iZeroTimeIntervals > 0)
1221             {
1222                 printf("   *** WARNING: %d time intervals were measured as zero. "
1223                     "This perf timer has insufficient precision!\n\n",
1224                     (int) rResults.iZeroTimeIntervals);
1225             }
1226         }
1227     }
1228     if (FALSE == fResult)
1229         printf("Results not available!\n");
1230 }
1231 
1232 
OutputPerfTimerReport(CWMImageStrCodec * pState)1233 void OutputPerfTimerReport(CWMImageStrCodec *pState)
1234 {
1235     float               fltMegaPixels;
1236 
1237     assert(pState->m_fMeasurePerf);
1238 
1239     printf("***************************************************************************\n");
1240     printf("* Perf Report\n");
1241     printf("***************************************************************************\n\n");
1242 
1243     fltMegaPixels = (float)pState->WMII.cWidth * pState->WMII.cHeight / 1000000;
1244     printf("Image Width = %d, Height = %d, total MegaPixels = %.1f MP\n",
1245         (int) pState->WMII.cWidth, (int) pState->WMII.cHeight, fltMegaPixels);
1246 
1247     OutputIndivPerfTimer(pState->m_ptEncDecPerf, "m_ptEncDecPerf", "excl I/O", fltMegaPixels);
1248     OutputIndivPerfTimer(pState->m_ptEndToEndPerf, "m_ptEndToEndPerf", "incl I/O", fltMegaPixels);
1249 }
1250 
1251 #endif // DISABLE_PERF_MEASUREMENT
1252