Fixed const correctness of RECTANGLE_16 variable
authorArmin Novak <armin.novak@thincast.com>
Mon, 18 Jan 2021 08:34:18 +0000 (09:34 +0100)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 25 Feb 2021 08:51:41 +0000 (09:51 +0100)
(cherry picked from commit 9549d090ab849c405cb486fad6c9dd3867b28c45)

libfreerdp/codec/progressive.c

index aae6bd1..6c5f7ee 100644 (file)
@@ -823,6 +823,7 @@ static INLINE int progressive_rfx_dwt_2d_decode(PROGRESSIVE_CONTEXT* progressive
        temp = (INT16*)BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */
        if (!temp)
                return -2;
+
        if (!extrapolate)
        {
                progressive->rfx_context->dwt_2d_decode(buffer, temp);
@@ -861,7 +862,6 @@ static INLINE int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progress
                return status;
 
        CopyMemory(sign, buffer, 4096 * 2);
-
        if (!subbandDiff)
        {
                rfx_differential_decode(buffer + 4032, 64);
@@ -1019,7 +1019,6 @@ static INLINE int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progres
        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;
 
@@ -2319,10 +2318,253 @@ fail:
        return rc;
 }
 
+static BOOL progressive_rfx_write_message_progressive_simple(RFX_CONTEXT* context, wStream* s,
+                                                             RFX_MESSAGE* msg)
+{
+       UINT32 blockLen;
+       UINT32 i;
+       UINT32* qv;
+       RFX_TILE* tile;
+       UINT32 tilesDataSize;
+
+       if (context->mode != RLGR1)
+       {
+               WLog_ERR(TAG, "%s: error, RLGR1 mode is required!", __FUNCTION__);
+               return FALSE;
+       }
+
+       /* RFX_PROGRESSIVE_SYNC */
+       blockLen = 12;
+       if (!Stream_EnsureRemainingCapacity(s, blockLen))
+       {
+               return FALSE;
+       }
+       Stream_Write_UINT16(s, 0xCCC0);     /* blockType (2 bytes) */
+       Stream_Write_UINT32(s, blockLen);   /* blockLen (4 bytes) */
+       Stream_Write_UINT32(s, 0xCACCACCA); /* magic (4 bytes) */
+       Stream_Write_UINT16(s, 0x0100);     /* version (2 bytes) */
+
+       /* RFX_PROGRESSIVE_CONTEXT */
+       blockLen = 10;
+       if (!Stream_EnsureRemainingCapacity(s, blockLen))
+       {
+               return FALSE;
+       }
+       Stream_Write_UINT16(s, 0xCCC3); /* blockType (2 bytes) */
+       Stream_Write_UINT32(s, 10);     /* blockLen (4 bytes) */
+       Stream_Write_UINT8(s, 0);       /* ctxId (1 byte) */
+       Stream_Write_UINT16(s, 64);     /* tileSize (2 bytes) */
+       Stream_Write_UINT8(s, 0);       /* flags (1 byte) */
+
+       /* RFX_PROGRESSIVE_FRAME_BEGIN */
+       blockLen = 12;
+       if (!Stream_EnsureRemainingCapacity(s, blockLen))
+       {
+               return FALSE;
+       }
+       Stream_Write_UINT16(s, 0xCCC1);        /* blockType (2 bytes) */
+       Stream_Write_UINT32(s, blockLen);      /* blockLen (4 bytes) */
+       Stream_Write_UINT32(s, msg->frameIdx); /* frameIndex (4 bytes) */
+       Stream_Write_UINT16(s, 1);             /* regionCount (2 bytes) */
+
+       /* RFX_PROGRESSIVE_REGION */
+       blockLen = 18;
+       blockLen += msg->numRects * 8;
+       blockLen += msg->numQuant * 5;
+       tilesDataSize = msg->numTiles * 22;
+       for (i = 0; i < msg->numTiles; i++)
+       {
+               tile = msg->tiles[i];
+               tilesDataSize += tile->YLen + tile->CbLen + tile->CrLen;
+       }
+       blockLen += tilesDataSize;
+
+       if (!Stream_EnsureRemainingCapacity(s, blockLen))
+       {
+               return FALSE;
+       }
+       Stream_Write_UINT16(s, 0xCCC4);        /* blockType (2 bytes) */
+       Stream_Write_UINT32(s, blockLen);      /* blockLen (4 bytes) */
+       Stream_Write_UINT8(s, 64);             /* tileSize (1 byte) */
+       Stream_Write_UINT16(s, msg->numRects); /* numRects (2 bytes) */
+       Stream_Write_UINT8(s, msg->numQuant);  /* numQuant (1 byte) */
+       Stream_Write_UINT8(s, 0);              /* numProgQuant (1 byte) */
+       Stream_Write_UINT8(s, 0);              /* flags (1 byte) */
+       Stream_Write_UINT16(s, msg->numTiles); /* numTiles (2 bytes) */
+       Stream_Write_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */
+
+       for (i = 0; i < msg->numRects; i++)
+       {
+               /* TS_RFX_RECT */
+               Stream_Write_UINT16(s, msg->rects[i].x);      /* x (2 bytes) */
+               Stream_Write_UINT16(s, msg->rects[i].y);      /* y (2 bytes) */
+               Stream_Write_UINT16(s, msg->rects[i].width);  /* width (2 bytes) */
+               Stream_Write_UINT16(s, msg->rects[i].height); /* height (2 bytes) */
+       }
+
+       /**
+        * Note: The RFX_COMPONENT_CODEC_QUANT structure differs from the
+        * TS_RFX_CODEC_QUANT ([MS-RDPRFX] section 2.2.2.1.5) structure with respect
+        * to the order of the bands.
+        *             0    1    2   3     4    5    6    7    8    9
+        * RDPRFX:   LL3, LH3, HL3, HH3, LH2, HL2, HH2, LH1, HL1, HH1
+        * RDPEGFX:  LL3, HL3, LH3, HH3, HL2, LH2, HH2, HL1, LH1, HH1
+        */
+       for (i = 0, qv = msg->quantVals; i < msg->numQuant; i++, qv += 10)
+       {
+               /* RFX_COMPONENT_CODEC_QUANT */
+               Stream_Write_UINT8(s, qv[0] + (qv[2] << 4)); /* LL3 (4-bit), HL3 (4-bit) */
+               Stream_Write_UINT8(s, qv[1] + (qv[3] << 4)); /* LH3 (4-bit), HH3 (4-bit) */
+               Stream_Write_UINT8(s, qv[5] + (qv[4] << 4)); /* HL2 (4-bit), LH2 (4-bit) */
+               Stream_Write_UINT8(s, qv[6] + (qv[8] << 4)); /* HH2 (4-bit), HL1 (4-bit) */
+               Stream_Write_UINT8(s, qv[7] + (qv[9] << 4)); /* LH1 (4-bit), HH1 (4-bit) */
+       }
+
+       for (i = 0; i < msg->numTiles; i++)
+       {
+               /* RFX_PROGRESSIVE_TILE_SIMPLE */
+               tile = msg->tiles[i];
+               blockLen = 22 + tile->YLen + tile->CbLen + tile->CrLen;
+               Stream_Write_UINT16(s, 0xCCC5);             /* blockType (2 bytes) */
+               Stream_Write_UINT32(s, blockLen);           /* blockLen (4 bytes) */
+               Stream_Write_UINT8(s, tile->quantIdxY);     /* quantIdxY (1 byte) */
+               Stream_Write_UINT8(s, tile->quantIdxCb);    /* quantIdxCb (1 byte) */
+               Stream_Write_UINT8(s, tile->quantIdxCr);    /* quantIdxCr (1 byte) */
+               Stream_Write_UINT16(s, tile->xIdx);         /* xIdx (2 bytes) */
+               Stream_Write_UINT16(s, tile->yIdx);         /* yIdx (2 bytes) */
+               Stream_Write_UINT8(s, 0);                   /* flags (1 byte) */
+               Stream_Write_UINT16(s, tile->YLen);         /* YLen (2 bytes) */
+               Stream_Write_UINT16(s, tile->CbLen);        /* CbLen (2 bytes) */
+               Stream_Write_UINT16(s, tile->CrLen);        /* CrLen (2 bytes) */
+               Stream_Write_UINT16(s, 0);                  /* tailLen (2 bytes) */
+               Stream_Write(s, tile->YData, tile->YLen);   /* YData */
+               Stream_Write(s, tile->CbData, tile->CbLen); /* CbData */
+               Stream_Write(s, tile->CrData, tile->CrLen); /* CrData */
+       }
+
+       /* RFX_PROGRESSIVE_FRAME_END */
+       blockLen = 6;
+       if (!Stream_EnsureRemainingCapacity(s, blockLen))
+       {
+               return FALSE;
+       }
+       Stream_Write_UINT16(s, 0xCCC2);   /* blockType (2 bytes) */
+       Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
+
+       return TRUE;
+}
+
 int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData, UINT32 SrcSize,
-                         BYTE** ppDstData, UINT32* pDstSize)
+                         UINT32 SrcFormat, UINT32 Width, UINT32 Height, UINT32 ScanLine,
+                         const REGION16* invalidRegion, BYTE** ppDstData, UINT32* pDstSize)
 {
-       return -1;
+       BOOL rc;
+       int res = -6;
+       wStream* s;
+       UINT32 i, numRects;
+       UINT32 x, y;
+       RFX_RECT* rects = NULL;
+       RFX_MESSAGE* message;
+
+       if (!progressive || !pSrcData || !ppDstData || !pDstSize)
+       {
+               return -1;
+       }
+
+       if (ScanLine == 0)
+       {
+               switch (SrcFormat)
+               {
+                       case PIXEL_FORMAT_ABGR32:
+                       case PIXEL_FORMAT_ARGB32:
+                       case PIXEL_FORMAT_XBGR32:
+                       case PIXEL_FORMAT_XRGB32:
+                       case PIXEL_FORMAT_BGRA32:
+                       case PIXEL_FORMAT_BGRX32:
+                       case PIXEL_FORMAT_RGBA32:
+                       case PIXEL_FORMAT_RGBX32:
+                               ScanLine = Width * 4;
+                               break;
+                       default:
+                               return -2;
+               }
+       }
+       if (ScanLine / Width != 4)
+               return -3;
+       if (SrcSize < Height * ScanLine)
+               return -4;
+
+       if (!invalidRegion)
+       {
+               numRects = (Width + 63) / 64;
+               numRects *= (Height + 63) / 64;
+       }
+       else
+               numRects = region16_n_rects(invalidRegion);
+
+       if (numRects == 0)
+               return 0;
+
+       if (!Stream_EnsureCapacity(progressive->rects, numRects * sizeof(RFX_RECT)))
+               return -5;
+       rects = (RFX_RECT*)Stream_Buffer(progressive->rects);
+       if (invalidRegion)
+       {
+               const RECTANGLE_16* r = region16_rects(invalidRegion, NULL);
+               for (x = 0; x < numRects; x++)
+               {
+                       rects[x].x = r[x].left;
+                       rects[x].y = r[x].top;
+                       rects[x].width = r[x].right - r[x].left;
+                       rects[x].height = r[x].bottom - r[x].top;
+               }
+       }
+       else
+       {
+               x = 0;
+               y = 0;
+               for (i = 0; i < numRects; i++)
+               {
+                       RFX_RECT* r = &rects[i];
+                       r->x = x;
+                       r->y = y;
+                       r->width = MIN(64, Width - x);
+                       r->height = MIN(64, Height - y);
+
+                       if (x + 64 >= Width)
+                       {
+                               y += 64;
+                               x = 0;
+                       }
+                       else
+                               x += 64;
+               }
+       }
+       s = progressive->buffer;
+       Stream_SetPosition(s, 0);
+
+       progressive->rfx_context->mode = RLGR1;
+
+       message = rfx_encode_message(progressive->rfx_context, rects, numRects, pSrcData, Width, Height,
+                                    ScanLine);
+       if (!message)
+       {
+               WLog_ERR(TAG, "failed to encode rfx message");
+               goto fail;
+       }
+
+       message->freeRects = TRUE;
+
+       rc = progressive_rfx_write_message_progressive_simple(progressive->rfx_context, s, message);
+       rfx_message_free(progressive->rfx_context, message);
+       if (!rc)
+               goto fail;
+
+       *pDstSize = Stream_GetPosition(s);
+       *ppDstData = Stream_Buffer(s);
+       res = 0;
+fail:
+       return res;
 }
 
 BOOL progressive_context_reset(PROGRESSIVE_CONTEXT* progressive)
@@ -2339,6 +2581,7 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor)
 
        if (!progressive)
                return NULL;
+
        progressive->Compressor = Compressor;
        progressive->quantProgValFull.quality = 100;
        progressive->log = WLog_Get(TAG);
@@ -2354,7 +2597,6 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor)
        if (!progressive->rects)
                goto fail;
        progressive->bufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16);
-
        if (!progressive->bufferPool)
                goto fail;
        progressive->SurfaceContexts = HashTable_New(TRUE);
@@ -2378,6 +2620,7 @@ void progressive_context_free(PROGRESSIVE_CONTEXT* progressive)
 
        if (!progressive)
                return;
+
        Stream_Free(progressive->buffer, TRUE);
        Stream_Free(progressive->rects, TRUE);
        rfx_context_free(progressive->rfx_context);