* Progressive Codec Bitmap Compression
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2019 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2019 Thincast Technologies GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/* SRL state */
- int kp;
+ UINT32 kp;
int nz;
BOOL mode;
};
default:
return "PROGRESSIVE_WBT_UNKNOWN";
}
-
- return "PROGRESSIVE_WBT_UNKNOWN";
}
-static INLINE void progressive_component_codec_quant_read(const BYTE* block,
+static INLINE void progressive_component_codec_quant_read(wStream* s,
RFX_COMPONENT_CODEC_QUANT* quantVal)
{
- quantVal->LL3 = block[0] & 0x0F;
- quantVal->HL3 = block[0] >> 4;
- quantVal->LH3 = block[1] & 0x0F;
- quantVal->HH3 = block[1] >> 4;
- quantVal->HL2 = block[2] & 0x0F;
- quantVal->LH2 = block[2] >> 4;
- quantVal->HH2 = block[3] & 0x0F;
- quantVal->HL1 = block[3] >> 4;
- quantVal->LH1 = block[4] & 0x0F;
- quantVal->HH1 = block[4] >> 4;
+ BYTE b;
+ Stream_Read_UINT8(s, b);
+ quantVal->LL3 = b & 0x0F;
+ quantVal->HL3 = b >> 4;
+ Stream_Read_UINT8(s, b);
+ quantVal->LH3 = b & 0x0F;
+ quantVal->HH3 = b >> 4;
+ Stream_Read_UINT8(s, b);
+ quantVal->HL2 = b & 0x0F;
+ quantVal->LH2 = b >> 4;
+ Stream_Read_UINT8(s, b);
+ quantVal->HH2 = b & 0x0F;
+ quantVal->HL1 = b >> 4;
+ Stream_Read_UINT8(s, b);
+ quantVal->LH1 = b & 0x0F;
+ quantVal->HH1 = b >> 4;
}
static INLINE void progressive_rfx_quant_ladd(RFX_COMPONENT_CODEC_QUANT* q, int val)
q->LL3 += val; /* LL3 */
}
-static INLINE void progressive_rfx_quant_add(RFX_COMPONENT_CODEC_QUANT* q1,
- RFX_COMPONENT_CODEC_QUANT* q2,
+static INLINE void progressive_rfx_quant_add(const RFX_COMPONENT_CODEC_QUANT* q1,
+ const RFX_COMPONENT_CODEC_QUANT* q2,
RFX_COMPONENT_CODEC_QUANT* dst)
{
dst->HL1 = q1->HL1 + q2->HL1; /* HL1 */
q->LL3 -= val; /* LL3 */
}
-static INLINE void progressive_rfx_quant_sub(RFX_COMPONENT_CODEC_QUANT* q1,
- RFX_COMPONENT_CODEC_QUANT* q2,
+static INLINE void progressive_rfx_quant_sub(const RFX_COMPONENT_CODEC_QUANT* q1,
+ const RFX_COMPONENT_CODEC_QUANT* q2,
RFX_COMPONENT_CODEC_QUANT* dst)
{
dst->HL1 = q1->HL1 - q2->HL1; /* HL1 */
dst->LL3 = q1->LL3 - q2->LL3; /* LL3 */
}
-static INLINE BOOL progressive_rfx_quant_lcmp_less_equal(RFX_COMPONENT_CODEC_QUANT* q, int val)
+static INLINE BOOL progressive_rfx_quant_lcmp_less_equal(const RFX_COMPONENT_CODEC_QUANT* q,
+ int val)
{
if (q->HL1 > val)
return FALSE; /* HL1 */
return TRUE;
}
-static INLINE BOOL progressive_rfx_quant_cmp_less_equal(RFX_COMPONENT_CODEC_QUANT* q1,
- RFX_COMPONENT_CODEC_QUANT* q2)
+static INLINE BOOL progressive_rfx_quant_cmp_less_equal(const RFX_COMPONENT_CODEC_QUANT* q1,
+ const RFX_COMPONENT_CODEC_QUANT* q2)
{
if (q1->HL1 > q2->HL1)
return FALSE; /* HL1 */
return TRUE;
}
-static INLINE BOOL progressive_rfx_quant_lcmp_greater_equal(RFX_COMPONENT_CODEC_QUANT* q, int val)
+static INLINE BOOL progressive_rfx_quant_lcmp_greater_equal(const RFX_COMPONENT_CODEC_QUANT* q,
+ int val)
{
if (q->HL1 < val)
return FALSE; /* HL1 */
return TRUE;
}
-static INLINE BOOL progressive_rfx_quant_cmp_greater_equal(RFX_COMPONENT_CODEC_QUANT* q1,
- RFX_COMPONENT_CODEC_QUANT* q2)
+static INLINE BOOL progressive_rfx_quant_cmp_greater_equal(const RFX_COMPONENT_CODEC_QUANT* q1,
+ const RFX_COMPONENT_CODEC_QUANT* q2)
{
if (q1->HL1 < q2->HL1)
return FALSE; /* HL1 */
return TRUE;
}
-static INLINE BOOL progressive_rfx_quant_cmp_equal(RFX_COMPONENT_CODEC_QUANT* q1,
- RFX_COMPONENT_CODEC_QUANT* q2)
+static INLINE BOOL progressive_rfx_quant_cmp_equal(const RFX_COMPONENT_CODEC_QUANT* q1,
+ const RFX_COMPONENT_CODEC_QUANT* q2)
{
if (q1->HL1 != q2->HL1)
return FALSE; /* HL1 */
return TRUE;
}
-static void progressive_rfx_quant_print(RFX_COMPONENT_CODEC_QUANT* q, const char* name)
-{
- fprintf(stderr,
- "%s: HL1: %" PRIu8 " LH1: %" PRIu8 " HH1: %" PRIu8 " HL2: %" PRIu8 " LH2: %" PRIu8
- " HH2: %" PRIu8 " HL3: %" PRIu8 " LH3: %" PRIu8 " HH3: %" PRIu8 " LL3: %" PRIu8 "\n",
- name, q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3);
-}
-
static INLINE BOOL progressive_set_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId,
void* pData)
{
return TRUE;
}
-static INLINE void* progressive_get_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId)
+static INLINE PROGRESSIVE_SURFACE_CONTEXT*
+progressive_get_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId)
{
- ULONG_PTR key;
+ void* key = (void*)(((ULONG_PTR)surfaceId) + 1);
void* pData = NULL;
- key = ((ULONG_PTR)surfaceId) + 1;
- pData = HashTable_GetItemValue(progressive->SurfaceContexts, (void*)key);
+
+ if (!progressive)
+ return NULL;
+
+ pData = HashTable_GetItemValue(progressive->SurfaceContexts, key);
return pData;
}
+static void progressive_tile_free(RFX_PROGRESSIVE_TILE* tile)
+{
+ if (tile)
+ {
+ _aligned_free(tile->sign);
+ _aligned_free(tile->current);
+ _aligned_free(tile->data);
+ }
+}
+
+static void progressive_surface_context_free(PROGRESSIVE_SURFACE_CONTEXT* surface)
+{
+ UINT32 index;
+
+ for (index = 0; index < surface->gridSize; index++)
+ {
+ RFX_PROGRESSIVE_TILE* tile = &(surface->tiles[index]);
+ progressive_tile_free(tile);
+ }
+
+ free(surface->tiles);
+ free(surface);
+}
+
+static INLINE BOOL progressive_tile_allocate(RFX_PROGRESSIVE_TILE* tile)
+{
+ BOOL rc = FALSE;
+ if (!tile)
+ return FALSE;
+
+ tile->width = 64;
+ tile->height = 64;
+ tile->stride = 4 * tile->width;
+
+ {
+ size_t dataLen = tile->stride * tile->height;
+ tile->data = (BYTE*)_aligned_malloc(dataLen, 16);
+ }
+
+ {
+ size_t signLen = (8192 + 32) * 3;
+ tile->sign = (BYTE*)_aligned_malloc(signLen, 16);
+ }
+
+ {
+ size_t currentLen = (8192 + 32) * 3;
+ tile->current = (BYTE*)_aligned_malloc(currentLen, 16);
+ }
+
+ rc = tile->data && tile->sign && tile->current;
+
+ if (!rc)
+ progressive_tile_free(tile);
+
+ return rc;
+}
+
static PROGRESSIVE_SURFACE_CONTEXT* progressive_surface_context_new(UINT16 surfaceId, UINT32 width,
UINT32 height)
{
+ UINT32 x;
PROGRESSIVE_SURFACE_CONTEXT* surface;
surface = (PROGRESSIVE_SURFACE_CONTEXT*)calloc(1, sizeof(PROGRESSIVE_SURFACE_CONTEXT));
free(surface);
return NULL;
}
+ for (x = 0; x < surface->gridSize; x++)
+ {
+ if (!progressive_tile_allocate(&surface->tiles[x]))
+ {
+ progressive_surface_context_free(surface);
+ return NULL;
+ }
+ }
return surface;
}
-static void progressive_surface_context_free(PROGRESSIVE_SURFACE_CONTEXT* surface)
+static BOOL progressive_surface_tile_replace(PROGRESSIVE_SURFACE_CONTEXT* surface,
+ PROGRESSIVE_BLOCK_REGION* region,
+ const RFX_PROGRESSIVE_TILE* tile, BOOL upgrade)
{
- UINT32 index;
- RFX_PROGRESSIVE_TILE* tile;
+ RFX_PROGRESSIVE_TILE* t;
- for (index = 0; index < surface->gridSize; index++)
+ size_t zIdx;
+ if (!surface || !tile)
+ return FALSE;
+
+ zIdx = (tile->yIdx * surface->gridWidth) + tile->xIdx;
+
+ if (zIdx >= surface->gridSize)
{
- tile = &(surface->tiles[index]);
+ WLog_ERR(TAG, "Invalid zIndex %" PRIuz, zIdx);
+ return FALSE;
+ }
- if (tile->data)
- _aligned_free(tile->data);
+ t = &surface->tiles[zIdx];
- if (tile->sign)
- _aligned_free(tile->sign);
+ if (upgrade)
+ {
+ t->blockType = tile->blockType;
+ t->blockLen = tile->blockLen;
+ t->quantIdxY = tile->quantIdxY;
+ t->quantIdxCb = tile->quantIdxCb;
+ t->quantIdxCr = tile->quantIdxCr;
+ t->xIdx = tile->xIdx;
+ t->yIdx = tile->yIdx;
+ t->flags = tile->flags;
+ t->quality = tile->quality;
+ t->ySrlLen = tile->ySrlLen;
+ t->yRawLen = tile->yRawLen;
+ t->cbSrlLen = tile->cbSrlLen;
+ t->cbRawLen = tile->cbRawLen;
+ t->crSrlLen = tile->crSrlLen;
+ t->crRawLen = tile->crRawLen;
+ t->ySrlData = tile->ySrlData;
+ t->yRawData = tile->yRawData;
+ t->cbSrlData = tile->cbSrlData;
+ t->cbRawData = tile->cbRawData;
+ t->crSrlData = tile->crSrlData;
+ t->crRawData = tile->crRawData;
+ t->x = tile->xIdx * t->width;
+ t->y = tile->yIdx * t->height;
+ }
+ else
+ {
+ t->blockType = tile->blockType;
+ t->blockLen = tile->blockLen;
+ t->quantIdxY = tile->quantIdxY;
+ t->quantIdxCb = tile->quantIdxCb;
+ t->quantIdxCr = tile->quantIdxCr;
+ t->xIdx = tile->xIdx;
+ t->yIdx = tile->yIdx;
+ t->flags = tile->flags;
+ t->quality = tile->quality;
+ t->yLen = tile->yLen;
+ t->cbLen = tile->cbLen;
+ t->crLen = tile->crLen;
+ t->tailLen = tile->tailLen;
+ t->yData = tile->yData;
+ t->cbData = tile->cbData;
+ t->crData = tile->crData;
+ t->tailData = tile->tailData;
+ t->x = tile->xIdx * t->width;
+ t->y = tile->yIdx * t->height;
+ }
- if (tile->current)
- _aligned_free(tile->current);
+ if (region->usedTiles >= region->numTiles)
+ {
+ WLog_ERR(TAG, "Invalid tile count, only expected %" PRIu16 ", got %" PRIu16,
+ region->numTiles, region->usedTiles);
+ return FALSE;
}
- free(surface->tiles);
- free(surface);
+ region->tiles[region->usedTiles++] = t;
+ return TRUE;
}
INT32 progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId,
UINT32 width, UINT32 height)
{
PROGRESSIVE_SURFACE_CONTEXT* surface;
- surface = (PROGRESSIVE_SURFACE_CONTEXT*)progressive_get_surface_data(progressive, surfaceId);
+ surface = progressive_get_surface_data(progressive, surfaceId);
if (!surface)
{
int progressive_delete_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId)
{
- PROGRESSIVE_SURFACE_CONTEXT* surface;
- surface = (PROGRESSIVE_SURFACE_CONTEXT*)progressive_get_surface_data(progressive, surfaceId);
+ PROGRESSIVE_SURFACE_CONTEXT* surface = progressive_get_surface_data(progressive, surfaceId);
if (surface)
{
}
/*
- * Band Offset Dimensions Size
+ * Band Offset Dimensions Size
*
- * HL1 0 31x33 1023
- * LH1 1023 33x31 1023
- * HH1 2046 31x31 961
+ * HL1 0 31x33 1023
+ * LH1 1023 33x31 1023
+ * HH1 2046 31x31 961
*
- * HL2 3007 16x17 272
- * LH2 3279 17x16 272
- * HH2 3551 16x16 256
+ * HL2 3007 16x17 272
+ * LH2 3279 17x16 272
+ * HH2 3551 16x16 256
*
- * HL3 3807 8x9 72
- * LH3 3879 9x8 72
- * HH3 3951 8x8 64
+ * HL3 3807 8x9 72
+ * LH3 3879 9x8 72
+ * HH3 3951 8x8 64
*
- * LL3 4015 9x9 81
+ * LL3 4015 9x9 81
*/
-static INLINE void progressive_rfx_idwt_x(INT16* pLowBand, int nLowStep, INT16* pHighBand,
- int nHighStep, INT16* pDstBand, int nDstStep,
- int nLowCount, int nHighCount, int nDstCount)
+static INLINE void progressive_rfx_idwt_x(const INT16* pLowBand, size_t nLowStep,
+ const INT16* pHighBand, size_t nHighStep, INT16* pDstBand,
+ size_t nDstStep, size_t nLowCount, size_t nHighCount,
+ size_t nDstCount)
{
- int i, j;
+ size_t i;
INT16 L0;
INT16 H0, H1;
INT16 X0, X1, X2;
- INT16 *pL, *pH, *pX;
for (i = 0; i < nDstCount; i++)
{
- pL = pLowBand;
- pH = pHighBand;
- pX = pDstBand;
- H0 = *pH;
- pH++;
- L0 = *pL;
- pL++;
+ size_t j;
+ const INT16* pL = pLowBand;
+ const INT16* pH = pHighBand;
+ INT16* pX = pDstBand;
+ H0 = *pH++;
+ L0 = *pL++;
X0 = L0 - H0;
X2 = L0 - H0;
}
}
-static INLINE void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* pHighBand,
- int nHighStep, INT16* pDstBand, int nDstStep,
- int nLowCount, int nHighCount, int nDstCount)
+static INLINE void progressive_rfx_idwt_y(const INT16* pLowBand, size_t nLowStep,
+ const INT16* pHighBand, size_t nHighStep, INT16* pDstBand,
+ size_t nDstStep, size_t nLowCount, size_t nHighCount,
+ size_t nDstCount)
{
- int i, j;
+ size_t i;
INT16 L0;
INT16 H0, H1;
INT16 X0, X1, X2;
- INT16 *pL, *pH, *pX;
for (i = 0; i < nDstCount; i++)
{
- pL = pLowBand;
- pH = pHighBand;
- pX = pDstBand;
+ size_t j;
+ const INT16* pL = pLowBand;
+ const INT16* pH = pHighBand;
+ INT16* pX = pDstBand;
H0 = *pH;
pH += nHighStep;
L0 = *pL;
}
}
-static INLINE int progressive_rfx_get_band_l_count(int level)
+static INLINE size_t progressive_rfx_get_band_l_count(size_t level)
{
return (64 >> level) + 1;
}
-static INLINE int progressive_rfx_get_band_h_count(int level)
+static INLINE size_t progressive_rfx_get_band_h_count(size_t level)
{
if (level == 1)
return (64 >> 1) - 1;
return (64 + (1 << (level - 1))) >> level;
}
-static INLINE void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* temp, int level)
+static INLINE void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* temp, size_t level,
+ BOOL extrapolate)
{
- int offset;
- int nBandL;
- int nBandH;
- int nDstStepX;
- int nDstStepY;
+ size_t nDstStepX;
+ size_t nDstStepY;
INT16 *HL, *LH;
INT16 *HH, *LL;
INT16 *L, *H, *LLx;
- INT16* pLowBand[3];
- INT16* pHighBand[3];
- INT16* pDstBand[3];
- int nLowStep[3];
- int nHighStep[3];
- int nDstStep[3];
- int nLowCount[3];
- int nHighCount[3];
- int nDstCount[3];
- nBandL = progressive_rfx_get_band_l_count(level);
- nBandH = progressive_rfx_get_band_h_count(level);
- offset = 0;
+
+ const size_t nBandL = progressive_rfx_get_band_l_count(level);
+ const size_t nBandH = progressive_rfx_get_band_h_count(level);
+ size_t offset = 0;
HL = &buffer[offset];
offset += (nBandH * nBandL);
LH = &buffer[offset];
offset += (nBandL * nDstStepX);
H = &temp[offset];
LLx = &buffer[0];
+
/* horizontal (LL + HL -> L) */
- pLowBand[0] = LL;
- nLowStep[0] = nBandL;
- pHighBand[0] = HL;
- nHighStep[0] = nBandH;
- pDstBand[0] = L;
- nDstStep[0] = nDstStepX;
- nLowCount[0] = nBandL;
- nHighCount[0] = nBandH;
- nDstCount[0] = nBandL;
- progressive_rfx_idwt_x(pLowBand[0], nLowStep[0], pHighBand[0], nHighStep[0], pDstBand[0],
- nDstStep[0], nLowCount[0], nHighCount[0], nDstCount[0]);
+ progressive_rfx_idwt_x(LL, nBandL, HL, nBandH, L, nDstStepX, nBandL, nBandH, nBandL);
+
/* horizontal (LH + HH -> H) */
- pLowBand[1] = LH;
- nLowStep[1] = nBandL;
- pHighBand[1] = HH;
- nHighStep[1] = nBandH;
- pDstBand[1] = H;
- nDstStep[1] = nDstStepX;
- nLowCount[1] = nBandL;
- nHighCount[1] = nBandH;
- nDstCount[1] = nBandH;
- progressive_rfx_idwt_x(pLowBand[1], nLowStep[1], pHighBand[1], nHighStep[1], pDstBand[1],
- nDstStep[1], nLowCount[1], nHighCount[1], nDstCount[1]);
+ progressive_rfx_idwt_x(LH, nBandL, HH, nBandH, H, nDstStepX, nBandL, nBandH, nBandH);
+
/* vertical (L + H -> LL) */
- pLowBand[2] = pDstBand[0];
- nLowStep[2] = nDstStep[0];
- pHighBand[2] = pDstBand[1];
- nHighStep[2] = nDstStep[1];
- pDstBand[2] = LLx;
- nDstStep[2] = nDstStepY;
- nLowCount[2] = nBandL;
- nHighCount[2] = nBandH;
- nDstCount[2] = nBandL + nBandH;
- progressive_rfx_idwt_y(pLowBand[2], nLowStep[2], pHighBand[2], nHighStep[2], pDstBand[2],
- nDstStep[2], nLowCount[2], nHighCount[2], nDstCount[2]);
+ progressive_rfx_idwt_y(L, nDstStepX, H, nDstStepX, LLx, nDstStepY, nBandL, nBandH,
+ nBandL + nBandH);
}
static INLINE void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current,
- INT16* sign, BOOL diff)
+ INT16* sign, BOOL diff, BOOL extrapolate)
{
const primitives_t* prims = primitives_get();
prims->add_16s(buffer, current, buffer, 4096);
CopyMemory(current, buffer, 4096 * 2);
- progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3);
- progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2);
- progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1);
+ progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3, extrapolate);
+ progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2, extrapolate);
+ progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1, extrapolate);
}
static INLINE void progressive_rfx_decode_block(const primitives_t* prims, INT16* buffer,
- int length, UINT32 shift)
+ UINT32 length, UINT32 shift)
{
if (!shift)
return;
}
static INLINE int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive,
- RFX_COMPONENT_CODEC_QUANT* shift,
- const BYTE* data, int length, INT16* buffer,
- INT16* current, INT16* sign, BOOL diff)
+ const RFX_COMPONENT_CODEC_QUANT* shift,
+ const BYTE* data, UINT32 length, INT16* buffer,
+ INT16* current, INT16* sign, BOOL diff,
+ BOOL subbandDiff, BOOL extrapolate)
{
int status;
INT16* temp;
return status;
CopyMemory(sign, buffer, 4096 * 2);
- rfx_differential_decode(&buffer[4015], 81); /* LL3 */
+
progressive_rfx_decode_block(prims, &buffer[0], 1023, shift->HL1); /* HL1 */
progressive_rfx_decode_block(prims, &buffer[1023], 1023, shift->LH1); /* LH1 */
progressive_rfx_decode_block(prims, &buffer[2046], 961, shift->HH1); /* HH1 */
progressive_rfx_decode_block(prims, &buffer[3807], 72, shift->HL3); /* HL3 */
progressive_rfx_decode_block(prims, &buffer[3879], 72, shift->LH3); /* LH3 */
progressive_rfx_decode_block(prims, &buffer[3951], 64, shift->HH3); /* HH3 */
+ rfx_differential_decode(&buffer[4015], 81); /* LL3 */
progressive_rfx_decode_block(prims, &buffer[4015], 81, shift->LL3); /* LL3 */
+
temp = (INT16*)BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */
- progressive_rfx_dwt_2d_decode(buffer, temp, current, sign, diff);
+ progressive_rfx_dwt_2d_decode(buffer, temp, current, sign, diff, extrapolate);
BufferPool_Return(progressive->bufferPool, temp);
return 1;
}
static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive,
- RFX_PROGRESSIVE_TILE* tile)
+ RFX_PROGRESSIVE_TILE* tile,
+ PROGRESSIVE_BLOCK_REGION* region,
+ const PROGRESSIVE_BLOCK_CONTEXT* context)
{
- BOOL diff;
+ int rc;
+ BOOL diff, sub, extrapolate;
BYTE* pBuffer;
INT16* pSign[3];
INT16* pSrcDst[3];
INT16* pCurrent[3];
- PROGRESSIVE_BLOCK_REGION* region;
- RFX_COMPONENT_CODEC_QUANT shiftY;
- RFX_COMPONENT_CODEC_QUANT shiftCb;
- RFX_COMPONENT_CODEC_QUANT shiftCr;
+ RFX_COMPONENT_CODEC_QUANT shiftY = { 0 };
+ RFX_COMPONENT_CODEC_QUANT shiftCb = { 0 };
+ RFX_COMPONENT_CODEC_QUANT shiftCr = { 0 };
RFX_COMPONENT_CODEC_QUANT* quantY;
RFX_COMPONENT_CODEC_QUANT* quantCb;
RFX_COMPONENT_CODEC_QUANT* quantCr;
tile->pass = 1;
diff = tile->flags & RFX_TILE_DIFFERENCE;
+ sub = context->flags & RFX_SUBBAND_DIFFING;
+ extrapolate = region->flags & RFX_DWT_REDUCE_EXTRAPOLATE;
+
WLog_Print(progressive->log, WLOG_DEBUG,
"ProgressiveTile%s: quantIdx Y: %" PRIu8 " Cb: %" PRIu8 " Cr: %" PRIu8
" xIdx: %" PRIu16 " yIdx: %" PRIu16 " flags: 0x%02" PRIX8 " quality: %" PRIu8
(tile->blockType == PROGRESSIVE_WBT_TILE_FIRST) ? "First" : "Simple",
tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx,
tile->flags, tile->quality, tile->yLen, tile->cbLen, tile->crLen, tile->tailLen);
- region = &(progressive->region);
if (tile->quantIdxY >= region->numQuant)
+ {
+ WLog_ERR(TAG, "quantIdxY %" PRIu8 " > numQuant %" PRIu8, tile->quantIdxY, region->numQuant);
return -1;
+ }
quantY = &(region->quantVals[tile->quantIdxY]);
if (tile->quantIdxCb >= region->numQuant)
+ {
+ WLog_ERR(TAG, "quantIdxCb %" PRIu8 " > numQuant %" PRIu8, tile->quantIdxCb,
+ region->numQuant);
return -1;
+ }
quantCb = &(region->quantVals[tile->quantIdxCb]);
if (tile->quantIdxCr >= region->numQuant)
+ {
+ WLog_ERR(TAG, "quantIdxCr %" PRIu8 " > numQuant %" PRIu8, tile->quantIdxCr,
+ region->numQuant);
return -1;
+ }
quantCr = &(region->quantVals[tile->quantIdxCr]);
else
{
if (tile->quality >= region->numProgQuant)
+ {
+ WLog_ERR(TAG, "quality %" PRIu8 " > numProgQuant %" PRIu8, tile->quality,
+ region->numProgQuant);
return -1;
+ }
quantProgVal = &(region->quantProgVals[tile->quality]);
}
quantProgCb = &(quantProgVal->cbQuantValues);
quantProgCr = &(quantProgVal->crQuantValues);
- CopyMemory(&(tile->yQuant), quantY, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->cbQuant), quantCb, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->crQuant), quantCr, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->yProgQuant), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->cbProgQuant), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->crProgQuant), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT));
+ tile->yQuant = *quantY;
+ tile->cbQuant = *quantCb;
+ tile->crQuant = *quantCr;
+ tile->yProgQuant = *quantProgY;
+ tile->cbProgQuant = *quantProgCb;
+ tile->crProgQuant = *quantProgCr;
+
+ if (!(region->flags & RFX_DWT_REDUCE_EXTRAPOLATE))
+ WLog_Print(progressive->log, WLOG_WARN,
+ "RFX_PROGRESSIVE_REGION::flags & RFX_DWT_REDUCE_EXTRAPOLATE not set");
+
+ if (!(context->flags & RFX_SUBBAND_DIFFING))
+ WLog_WARN(TAG, "PROGRESSIVE_BLOCK_CONTEXT::flags & RFX_SUBBAND_DIFFING not set");
progressive_rfx_quant_add(quantY, quantProgY, &(tile->yBitPos));
progressive_rfx_quant_add(quantCb, quantProgCb, &(tile->cbBitPos));
progressive_rfx_quant_add(quantCr, quantProgCr, &shiftCr);
progressive_rfx_quant_lsub(&shiftCr, 1); /* -6 + 5 = -1 */
- if (!tile->data)
- {
- tile->data = (BYTE*)_aligned_malloc(64 * 64 * 4, 16);
- if (!tile->data)
- return -1;
- }
-
- if (!tile->sign)
- {
- tile->sign = (BYTE*)_aligned_malloc((8192 + 32) * 3, 16);
- if (!tile->sign)
- return -1;
- }
-
- if (!tile->current)
- {
- tile->current = (BYTE*)_aligned_malloc((8192 + 32) * 3, 16);
- if (!tile->current)
- return -1;
- }
-
- pBuffer = tile->sign;
- pSign[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */
- pSign[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
- pSign[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
+ pSign[0] = (INT16*)((BYTE*)(&tile->sign[((8192 + 32) * 0) + 16])); /* Y/R buffer */
+ pSign[1] = (INT16*)((BYTE*)(&tile->sign[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
+ pSign[2] = (INT16*)((BYTE*)(&tile->sign[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
- pBuffer = tile->current;
- pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */
- pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
- pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
+ pCurrent[0] = (INT16*)((BYTE*)(&tile->current[((8192 + 32) * 0) + 16])); /* Y/R buffer */
+ pCurrent[1] = (INT16*)((BYTE*)(&tile->current[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
+ pCurrent[2] = (INT16*)((BYTE*)(&tile->current[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
pBuffer = (BYTE*)BufferPool_Take(progressive->bufferPool, -1);
pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */
pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
- progressive_rfx_decode_component(progressive, &shiftY, tile->yData, tile->yLen, pSrcDst[0],
- pCurrent[0], pSign[0], diff); /* Y */
- progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen, pSrcDst[1],
- pCurrent[1], pSign[1], diff); /* Cb */
- progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen, pSrcDst[2],
- pCurrent[2], pSign[2], diff); /* Cr */
-
- prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**)pSrcDst, 64 * 2, tile->data, tile->stride,
- tile->format, &roi_64x64);
+ rc = progressive_rfx_decode_component(progressive, &shiftY, tile->yData, tile->yLen, pSrcDst[0],
+ pCurrent[0], pSign[0], diff, sub, extrapolate); /* Y */
+ if (rc < 0)
+ goto fail;
+ rc = progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen,
+ pSrcDst[1], pCurrent[1], pSign[1], diff, sub,
+ extrapolate); /* Cb */
+ if (rc < 0)
+ goto fail;
+ rc = progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen,
+ pSrcDst[2], pCurrent[2], pSign[2], diff, sub,
+ extrapolate); /* Cr */
+ if (rc < 0)
+ goto fail;
+
+ rc = prims->yCbCrToRGB_16s8u_P3AC4R((const INT16* const*)pSrcDst, 64 * 2, tile->data,
+ tile->stride, progressive->format, &roi_64x64);
+fail:
BufferPool_Return(progressive->bufferPool, pBuffer);
- return 1;
+ return rc;
}
static INLINE INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numBits)
{
- int k;
+ UINT32 k;
UINT32 bit;
UINT32 max;
UINT32 mag;
/* read sign bit */
sign = (bs->accumulator & 0x80000000) ? 1 : 0;
BitStream_Shift(bs, 1);
- state->kp -= 6;
- if (state->kp < 0)
+ if (state->kp < 6)
state->kp = 0;
+ else
+ state->kp -= 6;
if (numBits == 1)
return sign ? -1 : 1;
static INLINE int progressive_rfx_upgrade_state_finish(RFX_PROGRESSIVE_UPGRADE_STATE* state)
{
- int pad;
+ UINT32 pad;
wBitStream* srl;
wBitStream* raw;
+ if (!state)
+ return -1;
+
srl = state->srl;
raw = state->raw;
/* Read trailing bits from RAW/SRL bit streams */
return 1;
}
-static INLINE int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive,
- RFX_COMPONENT_CODEC_QUANT* shift,
- RFX_COMPONENT_CODEC_QUANT* bitPos,
- RFX_COMPONENT_CODEC_QUANT* numBits,
- INT16* buffer, INT16* current, INT16* sign,
- const BYTE* srlData, UINT32 srlLen,
- const BYTE* rawData, UINT32 rawLen)
+static INLINE int progressive_rfx_upgrade_component(
+ PROGRESSIVE_CONTEXT* progressive, const RFX_COMPONENT_CODEC_QUANT* shift,
+ const RFX_COMPONENT_CODEC_QUANT* bitPos, const RFX_COMPONENT_CODEC_QUANT* numBits,
+ INT16* buffer, INT16* current, INT16* sign, const BYTE* srlData, UINT32 srlLen,
+ const BYTE* rawData, UINT32 rawLen, BOOL subbandDiff, BOOL extrapolate)
{
+ int rc;
INT16* temp;
UINT32 aRawLen;
UINT32 aSrlLen;
- wBitStream s_srl;
- wBitStream s_raw;
- RFX_PROGRESSIVE_UPGRADE_STATE state;
+ wBitStream s_srl = { 0 };
+ wBitStream s_raw = { 0 };
+ RFX_PROGRESSIVE_UPGRADE_STATE state = { 0 };
- ZeroMemory(&s_srl, sizeof(wBitStream));
- ZeroMemory(&s_raw, sizeof(wBitStream));
- ZeroMemory(&state, sizeof(RFX_PROGRESSIVE_UPGRADE_STATE));
state.kp = 8;
state.mode = 0;
state.srl = &s_srl;
BitStream_Fetch(state.raw);
state.nonLL = TRUE;
- progressive_rfx_upgrade_block(&state, ¤t[0], &sign[0], 1023, shift->HL1, bitPos->HL1,
- numBits->HL1); /* HL1 */
- progressive_rfx_upgrade_block(&state, ¤t[1023], &sign[1023], 1023, shift->LH1,
- bitPos->LH1, numBits->LH1); /* LH1 */
- progressive_rfx_upgrade_block(&state, ¤t[2046], &sign[2046], 961, shift->HH1, bitPos->HH1,
- numBits->HH1); /* HH1 */
- progressive_rfx_upgrade_block(&state, ¤t[3007], &sign[3007], 272, shift->HL2, bitPos->HL2,
- numBits->HL2); /* HL2 */
- progressive_rfx_upgrade_block(&state, ¤t[3279], &sign[3279], 272, shift->LH2, bitPos->LH2,
- numBits->LH2); /* LH2 */
- progressive_rfx_upgrade_block(&state, ¤t[3551], &sign[3551], 256, shift->HH2, bitPos->HH2,
- numBits->HH2); /* HH2 */
- progressive_rfx_upgrade_block(&state, ¤t[3807], &sign[3807], 72, shift->HL3, bitPos->HL3,
- numBits->HL3); /* HL3 */
- progressive_rfx_upgrade_block(&state, ¤t[3879], &sign[3879], 72, shift->LH3, bitPos->LH3,
- numBits->LH3); /* LH3 */
- progressive_rfx_upgrade_block(&state, ¤t[3951], &sign[3951], 64, shift->HH3, bitPos->HH3,
- numBits->HH3); /* HH3 */
+ rc = progressive_rfx_upgrade_block(&state, ¤t[0], &sign[0], 1023, shift->HL1, bitPos->HL1,
+ numBits->HL1); /* HL1 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[1023], &sign[1023], 1023, shift->LH1,
+ bitPos->LH1, numBits->LH1); /* LH1 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[2046], &sign[2046], 961, shift->HH1,
+ bitPos->HH1, numBits->HH1); /* HH1 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[3007], &sign[3007], 272, shift->HL2,
+ bitPos->HL2, numBits->HL2); /* HL2 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[3279], &sign[3279], 272, shift->LH2,
+ bitPos->LH2, numBits->LH2); /* LH2 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[3551], &sign[3551], 256, shift->HH2,
+ bitPos->HH2, numBits->HH2); /* HH2 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[3807], &sign[3807], 72, shift->HL3,
+ bitPos->HL3, numBits->HL3); /* HL3 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[3879], &sign[3879], 72, shift->LH3,
+ bitPos->LH3, numBits->LH3); /* LH3 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_block(&state, ¤t[3951], &sign[3951], 64, shift->HH3,
+ bitPos->HH3, numBits->HH3); /* HH3 */
+ if (rc < 0)
+ return rc;
state.nonLL = FALSE;
- progressive_rfx_upgrade_block(&state, ¤t[4015], &sign[4015], 81, shift->LL3, bitPos->LL3,
- numBits->LL3); /* LL3 */
- progressive_rfx_upgrade_state_finish(&state);
+ rc = progressive_rfx_upgrade_block(&state, ¤t[4015], &sign[4015], 81, shift->LL3,
+ bitPos->LL3, numBits->LL3); /* LL3 */
+ if (rc < 0)
+ return rc;
+ rc = progressive_rfx_upgrade_state_finish(&state);
+ if (rc < 0)
+ return rc;
aRawLen = (state.raw->position + 7) / 8;
aSrlLen = (state.srl->position + 7) / 8;
temp = (INT16*)BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */
CopyMemory(buffer, current, 4096 * 2);
- progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3);
- progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2);
- progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1);
+ progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3, extrapolate);
+ progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2, extrapolate);
+ progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1, extrapolate);
BufferPool_Return(progressive->bufferPool, temp);
return 1;
}
static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive,
- RFX_PROGRESSIVE_TILE* tile)
+ RFX_PROGRESSIVE_TILE* tile,
+ PROGRESSIVE_BLOCK_REGION* region,
+ const PROGRESSIVE_BLOCK_CONTEXT* context)
{
int status;
+ BOOL sub, extrapolate;
BYTE* pBuffer;
- INT16* pSign[3];
- INT16* pSrcDst[3];
- INT16* pCurrent[3];
- PROGRESSIVE_BLOCK_REGION* region;
- RFX_COMPONENT_CODEC_QUANT shiftY;
- RFX_COMPONENT_CODEC_QUANT shiftCb;
- RFX_COMPONENT_CODEC_QUANT shiftCr;
- RFX_COMPONENT_CODEC_QUANT yBitPos;
- RFX_COMPONENT_CODEC_QUANT cbBitPos;
- RFX_COMPONENT_CODEC_QUANT crBitPos;
- RFX_COMPONENT_CODEC_QUANT yNumBits;
- RFX_COMPONENT_CODEC_QUANT cbNumBits;
- RFX_COMPONENT_CODEC_QUANT crNumBits;
+ INT16* pSign[3] = { 0 };
+ INT16* pSrcDst[3] = { 0 };
+ INT16* pCurrent[3] = { 0 };
+ RFX_COMPONENT_CODEC_QUANT shiftY = { 0 };
+ RFX_COMPONENT_CODEC_QUANT shiftCb = { 0 };
+ RFX_COMPONENT_CODEC_QUANT shiftCr = { 0 };
+ RFX_COMPONENT_CODEC_QUANT yBitPos = { 0 };
+ RFX_COMPONENT_CODEC_QUANT cbBitPos = { 0 };
+ RFX_COMPONENT_CODEC_QUANT crBitPos = { 0 };
+ RFX_COMPONENT_CODEC_QUANT yNumBits = { 0 };
+ RFX_COMPONENT_CODEC_QUANT cbNumBits = { 0 };
+ RFX_COMPONENT_CODEC_QUANT crNumBits = { 0 };
RFX_COMPONENT_CODEC_QUANT* quantY;
RFX_COMPONENT_CODEC_QUANT* quantCb;
RFX_COMPONENT_CODEC_QUANT* quantCr;
RFX_PROGRESSIVE_CODEC_QUANT* quantProg;
static const prim_size_t roi_64x64 = { 64, 64 };
const primitives_t* prims = primitives_get();
+
+ sub = context->flags & RFX_SUBBAND_DIFFING;
+ extrapolate = region->flags & RFX_DWT_REDUCE_EXTRAPOLATE;
+
tile->pass++;
WLog_Print(progressive->log, WLOG_DEBUG,
"ProgressiveTileUpgrade: pass: %" PRIu16 " quantIdx Y: %" PRIu8 " Cb: %" PRIu8
tile->pass, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx,
tile->yIdx, tile->quality, tile->ySrlLen, tile->yRawLen, tile->cbSrlLen,
tile->cbRawLen, tile->crSrlLen, tile->crRawLen);
- region = &(progressive->region);
if (tile->quantIdxY >= region->numQuant)
+ {
+ WLog_ERR(TAG, "quantIdxY %" PRIu8 " > numQuant %" PRIu8, tile->quantIdxY, region->numQuant);
return -1;
+ }
quantY = &(region->quantVals[tile->quantIdxY]);
if (tile->quantIdxCb >= region->numQuant)
+ {
+ WLog_ERR(TAG, "quantIdxCb %" PRIu8 " > numQuant %" PRIu8, tile->quantIdxCb,
+ region->numQuant);
return -1;
+ }
quantCb = &(region->quantVals[tile->quantIdxCb]);
if (tile->quantIdxCr >= region->numQuant)
+ {
+ WLog_ERR(TAG, "quantIdxCr %" PRIu8 " > numQuant %" PRIu8, tile->quantIdxCr,
+ region->numQuant);
return -1;
+ }
quantCr = &(region->quantVals[tile->quantIdxCr]);
else
{
if (tile->quality >= region->numProgQuant)
+ {
+ WLog_ERR(TAG, "quality %" PRIu8 " > numProgQuant %" PRIu8, tile->quality,
+ region->numProgQuant);
return -1;
+ }
quantProg = &(region->quantProgVals[tile->quality]);
}
if (!progressive_rfx_quant_cmp_equal(quantCr, &(tile->crQuant)))
WLog_Print(progressive->log, WLOG_WARN, "non-progressive quantCr has changed!");
+ if (!(region->flags & RFX_DWT_REDUCE_EXTRAPOLATE))
+ WLog_Print(progressive->log, WLOG_WARN,
+ "RFX_PROGRESSIVE_REGION::flags & RFX_DWT_REDUCE_EXTRAPOLATE not set");
+
+ if (!(context->flags & RFX_SUBBAND_DIFFING))
+ WLog_WARN(TAG, "PROGRESSIVE_BLOCK_CONTEXT::flags & RFX_SUBBAND_DIFFING not set");
+
progressive_rfx_quant_add(quantY, quantProgY, &yBitPos);
progressive_rfx_quant_add(quantCb, quantProgCb, &cbBitPos);
progressive_rfx_quant_add(quantCr, quantProgCr, &crBitPos);
progressive_rfx_quant_add(quantCr, quantProgCr, &shiftCr);
progressive_rfx_quant_lsub(&shiftCr, 1); /* -6 + 5 = -1 */
- CopyMemory(&(tile->yBitPos), &yBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->cbBitPos), &cbBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->crBitPos), &crBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->yQuant), quantY, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->cbQuant), quantCb, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->crQuant), quantCr, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->yProgQuant), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->cbProgQuant), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT));
- CopyMemory(&(tile->crProgQuant), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT));
-
- pBuffer = tile->sign;
- pSign[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */
- pSign[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
- pSign[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
-
- pBuffer = tile->current;
- pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */
- pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
- pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
+ tile->yBitPos = yBitPos;
+ tile->cbBitPos = cbBitPos;
+ tile->crBitPos = crBitPos;
+ tile->yQuant = *quantY;
+ tile->cbQuant = *quantCb;
+ tile->crQuant = *quantCr;
+ tile->yProgQuant = *quantProgY;
+ tile->cbProgQuant = *quantProgCb;
+ tile->crProgQuant = *quantProgCr;
+
+ pSign[0] = (INT16*)((BYTE*)(&tile->sign[((8192 + 32) * 0) + 16])); /* Y/R buffer */
+ pSign[1] = (INT16*)((BYTE*)(&tile->sign[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
+ pSign[2] = (INT16*)((BYTE*)(&tile->sign[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
+
+ pCurrent[0] = (INT16*)((BYTE*)(&tile->current[((8192 + 32) * 0) + 16])); /* Y/R buffer */
+ pCurrent[1] = (INT16*)((BYTE*)(&tile->current[((8192 + 32) * 1) + 16])); /* Cb/G buffer */
+ pCurrent[2] = (INT16*)((BYTE*)(&tile->current[((8192 + 32) * 2) + 16])); /* Cr/B buffer */
pBuffer = (BYTE*)BufferPool_Take(progressive->bufferPool, -1);
pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */
status = progressive_rfx_upgrade_component(
progressive, &shiftY, quantProgY, &yNumBits, pSrcDst[0], pCurrent[0], pSign[0],
- tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen); /* Y */
+ tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen, sub, extrapolate); /* Y */
if (status < 0)
- return -1;
+ goto fail;
- status = progressive_rfx_upgrade_component(
- progressive, &shiftCb, quantProgCb, &cbNumBits, pSrcDst[1], pCurrent[1], pSign[1],
- tile->cbSrlData, tile->cbSrlLen, tile->cbRawData, tile->cbRawLen); /* Cb */
+ status = progressive_rfx_upgrade_component(progressive, &shiftCb, quantProgCb, &cbNumBits,
+ pSrcDst[1], pCurrent[1], pSign[1], tile->cbSrlData,
+ tile->cbSrlLen, tile->cbRawData, tile->cbRawLen, sub,
+ extrapolate); /* Cb */
if (status < 0)
- return -1;
+ goto fail;
- status = progressive_rfx_upgrade_component(
- progressive, &shiftCr, quantProgCr, &crNumBits, pSrcDst[2], pCurrent[2], pSign[2],
- tile->crSrlData, tile->crSrlLen, tile->crRawData, tile->crRawLen); /* Cr */
+ status = progressive_rfx_upgrade_component(progressive, &shiftCr, quantProgCr, &crNumBits,
+ pSrcDst[2], pCurrent[2], pSign[2], tile->crSrlData,
+ tile->crSrlLen, tile->crRawData, tile->crRawLen, sub,
+ extrapolate); /* Cr */
if (status < 0)
- return -1;
+ goto fail;
- prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**)pSrcDst, 64 * 2, tile->data, tile->stride,
- tile->format, &roi_64x64);
+ status = prims->yCbCrToRGB_16s8u_P3AC4R((const INT16* const*)pSrcDst, 64 * 2, tile->data,
+ tile->stride, progressive->format, &roi_64x64);
+fail:
BufferPool_Return(progressive->bufferPool, pBuffer);
- return 1;
+ return status;
+}
+
+static INLINE BOOL progressive_tile_read_upgrade(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen,
+ PROGRESSIVE_SURFACE_CONTEXT* surface,
+ PROGRESSIVE_BLOCK_REGION* region,
+ const PROGRESSIVE_BLOCK_CONTEXT* context)
+{
+ RFX_PROGRESSIVE_TILE tile = { 0 };
+ const size_t expect = 20;
+
+ if (Stream_GetRemainingLength(s) < expect)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "Expected %" PRIuz " bytes, got %" PRIuz, expect,
+ Stream_GetRemainingLength(s));
+ return FALSE;
+ }
+
+ tile.blockType = blockType;
+ tile.blockLen = blockLen;
+ tile.flags = 0;
+
+ Stream_Read_UINT8(s, tile.quantIdxY);
+ Stream_Read_UINT8(s, tile.quantIdxCb);
+ Stream_Read_UINT8(s, tile.quantIdxCr);
+ Stream_Read_UINT16(s, tile.xIdx);
+ Stream_Read_UINT16(s, tile.yIdx);
+ Stream_Read_UINT8(s, tile.quality);
+ Stream_Read_UINT16(s, tile.ySrlLen);
+ Stream_Read_UINT16(s, tile.yRawLen);
+ Stream_Read_UINT16(s, tile.cbSrlLen);
+ Stream_Read_UINT16(s, tile.cbRawLen);
+ Stream_Read_UINT16(s, tile.crSrlLen);
+ Stream_Read_UINT16(s, tile.crRawLen);
+
+ tile.ySrlData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.ySrlLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes", tile.ySrlLen);
+ return FALSE;
+ }
+
+ tile.yRawData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.yRawLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes", tile.yRawLen);
+ return FALSE;
+ }
+
+ tile.cbSrlData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.cbSrlLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes",
+ tile.cbSrlLen);
+ return FALSE;
+ }
+
+ tile.cbRawData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.cbRawLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes",
+ tile.cbRawLen);
+ return FALSE;
+ }
+
+ tile.crSrlData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.crSrlLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes",
+ tile.crSrlLen);
+ return FALSE;
+ }
+
+ tile.crRawData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.crRawLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes",
+ tile.crRawLen);
+ return FALSE;
+ }
+
+ return progressive_surface_tile_replace(surface, region, &tile, TRUE);
+}
+
+static INLINE BOOL progressive_tile_read(PROGRESSIVE_CONTEXT* progressive, BOOL simple, wStream* s,
+ UINT16 blockType, UINT32 blockLen,
+ PROGRESSIVE_SURFACE_CONTEXT* surface,
+ PROGRESSIVE_BLOCK_REGION* region,
+ const PROGRESSIVE_BLOCK_CONTEXT* context)
+{
+ RFX_PROGRESSIVE_TILE tile = { 0 };
+ size_t expect = simple ? 16 : 17;
+
+ if (Stream_GetRemainingLength(s) < expect)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "Expected %" PRIuz " bytes, got %" PRIuz, expect,
+ Stream_GetRemainingLength(s));
+ return FALSE;
+ }
+
+ tile.blockType = blockType;
+ tile.blockLen = blockLen;
+
+ Stream_Read_UINT8(s, tile.quantIdxY);
+ Stream_Read_UINT8(s, tile.quantIdxCb);
+ Stream_Read_UINT8(s, tile.quantIdxCr);
+ Stream_Read_UINT16(s, tile.xIdx);
+ Stream_Read_UINT16(s, tile.yIdx);
+ Stream_Read_UINT8(s, tile.flags);
+
+ if (!simple)
+ Stream_Read_UINT8(s, tile.quality);
+ else
+ tile.quality = 0xFF;
+ Stream_Read_UINT16(s, tile.yLen);
+ Stream_Read_UINT16(s, tile.cbLen);
+ Stream_Read_UINT16(s, tile.crLen);
+ Stream_Read_UINT16(s, tile.tailLen);
+
+ tile.yData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.yLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes", tile.yLen);
+ return FALSE;
+ }
+
+ tile.cbData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.cbLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes", tile.cbLen);
+ return FALSE;
+ }
+
+ tile.crData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.crLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes", tile.crLen);
+ return FALSE;
+ }
+
+ tile.tailData = Stream_Pointer(s);
+ if (!Stream_SafeSeek(s, tile.tailLen))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, " Failed to seek %" PRIu32 " bytes", tile.tailLen);
+ return FALSE;
+ }
+
+ return progressive_surface_tile_replace(surface, region, &tile, FALSE);
}
-static INLINE int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, const BYTE* blocks,
- UINT32 blocksLen,
- const PROGRESSIVE_SURFACE_CONTEXT* surface)
+static INLINE int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ PROGRESSIVE_BLOCK_REGION* region,
+ PROGRESSIVE_SURFACE_CONTEXT* surface,
+ const PROGRESSIVE_BLOCK_CONTEXT* context)
{
int status = -1;
- const BYTE* block;
- UINT16 xIdx;
- UINT16 yIdx;
- UINT16 zIdx;
+ size_t end;
+ const size_t start = Stream_GetPosition(s);
UINT16 index;
- UINT32 boffset;
UINT16 blockType;
UINT32 blockLen;
UINT32 count = 0;
- UINT32 offset = 0;
- RFX_PROGRESSIVE_TILE* tile;
- RFX_PROGRESSIVE_TILE** tiles;
- PROGRESSIVE_BLOCK_REGION* region;
- region = &(progressive->region);
- tiles = region->tiles;
- while ((blocksLen - offset) >= 6)
+ if (Stream_GetRemainingLength(s) < region->tileDataSize)
{
- boffset = 0;
- block = &blocks[offset];
- blockType = *((UINT16*)&block[boffset + 0]); /* blockType (2 bytes) */
- blockLen = *((UINT32*)&block[boffset + 2]); /* blockLen (4 bytes) */
- boffset += 6;
+ WLog_Print(progressive->log, WLOG_ERROR, "Short block %" PRIuz ", expected %" PRIu32,
+ Stream_GetRemainingLength(s), region->tileDataSize);
+ return -1;
+ }
+
+ while ((Stream_GetRemainingLength(s) >= 6) &&
+ (region->tileDataSize > (Stream_GetPosition(s) - start)))
+ {
+ size_t rem;
+ const size_t pos = Stream_GetPosition(s);
+ rem = Stream_GetRemainingLength(s);
+
+ Stream_Read_UINT16(s, blockType);
+ Stream_Read_UINT32(s, blockLen);
+
WLog_Print(progressive->log, WLOG_DEBUG, "%s",
progressive_get_block_type_string(blockType));
- if ((blocksLen - offset) < blockLen)
+ if (rem < blockLen)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "Expected %" PRIu32 " remaining %" PRIuz,
+ blockLen, rem);
return -1003;
+ }
+ rem = Stream_GetRemainingLength(s);
switch (blockType)
{
case PROGRESSIVE_WBT_TILE_SIMPLE:
- if ((blockLen - boffset) < 16)
+ if (!progressive_tile_read(progressive, TRUE, s, blockType, blockLen, surface,
+ region, context))
return -1022;
-
- xIdx = *((UINT16*)&block[boffset + 3]); /* xIdx (2 bytes) */
- yIdx = *((UINT16*)&block[boffset + 5]); /* yIdx (2 bytes) */
- zIdx = (yIdx * surface->gridWidth) + xIdx;
-
- if (zIdx >= surface->gridSize)
- return -1;
-
- tiles[count] = tile = &(surface->tiles[zIdx]);
- tile->blockType = blockType;
- tile->blockLen = blockLen;
- tile->quality = 0xFF; /* simple tiles use no progressive techniques */
- tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */
- tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */
- tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */
- tile->xIdx = *((UINT16*)&block[boffset + 3]); /* xIdx (2 bytes) */
- tile->yIdx = *((UINT16*)&block[boffset + 5]); /* yIdx (2 bytes) */
- tile->flags = block[boffset + 7] & 1; /* flags (1 byte) */
- tile->yLen = *((UINT16*)&block[boffset + 8]); /* yLen (2 bytes) */
- tile->cbLen = *((UINT16*)&block[boffset + 10]); /* cbLen (2 bytes) */
- tile->crLen = *((UINT16*)&block[boffset + 12]); /* crLen (2 bytes) */
- tile->tailLen = *((UINT16*)&block[boffset + 14]); /* tailLen (2 bytes) */
- boffset += 16;
-
- if ((tile->blockLen - boffset) < tile->yLen)
- return -1023;
-
- tile->yData = &block[boffset];
- boffset += tile->yLen;
-
- if ((tile->blockLen - boffset) < tile->cbLen)
- return -1024;
-
- tile->cbData = &block[boffset];
- boffset += tile->cbLen;
-
- if ((tile->blockLen - boffset) < tile->crLen)
- return -1025;
-
- tile->crData = &block[boffset];
- boffset += tile->crLen;
-
- if ((tile->blockLen - boffset) < tile->tailLen)
- return -1026;
-
- tile->tailData = &block[boffset];
- boffset += tile->tailLen;
- tile->width = 64;
- tile->height = 64;
- tile->x = tile->xIdx * 64;
- tile->y = tile->yIdx * 64;
- tile->format = progressive->format;
- tile->stride = GetBytesPerPixel(tile->format) * tile->width;
- tile->flags &= 1;
break;
case PROGRESSIVE_WBT_TILE_FIRST:
- if ((blockLen - boffset) < 17)
+ if (!progressive_tile_read(progressive, FALSE, s, blockType, blockLen, surface,
+ region, context))
return -1027;
-
- xIdx = *((UINT16*)&block[boffset + 3]); /* xIdx (2 bytes) */
- yIdx = *((UINT16*)&block[boffset + 5]); /* yIdx (2 bytes) */
- zIdx = (yIdx * surface->gridWidth) + xIdx;
-
- if (zIdx >= surface->gridSize)
- return -1;
-
- tiles[count] = tile = &(surface->tiles[zIdx]);
- tile->blockType = blockType;
- tile->blockLen = blockLen;
- tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */
- tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */
- tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */
- tile->xIdx = *((UINT16*)&block[boffset + 3]); /* xIdx (2 bytes) */
- tile->yIdx = *((UINT16*)&block[boffset + 5]); /* yIdx (2 bytes) */
- tile->flags = block[boffset + 7] & 1; /* flags (1 byte) */
- tile->quality = block[boffset + 8]; /* quality (1 byte) */
- tile->yLen = *((UINT16*)&block[boffset + 9]); /* yLen (2 bytes) */
- tile->cbLen = *((UINT16*)&block[boffset + 11]); /* cbLen (2 bytes) */
- tile->crLen = *((UINT16*)&block[boffset + 13]); /* crLen (2 bytes) */
- tile->tailLen = *((UINT16*)&block[boffset + 15]); /* tailLen (2 bytes) */
- boffset += 17;
-
- if ((tile->blockLen - boffset) < tile->yLen)
- return -1028;
-
- tile->yData = &block[boffset];
- boffset += tile->yLen;
-
- if ((tile->blockLen - boffset) < tile->cbLen)
- return -1029;
-
- tile->cbData = &block[boffset];
- boffset += tile->cbLen;
-
- if ((tile->blockLen - boffset) < tile->crLen)
- return -1030;
-
- tile->crData = &block[boffset];
- boffset += tile->crLen;
-
- if ((tile->blockLen - boffset) < tile->tailLen)
- return -1031;
-
- tile->tailData = &block[boffset];
- boffset += tile->tailLen;
- tile->width = 64;
- tile->height = 64;
- tile->x = tile->xIdx * 64;
- tile->y = tile->yIdx * 64;
- tile->format = progressive->format;
- tile->stride = GetBytesPerPixel(tile->format) * tile->width;
break;
case PROGRESSIVE_WBT_TILE_UPGRADE:
- if ((blockLen - boffset) < 20)
+ if (!progressive_tile_read_upgrade(progressive, s, blockType, blockLen, surface,
+ region, context))
return -1032;
-
- xIdx = *((UINT16*)&block[boffset + 3]); /* xIdx (2 bytes) */
- yIdx = *((UINT16*)&block[boffset + 5]); /* yIdx (2 bytes) */
- zIdx = (yIdx * surface->gridWidth) + xIdx;
-
- if (zIdx >= surface->gridSize)
- return -1;
-
- tiles[count] = tile = &(surface->tiles[zIdx]);
- tile->blockType = blockType;
- tile->blockLen = blockLen;
- tile->flags = 0;
- tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */
- tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */
- tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */
- tile->xIdx = *((UINT16*)&block[boffset + 3]); /* xIdx (2 bytes) */
- tile->yIdx = *((UINT16*)&block[boffset + 5]); /* yIdx (2 bytes) */
- tile->quality = block[boffset + 7]; /* quality (1 byte) */
- tile->ySrlLen = *((UINT16*)&block[boffset + 8]); /* ySrlLen (2 bytes) */
- tile->yRawLen = *((UINT16*)&block[boffset + 10]); /* yRawLen (2 bytes) */
- tile->cbSrlLen = *((UINT16*)&block[boffset + 12]); /* cbSrlLen (2 bytes) */
- tile->cbRawLen = *((UINT16*)&block[boffset + 14]); /* cbRawLen (2 bytes) */
- tile->crSrlLen = *((UINT16*)&block[boffset + 16]); /* crSrlLen (2 bytes) */
- tile->crRawLen = *((UINT16*)&block[boffset + 18]); /* crRawLen (2 bytes) */
- boffset += 20;
-
- if ((tile->blockLen - boffset) < tile->ySrlLen)
- return -1033;
-
- tile->ySrlData = &block[boffset];
- boffset += tile->ySrlLen;
-
- if ((tile->blockLen - boffset) < tile->yRawLen)
- return -1034;
-
- tile->yRawData = &block[boffset];
- boffset += tile->yRawLen;
-
- if ((tile->blockLen - boffset) < tile->cbSrlLen)
- return -1035;
-
- tile->cbSrlData = &block[boffset];
- boffset += tile->cbSrlLen;
-
- if ((tile->blockLen - boffset) < tile->cbRawLen)
- return -1036;
-
- tile->cbRawData = &block[boffset];
- boffset += tile->cbRawLen;
-
- if ((tile->blockLen - boffset) < tile->crSrlLen)
- return -1037;
-
- tile->crSrlData = &block[boffset];
- boffset += tile->crSrlLen;
-
- if ((tile->blockLen - boffset) < tile->crRawLen)
- return -1038;
-
- tile->crRawData = &block[boffset];
- boffset += tile->crRawLen;
- tile->width = 64;
- tile->height = 64;
- tile->x = tile->xIdx * 64;
- tile->y = tile->yIdx * 64;
- tile->format = progressive->format;
- tile->stride = GetBytesPerPixel(tile->format) * tile->width;
break;
-
default:
+ WLog_ERR(TAG, "Invalid block type %04 (%s)" PRIx16, blockType,
+ progressive_get_block_type_string(blockType));
return -1039;
}
- if (boffset != blockLen)
+ rem = Stream_GetPosition(s);
+ if ((rem - pos) != blockLen)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "Actual block read %" PRIuz " but expected %" PRIu32, rem - pos, blockLen);
return -1040;
-
- offset += blockLen;
+ }
count++;
}
- if (offset != blocksLen)
+ end = Stream_GetPosition(s);
+ if ((end - start) != region->tileDataSize)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "Actual total blocks read %" PRIuz " but expected %" PRIu32, end - start,
+ region->tileDataSize);
return -1041;
+ }
if (count != region->numTiles)
{
WLog_Print(progressive->log, WLOG_WARN,
"numTiles inconsistency: actual: %" PRIu32 ", expected: %" PRIu16 "\n", count,
region->numTiles);
+ return -1044;
}
for (index = 0; index < region->numTiles; index++)
{
- tile = tiles[index];
+ RFX_PROGRESSIVE_TILE* tile = region->tiles[index];
switch (tile->blockType)
{
case PROGRESSIVE_WBT_TILE_SIMPLE:
case PROGRESSIVE_WBT_TILE_FIRST:
- status = progressive_decompress_tile_first(progressive, tile);
+ status = progressive_decompress_tile_first(progressive, tile, region, context);
break;
case PROGRESSIVE_WBT_TILE_UPGRADE:
- status = progressive_decompress_tile_upgrade(progressive, tile);
+ status = progressive_decompress_tile_upgrade(progressive, tile, region, context);
break;
+ default:
+ WLog_Print(progressive->log, WLOG_ERROR, "Invalid block type %04 (%s)" PRIx16,
+ tile->blockType, progressive_get_block_type_string(tile->blockType));
+ return -42;
}
if (status < 0)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "Failed to decompress %s at %" PRIu16,
+ progressive_get_block_type_string(tile->blockType), index);
return -1;
+ }
}
- return (int)offset;
+ return (int)end - start;
}
-INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
- BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,
- UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId)
+static INLINE INT32 progressive_wb_sync(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen)
{
- INT32 rc = 1;
- INT32 status;
- const BYTE* block;
- const BYTE* blocks;
- UINT16 i, j;
+ const UINT32 magic = 0xCACCACCA;
+ const UINT16 version = 0x0100;
+ PROGRESSIVE_BLOCK_SYNC sync;
+
+ sync.blockType = blockType;
+ sync.blockLen = blockLen;
+
+ if (sync.blockLen != 12)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "PROGRESSIVE_BLOCK_SYNC::blockLen = 0x%08" PRIx32 " != 0x%08" PRIx32,
+ sync.blockLen, 12);
+ return -1005;
+ }
+
+ if (Stream_GetRemainingLength(s) < 6)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveSync short %" PRIuz ", expected %" PRIuz,
+ Stream_GetRemainingLength(s), 6);
+ return -1004;
+ }
+
+ WLog_Print(progressive->log, WLOG_DEBUG, "ProgressiveSync");
+
+ Stream_Read_UINT32(s, sync.magic);
+ Stream_Read_UINT16(s, sync.version);
+
+ if (sync.magic != magic)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "PROGRESSIVE_BLOCK_SYNC::magic = 0x%08" PRIx32 " != 0x%08" PRIx32, sync.magic,
+ magic);
+ return -1005;
+ }
+
+ if (sync.version != 0x0100)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "PROGRESSIVE_BLOCK_SYNC::version = 0x%04" PRIx16 " != 0x%04" PRIu16,
+ sync.version, version);
+ return -1006;
+ }
+
+ if ((progressive->state & FLAG_WBT_SYNC) != 0)
+ WLog_WARN(TAG, "Duplicate PROGRESSIVE_BLOCK_SYNC, ignoring");
+
+ progressive->state |= FLAG_WBT_SYNC;
+ return 1;
+}
+
+static INLINE INT32 progressive_wb_frame_begin(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen)
+{
+ PROGRESSIVE_BLOCK_FRAME_BEGIN frameBegin;
+
+ frameBegin.blockType = blockType;
+ frameBegin.blockLen = blockLen;
+
+ if (frameBegin.blockLen != 12)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ " RFX_PROGRESSIVE_FRAME_BEGIN::blockLen = 0x%08" PRIx32 " != 0x%08" PRIx32,
+ frameBegin.blockLen, 12);
+ return -1005;
+ }
+
+ if (Stream_GetRemainingLength(s) < 6)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveFrameBegin short %" PRIuz ", expected %" PRIuz,
+ Stream_GetRemainingLength(s), 6);
+ return -1007;
+ }
+
+ Stream_Read_UINT32(s, frameBegin.frameIndex);
+ Stream_Read_UINT16(s, frameBegin.regionCount);
+
+ WLog_Print(progressive->log, WLOG_DEBUG,
+ "ProgressiveFrameBegin: frameIndex: %" PRIu32 " regionCount: %" PRIu16 "",
+ frameBegin.frameIndex, frameBegin.regionCount);
+ /**
+ * If the number of elements specified by the regionCount field is
+ * larger than the actual number of elements in the regions field,
+ * the decoder SHOULD ignore this inconsistency.
+ */
+
+ if ((progressive->state & FLAG_WBT_FRAME_BEGIN) != 0)
+ {
+ WLog_ERR(TAG, "Duplicate RFX_PROGRESSIVE_FRAME_BEGIN in stream, this is not allowed!");
+ return -1008;
+ }
+
+ if ((progressive->state & FLAG_WBT_FRAME_END) != 0)
+ {
+ WLog_ERR(TAG, "RFX_PROGRESSIVE_FRAME_BEGIN after RFX_PROGRESSIVE_FRAME_END in stream, this "
+ "is not allowed!");
+ return -1008;
+ }
+
+ progressive->state |= FLAG_WBT_FRAME_BEGIN;
+ return 1;
+}
+
+static INLINE INT32 progressive_wb_frame_end(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen)
+{
+ PROGRESSIVE_BLOCK_FRAME_END frameEnd;
+
+ frameEnd.blockType = blockType;
+ frameEnd.blockLen = blockLen;
+
+ if (frameEnd.blockLen != 6)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ " RFX_PROGRESSIVE_FRAME_END::blockLen = 0x%08" PRIx32 " != 0x%08" PRIx32,
+ frameEnd.blockLen, 6);
+ return -1005;
+ }
+
+ if (Stream_GetRemainingLength(s) != 0)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveFrameEnd short %" PRIuz ", expected %" PRIuz,
+ Stream_GetRemainingLength(s), 0);
+ return -1008;
+ }
+
+ WLog_Print(progressive->log, WLOG_DEBUG, "ProgressiveFrameEnd");
+ if ((progressive->state & FLAG_WBT_FRAME_BEGIN) == 0)
+ WLog_WARN(TAG, "RFX_PROGRESSIVE_FRAME_END before RFX_PROGRESSIVE_FRAME_BEGIN, ignoring");
+ if ((progressive->state & FLAG_WBT_FRAME_END) != 0)
+ WLog_WARN(TAG, "Duplicate RFX_PROGRESSIVE_FRAME_END, ignoring");
+
+ progressive->state |= FLAG_WBT_FRAME_END;
+ return 1;
+}
+
+static INLINE int progressive_wb_context(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen)
+{
+ PROGRESSIVE_BLOCK_CONTEXT* context = &progressive->context;
+ context->blockType = blockType;
+ context->blockLen = blockLen;
+
+ if (context->blockLen != 10)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "RFX_PROGRESSIVE_CONTEXT::blockLen = 0x%08" PRIx32 " != 0x%08" PRIx32,
+ context->blockLen, 10);
+ return -1005;
+ }
+
+ if (Stream_GetRemainingLength(s) < 4)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveContext short %" PRIuz ", expected %" PRIuz,
+ Stream_GetRemainingLength(s), 4);
+ return -1009;
+ }
+
+ Stream_Read_UINT8(s, context->ctxId);
+ Stream_Read_UINT16(s, context->tileSize);
+ Stream_Read_UINT8(s, context->flags);
+
+ if (context->ctxId != 0x00)
+ WLog_WARN(TAG, "RFX_PROGRESSIVE_CONTEXT::ctxId != 0x00: %" PRIu8, context->ctxId);
+
+ if (context->tileSize != 64)
+ {
+ WLog_ERR(TAG, "RFX_PROGRESSIVE_CONTEXT::tileSize != 0x40: %" PRIu16, context->tileSize);
+ return -1010;
+ }
+
+ if ((progressive->state & FLAG_WBT_FRAME_BEGIN) != 0)
+ WLog_WARN(TAG, "RFX_PROGRESSIVE_CONTEXT received after RFX_PROGRESSIVE_FRAME_BEGIN");
+ if ((progressive->state & FLAG_WBT_FRAME_END) != 0)
+ WLog_WARN(TAG, "RFX_PROGRESSIVE_CONTEXT received after RFX_PROGRESSIVE_FRAME_END");
+ if ((progressive->state & FLAG_WBT_CONTEXT) != 0)
+ WLog_WARN(TAG, "Duplicate RFX_PROGRESSIVE_CONTEXT received, ignoring.");
+
+ WLog_Print(progressive->log, WLOG_DEBUG, "ProgressiveContext: flags: 0x%02" PRIX8 "",
+ context->flags);
+
+ progressive->state |= FLAG_WBT_CONTEXT;
+ return 1;
+}
+
+static INLINE INT32 progressive_wb_read_region_header(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen,
+ PROGRESSIVE_BLOCK_REGION* region)
+{
+ size_t offset, len;
+
+ if (Stream_GetRemainingLength(s) < 12)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveRegion short %" PRIuz ", expected %" PRIuz,
+ Stream_GetRemainingLength(s), 12);
+ return -1011;
+ }
+
+ region->blockType = blockType;
+ region->blockLen = blockLen;
+ Stream_Read_UINT8(s, region->tileSize);
+ Stream_Read_UINT16(s, region->numRects);
+ Stream_Read_UINT8(s, region->numQuant);
+ Stream_Read_UINT8(s, region->numProgQuant);
+ Stream_Read_UINT8(s, region->flags);
+ Stream_Read_UINT16(s, region->numTiles);
+ Stream_Read_UINT32(s, region->tileDataSize);
+
+ if (region->tileSize != 64)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveRegion tile size %" PRIu8 ", expected %" PRIuz, region->tileSize,
+ 64);
+ return -1012;
+ }
+
+ if (region->numRects < 1)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion missing rect count %" PRIu16,
+ region->numRects);
+ return -1013;
+ }
+
+ if (region->numQuant > 7)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveRegion quant count too high %" PRIu8 ", expected < %" PRIuz,
+ region->numQuant, 7);
+ return -1014;
+ }
+
+ len = Stream_GetRemainingLength(s);
+ offset = (region->numRects * 8);
+ if (len < offset)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion data short for region->rects");
+ return -1015;
+ }
+
+ offset += (region->numQuant * 5);
+ if (len < offset)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion data short for region->cQuant");
+ return -1018;
+ }
+
+ offset += (region->numProgQuant * 16);
+ if (len < offset)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveRegion data short for region->cProgQuant");
+ return -1021;
+ }
+
+ offset += region->tileDataSize;
+ if (len < offset)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion data short for region->tiles");
+ return -1024;
+ }
+
+ return 0;
+}
+
+static INLINE INT32 progressive_wb_skip_region(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen)
+{
+ INT32 rc;
+ size_t total;
+ PROGRESSIVE_BLOCK_REGION region = { 0 };
+
+ rc = progressive_wb_read_region_header(progressive, s, blockType, blockLen, ®ion);
+ if (rc < 0)
+ return rc;
+
+ total = (region.numRects * 8);
+ total += (region.numQuant * 5);
+ total += (region.numProgQuant * 16);
+ total += region.tileDataSize;
+ if (!Stream_SafeSeek(s, total))
+ return -1111;
+
+ return 0;
+}
+
+static INLINE INT32 progressive_wb_region(PROGRESSIVE_CONTEXT* progressive, wStream* s,
+ UINT16 blockType, UINT32 blockLen,
+ PROGRESSIVE_SURFACE_CONTEXT* surface,
+ PROGRESSIVE_BLOCK_REGION* region)
+{
+ INT32 rc;
UINT16 index;
UINT16 boxLeft;
UINT16 boxTop;
UINT16 idxTop;
UINT16 idxRight;
UINT16 idxBottom;
- UINT32 boffset;
+ const PROGRESSIVE_BLOCK_CONTEXT* context = &progressive->context;
+
+ if ((progressive->state & FLAG_WBT_FRAME_BEGIN) == 0)
+ {
+ WLog_WARN(TAG, "RFX_PROGRESSIVE_REGION before RFX_PROGRESSIVE_FRAME_BEGIN, ignoring");
+ return progressive_wb_skip_region(progressive, s, blockType, blockLen);
+ }
+ if ((progressive->state & FLAG_WBT_FRAME_END) != 0)
+ {
+ WLog_WARN(TAG, "RFX_PROGRESSIVE_REGION after RFX_PROGRESSIVE_FRAME_END, ignoring");
+ return progressive_wb_skip_region(progressive, s, blockType, blockLen);
+ }
+
+ progressive->state |= FLAG_WBT_REGION;
+
+ rc = progressive_wb_read_region_header(progressive, s, blockType, blockLen, region);
+ if (rc < 0)
+ return rc;
+
+ for (index = 0; index < region->numRects; index++)
+ {
+ RFX_RECT* rect = &(region->rects[index]);
+ Stream_Read_UINT16(s, rect->x);
+ Stream_Read_UINT16(s, rect->y);
+ Stream_Read_UINT16(s, rect->width);
+ Stream_Read_UINT16(s, rect->height);
+ }
+
+ for (index = 0; index < region->numQuant; index++)
+ {
+ RFX_COMPONENT_CODEC_QUANT* quantVal = &(region->quantVals[index]);
+ progressive_component_codec_quant_read(s, quantVal);
+
+ if (!progressive_rfx_quant_lcmp_greater_equal(quantVal, 6))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveRegion region->cQuant[%" PRIu32 "] < 6", index);
+ return -1;
+ }
+
+ if (!progressive_rfx_quant_lcmp_less_equal(quantVal, 15))
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "ProgressiveRegion region->cQuant[%" PRIu32 "] > 15", index);
+ return -1;
+ }
+ }
+
+ for (index = 0; index < region->numProgQuant; index++)
+ {
+ RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal = &(region->quantProgVals[index]);
+
+ Stream_Read_UINT8(s, quantProgVal->quality);
+
+ progressive_component_codec_quant_read(s, &(quantProgVal->yQuantValues));
+ progressive_component_codec_quant_read(s, &(quantProgVal->cbQuantValues));
+ progressive_component_codec_quant_read(s, &(quantProgVal->crQuantValues));
+ }
+
+ WLog_Print(progressive->log, WLOG_DEBUG,
+ "ProgressiveRegion: numRects: %" PRIu16 " numTiles: %" PRIu16
+ " tileDataSize: %" PRIu32 " flags: 0x%02" PRIX8 " numQuant: %" PRIu8
+ " numProgQuant: %" PRIu8 "",
+ region->numRects, region->numTiles, region->tileDataSize, region->flags,
+ region->numQuant, region->numProgQuant);
+
+ boxLeft = surface->gridWidth;
+ boxTop = surface->gridHeight;
+ boxRight = 0;
+ boxBottom = 0;
+
+ for (index = 0; index < region->numRects; index++)
+ {
+ RFX_RECT* rect = &(region->rects[index]);
+ idxLeft = rect->x / 64;
+ idxTop = rect->y / 64;
+ idxRight = (rect->x + rect->width + 63) / 64;
+ idxBottom = (rect->y + rect->height + 63) / 64;
+
+ if (idxLeft < boxLeft)
+ boxLeft = idxLeft;
+
+ if (idxTop < boxTop)
+ boxTop = idxTop;
+
+ if (idxRight > boxRight)
+ boxRight = idxRight;
+
+ if (idxBottom > boxBottom)
+ boxBottom = idxBottom;
+
+ WLog_Print(progressive->log, WLOG_DEBUG,
+ "rect[%" PRIu16 "]: x: %" PRIu16 " y: %" PRIu16 " w: %" PRIu16 " h: %" PRIu16 "",
+ index, rect->x, rect->y, rect->width, rect->height);
+ }
+
+ return progressive_process_tiles(progressive, s, region, surface, context);
+}
+
+INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
+ BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst,
+ UINT32 nYDst, REGION16* invalidRegion, UINT16 surfaceId)
+{
+ INT32 rc = 1;
+ UINT16 i, j;
UINT16 blockType;
UINT32 blockLen;
- UINT32 blocksLen;
UINT32 count = 0;
- UINT32 offset = 0;
- RFX_RECT* rect = NULL;
+ wStream *s, ss;
+ size_t start, end;
REGION16 clippingRects, updateRegion;
- PROGRESSIVE_SURFACE_CONTEXT* surface;
PROGRESSIVE_BLOCK_REGION* region;
- surface = (PROGRESSIVE_SURFACE_CONTEXT*)progressive_get_surface_data(progressive, surfaceId);
+ PROGRESSIVE_SURFACE_CONTEXT* surface = progressive_get_surface_data(progressive, surfaceId);
if (!surface)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "ProgressiveRegion no surface for %" PRIu16,
+ surfaceId);
return -1001;
+ }
- blocks = pSrcData;
- blocksLen = SrcSize;
- region = &(progressive->region);
- progressive->format = DstFormat;
-
- while ((blocksLen - offset) >= 6)
- {
- PROGRESSIVE_BLOCK_SYNC sync;
- PROGRESSIVE_BLOCK_CONTEXT context;
- PROGRESSIVE_BLOCK_FRAME_BEGIN frameBegin;
- PROGRESSIVE_BLOCK_FRAME_END frameEnd;
- RFX_COMPONENT_CODEC_QUANT* quantVal;
- RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal;
- boffset = 0;
- block = &blocks[offset];
- blockType = *((UINT16*)&block[boffset + 0]); /* blockType (2 bytes) */
- blockLen = *((UINT32*)&block[boffset + 2]); /* blockLen (4 bytes) */
- boffset += 6;
-
- if ((blocksLen - offset) < blockLen)
- return -1003;
+ region = calloc(1, sizeof(PROGRESSIVE_BLOCK_REGION));
+ if (!region)
+ return -1111;
- switch (blockType)
- {
- case PROGRESSIVE_WBT_SYNC:
- WLog_Print(progressive->log, WLOG_DEBUG, "ProgressiveSync");
- sync.blockType = blockType;
- sync.blockLen = blockLen;
+ Stream_StaticInit(&ss, pSrcData, SrcSize);
+ s = &ss;
+
+ switch (DstFormat)
+ {
+ case PIXEL_FORMAT_RGBA32:
+ case PIXEL_FORMAT_RGBX32:
+ case PIXEL_FORMAT_BGRA32:
+ case PIXEL_FORMAT_BGRX32:
+ progressive->format = DstFormat;
+ break;
+ default:
+ progressive->format = PIXEL_FORMAT_XRGB32;
+ break;
+ }
- if ((blockLen - boffset) != 6)
- return -1004;
+ start = Stream_GetPosition(s);
+ progressive->state = 0; /* Set state to not initialized */
+ while (Stream_GetRemainingLength(s) >= 6)
+ {
+ size_t rem, st, e;
- sync.magic = (UINT32) * ((UINT32*)&block[boffset + 0]); /* magic (4 bytes) */
- sync.version = (UINT32) * ((UINT16*)&block[boffset + 4]); /* version (2 bytes) */
- boffset += 6;
+ st = Stream_GetPosition(s);
+ rem = Stream_GetRemainingLength(s);
- if (sync.magic != 0xCACCACCA)
- return -1005;
+ Stream_Read_UINT16(s, blockType);
+ Stream_Read_UINT32(s, blockLen);
- if (sync.version != 0x0100)
- return -1006;
+ if (rem < blockLen)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR, "Short block %" PRIuz ", expected %" PRIu32,
+ rem, blockLen);
+ rc = -1003;
+ goto fail;
+ }
+ rem = Stream_GetRemainingLength(s);
+ switch (blockType)
+ {
+ case PROGRESSIVE_WBT_SYNC:
+ rc = progressive_wb_sync(progressive, s, blockType, blockLen);
break;
case PROGRESSIVE_WBT_FRAME_BEGIN:
- frameBegin.blockType = blockType;
- frameBegin.blockLen = blockLen;
-
- if ((blockLen - boffset) < 6)
- return -1007;
-
- frameBegin.frameIndex =
- (UINT32) * ((UINT32*)&block[boffset + 0]); /* frameIndex (4 bytes) */
- frameBegin.regionCount =
- (UINT32) * ((UINT16*)&block[boffset + 4]); /* regionCount (2 bytes) */
- boffset += 6;
- WLog_Print(progressive->log, WLOG_DEBUG,
- "ProgressiveFrameBegin: frameIndex: %" PRIu32 " regionCount: %" PRIu16
- "",
- frameBegin.frameIndex, frameBegin.regionCount);
- /**
- * If the number of elements specified by the regionCount field is
- * larger than the actual number of elements in the regions field,
- * the decoder SHOULD ignore this inconsistency.
- */
+ rc = progressive_wb_frame_begin(progressive, s, blockType, blockLen);
break;
case PROGRESSIVE_WBT_FRAME_END:
- WLog_Print(progressive->log, WLOG_DEBUG, "ProgressiveFrameEnd");
- frameEnd.blockType = blockType;
- frameEnd.blockLen = blockLen;
-
- if ((blockLen - boffset) != 0)
- return -1008;
-
+ rc = progressive_wb_frame_end(progressive, s, blockType, blockLen);
break;
case PROGRESSIVE_WBT_CONTEXT:
- context.blockType = blockType;
- context.blockLen = blockLen;
-
- if ((blockLen - boffset) != 4)
- return -1009;
-
- context.ctxId = block[boffset + 0]; /* ctxId (1 byte) */
- context.tileSize = *((UINT16*)&block[boffset + 1]); /* tileSize (2 bytes) */
- context.flags = block[boffset + 3]; /* flags (1 byte) */
- boffset += 4;
-
- if (context.tileSize != 64)
- return -1010;
-
- WLog_Print(progressive->log, WLOG_DEBUG,
- "ProgressiveContext: flags: 0x%02" PRIX8 "", context.flags);
-
- if (!(context.flags & RFX_SUBBAND_DIFFING))
- WLog_Print(progressive->log, WLOG_WARN, "RFX_SUBBAND_DIFFING is not set");
-
+ rc = progressive_wb_context(progressive, s, blockType, blockLen);
break;
case PROGRESSIVE_WBT_REGION:
- region->blockType = blockType;
- region->blockLen = blockLen;
-
- if ((blockLen - boffset) < 12)
- return -1011;
-
- region->tileSize = block[boffset + 0]; /* tileSize (1 byte) */
- region->numRects = *((UINT16*)&block[boffset + 1]); /* numRects (2 bytes) */
- region->numQuant = block[boffset + 3]; /* numQuant (1 byte) */
- region->numProgQuant = block[boffset + 4]; /* numProgQuant (1 byte) */
- region->flags = block[boffset + 5]; /* flags (1 byte) */
- region->numTiles = *((UINT16*)&block[boffset + 6]); /* numTiles (2 bytes) */
- region->tileDataSize = *((UINT32*)&block[boffset + 8]); /* tileDataSize (4 bytes) */
- boffset += 12;
-
- if (region->tileSize != 64)
- return -1012;
-
- if (region->numRects < 1)
- return -1013;
-
- if (region->numQuant > 7)
- return -1014;
-
- if ((blockLen - boffset) < (region->numRects * 8))
- return -1015;
-
- if (region->numRects > progressive->cRects)
- {
- RFX_RECT* tmpBuf =
- (RFX_RECT*)realloc(progressive->rects, region->numRects * sizeof(RFX_RECT));
- if (!tmpBuf)
- return -1016;
-
- progressive->rects = tmpBuf;
- progressive->cRects = region->numRects;
- }
-
- region->rects = progressive->rects;
-
- if (!region->rects)
- return -1017;
-
- for (index = 0; index < region->numRects; index++)
- {
- rect = &(region->rects[index]);
- rect->x = *((UINT16*)&block[boffset + 0]);
- rect->y = *((UINT16*)&block[boffset + 2]);
- rect->width = *((UINT16*)&block[boffset + 4]);
- rect->height = *((UINT16*)&block[boffset + 6]);
- boffset += 8;
- }
-
- if ((blockLen - boffset) < (region->numQuant * 5))
- return -1018;
-
- if (region->numQuant > progressive->cQuant)
- {
- RFX_COMPONENT_CODEC_QUANT* tmpBuf = (RFX_COMPONENT_CODEC_QUANT*)realloc(
- progressive->quantVals,
- region->numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT));
- if (!tmpBuf)
- return -1019;
-
- progressive->quantVals = tmpBuf;
- progressive->cQuant = region->numQuant;
- }
-
- region->quantVals = progressive->quantVals;
-
- if (!region->quantVals)
- return -1020;
-
- for (index = 0; index < region->numQuant; index++)
- {
- quantVal = &(region->quantVals[index]);
- progressive_component_codec_quant_read(&block[boffset], quantVal);
- boffset += 5;
-
- if (!progressive_rfx_quant_lcmp_greater_equal(quantVal, 6))
- return -1;
-
- if (!progressive_rfx_quant_lcmp_less_equal(quantVal, 15))
- return -1;
- }
-
- if ((blockLen - boffset) < (region->numProgQuant * 16))
- return -1021;
-
- if (region->numProgQuant > progressive->cProgQuant)
- {
- RFX_PROGRESSIVE_CODEC_QUANT* tmpBuf = (RFX_PROGRESSIVE_CODEC_QUANT*)realloc(
- progressive->quantProgVals,
- region->numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT));
- if (!tmpBuf)
- return -1022;
-
- progressive->quantProgVals = tmpBuf;
- progressive->cProgQuant = region->numProgQuant;
- }
-
- region->quantProgVals = progressive->quantProgVals;
-
- if (!region->quantProgVals)
- return -1023;
-
- for (index = 0; index < region->numProgQuant; index++)
- {
- quantProgVal = &(region->quantProgVals[index]);
- quantProgVal->quality = block[boffset + 0];
- progressive_component_codec_quant_read(&block[boffset + 1],
- &(quantProgVal->yQuantValues));
- progressive_component_codec_quant_read(&block[boffset + 6],
- &(quantProgVal->cbQuantValues));
- progressive_component_codec_quant_read(&block[boffset + 11],
- &(quantProgVal->crQuantValues));
- boffset += 16;
- }
-
- if ((blockLen - boffset) < region->tileDataSize)
- return -1024;
-
- if (progressive->cTiles < surface->gridSize)
- {
- RFX_PROGRESSIVE_TILE** tmpBuf = (RFX_PROGRESSIVE_TILE**)realloc(
- progressive->tiles, surface->gridSize * sizeof(RFX_PROGRESSIVE_TILE*));
- if (!tmpBuf)
- return -1025;
-
- progressive->tiles = tmpBuf;
- progressive->cTiles = surface->gridSize;
- }
-
- region->tiles = progressive->tiles;
-
- if (!region->tiles)
- return -1;
-
- WLog_Print(progressive->log, WLOG_DEBUG,
- "ProgressiveRegion: numRects: %" PRIu16 " numTiles: %" PRIu16
- " tileDataSize: %" PRIu32 " flags: 0x%02" PRIX8 " numQuant: %" PRIu8
- " numProgQuant: %" PRIu8 "",
- region->numRects, region->numTiles, region->tileDataSize, region->flags,
- region->numQuant, region->numProgQuant);
-
- if (!(region->flags & RFX_DWT_REDUCE_EXTRAPOLATE))
- WLog_Print(progressive->log, WLOG_WARN,
- "RFX_DWT_REDUCE_EXTRAPOLATE is not set");
-
- boxLeft = surface->gridWidth;
- boxTop = surface->gridHeight;
- boxRight = 0;
- boxBottom = 0;
-
- for (index = 0; index < region->numRects; index++)
- {
- rect = &(region->rects[index]);
- idxLeft = rect->x / 64;
- idxTop = rect->y / 64;
- idxRight = (rect->x + rect->width + 63) / 64;
- idxBottom = (rect->y + rect->height + 63) / 64;
-
- if (idxLeft < boxLeft)
- boxLeft = idxLeft;
-
- if (idxTop < boxTop)
- boxTop = idxTop;
-
- if (idxRight > boxRight)
- boxRight = idxRight;
-
- if (idxBottom > boxBottom)
- boxBottom = idxBottom;
-
- WLog_Print(progressive->log, WLOG_DEBUG,
- "rect[%" PRIu16 "]: x: %" PRIu16 " y: %" PRIu16 " w: %" PRIu16
- " h: %" PRIu16 "",
- index, rect->x, rect->y, rect->width, rect->height);
- }
-
- status = progressive_process_tiles(progressive, &block[boffset],
- region->tileDataSize, surface);
-
- if (status < 0)
- return status;
-
- region->numTiles = 0;
-
- for (index = 0; index < surface->gridSize; index++)
- {
- RFX_PROGRESSIVE_TILE* tile = &(surface->tiles[index]);
-
- if (!tile->data)
- continue;
-
- if ((tile->xIdx < boxLeft) || (tile->xIdx > boxRight))
- continue;
-
- if ((tile->yIdx < boxTop) || (tile->yIdx > boxBottom))
- continue;
-
- region->tiles[region->numTiles++] = tile;
- }
-
- boffset += (UINT32)status;
+ rc = progressive_wb_region(progressive, s, blockType, blockLen, surface, region);
break;
default:
- return -1039;
- break;
+ WLog_Print(progressive->log, WLOG_ERROR, "Invalid block type %04" PRIx16,
+ blockType);
+ rc = -1039;
}
- if (boffset != blockLen)
- return -1040;
+ if (rc < 0)
+ goto fail;
- offset += blockLen;
+ e = Stream_GetPosition(s);
+ if ((e - st) != blockLen)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "block len %" PRIuz " does not match read data %" PRIu32, e - st, blockLen);
+ rc = -1040;
+ goto fail;
+ }
count++;
}
- if (offset != blocksLen)
- return -1041;
+ end = Stream_GetPosition(s);
+ if ((end - start) != SrcSize)
+ {
+ WLog_Print(progressive->log, WLOG_ERROR,
+ "total block len %" PRIuz " does not match read data %" PRIu32, end - start,
+ SrcSize);
+ rc = -1041;
+ goto fail;
+ }
- region = &(progressive->region);
region16_init(&clippingRects);
for (i = 0; i < region->numRects; i++)
const RECTANGLE_16* updateRects;
RECTANGLE_16 updateRect;
RFX_PROGRESSIVE_TILE* tile = region->tiles[i];
+
updateRect.left = nXDst + tile->x;
updateRect.top = nYDst + tile->y;
updateRect.right = updateRect.left + 64;
const UINT32 height = rect->bottom - rect->top;
if (!freerdp_image_copy(pDstData, DstFormat, nDstStep, rect->left, rect->top, width,
- height, tile->data, tile->format, tile->stride, nXSrc, nYSrc,
- NULL, FREERDP_FLIP_NONE))
+ height, tile->data, progressive->format, tile->stride, nXSrc,
+ nYSrc, NULL, FREERDP_FLIP_NONE))
{
rc = -42;
break;
}
region16_uninit(&clippingRects);
+
+fail:
+ free(region);
return rc;
}
{
progressive->Compressor = Compressor;
progressive->bufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
- progressive->cRects = 64;
- progressive->rects = (RFX_RECT*)calloc(progressive->cRects, sizeof(RFX_RECT));
-
- if (!progressive->rects)
- goto cleanup;
-
- progressive->cTiles = 64;
- progressive->tiles =
- (RFX_PROGRESSIVE_TILE**)calloc(progressive->cTiles, sizeof(RFX_PROGRESSIVE_TILE*));
-
- if (!progressive->tiles)
- goto cleanup;
-
- progressive->cQuant = 8;
- progressive->quantVals = (RFX_COMPONENT_CODEC_QUANT*)calloc(
- progressive->cQuant, sizeof(RFX_COMPONENT_CODEC_QUANT));
-
- if (!progressive->quantVals)
- goto cleanup;
-
- progressive->cProgQuant = 8;
- progressive->quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*)calloc(
- progressive->cProgQuant, sizeof(RFX_PROGRESSIVE_CODEC_QUANT));
-
- if (!progressive->quantProgVals)
- goto cleanup;
ZeroMemory(&(progressive->quantProgValFull), sizeof(RFX_PROGRESSIVE_CODEC_QUANT));
progressive->quantProgValFull.quality = 100;
}
return progressive;
-cleanup:
- progressive_context_free(progressive);
- return NULL;
}
void progressive_context_free(PROGRESSIVE_CONTEXT* progressive)
return;
BufferPool_Free(progressive->bufferPool);
- free(progressive->rects);
- free(progressive->tiles);
- free(progressive->quantVals);
- free(progressive->quantProgVals);
if (progressive->SurfaceContexts)
{