Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/jxr/image/sys/strcodec.c
4393 views
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
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
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
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
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
//================================================================
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
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 */
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
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
//================================================================
239
Int IDPEmpty(CWMImageStrCodec* pSC)
240
{
241
UNREFERENCED_PARAMETER( pSC );
242
243
return ICERR_OK;
244
}
245
246
ERR WMPAlloc(void** ppv, size_t cb)
247
{
248
*ppv = calloc(1, cb);
249
return *ppv ? WMP_errSuccess : WMP_errOutOfMemory;
250
}
251
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
//================================================================
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
#ifdef WIN32
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
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
307
Bool EOSWS_File(struct WMPStream* pWS)
308
{
309
return feof(pWS->state.file.pFile);
310
}
311
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
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
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
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
//----------------------------------------------------------------
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
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
390
Bool EOSWS_Memory(struct WMPStream* pWS)
391
{
392
return pWS->state.buf.cbBuf <= pWS->state.buf.cbCur;
393
}
394
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
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
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
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
//=================================================================
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
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
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
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
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
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
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
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
644
Void flushToByte_SB(SimpleBitIO* pSB)
645
{
646
pSB->bAccumulator = 0;
647
pSB->cBitLeft = 0;
648
}
649
650
// return read byte count
651
U32 getByteRead_SB(SimpleBitIO* pSB)
652
{
653
return pSB->cbRead;
654
}
655
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(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_
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
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
//================================================================
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
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
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
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
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
855
Void freeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS])
856
{
857
if(pQuantizer[0] != NULL)
858
free(pQuantizer[0]);
859
}
860
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
}
873
remapQP(pQuantizer[iCh] + iPos, (iCh > 0 && bShiftedUV == TRUE) ? SHIFTZERO - 1 : SHIFTZERO, bScaledArith);
874
}
875
}
876
877
Void setUniformQuantizer(CWMImageStrCodec * pSC, size_t sb)
878
{
879
size_t iCh, iTile;
880
881
for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
882
for(iTile = 1; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
883
if(sb == 0) // DC
884
pSC->pTile[iTile].pQuantizerDC[iCh] = pSC->pTile[0].pQuantizerDC[iCh];
885
else if(sb == 1) // LP
886
pSC->pTile[iTile].pQuantizerLP[iCh] = pSC->pTile[0].pQuantizerLP[iCh];
887
else // HP
888
pSC->pTile[iTile].pQuantizerHP[iCh] = pSC->pTile[0].pQuantizerHP[iCh];
889
}
890
891
Void useDCQuantizer(CWMImageStrCodec * pSC, size_t iTile)
892
{
893
size_t iCh;
894
895
for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
896
pSC->pTile[iTile].pQuantizerLP[iCh][0] = *pSC->pTile[iTile].pQuantizerDC[iCh];
897
}
898
899
Void useLPQuantizer(CWMImageStrCodec * pSC, size_t cQP, size_t iTile)
900
{
901
size_t iCh, iQP;
902
903
for(iCh = 0; iCh < pSC->m_param.cNumChannels; iCh ++)
904
for(iQP = 0; iQP < cQP; iQP ++)
905
pSC->pTile[iTile].pQuantizerHP[iCh][iQP] = pSC->pTile[iTile].pQuantizerLP[iCh][iQP];
906
}
907
908
U8 dquantBits(U8 cQP)
909
{
910
return (cQP < 2 ? 0 : (cQP < 4 ? 1 : (cQP < 6 ? 2 : (cQP < 10 ? 3 : 4))));
911
}
912
913
#ifndef ARMOPT_BITIO
914
U32 peekBit16(BitIOInfo* pIO, U32 cBits)
915
{
916
PEEKBIT16(pIO, cBits);
917
}
918
919
U32 flushBit16(BitIOInfo* pIO, U32 cBits)
920
{
921
FLUSHBIT16(pIO, cBits);
922
}
923
924
U32 getBit16(BitIOInfo* pIO, U32 cBits)
925
{
926
U32 uiRet = peekBit16(pIO, cBits);
927
flushBit16(pIO, cBits);
928
929
return uiRet;
930
}
931
932
U32 getBool16(BitIOInfo* pIO)
933
{
934
U32 uiRet = peekBit16(pIO, 1);
935
flushBit16(pIO, 1);
936
return uiRet;
937
}
938
939
/** this function returns cBits if zero is read, or a signed value if first cBits are not all zero **/
940
I32 getBit16s(BitIOInfo* pIO, U32 cBits)
941
{
942
U32 uiRet = peekBit16(pIO, cBits + 1);
943
if (uiRet < 2) {
944
flushBit16(pIO, cBits);
945
return 0;
946
}
947
else {
948
flushBit16(pIO, cBits + 1);
949
if (uiRet & 1)
950
return (-(I32)(uiRet >> 1));
951
else
952
return (I32)(uiRet >> 1);
953
}
954
}
955
956
U32 getBit32(BitIOInfo* pIO, U32 cBits)
957
{
958
U32 uiRet = 0;
959
960
assert(0 <= (I32)cBits && cBits <= 32);
961
962
if (16 < cBits)
963
{
964
uiRet = getBit16(pIO, 16);
965
cBits -= 16;
966
uiRet <<= cBits;
967
}
968
969
uiRet |= getBit16(pIO, cBits);
970
971
return uiRet;
972
}
973
974
U32 flushToByte(BitIOInfo* pIO)
975
{
976
return flushBit16(pIO, (16 - pIO->cBitsUsed) & 7);
977
}
978
#endif // ARMOPT_BITIO
979
980
//----------------------------------------------------------------
981
Void putBit16z(BitIOInfo* pIO, U32 uiBits, U32 cBits)
982
{
983
assert(cBits <= 16);
984
assert(0 == uiBits >> cBits);
985
986
pIO->uiAccumulator = (pIO->uiAccumulator << cBits) | uiBits;
987
pIO->cBitsUsed += cBits;
988
989
*(U16*)pIO->pbCurrent = (U16)WRITESWAP_ENDIAN(pIO->uiAccumulator << (32 - pIO->cBitsUsed));
990
991
pIO->pbCurrent = MASKPTR(pIO->pbCurrent + ((pIO->cBitsUsed >> 3) & 2), pIO->iMask);
992
pIO->cBitsUsed &= 16 - 1;
993
}
994
995
Void putBit16(BitIOInfo* pIO, U32 uiBits, U32 cBits)
996
{
997
assert(cBits <= 16);
998
999
uiBits &= ~(-1 << cBits);
1000
putBit16z(pIO, uiBits, cBits);
1001
}
1002
1003
Void putBit32(BitIOInfo* pIO, U32 uiBits, U32 cBits)
1004
{
1005
assert(0 <= (I32)cBits && cBits <= 32);
1006
1007
if (16 < cBits)
1008
{
1009
putBit16(pIO, uiBits >> (cBits - 16), 16);
1010
cBits -= 16;
1011
}
1012
1013
putBit16(pIO, uiBits, cBits);
1014
}
1015
1016
Void fillToByte(BitIOInfo* pIO)
1017
{
1018
putBit16z(pIO, 0, (16 - pIO->cBitsUsed) & 7);
1019
}
1020
1021
//----------------------------------------------------------------
1022
U32 getBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 cBits)
1023
{
1024
U32 rc = getBit16(pIO, cBits);
1025
readIS_L1(pSC, pIO);
1026
1027
return rc;
1028
}
1029
1030
U32 putBit16_S(CWMImageStrCodec* pSC, BitIOInfo* pIO, U32 uiBits, U32 cBits)
1031
{
1032
putBit16(pIO, uiBits, cBits);
1033
writeIS_L1(pSC, pIO);
1034
1035
return 0;
1036
}
1037
1038
1039
//----------------------------------------------------------------
1040
// Query buffered data size held in BitIOInfo
1041
// Write() for Enc, Read() for Dec
1042
//----------------------------------------------------------------
1043
U32 getSizeRead(BitIOInfo* pIO)
1044
{
1045
return (U32)(UINTPTR_T)(pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8;
1046
}
1047
1048
U32 getSizeWrite(BitIOInfo* pIO)
1049
{
1050
return (U32)(UINTPTR_T)(pIO->pbCurrent + (pIO->pbStart <= pIO->pbCurrent ? 0 : PACKETLENGTH * 2) - pIO->pbStart) + pIO->cBitsUsed / 8;
1051
}
1052
1053
//----------------------------------------------------------------
1054
// Query stream offset from attached BitIO object for dec
1055
//----------------------------------------------------------------
1056
U32 getPosRead(BitIOInfo* pIO)
1057
{
1058
size_t cbCached = (pIO->pbStart + PACKETLENGTH * 2 - pIO->pbCurrent) - pIO->cBitsUsed / 8;
1059
return (U32)(pIO->offRef - cbCached);
1060
}
1061
1062
//================================================================
1063
// Block I/O functions
1064
//================================================================
1065
#ifndef ARMOPT_BITIO
1066
ERR attachISRead(BitIOInfo* pIO, struct WMPStream* pWS, CWMImageStrCodec* pSC)
1067
{
1068
UNREFERENCED_PARAMETER( pSC );
1069
1070
pWS->GetPos(pWS, &pIO->offRef);
1071
1072
pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2;
1073
pIO->pbCurrent = pIO->pbStart;
1074
1075
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1076
pWS->SetPos(pWS, pIO->offRef);
1077
pWS->Read(pWS, pIO->pbStart, PACKETLENGTH * 2);
1078
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1079
pIO->offRef += PACKETLENGTH * 2;
1080
1081
pIO->uiAccumulator = load4BE(pIO->pbStart);
1082
1083
pIO->cBitsUsed = 0;
1084
pIO->iMask = ~(PACKETLENGTH * 2);
1085
pIO->iMask &= ~1;
1086
1087
pIO->pWS = pWS;
1088
return WMP_errSuccess;
1089
}
1090
1091
ERR readIS(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1092
{
1093
ERR err = WMP_errSuccess;
1094
1095
UNREFERENCED_PARAMETER( pSC );
1096
1097
if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH))
1098
{
1099
struct WMPStream *pWS = pIO->pWS;
1100
1101
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1102
//Call(0 != pIO->pWS->Read(pIO->pWS, pIO->pbStart, PACKETLENGTH));
1103
// TODO: add error checking code
1104
pWS->SetPos(pWS, pIO->offRef);
1105
pWS->Read(pWS, pIO->pbStart, PACKETLENGTH);
1106
pIO->offRef += PACKETLENGTH;
1107
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1108
1109
// make shadow copy for first 4B
1110
pIO->uiShadow = *(U32*)pIO->pbStart;
1111
1112
// reposition pbPacket pointer
1113
pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask);
1114
}
1115
1116
//Cleanup:
1117
return err;
1118
}
1119
1120
ERR detachISRead(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1121
{
1122
ERR err = WMP_errSuccess;
1123
1124
struct WMPStream* pWS = pIO->pWS;
1125
size_t cbRemain = 0;
1126
1127
// we can ONLY detach IStream at byte boundary
1128
flushToByte(pIO);
1129
assert(0 == (pIO->cBitsUsed % 8));
1130
Call(readIS_L1(pSC, pIO));
1131
1132
// set stream to right offset, undo buffering
1133
cbRemain = (pIO->pbStart + PACKETLENGTH * 2) - (pIO->pbCurrent + pIO->cBitsUsed / 8);
1134
pWS->SetPos(pWS, pIO->offRef - cbRemain);
1135
1136
pIO->pWS = NULL;
1137
Cleanup:
1138
return err;
1139
}
1140
#endif // ARMOPT_BITIO
1141
1142
//----------------------------------------------------------------
1143
ERR attachISWrite(BitIOInfo* pIO, struct WMPStream* pWS)
1144
{
1145
pWS->GetPos(pWS, &pIO->offRef);
1146
1147
pIO->pbStart = (U8*)pIO - PACKETLENGTH * 2;
1148
pIO->pbCurrent = pIO->pbStart;
1149
1150
pIO->uiAccumulator = 0;
1151
pIO->cBitsUsed = 0;
1152
pIO->iMask = ~(PACKETLENGTH * 2);
1153
1154
pIO->pWS = pWS;
1155
return WMP_errSuccess;
1156
}
1157
1158
// write out packet if we have >=1 packet data filled
1159
ERR writeIS(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1160
{
1161
ERR err = WMP_errSuccess;
1162
1163
UNREFERENCED_PARAMETER( pSC );
1164
1165
if (PACKET1(pIO->pbStart, pIO->pbCurrent, PACKETLENGTH))
1166
{
1167
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1168
err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, PACKETLENGTH);
1169
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1170
Call(err);
1171
1172
// reposition pbStart pointer
1173
pIO->pbStart = MASKPTR(pIO->pbStart + PACKETLENGTH, pIO->iMask);
1174
}
1175
1176
Cleanup:
1177
return err;
1178
}
1179
1180
// write out partially filled buffer and detach bitIO from IStream
1181
ERR detachISWrite(CWMImageStrCodec* pSC, BitIOInfo* pIO)
1182
{
1183
ERR err = WMP_errSuccess;
1184
1185
// we can ONLY detach IStream at byte boundary
1186
assert(0 == (pIO->cBitsUsed % 8));
1187
Call(writeIS_L1(pSC, pIO));
1188
1189
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1190
err = pIO->pWS->Write(pIO->pWS, pIO->pbStart, pIO->pbCurrent + pIO->cBitsUsed / 8 - pIO->pbStart);
1191
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1192
Call(err);
1193
1194
pIO->pWS = NULL;
1195
Cleanup:
1196
return err;
1197
}
1198
1199
//=========================
1200
// Performance Measurement
1201
//=========================
1202
#ifndef DISABLE_PERF_MEASUREMENT
1203
1204
void OutputIndivPerfTimer(struct PERFTIMERSTATE *pPerfTimer,
1205
char *pszTimerName,
1206
char *pszDescription,
1207
float fltMegaPixels)
1208
{
1209
PERFTIMERRESULTS rResults;
1210
Bool fResult;
1211
1212
fResult = FALSE;
1213
printf("%s (%s): ", pszTimerName, pszDescription);
1214
if (pPerfTimer)
1215
{
1216
fResult = PerfTimerGetResults(pPerfTimer, &rResults);
1217
if (fResult)
1218
{
1219
printf("%.3f milliseconds, %.6f MP/sec\n", (float)rResults.iElapsedTime / 1000000,
1220
1000000000 * fltMegaPixels / rResults.iElapsedTime);
1221
if (rResults.iZeroTimeIntervals > 0)
1222
{
1223
printf(" *** WARNING: %d time intervals were measured as zero. "
1224
"This perf timer has insufficient precision!\n\n",
1225
(int) rResults.iZeroTimeIntervals);
1226
}
1227
}
1228
}
1229
if (FALSE == fResult)
1230
printf("Results not available!\n");
1231
}
1232
1233
1234
void OutputPerfTimerReport(CWMImageStrCodec *pState)
1235
{
1236
float fltMegaPixels;
1237
1238
assert(pState->m_fMeasurePerf);
1239
1240
printf("***************************************************************************\n");
1241
printf("* Perf Report\n");
1242
printf("***************************************************************************\n\n");
1243
1244
fltMegaPixels = (float)pState->WMII.cWidth * pState->WMII.cHeight / 1000000;
1245
printf("Image Width = %d, Height = %d, total MegaPixels = %.1f MP\n",
1246
(int) pState->WMII.cWidth, (int) pState->WMII.cHeight, fltMegaPixels);
1247
1248
OutputIndivPerfTimer(pState->m_ptEncDecPerf, "m_ptEncDecPerf", "excl I/O", fltMegaPixels);
1249
OutputIndivPerfTimer(pState->m_ptEndToEndPerf, "m_ptEndToEndPerf", "incl I/O", fltMegaPixels);
1250
}
1251
1252
#endif // DISABLE_PERF_MEASUREMENT
1253
1254