From 1fa00c431845e109f3c0a5819d766bd1c8317769 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 10 Dec 2019 16:19:20 +0100 Subject: [PATCH] Refactored progressive codec. --- libfreerdp/codec/progressive.c | 1973 +++++++++++++++++++++++----------------- libfreerdp/codec/progressive.h | 35 +- 2 files changed, 1151 insertions(+), 857 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 9371030..02d45bf 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -3,6 +3,8 @@ * Progressive Codec Bitmap Compression * * Copyright 2014 Marc-Andre Moreau + * Copyright 2019 Armin Novak + * 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. @@ -46,7 +48,7 @@ struct _RFX_PROGRESSIVE_UPGRADE_STATE /* SRL state */ - int kp; + UINT32 kp; int nz; BOOL mode; }; @@ -83,23 +85,27 @@ static const char* progressive_get_block_type_string(UINT16 blockType) 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) @@ -116,8 +122,8 @@ static INLINE void progressive_rfx_quant_ladd(RFX_COMPONENT_CODEC_QUANT* q, int 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 */ @@ -146,8 +152,8 @@ static INLINE void progressive_rfx_quant_lsub(RFX_COMPONENT_CODEC_QUANT* q, int 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 */ @@ -162,7 +168,8 @@ static INLINE void progressive_rfx_quant_sub(RFX_COMPONENT_CODEC_QUANT* q1, 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 */ @@ -197,8 +204,8 @@ static INLINE BOOL progressive_rfx_quant_lcmp_less_equal(RFX_COMPONENT_CODEC_QUA 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 */ @@ -233,7 +240,8 @@ static INLINE BOOL progressive_rfx_quant_cmp_less_equal(RFX_COMPONENT_CODEC_QUAN 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 */ @@ -268,8 +276,8 @@ static INLINE BOOL progressive_rfx_quant_lcmp_greater_equal(RFX_COMPONENT_CODEC_ 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 */ @@ -304,8 +312,8 @@ static INLINE BOOL progressive_rfx_quant_cmp_greater_equal(RFX_COMPONENT_CODEC_Q 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 */ @@ -340,14 +348,6 @@ static INLINE BOOL progressive_rfx_quant_cmp_equal(RFX_COMPONENT_CODEC_QUANT* q1 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) { @@ -361,18 +361,80 @@ static INLINE BOOL progressive_set_surface_data(PROGRESSIVE_CONTEXT* progressive 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)); @@ -392,38 +454,103 @@ static PROGRESSIVE_SURFACE_CONTEXT* progressive_surface_context_new(UINT16 surfa 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) { @@ -444,8 +571,7 @@ INT32 progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT1 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) { @@ -457,42 +583,41 @@ int progressive_delete_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 } /* - * 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; @@ -547,21 +672,22 @@ static INLINE void progressive_rfx_idwt_x(INT16* pLowBand, int nLowStep, INT16* } } -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; @@ -625,12 +751,12 @@ static INLINE void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* } } -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; @@ -638,28 +764,18 @@ static INLINE int progressive_rfx_get_band_h_count(int level) 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]; @@ -674,46 +790,20 @@ static INLINE void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* tem 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(); @@ -721,13 +811,13 @@ static INLINE void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT 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; @@ -736,9 +826,10 @@ static INLINE void progressive_rfx_decode_block(const primitives_t* prims, INT16 } 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; @@ -749,7 +840,7 @@ static INLINE int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progress 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 */ @@ -759,25 +850,29 @@ static INLINE int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progress 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; @@ -790,6 +885,9 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres 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 @@ -797,20 +895,30 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres (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]); @@ -821,7 +929,11 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres else { if (tile->quality >= region->numProgQuant) + { + WLog_ERR(TAG, "quality %" PRIu8 " > numProgQuant %" PRIu8, tile->quality, + region->numProgQuant); return -1; + } quantProgVal = &(region->quantProgVals[tile->quality]); } @@ -830,12 +942,19 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres 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)); @@ -847,58 +966,44 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres 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; @@ -957,10 +1062,11 @@ static INLINE INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* stat /* 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; @@ -984,9 +1090,12 @@ static INLINE INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* stat 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 */ @@ -1062,24 +1171,20 @@ static INLINE int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* s 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; @@ -1090,29 +1195,51 @@ static INLINE int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progres 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; @@ -1138,31 +1265,33 @@ static INLINE int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progres 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; @@ -1172,6 +1301,10 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr 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 @@ -1181,20 +1314,30 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr 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]); @@ -1205,7 +1348,11 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr else { if (tile->quality >= region->numProgQuant) + { + WLog_ERR(TAG, "quality %" PRIu8 " > numProgQuant %" PRIu8, tile->quality, + region->numProgQuant); return -1; + } quantProg = &(region->quantProgVals[tile->quality]); } @@ -1223,6 +1370,13 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr 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); @@ -1236,25 +1390,23 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr 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 */ @@ -1263,309 +1415,604 @@ static INLINE int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progr 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; @@ -1575,345 +2022,220 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD 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++) @@ -1933,6 +2255,7 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD 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; @@ -1950,8 +2273,8 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD 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; @@ -1965,6 +2288,9 @@ INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcD } region16_uninit(&clippingRects); + +fail: + free(region); return rc; } @@ -1991,32 +2317,6 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) { 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; @@ -2026,9 +2326,6 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) } return progressive; -cleanup: - progressive_context_free(progressive); - return NULL; } void progressive_context_free(PROGRESSIVE_CONTEXT* progressive) @@ -2042,10 +2339,6 @@ 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) { diff --git a/libfreerdp/codec/progressive.h b/libfreerdp/codec/progressive.h index e54ed98..edd3e47 100644 --- a/libfreerdp/codec/progressive.h +++ b/libfreerdp/codec/progressive.h @@ -133,7 +133,6 @@ struct _RFX_PROGRESSIVE_TILE UINT32 y; UINT32 width; UINT32 height; - UINT32 format; UINT32 stride; BYTE* data; @@ -141,6 +140,7 @@ struct _RFX_PROGRESSIVE_TILE UINT16 pass; BYTE* sign; + RFX_COMPONENT_CODEC_QUANT yBitPos; RFX_COMPONENT_CODEC_QUANT cbBitPos; RFX_COMPONENT_CODEC_QUANT crBitPos; @@ -164,11 +164,12 @@ struct _PROGRESSIVE_BLOCK_REGION BYTE numProgQuant; BYTE flags; UINT16 numTiles; + UINT16 usedTiles; UINT32 tileDataSize; - RFX_RECT* rects; - RFX_COMPONENT_CODEC_QUANT* quantVals; - RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; - RFX_PROGRESSIVE_TILE** tiles; + RFX_RECT rects[0x10000]; + RFX_COMPONENT_CODEC_QUANT quantVals[0x100]; + RFX_PROGRESSIVE_CODEC_QUANT quantProgVals[0x100]; + RFX_PROGRESSIVE_TILE* tiles[0x10000]; }; typedef struct _PROGRESSIVE_BLOCK_REGION PROGRESSIVE_BLOCK_REGION; @@ -202,26 +203,26 @@ struct _PROGRESSIVE_SURFACE_CONTEXT }; typedef struct _PROGRESSIVE_SURFACE_CONTEXT PROGRESSIVE_SURFACE_CONTEXT; +enum _WBT_STATE_FLAG +{ + FLAG_WBT_SYNC = 0x01, + FLAG_WBT_FRAME_BEGIN = 0x02, + FLAG_WBT_FRAME_END = 0x04, + FLAG_WBT_CONTEXT = 0x08, + FLAG_WBT_REGION = 0x10 +}; +typedef enum _WBT_STATE_FLAG WBT_STATE_FLAG; + struct _PROGRESSIVE_CONTEXT { BOOL Compressor; wBufferPool* bufferPool; - UINT32 cRects; - RFX_RECT* rects; - UINT32 format; + UINT32 state; - UINT32 cTiles; - RFX_PROGRESSIVE_TILE** tiles; - - UINT32 cQuant; - RFX_COMPONENT_CODEC_QUANT* quantVals; - - UINT32 cProgQuant; - RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; - + PROGRESSIVE_BLOCK_CONTEXT context; PROGRESSIVE_BLOCK_REGION region; RFX_PROGRESSIVE_CODEC_QUANT quantProgValFull; -- 2.7.4