#include <winpr/stream.h>
#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct _NSC_MESSAGE
-{
- UINT32 x;
- UINT32 y;
- UINT32 width;
- UINT32 height;
- const BYTE* data;
- UINT32 scanline;
- BYTE* PlaneBuffer;
- UINT32 MaxPlaneSize;
- BYTE* PlaneBuffers[5];
- UINT32 OrgByteCount[4];
-
- UINT32 LumaPlaneByteCount;
- UINT32 OrangeChromaPlaneByteCount;
- UINT32 GreenChromaPlaneByteCount;
- UINT32 AlphaPlaneByteCount;
- UINT32 ColorLossLevel;
- UINT32 ChromaSubsamplingLevel;
-};
-typedef struct _NSC_MESSAGE NSC_MESSAGE;
-
-typedef struct _NSC_CONTEXT_PRIV NSC_CONTEXT_PRIV;
-
-typedef struct _NSC_CONTEXT NSC_CONTEXT;
-
-struct _NSC_CONTEXT
+extern "C"
{
- UINT32 OrgByteCount[4];
- UINT32 format;
- UINT16 width;
- UINT16 height;
- BYTE* BitmapData;
- UINT32 BitmapDataLength;
-
- BYTE* Planes;
- UINT32 PlaneByteCount[4];
- UINT32 ColorLossLevel;
- UINT32 ChromaSubsamplingLevel;
- BOOL DynamicColorFidelity;
-
- /* color palette allocated by the application */
- const BYTE* palette;
-
- BOOL (*decode)(NSC_CONTEXT* context);
- BOOL (*encode)(NSC_CONTEXT* context, const BYTE* BitmapData,
- UINT32 rowstride);
-
- NSC_CONTEXT_PRIV* priv;
-};
-
-FREERDP_API BOOL nsc_context_set_pixel_format(NSC_CONTEXT* context,
- UINT32 pixel_format);
-FREERDP_API BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp,
- UINT32 width, UINT32 height,
- const BYTE* data, UINT32 length,
- BYTE* pDstData, UINT32 DstFormat,
- UINT32 nDstStride, UINT32 nXDst, UINT32 nYDst,
- UINT32 nWidth, UINT32 nHeight, UINT32 flip);
-FREERDP_API BOOL nsc_compose_message(NSC_CONTEXT* context, wStream* s,
- const BYTE* bmpdata,
- UINT32 width, UINT32 height, UINT32 rowstride);
-
-FREERDP_API NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context,
- const BYTE* data,
- UINT32 x, UINT32 y,
- UINT32 width, UINT32 height, UINT32 scanline,
- UINT32* numMessages, UINT32 maxDataSize);
-FREERDP_API BOOL nsc_write_message(NSC_CONTEXT* context, wStream* s,
- NSC_MESSAGE* message);
-FREERDP_API void nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message);
-
-FREERDP_API BOOL nsc_context_reset(NSC_CONTEXT* context, UINT32 width,
- UINT32 height);
+#endif
-FREERDP_API NSC_CONTEXT* nsc_context_new(void);
-FREERDP_API void nsc_context_free(NSC_CONTEXT* context);
+ typedef enum
+ {
+ NSC_COLOR_LOSS_LEVEL,
+ NSC_ALLOW_SUBSAMPLING,
+ NSC_DYNAMIC_COLOR_FIDELITY,
+ NSC_COLOR_FORMAT
+ } NSC_PARAMETER;
+
+ typedef struct _NSC_CONTEXT NSC_CONTEXT;
+
+ FREERDP_API WINPR_DEPRECATED(BOOL nsc_context_set_pixel_format(NSC_CONTEXT* context,
+ UINT32 pixel_format));
+ FREERDP_API BOOL nsc_context_set_parameters(NSC_CONTEXT* context, NSC_PARAMETER what,
+ UINT32 value);
+
+ FREERDP_API BOOL nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, UINT32 width,
+ UINT32 height, const BYTE* data, UINT32 length,
+ BYTE* pDstData, UINT32 DstFormat, UINT32 nDstStride,
+ UINT32 nXDst, UINT32 nYDst, UINT32 nWidth, UINT32 nHeight,
+ UINT32 flip);
+ FREERDP_API BOOL nsc_compose_message(NSC_CONTEXT* context, wStream* s, const BYTE* bmpdata,
+ UINT32 width, UINT32 height, UINT32 rowstride);
+ FREERDP_API BOOL nsc_decompose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata,
+ UINT32 x, UINT32 y, UINT32 width, UINT32 height,
+ UINT32 rowstride, UINT32 format, UINT32 flip);
+
+ FREERDP_API BOOL nsc_context_reset(NSC_CONTEXT* context, UINT32 width, UINT32 height);
+
+ FREERDP_API NSC_CONTEXT* nsc_context_new(void);
+ FREERDP_API void nsc_context_free(NSC_CONTEXT* context);
#ifdef __cplusplus
}
#include "nsc_types.h"
#include "nsc_encode.h"
+struct _NSC_MESSAGE
+{
+ UINT32 x;
+ UINT32 y;
+ UINT32 width;
+ UINT32 height;
+ const BYTE* data;
+ UINT32 scanline;
+ BYTE* PlaneBuffer;
+ UINT32 MaxPlaneSize;
+ BYTE* PlaneBuffers[5];
+ UINT32 OrgByteCount[4];
+
+ UINT32 LumaPlaneByteCount;
+ UINT32 OrangeChromaPlaneByteCount;
+ UINT32 GreenChromaPlaneByteCount;
+ UINT32 AlphaPlaneByteCount;
+ UINT8 ColorLossLevel;
+ UINT8 ChromaSubsamplingLevel;
+};
+typedef struct _NSC_MESSAGE NSC_MESSAGE;
+
+static BOOL nsc_write_message(NSC_CONTEXT* context, wStream* s,
+ const NSC_MESSAGE* message);
+
static BOOL nsc_context_initialize_encode(NSC_CONTEXT* context)
{
int i;
rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
ccl = context->ColorLossLevel;
- if (context->priv->PlaneBuffersLength < rw * scanline)
+ /* Internal buffer must conatin height * width pixels (aligned) */
+ if (context->priv->PlaneBuffersLength < context->height * rw)
return FALSE;
- if (rw < scanline * 2)
+ /* Input stride must contain enough data for width */
+ if (rw * GetBytesPerPixel(context->format) < scanline)
return FALSE;
for (y = 0; y < context->height; y++)
return maxPlaneSize;
}
-NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, const BYTE* data,
- UINT32 x, UINT32 y, UINT32 width, UINT32 height,
- UINT32 scanline, UINT32* numMessages,
- UINT32 maxDataSize)
-{
- UINT32 i, j, k;
- UINT32 dataOffset;
- UINT32 rows, cols;
- UINT32 BytesPerPixel;
- UINT32 MaxRegionWidth;
- UINT32 MaxRegionHeight;
- UINT32 ByteCount[4];
- UINT32 MaxPlaneSize;
- UINT32 MaxMessageSize;
- NSC_MESSAGE* messages;
- UINT32 PaddedMaxPlaneSize;
-
- if (!context || !data || !numMessages)
- return NULL;
-
- if (maxDataSize < 1024)
- return NULL;
-
- k = 0;
- MaxRegionWidth = 64 * 4;
- MaxRegionHeight = 64 * 2;
- BytesPerPixel = GetBytesPerPixel(context->format);
- rows = (width + (MaxRegionWidth - (width % MaxRegionWidth))) / MaxRegionWidth;
- cols = (height + (MaxRegionHeight - (height % MaxRegionHeight))) /
- MaxRegionHeight;
- *numMessages = rows * cols;
- MaxPlaneSize = nsc_compute_byte_count(context, (UINT32*) ByteCount, width,
- height);
- MaxMessageSize = ByteCount[0] + ByteCount[1] + ByteCount[2] + ByteCount[3] + 20;
- maxDataSize -= 1024; /* reserve enough space for headers */
- if (maxDataSize < (*numMessages) * sizeof(NSC_MESSAGE))
- return NULL;
-
- messages = (NSC_MESSAGE*) calloc(*numMessages, sizeof(NSC_MESSAGE));
-
- if (!messages)
- return NULL;
-
- for (i = 0; i < rows; i++)
- {
- for (j = 0; j < cols; j++)
- {
- messages[k].x = x + (i * MaxRegionWidth);
- messages[k].y = y + (j * MaxRegionHeight);
- messages[k].width = (i < (rows - 1)) ? MaxRegionWidth : width -
- (i * MaxRegionWidth);
- messages[k].height = (j < (cols - 1)) ? MaxRegionHeight : height -
- (j * MaxRegionHeight);
- messages[k].data = data;
- messages[k].scanline = scanline;
- messages[k].MaxPlaneSize = nsc_compute_byte_count(context,
- (UINT32*) messages[k].OrgByteCount, messages[k].width, messages[k].height);
- k++;
- }
- }
-
- *numMessages = k;
-
- for (i = 0; i < *numMessages; i++)
- {
- PaddedMaxPlaneSize = messages[i].MaxPlaneSize + 32;
- messages[i].PlaneBuffer = (BYTE*) BufferPool_Take(context->priv->PlanePool,
- PaddedMaxPlaneSize * 5);
-
- if (!messages[i].PlaneBuffer)
- goto fail;
-
- messages[i].PlaneBuffers[0] = (BYTE*) &
- (messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 0) + 16]);
- messages[i].PlaneBuffers[1] = (BYTE*) &
- (messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 1) + 16]);
- messages[i].PlaneBuffers[2] = (BYTE*) &
- (messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 2) + 16]);
- messages[i].PlaneBuffers[3] = (BYTE*) &
- (messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 3) + 16]);
- messages[i].PlaneBuffers[4] = (BYTE*) &
- (messages[i].PlaneBuffer[(PaddedMaxPlaneSize * 4) + 16]);
- }
-
- for (i = 0; i < *numMessages; i++)
- {
- context->width = messages[i].width;
- context->height = messages[i].height;
- context->OrgByteCount[0] = messages[i].OrgByteCount[0];
- context->OrgByteCount[1] = messages[i].OrgByteCount[1];
- context->OrgByteCount[2] = messages[i].OrgByteCount[2];
- context->OrgByteCount[3] = messages[i].OrgByteCount[3];
- context->priv->PlaneBuffersLength = messages[i].MaxPlaneSize;
- context->priv->PlaneBuffers[0] = messages[i].PlaneBuffers[0];
- context->priv->PlaneBuffers[1] = messages[i].PlaneBuffers[1];
- context->priv->PlaneBuffers[2] = messages[i].PlaneBuffers[2];
- context->priv->PlaneBuffers[3] = messages[i].PlaneBuffers[3];
- context->priv->PlaneBuffers[4] = messages[i].PlaneBuffers[4];
- dataOffset = (messages[i].y * messages[i].scanline) + (messages[i].x *
- BytesPerPixel);
- PROFILER_ENTER(context->priv->prof_nsc_encode)
- context->encode(context, &data[dataOffset], scanline);
- PROFILER_EXIT(context->priv->prof_nsc_encode)
- PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data)
- nsc_rle_compress_data(context);
- PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data)
- messages[i].LumaPlaneByteCount = context->PlaneByteCount[0];
- messages[i].OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
- messages[i].GreenChromaPlaneByteCount = context->PlaneByteCount[2];
- messages[i].AlphaPlaneByteCount = context->PlaneByteCount[3];
- messages[i].ColorLossLevel = context->ColorLossLevel;
- messages[i].ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
- }
-
- context->priv->PlaneBuffers[0] = NULL;
- context->priv->PlaneBuffers[1] = NULL;
- context->priv->PlaneBuffers[2] = NULL;
- context->priv->PlaneBuffers[3] = NULL;
- context->priv->PlaneBuffers[4] = NULL;
- return messages;
-fail:
-
- for (i = 0; i < *numMessages; i++)
- BufferPool_Return(context->priv->PlanePool, messages[i].PlaneBuffer);
-
- free(messages);
- return NULL;
-}
-
-BOOL nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
+BOOL nsc_write_message(NSC_CONTEXT* context, wStream* s, const NSC_MESSAGE* message)
{
UINT32 totalPlaneByteCount;
totalPlaneByteCount = message->LumaPlaneByteCount +
message->GreenChromaPlaneByteCount + message->AlphaPlaneByteCount;
if (!Stream_EnsureRemainingCapacity(s, 20 + totalPlaneByteCount))
- return -1;
+ return FALSE;
Stream_Write_UINT32(s,
message->LumaPlaneByteCount); /* LumaPlaneByteCount (4 bytes) */
return TRUE;
}
-void nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
-{
- BufferPool_Return(context->priv->PlanePool, message->PlaneBuffer);
-}
-
BOOL nsc_compose_message(NSC_CONTEXT* context, wStream* s, const BYTE* data,
UINT32 width, UINT32 height, UINT32 scanline)
{
- NSC_MESSAGE s_message = { 0 };
- NSC_MESSAGE* message = &s_message;
+ BOOL rc;
+ NSC_MESSAGE message = { 0 };
+
+ if (!context || !s || !data)
+ return FALSE;
+
context->width = width;
context->height = height;
/* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */
PROFILER_ENTER(context->priv->prof_nsc_encode)
- context->encode(context, data, scanline);
+ rc = context->encode(context, data, scanline);
PROFILER_EXIT(context->priv->prof_nsc_encode)
+ if (!rc)
+ return FALSE;
+
/* RLE encode */
PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data)
nsc_rle_compress_data(context);
PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data)
- message->PlaneBuffers[0] = context->priv->PlaneBuffers[0];
- message->PlaneBuffers[1] = context->priv->PlaneBuffers[1];
- message->PlaneBuffers[2] = context->priv->PlaneBuffers[2];
- message->PlaneBuffers[3] = context->priv->PlaneBuffers[3];
- message->LumaPlaneByteCount = context->PlaneByteCount[0];
- message->OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
- message->GreenChromaPlaneByteCount = context->PlaneByteCount[2];
- message->AlphaPlaneByteCount = context->PlaneByteCount[3];
- message->ColorLossLevel = context->ColorLossLevel;
- message->ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
- return nsc_write_message(context, s, message);
+ message.PlaneBuffers[0] = context->priv->PlaneBuffers[0];
+ message.PlaneBuffers[1] = context->priv->PlaneBuffers[1];
+ message.PlaneBuffers[2] = context->priv->PlaneBuffers[2];
+ message.PlaneBuffers[3] = context->priv->PlaneBuffers[3];
+ message.LumaPlaneByteCount = context->PlaneByteCount[0];
+ message.OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
+ message.GreenChromaPlaneByteCount = context->PlaneByteCount[2];
+ message.AlphaPlaneByteCount = context->PlaneByteCount[3];
+ message.ColorLossLevel = context->ColorLossLevel;
+ message.ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
+ return nsc_write_message(context, s, &message);
+}
+
+BOOL nsc_decompose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata,
+ UINT32 x, UINT32 y, UINT32 width, UINT32 height,
+ UINT32 rowstride, UINT32 format, UINT32 flip)
+{
+ size_t size = Stream_GetRemainingLength(s);
+ if (size > UINT32_MAX)
+ return FALSE;
+
+ if (!nsc_process_message(context, (UINT16)GetBitsPerPixel(context->format),
+ width, height, Stream_Pointer(s),
+ (UINT32)size, bmpdata, format,
+ rowstride, x, y, width, height, flip))
+ return FALSE;
+ Stream_Seek(s, size);
+ return TRUE;
}