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