#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
}
}
-static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
+static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scanline)
{
UINT16 x;
UINT16 y;
for (y = 0; y < context->height; y++)
{
- src = bmpdata + (context->height - 1 - y) * rowstride;
+ src = data + (context->height - 1 - y) * scanline;
yplane = context->priv->PlaneBuffers[0] + y * rw;
coplane = context->priv->PlaneBuffers[1] + y * rw;
cgplane = context->priv->PlaneBuffers[2] + y * rw;
static void nsc_rle_compress_data(NSC_CONTEXT* context)
{
UINT16 i;
- BYTE* rle;
UINT32 planeSize;
UINT32 originalSize;
- rle = context->nsc_stream.Planes;
-
for (i = 0; i < 4; i++)
{
originalSize = context->OrgByteCount[i];
NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
int width, int height, int scanline, int* numMessages, int maxDataSize)
{
- int step;
- int i, j;
+ int i, j, k;
+ int dataOffset;
+ int rows, cols;
+ int BytesPerPixel;
+ int MaxRegionWidth;
+ int MaxRegionHeight;
UINT32 ByteCount[4];
UINT32 MaxPlaneSize;
UINT32 MaxMessageSize;
NSC_MESSAGE* messages;
- MaxPlaneSize = nsc_compute_byte_count(context, (UINT32*) ByteCount, width, height);
- MaxMessageSize = MaxPlaneSize + 20;
+ k = 0;
+ MaxRegionWidth = 64 * 4;
+ MaxRegionHeight = 64 * 2;
+ BytesPerPixel = (context->bpp / 8);
- maxDataSize -= 1024; /* reserve enough space for headers */
+ rows = (width + (MaxRegionWidth - (width % MaxRegionWidth))) / MaxRegionWidth;
+ cols = (height + (MaxRegionHeight - (height % MaxRegionHeight))) / MaxRegionHeight;
+ *numMessages = rows * cols;
- if (MaxMessageSize > maxDataSize)
- *numMessages = MaxMessageSize / maxDataSize;
+ MaxPlaneSize = nsc_compute_byte_count(context, (UINT32*) ByteCount, width, height);
+ MaxMessageSize = ByteCount[0] + ByteCount[1] + ByteCount[2] + ByteCount[3] + 20;
- if (*numMessages < 1)
- *numMessages = 1;
+ maxDataSize -= 1024; /* reserve enough space for headers */
messages = (NSC_MESSAGE*) malloc(sizeof(NSC_MESSAGE) * (*numMessages));
ZeroMemory(messages, sizeof(sizeof(NSC_MESSAGE) * (*numMessages)));
- if (width > height)
+ for (i = 0; i < rows; i++)
{
- /**
- * Horizontal Split
- */
-
- step = height / *numMessages;
- step += (step % 4);
-
- for (i = 0; i < *numMessages; i++)
+ for (j = 0; j < cols; j++)
{
- messages[i].x = x;
- messages[i].width = width;
- messages[i].data = data;
- messages[i].scanline = scanline;
+ 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[i].y = y + (i * step);
- messages[i].height = height - (i * step);
+ messages[k].MaxPlaneSize = nsc_compute_byte_count(context,
+ (UINT32*) messages[k].OrgByteCount, messages[k].width, messages[k].height);
- messages[i].MaxPlaneSize = nsc_compute_byte_count(context,
- (UINT32*) messages[i].OrgByteCount, messages[i].width, messages[i].height);
+ k++;
}
}
- else
+
+ *numMessages = k;
+
+ for (i = 0; i < *numMessages; i++)
{
- /**
- * Vertical Split
- */
+ messages[i].PlaneBuffers[0] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[1] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[2] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[3] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ messages[i].PlaneBuffers[4] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize);
+ }
- step = width / *numMessages;
- step += (step % 4);
+ 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].PlaneByteCount[0] = context->nsc_stream.PlaneByteCount[0];
+ messages[i].PlaneByteCount[1] = context->nsc_stream.PlaneByteCount[1];
+ messages[i].PlaneByteCount[2] = context->nsc_stream.PlaneByteCount[2];
+ messages[i].PlaneByteCount[3] = context->nsc_stream.PlaneByteCount[3];
+ }
- for (i = 0; i < *numMessages; i++)
- {
- messages[i].y = y;
- messages[i].height = height;
- messages[i].data = data;
- messages[i].scanline = scanline;
+ 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;
- messages[i].x = x + (i * step);
- messages[i].width = width - (i * step);
+ return messages;
+}
- messages[i].MaxPlaneSize = nsc_compute_byte_count(context,
- (UINT32*) messages[i].OrgByteCount, messages[i].width, messages[i].height);
- }
- }
+int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
+{
+ int i;
- for (i = 0; i < *numMessages; i++)
+ Stream_EnsureRemainingCapacity(s, 20);
+ Stream_Write_UINT32(s, message->PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT32(s, message->PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT32(s, message->PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT32(s, message->PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */
+ Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */
+ Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
+ Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
+
+ for (i = 0; i < 4; i++)
{
- for (j = 0; j < 4; j++)
+ if (message->PlaneByteCount[i] > 0)
{
- messages[i].PlaneBuffers[j] = NULL;
+ Stream_EnsureRemainingCapacity(s, (int) message->PlaneByteCount[i]);
+ Stream_Write(s, message->PlaneBuffers[i], message->PlaneByteCount[i]);
}
}
- return messages;
+ return 0;
+}
+
+int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
+{
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[0]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[1]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[2]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[3]);
+ BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[4]);
+ return 0;
}
void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width, int height, int scanline)
#include <malloc.h>
#endif
-struct _aligned_meminfo {
+struct _aligned_meminfo
+{
size_t size;
- void *base_addr;
+ void* base_addr;
};
-
void* _aligned_malloc(size_t size, size_t alignment)
{
return _aligned_offset_malloc(size, alignment, 0);
/* malloc size + alignment to make sure we can align afterwards */
tmpptr = malloc(size + alignment + sizeof(struct _aligned_meminfo));
+
if (!tmpptr)
return NULL;
-
memptr = (void *)((((size_t)((PBYTE)tmpptr + alignment + offset + sizeof(struct _aligned_meminfo)) & ~(alignment - 1)) - offset));
- ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memptr - sizeof(struct _aligned_meminfo))));
+ ameminfo = (struct _aligned_meminfo*) (((size_t)((PBYTE)memptr - sizeof(struct _aligned_meminfo))));
ameminfo->base_addr = tmpptr;
ameminfo->size = size;
void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, size_t offset)
{
- struct _aligned_meminfo *ameminfo;
- void *newmem;
+ void* newmem;
+ struct _aligned_meminfo* ameminfo;
if (!memblock)
return _aligned_offset_malloc(size, alignment, offset);
_aligned_free(memblock);
return NULL;
}
+
/* The following is not very performant but a simple and working solution */
newmem = _aligned_offset_malloc(size, alignment, offset);
if (!newmem)
return NULL;
- ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo))));
- memcpy(newmem, memblock, ameminfo->size);
+ ameminfo = (struct _aligned_meminfo*) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo))));
+ CopyMemory(newmem, memblock, ameminfo->size);
_aligned_free(memblock);
+
return newmem;
}
void _aligned_free(void* memblock)
{
- struct _aligned_meminfo *ameminfo;
+ struct _aligned_meminfo* ameminfo;
+
if (!memblock)
return;
- ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo))));
+ ameminfo = (struct _aligned_meminfo*) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo))));
free(ameminfo->base_addr);
}