Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/jxr/image/encode/strenc.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 "encode.h"
30
#include "strTransform.h"
31
#include <math.h>
32
#include "perfTimer.h"
33
34
#ifdef MEM_TRACE
35
#define TRACE_MALLOC 1
36
#define TRACE_NEW 0
37
#define TRACE_HEAP 0
38
#include "memtrace.h"
39
#endif
40
41
#ifdef ADI_SYS_OPT
42
extern char L1WW[];
43
#endif
44
45
#ifdef X86OPT_INLINE
46
#define _FORCEINLINE __forceinline
47
#else // X86OPT_INLINE
48
#define _FORCEINLINE
49
#endif // X86OPT_INLINE
50
51
Int inputMBRow(CWMImageStrCodec *);
52
53
#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_ENC) || defined(WMP_OPT_TRFM_ENC)
54
void StrEncOpt(CWMImageStrCodec* pSC);
55
#endif // OPT defined
56
57
#define MINIMUM_PACKET_LENGTH 4 // as long as packet header - skipped if data is not accessed (happens only for flexbits)
58
59
Void writeQuantizer(CWMIQuantizer * pQuantizer[MAX_CHANNELS], BitIOInfo * pIO, U8 cChMode, size_t cChannel, size_t iPos)
60
{
61
if(cChMode > 2)
62
cChMode = 2;
63
64
if(cChannel > 1)
65
putBit16(pIO, cChMode, 2); // Channel mode
66
else
67
cChMode = 0;
68
69
putBit16(pIO, pQuantizer[0][iPos].iIndex, 8); // Y
70
71
if(cChMode == 1) // MIXED
72
putBit16(pIO, pQuantizer[1][iPos].iIndex, 8); // UV
73
else if(cChMode > 0){ // INDEPENDENT
74
size_t i;
75
76
for(i = 1; i < cChannel; i ++)
77
putBit16(pIO, pQuantizer[i][iPos].iIndex, 8); // UV
78
}
79
}
80
81
// packet header: 00000000 00000000 00000001 ?????xxx
82
// xxx: 000(spatial) 001(DC) 010(AD) 011(AC) 100(FL) 101-111(reserved)
83
// ?????: (iTileY * cNumOfSliceV + iTileX)
84
Void writePacketHeader(BitIOInfo * pIO, U8 ptPacketType, U8 pID)
85
{
86
putBit16(pIO, 0, 8);
87
putBit16(pIO, 0, 8);
88
putBit16(pIO, 1, 8);
89
putBit16(pIO, (pID << 3) + (ptPacketType & 7), 8);
90
}
91
92
Int writeTileHeaderDC(CWMImageStrCodec * pSC, BitIOInfo * pIO)
93
{
94
size_t iTile, j = (pSC->m_pNextSC == NULL ? 1U : 2U);
95
96
for(; j > 0; j --){
97
if((pSC->m_param.uQPMode & 1) != 0){ // not DC uniform
98
CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
99
size_t i;
100
101
pTile->cChModeDC = (U8)(rand() & 3); // channel mode, just for concept proofing!
102
103
if(pSC->cTileRow + pSC->cTileColumn == 0) // allocate DC QP info
104
for(iTile = 0; iTile <= pSC->WMISCP.cNumOfSliceMinus1V; iTile ++)
105
if(allocateQuantizer(pSC->pTile[iTile].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK)
106
return ICERR_ERROR;
107
108
for(i = 0; i < pSC->m_param.cNumChannels; i ++)
109
pTile->pQuantizerDC[i]->iIndex = (U8)((rand() & 0x2f) + 1); // QP indexes, just for concept proofing!
110
111
formatQuantizer(pTile->pQuantizerDC, pTile->cChModeDC, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
112
113
for(i = 0; i < pSC->m_param.cNumChannels; i ++)
114
pTile->pQuantizerDC[i]->iOffset = (pTile->pQuantizerDC[i]->iQP >> 1);
115
116
writeQuantizer(pTile->pQuantizerDC, pIO, pTile->cChModeDC, pSC->m_param.cNumChannels, 0);
117
}
118
119
pSC = pSC->m_pNextSC;
120
}
121
122
return ICERR_OK;
123
}
124
125
Int writeTileHeaderLP(CWMImageStrCodec * pSC, BitIOInfo * pIO)
126
{
127
size_t k = (pSC->m_pNextSC == NULL ? 1U : 2U);
128
129
for(; k > 0; k --){
130
if(pSC->WMISCP.sbSubband != SB_DC_ONLY && (pSC->m_param.uQPMode & 2) != 0){ // not LP uniform
131
CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
132
U8 i, j;
133
134
pTile->bUseDC = ((rand() & 1) == 0 ? TRUE : FALSE); // use DC quantizer?
135
putBit16(pIO, pTile->bUseDC == TRUE ? 1 : 0, 1);
136
pTile->cBitsLP = 0;
137
138
pTile->cNumQPLP = (pTile->bUseDC == TRUE ? 1 : (U8)((rand() & 0xf) + 1)); // # of LP QPs
139
140
if(pSC->cTileRow > 0)
141
freeQuantizer(pTile->pQuantizerLP);
142
143
if(allocateQuantizer(pTile->pQuantizerLP, pSC->m_param.cNumChannels, pTile->cNumQPLP) != ICERR_OK)
144
return ICERR_ERROR;
145
146
if(pTile->bUseDC == TRUE)
147
useDCQuantizer(pSC, pSC->cTileColumn);
148
else{
149
putBit16(pIO, pTile->cNumQPLP - 1, 4);
150
151
pTile->cBitsLP = dquantBits(pTile->cNumQPLP);
152
153
for(i = 0; i < pTile->cNumQPLP; i ++){
154
pTile->cChModeLP[i] = (U8)(rand() & 3); // channel mode, just for concept proofing!
155
156
for(j = 0; j < pSC->m_param.cNumChannels; j ++)
157
pTile->pQuantizerLP[j][i].iIndex = (U8)((rand() & 0xfe) + 1); // QP indexes, just for concept proofing!
158
formatQuantizer(pTile->pQuantizerLP, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i, TRUE, pSC->m_param.bScaledArith);
159
writeQuantizer(pTile->pQuantizerLP, pIO, pTile->cChModeLP[i], pSC->m_param.cNumChannels, i);
160
}
161
}
162
}
163
pSC = pSC->m_pNextSC;
164
}
165
166
return ICERR_OK;
167
}
168
169
Int writeTileHeaderHP(CWMImageStrCodec * pSC, BitIOInfo * pIO)
170
{
171
size_t k = (pSC->m_pNextSC == NULL ? 1U : 2U);
172
173
for(; k > 0; k --){
174
if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS && (pSC->m_param.uQPMode & 4) != 0){ // not HP uniform
175
CWMITile * pTile = pSC->pTile + pSC->cTileColumn;
176
U8 i, j;
177
178
pTile->bUseLP = ((rand() & 1) == 0 ? TRUE : FALSE); // use LP quantizer?
179
putBit16(pIO, pTile->bUseLP == TRUE ? 1 : 0, 1);
180
pTile->cBitsHP = 0;
181
182
pTile->cNumQPHP = (pTile->bUseLP == TRUE ? pTile->cNumQPLP : (U8)((rand() & 0xf) + 1)); // # of LP QPs
183
184
if(pSC->cTileRow > 0)
185
freeQuantizer(pTile->pQuantizerHP);
186
187
if(allocateQuantizer(pTile->pQuantizerHP, pSC->m_param.cNumChannels, pTile->cNumQPHP) != ICERR_OK)
188
return ICERR_ERROR;
189
190
if(pTile->bUseLP == TRUE)
191
useLPQuantizer(pSC, pTile->cNumQPHP, pSC->cTileColumn);
192
else{
193
putBit16(pIO, pTile->cNumQPHP - 1, 4);
194
pTile->cBitsHP = dquantBits(pTile->cNumQPHP);
195
196
for(i = 0; i < pTile->cNumQPHP; i ++){
197
pTile->cChModeHP[i] = (U8)(rand() & 3); // channel mode, just for concept proofing!
198
199
for(j = 0; j < pSC->m_param.cNumChannels; j ++)
200
pTile->pQuantizerHP[j][i].iIndex = (U8)((rand() & 0xfe) + 1); // QP indexes, just for concept proofing!
201
formatQuantizer(pTile->pQuantizerHP, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i, FALSE, pSC->m_param.bScaledArith);
202
writeQuantizer(pTile->pQuantizerHP, pIO, pTile->cChModeHP[i], pSC->m_param.cNumChannels, i);
203
}
204
}
205
}
206
pSC = pSC->m_pNextSC;
207
}
208
209
return ICERR_OK;
210
}
211
212
Int encodeMB(CWMImageStrCodec * pSC, Int iMBX, Int iMBY)
213
{
214
CCodingContext * pContext = &pSC->m_pCodingContext[pSC->cTileColumn];
215
216
if(pSC->m_bCtxLeft && pSC->m_bCtxTop && pSC->m_bSecondary == FALSE && pSC->m_param.bTranscode == FALSE){ // write packet headers
217
U8 pID = (U8)((pSC->cTileRow * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + pSC->cTileColumn) & 0x1F);
218
219
if(pSC->WMISCP.bfBitstreamFormat == SPATIAL) {
220
writePacketHeader(pContext->m_pIODC, 0, pID);
221
if (pSC->m_param.bTrimFlexbitsFlag)
222
putBit16(pContext->m_pIODC, pContext->m_iTrimFlexBits, 4);
223
writeTileHeaderDC(pSC, pContext->m_pIODC);
224
writeTileHeaderLP(pSC, pContext->m_pIODC);
225
writeTileHeaderHP(pSC, pContext->m_pIODC);
226
}
227
else{
228
writePacketHeader(pContext->m_pIODC, 1, pID);
229
writeTileHeaderDC(pSC, pContext->m_pIODC);
230
if(pSC->cSB > 1){
231
writePacketHeader(pContext->m_pIOLP, 2, pID);
232
writeTileHeaderLP(pSC, pContext->m_pIOLP);
233
}
234
if(pSC->cSB > 2){
235
writePacketHeader(pContext->m_pIOAC, 3, pID);
236
writeTileHeaderHP(pSC, pContext->m_pIOAC);
237
}
238
if(pSC->cSB > 3) {
239
writePacketHeader(pContext->m_pIOFL, 4, pID);
240
if (pSC->m_param.bTrimFlexbitsFlag)
241
putBit16(pContext->m_pIOFL, pContext->m_iTrimFlexBits, 4);
242
}
243
}
244
}
245
246
if(EncodeMacroblockDC(pSC, pContext, iMBX, iMBY) != ICERR_OK)
247
return ICERR_ERROR;
248
249
if(pSC->WMISCP.sbSubband != SB_DC_ONLY)
250
if(EncodeMacroblockLowpass(pSC, pContext, iMBX, iMBY) != ICERR_OK)
251
return ICERR_ERROR;
252
253
if(pSC->WMISCP.sbSubband != SB_DC_ONLY && pSC->WMISCP.sbSubband != SB_NO_HIGHPASS)
254
if(EncodeMacroblockHighpass(pSC, pContext, iMBX, iMBY) != ICERR_OK)
255
return ICERR_ERROR;
256
257
if(iMBX + 1 == (int) pSC->cmbWidth && (iMBY + 1 == (int) pSC->cmbHeight ||
258
(pSC->cTileRow < pSC->WMISCP.cNumOfSliceMinus1H && iMBY == (int) pSC->WMISCP.uiTileY[pSC->cTileRow + 1] - 1)))
259
{ // end of a horizontal slice
260
size_t k, l;
261
262
// get sizes of each packet and update index table
263
if (pSC->m_pNextSC == NULL || pSC->m_bSecondary) {
264
for(k = 0; k < pSC->cNumBitIO; k ++){
265
fillToByte(pSC->m_ppBitIO[k]);
266
pSC->ppWStream[k]->GetPos(pSC->ppWStream[k], &l);
267
pSC->pIndexTable[pSC->cNumBitIO * pSC->cTileRow + k] = l + getSizeWrite(pSC->m_ppBitIO[k]); // offset
268
}
269
}
270
271
// reset coding contexts
272
if(iMBY + 1 != (int) pSC->cmbHeight){
273
for(k = 0; k <= pSC->WMISCP.cNumOfSliceMinus1V; k ++)
274
ResetCodingContextEnc(&pSC->m_pCodingContext[k]);
275
}
276
}
277
278
return ICERR_OK;
279
}
280
281
/*************************************************************************
282
Top level function for processing a macroblock worth of input
283
*************************************************************************/
284
Int processMacroblock(CWMImageStrCodec *pSC)
285
{
286
Bool topORleft = (pSC->cColumn == 0 || pSC->cRow == 0);
287
ERR_CODE result = ICERR_OK;
288
size_t j, jend = (pSC->m_pNextSC != NULL);
289
290
for (j = 0; j <= jend; j++) {
291
transformMacroblock(pSC);
292
if(!topORleft){
293
getTilePos(pSC, (Int)pSC->cColumn - 1, (Int)pSC->cRow - 1);
294
if(jend){
295
pSC->m_pNextSC->cTileRow = pSC->cTileRow;
296
pSC->m_pNextSC->cTileColumn = pSC->cTileColumn;
297
}
298
if ((result = encodeMB(pSC, (Int)pSC->cColumn - 1, (Int)pSC->cRow - 1)) != ICERR_OK)
299
return result;
300
}
301
302
if (jend) {
303
pSC->m_pNextSC->cRow = pSC->cRow;
304
pSC->m_pNextSC->cColumn = pSC->cColumn;
305
pSC = pSC->m_pNextSC;
306
}
307
}
308
309
return ICERR_OK;
310
}
311
312
/*************************************************************************
313
forwardRGBE: forward conversion from RGBE to RGB
314
*************************************************************************/
315
static _FORCEINLINE PixelI forwardRGBE (PixelI RGB, PixelI E)
316
{
317
PixelI iResult = 0, iAppend = 1;
318
319
if (E == 0)
320
return 0;
321
322
assert (E!=0);
323
324
E--;
325
while (((RGB & 0x80) == 0) && (E > 0)) {
326
RGB = (RGB << 1) + iAppend;
327
iAppend = 0;
328
E--;
329
}
330
331
// result will always be one of 3 cases
332
// E RGB convert to
333
// 0 [0.x] [0 x]
334
// 0 [1.x] [1 x]
335
// e [1.x] [e+1 x]
336
if (E == 0) {
337
iResult = RGB;
338
}
339
else {
340
E++;
341
iResult = (RGB & 0x7f) + (E << 7);
342
}
343
344
return iResult;
345
}
346
347
/*************************************************************************
348
convert float-32 into float with (c, lm)!!
349
*************************************************************************/
350
static _FORCEINLINE PixelI float2pixel (float f, const char _c, const unsigned char _lm)
351
{
352
union uif
353
{
354
I32 i;
355
float f;
356
} x;
357
358
PixelI _h, e, e1, m, s;
359
360
if (f == 0)
361
{
362
_h = 0;
363
}
364
else
365
{
366
x.f = f;
367
368
e = (x.i >> 23) & 0x000000ff;//here set e as e, not s! e includes s: [s e] 9 bits [31..23]
369
m = (x.i & 0x007fffff) | 0x800000; // actual mantissa, with normalizer
370
if (e == 0) { // denormal-land
371
m ^= 0x800000; // actual mantissa, removing normalizer
372
e++; // actual exponent -126
373
}
374
375
e1 = e - 127 + _c; // this is basically a division or quantization to a different exponent
376
// note: _c cannot be greater than 127, so e1 cannot be greater than e
377
//assert (_c <= 127);
378
if (e1 <= 1) { // denormal-land
379
if (e1 < 1)
380
m >>= (1 - e1); // shift mantissa right to make exponent 1
381
e1 = 1;
382
if ((m & 0x800000) == 0) // if denormal, set e1 to zero else to 1
383
e1 = 0;
384
}
385
m &= 0x007fffff;
386
387
//for float-22:
388
_h = (e1 << _lm) + ((m + (1 << (23 - _lm - 1))) >> (23 - _lm));//take 23-bit m, shift (23-lm), get lm-bit m for float22
389
s = ((PixelI) x.i) >> 31;
390
//padding to int-32:
391
_h = (_h ^ s) - s;
392
}
393
394
return _h;
395
}
396
397
/*************************************************************************
398
convert Half-16 to internal format, only need to handle sign bit
399
*************************************************************************/
400
static _FORCEINLINE PixelI forwardHalf (PixelI hHalf)
401
{
402
PixelI s;
403
s = hHalf >> 31;
404
hHalf = ((hHalf & 0x7fff) ^ s) - s;
405
return hHalf;
406
}
407
408
409
//================================================================
410
// Color Conversion
411
// functions to get image data from input buffer
412
// this inlcudes necessary color conversion and boundary padding
413
//================================================================
414
#define _CC(r, g, b) (b -= r, r += ((b + 1) >> 1) - g, g += ((r + 0) >> 1))
415
#define _CC_CMYK(c, m, y, k) (y -= c, c += ((y + 1) >> 1) - m, m += (c >> 1) - k, k += ((m + 1) >> 1))
416
417
//================================================================
418
// BitIOInfo init/term for encoding
419
const size_t MAX_MEMORY_SIZE_IN_WORDS = 64 << 20; // 1 << 20 \approx 1 million
420
421
Int StrIOEncInit(CWMImageStrCodec* pSC)
422
{
423
pSC->m_param.bIndexTable = !(pSC->WMISCP.bfBitstreamFormat == SPATIAL && pSC->WMISCP.cNumOfSliceMinus1H + pSC->WMISCP.cNumOfSliceMinus1V == 0);
424
if(allocateBitIOInfo(pSC) != ICERR_OK){
425
return ICERR_ERROR;
426
}
427
428
attachISWrite(pSC->pIOHeader, pSC->WMISCP.pWStream);
429
430
if(pSC->cNumBitIO > 0){
431
size_t i;
432
#if defined(_WINDOWS_) || defined(UNDER_CE) // tmpnam does not exist in VS2005 WinCE CRT
433
TCHAR szPath[MAX_PATH];
434
DWORD cSize, j, k;
435
#endif
436
char * pFilename;
437
438
pSC->ppWStream = (struct WMPStream **)malloc(pSC->cNumBitIO * sizeof(struct WMPStream *));
439
if(pSC->ppWStream == NULL) return ICERR_ERROR;
440
memset(pSC->ppWStream, 0, pSC->cNumBitIO * sizeof(struct WMPStream *));
441
442
if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS) {
443
#ifdef _WINDOWS_
444
pSC->ppTempFile = (TCHAR **)malloc(pSC->cNumBitIO * sizeof(TCHAR *));
445
if(pSC->ppTempFile == NULL) return ICERR_ERROR;
446
memset(pSC->ppTempFile, 0, pSC->cNumBitIO * sizeof(TCHAR *));
447
#else
448
pSC->ppTempFile = (char **)malloc(pSC->cNumBitIO * sizeof(char *));
449
if(pSC->ppTempFile == NULL) return ICERR_ERROR;
450
memset(pSC->ppTempFile, 0, pSC->cNumBitIO * sizeof(char *));
451
#endif
452
}
453
454
for(i = 0; i < pSC->cNumBitIO; i ++){
455
if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS) {
456
#if defined(_WINDOWS_) || defined(UNDER_CE) // tmpnam does not exist in VS2005 WinCE CRT
457
Bool bUnicode = sizeof(TCHAR) == 2;
458
pSC->ppTempFile[i] = (TCHAR *)malloc(MAX_PATH * sizeof(TCHAR));
459
if(pSC->ppTempFile[i] == NULL) return ICERR_ERROR;
460
461
pFilename = (char *)pSC->ppTempFile[i];
462
463
cSize = GetTempPath(MAX_PATH, szPath);
464
if(cSize == 0 || cSize >= MAX_PATH)
465
return ICERR_ERROR;
466
if(!GetTempFileName(szPath, TEXT("wdp"), 0, pSC->ppTempFile[i]))
467
return ICERR_ERROR;
468
469
if(bUnicode){ // unicode file name
470
for(k = j = cSize = 0; cSize < MAX_PATH; cSize ++, j += 2){
471
if(pSC->ppTempFile[i][cSize] == '\0')
472
break;
473
if(pFilename[j] != '\0')
474
pFilename[k ++] = pFilename[j];
475
if(pFilename[j + 1] != '\0')
476
pFilename[k ++] = pFilename[j + 1];
477
}
478
pFilename[cSize] = '\0';
479
}
480
481
#else //DPK needs to support ANSI
482
pSC->ppTempFile[i] = (char *)malloc(FILENAME_MAX * sizeof(char));
483
if(pSC->ppTempFile[i] == NULL) return ICERR_ERROR;
484
485
if ((pFilename = tmpnam(NULL)) == NULL)
486
return ICERR_ERROR;
487
strcpy(pSC->ppTempFile[i], pFilename);
488
#endif
489
if(CreateWS_File(pSC->ppWStream + i, pFilename, "w+b") != ICERR_OK) return ICERR_ERROR;
490
491
}
492
else {
493
if(CreateWS_List(pSC->ppWStream + i) != ICERR_OK) return ICERR_ERROR;
494
}
495
attachISWrite(pSC->m_ppBitIO[i], pSC->ppWStream[i]);
496
}
497
}
498
499
return ICERR_OK;
500
}
501
502
#define PUTBITS putBit16
503
/*************************************************************************
504
Write variable length byte aligned integer
505
*************************************************************************/
506
static Void PutVLWordEsc(BitIOInfo* pIO, Int iEscape, size_t s)
507
{
508
if (iEscape) {
509
assert(iEscape <= 0xff && iEscape > 0xfc); // fd,fe,ff are the only valid escapes
510
PUTBITS(pIO, iEscape, 8);
511
}
512
else if (s < 0xfb00) {
513
PUTBITS(pIO, (U32) s, 16);
514
}
515
else {
516
size_t t = s >> 16;
517
if ((t >> 16) == 0) {
518
PUTBITS(pIO, 0xfb, 8);
519
}
520
else {
521
t >>= 16;
522
PUTBITS(pIO, 0xfc, 8);
523
PUTBITS(pIO, (U32)(t >> 16) & 0xffff, 16);
524
PUTBITS(pIO, (U32) t & 0xffff, 16);
525
}
526
PUTBITS(pIO, (U32) t & 0xffff, 16);
527
PUTBITS(pIO, (U32) s & 0xffff, 16);
528
}
529
}
530
531
/*************************************************************************
532
Write index table at start (null index table)
533
*************************************************************************/
534
Int writeIndexTableNull(CWMImageStrCodec * pSC)
535
{
536
if(pSC->cNumBitIO == 0){
537
BitIOInfo* pIO = pSC->pIOHeader;
538
fillToByte(pIO);
539
540
/* Profile / Level info */
541
PutVLWordEsc(pIO, 0, 4); // 4 bytes
542
PUTBITS(pIO, 111, 8); // default profile idc
543
PUTBITS(pIO, 255, 8); // default level idc
544
PUTBITS(pIO, 1, 16); // LAST_FLAG
545
}
546
547
return ICERR_OK;
548
}
549
550
/*************************************************************************
551
Write index table
552
*************************************************************************/
553
Int writeIndexTable(CWMImageStrCodec * pSC)
554
{
555
if(pSC->cNumBitIO > 0){
556
BitIOInfo* pIO = pSC->pIOHeader;
557
size_t *pTable = pSC->pIndexTable, iSize[4] = { 0 };
558
I32 iEntry = (I32)pSC->cNumBitIO * (pSC->WMISCP.cNumOfSliceMinus1H + 1), i, k, l;
559
560
// write index table header [0x0001] - 2 bytes
561
PUTBITS(pIO, 1, 16);
562
563
for(i = pSC->WMISCP.cNumOfSliceMinus1H; i>= 0 && pSC->bTileExtraction == FALSE; i --){
564
for(k = 0; k < (int)pSC->cNumBitIO; ){
565
for(l = 0; l < (pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++, k ++)
566
{
567
if (i > 0)
568
pTable[pSC->cNumBitIO * i + k] -= pSC->pIndexTable[pSC->cNumBitIO * (i - 1) + k]; // packet length
569
iSize[l] += pTable[pSC->cNumBitIO * i + k];
570
}
571
}
572
}
573
574
iSize[3] = iSize[2] + iSize[1] + iSize[0];
575
iSize[2] = iSize[1] + iSize[0];
576
iSize[1] = iSize[0];
577
iSize[0] = 0;
578
579
for(i = 0; i < iEntry; ){
580
for(l = 0; l < (pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++, i ++)
581
{
582
writeIS_L1(pSC, pIO);
583
PutVLWordEsc(pIO, (pTable[i] <= MINIMUM_PACKET_LENGTH) ? 0xff : 0, iSize[l]);
584
iSize[l] += (pTable[i] <= MINIMUM_PACKET_LENGTH) ? 0 : pTable[i];
585
}
586
}
587
588
writeIS_L1(pSC, pIO);
589
PutVLWordEsc(pIO, 0xff, 0); // escape to end
590
fillToByte(pIO);
591
}
592
593
return ICERR_OK;
594
}
595
596
Int copyTo(struct WMPStream * pSrc, struct WMPStream * pDst, size_t iBytes)
597
{
598
char pData[PACKETLENGTH];
599
600
if (iBytes <= MINIMUM_PACKET_LENGTH){
601
pSrc->Read(pSrc, pData, iBytes);
602
return ICERR_OK;
603
}
604
605
while(iBytes > PACKETLENGTH){
606
pSrc->Read(pSrc, pData, PACKETLENGTH);
607
pDst->Write(pDst, pData, PACKETLENGTH);
608
iBytes -= PACKETLENGTH;
609
}
610
pSrc->Read(pSrc, pData, iBytes);
611
pDst->Write(pDst, pData, iBytes);
612
613
return ICERR_OK;
614
}
615
616
Int StrIOEncTerm(CWMImageStrCodec* pSC)
617
{
618
BitIOInfo * pIO = pSC->pIOHeader;
619
620
fillToByte(pIO);
621
622
if(pSC->WMISCP.bVerbose){
623
U32 i, j;
624
625
printf("\n%d horizontal tiles:\n", pSC->WMISCP.cNumOfSliceMinus1H + 1);
626
for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){
627
printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileY[i]);
628
}
629
630
printf("\n%d vertical tiles:\n", pSC->WMISCP.cNumOfSliceMinus1V + 1);
631
for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
632
printf(" offset of tile %d in MBs: %d\n", i, pSC->WMISCP.uiTileX[i]);
633
}
634
635
if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
636
printf("\nSpatial order bitstream\n");
637
}
638
else{
639
printf("\nFrequency order bitstream\n");
640
}
641
642
if(!pSC->m_param.bIndexTable){
643
printf("\nstreaming mode, no index table.\n");
644
}
645
else if(pSC->WMISCP.bfBitstreamFormat == SPATIAL){
646
for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){
647
for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
648
printf("bitstream size for tile (%d, %d): %d.\n", j, i, (int) pSC->pIndexTable[j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i]);
649
}
650
}
651
}
652
else{
653
for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1H; j ++){
654
for(i = 0; i <= pSC->WMISCP.cNumOfSliceMinus1V; i ++){
655
size_t * p = &pSC->pIndexTable[(j * (pSC->WMISCP.cNumOfSliceMinus1V + 1) + i) * 4];
656
printf("bitstream size of (DC, LP, AC, FL) for tile (%d, %d): %d %d %d %d.\n", j, i,
657
(int) p[0], (int) p[1], (int) p[2], (int) p[3]);
658
}
659
}
660
}
661
}
662
663
writeIndexTable(pSC); // write index table to the header
664
665
detachISWrite(pSC, pIO);
666
667
if(pSC->cNumBitIO > 0){
668
size_t i, j, k, l;
669
struct WMPStream * pDst = pSC->WMISCP.pWStream;
670
size_t * pTable = pSC->pIndexTable;
671
672
for(i = 0; i < pSC->cNumBitIO; i ++){
673
detachISWrite(pSC, pSC->m_ppBitIO[i]);
674
}
675
676
for(i = 0; i < pSC->cNumBitIO; i ++){
677
pSC->ppWStream[i]->SetPos(pSC->ppWStream[i], 0); // seek back for read
678
}
679
680
for(l = 0; l < (size_t)(pSC->WMISCP.bfBitstreamFormat == FREQUENCY && pSC->WMISCP.bProgressiveMode ? pSC->cSB : 1); l ++){
681
for(i = 0, k = l; i <= pSC->WMISCP.cNumOfSliceMinus1H; i ++){ // loop through tiles
682
for(j = 0; j <= pSC->WMISCP.cNumOfSliceMinus1V; j ++){
683
684
if(pSC->WMISCP.bfBitstreamFormat == SPATIAL)
685
copyTo(pSC->ppWStream[j], pDst, pTable[k ++]);
686
else if (!pSC->WMISCP.bProgressiveMode){
687
copyTo(pSC->ppWStream[j * pSC->cSB + 0], pDst, pTable[k ++]);
688
if(pSC->cSB > 1)
689
copyTo(pSC->ppWStream[j * pSC->cSB + 1], pDst, pTable[k ++]);
690
if(pSC->cSB > 2)
691
copyTo(pSC->ppWStream[j * pSC->cSB + 2], pDst, pTable[k ++]);
692
if(pSC->cSB > 3)
693
copyTo(pSC->ppWStream[j * pSC->cSB + 3], pDst, pTable[k ++]);
694
}
695
else{
696
copyTo(pSC->ppWStream[j * pSC->cSB + l], pDst, pTable[k]);
697
k += pSC->cSB;
698
}
699
}
700
}
701
}
702
703
if (pSC->cmbHeight * pSC->cmbWidth * pSC->WMISCP.cChannel >= MAX_MEMORY_SIZE_IN_WORDS){
704
for(i = 0; i < pSC->cNumBitIO; i ++){
705
if(pSC->ppWStream && pSC->ppWStream[i]){
706
if((*(pSC->ppWStream + i))->state.file.pFile){
707
fclose((*(pSC->ppWStream + i))->state.file.pFile);
708
#ifdef _WINDOWS_
709
if(DeleteFileA((LPCSTR)pSC->ppTempFile[i]) == 0)
710
return ICERR_ERROR;
711
#else
712
if (remove(pSC->ppTempFile[i]) == -1)
713
return ICERR_ERROR;
714
#endif
715
}
716
717
if (*(pSC->ppWStream + i))
718
free(*(pSC->ppWStream + i));
719
}
720
if(pSC->ppTempFile){
721
if(pSC->ppTempFile[i])
722
free(pSC->ppTempFile[i]);
723
}
724
}
725
726
if(pSC->ppTempFile)
727
free(pSC->ppTempFile);
728
}
729
else{
730
for(i = 0; i < pSC->cNumBitIO; i ++){
731
if(pSC->ppWStream && pSC->ppWStream[i])
732
pSC->ppWStream[i]->Close(pSC->ppWStream + i);
733
}
734
}
735
736
free(pSC->ppWStream);
737
738
free(pSC->m_ppBitIO);
739
free(pSC->pIndexTable);
740
}
741
742
return 0;
743
}
744
745
/*************************************************************************
746
Write header of image plane
747
*************************************************************************/
748
Int WriteImagePlaneHeader(CWMImageStrCodec * pSC)
749
{
750
CWMImageInfo * pII = &pSC->WMII;
751
CWMIStrCodecParam * pSCP = &pSC->WMISCP;
752
BitIOInfo* pIO = pSC->pIOHeader;
753
754
PUTBITS(pIO, (Int) pSC->m_param.cfColorFormat, 3); // internal color format
755
PUTBITS(pIO, (Int) pSC->m_param.bScaledArith, 1); // lossless mode
756
757
// subbands
758
PUTBITS(pIO, (U32)pSCP->sbSubband, 4);
759
760
// color parameters
761
switch (pSC->m_param.cfColorFormat) {
762
case YUV_420:
763
case YUV_422:
764
case YUV_444:
765
PUTBITS(pIO, 0, 4);
766
PUTBITS(pIO, 0, 4);
767
break;
768
case NCOMPONENT:
769
PUTBITS(pIO, (Int) pSC->m_param.cNumChannels - 1, 4);
770
PUTBITS(pIO, 0, 4);
771
break;
772
default:
773
break;
774
}
775
776
// float and 32s additional parameters
777
switch (pII->bdBitDepth) {
778
case BD_16:
779
case BD_16S:
780
PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);
781
break;
782
case BD_32:
783
case BD_32S:
784
if(pSCP->nLenMantissaOrShift == 0)
785
pSCP->nLenMantissaOrShift = 10;//default
786
PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);
787
break;
788
case BD_32F:
789
if(pSCP->nLenMantissaOrShift == 0)
790
pSCP->nLenMantissaOrShift = 13;//default
791
PUTBITS(pIO, pSCP->nLenMantissaOrShift, 8);//float conversion parameters
792
PUTBITS(pIO, pSCP->nExpBias, 8);
793
break;
794
default:
795
break;
796
}
797
798
// quantization
799
PUTBITS(pIO, (pSC->m_param.uQPMode & 1) == 1 ? 0 : 1, 1); // DC frame uniform quantization?
800
if((pSC->m_param.uQPMode & 1) == 0)
801
writeQuantizer(pSC->pTile[0].pQuantizerDC, pIO, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0);
802
if(pSC->WMISCP.sbSubband != SB_DC_ONLY){
803
PUTBITS(pIO, (pSC->m_param.uQPMode & 0x200) == 0 ? 1 : 0, 1); // use DC quantization?
804
if((pSC->m_param.uQPMode & 0x200) != 0){
805
PUTBITS(pIO, (pSC->m_param.uQPMode & 2) == 2 ? 0 : 1, 1); // LP frame uniform quantization?
806
if((pSC->m_param.uQPMode & 2) == 0)
807
writeQuantizer(pSC->pTile[0].pQuantizerLP, pIO, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0);
808
}
809
810
if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){
811
PUTBITS(pIO, (pSC->m_param.uQPMode & 0x400) == 0 ? 1 : 0, 1); // use LP quantization?
812
if((pSC->m_param.uQPMode & 0x400) != 0){
813
PUTBITS(pIO, (pSC->m_param.uQPMode & 4) == 4 ? 0 : 1, 1); // HP frame uniform quantization?
814
if((pSC->m_param.uQPMode & 4) == 0)
815
writeQuantizer(pSC->pTile[0].pQuantizerHP, pIO, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0);
816
}
817
}
818
}
819
820
fillToByte(pIO); // remove this later
821
return ICERR_OK;
822
}
823
824
/*************************************************************************
825
Write header to buffer
826
*************************************************************************/
827
Int WriteWMIHeader(CWMImageStrCodec * pSC)
828
{
829
CWMImageInfo * pII = &pSC->WMII;
830
CWMIStrCodecParam * pSCP = &pSC->WMISCP;
831
CCoreParameters * pCoreParam = &pSC->m_param;
832
BitIOInfo* pIO = pSC->pIOHeader;
833
U32 /*iSizeOfSize = 2,*/ i;
834
// temporary assignments / reserved words
835
// const Int HEADERSIZE = 0;
836
Bool bInscribed = FALSE;
837
Bool bAbbreviatedHeader = (((pII->cWidth + 15) / 16 > 255 || (pII->cHeight + 15) / 16 > 255) ? FALSE : TRUE);
838
839
if(pCoreParam->bTranscode == FALSE)
840
pCoreParam->cExtraPixelsTop = pCoreParam->cExtraPixelsLeft = pCoreParam->cExtraPixelsRight = pCoreParam->cExtraPixelsBottom = 0;
841
842
// num of extra boundary pixels due to compressed domain processing
843
bInscribed = (pCoreParam->cExtraPixelsTop || pCoreParam->cExtraPixelsLeft || pCoreParam->cExtraPixelsBottom || pCoreParam->cExtraPixelsRight);
844
845
// 0
846
/** signature **/
847
for (i = 0; i < 8; PUTBITS(pSC->pIOHeader, gGDISignature[i++], 8));
848
849
// 8
850
/** codec version and subversion **/
851
PUTBITS(pIO, CODEC_VERSION, 4); // this should be changed to "profile" in RTM
852
if (pSC->WMISCP.bUseHardTileBoundaries)
853
PUTBITS(pIO, CODEC_SUBVERSION_NEWSCALING_HARD_TILES, 4);
854
else
855
PUTBITS(pIO, CODEC_SUBVERSION_NEWSCALING_SOFT_TILES, 4);
856
857
// 9 primary parameters
858
PUTBITS(pIO, (pSCP->cNumOfSliceMinus1V || pSCP->cNumOfSliceMinus1H) ? 1 : 0, 1); // tiling present
859
PUTBITS(pIO, (Int) pSCP->bfBitstreamFormat, 1); // bitstream layout
860
PUTBITS(pIO, pII->oOrientation, 3); // m_iRotateFlip
861
PUTBITS(pIO, pSC->m_param.bIndexTable, 1); // index table present
862
PUTBITS(pIO, pSCP->olOverlap, 2); // overlap
863
864
// 10
865
PUTBITS(pIO, bAbbreviatedHeader, 1); // short words for size and tiles
866
PUTBITS(pIO, 1, 1); // long word length (use intelligence later)
867
PUTBITS(pIO, bInscribed, 1); // windowing
868
PUTBITS(pIO, pSC->m_param.bTrimFlexbitsFlag, 1); // trim flexbits flag sent
869
PUTBITS(pIO, 0, 1); // tile stretching parameters (not enabled)
870
PUTBITS(pIO, 0, 2); // reserved bits
871
PUTBITS(pIO, (Int) pSC->m_param.bAlphaChannel, 1); // alpha channel present
872
873
// 11 - informational
874
PUTBITS(pIO, (Int) pII->cfColorFormat, 4); // source color format
875
if(BD_1 == pII->bdBitDepth && pSCP->bBlackWhite)
876
PUTBITS(pIO, (Int) BD_1alt, 4); // source bit depth
877
else
878
PUTBITS(pIO, (Int) pII->bdBitDepth, 4); // source bit depth
879
880
// 12 - Variable length fields
881
// size
882
putBit32(pIO, (U32)(pII->cWidth - 1), bAbbreviatedHeader ? 16 : 32);
883
putBit32(pIO, (U32)(pII->cHeight - 1), bAbbreviatedHeader ? 16 : 32);
884
885
// tiling
886
if (pSCP->cNumOfSliceMinus1V || pSCP->cNumOfSliceMinus1H) {
887
PUTBITS(pIO, pSCP->cNumOfSliceMinus1V, LOG_MAX_TILES); // # of vertical slices
888
PUTBITS(pIO, pSCP->cNumOfSliceMinus1H, LOG_MAX_TILES); // # of horizontal slices
889
}
890
891
// tile sizes
892
for(i = 0; i < pSCP->cNumOfSliceMinus1V; i ++){ // width in MB of vertical slices, not needed for last slice!
893
PUTBITS(pIO, pSCP->uiTileX[i + 1] - pSCP->uiTileX[i], bAbbreviatedHeader ? 8 : 16);
894
}
895
for(i = 0; i < pSCP->cNumOfSliceMinus1H; i ++){ // width in MB of horizontal slices, not needed for last slice!
896
PUTBITS(pIO, pSCP->uiTileY[i + 1] - pSCP->uiTileY[i], bAbbreviatedHeader ? 8 : 16);
897
}
898
899
// window due to compressed domain processing
900
if (bInscribed) {
901
PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsTop, 6);
902
PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsLeft, 6);
903
PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsBottom, 6);
904
PUTBITS(pIO, (U32)pCoreParam->cExtraPixelsRight, 6);
905
}
906
fillToByte(pIO); // redundant
907
908
// write image plane headers
909
WriteImagePlaneHeader(pSC);
910
911
return ICERR_OK;
912
}
913
914
// streaming codec init/term
915
Int StrEncInit(CWMImageStrCodec* pSC)
916
{
917
COLORFORMAT cf = pSC->m_param.cfColorFormat;
918
COLORFORMAT cfE = pSC->WMII.cfColorFormat;
919
U16 iQPIndexY = 0, iQPIndexYLP = 0, iQPIndexYHP = 0;
920
U16 iQPIndexU = 0, iQPIndexULP = 0, iQPIndexUHP = 0;
921
U16 iQPIndexV = 0, iQPIndexVLP = 0, iQPIndexVHP = 0;
922
size_t i;
923
Bool b32bit = sizeof(size_t) == 4;
924
925
/** color transcoding with resolution change **/
926
pSC->m_bUVResolutionChange = (((cfE == CF_RGB || cfE == YUV_444 || cfE == CMYK || cfE == CF_RGBE) &&
927
(cf == YUV_422 || cf == YUV_420))
928
|| (cfE == YUV_422 && cf == YUV_420)) && !pSC->WMISCP.bYUVData;
929
930
if(pSC->m_bUVResolutionChange){
931
size_t cSize = ((cfE == YUV_422 ? 128 : 256) + (cf == YUV_420 ? 32 : 0)) * pSC->cmbWidth + 256;
932
933
if(b32bit){ // integer overlow/underflow check for 32-bit system
934
if(((pSC->cmbWidth >> 16) * ((cfE == YUV_422 ? 128 : 256) + (cf == YUV_420 ? 32 : 0))) & 0xffff0000)
935
return ICERR_ERROR;
936
if(cSize >= 0x3fffffff)
937
return ICERR_ERROR;
938
}
939
pSC->pResU = (PixelI *)malloc(cSize * sizeof(PixelI));
940
pSC->pResV = (PixelI *)malloc(cSize * sizeof(PixelI));
941
if(pSC->pResU == NULL || pSC->pResV == NULL){
942
return ICERR_ERROR;
943
}
944
}
945
946
pSC->cTileColumn = pSC->cTileRow = 0;
947
948
if(allocateTileInfo(pSC) != ICERR_OK)
949
return ICERR_ERROR;
950
951
if(pSC->m_param.bTranscode == FALSE){
952
pSC->m_param.uQPMode = 0x150; // 101010 000
953
// 000 == uniform (not per tile) DC, LP, HP
954
// 101010 == cChMode == 2 == independent (not same) DC, LP, HP
955
956
/** lossless or Y component lossless condition: all subbands present, uniform quantization with QPIndex 1 **/
957
pSC->m_param.bScaledArith = !((pSC->m_param.uQPMode & 7) == 0 &&
958
1 == pSC->WMISCP.uiDefaultQPIndex <= 1 &&
959
pSC->WMISCP.sbSubband == SB_ALL &&
960
pSC->m_bUVResolutionChange == FALSE) &&
961
!pSC->WMISCP.bUnscaledArith;
962
if (BD_32 == pSC->WMII.bdBitDepth || BD_32S == pSC->WMII.bdBitDepth || BD_32F == pSC->WMII.bdBitDepth) {
963
pSC->m_param.bScaledArith = FALSE;
964
}
965
pSC->m_param.uQPMode |= 0x600; // don't use DC QP for LP, LP QP for HP
966
967
// default QPs
968
iQPIndexY = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1?
969
pSC->WMISCP.uiDefaultQPIndexAlpha : pSC->WMISCP.uiDefaultQPIndex;
970
971
// determine the U,V index
972
iQPIndexU = pSC->WMISCP.uiDefaultQPIndexU!=0?
973
pSC->WMISCP.uiDefaultQPIndexU: iQPIndexY;
974
iQPIndexV = pSC->WMISCP.uiDefaultQPIndexV!=0?
975
pSC->WMISCP.uiDefaultQPIndexV: iQPIndexY;
976
977
// determine the QPIndexYLP
978
iQPIndexYLP = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1 ?
979
pSC->WMISCP.uiDefaultQPIndexAlpha :
980
(pSC->WMISCP.uiDefaultQPIndexYLP == 0 ?
981
pSC->WMISCP.uiDefaultQPIndex : pSC->WMISCP.uiDefaultQPIndexYLP); // default to QPIndex if not set
982
983
// determine the QPIndexYHP
984
iQPIndexYHP = pSC->m_param.bAlphaChannel && pSC->m_param.cNumChannels == 1 ?
985
pSC->WMISCP.uiDefaultQPIndexAlpha :
986
(pSC->WMISCP.uiDefaultQPIndexYHP == 0 ?
987
pSC->WMISCP.uiDefaultQPIndex : pSC->WMISCP.uiDefaultQPIndexYHP); // default to QPIndex if not set
988
989
// determine the U,V LP index
990
iQPIndexULP = pSC->WMISCP.uiDefaultQPIndexULP!=0?
991
pSC->WMISCP.uiDefaultQPIndexULP: iQPIndexU;
992
iQPIndexVLP = pSC->WMISCP.uiDefaultQPIndexVLP!=0?
993
pSC->WMISCP.uiDefaultQPIndexVLP: iQPIndexV;
994
995
// determine the U,V HP index
996
iQPIndexUHP = pSC->WMISCP.uiDefaultQPIndexUHP!=0?
997
pSC->WMISCP.uiDefaultQPIndexUHP: iQPIndexU;
998
iQPIndexVHP = pSC->WMISCP.uiDefaultQPIndexVHP!=0?
999
pSC->WMISCP.uiDefaultQPIndexVHP: iQPIndexV;
1000
1001
// clamp the QPIndex - 0 is lossless mode
1002
if(iQPIndexY < 2)
1003
iQPIndexY = 0;
1004
if (iQPIndexYLP < 2)
1005
iQPIndexYLP = 0;
1006
if (iQPIndexYHP < 2)
1007
iQPIndexYHP = 0;
1008
if(iQPIndexU < 2)
1009
iQPIndexU = 0;
1010
if (iQPIndexULP < 2)
1011
iQPIndexULP = 0;
1012
if (iQPIndexUHP < 2)
1013
iQPIndexUHP = 0;
1014
if(iQPIndexV < 2)
1015
iQPIndexV = 0;
1016
if (iQPIndexVLP < 2)
1017
iQPIndexVLP = 0;
1018
if (iQPIndexVHP < 2)
1019
iQPIndexVHP = 0;
1020
}
1021
1022
if((pSC->m_param.uQPMode & 1) == 0){ // DC frame uniform quantization
1023
if(allocateQuantizer(pSC->pTile[0].pQuantizerDC, pSC->m_param.cNumChannels, 1) != ICERR_OK)
1024
return ICERR_ERROR;
1025
setUniformQuantizer(pSC, 0);
1026
for(i = 0; i < pSC->m_param.cNumChannels; i ++)
1027
if(pSC->m_param.bTranscode)
1028
pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i];
1029
else
1030
pSC->pTile[0].pQuantizerDC[i]->iIndex = pSC->m_param.uiQPIndexDC[i] = (U8)(((i == 0 ? iQPIndexY : (i == 1) ? iQPIndexU: iQPIndexV)) & 0xff);
1031
formatQuantizer(pSC->pTile[0].pQuantizerDC, (pSC->m_param.uQPMode >> 3) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
1032
1033
for(i = 0; i < pSC->m_param.cNumChannels; i ++)
1034
pSC->pTile[0].pQuantizerDC[i]->iOffset = (pSC->pTile[0].pQuantizerDC[i]->iQP >> 1);
1035
}
1036
1037
if(pSC->WMISCP.sbSubband != SB_DC_ONLY){
1038
if((pSC->m_param.uQPMode & 2) == 0){ // LP frame uniform quantization
1039
if(allocateQuantizer(pSC->pTile[0].pQuantizerLP, pSC->m_param.cNumChannels, 1) != ICERR_OK)
1040
return ICERR_ERROR;
1041
setUniformQuantizer(pSC, 1);
1042
for(i = 0; i < pSC->m_param.cNumChannels; i ++)
1043
if(pSC->m_param.bTranscode)
1044
pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i];
1045
else
1046
pSC->pTile[0].pQuantizerLP[i]->iIndex = pSC->m_param.uiQPIndexLP[i] = (U8)(((i == 0 ? iQPIndexYLP : (i == 1) ? iQPIndexULP: iQPIndexVLP)) & 0xff);
1047
formatQuantizer(pSC->pTile[0].pQuantizerLP, (pSC->m_param.uQPMode >> 5) & 3, pSC->m_param.cNumChannels, 0, TRUE, pSC->m_param.bScaledArith);
1048
}
1049
1050
if(pSC->WMISCP.sbSubband != SB_NO_HIGHPASS){
1051
if((pSC->m_param.uQPMode & 4) == 0){ // HP frame uniform quantization
1052
if(allocateQuantizer(pSC->pTile[0].pQuantizerHP, pSC->m_param.cNumChannels, 1) != ICERR_OK)
1053
return ICERR_ERROR;
1054
setUniformQuantizer(pSC, 2);
1055
for(i = 0; i < pSC->m_param.cNumChannels; i ++)
1056
if(pSC->m_param.bTranscode)
1057
pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i];
1058
else
1059
pSC->pTile[0].pQuantizerHP[i]->iIndex = pSC->m_param.uiQPIndexHP[i] = (U8)(((i == 0 ? iQPIndexYHP : (i == 1) ? iQPIndexUHP: iQPIndexVHP)) & 0xff);
1060
formatQuantizer(pSC->pTile[0].pQuantizerHP, (pSC->m_param.uQPMode >> 7) & 3, pSC->m_param.cNumChannels, 0, FALSE, pSC->m_param.bScaledArith);
1061
}
1062
}
1063
}
1064
1065
if(allocatePredInfo(pSC) != ICERR_OK){
1066
return ICERR_ERROR;
1067
}
1068
1069
if(pSC->WMISCP.cNumOfSliceMinus1V >= MAX_TILES || AllocateCodingContextEnc (pSC, pSC->WMISCP.cNumOfSliceMinus1V + 1, pSC->WMISCP.uiTrimFlexBits) != ICERR_OK){
1070
return ICERR_ERROR;
1071
}
1072
1073
if (pSC->m_bSecondary) {
1074
pSC->pIOHeader = pSC->m_pNextSC->pIOHeader;
1075
pSC->m_ppBitIO = pSC->m_pNextSC->m_ppBitIO;
1076
pSC->cNumBitIO = pSC->m_pNextSC->cNumBitIO;
1077
pSC->cSB = pSC->m_pNextSC->cSB;
1078
pSC->ppWStream = pSC->m_pNextSC->ppWStream;
1079
pSC->pIndexTable = pSC->m_pNextSC->pIndexTable;
1080
setBitIOPointers(pSC);
1081
}
1082
else {
1083
StrIOEncInit(pSC);
1084
setBitIOPointers(pSC);
1085
WriteWMIHeader(pSC);
1086
}
1087
1088
return ICERR_OK;
1089
}
1090
1091
static Int StrEncTerm(CTXSTRCODEC ctxSC)
1092
{
1093
CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
1094
size_t j, jend = (pSC->m_pNextSC != NULL);
1095
1096
for (j = 0; j <= jend; j++) {
1097
if (sizeof(*pSC) != pSC->cbStruct) {
1098
return ICERR_ERROR;
1099
}
1100
1101
if(pSC->m_bUVResolutionChange){
1102
if(pSC->pResU != NULL)
1103
free(pSC->pResU);
1104
if(pSC->pResV != NULL)
1105
free(pSC->pResV);
1106
}
1107
1108
freePredInfo(pSC);
1109
1110
if (j == 0)
1111
StrIOEncTerm(pSC);
1112
1113
FreeCodingContextEnc(pSC);
1114
1115
freeTileInfo(pSC);
1116
1117
pSC->WMISCP.nExpBias -= 128; // reset
1118
1119
pSC = pSC->m_pNextSC;
1120
}
1121
1122
return 0;
1123
}
1124
1125
U32 setUniformTiling(U32 * pTile, U32 cNumTile, U32 cNumMB)
1126
{
1127
U32 i, j;
1128
1129
while((cNumMB + cNumTile - 1) / cNumTile > 65535) // too few tiles
1130
cNumTile ++;
1131
1132
for(i = cNumTile, j = cNumMB; i > 1; i --){
1133
pTile[cNumTile - i] = (j + i - 1) / i;
1134
j -= pTile[cNumTile - i];
1135
}
1136
1137
return cNumTile;
1138
}
1139
1140
U32 validateTiling(U32 * pTile, U32 cNumTile, U32 cNumMB)
1141
{
1142
U32 i, cMBs;
1143
1144
if(cNumTile == 0)
1145
cNumTile = 1;
1146
if(cNumTile > cNumMB) // too many tiles
1147
cNumTile = 1;
1148
if(cNumTile > MAX_TILES)
1149
cNumTile = MAX_TILES;
1150
1151
for(i = cMBs = 0; i + 1 < cNumTile; i ++){
1152
if(pTile[i] == 0 || pTile[i] > 65535){ // invalid tile setting, resetting to uniform tiling
1153
cNumTile = setUniformTiling(pTile, cNumTile, cNumMB);
1154
break;
1155
}
1156
1157
cMBs += pTile[i];
1158
1159
if(cMBs >= cNumMB){
1160
cNumTile = i + 1;
1161
break;
1162
}
1163
}
1164
1165
// last tile
1166
if(cNumMB - cMBs > 65536)
1167
cNumTile = setUniformTiling(pTile, cNumTile, cNumMB);
1168
1169
for(i = 1; i < cNumTile; i ++)
1170
pTile[i] += pTile[i - 1];
1171
for(i = cNumTile - 1; i > 0; i --)
1172
pTile[i] = pTile[i - 1];
1173
pTile[0] = 0;
1174
1175
return cNumTile;
1176
}
1177
1178
/*************************************************************************
1179
Validate and adjust input params here
1180
*************************************************************************/
1181
Int ValidateArgs(CWMImageInfo* pII, CWMIStrCodecParam *pSCP)
1182
{
1183
int i;
1184
Bool bTooNarrowTile = FALSE;
1185
1186
if(pII->cWidth > (1 << 28) || pII->cHeight > (1 << 28) || pII->cWidth == 0 || pII->cHeight == 0){
1187
printf("Unsurpported image size!\n");
1188
return ICERR_ERROR; // unsurpported image size
1189
}
1190
1191
if (((pSCP->cfColorFormat == YUV_420) || (pSCP->cfColorFormat == YUV_422)) && (pSCP->olOverlap == OL_TWO) && ((Int)(((U32)pII->cWidth + 15) >> 4) < 2)) {
1192
printf("Image width must be at least 2 MB wide for subsampled chroma and two levels of overlap!\n");
1193
return ICERR_ERROR;
1194
}
1195
1196
if(pSCP->sbSubband == SB_ISOLATED || pSCP->sbSubband >= SB_MAX) // not allowed
1197
pSCP->sbSubband = SB_ALL;
1198
1199
if(pII->bdBitDepth == BD_5 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 16 || pII->cLeadingPadding != 0)){
1200
printf("Unsupported BD_5 image format!\n");
1201
return ICERR_ERROR; // BD_5 must be compact RGB!
1202
}
1203
if(pII->bdBitDepth == BD_565 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 16 || pII->cLeadingPadding != 0)){
1204
printf("Unsupported BD_565 image format!\n");
1205
return ICERR_ERROR; // BD_5 must be compact RGB!
1206
}
1207
if(pII->bdBitDepth == BD_10 && (pII->cfColorFormat != CF_RGB || pII->cBitsPerUnit != 32 || pII->cLeadingPadding != 0)){
1208
printf("Unsupported BD_10 image format!\n");
1209
return ICERR_ERROR; // BD_10 must be compact RGB!
1210
}
1211
1212
if((pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_565 || pII->bdBitDepth == BD_10) &&
1213
(pSCP->cfColorFormat != YUV_420 && pSCP->cfColorFormat != YUV_422 && pSCP->cfColorFormat != Y_ONLY))
1214
pSCP->cfColorFormat = YUV_444;
1215
1216
if(BD_1 == pII->bdBitDepth){ // binary image
1217
if(pII->cfColorFormat != Y_ONLY){
1218
printf("BD_1 image must be black-and white!\n");
1219
return ICERR_ERROR;
1220
}
1221
pSCP->cfColorFormat = Y_ONLY; // can only be black white
1222
}
1223
1224
if(pSCP->bdBitDepth != BD_LONG)
1225
pSCP->bdBitDepth = BD_LONG; // currently only support 32 bit internally
1226
1227
if(pSCP->uAlphaMode > 1 && (pII->cfColorFormat == YUV_420 || pII->cfColorFormat == YUV_422
1228
|| pII->bdBitDepth == BD_5 || pII->bdBitDepth == BD_10
1229
|| pII->bdBitDepth == BD_1))
1230
{
1231
printf("Alpha is not supported for this pixel format!\n");
1232
return ICERR_ERROR;
1233
}
1234
1235
if((pSCP->cfColorFormat == YUV_420 || pSCP->cfColorFormat == YUV_422) && (pII->bdBitDepth == BD_16F || pII->bdBitDepth == BD_32F || pII->cfColorFormat == CF_RGBE))
1236
{
1237
printf("Float or RGBE images must be encoded with YUV 444!\n");
1238
return ICERR_ERROR;
1239
}
1240
1241
// adjust tiling
1242
pSCP->cNumOfSliceMinus1V = validateTiling(pSCP->uiTileX, pSCP->cNumOfSliceMinus1V + 1, (((U32)pII->cWidth + 15) >> 4)) - 1;
1243
pSCP->cNumOfSliceMinus1H = validateTiling(pSCP->uiTileY, pSCP->cNumOfSliceMinus1H + 1, (((U32)pII->cHeight + 15) >> 4)) - 1;
1244
1245
if (pSCP->bUseHardTileBoundaries && ((pSCP->cfColorFormat == YUV_420) || (pSCP->cfColorFormat == YUV_422)) && (pSCP->olOverlap == OL_TWO)) {
1246
for (i = 1; i < (int) (pSCP->cNumOfSliceMinus1H + 1); i++) {
1247
if ((Int)(pSCP->uiTileY[i] - pSCP->uiTileY[i - 1]) < 2) {
1248
bTooNarrowTile = TRUE;
1249
break;
1250
}
1251
}
1252
if ((Int)((((U32)pII->cWidth + 15) >> 4) - pSCP->uiTileY[pSCP->cNumOfSliceMinus1H]) < 2)
1253
bTooNarrowTile = TRUE;
1254
}
1255
if (bTooNarrowTile) {
1256
printf("Tile width must be at least 2 MB wide for hard tiles, subsampled chroma, and two levels of overlap!\n");
1257
return ICERR_ERROR;
1258
}
1259
1260
if(pSCP->cChannel > MAX_CHANNELS)
1261
return ICERR_ERROR;
1262
1263
/** supported color transcoding **/
1264
/** ARGB, RGB => YUV_444, YUV_422, YUV_420, Y_ONLY **/
1265
/** YUV_444 => YUV_422, YUV_420, Y_ONLY **/
1266
/** YUV_422 => YUV_420, Y_ONLY **/
1267
/** YUV_420 => Y_ONLY **/
1268
1269
/** unsupported color transcoding **/
1270
/** Y_ONLY, YUV_420, YUV_422 => YUV_444 **/
1271
/** Y_ONLY, YUV_420 => YUV_422 **/
1272
/** Y_ONLY => YUV_420 **/
1273
if((pII->cfColorFormat == Y_ONLY && pSCP->cfColorFormat != Y_ONLY) ||
1274
(pSCP->cfColorFormat == YUV_422 && (pII->cfColorFormat == YUV_420 || pII->cfColorFormat == Y_ONLY)) ||
1275
(pSCP->cfColorFormat == YUV_444 && (pII->cfColorFormat == YUV_422 || pII->cfColorFormat == YUV_420 || pII->cfColorFormat == Y_ONLY))){
1276
pSCP->cfColorFormat = pII->cfColorFormat; // force not to do color transcoding!
1277
}
1278
else if (pII->cfColorFormat == NCOMPONENT) {
1279
pSCP->cfColorFormat = NCOMPONENT; // force not to do color transcoding!
1280
}
1281
if (CMYK == pII->cfColorFormat && pSCP->cfColorFormat == NCOMPONENT)
1282
{
1283
pSCP->cfColorFormat = CMYK;
1284
}
1285
1286
if(pSCP->cfColorFormat != NCOMPONENT){
1287
if(pSCP->cfColorFormat == Y_ONLY)
1288
pSCP->cChannel = 1;
1289
else if(pSCP->cfColorFormat == CMYK)
1290
pSCP->cChannel = 4;
1291
else
1292
pSCP->cChannel = 3;
1293
}
1294
1295
if(pSCP->sbSubband >= SB_MAX)
1296
pSCP->sbSubband = SB_ALL;
1297
1298
1299
pII->cChromaCenteringX = 0;
1300
pII->cChromaCenteringY = 0;
1301
1302
return ICERR_OK;
1303
}
1304
1305
/*************************************************************************
1306
Initialization of CWMImageStrCodec struct
1307
*************************************************************************/
1308
static Void InitializeStrEnc(CWMImageStrCodec *pSC,
1309
const CWMImageInfo* pII, const CWMIStrCodecParam *pSCP)
1310
{
1311
pSC->cbStruct = sizeof(*pSC);
1312
pSC->WMII = *pII;
1313
pSC->WMISCP = *pSCP;
1314
1315
// set nExpBias
1316
if (pSC->WMISCP.nExpBias == 0)
1317
pSC->WMISCP.nExpBias = (I8)(4 + 128);//default
1318
pSC->WMISCP.nExpBias += 128; // rollover arithmetic
1319
1320
pSC->cRow = 0;
1321
pSC->cColumn = 0;
1322
1323
pSC->cmbWidth = (pSC->WMII.cWidth + 15) / 16;
1324
pSC->cmbHeight = (pSC->WMII.cHeight + 15) / 16;
1325
1326
pSC->Load = inputMBRow;
1327
pSC->Quantize = quantizeMacroblock;
1328
pSC->ProcessTopLeft = processMacroblock;
1329
pSC->ProcessTop = processMacroblock;
1330
pSC->ProcessTopRight = processMacroblock;
1331
pSC->ProcessLeft = processMacroblock;
1332
pSC->ProcessCenter = processMacroblock;
1333
pSC->ProcessRight = processMacroblock;
1334
pSC->ProcessBottomLeft = processMacroblock;
1335
pSC->ProcessBottom = processMacroblock;
1336
pSC->ProcessBottomRight = processMacroblock;
1337
1338
pSC->m_pNextSC = NULL;
1339
pSC->m_bSecondary = FALSE;
1340
}
1341
1342
/*************************************************************************
1343
Streaming API init
1344
*************************************************************************/
1345
Int ImageStrEncInit(
1346
CWMImageInfo* pII,
1347
CWMIStrCodecParam *pSCP,
1348
CTXSTRCODEC* pctxSC)
1349
{
1350
static size_t cbChannels[BD_MAX] = {2, 4};
1351
1352
size_t cbChannel = 0, cblkChroma = 0, i;
1353
size_t cbMacBlockStride = 0, cbMacBlockChroma = 0, cMacBlock = 0;
1354
1355
CWMImageStrCodec* pSC = NULL, *pNextSC = NULL;
1356
char* pb = NULL;
1357
size_t cb = 0;
1358
Bool b32bit = sizeof(size_t) == 4;
1359
1360
Int err;
1361
1362
if(ValidateArgs(pII, pSCP) != ICERR_OK){
1363
goto ErrorExit;
1364
}
1365
1366
//================================================
1367
*pctxSC = NULL;
1368
1369
//================================================
1370
cbChannel = cbChannels[pSCP->bdBitDepth];
1371
cblkChroma = cblkChromas[pSCP->cfColorFormat];
1372
cbMacBlockStride = cbChannel * 16 * 16;
1373
cbMacBlockChroma = cbChannel * 16 * cblkChroma;
1374
cMacBlock = (pII->cWidth + 15) / 16;
1375
1376
//================================================
1377
cb = sizeof(*pSC) + (128 - 1) + (PACKETLENGTH * 4 - 1) + (PACKETLENGTH * 2 ) + sizeof(*pSC->pIOHeader);
1378
i = cbMacBlockStride + cbMacBlockChroma * (pSCP->cChannel - 1);
1379
if(b32bit) // integer overlow/underflow check for 32-bit system
1380
if(((cMacBlock >> 15) * i) & 0xffff0000)
1381
return ICERR_ERROR;
1382
i *= cMacBlock * 2;
1383
cb += i;
1384
1385
pb = malloc(cb);
1386
if (NULL == pb)
1387
{
1388
goto ErrorExit;
1389
}
1390
memset(pb, 0, cb);
1391
1392
//================================================
1393
pSC = (CWMImageStrCodec*)pb; pb += sizeof(*pSC);
1394
1395
// Set up perf timers
1396
PERFTIMER_ONLY(pSC->m_fMeasurePerf = pSCP->fMeasurePerf);
1397
PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEndToEndPerf);
1398
PERFTIMER_NEW(pSC->m_fMeasurePerf, &pSC->m_ptEncDecPerf);
1399
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
1400
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1401
PERFTIMER_COPYSTARTTIME(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf, pSC->m_ptEndToEndPerf);
1402
1403
pSC->m_param.cfColorFormat = pSCP->cfColorFormat;
1404
pSC->m_param.bAlphaChannel = (pSCP->uAlphaMode == 3);
1405
pSC->m_param.cNumChannels = pSCP->cChannel;
1406
pSC->m_param.cExtraPixelsTop = pSC->m_param.cExtraPixelsBottom
1407
= pSC->m_param.cExtraPixelsLeft = pSC->m_param.cExtraPixelsRight = 0;
1408
1409
pSC->cbChannel = cbChannel;
1410
1411
pSC->m_param.bTranscode = pSC->bTileExtraction = FALSE;
1412
1413
//================================================
1414
InitializeStrEnc(pSC, pII, pSCP);
1415
1416
//================================================
1417
// 2 Macro Row buffers for each channel
1418
pb = ALIGNUP(pb, 128);
1419
for (i = 0; i < pSC->m_param.cNumChannels; i++) {
1420
pSC->a0MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
1421
pSC->a1MBbuffer[i] = (PixelI*)pb; pb += cbMacBlockStride * pSC->cmbWidth;
1422
cbMacBlockStride = cbMacBlockChroma;
1423
}
1424
1425
//================================================
1426
// lay 2 aligned IO buffers just below pIO struct
1427
pb = (char*)ALIGNUP(pb, PACKETLENGTH * 4) + PACKETLENGTH * 2;
1428
pSC->pIOHeader = (BitIOInfo*)pb;
1429
1430
//================================================
1431
err = StrEncInit(pSC);
1432
if (ICERR_OK != err)
1433
goto ErrorExit;
1434
1435
// if interleaved alpha is needed
1436
if (pSC->m_param.bAlphaChannel) {
1437
cbMacBlockStride = cbChannel * 16 * 16;
1438
// 1. allocate new pNextSC info
1439
//================================================
1440
cb = sizeof(*pNextSC) + (128 - 1) + cbMacBlockStride * cMacBlock * 2;
1441
pb = malloc(cb);
1442
if (NULL == pb)
1443
{
1444
goto ErrorExit;
1445
}
1446
memset(pb, 0, cb);
1447
//================================================
1448
pNextSC = (CWMImageStrCodec*)pb; pb += sizeof(*pNextSC);
1449
1450
// 2. initialize pNextSC
1451
pNextSC->m_param.cfColorFormat = Y_ONLY;
1452
pNextSC->m_param.cNumChannels = 1;
1453
pNextSC->m_param.bAlphaChannel = TRUE;
1454
pNextSC->cbChannel = cbChannel;
1455
//================================================
1456
1457
// 3. initialize arrays
1458
InitializeStrEnc(pNextSC, pII, pSCP);
1459
//================================================
1460
1461
// 2 Macro Row buffers for each channel
1462
pb = ALIGNUP(pb, 128);
1463
pNextSC->a0MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth;
1464
pNextSC->a1MBbuffer[0] = (PixelI*)pb; pb += cbMacBlockStride * pNextSC->cmbWidth;
1465
//================================================
1466
pNextSC->pIOHeader = pSC->pIOHeader;
1467
//================================================
1468
1469
// 4. link pSC->pNextSC = pNextSC
1470
pNextSC->m_pNextSC = pSC;
1471
pNextSC->m_bSecondary = TRUE;
1472
1473
// 5. StrEncInit
1474
StrEncInit(pNextSC);
1475
1476
// 6. Write header of image plane
1477
WriteImagePlaneHeader(pNextSC);
1478
}
1479
1480
pSC->m_pNextSC = pNextSC;
1481
//================================================
1482
*pctxSC = (CTXSTRCODEC)pSC;
1483
1484
writeIndexTableNull(pSC);
1485
#if defined(WMP_OPT_SSE2) || defined(WMP_OPT_CC_ENC) || defined(WMP_OPT_TRFM_ENC)
1486
StrEncOpt(pSC);
1487
#endif // OPT defined
1488
1489
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1490
return ICERR_OK;
1491
1492
ErrorExit:
1493
return ICERR_ERROR;
1494
}
1495
1496
/*************************************************************************
1497
Streaming API encode
1498
*************************************************************************/
1499
Int ImageStrEncEncode(
1500
CTXSTRCODEC ctxSC,
1501
const CWMImageBufferInfo* pBI)
1502
{
1503
CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
1504
CWMImageStrCodec* pNextSC = pSC->m_pNextSC;
1505
ImageDataProc ProcessLeft, ProcessCenter, ProcessRight;
1506
1507
if (sizeof(*pSC) != pSC->cbStruct)
1508
{
1509
return ICERR_ERROR;
1510
}
1511
1512
//================================
1513
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1514
1515
pSC->WMIBI = *pBI;
1516
pSC->cColumn = 0;
1517
initMRPtr(pSC);
1518
if (pNextSC)
1519
pNextSC->WMIBI = *pBI;
1520
1521
if (0 == pSC->cRow) {
1522
ProcessLeft = pSC->ProcessTopLeft;
1523
ProcessCenter = pSC->ProcessTop;
1524
ProcessRight = pSC->ProcessTopRight;
1525
}
1526
else {
1527
ProcessLeft = pSC->ProcessLeft;
1528
ProcessCenter = pSC->ProcessCenter;
1529
ProcessRight = pSC->ProcessRight;
1530
}
1531
1532
if( pSC->Load(pSC) != ICERR_OK )
1533
return ICERR_ERROR;
1534
if(ProcessLeft(pSC) != ICERR_OK)
1535
return ICERR_ERROR;
1536
advanceMRPtr(pSC);
1537
1538
//================================
1539
for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) {
1540
if(ProcessCenter(pSC) != ICERR_OK)
1541
return ICERR_ERROR;
1542
advanceMRPtr(pSC);
1543
}
1544
1545
//================================
1546
if(ProcessRight(pSC) != ICERR_OK)
1547
return ICERR_ERROR;
1548
if (pSC->cRow)
1549
advanceOneMBRow(pSC);
1550
1551
++pSC->cRow;
1552
swapMRPtr(pSC);
1553
1554
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1555
return ICERR_OK;
1556
}
1557
1558
/*************************************************************************
1559
Streaming API term
1560
*************************************************************************/
1561
Int ImageStrEncTerm(
1562
CTXSTRCODEC ctxSC)
1563
{
1564
CWMImageStrCodec* pSC = (CWMImageStrCodec*)ctxSC;
1565
// CWMImageStrCodec *pNextSC = pSC->m_pNextSC;
1566
1567
if (sizeof(*pSC) != pSC->cbStruct)
1568
{
1569
return ICERR_ERROR;
1570
}
1571
1572
//================================
1573
PERFTIMER_START(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1574
pSC->cColumn = 0;
1575
initMRPtr(pSC);
1576
1577
pSC->ProcessBottomLeft(pSC);
1578
advanceMRPtr(pSC);
1579
1580
//================================
1581
for (pSC->cColumn = 1; pSC->cColumn < pSC->cmbWidth; ++pSC->cColumn) {
1582
pSC->ProcessBottom(pSC);
1583
advanceMRPtr(pSC);
1584
}
1585
1586
//================================
1587
pSC->ProcessBottomRight(pSC);
1588
1589
//================================
1590
StrEncTerm(pSC);
1591
1592
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1593
PERFTIMER_STOP(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
1594
PERFTIMER_REPORT(pSC->m_fMeasurePerf, pSC);
1595
PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEncDecPerf);
1596
PERFTIMER_DELETE(pSC->m_fMeasurePerf, pSC->m_ptEndToEndPerf);
1597
1598
free(pSC);
1599
return ICERR_OK;
1600
}
1601
1602
// centralized UV downsampling
1603
#define DF_ODD ((((d1 + d2 + d3) << 2) + (d2 << 1) + d0 + d4 + 8) >> 4)
1604
Void downsampleUV(CWMImageStrCodec * pSC)
1605
{
1606
const COLORFORMAT cfInt = pSC->m_param.cfColorFormat;
1607
const COLORFORMAT cfExt = pSC->WMII.cfColorFormat;
1608
PixelI * pSrc, * pDst;
1609
PixelI d0, d1, d2, d3, d4;
1610
size_t iChannel, iRow, iColumn;
1611
1612
for(iChannel = 1; iChannel < 3; iChannel ++){
1613
if(cfExt != YUV_422){ // need to do horizontal downsampling, 444 => 422
1614
const size_t cShift = (cfInt == YUV_422 ? 1 : 0);
1615
1616
pSrc = (iChannel == 1 ? pSC->pResU : pSC->pResV);
1617
pDst = (cfInt == YUV_422 ? pSC->p1MBbuffer[iChannel] : pSrc);
1618
1619
for(iRow = 0; iRow < 16; iRow ++){
1620
d0 = d4 = pSrc[idxCC[iRow][2]], d1 = d3 = pSrc[idxCC[iRow][1]], d2 = pSrc[idxCC[iRow][0]]; // left boundary
1621
1622
for(iColumn = 0; iColumn + 2 < pSC->cmbWidth * 16; iColumn += 2){
1623
pDst[((iColumn >> 4) << (8 - cShift)) + idxCC[iRow][(iColumn & 15) >> cShift]] = DF_ODD;
1624
d0 = d2, d1 = d3, d2 = d4;
1625
d3 = pSrc[(((iColumn + 3) >> 4) << 8) + idxCC[iRow][(iColumn + 3) & 0xf]];
1626
d4 = pSrc[(((iColumn + 4) >> 4) << 8) + idxCC[iRow][(iColumn + 4) & 0xf]];
1627
}
1628
1629
d4 = d2; // right boundary
1630
pDst[((iColumn >> 4) << (8 - cShift)) + idxCC[iRow][(iColumn & 15) >> cShift]] = DF_ODD;
1631
}
1632
}
1633
1634
if(cfInt == YUV_420){ // need to do vertical downsampling
1635
const size_t cShift = (cfExt == YUV_422 ? 0 : 1);
1636
PixelI * pBuf[4];
1637
size_t mbOff, pxOff;
1638
1639
pDst = pSC->p1MBbuffer[iChannel];
1640
pSrc = (iChannel == 1 ? pSC->pResU : pSC->pResV);
1641
pBuf[0] = pSrc + (pSC->cmbWidth << (cfExt == YUV_422 ? 7 : 8));
1642
pBuf[1] = pBuf[0] + pSC->cmbWidth * 8, pBuf[2] = pBuf[1] + pSC->cmbWidth * 8, pBuf[3] = pBuf[2] + pSC->cmbWidth * 8;
1643
1644
for(iColumn = 0; iColumn < pSC->cmbWidth * 8; iColumn ++){
1645
mbOff = (iColumn >> 3) << (7 + cShift);
1646
pxOff = (iColumn & 7) << cShift;
1647
1648
if(pSC->cRow == 0) // top image boundary
1649
d0 = d4 = pSrc[mbOff + idxCC[2][pxOff]], d1 = d3 = pSrc[mbOff + idxCC[1][pxOff]], d2 = pSrc[mbOff + idxCC[0][pxOff]]; // top MB boundary
1650
else{
1651
// last row of previous MB row
1652
d0 = pBuf[0][iColumn], d1 = pBuf[1][iColumn], d2 = pBuf[2][iColumn], d3 = pBuf[3][iColumn], d4 = pSrc[mbOff + idxCC[0][pxOff]];
1653
pSC->p0MBbuffer[iChannel][((iColumn >> 3) << 6) + idxCC_420[7][iColumn & 7]] = DF_ODD;
1654
1655
// for first row of current MB
1656
d0 = pBuf[2][iColumn], d1 = pBuf[3][iColumn];
1657
d2 = pSrc[mbOff + idxCC[0][pxOff]], d3 = pSrc[mbOff + idxCC[1][pxOff]], d4 = pSrc[mbOff + idxCC[2][pxOff]];
1658
}
1659
1660
for(iRow = 0; iRow < 12; iRow += 2){
1661
pDst[((iColumn >> 3) << 6) + idxCC_420[iRow >> 1][iColumn & 7]] = DF_ODD;
1662
d0 = d2, d1 = d3, d2 = d4;
1663
d3 = pSrc[mbOff + idxCC[iRow + 3][pxOff]];
1664
d4 = pSrc[mbOff + idxCC[iRow + 4][pxOff]];
1665
}
1666
1667
//last row of current MB
1668
pDst[((iColumn >> 3) << 6) + idxCC_420[6][iColumn & 7]] = DF_ODD;
1669
d0 = d2, d1 = d3, d2 = d4;
1670
d3 = pSrc[mbOff + idxCC[iRow + 3][pxOff]];
1671
1672
if(pSC->cRow + 1 == pSC->cmbHeight){ // bottom image boundary
1673
d4 = d2;
1674
pDst[((iColumn >> 3) << 6) + idxCC_420[7][iColumn & 7]] = DF_ODD;
1675
}
1676
else{
1677
for(iRow = 0; iRow < 4; iRow ++)
1678
pBuf[iRow][iColumn] = pSrc[mbOff + idxCC[iRow + 12][pxOff]];
1679
}
1680
}
1681
}
1682
}
1683
}
1684
1685
// centralized horizontal padding
1686
Void padHorizontally(CWMImageStrCodec * pSC)
1687
{
1688
if(pSC->WMII.cWidth != pSC->cmbWidth * 16){ // horizontal padding is necessary!
1689
const COLORFORMAT cfExt = pSC->WMISCP.bYUVData ?
1690
pSC->m_param.cfColorFormat : pSC->WMII.cfColorFormat;
1691
size_t cFullChannel = pSC->WMISCP.cChannel;
1692
size_t iLast = pSC->WMII.cWidth - 1;
1693
PixelI * pCh[16];
1694
size_t iChannel, iColumn, iRow;
1695
1696
if(cfExt == YUV_420 || cfExt == YUV_422 || cfExt == Y_ONLY)
1697
cFullChannel = 1;
1698
1699
assert(cFullChannel <= 16);
1700
1701
assert(pSC->WMISCP.cChannel <= 16);
1702
for(iChannel = 0; iChannel < pSC->WMISCP.cChannel; iChannel ++)
1703
pCh[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15];
1704
1705
if(pSC->m_bUVResolutionChange)
1706
pCh[1] = pSC->pResU, pCh[2] = pSC->pResV;
1707
1708
// pad full resoluton channels
1709
for(iRow = 0; iRow < 16; iRow ++){
1710
const size_t iPosLast = ((iLast >> 4) << 8) + idxCC[iRow][iLast & 0xf];
1711
for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 16; iColumn ++){
1712
const size_t iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
1713
for(iChannel = 0; iChannel < cFullChannel; iChannel ++)
1714
pCh[iChannel & 15][iPos] = pCh[iChannel & 15][iPosLast];
1715
}
1716
}
1717
1718
if(cfExt == YUV_422) // pad YUV_422 UV
1719
for(iLast >>= 1, iRow = 0; iRow < 16; iRow ++){
1720
const size_t iPosLast = ((iLast >> 3) << 7) + idxCC[iRow][iLast & 7];
1721
for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 8; iColumn ++){
1722
const size_t iPos = ((iColumn >> 3) << 7) + idxCC[iRow][iColumn & 7];
1723
for(iChannel = 1; iChannel < 3; iChannel ++)
1724
pCh[iChannel][iPos] = pCh[iChannel][iPosLast];
1725
}
1726
}
1727
else if(cfExt == YUV_420) // pad YUV_420 UV
1728
for(iLast >>= 1, iRow = 0; iRow < 8; iRow ++){
1729
const size_t iPosLast = ((iLast >> 3) << 6) + idxCC_420[iRow][iLast & 7];
1730
for(iColumn = iLast + 1; iColumn < pSC->cmbWidth * 8; iColumn ++){
1731
const size_t iPos = ((iColumn >> 3) << 6) + idxCC_420[iRow][iColumn & 7];
1732
for(iChannel = 1; iChannel < 3; iChannel ++)
1733
pCh[iChannel][iPos] = pCh[iChannel][iPosLast];
1734
}
1735
}
1736
}
1737
}
1738
1739
// centralized alpha channel color conversion, small perf penalty
1740
Int inputMBRowAlpha(CWMImageStrCodec* pSC)
1741
{
1742
if(pSC->m_bSecondary == FALSE && pSC->m_pNextSC != NULL){ // alpha channel is present
1743
const size_t cShift = (pSC->m_pNextSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0);
1744
const BITDEPTH_BITS bdExt = pSC->WMII.bdBitDepth;
1745
const size_t iAlphaPos = pSC->WMII.cLeadingPadding + (pSC->WMII.cfColorFormat == CMYK ? 4 : 3);//only RGB and CMYK may have interleaved alpha
1746
const size_t cRow = pSC->WMIBI.cLine;
1747
const size_t cColumn = pSC->WMII.cWidth;
1748
const U8 * pSrc0 = (U8 *)pSC->WMIBI.pv;
1749
PixelI * pA = pSC->m_pNextSC->p1MBbuffer[0];
1750
size_t iRow, iColumn;
1751
1752
for(iRow = 0; iRow < 16; iRow ++){
1753
if(bdExt == BD_8){
1754
const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3);
1755
const U8 * pSrc = pSrc0;
1756
1757
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
1758
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((PixelI)pSrc[iAlphaPos] - (1 << 7)) << cShift;
1759
}
1760
else if(bdExt == BD_16){
1761
const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(U16);
1762
const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
1763
const U16 * pSrc = (U16 *)pSrc0;
1764
1765
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
1766
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((((PixelI)pSrc[iAlphaPos] - (1 << 15)) >> nLenMantissaOrShift) << cShift);
1767
}
1768
else if(bdExt == BD_16S){
1769
const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(I16);
1770
const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
1771
const I16 * pSrc = (I16 *)pSrc0;
1772
1773
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
1774
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = (((PixelI)pSrc[iAlphaPos] >> nLenMantissaOrShift) << cShift);
1775
}
1776
else if(bdExt == BD_16F){
1777
const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(U16);
1778
const I16 * pSrc = (I16 *)pSrc0;
1779
1780
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
1781
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = forwardHalf (pSrc[iAlphaPos]) << cShift;
1782
}
1783
else if(bdExt == BD_32S){
1784
const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(I32);
1785
const U8 nLenMantissaOrShift = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
1786
const I32 * pSrc = (I32 *)pSrc0;
1787
1788
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
1789
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = (((PixelI)pSrc[iAlphaPos] >> nLenMantissaOrShift) << cShift);
1790
}
1791
else if(bdExt == BD_32F){
1792
const size_t cStride = (pSC->WMII.cBitsPerUnit >> 3) / sizeof(float);
1793
const U8 nLen = pSC->m_pNextSC->WMISCP.nLenMantissaOrShift;
1794
const I8 nExpBias = pSC->m_pNextSC->WMISCP.nExpBias;
1795
const float * pSrc = (float *)pSrc0;
1796
1797
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride)
1798
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = float2pixel (pSrc[iAlphaPos], nExpBias, nLen) << cShift;
1799
}
1800
else // not supported
1801
return ICERR_ERROR;
1802
1803
if(iRow + 1 < cRow) // vertical padding!
1804
pSrc0 += pSC->WMIBI.cbStride;
1805
1806
for(iColumn = cColumn; iColumn < pSC->cmbWidth * 16; iColumn ++) // horizontal padding
1807
pA[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = pA[(((cColumn - 1) >> 4) << 8) + idxCC[iRow][(cColumn - 1) & 0xf]];
1808
}
1809
}
1810
1811
return ICERR_OK;
1812
}
1813
1814
// input one MB row of image data from input buffer
1815
Int inputMBRow(CWMImageStrCodec* pSC)
1816
{
1817
const size_t cShift = (pSC->m_param.bScaledArith ? (SHIFTZERO + QPFRACBITS) : 0);
1818
const BITDEPTH_BITS bdExt = pSC->WMII.bdBitDepth;
1819
COLORFORMAT cfExt = pSC->WMII.cfColorFormat;
1820
const COLORFORMAT cfInt = pSC->m_param.cfColorFormat;
1821
const size_t cPixelStride = (pSC->WMII.cBitsPerUnit >> 3);
1822
const size_t iRowStride =
1823
(cfExt == YUV_420 || (pSC->WMISCP.bYUVData && pSC->m_param.cfColorFormat==YUV_420)) ? 2 : 1;
1824
const size_t cRow = pSC->WMIBI.cLine;
1825
const size_t cColumn = pSC->WMII.cWidth;
1826
const size_t iB = (pSC->WMII.bRGB ? 2 : 0);
1827
const size_t iR = 2 - iB;
1828
const U8 * pSrc0 = (U8 *)pSC->WMIBI.pv;
1829
const U8 nLen = pSC->WMISCP.nLenMantissaOrShift;
1830
const I8 nExpBias = pSC->WMISCP.nExpBias;
1831
1832
PixelI *pY = pSC->p1MBbuffer[0], *pU = pSC->p1MBbuffer[1], *pV = pSC->p1MBbuffer[2];
1833
size_t iRow, iColumn, iPos;
1834
1835
// guard input buffer
1836
if(checkImageBuffer(pSC, cColumn, cRow) != ICERR_OK)
1837
return ICERR_ERROR;
1838
1839
if(pSC->m_bUVResolutionChange) // will do downsampling somewhere else!
1840
pU = pSC->pResU, pV = pSC->pResV;
1841
else if(cfInt == Y_ONLY) // xxx to Y_ONLY transcoding!
1842
pU = pV = pY; // write pY AFTER pU and pV so Y will overwrite U&V
1843
1844
for(iRow = 0; iRow < 16; iRow += iRowStride){
1845
if (pSC->WMISCP.bYUVData){
1846
I32 * pSrc = (I32 *)pSrc0 + pSC->WMII.cLeadingPadding;
1847
1848
switch(pSC->m_param.cfColorFormat){
1849
case Y_ONLY:
1850
case YUV_444:
1851
case NCOMPONENT:
1852
{
1853
const size_t cChannel = pSC->m_param.cNumChannels;
1854
PixelI * pChannel[16];
1855
size_t iChannel;
1856
1857
assert(cChannel <= 16);
1858
for(iChannel = 0; iChannel < cChannel; iChannel ++)
1859
pChannel[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15];
1860
if(pSC->m_bUVResolutionChange)
1861
pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV;
1862
1863
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cChannel){
1864
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
1865
for(iChannel = 0; iChannel < cChannel; iChannel ++)
1866
pChannel[iChannel & 15][iPos] = (PixelI)pSrc[iChannel & 15];
1867
}
1868
}
1869
break;
1870
1871
case YUV_422:
1872
for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += 4){
1873
if(cfInt != Y_ONLY){
1874
iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
1875
pU[iPos] = (PixelI)pSrc[0];
1876
pV[iPos] = (PixelI)pSrc[2];
1877
}
1878
1879
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (PixelI)pSrc[1];
1880
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (PixelI)pSrc[3];
1881
}
1882
break;
1883
1884
case YUV_420:
1885
for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += 6){
1886
if(cfInt != Y_ONLY){
1887
iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
1888
pU[iPos] = (PixelI)pSrc[4];
1889
pV[iPos] = (PixelI)pSrc[5];
1890
}
1891
1892
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (PixelI)pSrc[0];
1893
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (PixelI)pSrc[1];
1894
pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (PixelI)pSrc[2];
1895
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (PixelI)pSrc[3];
1896
}
1897
break;
1898
1899
default:
1900
assert(0);
1901
break;
1902
}
1903
}
1904
else if(bdExt == BD_8){
1905
const U8 * pSrc = pSrc0 + pSC->WMII.cLeadingPadding;
1906
const PixelI iOffset = (128 << cShift);
1907
1908
switch(cfExt){
1909
case CF_RGB:
1910
assert (pSC->m_bSecondary == FALSE);
1911
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
1912
PixelI r = ((PixelI)pSrc[iR]) << cShift, g = ((PixelI)pSrc[1]) << cShift, b = ((PixelI)pSrc[iB]) << cShift;
1913
1914
_CC(r, g, b); // color conversion
1915
1916
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
1917
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
1918
}
1919
break;
1920
1921
case Y_ONLY:
1922
case YUV_444:
1923
case NCOMPONENT:
1924
{
1925
const size_t cChannel = pSC->m_param.cNumChannels;
1926
PixelI * pChannel[16];
1927
size_t iChannel;
1928
1929
assert(cChannel <= 16);
1930
for(iChannel = 0; iChannel < cChannel; iChannel ++)
1931
pChannel[iChannel & 15] = pSC->p1MBbuffer[iChannel & 15];
1932
if(pSC->m_bUVResolutionChange)
1933
pChannel[1] = pSC->pResU, pChannel[2] = pSC->pResV;
1934
1935
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
1936
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
1937
for(iChannel = 0; iChannel < cChannel; iChannel ++)
1938
pChannel[iChannel & 15][iPos] = (((PixelI)pSrc[iChannel & 15]) << cShift) - iOffset;
1939
}
1940
break;
1941
}
1942
1943
case CF_RGBE:
1944
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
1945
PixelI iExp = (PixelI)pSrc[3];
1946
PixelI r = forwardRGBE (pSrc[0], iExp) << cShift;
1947
PixelI g = forwardRGBE (pSrc[1], iExp) << cShift;
1948
PixelI b = forwardRGBE (pSrc[2], iExp) << cShift;
1949
1950
_CC(r, g, b);
1951
1952
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
1953
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
1954
}
1955
break;
1956
1957
case CMYK:
1958
{
1959
PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding!
1960
1961
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
1962
PixelI c = ((PixelI)pSrc[0]) << cShift;
1963
PixelI m = ((PixelI)pSrc[1]) << cShift;
1964
PixelI y = ((PixelI)pSrc[2]) << cShift;
1965
PixelI k = ((PixelI)pSrc[3]) << cShift;
1966
1967
_CC_CMYK(c, m, y, k);
1968
1969
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
1970
pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = iOffset - m;
1971
}
1972
break;
1973
}
1974
1975
case YUV_422:
1976
for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cPixelStride){
1977
if(cfInt != Y_ONLY){
1978
iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
1979
pU[iPos] = (((PixelI)pSrc[0]) << cShift) - iOffset;
1980
pV[iPos] = (((PixelI)pSrc[2]) << cShift) - iOffset;
1981
}
1982
1983
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
1984
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
1985
}
1986
break;
1987
1988
case YUV_420:
1989
for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cPixelStride){
1990
if(cfInt != Y_ONLY){
1991
iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
1992
pU[iPos] = (((PixelI)pSrc[4]) << cShift) - iOffset;
1993
pV[iPos] = (((PixelI)pSrc[5]) << cShift) - iOffset;
1994
}
1995
1996
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[0]) << cShift) - iOffset;
1997
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
1998
pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (((PixelI)pSrc[2]) << cShift) - iOffset;
1999
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
2000
}
2001
break;
2002
2003
default:
2004
assert(0);
2005
break;
2006
}
2007
}
2008
else if(bdExt == BD_16){
2009
const U16 * pSrc = (U16 *)pSrc0 + pSC->WMII.cLeadingPadding;
2010
const size_t cStride = cPixelStride / sizeof(U16);
2011
const PixelI iOffset = ((1 << 15) >> nLen) << cShift;
2012
2013
switch(cfExt){
2014
case CF_RGB:
2015
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2016
PixelI r = ((PixelI)pSrc[0] >> nLen) << cShift, g = ((PixelI)pSrc[1] >> nLen) << cShift, b = ((PixelI)pSrc[2] >> nLen) << cShift;
2017
2018
_CC(r, g, b); // color conversion
2019
2020
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2021
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
2022
}
2023
break;
2024
2025
case Y_ONLY:
2026
case YUV_444:
2027
case NCOMPONENT:
2028
{
2029
const size_t cChannel = pSC->WMISCP.cChannel;
2030
size_t iChannel;
2031
2032
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2033
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2034
for(iChannel = 0; iChannel < cChannel; iChannel ++)
2035
pSC->p1MBbuffer[iChannel][iPos] = (((PixelI)pSrc[iChannel] >> nLen) << cShift) - iOffset;
2036
}
2037
break;
2038
}
2039
2040
case CMYK:
2041
{
2042
PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding!
2043
2044
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2045
PixelI c = ((PixelI)pSrc[0] >> nLen) << cShift;
2046
PixelI m = ((PixelI)pSrc[1] >> nLen) << cShift;
2047
PixelI y = ((PixelI)pSrc[2] >> nLen) << cShift;
2048
PixelI k = ((PixelI)pSrc[3] >> nLen) << cShift;
2049
2050
_CC_CMYK(c, m, y, k);
2051
2052
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2053
pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = iOffset - m;
2054
}
2055
break;
2056
}
2057
2058
case YUV_422:
2059
for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cStride){
2060
if(cfInt != Y_ONLY){
2061
iPos = ((iColumn >> 4) << 7) + idxCC[iRow][(iColumn >> 1) & 7];
2062
pU[iPos] = (((PixelI)pSrc[0]) << cShift) - iOffset;
2063
pV[iPos] = (((PixelI)pSrc[2]) << cShift) - iOffset;
2064
}
2065
2066
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
2067
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
2068
}
2069
break;
2070
2071
case YUV_420:
2072
for(iColumn = 0; iColumn < cColumn; iColumn += 2, pSrc += cStride){
2073
if(cfInt != Y_ONLY){
2074
iPos = ((iColumn >> 4) << 6) + idxCC_420[iRow >> 1][(iColumn >> 1) & 7];
2075
pU[iPos] = (((PixelI)pSrc[4]) << cShift) - iOffset;
2076
pV[iPos] = (((PixelI)pSrc[5]) << cShift) - iOffset;
2077
}
2078
2079
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 15]] = (((PixelI)pSrc[0]) << cShift) - iOffset;
2080
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow][(iColumn + 1) & 15]] = (((PixelI)pSrc[1]) << cShift) - iOffset;
2081
pY[((iColumn >> 4) << 8) + idxCC[iRow + 1][iColumn & 15]] = (((PixelI)pSrc[2]) << cShift) - iOffset;
2082
pY[(((iColumn + 1) >> 4) << 8) + idxCC[iRow + 1][(iColumn + 1) & 15]] = (((PixelI)pSrc[3]) << cShift) - iOffset;
2083
}
2084
break;
2085
2086
default:
2087
assert(0);
2088
break;
2089
}
2090
}
2091
else if(bdExt == BD_16S){
2092
const I16 * pSrc = (I16 *)pSrc0 + pSC->WMII.cLeadingPadding;
2093
const size_t cStride = cPixelStride / sizeof(I16);
2094
2095
switch(cfExt){
2096
case CF_RGB:
2097
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2098
PixelI r = ((PixelI)pSrc[0] >> nLen) << cShift, g = ((PixelI)pSrc[1] >> nLen) << cShift, b = ((PixelI)pSrc[2] >> nLen) << cShift;
2099
2100
_CC(r, g, b); // color conversion
2101
2102
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2103
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
2104
}
2105
break;
2106
2107
case Y_ONLY:
2108
case YUV_444:
2109
case NCOMPONENT:
2110
{
2111
const size_t cChannel = pSC->WMISCP.cChannel;
2112
size_t iChannel;
2113
2114
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2115
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2116
for(iChannel = 0; iChannel < cChannel; iChannel ++)
2117
pSC->p1MBbuffer[iChannel][iPos] = (((PixelI)pSrc[iChannel] >> nLen) << cShift);
2118
}
2119
}
2120
break;
2121
2122
case CMYK:
2123
{
2124
PixelI * pK = (cfInt == CMYK ? pSC->p1MBbuffer[3] : pY); // CMYK -> YUV_xxx transcoding!
2125
2126
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2127
PixelI c = ((PixelI)pSrc[0] >> nLen) << cShift;
2128
PixelI m = ((PixelI)pSrc[1] >> nLen) << cShift;
2129
PixelI y = ((PixelI)pSrc[2] >> nLen) << cShift;
2130
PixelI k = ((PixelI)pSrc[3] >> nLen) << cShift;
2131
2132
_CC_CMYK(c, m, y, k);
2133
2134
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2135
pU[iPos] = c, pV[iPos] = -y, pK[iPos] = k, pY[iPos] = -m;
2136
}
2137
}
2138
break;
2139
2140
default:
2141
assert(0);
2142
break;
2143
}
2144
}
2145
else if(bdExt == BD_16F){
2146
const I16 * pSrc = (I16 *)pSrc0 + pSC->WMII.cLeadingPadding;
2147
const size_t cStride = cPixelStride / sizeof(U16);
2148
2149
switch(cfExt){
2150
case CF_RGB:
2151
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2152
PixelI r = forwardHalf (pSrc[0]) << cShift;
2153
PixelI g = forwardHalf (pSrc[1]) << cShift;
2154
PixelI b = forwardHalf (pSrc[2]) << cShift;
2155
2156
_CC(r, g, b); // color conversion
2157
2158
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2159
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
2160
}
2161
break;
2162
2163
case Y_ONLY:
2164
case YUV_444:
2165
case NCOMPONENT:
2166
{
2167
const size_t cChannel = pSC->WMISCP.cChannel; // check xxx => Y_ONLY transcoding!
2168
size_t iChannel;
2169
2170
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2171
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2172
for(iChannel = 0; iChannel < cChannel; iChannel ++)
2173
pSC->p1MBbuffer[iChannel][iPos] = forwardHalf (pSrc[iChannel]) << cShift;
2174
}
2175
}
2176
break;
2177
2178
default:
2179
assert(0);
2180
break;
2181
}
2182
}
2183
else if(bdExt == BD_32){
2184
const U32 * pSrc = (U32 *)pSrc0 + pSC->WMII.cLeadingPadding;
2185
const size_t cStride = cPixelStride / sizeof(U32);
2186
const PixelI iOffset = ((1 << 31) >> nLen) << cShift;
2187
2188
switch(cfExt){
2189
case CF_RGB:
2190
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2191
PixelI r = (pSrc[0] >> nLen) << cShift, g = (pSrc[1] >> nLen) << cShift, b = (pSrc[2] >> nLen) << cShift;
2192
2193
_CC(r, g, b); // color conversion
2194
2195
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2196
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
2197
}
2198
break;
2199
2200
case Y_ONLY:
2201
case YUV_444:
2202
case NCOMPONENT:
2203
{
2204
const size_t cChannel = pSC->WMISCP.cChannel;
2205
size_t iChannel;
2206
2207
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2208
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2209
for(iChannel = 0; iChannel < cChannel; iChannel ++)
2210
pSC->p1MBbuffer[iChannel][iPos] = (pSrc[iChannel] >> nLen) << cShift;
2211
}
2212
break;
2213
}
2214
2215
default:
2216
assert(0);
2217
break;
2218
}
2219
}
2220
else if(bdExt == BD_32S){
2221
const I32 * pSrc = (I32 *)pSrc0 + pSC->WMII.cLeadingPadding;
2222
const size_t cStride = cPixelStride / sizeof(I32);
2223
2224
switch(cfExt){
2225
case CF_RGB:
2226
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2227
PixelI r = (pSrc[0] >> nLen)<< cShift, g = (pSrc[1] >> nLen)<< cShift, b = (pSrc[2] >> nLen)<< cShift;
2228
2229
_CC(r, g, b); // color conversion
2230
2231
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2232
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
2233
}
2234
break;
2235
2236
case Y_ONLY:
2237
case YUV_444:
2238
case NCOMPONENT:
2239
{
2240
const size_t cChannel = pSC->WMISCP.cChannel; // check xxx => Y_ONLY transcoding!
2241
size_t iChannel;
2242
2243
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2244
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2245
for(iChannel = 0; iChannel < cChannel; iChannel ++)
2246
pSC->p1MBbuffer[iChannel][iPos] = (pSrc[iChannel] >> nLen) << cShift;
2247
}
2248
}
2249
break;
2250
2251
default:
2252
assert(0);
2253
break;
2254
}
2255
}
2256
else if(bdExt == BD_32F){
2257
const float * pSrc = (float *)pSrc0 + pSC->WMII.cLeadingPadding;
2258
const size_t cStride = cPixelStride / sizeof(float);
2259
2260
switch(cfExt){
2261
case CF_RGB:
2262
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2263
PixelI r = float2pixel (pSrc[0], nExpBias, nLen) << cShift;
2264
PixelI g = float2pixel (pSrc[1], nExpBias, nLen) << cShift;
2265
PixelI b = float2pixel (pSrc[2], nExpBias, nLen) << cShift;
2266
2267
_CC(r, g, b); // color conversion
2268
2269
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2270
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g;
2271
}
2272
break;
2273
2274
case Y_ONLY:
2275
case YUV_444:
2276
case NCOMPONENT:
2277
{
2278
const size_t cChannel = pSC->WMISCP.cChannel;
2279
size_t iChannel;
2280
2281
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cStride){
2282
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2283
for(iChannel = 0; iChannel < cChannel; iChannel ++)
2284
pSC->p1MBbuffer[iChannel][iPos] = float2pixel (pSrc[iChannel], nExpBias, nLen) << cShift;
2285
}
2286
}
2287
break;
2288
default:
2289
assert(0);
2290
break;
2291
}
2292
}
2293
else if(bdExt == BD_5){ // RGB 555, work for both big endian and small endian!
2294
const U8 * pSrc = pSrc0;
2295
const PixelI iOffset = (16 << cShift);
2296
2297
assert(cfExt == CF_RGB);
2298
2299
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
2300
PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = ((g >> 2) & 0x1F) << cShift;
2301
2302
g = ((r >> 5) + ((g & 3) << 3)) << cShift, r = (r & 0x1F) << cShift;
2303
2304
_CC(r, g, b); // color conversion
2305
2306
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2307
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
2308
}
2309
}
2310
else if(bdExt == BD_565){ // RGB 555, work for both big endian and small endian!
2311
const U8 * pSrc = pSrc0;
2312
const PixelI iOffset = (32 << cShift);
2313
2314
assert(cfExt == CF_RGB);
2315
2316
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
2317
PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = (g >> 3) << (cShift + 1);
2318
2319
g = ((r >> 5) + ((g & 7) << 3)) << cShift, r = (r & 0x1F) << (cShift + 1);
2320
2321
_CC(r, g, b); // color conversion
2322
2323
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2324
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
2325
}
2326
}
2327
else if(bdExt == BD_10){ //RGB 101010, work for both big endian and small endian!
2328
const U8 * pSrc = pSrc0;
2329
const PixelI iOffset = (512 << cShift);
2330
2331
assert(cfExt == CF_RGB);
2332
2333
for(iColumn = 0; iColumn < cColumn; iColumn ++, pSrc += cPixelStride){
2334
PixelI r = (PixelI)pSrc[0], g = (PixelI)pSrc[1], b = (PixelI)pSrc[2];
2335
2336
r = (r + ((g & 3) << 8)) << cShift, g = ((g >> 2) + ((b & 0xF) << 6)) << cShift;
2337
b = ((b >> 4) + (((PixelI)pSrc[3] & 0x3F) << 4)) << cShift;
2338
2339
_CC(r, g, b); // color conversion
2340
2341
iPos = ((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf];
2342
pU[iPos] = -r, pV[iPos] = b, pY[iPos] = g - iOffset;
2343
}
2344
}
2345
else if(bdExt == BD_1){
2346
assert(cfExt == Y_ONLY);
2347
for(iColumn = 0; iColumn < cColumn; iColumn ++) {
2348
pY[((iColumn >> 4) << 8) + idxCC[iRow][iColumn & 0xf]] = ((pSC->WMISCP.bBlackWhite + (pSrc0[iColumn >> 3] >> (7 - (iColumn & 7)))) & 1) << cShift;
2349
}
2350
}
2351
2352
if(iRow + iRowStride < cRow) // centralized vertical padding!
2353
pSrc0 += pSC->WMIBI.cbStride;
2354
}
2355
2356
padHorizontally(pSC); // centralized horizontal padding
2357
2358
// centralized down-sampling
2359
if(pSC->m_bUVResolutionChange)
2360
downsampleUV(pSC);
2361
2362
// centralized alpha channel handdling
2363
if (pSC->WMISCP.uAlphaMode == 3)
2364
if(inputMBRowAlpha(pSC) != ICERR_OK)
2365
return ICERR_ERROR;
2366
2367
return ICERR_OK;
2368
}
2369
2370