mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Merge pull request #2084 from awakecoding/egfx
Progressive, H.264, YUV420, YCbCr, Planar, Interleaved
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -92,6 +92,7 @@ RelWithDebInfo
|
||||
|
||||
# Binaries
|
||||
*.a
|
||||
*.o
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
@@ -105,6 +106,7 @@ client/DirectFB/dfreerdp
|
||||
server/Sample/sfreerdp-server
|
||||
server/X11/xfreerdp-server
|
||||
xcode
|
||||
libfreerdp/codec/test/TestOpenH264ASM
|
||||
|
||||
# Other
|
||||
*~
|
||||
|
||||
@@ -72,15 +72,19 @@ int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H264_METAB
|
||||
if (!meta->quantQualityVals)
|
||||
return -1;
|
||||
|
||||
#if 0
|
||||
printf("H264_METABLOCK: numRegionRects: %d\n", (int) meta->numRegionRects);
|
||||
#endif
|
||||
|
||||
for (index = 0; index < meta->numRegionRects; index++)
|
||||
{
|
||||
regionRect = &(meta->regionRects[index]);
|
||||
rdpgfx_read_rect16(s, regionRect);
|
||||
|
||||
#if 0
|
||||
printf("regionRects[%d]: left: %d top: %d right: %d bottom: %d\n",
|
||||
index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 2))
|
||||
@@ -96,8 +100,10 @@ int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H264_METAB
|
||||
quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1;
|
||||
quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1;
|
||||
|
||||
#if 0
|
||||
printf("quantQualityVals[%d]: qp: %d r: %d p: %d qualityVal: %d\n",
|
||||
index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, quantQualityVal->qualityVal);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -130,6 +130,8 @@ int rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */
|
||||
Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */
|
||||
Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */
|
||||
|
||||
/*TODO: interpret this answer*/
|
||||
|
||||
WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%04X flags: 0x%04X",
|
||||
capsSet.version, capsSet.flags);
|
||||
@@ -546,6 +548,8 @@ int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
context->SolidFill(context, &pdu);
|
||||
}
|
||||
|
||||
free(pdu.fillRects);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -591,6 +595,8 @@ int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
|
||||
context->SurfaceToSurface(context, &pdu);
|
||||
}
|
||||
|
||||
free(pdu.destPts);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -856,6 +862,9 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
}
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
|
||||
//free(Stream_Buffer(data));
|
||||
//Stream_Free(data,TRUE);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -1057,6 +1066,10 @@ int rdpgfx_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
return -1;
|
||||
|
||||
gfx->log = WLog_Get("com.freerdp.gfx.client");
|
||||
#if 0
|
||||
WLog_SetLogLevel(gfx->log, WLOG_DEBUG);
|
||||
#endif
|
||||
|
||||
gfx->settings = (rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints);
|
||||
|
||||
gfx->iface.Initialize = rdpgfx_plugin_initialize;
|
||||
|
||||
@@ -568,15 +568,13 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
|
||||
RFX_MESSAGE* message;
|
||||
BITMAPINFO bitmap_info;
|
||||
|
||||
RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) wfc->rfx_context;
|
||||
NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) wfc->nsc_context;
|
||||
|
||||
tile_bitmap = (char*) malloc(32);
|
||||
ZeroMemory(tile_bitmap, 32);
|
||||
|
||||
if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
|
||||
{
|
||||
message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_REMOTEFX);
|
||||
message = rfx_process_message(wfc->codecs->rfx, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
|
||||
/* blit each tile */
|
||||
for (i = 0; i < message->numTiles; i++)
|
||||
@@ -607,11 +605,12 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
|
||||
wf_invalidate_region(wfc, tx, ty, message->rects[i].width, message->rects[i].height);
|
||||
}
|
||||
|
||||
rfx_message_free(rfx_context, message);
|
||||
rfx_message_free(wfc->codecs->rfx, message);
|
||||
}
|
||||
else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC)
|
||||
{
|
||||
nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
|
||||
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_NSCODEC);
|
||||
nsc_process_message(wfc->codecs->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
|
||||
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
ZeroMemory(&bitmap_info, sizeof(bitmap_info));
|
||||
bitmap_info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
@@ -622,7 +621,7 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm
|
||||
bitmap_info.bmiHeader.biCompression = BI_RGB;
|
||||
SetDIBitsToDevice(wfc->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop,
|
||||
surface_bits_command->width, surface_bits_command->height, 0, 0, 0, surface_bits_command->height,
|
||||
nsc_context->BitmapData, &bitmap_info, DIB_RGB_COLORS);
|
||||
wfc->codecs->nsc->BitmapData, &bitmap_info, DIB_RGB_COLORS);
|
||||
wf_invalidate_region(wfc, surface_bits_command->destLeft, surface_bits_command->destTop,
|
||||
surface_bits_command->width, surface_bits_command->height);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codecs.h>
|
||||
|
||||
#include "wf_gdi.h"
|
||||
#include "wf_graphics.h"
|
||||
@@ -142,8 +142,9 @@ void wf_Bitmap_Paint(wfContext* wfc, rdpBitmap* bitmap)
|
||||
}
|
||||
|
||||
void wf_Bitmap_Decompress(wfContext* wfc, rdpBitmap* bitmap,
|
||||
BYTE* data, int width, int height, int bpp, int length, BOOL compressed, int codec_id)
|
||||
BYTE* data, int width, int height, int bpp, int length, BOOL compressed, int codecId)
|
||||
{
|
||||
int status;
|
||||
UINT16 size;
|
||||
|
||||
size = width * height * (bpp / 8);
|
||||
@@ -155,13 +156,35 @@ void wf_Bitmap_Decompress(wfContext* wfc, rdpBitmap* bitmap,
|
||||
|
||||
if (compressed)
|
||||
{
|
||||
BOOL status;
|
||||
BYTE* pDstData;
|
||||
UINT32 SrcSize;
|
||||
|
||||
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
||||
SrcSize = (UINT32) length;
|
||||
pDstData = bitmap->data;
|
||||
|
||||
if (status != TRUE)
|
||||
if (bpp < 32)
|
||||
{
|
||||
DEBUG_WARN( "Bitmap Decompression Failed\n");
|
||||
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_INTERLEAVED);
|
||||
|
||||
status = interleaved_decompress(wfc->codecs->interleaved, data, SrcSize, bpp,
|
||||
&pDstData, PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("wf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_client_codecs_prepare(wfc->codecs, FREERDP_CODEC_PLANAR);
|
||||
|
||||
status = planar_decompress(wfc->codecs->planar, data, SrcSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("wf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -190,6 +190,7 @@ BOOL wf_pre_connect(freerdp* instance)
|
||||
context = instance->context;
|
||||
wfc = (wfContext*) instance->context;
|
||||
wfc->instance = instance;
|
||||
wfc->codecs = instance->context->codecs;
|
||||
|
||||
settings = instance->settings;
|
||||
|
||||
@@ -375,12 +376,6 @@ BOOL wf_post_connect(freerdp* instance)
|
||||
if (settings->RemoteFxCodec)
|
||||
{
|
||||
wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL);
|
||||
wfc->rfx_context = rfx_context_new(FALSE);
|
||||
}
|
||||
|
||||
if (settings->NSCodec)
|
||||
{
|
||||
wfc->nsc_context = nsc_context_new();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ struct wf_context
|
||||
HGDI_DC hdc;
|
||||
UINT16 srcBpp;
|
||||
UINT16 dstBpp;
|
||||
rdpCodecs* codecs;
|
||||
freerdp* instance;
|
||||
wfBitmap* primary;
|
||||
wfBitmap* drawing;
|
||||
@@ -110,8 +111,6 @@ struct wf_context
|
||||
wfBitmap* tile;
|
||||
DWORD mainThreadId;
|
||||
DWORD keyboardThreadId;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
NSC_CONTEXT* nsc_context;
|
||||
|
||||
BOOL sw_gdi;
|
||||
|
||||
|
||||
@@ -695,17 +695,22 @@ static void xf_post_disconnect(freerdp *instance)
|
||||
* @return TRUE if successful. FALSE otherwise.
|
||||
* Can exit with error code XF_EXIT_PARSE_ARGUMENTS if there is an error in the parameters.
|
||||
*/
|
||||
BOOL xf_pre_connect(freerdp *instance)
|
||||
BOOL xf_pre_connect(freerdp* instance)
|
||||
{
|
||||
rdpChannels *channels;
|
||||
rdpSettings *settings;
|
||||
xfContext *xfc = (xfContext *) instance->context;
|
||||
rdpChannels* channels;
|
||||
rdpSettings* settings;
|
||||
xfContext* xfc = (xfContext*) instance->context;
|
||||
|
||||
xfc->codecs = instance->context->codecs;
|
||||
xfc->settings = instance->settings;
|
||||
xfc->instance = instance;
|
||||
|
||||
settings = instance->settings;
|
||||
channels = instance->context->channels;
|
||||
|
||||
settings->OsMajorType = OSMAJORTYPE_UNIX;
|
||||
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
|
||||
|
||||
ZeroMemory(settings->OrderSupport, 32);
|
||||
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
|
||||
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
|
||||
@@ -810,6 +815,7 @@ BOOL xf_pre_connect(freerdp *instance)
|
||||
xfc->fullscreen_toggle = settings->ToggleFullscreen;
|
||||
xf_detect_monitors(xfc, settings);
|
||||
xfc->colormap = DefaultColormap(xfc->display, xfc->screen_number);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -860,12 +866,12 @@ BOOL xf_post_connect(freerdp *instance)
|
||||
|
||||
if (settings->RemoteFxCodec)
|
||||
{
|
||||
xfc->rfx = rfx_context_new(FALSE);
|
||||
xfc->codecs->rfx = rfx_context_new(FALSE);
|
||||
}
|
||||
|
||||
if (settings->NSCodec)
|
||||
{
|
||||
xfc->nsc = nsc_context_new();
|
||||
xfc->codecs->nsc = nsc_context_new();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1102,22 +1108,22 @@ void xf_window_free(xfContext *xfc)
|
||||
context->rail = NULL;
|
||||
}
|
||||
|
||||
if (xfc->rfx)
|
||||
if (xfc->codecs->rfx)
|
||||
{
|
||||
rfx_context_free(xfc->rfx);
|
||||
xfc->rfx = NULL;
|
||||
rfx_context_free(xfc->codecs->rfx);
|
||||
xfc->codecs->rfx = NULL;
|
||||
}
|
||||
|
||||
if (xfc->nsc)
|
||||
if (xfc->codecs->nsc)
|
||||
{
|
||||
nsc_context_free(xfc->nsc);
|
||||
xfc->nsc = NULL;
|
||||
nsc_context_free(xfc->codecs->nsc);
|
||||
xfc->codecs->nsc = NULL;
|
||||
}
|
||||
|
||||
if (xfc->clear)
|
||||
if (xfc->codecs->clear)
|
||||
{
|
||||
clear_context_free(xfc->clear);
|
||||
xfc->clear = NULL;
|
||||
clear_context_free(xfc->codecs->clear);
|
||||
xfc->codecs->clear = NULL;
|
||||
}
|
||||
|
||||
if (xfc->clrconv)
|
||||
|
||||
@@ -1033,7 +1033,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
|
||||
|
||||
if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
|
||||
{
|
||||
message = rfx_process_message(xfc->rfx,
|
||||
message = rfx_process_message(xfc->codecs->rfx,
|
||||
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
|
||||
XSetFunction(xfc->display, xfc->gc, GXcopy);
|
||||
@@ -1070,11 +1070,11 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
|
||||
}
|
||||
|
||||
XSetClipMask(xfc->display, xfc->gc, None);
|
||||
rfx_message_free(xfc->rfx, message);
|
||||
rfx_message_free(xfc->codecs->rfx, message);
|
||||
}
|
||||
else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC)
|
||||
{
|
||||
nsc_process_message(xfc->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
|
||||
nsc_process_message(xfc->codecs->nsc, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
|
||||
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
|
||||
XSetFunction(xfc->display, xfc->gc, GXcopy);
|
||||
@@ -1083,7 +1083,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
|
||||
xfc->bmp_codec_nsc = (BYTE*) realloc(xfc->bmp_codec_nsc,
|
||||
surface_bits_command->width * surface_bits_command->height * 4);
|
||||
|
||||
freerdp_image_flip(xfc->nsc->BitmapData, xfc->bmp_codec_nsc,
|
||||
freerdp_image_flip(xfc->codecs->nsc->BitmapData, xfc->bmp_codec_nsc,
|
||||
surface_bits_command->width, surface_bits_command->height, 32);
|
||||
|
||||
image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0,
|
||||
|
||||
@@ -27,53 +27,53 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re
|
||||
{
|
||||
xfContext* xfc = (xfContext*) context->custom;
|
||||
|
||||
if (xfc->rfx)
|
||||
if (xfc->codecs->rfx)
|
||||
{
|
||||
rfx_context_free(xfc->rfx);
|
||||
xfc->rfx = NULL;
|
||||
rfx_context_free(xfc->codecs->rfx);
|
||||
xfc->codecs->rfx = NULL;
|
||||
}
|
||||
|
||||
xfc->rfx = rfx_context_new(FALSE);
|
||||
xfc->codecs->rfx = rfx_context_new(FALSE);
|
||||
|
||||
xfc->rfx->width = resetGraphics->width;
|
||||
xfc->rfx->height = resetGraphics->height;
|
||||
rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
xfc->codecs->rfx->width = resetGraphics->width;
|
||||
xfc->codecs->rfx->height = resetGraphics->height;
|
||||
rfx_context_set_pixel_format(xfc->codecs->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
if (xfc->nsc)
|
||||
if (xfc->codecs->nsc)
|
||||
{
|
||||
nsc_context_free(xfc->nsc);
|
||||
xfc->nsc = NULL;
|
||||
nsc_context_free(xfc->codecs->nsc);
|
||||
xfc->codecs->nsc = NULL;
|
||||
}
|
||||
|
||||
xfc->nsc = nsc_context_new();
|
||||
xfc->codecs->nsc = nsc_context_new();
|
||||
|
||||
xfc->nsc->width = resetGraphics->width;
|
||||
xfc->nsc->height = resetGraphics->height;
|
||||
nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
xfc->codecs->nsc->width = resetGraphics->width;
|
||||
xfc->codecs->nsc->height = resetGraphics->height;
|
||||
nsc_context_set_pixel_format(xfc->codecs->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
if (xfc->clear)
|
||||
if (xfc->codecs->clear)
|
||||
{
|
||||
clear_context_free(xfc->clear);
|
||||
xfc->clear = NULL;
|
||||
clear_context_free(xfc->codecs->clear);
|
||||
xfc->codecs->clear = NULL;
|
||||
}
|
||||
|
||||
xfc->clear = clear_context_new(FALSE);
|
||||
xfc->codecs->clear = clear_context_new(FALSE);
|
||||
|
||||
if (xfc->h264)
|
||||
if (xfc->codecs->h264)
|
||||
{
|
||||
h264_context_free(xfc->h264);
|
||||
xfc->h264 = NULL;
|
||||
h264_context_free(xfc->codecs->h264);
|
||||
xfc->codecs->h264 = NULL;
|
||||
}
|
||||
|
||||
xfc->h264 = h264_context_new(FALSE);
|
||||
xfc->codecs->h264 = h264_context_new(FALSE);
|
||||
|
||||
if (xfc->progressive)
|
||||
if (xfc->codecs->progressive)
|
||||
{
|
||||
progressive_context_free(xfc->progressive);
|
||||
xfc->progressive = NULL;
|
||||
progressive_context_free(xfc->codecs->progressive);
|
||||
xfc->codecs->progressive = NULL;
|
||||
}
|
||||
|
||||
xfc->progressive = progressive_context_new(TRUE);
|
||||
xfc->codecs->progressive = progressive_context_new(TRUE);
|
||||
|
||||
region16_init(&(xfc->invalidRegion));
|
||||
|
||||
@@ -136,6 +136,9 @@ int xf_OutputUpdate(xfContext* xfc)
|
||||
|
||||
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
|
||||
{
|
||||
/** *********************************
|
||||
* to be improved?
|
||||
* *********************************/
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
invalidRect.left = x;
|
||||
@@ -213,12 +216,14 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
|
||||
REGION16 clippingRects;
|
||||
RECTANGLE_16 clippingRect;
|
||||
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX);
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
return -1;
|
||||
|
||||
message = rfx_process_message(xfc->rfx, cmd->data, cmd->length);
|
||||
message = rfx_process_message(xfc->codecs->rfx, cmd->data, cmd->length);
|
||||
|
||||
if (!message)
|
||||
return -1;
|
||||
@@ -267,7 +272,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
|
||||
region16_uninit(&updateRegion);
|
||||
}
|
||||
|
||||
rfx_message_free(xfc->rfx, message);
|
||||
rfx_message_free(xfc->codecs->rfx, message);
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
@@ -282,6 +287,8 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_CLEARCODEC);
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
@@ -289,7 +296,7 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
|
||||
|
||||
DstData = surface->data;
|
||||
|
||||
status = clear_decompress(xfc->clear, cmd->data, cmd->length, &DstData,
|
||||
status = clear_decompress(xfc->codecs->clear, cmd->data, cmd->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
|
||||
|
||||
if (status < 0)
|
||||
@@ -305,6 +312,7 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
||||
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
|
||||
@@ -318,6 +326,8 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR);
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
@@ -325,7 +335,7 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
|
||||
|
||||
DstData = surface->data;
|
||||
|
||||
status = planar_decompress(NULL, cmd->data, cmd->length, &DstData,
|
||||
status = planar_decompress(xfc->codecs->planar, cmd->data, cmd->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
|
||||
|
||||
invalidRect.left = cmd->left;
|
||||
@@ -344,23 +354,16 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
|
||||
int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
|
||||
{
|
||||
int status;
|
||||
UINT32 i, j;
|
||||
int nXDst, nYDst;
|
||||
int nWidth, nHeight;
|
||||
int nbUpdateRects;
|
||||
UINT32 i;
|
||||
BYTE* DstData = NULL;
|
||||
RDPGFX_RECT16* rect;
|
||||
H264_CONTEXT* h264;
|
||||
xfGfxSurface* surface;
|
||||
REGION16 updateRegion;
|
||||
RECTANGLE_16 updateRect;
|
||||
RECTANGLE_16* updateRects;
|
||||
REGION16 clippingRects;
|
||||
RECTANGLE_16 clippingRect;
|
||||
RDPGFX_H264_METABLOCK* meta;
|
||||
RDPGFX_H264_BITMAP_STREAM* bs;
|
||||
|
||||
h264 = xfc->h264;
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_H264);
|
||||
|
||||
h264 = xfc->codecs->h264;
|
||||
|
||||
bs = (RDPGFX_H264_BITMAP_STREAM*) cmd->extra;
|
||||
|
||||
@@ -376,68 +379,20 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_
|
||||
|
||||
DstData = surface->data;
|
||||
|
||||
status = h264_decompress(xfc->h264, bs->data, bs->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height);
|
||||
|
||||
printf("xf_SurfaceCommand_H264: status: %d\n", status);
|
||||
status = h264_decompress(xfc->codecs->h264, bs->data, bs->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline , surface->height, meta->regionRects, meta->numRegionRects);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
printf("h264_decompress failure: %d\n",status);
|
||||
return -1;
|
||||
|
||||
region16_init(&clippingRects);
|
||||
}
|
||||
|
||||
for (i = 0; i < meta->numRegionRects; i++)
|
||||
{
|
||||
rect = &(meta->regionRects[i]);
|
||||
|
||||
clippingRect.left = rect->left;
|
||||
clippingRect.top = rect->top;
|
||||
clippingRect.right = rect->right;
|
||||
clippingRect.bottom = rect->bottom;
|
||||
|
||||
region16_union_rect(&clippingRects, &clippingRects, &clippingRect);
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), (RECTANGLE_16*) &(meta->regionRects[i]));
|
||||
}
|
||||
|
||||
updateRect.left = cmd->left;
|
||||
updateRect.top = cmd->top;
|
||||
updateRect.right = cmd->right;
|
||||
updateRect.bottom = cmd->bottom;
|
||||
|
||||
region16_init(&updateRegion);
|
||||
region16_intersect_rect(&updateRegion, &clippingRects, &updateRect);
|
||||
updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects);
|
||||
|
||||
printf("numRegionRects: %d nbUpdateRects: %d\n", meta->numRegionRects, nbUpdateRects);
|
||||
|
||||
for (j = 0; j < nbUpdateRects; j++)
|
||||
{
|
||||
nXDst = updateRects[j].left;
|
||||
nYDst = updateRects[j].top;
|
||||
nWidth = updateRects[j].right - updateRects[j].left;
|
||||
nHeight = updateRects[j].bottom - updateRects[j].top;
|
||||
|
||||
/* update region from decoded H264 buffer */
|
||||
|
||||
printf("nXDst: %d nYDst: %d nWidth: %d nHeight: %d decoded: width: %d height: %d cmd: left: %d top: %d right: %d bottom: %d\n",
|
||||
nXDst, nYDst, nWidth, nHeight, h264->width, h264->height,
|
||||
cmd->left, cmd->top, cmd->right, cmd->bottom);
|
||||
|
||||
freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
nXDst, nYDst, nWidth, nHeight,
|
||||
h264->data, PIXEL_FORMAT_XRGB32, h264->scanline, nXDst, nYDst);
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]);
|
||||
}
|
||||
|
||||
region16_uninit(&updateRegion);
|
||||
|
||||
#if 0
|
||||
/* fill with red for now to distinguish from the rest */
|
||||
|
||||
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
|
||||
cmd->left, cmd->top, cmd->width, cmd->height, 0xFF0000);
|
||||
#endif
|
||||
|
||||
if (!xfc->inGfxFrame)
|
||||
xf_OutputUpdate(xfc);
|
||||
|
||||
@@ -450,6 +405,8 @@ int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX
|
||||
xfGfxSurface* surface;
|
||||
RECTANGLE_16 invalidRect;
|
||||
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_ALPHACODEC);
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
@@ -494,16 +451,18 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
|
||||
RFX_PROGRESSIVE_TILE* tile;
|
||||
PROGRESSIVE_BLOCK_REGION* region;
|
||||
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PROGRESSIVE);
|
||||
|
||||
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
|
||||
|
||||
if (!surface)
|
||||
return -1;
|
||||
|
||||
progressive_create_surface_context(xfc->progressive, cmd->surfaceId, surface->width, surface->height);
|
||||
progressive_create_surface_context(xfc->codecs->progressive, cmd->surfaceId, surface->width, surface->height);
|
||||
|
||||
DstData = surface->data;
|
||||
|
||||
status = progressive_decompress(xfc->progressive, cmd->data, cmd->length, &DstData,
|
||||
status = progressive_decompress(xfc->codecs->progressive, cmd->data, cmd->length, &DstData,
|
||||
PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId);
|
||||
|
||||
if (status < 0)
|
||||
@@ -512,7 +471,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
|
||||
return -1;
|
||||
}
|
||||
|
||||
region = &(xfc->progressive->region);
|
||||
region = &(xfc->codecs->progressive->region);
|
||||
|
||||
region16_init(&clippingRects);
|
||||
|
||||
@@ -659,7 +618,7 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de
|
||||
|
||||
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
|
||||
|
||||
progressive_delete_surface_context(xfc->progressive, deleteSurface->surfaceId);
|
||||
progressive_delete_surface_context(xfc->codecs->progressive, deleteSurface->surfaceId);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -724,6 +683,7 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
|
||||
|
||||
rectSrc = &(surfaceToSurface->rectSrc);
|
||||
destPt = &surfaceToSurface->destPts[0];
|
||||
/**not needed?*/
|
||||
|
||||
surfaceSrc = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToSurface->surfaceIdSrc);
|
||||
|
||||
@@ -750,6 +710,8 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
|
||||
invalidRect.top = destPt->y;
|
||||
invalidRect.right = destPt->x + rectSrc->right;
|
||||
invalidRect.bottom = destPt->y + rectSrc->bottom;
|
||||
|
||||
/**width,height?*/
|
||||
|
||||
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
|
||||
}
|
||||
@@ -783,7 +745,7 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU*
|
||||
cacheEntry->alpha = surface->alpha;
|
||||
|
||||
cacheEntry->scanline = (cacheEntry->width + (cacheEntry->width % 4)) * 4;
|
||||
cacheEntry->data = (BYTE*) calloc(1, surface->scanline * surface->height);
|
||||
cacheEntry->data = (BYTE*) calloc(1, cacheEntry->scanline * cacheEntry->height);
|
||||
|
||||
if (!cacheEntry->data)
|
||||
return -1;
|
||||
|
||||
@@ -120,14 +120,14 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
|
||||
|
||||
void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
BYTE* data, int width, int height, int bpp, int length,
|
||||
BOOL compressed, int codec_id)
|
||||
BOOL compressed, int codecId)
|
||||
{
|
||||
int status;
|
||||
UINT16 size;
|
||||
BYTE* src;
|
||||
BYTE* dst;
|
||||
int yindex;
|
||||
int xindex;
|
||||
BOOL status;
|
||||
RFX_MESSAGE* msg;
|
||||
xfContext* xfc = (xfContext*) context;
|
||||
|
||||
@@ -138,19 +138,21 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
else
|
||||
bitmap->data = (BYTE*) _aligned_realloc(bitmap->data, size, 16);
|
||||
|
||||
switch (codec_id)
|
||||
switch (codecId)
|
||||
{
|
||||
case RDP_CODEC_ID_NSCODEC:
|
||||
DEBUG_WARN( "xf_Bitmap_Decompress: nsc not done\n");
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_NSCODEC);
|
||||
DEBUG_WARN("xf_Bitmap_Decompress: nsc not done\n");
|
||||
break;
|
||||
|
||||
case RDP_CODEC_ID_REMOTEFX:
|
||||
rfx_context_set_pixel_format(xfc->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
msg = rfx_process_message(xfc->rfx, data, length);
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_REMOTEFX);
|
||||
rfx_context_set_pixel_format(xfc->codecs->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
msg = rfx_process_message(xfc->codecs->rfx, data, length);
|
||||
|
||||
if (!msg)
|
||||
{
|
||||
DEBUG_WARN( "xf_Bitmap_Decompress: rfx Decompression Failed\n");
|
||||
DEBUG_WARN("xf_Bitmap_Decompress: rfx Decompression Failed\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -166,7 +168,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
src++;
|
||||
}
|
||||
}
|
||||
rfx_message_free(xfc->rfx, msg);
|
||||
rfx_message_free(xfc->codecs->rfx, msg);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -180,11 +182,35 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
default:
|
||||
if (compressed)
|
||||
{
|
||||
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
||||
BYTE* pDstData;
|
||||
UINT32 SrcSize;
|
||||
|
||||
if (!status)
|
||||
SrcSize = (UINT32) length;
|
||||
pDstData = bitmap->data;
|
||||
|
||||
if (bpp < 32)
|
||||
{
|
||||
DEBUG_WARN( "xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_INTERLEAVED);
|
||||
|
||||
status = interleaved_decompress(xfc->codecs->interleaved, data, SrcSize, bpp,
|
||||
&pDstData, PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_client_codecs_prepare(xfc->codecs, FREERDP_CODEC_PLANAR);
|
||||
|
||||
status = planar_decompress(xfc->codecs->planar, data, SrcSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("gdi_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -75,6 +75,7 @@ struct xf_context
|
||||
|
||||
freerdp* instance;
|
||||
rdpSettings* settings;
|
||||
rdpCodecs* codecs;
|
||||
|
||||
GC gc;
|
||||
int bpp;
|
||||
@@ -152,11 +153,6 @@ struct xf_context
|
||||
VIRTUAL_SCREEN vscreen;
|
||||
BYTE* bmp_codec_none;
|
||||
BYTE* bmp_codec_nsc;
|
||||
RFX_CONTEXT* rfx;
|
||||
NSC_CONTEXT* nsc;
|
||||
CLEAR_CONTEXT* clear;
|
||||
H264_CONTEXT* h264;
|
||||
PROGRESSIVE_CONTEXT* progressive;
|
||||
void* xv_context;
|
||||
void* clipboard_context;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
if((CMAKE_SYSTEM_PROCESSOR MATCHES "i386|i686|x86") AND (CMAKE_SIZEOF_VOID_P EQUAL 4))
|
||||
if((CMAKE_SYSTEM_PROCESSOR MATCHES "i386|i686|x86|AMD64") AND (CMAKE_SIZEOF_VOID_P EQUAL 4))
|
||||
set(TARGET_ARCH "x86")
|
||||
elseif((CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") AND (CMAKE_SIZEOF_VOID_P EQUAL 8))
|
||||
set(TARGET_ARCH "x64")
|
||||
|
||||
@@ -32,27 +32,9 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp);
|
||||
|
||||
FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
|
||||
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
|
||||
|
||||
#define PLANAR_FORMAT_HEADER_CS (1 << 3)
|
||||
#define PLANAR_FORMAT_HEADER_RLE (1 << 4)
|
||||
#define PLANAR_FORMAT_HEADER_NA (1 << 5)
|
||||
#define PLANAR_FORMAT_HEADER_CLL_MASK 0x07
|
||||
|
||||
typedef struct _BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT;
|
||||
|
||||
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
|
||||
int width, int height, int scanline, BYTE* dstData, int* dstSize);
|
||||
|
||||
FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight);
|
||||
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
|
||||
|
||||
FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef FREERDP_CODEC_CLEAR_H
|
||||
#define FREERDP_CODEC_CLEAR_H
|
||||
|
||||
typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
@@ -59,7 +61,6 @@ struct _CLEAR_CONTEXT
|
||||
UINT32 ShortVBarStorageCursor;
|
||||
CLEAR_VBAR_ENTRY ShortVBarStorage[16384];
|
||||
};
|
||||
typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -22,14 +22,14 @@
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/channels/rdpgfx.h>
|
||||
|
||||
typedef struct _H264_CONTEXT H264_CONTEXT;
|
||||
|
||||
typedef BOOL (*pfnH264SubsystemInit)(H264_CONTEXT* h264);
|
||||
typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264);
|
||||
|
||||
typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize);
|
||||
|
||||
struct _H264_CONTEXT_SUBSYSTEM
|
||||
{
|
||||
@@ -44,11 +44,11 @@ struct _H264_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
BYTE* data;
|
||||
UINT32 size;
|
||||
UINT32 width;
|
||||
UINT32 height;
|
||||
int scanline;
|
||||
|
||||
int iStride[3];
|
||||
BYTE* pYUVData[3];
|
||||
|
||||
void* pSystemData;
|
||||
H264_CONTEXT_SUBSYSTEM* subsystem;
|
||||
@@ -61,7 +61,7 @@ extern "C" {
|
||||
FREERDP_API int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize);
|
||||
|
||||
FREERDP_API int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nDstHeight, RDPGFX_RECT16* regionRects, int numRegionRect);
|
||||
|
||||
FREERDP_API H264_CONTEXT* h264_context_new(BOOL Compressor);
|
||||
FREERDP_API void h264_context_free(H264_CONTEXT* h264);
|
||||
|
||||
46
include/freerdp/codec/interleaved.h
Normal file
46
include/freerdp/codec/interleaved.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Interleaved RLE Bitmap Codec
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CODEC_INTERLEAVED_H
|
||||
#define FREERDP_CODEC_INTERLEAVED_H
|
||||
|
||||
typedef struct _BITMAP_INTERLEAVED_CONTEXT BITMAP_INTERLEAVED_CONTEXT;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
|
||||
struct _BITMAP_INTERLEAVED_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
UINT32 FlipSize;
|
||||
BYTE* FlipBuffer;
|
||||
};
|
||||
|
||||
FREERDP_API int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
|
||||
FREERDP_API BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor);
|
||||
FREERDP_API void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved);
|
||||
|
||||
#endif /* FREERDP_CODEC_INTERLEAVED_H */
|
||||
|
||||
@@ -17,14 +17,21 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CODEC_PLANAR_PRIVATE_H
|
||||
#define FREERDP_CODEC_PLANAR_PRIVATE_H
|
||||
#ifndef FREERDP_CODEC_PLANAR_H
|
||||
#define FREERDP_CODEC_PLANAR_H
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
typedef struct _BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT;
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
|
||||
#define PLANAR_FORMAT_HEADER_CS (1 << 3)
|
||||
#define PLANAR_FORMAT_HEADER_RLE (1 << 4)
|
||||
#define PLANAR_FORMAT_HEADER_NA (1 << 5)
|
||||
#define PLANAR_FORMAT_HEADER_CLL_MASK 0x07
|
||||
|
||||
#define PLANAR_CONTROL_BYTE(_nRunLength, _cRawBytes) \
|
||||
(_nRunLength & 0x0F) | ((_cRawBytes & 0x0F) << 4)
|
||||
|
||||
@@ -92,4 +99,14 @@ FREERDP_API BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int widt
|
||||
FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane);
|
||||
FREERDP_API int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4]);
|
||||
|
||||
#endif /* FREERDP_CODEC_PLANAR_PRIVATE_H */
|
||||
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
|
||||
int width, int height, int scanline, BYTE* dstData, int* dstSize);
|
||||
|
||||
FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight);
|
||||
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
|
||||
|
||||
FREERDP_API int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
|
||||
|
||||
#endif /* FREERDP_CODEC_PLANAR_H */
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef FREERDP_CODEC_PROGRESSIVE_H
|
||||
#define FREERDP_CODEC_PROGRESSIVE_H
|
||||
|
||||
typedef struct _PROGRESSIVE_CONTEXT PROGRESSIVE_CONTEXT;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
|
||||
@@ -301,7 +303,6 @@ struct _PROGRESSIVE_CONTEXT
|
||||
|
||||
wHashTable* SurfaceContexts;
|
||||
};
|
||||
typedef struct _PROGRESSIVE_CONTEXT PROGRESSIVE_CONTEXT;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
#ifndef FREERDP_CODEC_REMOTEFX_H
|
||||
#define FREERDP_CODEC_REMOTEFX_H
|
||||
|
||||
typedef enum _RLGR_MODE RLGR_MODE;
|
||||
typedef struct _RFX_RECT RFX_RECT;
|
||||
typedef struct _RFX_TILE RFX_TILE;
|
||||
typedef struct _RFX_MESSAGE RFX_MESSAGE;
|
||||
typedef struct _RFX_CONTEXT RFX_CONTEXT;
|
||||
|
||||
#include <freerdp/api.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
@@ -36,7 +42,6 @@ enum _RLGR_MODE
|
||||
RLGR1,
|
||||
RLGR3
|
||||
};
|
||||
typedef enum _RLGR_MODE RLGR_MODE;
|
||||
|
||||
struct _RFX_RECT
|
||||
{
|
||||
@@ -45,7 +50,6 @@ struct _RFX_RECT
|
||||
UINT16 width;
|
||||
UINT16 height;
|
||||
};
|
||||
typedef struct _RFX_RECT RFX_RECT;
|
||||
|
||||
struct _RFX_TILE
|
||||
{
|
||||
@@ -69,7 +73,6 @@ struct _RFX_TILE
|
||||
BYTE* CrData;
|
||||
BYTE* YCbCrData;
|
||||
};
|
||||
typedef struct _RFX_TILE RFX_TILE;
|
||||
|
||||
struct _RFX_MESSAGE
|
||||
{
|
||||
@@ -99,7 +102,6 @@ struct _RFX_MESSAGE
|
||||
|
||||
BOOL freeArray;
|
||||
};
|
||||
typedef struct _RFX_MESSAGE RFX_MESSAGE;
|
||||
|
||||
typedef struct _RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV;
|
||||
|
||||
@@ -150,7 +152,6 @@ struct _RFX_CONTEXT
|
||||
/* private definitions */
|
||||
RFX_CONTEXT_PRIV* priv;
|
||||
};
|
||||
typedef struct _RFX_CONTEXT RFX_CONTEXT;
|
||||
|
||||
FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder);
|
||||
FREERDP_API void rfx_context_free(RFX_CONTEXT* context);
|
||||
|
||||
63
include/freerdp/codecs.h
Normal file
63
include/freerdp/codecs.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Codecs
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CODECS_H
|
||||
#define FREERDP_CODECS_H
|
||||
|
||||
#include <freerdp/api.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
#include <freerdp/codec/nsc.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
#include <freerdp/codec/clear.h>
|
||||
#include <freerdp/codec/planar.h>
|
||||
#include <freerdp/codec/interleaved.h>
|
||||
#include <freerdp/codec/progressive.h>
|
||||
|
||||
#define FREERDP_CODEC_INTERLEAVED 0x00000001
|
||||
#define FREERDP_CODEC_PLANAR 0x00000002
|
||||
#define FREERDP_CODEC_NSCODEC 0x00000004
|
||||
#define FREERDP_CODEC_REMOTEFX 0x00000008
|
||||
#define FREERDP_CODEC_CLEARCODEC 0x00000010
|
||||
#define FREERDP_CODEC_ALPHACODEC 0x00000020
|
||||
#define FREERDP_CODEC_PROGRESSIVE 0x00000040
|
||||
#define FREERDP_CODEC_H264 0x00000080
|
||||
|
||||
struct rdp_codecs
|
||||
{
|
||||
rdpContext* context;
|
||||
|
||||
RFX_CONTEXT* rfx;
|
||||
NSC_CONTEXT* nsc;
|
||||
H264_CONTEXT* h264;
|
||||
CLEAR_CONTEXT* clear;
|
||||
PROGRESSIVE_CONTEXT* progressive;
|
||||
BITMAP_PLANAR_CONTEXT* planar;
|
||||
BITMAP_INTERLEAVED_CONTEXT* interleaved;
|
||||
};
|
||||
|
||||
FREERDP_API int freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags);
|
||||
|
||||
FREERDP_API rdpCodecs* codecs_new(rdpContext* context);
|
||||
FREERDP_API void codecs_free(rdpCodecs* codecs);
|
||||
|
||||
#endif /* FREERDP_CODECS_H */
|
||||
|
||||
@@ -27,6 +27,7 @@ typedef struct rdp_cache rdpCache;
|
||||
typedef struct rdp_channels rdpChannels;
|
||||
typedef struct rdp_graphics rdpGraphics;
|
||||
typedef struct rdp_metrics rdpMetrics;
|
||||
typedef struct rdp_codecs rdpCodecs;
|
||||
|
||||
typedef struct rdp_freerdp freerdp;
|
||||
typedef struct rdp_context rdpContext;
|
||||
@@ -40,6 +41,7 @@ typedef RDP_CLIENT_ENTRY_POINTS_V1 RDP_CLIENT_ENTRY_POINTS;
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/error.h>
|
||||
#include <freerdp/event.h>
|
||||
#include <freerdp/codecs.h>
|
||||
#include <freerdp/metrics.h>
|
||||
#include <freerdp/settings.h>
|
||||
#include <freerdp/extension.h>
|
||||
@@ -120,7 +122,8 @@ struct rdp_context
|
||||
ALIGN64 rdpUpdate* update; /* 39 */
|
||||
ALIGN64 rdpSettings* settings; /* 40 */
|
||||
ALIGN64 rdpMetrics* metrics; /* 41 */
|
||||
UINT64 paddingC[64 - 42]; /* 42 */
|
||||
ALIGN64 rdpCodecs* codecs; /* 42 */
|
||||
UINT64 paddingC[64 - 43]; /* 43 */
|
||||
|
||||
UINT64 paddingD[96 - 64]; /* 64 */
|
||||
UINT64 paddingE[128 - 96]; /* 96 */
|
||||
|
||||
@@ -279,6 +279,7 @@ struct rdp_gdi
|
||||
int cursor_x;
|
||||
int cursor_y;
|
||||
int bytesPerPixel;
|
||||
rdpCodecs* codecs;
|
||||
|
||||
HGDI_DC hdc;
|
||||
HCLRCONV clrconv;
|
||||
@@ -286,8 +287,6 @@ struct rdp_gdi
|
||||
gdiBitmap* drawing;
|
||||
BYTE* primary_buffer;
|
||||
GDI_COLOR textColor;
|
||||
void* rfx_context;
|
||||
void* nsc_context;
|
||||
gdiBitmap* tile;
|
||||
gdiBitmap* image;
|
||||
};
|
||||
|
||||
@@ -152,7 +152,7 @@ typedef pstatus_t (*__RGBToRGB_16s8u_P3AC4R_t)(
|
||||
const INT16 *pSrc[3], INT32 srcStep,
|
||||
BYTE *pDst, INT32 dstStep,
|
||||
const prim_size_t *roi);
|
||||
typedef pstatus_t (*__YCoCgRToRGB_8u_AC4R_t)(
|
||||
typedef pstatus_t (*__YCoCgToRGB_8u_AC4R_t)(
|
||||
const BYTE *pSrc, INT32 srcStep,
|
||||
BYTE *pDst, INT32 dstStep,
|
||||
UINT32 width, UINT32 height,
|
||||
@@ -164,6 +164,10 @@ typedef pstatus_t (*__RGB565ToARGB_16u32u_C3C4_t)(
|
||||
UINT32* pDst, INT32 dstStep,
|
||||
UINT32 width, UINT32 height,
|
||||
BOOL alpha, BOOL invert);
|
||||
typedef pstatus_t (*__YUV420ToRGB_8u_P3AC4R_t)(
|
||||
const BYTE* pSrc[3], INT32 srcStep[3],
|
||||
BYTE* pDst, INT32 dstStep,
|
||||
const prim_size_t* roi);
|
||||
typedef pstatus_t (*__andC_32u_t)(
|
||||
const UINT32 *pSrc,
|
||||
UINT32 val,
|
||||
@@ -207,8 +211,9 @@ typedef struct
|
||||
__yCbCrToRGB_16s16s_P3P3_t yCbCrToRGB_16s16s_P3P3;
|
||||
__RGBToYCbCr_16s16s_P3P3_t RGBToYCbCr_16s16s_P3P3;
|
||||
__RGBToRGB_16s8u_P3AC4R_t RGBToRGB_16s8u_P3AC4R;
|
||||
__YCoCgRToRGB_8u_AC4R_t YCoCgRToRGB_8u_AC4R;
|
||||
__YCoCgToRGB_8u_AC4R_t YCoCgToRGB_8u_AC4R;
|
||||
__RGB565ToARGB_16u32u_C3C4_t RGB565ToARGB_16u32u_C3C4;
|
||||
__YUV420ToRGB_8u_P3AC4R_t YUV420ToRGB_8u_P3AC4R;
|
||||
} primitives_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -32,6 +32,21 @@
|
||||
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
struct _PALETTE_ENTRY
|
||||
{
|
||||
BYTE red;
|
||||
BYTE green;
|
||||
BYTE blue;
|
||||
};
|
||||
typedef struct _PALETTE_ENTRY PALETTE_ENTRY;
|
||||
|
||||
struct rdp_palette
|
||||
{
|
||||
UINT32 count;
|
||||
PALETTE_ENTRY entries[256];
|
||||
};
|
||||
typedef struct rdp_palette rdpPalette;
|
||||
|
||||
#include <freerdp/settings.h>
|
||||
|
||||
struct _RDP_PLUGIN_DATA
|
||||
|
||||
@@ -73,14 +73,6 @@ typedef struct _BITMAP_UPDATE BITMAP_UPDATE;
|
||||
|
||||
/* Palette Updates */
|
||||
|
||||
struct _PALETTE_ENTRY
|
||||
{
|
||||
BYTE red;
|
||||
BYTE green;
|
||||
BYTE blue;
|
||||
};
|
||||
typedef struct _PALETTE_ENTRY PALETTE_ENTRY;
|
||||
|
||||
struct _PALETTE_UPDATE
|
||||
{
|
||||
UINT32 number;
|
||||
@@ -88,13 +80,6 @@ struct _PALETTE_UPDATE
|
||||
};
|
||||
typedef struct _PALETTE_UPDATE PALETTE_UPDATE;
|
||||
|
||||
struct rdp_palette
|
||||
{
|
||||
UINT32 count;
|
||||
PALETTE_ENTRY entries[256];
|
||||
};
|
||||
typedef struct rdp_palette rdpPalette;
|
||||
|
||||
/* Play Sound (System Beep) Updates */
|
||||
|
||||
struct _PLAY_SOUND_UPDATE
|
||||
|
||||
@@ -23,10 +23,9 @@ set(${MODULE_PREFIX}_SRCS
|
||||
color.c
|
||||
audio.c
|
||||
planar.c
|
||||
planar.h
|
||||
bitmap.c
|
||||
interleaved.c
|
||||
progressive.c
|
||||
bitmap_decode.c
|
||||
bitmap_encode.c
|
||||
rfx_bitstream.h
|
||||
rfx_constants.h
|
||||
rfx_decode.c
|
||||
@@ -101,6 +100,7 @@ if(WITH_LIBAVCODEC)
|
||||
set(FREERDP_LIBAVCODEC_LIBS ${LIBAVCODEC_LIB} ${LIBAVUTIL_LIB})
|
||||
endif()
|
||||
|
||||
|
||||
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
|
||||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
SOURCES ${${MODULE_PREFIX}_SRCS}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#endif
|
||||
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/planar.h>
|
||||
|
||||
#define GETPIXEL16(d, x, y, w) (*(((unsigned short*)d) + ((y) * (w) + (x))))
|
||||
#define GETPIXEL32(d, x, y, w) (*(((unsigned int*)d) + ((y) * (w) + (x))))
|
||||
@@ -25,139 +25,14 @@
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/primitives.h>
|
||||
#include <freerdp/codec/h264.h>
|
||||
|
||||
static INLINE BYTE clip(int x)
|
||||
{
|
||||
if (x < 0) return 0;
|
||||
if (x > 255) return 255;
|
||||
return (BYTE) x;
|
||||
}
|
||||
|
||||
static INLINE UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V)
|
||||
{
|
||||
int C, D, E;
|
||||
BYTE R, G, B;
|
||||
|
||||
C = Y;
|
||||
D = U - 128;
|
||||
E = V - 128;
|
||||
|
||||
R = clip(( 256 * C + 403 * E + 128) >> 8);
|
||||
G = clip(( 256 * C - 48 * D - 120 * E + 128) >> 8);
|
||||
B = clip(( 256 * C + 475 * D + 128) >> 8);
|
||||
|
||||
return RGB32(R, G, B);
|
||||
}
|
||||
|
||||
static int g_H264FrameId = 0;
|
||||
static BOOL g_H264DumpFrames = FALSE;
|
||||
|
||||
static void h264_dump_h264_data(BYTE* data, int size)
|
||||
{
|
||||
FILE* fp;
|
||||
char buf[4096];
|
||||
|
||||
sprintf_s(buf, sizeof(buf), "/tmp/wlog/bs_%d.h264", g_H264FrameId);
|
||||
fp = fopen(buf, "wb");
|
||||
fwrite(data, 1, size, fp);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void h264_dump_yuv_data(BYTE* yuv[], int width, int height, int stride[])
|
||||
{
|
||||
FILE* fp;
|
||||
BYTE* srcp;
|
||||
char buf[4096];
|
||||
int j;
|
||||
|
||||
sprintf_s(buf, sizeof(buf), "/tmp/wlog/H264_%d.ppm", g_H264FrameId);
|
||||
fp = fopen(buf, "wb");
|
||||
fwrite("P5\n", 1, 3, fp);
|
||||
sprintf_s(buf, sizeof(buf), "%d %d\n", width, height);
|
||||
fwrite(buf, 1, strlen(buf), fp);
|
||||
fwrite("255\n", 1, 4, fp);
|
||||
|
||||
srcp = yuv[0];
|
||||
|
||||
for (j = 0; j < height; j++)
|
||||
{
|
||||
fwrite(srcp, 1, width, fp);
|
||||
srcp += stride[0];
|
||||
}
|
||||
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height)
|
||||
{
|
||||
UINT32 size;
|
||||
|
||||
h264->width = width;
|
||||
h264->height = height;
|
||||
h264->scanline = h264->width * 4;
|
||||
size = h264->scanline * h264->height;
|
||||
|
||||
if (size > h264->size)
|
||||
{
|
||||
h264->size = size;
|
||||
h264->data = (BYTE*) realloc(h264->data, h264->size);
|
||||
memset(h264->data, 0, h264->size);
|
||||
}
|
||||
|
||||
if (!h264->data)
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int freerdp_image_copy_yuv420p_to_xrgb(BYTE* pDstData, int nDstStep, int nXDst, int nYDst,
|
||||
int nWidth, int nHeight, BYTE* pSrcData[3], int nSrcStep[2], int nXSrc, int nYSrc)
|
||||
{
|
||||
int x, y;
|
||||
BYTE* pDstPixel8;
|
||||
BYTE *pY, *pU, *pV;
|
||||
int shift = 1;
|
||||
|
||||
pY = pSrcData[0] + (nYSrc * nSrcStep[0]) + nXSrc;
|
||||
|
||||
pDstPixel8 = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
pU = pSrcData[1] + ((nYSrc + y) >> shift) * nSrcStep[1];
|
||||
pV = pSrcData[2] + ((nYSrc + y) >> shift) * nSrcStep[1];
|
||||
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
BYTE Y, U, V;
|
||||
|
||||
Y = *pY;
|
||||
U = pU[(nXSrc + x) >> shift];
|
||||
V = pV[(nXSrc + x) >> shift];
|
||||
|
||||
*((UINT32*) pDstPixel8) = YUV_to_RGB(Y, U, V);
|
||||
|
||||
pDstPixel8 += 4;
|
||||
pY++;
|
||||
}
|
||||
|
||||
pDstPixel8 += (nDstStep - (nWidth * 4));
|
||||
pY += (nSrcStep[0] - nWidth);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy subsystem
|
||||
*/
|
||||
|
||||
static int dummy_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
static int dummy_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
@@ -202,10 +77,8 @@ static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* m
|
||||
printf("%d - %s\n", level, message);
|
||||
}
|
||||
|
||||
static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
BYTE* pYUVData[3];
|
||||
DECODING_STATE state;
|
||||
SBufferInfo sBufferInfo;
|
||||
SSysMEMBuffer* pSystemBuffer;
|
||||
@@ -218,9 +91,9 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
* Decompress the image. The RDP host only seems to send I420 format.
|
||||
*/
|
||||
|
||||
pYUVData[0] = NULL;
|
||||
pYUVData[1] = NULL;
|
||||
pYUVData[2] = NULL;
|
||||
h264->pYUVData[0] = NULL;
|
||||
h264->pYUVData[1] = NULL;
|
||||
h264->pYUVData[2] = NULL;
|
||||
|
||||
ZeroMemory(&sBufferInfo, sizeof(sBufferInfo));
|
||||
|
||||
@@ -228,7 +101,7 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
sys->pDecoder,
|
||||
pSrcData,
|
||||
SrcSize,
|
||||
pYUVData,
|
||||
h264->pYUVData,
|
||||
&sBufferInfo);
|
||||
|
||||
/**
|
||||
@@ -239,13 +112,13 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
*/
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, pYUVData, &sBufferInfo);
|
||||
state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, h264->pYUVData, &sBufferInfo);
|
||||
|
||||
pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer;
|
||||
|
||||
#if 0
|
||||
printf("h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]\n",
|
||||
state, pYUVData[0], pYUVData[1], pYUVData[2], sBufferInfo.iBufferStatus,
|
||||
state, h264->pYUVData[0], h264->pYUVData[1], h264->pYUVData[2], sBufferInfo.iBufferStatus,
|
||||
pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat,
|
||||
pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]);
|
||||
#endif
|
||||
@@ -253,29 +126,21 @@ static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSiz
|
||||
if (state != 0)
|
||||
return -1;
|
||||
|
||||
if (!pYUVData[0] || !pYUVData[1] || !pYUVData[2])
|
||||
return -1;
|
||||
|
||||
if (sBufferInfo.iBufferStatus != 1)
|
||||
return -1;
|
||||
return -2;
|
||||
|
||||
if (pSystemBuffer->iFormat != videoFormatI420)
|
||||
return -1;
|
||||
|
||||
/* Convert I420 (same as IYUV) to XRGB. */
|
||||
|
||||
if (g_H264DumpFrames)
|
||||
{
|
||||
h264_dump_yuv_data(pYUVData, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iStride);
|
||||
}
|
||||
|
||||
g_H264FrameId++;
|
||||
|
||||
if (h264_prepare_rgb_buffer(h264, pSystemBuffer->iWidth, pSystemBuffer->iHeight) < 0)
|
||||
if (!h264->pYUVData[0] || !h264->pYUVData[1] || !h264->pYUVData[2])
|
||||
return -1;
|
||||
|
||||
freerdp_image_copy_yuv420p_to_xrgb(h264->data, h264->scanline, 0, 0,
|
||||
h264->width, h264->height, pYUVData, pSystemBuffer->iStride, 0, 0);
|
||||
h264->iStride[0] = pSystemBuffer->iStride[0];
|
||||
h264->iStride[1] = pSystemBuffer->iStride[1];
|
||||
h264->iStride[2] = pSystemBuffer->iStride[1];
|
||||
|
||||
h264->width = pSystemBuffer->iWidth;
|
||||
h264->height = pSystemBuffer->iHeight;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -404,8 +269,7 @@ struct _H264_CONTEXT_LIBAVCODEC
|
||||
};
|
||||
typedef struct _H264_CONTEXT_LIBAVCODEC H264_CONTEXT_LIBAVCODEC;
|
||||
|
||||
static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize)
|
||||
{
|
||||
int status;
|
||||
int gotFrame = 0;
|
||||
@@ -425,27 +289,29 @@ static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcS
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])\n",
|
||||
status, gotFrame, sys->videoFrame->width, sys->videoFrame->height,
|
||||
sys->videoFrame->data[0], sys->videoFrame->linesize[0],
|
||||
sys->videoFrame->data[1], sys->videoFrame->linesize[1],
|
||||
sys->videoFrame->data[2], sys->videoFrame->linesize[2]);
|
||||
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
if (gotFrame)
|
||||
{
|
||||
if (g_H264DumpFrames)
|
||||
{
|
||||
h264_dump_yuv_data(sys->videoFrame->data, sys->videoFrame->width, sys->videoFrame->height, sys->videoFrame->linesize);
|
||||
}
|
||||
h264->pYUVData[0] = sys->videoFrame->data[0];
|
||||
h264->pYUVData[1] = sys->videoFrame->data[1];
|
||||
h264->pYUVData[2] = sys->videoFrame->data[2];
|
||||
|
||||
if (h264_prepare_rgb_buffer(h264, sys->videoFrame->width, sys->videoFrame->height) < 0)
|
||||
return -1;
|
||||
h264->iStride[0] = sys->videoFrame->linesize[0];
|
||||
h264->iStride[1] = sys->videoFrame->linesize[1];
|
||||
h264->iStride[2] = sys->videoFrame->linesize[2];
|
||||
|
||||
freerdp_image_copy_yuv420p_to_xrgb(h264->data, h264->scanline, 0, 0,
|
||||
h264->width, h264->height, sys->videoFrame->data, sys->videoFrame->linesize, 0, 0);
|
||||
h264->width = sys->videoFrame->width;
|
||||
h264->height = sys->videoFrame->height;
|
||||
}
|
||||
else
|
||||
return -2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -554,45 +420,68 @@ static H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec =
|
||||
#endif
|
||||
|
||||
int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nDstHeight, RDPGFX_RECT16* regionRects, int numRegionRects)
|
||||
{
|
||||
int index;
|
||||
int status;
|
||||
int* iStride;
|
||||
BYTE* pDstData;
|
||||
UINT32 UncompressedSize;
|
||||
BYTE* pDstPoint;
|
||||
prim_size_t roi;
|
||||
BYTE** pYUVData;
|
||||
int width, height;
|
||||
BYTE* pYUVPoint[3];
|
||||
RDPGFX_RECT16* rect;
|
||||
int UncompressedSize;
|
||||
primitives_t *prims = primitives_get();
|
||||
|
||||
if (!h264)
|
||||
return -1;
|
||||
|
||||
#if 0
|
||||
printf("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, nXDst=%d, nYDst=%d, nWidth=%d, nHeight=%d)\n",
|
||||
pSrcData, SrcSize, *ppDstData, nDstStep, nXDst, nYDst, nWidth, nHeight);
|
||||
printf("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, nDstHeight=%d, numRegionRects=%d\n",
|
||||
pSrcData, SrcSize, *ppDstData, nDstStep, nDstHeight, numRegionRects);
|
||||
#endif
|
||||
|
||||
/* Allocate a destination buffer (if needed). */
|
||||
|
||||
UncompressedSize = nWidth * nHeight * 4;
|
||||
|
||||
if (UncompressedSize == 0)
|
||||
if (!(pDstData = *ppDstData))
|
||||
return -1;
|
||||
|
||||
pDstData = *ppDstData;
|
||||
if ((status = h264->subsystem->Decompress(h264, pSrcData, SrcSize)) < 0)
|
||||
return status;
|
||||
|
||||
if (!pDstData)
|
||||
UncompressedSize = h264->width * h264->height * 4;
|
||||
|
||||
if (UncompressedSize > (nDstStep * nDstHeight))
|
||||
return -1;
|
||||
|
||||
pYUVData = h264->pYUVData;
|
||||
iStride = h264->iStride;
|
||||
|
||||
for (index = 0; index < numRegionRects; index++)
|
||||
{
|
||||
pDstData = (BYTE*) malloc(UncompressedSize);
|
||||
rect = &(regionRects[index]);
|
||||
|
||||
if (!pDstData)
|
||||
return -1;
|
||||
width = rect->right - rect->left;
|
||||
height = rect->bottom - rect->top;
|
||||
|
||||
pDstPoint = pDstData + rect->top * nDstStep + rect->left * 4;
|
||||
pYUVPoint[0] = pYUVData[0] + rect->top * iStride[0] + rect->left;
|
||||
|
||||
*ppDstData = pDstData;
|
||||
pYUVPoint[1] = pYUVData[1] + rect->top/2 * iStride[1] + rect->left/2;
|
||||
pYUVPoint[2] = pYUVData[2] + rect->top/2 * iStride[2] + rect->left/2;
|
||||
|
||||
#if 0
|
||||
printf("regionRect: x: %d y: %d width: %d height: %d\n",
|
||||
rect->left, rect->top, width, height);
|
||||
#endif
|
||||
|
||||
roi.width = width;
|
||||
roi.height = height;
|
||||
|
||||
prims->YUV420ToRGB_8u_P3AC4R((const BYTE**) pYUVPoint, iStride, pDstPoint, nDstStep, &roi);
|
||||
}
|
||||
|
||||
if (g_H264DumpFrames)
|
||||
{
|
||||
h264_dump_h264_data(pSrcData, SrcSize);
|
||||
}
|
||||
|
||||
return h264->subsystem->Decompress(h264, pSrcData, SrcSize,
|
||||
pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
|
||||
@@ -633,9 +522,6 @@ H264_CONTEXT* h264_context_new(BOOL Compressor)
|
||||
|
||||
h264->subsystem = &g_Subsystem_dummy;
|
||||
|
||||
if (h264_prepare_rgb_buffer(h264, 256, 256) < 0)
|
||||
return NULL;
|
||||
|
||||
if (!h264_context_init(h264))
|
||||
{
|
||||
free(h264);
|
||||
@@ -650,8 +536,6 @@ void h264_context_free(H264_CONTEXT* h264)
|
||||
{
|
||||
if (h264)
|
||||
{
|
||||
free(h264->data);
|
||||
|
||||
h264->subsystem->Uninit(h264);
|
||||
|
||||
free(h264);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Bitmap Decompression
|
||||
* Interleaved RLE Bitmap Codec
|
||||
*
|
||||
* Copyright 2011 Jay Sorg <jay.sorg@gmail.com>
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,14 +21,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
#include "planar.h"
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/interleaved.h>
|
||||
|
||||
/*
|
||||
RLE Compressed Bitmap Stream (RLE_BITMAP_STREAM)
|
||||
@@ -242,57 +235,104 @@ static INLINE UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* adv
|
||||
#define RLEEXTRA
|
||||
#include "include/bitmap.c"
|
||||
|
||||
/**
|
||||
* bitmap decompression routine
|
||||
*/
|
||||
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
|
||||
int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
{
|
||||
int status;
|
||||
BYTE* TmpBfr;
|
||||
BOOL vFlip;
|
||||
int scanline;
|
||||
BYTE* pDstData;
|
||||
UINT32 BufferSize;
|
||||
int dstBitsPerPixel;
|
||||
int dstBytesPerPixel;
|
||||
|
||||
if (srcBpp == 16 && dstBpp == 16)
|
||||
{
|
||||
TmpBfr = (BYTE*) _aligned_malloc(width * height * 2, 16);
|
||||
RleDecompress16to16(srcData, size, TmpBfr, width * 2, width, height);
|
||||
freerdp_bitmap_flip(TmpBfr, dstData, width * 2, height);
|
||||
_aligned_free(TmpBfr);
|
||||
}
|
||||
else if (srcBpp == 32 && dstBpp == 32)
|
||||
{
|
||||
pDstData = dstData;
|
||||
pDstData = *ppDstData;
|
||||
dstBitsPerPixel = FREERDP_PIXEL_FORMAT_DEPTH(DstFormat);
|
||||
dstBytesPerPixel = (FREERDP_PIXEL_FORMAT_BPP(DstFormat) / 8);
|
||||
vFlip = FREERDP_PIXEL_FORMAT_FLIP(DstFormat) ? TRUE : FALSE;
|
||||
|
||||
status = planar_decompress(NULL, srcData, size, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
if (!interleaved)
|
||||
return -1;
|
||||
|
||||
if (status < 0)
|
||||
return FALSE;
|
||||
}
|
||||
else if (srcBpp == 15 && dstBpp == 15)
|
||||
if (bpp == 24)
|
||||
{
|
||||
TmpBfr = (BYTE*) _aligned_malloc(width * height * 2, 16);
|
||||
RleDecompress16to16(srcData, size, TmpBfr, width * 2, width, height);
|
||||
freerdp_bitmap_flip(TmpBfr, dstData, width * 2, height);
|
||||
_aligned_free(TmpBfr);
|
||||
scanline = nWidth * 3;
|
||||
BufferSize = scanline * nHeight;
|
||||
|
||||
if (BufferSize > interleaved->FlipSize)
|
||||
{
|
||||
interleaved->FlipBuffer = _aligned_realloc(interleaved->FlipBuffer, BufferSize, 16);
|
||||
interleaved->FlipSize = BufferSize;
|
||||
}
|
||||
|
||||
if (!interleaved->FlipBuffer)
|
||||
return -1;
|
||||
|
||||
RleDecompress24to24(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
}
|
||||
else if (srcBpp == 8 && dstBpp == 8)
|
||||
else if ((bpp == 16) || (bpp == 15))
|
||||
{
|
||||
TmpBfr = (BYTE*) _aligned_malloc(width * height, 16);
|
||||
RleDecompress8to8(srcData, size, TmpBfr, width, width, height);
|
||||
freerdp_bitmap_flip(TmpBfr, dstData, width, height);
|
||||
_aligned_free(TmpBfr);
|
||||
scanline = nWidth * 2;
|
||||
BufferSize = scanline * nHeight;
|
||||
|
||||
if (BufferSize > interleaved->FlipSize)
|
||||
{
|
||||
interleaved->FlipBuffer = _aligned_realloc(interleaved->FlipBuffer, BufferSize, 16);
|
||||
interleaved->FlipSize = BufferSize;
|
||||
}
|
||||
|
||||
if (!interleaved->FlipBuffer)
|
||||
return -1;
|
||||
|
||||
RleDecompress16to16(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
}
|
||||
else if (srcBpp == 24 && dstBpp == 24)
|
||||
else if (bpp == 8)
|
||||
{
|
||||
TmpBfr = (BYTE*) _aligned_malloc(width * height * 3, 16);
|
||||
RleDecompress24to24(srcData, size, TmpBfr, width * 3, width, height);
|
||||
freerdp_bitmap_flip(TmpBfr, dstData, width * 3, height);
|
||||
_aligned_free(TmpBfr);
|
||||
scanline = nWidth;
|
||||
BufferSize = scanline * nHeight;
|
||||
|
||||
if (BufferSize > interleaved->FlipSize)
|
||||
{
|
||||
interleaved->FlipBuffer = _aligned_realloc(interleaved->FlipBuffer, BufferSize, 16);
|
||||
interleaved->FlipSize = BufferSize;
|
||||
}
|
||||
|
||||
if (!interleaved->FlipBuffer)
|
||||
return -1;
|
||||
|
||||
RleDecompress8to8(pSrcData, SrcSize, interleaved->FlipBuffer, scanline, nWidth, nHeight);
|
||||
freerdp_bitmap_flip(interleaved->FlipBuffer, pDstData, scanline, nHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
|
||||
{
|
||||
BITMAP_INTERLEAVED_CONTEXT* interleaved;
|
||||
|
||||
interleaved = (BITMAP_INTERLEAVED_CONTEXT*) calloc(1, sizeof(BITMAP_INTERLEAVED_CONTEXT));
|
||||
|
||||
if (interleaved)
|
||||
{
|
||||
interleaved->FlipSize = 64 * 64 * 3;
|
||||
interleaved->FlipBuffer = _aligned_malloc(interleaved->FlipSize, 16);
|
||||
}
|
||||
|
||||
return interleaved;
|
||||
}
|
||||
|
||||
void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
|
||||
{
|
||||
if (!interleaved)
|
||||
return;
|
||||
|
||||
_aligned_free(interleaved->FlipBuffer);
|
||||
|
||||
free(interleaved);
|
||||
}
|
||||
@@ -24,17 +24,65 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
|
||||
#include <freerdp/primitives.h>
|
||||
#include <freerdp/utils/debug.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/primitives.h>
|
||||
#include <freerdp/codec/planar.h>
|
||||
|
||||
#include "planar.h"
|
||||
static int planar_skip_plane_rle(const BYTE* pSrcData, UINT32 SrcSize, int nWidth, int nHeight)
|
||||
{
|
||||
int x, y;
|
||||
int cRawBytes;
|
||||
int nRunLength;
|
||||
BYTE controlByte;
|
||||
const BYTE* pRLE = pSrcData;
|
||||
const BYTE* pEnd = &pSrcData[SrcSize];
|
||||
|
||||
static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
for (y = 0; y < nHeight; y++)
|
||||
{
|
||||
for (x = 0; x < nWidth; )
|
||||
{
|
||||
if (pRLE >= pEnd)
|
||||
return -1;
|
||||
|
||||
controlByte = *pRLE++;
|
||||
|
||||
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
|
||||
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
|
||||
|
||||
if (nRunLength == 1)
|
||||
{
|
||||
nRunLength = cRawBytes + 16;
|
||||
cRawBytes = 0;
|
||||
}
|
||||
else if (nRunLength == 2)
|
||||
{
|
||||
nRunLength = cRawBytes + 32;
|
||||
cRawBytes = 0;
|
||||
}
|
||||
|
||||
pRLE += cRawBytes;
|
||||
x += cRawBytes;
|
||||
cRawBytes = 0;
|
||||
|
||||
x += nRunLength;
|
||||
nRunLength = 0;
|
||||
|
||||
if (x > nWidth)
|
||||
return -1;
|
||||
|
||||
if (pRLE > pEnd)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) (pRLE - pSrcData);
|
||||
}
|
||||
|
||||
static int planar_decompress_plane_rle(const BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip)
|
||||
{
|
||||
int x, y;
|
||||
BYTE* srcp;
|
||||
BYTE* dstp;
|
||||
UINT32 pixel;
|
||||
int cRawBytes;
|
||||
@@ -44,8 +92,8 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs
|
||||
BYTE controlByte;
|
||||
BYTE* currentScanline;
|
||||
BYTE* previousScanline;
|
||||
const BYTE* srcp = pSrcData;
|
||||
|
||||
srcp = pSrcData;
|
||||
dstp = pDstData;
|
||||
previousScanline = NULL;
|
||||
|
||||
@@ -168,13 +216,16 @@ static int planar_decompress_plane_rle(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs
|
||||
return (int) (srcp - pSrcData);
|
||||
}
|
||||
|
||||
static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData,
|
||||
int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, int nChannel, BOOL vFlip)
|
||||
static int planar_decompress_planes_raw(const BYTE* pSrcData[4], int nSrcStep, BYTE* pDstData,
|
||||
int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BOOL alpha, BOOL vFlip)
|
||||
{
|
||||
int x, y;
|
||||
int beg, end, inc;
|
||||
BYTE* dstp = NULL;
|
||||
BYTE* srcp = pSrcData;
|
||||
BYTE* pRGB = pDstData;
|
||||
const BYTE* pR = pSrcData[0];
|
||||
const BYTE* pG = pSrcData[1];
|
||||
const BYTE* pB = pSrcData[2];
|
||||
const BYTE* pA = pSrcData[3];
|
||||
|
||||
if (vFlip)
|
||||
{
|
||||
@@ -189,30 +240,63 @@ static int planar_decompress_plane_raw(BYTE* pSrcData, UINT32 SrcSize, BYTE* pDs
|
||||
inc = 1;
|
||||
}
|
||||
|
||||
for (y = beg; y != end; y += inc)
|
||||
if (alpha)
|
||||
{
|
||||
dstp = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4) + nChannel];
|
||||
|
||||
for (x = 0; x < nWidth; x++)
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
*dstp = *srcp;
|
||||
dstp += 4;
|
||||
srcp++;
|
||||
pRGB = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
*pRGB++ = *pB++;
|
||||
*pRGB++ = *pG++;
|
||||
*pRGB++ = *pR++;
|
||||
*pRGB++ = *pA++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = beg; y != end; y += inc)
|
||||
{
|
||||
pRGB = &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)];
|
||||
|
||||
for (x = 0; x < nWidth; x++)
|
||||
{
|
||||
*pRGB++ = *pB++;
|
||||
*pRGB++ = *pG++;
|
||||
*pRGB++ = *pR++;
|
||||
*pRGB++ = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (int) (srcp - pSrcData);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcSize,
|
||||
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight)
|
||||
{
|
||||
BOOL cs;
|
||||
BOOL rle;
|
||||
UINT32 cll;
|
||||
BOOL alpha;
|
||||
int status;
|
||||
BYTE* srcp;
|
||||
BOOL vFlip;
|
||||
int subSize;
|
||||
int subWidth;
|
||||
int subHeight;
|
||||
int planeSize;
|
||||
BYTE* pDstData;
|
||||
int rleSizes[4];
|
||||
int rawSizes[4];
|
||||
int rawWidths[4];
|
||||
int rawHeights[4];
|
||||
BYTE FormatHeader;
|
||||
BYTE* pDstData = NULL;
|
||||
const BYTE* planes[4];
|
||||
UINT32 UncompressedSize;
|
||||
const primitives_t* prims = primitives_get();
|
||||
|
||||
if ((nWidth * nHeight) <= 0)
|
||||
return -1;
|
||||
@@ -234,124 +318,262 @@ int planar_decompress(BITMAP_PLANAR_CONTEXT* planar, BYTE* pSrcData, UINT32 SrcS
|
||||
*ppDstData = pDstData;
|
||||
}
|
||||
|
||||
FormatHeader = *srcp;
|
||||
srcp++;
|
||||
FormatHeader = *srcp++;
|
||||
|
||||
/* AlphaPlane */
|
||||
cll = (FormatHeader & PLANAR_FORMAT_HEADER_CLL_MASK);
|
||||
cs = (FormatHeader & PLANAR_FORMAT_HEADER_CS) ? TRUE : FALSE;
|
||||
rle = (FormatHeader & PLANAR_FORMAT_HEADER_RLE) ? TRUE : FALSE;
|
||||
alpha = (FormatHeader & PLANAR_FORMAT_HEADER_NA) ? FALSE : TRUE;
|
||||
|
||||
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
|
||||
//printf("CLL: %d CS: %d RLE: %d ALPHA: %d\n", cll, cs, rle, alpha);
|
||||
|
||||
if (!cll && cs)
|
||||
return -1; /* Chroma subsampling requires YCoCg */
|
||||
|
||||
subWidth = (nWidth / 2) + (nWidth % 2);
|
||||
subHeight = (nHeight / 2) + (nHeight % 2);
|
||||
|
||||
planeSize = nWidth * nHeight;
|
||||
subSize = subWidth * subHeight;
|
||||
|
||||
if (!cs)
|
||||
{
|
||||
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||
rawSizes[0] = planeSize; /* LumaOrRedPlane */
|
||||
rawWidths[0] = nWidth;
|
||||
rawHeights[0] = nHeight;
|
||||
|
||||
rawSizes[1] = planeSize; /* OrangeChromaOrGreenPlane */
|
||||
rawWidths[1] = nWidth;
|
||||
rawHeights[1] = nHeight;
|
||||
|
||||
rawSizes[2] = planeSize; /* GreenChromaOrBluePlane */
|
||||
rawWidths[2] = nWidth;
|
||||
rawHeights[2] = nHeight;
|
||||
|
||||
rawSizes[3] = planeSize; /* AlphaPlane */
|
||||
rawWidths[3] = nWidth;
|
||||
rawHeights[3] = nHeight;
|
||||
}
|
||||
else /* Chroma Subsampling */
|
||||
{
|
||||
rawSizes[0] = planeSize; /* LumaOrRedPlane */
|
||||
rawWidths[0] = nWidth;
|
||||
rawHeights[0] = nHeight;
|
||||
|
||||
rawSizes[1] = subSize; /* OrangeChromaOrGreenPlane */
|
||||
rawWidths[1] = subWidth;
|
||||
rawHeights[1] = subHeight;
|
||||
|
||||
rawSizes[2] = subSize; /* GreenChromaOrBluePlane */
|
||||
rawWidths[2] = subWidth;
|
||||
rawHeights[2] = subHeight;
|
||||
|
||||
rawSizes[3] = planeSize; /* AlphaPlane */
|
||||
rawWidths[3] = nWidth;
|
||||
rawHeights[3] = nHeight;
|
||||
}
|
||||
|
||||
if (!rle) /* RAW */
|
||||
{
|
||||
if (alpha)
|
||||
{
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip);
|
||||
planes[3] = srcp; /* AlphaPlane */
|
||||
planes[0] = planes[3] + rawSizes[3]; /* LumaOrRedPlane */
|
||||
planes[1] = planes[0] + rawSizes[0]; /* OrangeChromaOrGreenPlane */
|
||||
planes[2] = planes[1] + rawSizes[1]; /* GreenChromaOrBluePlane */
|
||||
|
||||
if (status < 0)
|
||||
if ((planes[2] + rawSizes[2]) > &pSrcData[SrcSize])
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
if ((SrcSize - (srcp - pSrcData)) < (planeSize * 3))
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
planes[0] = srcp; /* LumaOrRedPlane */
|
||||
planes[1] = planes[0] + rawSizes[0]; /* OrangeChromaOrGreenPlane */
|
||||
planes[2] = planes[1] + rawSizes[1]; /* GreenChromaOrBluePlane */
|
||||
|
||||
if ((planes[2] + rawSizes[2]) > &pSrcData[SrcSize])
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
|
||||
else /* RLE */
|
||||
{
|
||||
/* LumaOrRedPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
|
||||
/* OrangeChromaOrGreenPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
|
||||
/* GreenChromeOrBluePlane */
|
||||
|
||||
status = planar_decompress_plane_rle(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* LumaOrRedPlane */
|
||||
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
|
||||
/* OrangeChromaOrGreenPlane */
|
||||
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
|
||||
/* GreenChromeOrBluePlane */
|
||||
|
||||
status = planar_decompress_plane_raw(srcp, SrcSize - (srcp - pSrcData),
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
srcp += status;
|
||||
srcp++;
|
||||
}
|
||||
|
||||
if (FormatHeader & PLANAR_FORMAT_HEADER_CLL_MASK)
|
||||
{
|
||||
/* The data is in YCoCg colorspace rather than RGB. */
|
||||
if (FormatHeader & PLANAR_FORMAT_HEADER_CS)
|
||||
if (alpha)
|
||||
{
|
||||
static BOOL been_warned = FALSE;
|
||||
if (!been_warned)
|
||||
DEBUG_WARN( "Chroma-Subsampling is not implemented.\n");
|
||||
been_warned = TRUE;
|
||||
planes[3] = srcp;
|
||||
rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - (planes[3] - pSrcData),
|
||||
rawWidths[3], rawHeights[3]); /* AlphaPlane */
|
||||
|
||||
if (rleSizes[3] < 0)
|
||||
return -1;
|
||||
|
||||
planes[0] = planes[3] + rleSizes[3];
|
||||
rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData),
|
||||
rawWidths[0], rawHeights[0]); /* RedPlane */
|
||||
|
||||
if (rleSizes[0] < 0)
|
||||
return -1;
|
||||
|
||||
planes[1] = planes[0] + rleSizes[0];
|
||||
rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData),
|
||||
rawWidths[1], rawHeights[1]); /* GreenPlane */
|
||||
|
||||
if (rleSizes[1] < 1)
|
||||
return -1;
|
||||
|
||||
planes[2] = planes[1] + rleSizes[1];
|
||||
rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData),
|
||||
rawWidths[2], rawHeights[2]); /* BluePlane */
|
||||
|
||||
if (rleSizes[2] < 1)
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOL alpha;
|
||||
int cll;
|
||||
planes[0] = srcp;
|
||||
rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData),
|
||||
rawWidths[0], rawHeights[0]); /* RedPlane */
|
||||
|
||||
alpha = (FormatHeader & PLANAR_FORMAT_HEADER_NA) ? FALSE : TRUE;
|
||||
cll = FormatHeader & PLANAR_FORMAT_HEADER_CLL_MASK;
|
||||
primitives_get()->YCoCgRToRGB_8u_AC4R(
|
||||
pDstData, nDstStep, pDstData, nDstStep,
|
||||
nWidth, nHeight, cll, alpha, FALSE);
|
||||
if (rleSizes[0] < 0)
|
||||
return -1;
|
||||
|
||||
planes[1] = planes[0] + rleSizes[0];
|
||||
rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData),
|
||||
rawWidths[1], rawHeights[1]); /* GreenPlane */
|
||||
|
||||
if (rleSizes[1] < 1)
|
||||
return -1;
|
||||
|
||||
planes[2] = planes[1] + rleSizes[1];
|
||||
rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData),
|
||||
rawWidths[2], rawHeights[2]); /* BluePlane */
|
||||
|
||||
if (rleSizes[2] < 1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cll) /* RGB */
|
||||
{
|
||||
if (!rle) /* RAW */
|
||||
{
|
||||
if (alpha)
|
||||
{
|
||||
planar_decompress_planes_raw(planes, nWidth, pDstData, nDstStep,
|
||||
nXDst, nYDst, nWidth, nHeight, alpha, vFlip);
|
||||
|
||||
srcp += rawSizes[0] + rawSizes[1] + rawSizes[2] + rawSizes[3];
|
||||
}
|
||||
else /* NoAlpha */
|
||||
{
|
||||
planar_decompress_planes_raw(planes, nWidth, pDstData, nDstStep,
|
||||
nXDst, nYDst, nWidth, nHeight, alpha, vFlip);
|
||||
|
||||
srcp += rawSizes[0] + rawSizes[1] + rawSizes[2];
|
||||
}
|
||||
|
||||
if ((SrcSize - (srcp - pSrcData)) == 1)
|
||||
srcp++; /* pad */
|
||||
}
|
||||
else /* RLE */
|
||||
{
|
||||
if (alpha)
|
||||
{
|
||||
status = planar_decompress_plane_rle(planes[3], rleSizes[3],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip); /* AlphaPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[0], rleSizes[0],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); /* RedPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[1], rleSizes[1],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); /* GreenPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[2], rleSizes[2],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); /* BluePlane */
|
||||
|
||||
srcp += rleSizes[0] + rleSizes[1] + rleSizes[2] + rleSizes[3];
|
||||
}
|
||||
else /* NoAlpha */
|
||||
{
|
||||
status = planar_decompress_plane_rle(planes[0], rleSizes[0],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); /* RedPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[1], rleSizes[1],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); /* GreenPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[2], rleSizes[2],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); /* BluePlane */
|
||||
|
||||
srcp += rleSizes[0] + rleSizes[1] + rleSizes[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* YCoCg */
|
||||
{
|
||||
if (cs)
|
||||
{
|
||||
fprintf(stderr, "Chroma subsampling unimplemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!rle) /* RAW */
|
||||
{
|
||||
if (alpha)
|
||||
{
|
||||
planar_decompress_planes_raw(planes, nWidth, pDstData, nDstStep,
|
||||
nXDst, nYDst, nWidth, nHeight, alpha, vFlip);
|
||||
|
||||
srcp += rawSizes[0] + rawSizes[1] + rawSizes[2] + rawSizes[3];
|
||||
}
|
||||
else /* NoAlpha */
|
||||
{
|
||||
planar_decompress_planes_raw(planes, nWidth, pDstData, nDstStep,
|
||||
nXDst, nYDst, nWidth, nHeight, alpha, vFlip);
|
||||
|
||||
srcp += rawSizes[0] + rawSizes[1] + rawSizes[2];
|
||||
}
|
||||
|
||||
if ((SrcSize - (srcp - pSrcData)) == 1)
|
||||
srcp++; /* pad */
|
||||
}
|
||||
else /* RLE */
|
||||
{
|
||||
if (alpha)
|
||||
{
|
||||
status = planar_decompress_plane_rle(planes[3], rleSizes[3],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 3, vFlip); /* AlphaPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[0], rleSizes[0],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); /* LumaPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[1], rleSizes[1],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); /* OrangeChromaPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[2], rleSizes[2],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); /* GreenChromaPlane */
|
||||
|
||||
srcp += rleSizes[0] + rleSizes[1] + rleSizes[2] + rleSizes[3];
|
||||
}
|
||||
else /* NoAlpha */
|
||||
{
|
||||
status = planar_decompress_plane_rle(planes[0], rleSizes[0],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 2, vFlip); /* LumaPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[1], rleSizes[1],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 1, vFlip); /* OrangeChromaPlane */
|
||||
|
||||
status = planar_decompress_plane_rle(planes[2], rleSizes[2],
|
||||
pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, 0, vFlip); /* GreenChromaPlane */
|
||||
|
||||
srcp += rleSizes[0] + rleSizes[1] + rleSizes[2];
|
||||
}
|
||||
}
|
||||
|
||||
prims->YCoCgToRGB_8u_AC4R(pDstData, nDstStep, pDstData, nDstStep, nWidth, nHeight, cll, alpha, FALSE);
|
||||
}
|
||||
|
||||
status = (SrcSize == (srcp - pSrcData)) ? 1 : -1;
|
||||
|
||||
return status;
|
||||
|
||||
@@ -897,10 +897,36 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB
|
||||
return sign ? -mag : mag;
|
||||
}
|
||||
|
||||
int progressive_rfx_upgrade_state_finish(RFX_PROGRESSIVE_UPGRADE_STATE* state)
|
||||
{
|
||||
int pad;
|
||||
wBitStream* srl;
|
||||
wBitStream* raw;
|
||||
|
||||
srl = state->srl;
|
||||
raw = state->raw;
|
||||
|
||||
/* Read trailing bits from RAW/SRL bit streams */
|
||||
|
||||
pad = (raw->position % 8) ? (8 - (raw->position % 8)) : 0;
|
||||
|
||||
if (pad)
|
||||
BitStream_Shift(raw, pad);
|
||||
|
||||
pad = (srl->position % 8) ? (8 - (srl->position % 8)) : 0;
|
||||
|
||||
if (pad)
|
||||
BitStream_Shift(srl, pad);
|
||||
|
||||
if (BitStream_GetRemainingLength(srl) == 8)
|
||||
BitStream_Shift(srl, 8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer,
|
||||
INT16* sign, int length, UINT32 shift, UINT32 bitPos, UINT32 numBits)
|
||||
{
|
||||
int pad;
|
||||
int index;
|
||||
INT16 input;
|
||||
wBitStream* srl;
|
||||
@@ -923,21 +949,6 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b
|
||||
buffer[index] += (input << shift);
|
||||
}
|
||||
|
||||
/* This is the last band, read padding bits from RAW and SRL bit streams */
|
||||
|
||||
pad = (raw->position % 8) ? (8 - (raw->position % 8)) : 0;
|
||||
|
||||
if (pad)
|
||||
BitStream_Shift(raw, pad);
|
||||
|
||||
pad = (srl->position % 8) ? (8 - (srl->position % 8)) : 0;
|
||||
|
||||
if (pad)
|
||||
BitStream_Shift(srl, pad);
|
||||
|
||||
if (BitStream_GetRemainingLength(srl) == 8)
|
||||
BitStream_Shift(srl, 8);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -966,10 +977,11 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b
|
||||
/* sign == 0, read from srl */
|
||||
|
||||
input = progressive_rfx_srl_read(state, numBits);
|
||||
|
||||
sign[index] = input;
|
||||
}
|
||||
|
||||
buffer[index] += (input << shift);
|
||||
sign[index] = input;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -1014,6 +1026,7 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP
|
||||
|
||||
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);
|
||||
|
||||
aRawLen = (state.raw->position + 7) / 8;
|
||||
aSrlLen = (state.srl->position + 7) / 8;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/bitmap.h>
|
||||
#include <freerdp/codec/planar.h>
|
||||
|
||||
/**
|
||||
* Experimental Case 01: 64x64 (32bpp)
|
||||
@@ -2864,16 +2865,6 @@ const BYTE TEST_RDP6_SCANLINES_DELTA_2C_ENCODED_UNSIGNED[3][6] =
|
||||
{ 0x01, 0x67, 0x8B, 0xA3, 0x78, 0xAF }
|
||||
};
|
||||
|
||||
#include "../planar.h"
|
||||
|
||||
static unsigned long next = 1;
|
||||
|
||||
static int simple_rand(void)
|
||||
{
|
||||
next = next * 1103515245 + 12345;
|
||||
return ((unsigned int) (next / 65536) % 32768);
|
||||
}
|
||||
|
||||
static void fill_bitmap_alpha_channel(BYTE* data, int width, int height, BYTE value)
|
||||
{
|
||||
int i, j;
|
||||
@@ -3095,9 +3086,10 @@ int test_individual_planes_encoding_rle()
|
||||
|
||||
int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
{
|
||||
int i, j;
|
||||
int i;
|
||||
int dstSize;
|
||||
UINT32 format;
|
||||
BYTE* pDstData;
|
||||
HCLRCONV clrconv;
|
||||
DWORD planarFlags;
|
||||
BYTE* srcBitmap32;
|
||||
@@ -3105,7 +3097,6 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
int width, height;
|
||||
BYTE* blackBitmap;
|
||||
BYTE* whiteBitmap;
|
||||
BYTE* randomBitmap;
|
||||
BYTE* compressedBitmap;
|
||||
BYTE* decompressedBitmap;
|
||||
BITMAP_PLANAR_CONTEXT* planar;
|
||||
@@ -3147,7 +3138,10 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
decompressedBitmap = (BYTE*) malloc(width * height * 4);
|
||||
ZeroMemory(decompressedBitmap, width * height * 4);
|
||||
|
||||
if (!bitmap_decompress(compressedBitmap, decompressedBitmap, width, height, dstSize, 32, 32))
|
||||
pDstData = decompressedBitmap;
|
||||
|
||||
if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0)
|
||||
{
|
||||
printf("failed to decompress white bitmap: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
@@ -3187,7 +3181,10 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
decompressedBitmap = (BYTE*) malloc(width * height * 4);
|
||||
ZeroMemory(decompressedBitmap, width * height * 4);
|
||||
|
||||
if (!bitmap_decompress(compressedBitmap, decompressedBitmap, width, height, dstSize, 32, 32))
|
||||
pDstData = decompressedBitmap;
|
||||
|
||||
if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0)
|
||||
{
|
||||
printf("failed to decompress black bitmap: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
@@ -3213,50 +3210,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
free(decompressedBitmap);
|
||||
}
|
||||
|
||||
for (i = 4; i < 64; i += 4)
|
||||
{
|
||||
width = i;
|
||||
height = i;
|
||||
|
||||
randomBitmap = (BYTE*) malloc(width * height * 4);
|
||||
|
||||
for (j = 0; j < width * height * 4; j++)
|
||||
{
|
||||
randomBitmap[j] = (BYTE) (simple_rand() % 256);
|
||||
}
|
||||
|
||||
fill_bitmap_alpha_channel(randomBitmap, width, height, 0x00);
|
||||
|
||||
compressedBitmap = freerdp_bitmap_compress_planar(planar, randomBitmap, format, width, height, width * 4, NULL, &dstSize);
|
||||
|
||||
decompressedBitmap = (BYTE*) malloc(width * height * 4);
|
||||
ZeroMemory(decompressedBitmap, width * height * 4);
|
||||
|
||||
if (!bitmap_decompress(compressedBitmap, decompressedBitmap, width, height, dstSize, 32, 32))
|
||||
{
|
||||
printf("failed to decompress random bitmap: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("success decompressing random bitmap: width: %d height: %d\n", width, height);
|
||||
}
|
||||
|
||||
if (memcmp(decompressedBitmap, randomBitmap, width * height * 4) != 0)
|
||||
{
|
||||
printf("random bitmap\n");
|
||||
winpr_HexDump(randomBitmap, width * height * 4);
|
||||
|
||||
printf("decompressed bitmap\n");
|
||||
winpr_HexDump(decompressedBitmap, width * height * 4);
|
||||
|
||||
printf("error decompressed random bitmap corrupted: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(compressedBitmap);
|
||||
free(decompressedBitmap);
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* Experimental Case 01 */
|
||||
|
||||
@@ -3269,7 +3223,10 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
decompressedBitmap = (BYTE*) malloc(width * height * 4);
|
||||
ZeroMemory(decompressedBitmap, width * height * 4);
|
||||
|
||||
if (!bitmap_decompress(compressedBitmap, decompressedBitmap, width, height, dstSize, 32, 32))
|
||||
pDstData = decompressedBitmap;
|
||||
|
||||
if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0)
|
||||
{
|
||||
printf("failed to decompress experimental bitmap 01: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
@@ -3310,7 +3267,10 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
decompressedBitmap = (BYTE*) malloc(width * height * 4);
|
||||
ZeroMemory(decompressedBitmap, width * height * 4);
|
||||
|
||||
if (!bitmap_decompress(compressedBitmap, decompressedBitmap, width, height, dstSize, 32, 32))
|
||||
pDstData = decompressedBitmap;
|
||||
|
||||
if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0)
|
||||
{
|
||||
printf("failed to decompress experimental bitmap 02: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
@@ -3357,7 +3317,10 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
|
||||
decompressedBitmap = (BYTE*) malloc(width * height * 4);
|
||||
ZeroMemory(decompressedBitmap, width * height * 4);
|
||||
|
||||
if (!bitmap_decompress(compressedBitmap, decompressedBitmap, width, height, dstSize, 32, 32))
|
||||
pDstData = decompressedBitmap;
|
||||
|
||||
if (planar_decompress(planar, compressedBitmap, dstSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32, width * 4, 0, 0, width, height) < 0)
|
||||
{
|
||||
printf("failed to decompress experimental bitmap 03: width: %d height: %d\n", width, height);
|
||||
return -1;
|
||||
|
||||
@@ -194,22 +194,22 @@ static int test_image_fill_quarter(BYTE* pDstData, int nDstStep, int nWidth, int
|
||||
case 1:
|
||||
x = nWidth / 2;
|
||||
y = nHeight / 2;
|
||||
width = nWidth;
|
||||
height = nHeight;
|
||||
width = nWidth / 2;
|
||||
height = nHeight /2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = nWidth / 2;
|
||||
y = 0;
|
||||
width = nWidth;
|
||||
height = nHeight / 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
x = 0;
|
||||
y = nHeight / 2;
|
||||
width = nWidth / 2;
|
||||
height = nHeight;
|
||||
height = nHeight /2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
x = nWidth / 2;
|
||||
y = 0;
|
||||
width = nWidth / 2;
|
||||
height = nHeight /2;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -220,6 +220,8 @@ static int test_image_fill_quarter(BYTE* pDstData, int nDstStep, int nWidth, int
|
||||
|
||||
static int test_image_fill_unused_quarters(BYTE* pDstData, int nDstStep, int nWidth, int nHeight, UINT32 color, int quarter)
|
||||
{
|
||||
return 1;
|
||||
|
||||
if (quarter == 0)
|
||||
{
|
||||
test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1);
|
||||
@@ -799,29 +801,21 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_memcmp_offset(const BYTE* mem1, const BYTE* mem2, int size)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
while ((index < size) && (*mem1 == *mem2))
|
||||
{
|
||||
mem1++;
|
||||
mem2++;
|
||||
index++;
|
||||
}
|
||||
|
||||
return (index == size) ? 1 : -index;
|
||||
}
|
||||
|
||||
static int test_memcmp_count(const BYTE* mem1, const BYTE* mem2, int size)
|
||||
static int test_memcmp_count(const BYTE* mem1, const BYTE* mem2, int size, int margin)
|
||||
{
|
||||
int error;
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
{
|
||||
if (*mem1 != *mem2)
|
||||
count++;
|
||||
{
|
||||
error = (*mem1 > *mem2) ? *mem1 - *mem2 : *mem2 - *mem1;
|
||||
|
||||
if (error > margin)
|
||||
count++;
|
||||
}
|
||||
|
||||
mem1++;
|
||||
mem2++;
|
||||
@@ -832,7 +826,6 @@ static int test_memcmp_count(const BYTE* mem1, const BYTE* mem2, int size)
|
||||
|
||||
int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], EGFX_SAMPLE_FILE bitmaps[4], int quarter, int count)
|
||||
{
|
||||
int cmp;
|
||||
int cnt;
|
||||
int pass;
|
||||
int size;
|
||||
@@ -878,18 +871,18 @@ int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE f
|
||||
break;
|
||||
|
||||
case 2:
|
||||
clippingRect.left = g_Width / 2;
|
||||
clippingRect.top = 0;
|
||||
clippingRect.right = g_Width;
|
||||
clippingRect.bottom = g_Height / 2;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
clippingRect.left = 0;
|
||||
clippingRect.top = g_Height / 2;
|
||||
clippingRect.right = g_Width / 2;
|
||||
clippingRect.bottom = g_Height;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
clippingRect.left = g_Width / 2;
|
||||
clippingRect.top = 0;
|
||||
clippingRect.right = g_Width;
|
||||
clippingRect.bottom = g_Height / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
for (index = 0; index < region->numTiles; index++)
|
||||
@@ -920,22 +913,13 @@ int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE f
|
||||
}
|
||||
|
||||
size = bitmaps[pass].size;
|
||||
cmp = test_memcmp_offset(g_DstData, bitmaps[pass].buffer, size);
|
||||
cnt = test_memcmp_count(g_DstData, bitmaps[pass].buffer, size);
|
||||
cnt = test_memcmp_count(g_DstData, bitmaps[pass].buffer, size, 1);
|
||||
|
||||
if (cmp <= 0)
|
||||
if (cnt)
|
||||
{
|
||||
float rate = ((float) cnt) / ((float) size) * 100.0f;
|
||||
|
||||
cmp *= -1;
|
||||
|
||||
printf("Progressive RemoteFX decompression failure\n");
|
||||
|
||||
printf("Actual, Expected (offset: %d diff: %d/%d = %.3f%%):\n",
|
||||
cmp, cnt, size, rate);
|
||||
|
||||
winpr_HexDump(&g_DstData[cmp], 16);
|
||||
winpr_HexDump(&bitmaps[pass].buffer[cmp], 16);
|
||||
printf("Actual, Expected (%d/%d = %.3f%%):\n", cnt, size, rate);
|
||||
}
|
||||
|
||||
//WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32);
|
||||
@@ -956,6 +940,9 @@ int test_progressive_ms_sample(char* ms_sample_path)
|
||||
g_Height = 1080;
|
||||
g_DstStep = g_Width * 4;
|
||||
|
||||
ZeroMemory(files, sizeof(files));
|
||||
ZeroMemory(bitmaps, sizeof(bitmaps));
|
||||
|
||||
status = test_progressive_load_files(ms_sample_path, files);
|
||||
|
||||
if (status < 0)
|
||||
@@ -966,7 +953,7 @@ int test_progressive_ms_sample(char* ms_sample_path)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
count = 1;
|
||||
count = 4;
|
||||
|
||||
progressive = progressive_context_new(FALSE);
|
||||
|
||||
@@ -978,7 +965,7 @@ int test_progressive_ms_sample(char* ms_sample_path)
|
||||
|
||||
if (1)
|
||||
{
|
||||
printf("Sample Image 1\n");
|
||||
printf("\nSample Image 1\n");
|
||||
test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000);
|
||||
test_progressive_decode(progressive, files[0][0], bitmaps[0][0], 0, count);
|
||||
test_progressive_decode(progressive, files[0][1], bitmaps[0][1], 1, count);
|
||||
@@ -986,11 +973,11 @@ int test_progressive_ms_sample(char* ms_sample_path)
|
||||
test_progressive_decode(progressive, files[0][3], bitmaps[0][3], 3, count);
|
||||
}
|
||||
|
||||
/* image 2 (incorrect) */
|
||||
/* image 2 */
|
||||
|
||||
if (0)
|
||||
{
|
||||
printf("Sample Image 2\n");
|
||||
printf("\nSample Image 2\n"); /* sample data is in incorrect order */
|
||||
test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000);
|
||||
test_progressive_decode(progressive, files[1][0], bitmaps[1][0], 0, count);
|
||||
test_progressive_decode(progressive, files[1][1], bitmaps[1][1], 1, count);
|
||||
@@ -1002,7 +989,7 @@ int test_progressive_ms_sample(char* ms_sample_path)
|
||||
|
||||
if (0)
|
||||
{
|
||||
printf("Sample Image 3\n");
|
||||
printf("\nSample Image 3\n"); /* sample data is in incorrect order */
|
||||
test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000);
|
||||
test_progressive_decode(progressive, files[2][0], bitmaps[2][0], 0, count);
|
||||
test_progressive_decode(progressive, files[2][1], bitmaps[2][1], 1, count);
|
||||
|
||||
@@ -79,6 +79,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
client.h
|
||||
server.c
|
||||
server.h
|
||||
codecs.c
|
||||
metrics.c
|
||||
capabilities.c
|
||||
capabilities.h
|
||||
|
||||
@@ -361,7 +361,15 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings)
|
||||
|
||||
header = rdp_capability_set_start(s);
|
||||
|
||||
drawingFlags |= DRAW_ALLOW_SKIP_ALPHA;
|
||||
if (settings->DrawAllowSkipAlpha)
|
||||
drawingFlags |= DRAW_ALLOW_SKIP_ALPHA;
|
||||
|
||||
if (settings->DrawAllowColorSubsampling)
|
||||
drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY;
|
||||
|
||||
if (settings->DrawAllowDynamicColorFidelity)
|
||||
drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; /* currently unimplemented */
|
||||
|
||||
/* While bitmap_decode.c now implements YCoCg, in turning it
|
||||
* on we have found Microsoft is inconsistent on whether to invert R & B.
|
||||
* And it's not only from one server to another; on Win7/2008R2, it appears
|
||||
@@ -370,9 +378,6 @@ void rdp_write_bitmap_capability_set(wStream* s, rdpSettings* settings)
|
||||
* will not send it. YCoCg is still needed for EGFX, but it at least
|
||||
* appears consistent in its use.
|
||||
*/
|
||||
/* drawingFlags |= DRAW_ALLOW_DYNAMIC_COLOR_FIDELITY; */
|
||||
/* YCoCg with chroma subsampling is not implemented in bitmap_decode.c. */
|
||||
/* drawingFlags |= DRAW_ALLOW_COLOR_SUBSAMPLING; */
|
||||
|
||||
if (settings->RdpVersion > 5)
|
||||
preferredBitsPerPixel = settings->ColorDepth;
|
||||
|
||||
157
libfreerdp/core/codecs.c
Normal file
157
libfreerdp/core/codecs.c
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* RDP Codecs
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "rdp.h"
|
||||
|
||||
#include <freerdp/codecs.h>
|
||||
|
||||
int freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags)
|
||||
{
|
||||
if (flags & FREERDP_CODEC_INTERLEAVED)
|
||||
{
|
||||
if (!codecs->interleaved)
|
||||
{
|
||||
codecs->interleaved = bitmap_interleaved_context_new(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_PLANAR)
|
||||
{
|
||||
if (!codecs->planar)
|
||||
{
|
||||
codecs->planar = freerdp_bitmap_planar_context_new(FALSE, 64, 64);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_NSCODEC)
|
||||
{
|
||||
if (!codecs->nsc)
|
||||
{
|
||||
codecs->nsc = nsc_context_new();
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_REMOTEFX)
|
||||
{
|
||||
if (!codecs->rfx)
|
||||
{
|
||||
codecs->rfx = rfx_context_new(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_CLEARCODEC)
|
||||
{
|
||||
if (!codecs->clear)
|
||||
{
|
||||
codecs->clear = clear_context_new(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_ALPHACODEC)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_PROGRESSIVE)
|
||||
{
|
||||
if (!codecs->progressive)
|
||||
{
|
||||
codecs->progressive = progressive_context_new(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & FREERDP_CODEC_H264)
|
||||
{
|
||||
if (!codecs->h264)
|
||||
{
|
||||
codecs->h264 = h264_context_new(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
rdpCodecs* codecs_new(rdpContext* context)
|
||||
{
|
||||
rdpCodecs* codecs;
|
||||
|
||||
codecs = (rdpCodecs*) calloc(1, sizeof(rdpCodecs));
|
||||
|
||||
if (codecs)
|
||||
{
|
||||
codecs->context = context;
|
||||
}
|
||||
|
||||
return codecs;
|
||||
}
|
||||
|
||||
void codecs_free(rdpCodecs* codecs)
|
||||
{
|
||||
if (!codecs)
|
||||
return;
|
||||
|
||||
if (codecs->rfx)
|
||||
{
|
||||
rfx_context_free(codecs->rfx);
|
||||
codecs->rfx = NULL;
|
||||
}
|
||||
|
||||
if (codecs->nsc)
|
||||
{
|
||||
nsc_context_free(codecs->nsc);
|
||||
codecs->nsc = NULL;
|
||||
}
|
||||
|
||||
if (codecs->h264)
|
||||
{
|
||||
h264_context_free(codecs->h264);
|
||||
codecs->h264 = NULL;
|
||||
}
|
||||
|
||||
if (codecs->clear)
|
||||
{
|
||||
clear_context_free(codecs->clear);
|
||||
codecs->clear = NULL;
|
||||
}
|
||||
|
||||
if (codecs->progressive)
|
||||
{
|
||||
progressive_context_free(codecs->progressive);
|
||||
codecs->progressive = NULL;
|
||||
}
|
||||
|
||||
if (codecs->planar)
|
||||
{
|
||||
freerdp_bitmap_planar_context_free(codecs->planar);
|
||||
codecs->planar = NULL;
|
||||
}
|
||||
|
||||
if (codecs->interleaved)
|
||||
{
|
||||
bitmap_interleaved_context_free(codecs->interleaved);
|
||||
codecs->interleaved = NULL;
|
||||
}
|
||||
|
||||
free(codecs);
|
||||
}
|
||||
|
||||
@@ -410,6 +410,7 @@ int freerdp_context_new(freerdp* instance)
|
||||
PubSub_AddEventTypes(context->pubSub, FreeRDP_Events, sizeof(FreeRDP_Events) / sizeof(wEventType));
|
||||
|
||||
context->metrics = metrics_new(context);
|
||||
context->codecs = codecs_new(context);
|
||||
|
||||
rdp = rdp_new(context);
|
||||
instance->input = rdp->input;
|
||||
@@ -465,6 +466,7 @@ void freerdp_context_free(freerdp* instance)
|
||||
PubSub_Free(instance->context->pubSub);
|
||||
|
||||
metrics_free(instance->context->metrics);
|
||||
codecs_free(instance->context->codecs);
|
||||
|
||||
free(instance->context);
|
||||
instance->context = NULL;
|
||||
|
||||
@@ -321,6 +321,10 @@ rdpSettings* freerdp_settings_new(DWORD flags)
|
||||
|
||||
settings->DrawGdiPlusEnabled = FALSE;
|
||||
|
||||
settings->DrawAllowSkipAlpha = TRUE;
|
||||
settings->DrawAllowColorSubsampling = FALSE;
|
||||
settings->DrawAllowDynamicColorFidelity = FALSE;
|
||||
|
||||
settings->FrameMarkerCommandEnabled = TRUE;
|
||||
settings->SurfaceFrameMarkerEnabled = TRUE;
|
||||
settings->BitmapCacheV3Enabled = FALSE;
|
||||
|
||||
@@ -793,55 +793,49 @@ void gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface
|
||||
|
||||
int tilenum = 0;
|
||||
|
||||
void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_command)
|
||||
void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
|
||||
{
|
||||
int i, j;
|
||||
int tx, ty;
|
||||
char* tile_bitmap;
|
||||
RFX_MESSAGE* message;
|
||||
rdpGdi* gdi = context->gdi;
|
||||
RFX_CONTEXT* rfx_context = (RFX_CONTEXT*) gdi->rfx_context;
|
||||
NSC_CONTEXT* nsc_context = (NSC_CONTEXT*) gdi->nsc_context;
|
||||
|
||||
DEBUG_GDI("destLeft %d destTop %d destRight %d destBottom %d "
|
||||
"bpp %d codecID %d width %d height %d length %d",
|
||||
surface_bits_command->destLeft, surface_bits_command->destTop,
|
||||
surface_bits_command->destRight, surface_bits_command->destBottom,
|
||||
surface_bits_command->bpp, surface_bits_command->codecID,
|
||||
surface_bits_command->width, surface_bits_command->height,
|
||||
surface_bits_command->bitmapDataLength);
|
||||
cmd->destLeft, cmd->destTop,
|
||||
cmd->destRight, cmd->destBottom,
|
||||
cmd->bpp, cmd->codecID,
|
||||
cmd->width, cmd->height,
|
||||
cmd->bitmapDataLength);
|
||||
|
||||
tile_bitmap = (char*) _aligned_malloc(32, 16);
|
||||
|
||||
if (!tile_bitmap)
|
||||
return;
|
||||
|
||||
if (surface_bits_command->codecID == RDP_CODEC_ID_REMOTEFX)
|
||||
if (cmd->codecID == RDP_CODEC_ID_REMOTEFX)
|
||||
{
|
||||
message = rfx_process_message(rfx_context,
|
||||
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX);
|
||||
|
||||
message = rfx_process_message(gdi->codecs->rfx,
|
||||
cmd->bitmapData, cmd->bitmapDataLength);
|
||||
|
||||
DEBUG_GDI("num_rects %d num_tiles %d", message->numRects, message->numTiles);
|
||||
|
||||
/* blit each tile */
|
||||
for (i = 0; i < message->numTiles; i++)
|
||||
{
|
||||
tx = message->tiles[i]->x + surface_bits_command->destLeft;
|
||||
ty = message->tiles[i]->y + surface_bits_command->destTop;
|
||||
tx = message->tiles[i]->x + cmd->destLeft;
|
||||
ty = message->tiles[i]->y + cmd->destTop;
|
||||
|
||||
freerdp_image_convert(message->tiles[i]->data, gdi->tile->bitmap->data, 64, 64, 32, 32, gdi->clrconv);
|
||||
|
||||
#ifdef DUMP_REMOTEFX_TILES
|
||||
sprintf(tile_bitmap, "/tmp/rfx/tile_%d.bmp", tilenum++);
|
||||
winpr_bitmap_write(tile_bitmap, gdi->tile->bitmap->data, 64, 64, 32);
|
||||
#endif
|
||||
|
||||
|
||||
for (j = 0; j < message->numRects; j++)
|
||||
{
|
||||
gdi_SetClipRgn(gdi->primary->hdc,
|
||||
surface_bits_command->destLeft + message->rects[j].x,
|
||||
surface_bits_command->destTop + message->rects[j].y,
|
||||
cmd->destLeft + message->rects[j].x,
|
||||
cmd->destTop + message->rects[j].y,
|
||||
message->rects[j].width, message->rects[j].height);
|
||||
|
||||
gdi_BitBlt(gdi->primary->hdc, tx, ty, 64, 64, gdi->tile->hdc, 0, 0, GDI_SRCCOPY);
|
||||
@@ -849,43 +843,45 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co
|
||||
}
|
||||
|
||||
gdi_SetNullClipRgn(gdi->primary->hdc);
|
||||
rfx_message_free(rfx_context, message);
|
||||
rfx_message_free(gdi->codecs->rfx, message);
|
||||
}
|
||||
else if (surface_bits_command->codecID == RDP_CODEC_ID_NSCODEC)
|
||||
else if (cmd->codecID == RDP_CODEC_ID_NSCODEC)
|
||||
{
|
||||
nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height,
|
||||
surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength);
|
||||
gdi->image->bitmap->width = surface_bits_command->width;
|
||||
gdi->image->bitmap->height = surface_bits_command->height;
|
||||
gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp;
|
||||
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_NSCODEC);
|
||||
|
||||
nsc_process_message(gdi->codecs->nsc, cmd->bpp, cmd->width, cmd->height,
|
||||
cmd->bitmapData, cmd->bitmapDataLength);
|
||||
gdi->image->bitmap->width = cmd->width;
|
||||
gdi->image->bitmap->height = cmd->height;
|
||||
gdi->image->bitmap->bitsPerPixel = cmd->bpp;
|
||||
gdi->image->bitmap->bytesPerPixel = gdi->image->bitmap->bitsPerPixel / 8;
|
||||
gdi->image->bitmap->data = (BYTE*) _aligned_realloc(gdi->image->bitmap->data, gdi->image->bitmap->width * gdi->image->bitmap->height * 4, 16);
|
||||
freerdp_image_convert(nsc_context->BitmapData, gdi->image->bitmap->data,
|
||||
surface_bits_command->width, surface_bits_command->height,
|
||||
surface_bits_command->bpp, gdi->dstBpp, gdi->clrconv);
|
||||
freerdp_image_convert(gdi->codecs->nsc->BitmapData, gdi->image->bitmap->data,
|
||||
cmd->width, cmd->height,
|
||||
cmd->bpp, gdi->dstBpp, gdi->clrconv);
|
||||
freerdp_image_flip(gdi->image->bitmap->data, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, gdi->dstBpp);
|
||||
gdi_BitBlt(gdi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY);
|
||||
gdi_BitBlt(gdi->primary->hdc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY);
|
||||
}
|
||||
else if (surface_bits_command->codecID == RDP_CODEC_ID_NONE)
|
||||
else if (cmd->codecID == RDP_CODEC_ID_NONE)
|
||||
{
|
||||
gdi->image->bitmap->width = surface_bits_command->width;
|
||||
gdi->image->bitmap->height = surface_bits_command->height;
|
||||
gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp;
|
||||
gdi->image->bitmap->width = cmd->width;
|
||||
gdi->image->bitmap->height = cmd->height;
|
||||
gdi->image->bitmap->bitsPerPixel = cmd->bpp;
|
||||
gdi->image->bitmap->bytesPerPixel = gdi->image->bitmap->bitsPerPixel / 8;
|
||||
|
||||
gdi->image->bitmap->data = (BYTE*) _aligned_realloc(gdi->image->bitmap->data,
|
||||
gdi->image->bitmap->width * gdi->image->bitmap->height * 4, 16);
|
||||
|
||||
if ((surface_bits_command->bpp != 32) || (gdi->clrconv->alpha == TRUE))
|
||||
if ((cmd->bpp != 32) || (gdi->clrconv->alpha))
|
||||
{
|
||||
BYTE* temp_image;
|
||||
|
||||
freerdp_image_convert(surface_bits_command->bitmapData, gdi->image->bitmap->data,
|
||||
freerdp_image_convert(cmd->bitmapData, gdi->image->bitmap->data,
|
||||
gdi->image->bitmap->width, gdi->image->bitmap->height,
|
||||
gdi->image->bitmap->bitsPerPixel, 32, gdi->clrconv);
|
||||
|
||||
surface_bits_command->bpp = 32;
|
||||
surface_bits_command->bitmapData = gdi->image->bitmap->data;
|
||||
cmd->bpp = 32;
|
||||
cmd->bitmapData = gdi->image->bitmap->data;
|
||||
|
||||
temp_image = (BYTE*) _aligned_malloc(gdi->image->bitmap->width * gdi->image->bitmap->height * 4, 16);
|
||||
freerdp_image_flip(gdi->image->bitmap->data, temp_image, gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
|
||||
@@ -894,16 +890,16 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_image_flip(surface_bits_command->bitmapData, gdi->image->bitmap->data,
|
||||
freerdp_image_flip(cmd->bitmapData, gdi->image->bitmap->data,
|
||||
gdi->image->bitmap->width, gdi->image->bitmap->height, 32);
|
||||
}
|
||||
|
||||
gdi_BitBlt(gdi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop,
|
||||
surface_bits_command->width, surface_bits_command->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY);
|
||||
gdi_BitBlt(gdi->primary->hdc, cmd->destLeft, cmd->destTop,
|
||||
cmd->width, cmd->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY);
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_WARN( "Unsupported codecID %d\n", surface_bits_command->codecID);
|
||||
DEBUG_WARN( "Unsupported codecID %d\n", cmd->codecID);
|
||||
}
|
||||
|
||||
if (tile_bitmap)
|
||||
@@ -1020,6 +1016,7 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer)
|
||||
instance->context->gdi = gdi;
|
||||
cache = instance->context->cache;
|
||||
|
||||
gdi->codecs = instance->context->codecs;
|
||||
gdi->width = instance->settings->DesktopWidth;
|
||||
gdi->height = instance->settings->DesktopHeight;
|
||||
gdi->srcBpp = instance->settings->ColorDepth;
|
||||
@@ -1103,9 +1100,6 @@ int gdi_init(freerdp* instance, UINT32 flags, BYTE* buffer)
|
||||
|
||||
gdi_register_graphics(instance->context->graphics);
|
||||
|
||||
gdi->rfx_context = rfx_context_new(FALSE);
|
||||
gdi->nsc_context = nsc_context_new();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1119,8 +1113,6 @@ void gdi_free(freerdp* instance)
|
||||
gdi_bitmap_free_ex(gdi->tile);
|
||||
gdi_bitmap_free_ex(gdi->image);
|
||||
gdi_DeleteDC(gdi->hdc);
|
||||
rfx_context_free((RFX_CONTEXT*) gdi->rfx_context);
|
||||
nsc_context_free((NSC_CONTEXT*) gdi->nsc_context);
|
||||
free(gdi->clrconv->palette);
|
||||
free(gdi->clrconv);
|
||||
free(gdi);
|
||||
|
||||
@@ -98,7 +98,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
BYTE* data, int width, int height, int bpp, int length,
|
||||
BOOL compressed, int codecId)
|
||||
{
|
||||
BOOL status;
|
||||
int status;
|
||||
UINT16 size;
|
||||
BYTE* src;
|
||||
BYTE* dst;
|
||||
@@ -107,6 +107,8 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
rdpGdi* gdi;
|
||||
RFX_MESSAGE* msg;
|
||||
|
||||
gdi = context->gdi;
|
||||
|
||||
size = width * height * ((bpp + 7) / 8);
|
||||
|
||||
if (!bitmap->data)
|
||||
@@ -117,15 +119,16 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
switch (codecId)
|
||||
{
|
||||
case RDP_CODEC_ID_NSCODEC:
|
||||
gdi = context->gdi;
|
||||
nsc_process_message(gdi->nsc_context, bpp, width, height, data, length);
|
||||
freerdp_image_flip(((NSC_CONTEXT*) gdi->nsc_context)->BitmapData, bitmap->data, width, height, bpp);
|
||||
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_NSCODEC);
|
||||
nsc_process_message(gdi->codecs->nsc, bpp, width, height, data, length);
|
||||
freerdp_image_flip(gdi->codecs->nsc->BitmapData, bitmap->data, width, height, bpp);
|
||||
break;
|
||||
|
||||
case RDP_CODEC_ID_REMOTEFX:
|
||||
gdi = context->gdi;
|
||||
rfx_context_set_pixel_format(gdi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
msg = rfx_process_message(gdi->rfx_context, data, length);
|
||||
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_REMOTEFX);
|
||||
rfx_context_set_pixel_format(gdi->codecs->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
msg = rfx_process_message(gdi->codecs->rfx, data, length);
|
||||
|
||||
if (!msg)
|
||||
{
|
||||
DEBUG_WARN( "gdi_Bitmap_Decompress: rfx Decompression Failed\n");
|
||||
@@ -136,6 +139,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
{
|
||||
src = msg->tiles[0]->data + yindex * 64 * 4;
|
||||
dst = bitmap->data + yindex * width * 3;
|
||||
|
||||
for (xindex = 0; xindex < width; xindex++)
|
||||
{
|
||||
*(dst++) = *(src++);
|
||||
@@ -144,7 +148,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
src++;
|
||||
}
|
||||
}
|
||||
rfx_message_free(gdi->rfx_context, msg);
|
||||
rfx_message_free(gdi->codecs->rfx, msg);
|
||||
}
|
||||
break;
|
||||
case RDP_CODEC_ID_JPEG:
|
||||
@@ -158,11 +162,35 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
|
||||
default:
|
||||
if (compressed)
|
||||
{
|
||||
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
|
||||
BYTE* pDstData;
|
||||
UINT32 SrcSize;
|
||||
|
||||
if (!status)
|
||||
SrcSize = (UINT32) length;
|
||||
pDstData = bitmap->data;
|
||||
|
||||
if (bpp < 32)
|
||||
{
|
||||
DEBUG_WARN( "gdi_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_INTERLEAVED);
|
||||
|
||||
status = interleaved_decompress(gdi->codecs->interleaved, data, SrcSize, bpp,
|
||||
&pDstData, PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("gdi_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
freerdp_client_codecs_prepare(gdi->codecs, FREERDP_CODEC_PLANAR);
|
||||
|
||||
status = planar_decompress(gdi->codecs->planar, data, SrcSize, &pDstData,
|
||||
PIXEL_FORMAT_XRGB32_VF, width * 4, 0, 0, width, height);
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
DEBUG_WARN("gdi_Bitmap_Decompress: Bitmap Decompression Failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -26,6 +26,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
prim_set.c
|
||||
prim_shift.c
|
||||
prim_sign.c
|
||||
prim_YUV.c
|
||||
prim_YCoCg.c
|
||||
primitives.c
|
||||
prim_internal.h)
|
||||
@@ -39,6 +40,7 @@ set(${MODULE_PREFIX}_OPT_SRCS
|
||||
prim_set_opt.c
|
||||
prim_shift_opt.c
|
||||
prim_sign_opt.c
|
||||
prim_YUV_opt.c
|
||||
prim_YCoCg_opt.c)
|
||||
|
||||
add_definitions(-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
|
||||
@@ -54,7 +56,7 @@ endif()
|
||||
|
||||
if(WITH_SSE2)
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set(OPTIMIZATION "${OPTIMIZATION} -msse2 -mssse3 -Wdeclaration-after-statement")
|
||||
set(OPTIMIZATION "${OPTIMIZATION} -msse2 -mssse3 -O2 -Wdeclaration-after-statement")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
@@ -69,6 +71,11 @@ endif()
|
||||
|
||||
set_property(SOURCE ${${MODULE_PREFIX}_OPT_SRCS} PROPERTY COMPILE_FLAGS ${OPTIMIZATION})
|
||||
|
||||
# always compile with optimization
|
||||
if(CMAKE_COMPILER_IS_GNUCC)
|
||||
set_property(SOURCE ${${MODULE_PREFIX}_SRCS} PROPERTY COMPILE_FLAGS "-O2")
|
||||
endif()
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_OPT_SRCS})
|
||||
|
||||
add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
|
||||
@@ -99,7 +106,7 @@ endif()
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
|
||||
|
||||
if(BUILD_TESTING AND ((NOT WIN32) AND (NOT APPLE)))
|
||||
if(BUILD_TESTING AND NOT WIN32 AND NOT APPLE)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#endif /* !MINMAX */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
pstatus_t general_YCoCgRToRGB_8u_AC4R(
|
||||
pstatus_t general_YCoCgToRGB_8u_AC4R(
|
||||
const BYTE *pSrc, INT32 srcStep,
|
||||
BYTE *pDst, INT32 dstStep,
|
||||
UINT32 width, UINT32 height,
|
||||
@@ -41,75 +41,85 @@ pstatus_t general_YCoCgRToRGB_8u_AC4R(
|
||||
BOOL withAlpha,
|
||||
BOOL invert)
|
||||
{
|
||||
const BYTE *sptr = pSrc;
|
||||
BYTE A;
|
||||
int x, y;
|
||||
BYTE *dptr = pDst;
|
||||
const BYTE *sptr = pSrc;
|
||||
INT16 Cg, Co, Y, T, R, G, B;
|
||||
int cll = shift - 1; /* -1 builds in the /2's */
|
||||
int x,y;
|
||||
int srcRowBump = srcStep - width*sizeof(UINT32);
|
||||
int dstRowBump = dstStep - width*sizeof(UINT32);
|
||||
int srcPad = srcStep - (width * 4);
|
||||
int dstPad = dstStep - (width * 4);
|
||||
|
||||
if (invert)
|
||||
{
|
||||
for (y=0; y<height; y++)
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x=0; x<width; x++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
INT16 cg, co, y, t, r, g, b;
|
||||
BYTE a;
|
||||
|
||||
/* Note: shifts must be done before sign-conversion. */
|
||||
cg = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
co = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
y = (INT16) (*sptr++); /* UINT8->INT16 */
|
||||
a = *sptr++;
|
||||
if (!withAlpha) a = 0xFFU;
|
||||
t = y - cg;
|
||||
r = t + co;
|
||||
g = y + cg;
|
||||
b = t - co;
|
||||
*dptr++ = (BYTE) MINMAX(r, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(g, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(b, 0, 255);
|
||||
*dptr++ = a;
|
||||
Cg = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
Co = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
Y = (INT16) (*sptr++); /* UINT8->INT16 */
|
||||
|
||||
A = *sptr++;
|
||||
|
||||
if (!withAlpha)
|
||||
A = 0xFFU;
|
||||
|
||||
T = Y - Cg;
|
||||
R = T + Co;
|
||||
G = Y + Cg;
|
||||
B = T - Co;
|
||||
|
||||
*dptr++ = (BYTE) MINMAX(R, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(G, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(B, 0, 255);
|
||||
*dptr++ = A;
|
||||
}
|
||||
sptr += srcRowBump;
|
||||
dptr += dstRowBump;
|
||||
|
||||
sptr += srcPad;
|
||||
dptr += dstPad;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y=0; y<height; y++)
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x=0; x<width; x++)
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
INT16 cg, co, y, t, r, g, b;
|
||||
BYTE a;
|
||||
|
||||
/* Note: shifts must be done before sign-conversion. */
|
||||
cg = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
co = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
y = (INT16) (*sptr++); /* UINT8->INT16 */
|
||||
a = *sptr++;
|
||||
if (!withAlpha) a = 0xFFU;
|
||||
t = y - cg;
|
||||
r = t + co;
|
||||
g = y + cg;
|
||||
b = t - co;
|
||||
*dptr++ = (BYTE) MINMAX(b, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(g, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(r, 0, 255);
|
||||
*dptr++ = a;
|
||||
Cg = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
Co = (INT16) ((INT8) ((*sptr++) << cll));
|
||||
Y = (INT16) (*sptr++); /* UINT8->INT16 */
|
||||
|
||||
A = *sptr++;
|
||||
|
||||
if (!withAlpha)
|
||||
A = 0xFFU;
|
||||
|
||||
T = Y - Cg;
|
||||
R = T + Co;
|
||||
G = Y + Cg;
|
||||
B = T - Co;
|
||||
|
||||
*dptr++ = (BYTE) MINMAX(B, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(G, 0, 255);
|
||||
*dptr++ = (BYTE) MINMAX(R, 0, 255);
|
||||
*dptr++ = A;
|
||||
}
|
||||
sptr += srcRowBump;
|
||||
dptr += dstRowBump;
|
||||
|
||||
sptr += srcPad;
|
||||
dptr += dstPad;
|
||||
}
|
||||
}
|
||||
|
||||
return PRIMITIVES_SUCCESS;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
void primitives_init_YCoCg(primitives_t* prims)
|
||||
{
|
||||
prims->YCoCgRToRGB_8u_AC4R = general_YCoCgRToRGB_8u_AC4R;
|
||||
prims->YCoCgToRGB_8u_AC4R = general_YCoCgToRGB_8u_AC4R;
|
||||
|
||||
primitives_init_YCoCg_opt(prims);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#ifndef __PRIM_YCOCG_H_INCLUDED__
|
||||
#define __PRIM_YCOCG_H_INCLUDED__
|
||||
|
||||
pstatus_t general_YCoCgRToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep, BYTE *pDst, INT32 dstStep, UINT32 width, UINT32 height, UINT8 shift, BOOL withAlpha, BOOL invert);
|
||||
pstatus_t general_YCoCgToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep, BYTE *pDst, INT32 dstStep, UINT32 width, UINT32 height, UINT8 shift, BOOL withAlpha, BOOL invert);
|
||||
|
||||
void primitives_init_YCoCg_opt(primitives_t* prims);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ static pstatus_t ssse3_YCoCgRToRGB_8u_AC4R_invert(
|
||||
if ((width < 8) || (ULONG_PTR) dptr & 0x03)
|
||||
{
|
||||
/* Too small, or we'll never hit a 16-byte boundary. Punt. */
|
||||
return general_YCoCgRToRGB_8u_AC4R(pSrc, srcStep,
|
||||
return general_YCoCgToRGB_8u_AC4R(pSrc, srcStep,
|
||||
pDst, dstStep, width, height, shift, withAlpha, TRUE);
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ static pstatus_t ssse3_YCoCgRToRGB_8u_AC4R_invert(
|
||||
{
|
||||
int startup = (16 - ((ULONG_PTR) dptr & 0x0f)) / 4;
|
||||
if (startup > width) startup = width;
|
||||
general_YCoCgRToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
general_YCoCgToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
startup, 1, shift, withAlpha, TRUE);
|
||||
sptr += startup * sizeof(UINT32);
|
||||
dptr += startup * sizeof(UINT32);
|
||||
@@ -185,7 +185,7 @@ static pstatus_t ssse3_YCoCgRToRGB_8u_AC4R_invert(
|
||||
|
||||
/* Handle any remainder pixels. */
|
||||
if (w > 0) {
|
||||
general_YCoCgRToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
general_YCoCgToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
w, 1, shift, withAlpha, TRUE);
|
||||
sptr += w * sizeof(UINT32);
|
||||
dptr += w * sizeof(UINT32);
|
||||
@@ -228,7 +228,7 @@ static pstatus_t ssse3_YCoCgRToRGB_8u_AC4R_no_invert(
|
||||
if ((width < 8) || (ULONG_PTR) dptr & 0x03)
|
||||
{
|
||||
/* Too small, or we'll never hit a 16-byte boundary. Punt. */
|
||||
return general_YCoCgRToRGB_8u_AC4R(pSrc, srcStep,
|
||||
return general_YCoCgToRGB_8u_AC4R(pSrc, srcStep,
|
||||
pDst, dstStep, width, height, shift, withAlpha, FALSE);
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ static pstatus_t ssse3_YCoCgRToRGB_8u_AC4R_no_invert(
|
||||
{
|
||||
int startup = (16 - ((ULONG_PTR) dptr & 0x0f)) / 4;
|
||||
if (startup > width) startup = width;
|
||||
general_YCoCgRToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
general_YCoCgToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
startup, 1, shift, withAlpha, FALSE);
|
||||
sptr += startup * sizeof(UINT32);
|
||||
dptr += startup * sizeof(UINT32);
|
||||
@@ -348,7 +348,7 @@ static pstatus_t ssse3_YCoCgRToRGB_8u_AC4R_no_invert(
|
||||
|
||||
/* Handle any remainder pixels. */
|
||||
if (w > 0) {
|
||||
general_YCoCgRToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
general_YCoCgToRGB_8u_AC4R(sptr, srcStep, dptr, dstStep,
|
||||
w, 1, shift, withAlpha, FALSE);
|
||||
sptr += w * sizeof(UINT32);
|
||||
dptr += w * sizeof(UINT32);
|
||||
@@ -393,7 +393,7 @@ void primitives_init_YCoCg_opt(primitives_t* prims)
|
||||
if (IsProcessorFeaturePresentEx(PF_EX_SSSE3)
|
||||
&& IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
|
||||
{
|
||||
prims->YCoCgRToRGB_8u_AC4R = ssse3_YCoCgRToRGB_8u_AC4R;
|
||||
prims->YCoCgToRGB_8u_AC4R = ssse3_YCoCgRToRGB_8u_AC4R;
|
||||
}
|
||||
#endif /* WITH_SSE2 */
|
||||
}
|
||||
|
||||
278
libfreerdp/primitives/prim_YUV.c
Normal file
278
libfreerdp/primitives/prim_YUV.c
Normal file
@@ -0,0 +1,278 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/primitives.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#include "prim_internal.h"
|
||||
#include "prim_YUV.h"
|
||||
|
||||
/**
|
||||
* | R | ( | 256 0 403 | | Y | )
|
||||
* | G | = ( | 256 -48 -120 | | U - 128 | ) >> 8
|
||||
* | B | ( | 256 475 0 | | V - 128 | )
|
||||
*
|
||||
* | Y | ( | 54 183 18 | | R | ) | 0 |
|
||||
* | U | = ( | -29 -99 128 | | G | ) >> 8 + | 128 |
|
||||
* | V | ( | 128 -116 -12 | | B | ) | 128 |
|
||||
*/
|
||||
|
||||
pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
|
||||
BYTE* pDst, int dstStep, const prim_size_t* roi)
|
||||
{
|
||||
int x, y;
|
||||
int dstPad;
|
||||
int srcPad[3];
|
||||
BYTE Y, U, V;
|
||||
int halfWidth;
|
||||
int halfHeight;
|
||||
const BYTE* pY;
|
||||
const BYTE* pU;
|
||||
const BYTE* pV;
|
||||
int R, G, B;
|
||||
int Yp, Up, Vp;
|
||||
int Up48, Up475;
|
||||
int Vp403, Vp120;
|
||||
BYTE* pRGB = pDst;
|
||||
int nWidth, nHeight;
|
||||
int lastRow, lastCol;
|
||||
|
||||
pY = pSrc[0];
|
||||
pU = pSrc[1];
|
||||
pV = pSrc[2];
|
||||
|
||||
lastCol = roi->width & 0x01;
|
||||
lastRow = roi->height & 0x01;
|
||||
|
||||
nWidth = (roi->width + 1) & ~0x0001;
|
||||
nHeight = (roi->height + 1) & ~0x0001;
|
||||
|
||||
halfWidth = nWidth / 2;
|
||||
halfHeight = nHeight / 2;
|
||||
|
||||
srcPad[0] = (srcStep[0] - nWidth);
|
||||
srcPad[1] = (srcStep[1] - halfWidth);
|
||||
srcPad[2] = (srcStep[2] - halfWidth);
|
||||
|
||||
dstPad = (dstStep - (nWidth * 4));
|
||||
|
||||
for (y = 0; y < halfHeight; )
|
||||
{
|
||||
if (++y == halfHeight)
|
||||
lastRow <<= 1;
|
||||
|
||||
for (x = 0; x < halfWidth; )
|
||||
{
|
||||
if (++x == halfWidth)
|
||||
lastCol <<= 1;
|
||||
|
||||
U = *pU++;
|
||||
V = *pV++;
|
||||
|
||||
Up = U - 128;
|
||||
Vp = V - 128;
|
||||
|
||||
Up48 = 48 * Up;
|
||||
Up475 = 475 * Up;
|
||||
|
||||
Vp403 = Vp * 403;
|
||||
Vp120 = Vp * 120;
|
||||
|
||||
/* 1st pixel */
|
||||
|
||||
Y = *pY++;
|
||||
Yp = Y << 8;
|
||||
|
||||
R = (Yp + Vp403) >> 8;
|
||||
G = (Yp - Up48 - Vp120) >> 8;
|
||||
B = (Yp + Up475) >> 8;
|
||||
|
||||
if (R < 0)
|
||||
R = 0;
|
||||
else if (R > 255)
|
||||
R = 255;
|
||||
|
||||
if (G < 0)
|
||||
G = 0;
|
||||
else if (G > 255)
|
||||
G = 255;
|
||||
|
||||
if (B < 0)
|
||||
B = 0;
|
||||
else if (B > 255)
|
||||
B = 255;
|
||||
|
||||
*pRGB++ = (BYTE) B;
|
||||
*pRGB++ = (BYTE) G;
|
||||
*pRGB++ = (BYTE) R;
|
||||
*pRGB++ = 0xFF;
|
||||
|
||||
/* 2nd pixel */
|
||||
|
||||
if (!(lastCol & 0x02))
|
||||
{
|
||||
Y = *pY++;
|
||||
Yp = Y << 8;
|
||||
|
||||
R = (Yp + Vp403) >> 8;
|
||||
G = (Yp - Up48 - Vp120) >> 8;
|
||||
B = (Yp + Up475) >> 8;
|
||||
|
||||
if (R < 0)
|
||||
R = 0;
|
||||
else if (R > 255)
|
||||
R = 255;
|
||||
|
||||
if (G < 0)
|
||||
G = 0;
|
||||
else if (G > 255)
|
||||
G = 255;
|
||||
|
||||
if (B < 0)
|
||||
B = 0;
|
||||
else if (B > 255)
|
||||
B = 255;
|
||||
|
||||
*pRGB++ = (BYTE) B;
|
||||
*pRGB++ = (BYTE) G;
|
||||
*pRGB++ = (BYTE) R;
|
||||
*pRGB++ = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pY++;
|
||||
pRGB += 4;
|
||||
lastCol >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pY += srcPad[0];
|
||||
pU -= halfWidth;
|
||||
pV -= halfWidth;
|
||||
pRGB += dstPad;
|
||||
|
||||
for (x = 0; x < halfWidth; )
|
||||
{
|
||||
if (++x == halfWidth)
|
||||
lastCol <<= 1;
|
||||
|
||||
U = *pU++;
|
||||
V = *pV++;
|
||||
|
||||
Up = U - 128;
|
||||
Vp = V - 128;
|
||||
|
||||
Up48 = 48 * Up;
|
||||
Up475 = 475 * Up;
|
||||
|
||||
Vp403 = Vp * 403;
|
||||
Vp120 = Vp * 120;
|
||||
|
||||
/* 3rd pixel */
|
||||
|
||||
Y = *pY++;
|
||||
Yp = Y << 8;
|
||||
|
||||
R = (Yp + Vp403) >> 8;
|
||||
G = (Yp - Up48 - Vp120) >> 8;
|
||||
B = (Yp + Up475) >> 8;
|
||||
|
||||
if (R < 0)
|
||||
R = 0;
|
||||
else if (R > 255)
|
||||
R = 255;
|
||||
|
||||
if (G < 0)
|
||||
G = 0;
|
||||
else if (G > 255)
|
||||
G = 255;
|
||||
|
||||
if (B < 0)
|
||||
B = 0;
|
||||
else if (B > 255)
|
||||
B = 255;
|
||||
|
||||
*pRGB++ = (BYTE) B;
|
||||
*pRGB++ = (BYTE) G;
|
||||
*pRGB++ = (BYTE) R;
|
||||
*pRGB++ = 0xFF;
|
||||
|
||||
/* 4th pixel */
|
||||
|
||||
if (!(lastCol & 0x02))
|
||||
{
|
||||
Y = *pY++;
|
||||
Yp = Y << 8;
|
||||
|
||||
R = (Yp + Vp403) >> 8;
|
||||
G = (Yp - Up48 - Vp120) >> 8;
|
||||
B = (Yp + Up475) >> 8;
|
||||
|
||||
if (R < 0)
|
||||
R = 0;
|
||||
else if (R > 255)
|
||||
R = 255;
|
||||
|
||||
if (G < 0)
|
||||
G = 0;
|
||||
else if (G > 255)
|
||||
G = 255;
|
||||
|
||||
if (B < 0)
|
||||
B = 0;
|
||||
else if (B > 255)
|
||||
B = 255;
|
||||
|
||||
*pRGB++ = (BYTE) B;
|
||||
*pRGB++ = (BYTE) G;
|
||||
*pRGB++ = (BYTE) R;
|
||||
*pRGB++ = 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pY++;
|
||||
pRGB += 4;
|
||||
lastCol >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
pY += srcPad[0];
|
||||
pU += srcPad[1];
|
||||
pV += srcPad[2];
|
||||
pRGB += dstPad;
|
||||
}
|
||||
|
||||
return PRIMITIVES_SUCCESS;
|
||||
}
|
||||
|
||||
void primitives_init_YUV(primitives_t* prims)
|
||||
{
|
||||
prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R;
|
||||
|
||||
primitives_init_YUV_opt(prims);
|
||||
}
|
||||
|
||||
void primitives_deinit_YUV(primitives_t* prims)
|
||||
{
|
||||
|
||||
}
|
||||
28
libfreerdp/primitives/prim_YUV.h
Normal file
28
libfreerdp/primitives/prim_YUV.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_PRIMITIVES_YUV_H
|
||||
#define FREERDP_PRIMITIVES_YUV_H
|
||||
|
||||
pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep, BYTE* pDst, int dstStep, const prim_size_t* roi);
|
||||
|
||||
void primitives_init_YUV(primitives_t* prims);
|
||||
void primitives_init_YUV_opt(primitives_t* prims);
|
||||
void primitives_deinit_YUV(primitives_t* prims);
|
||||
|
||||
#endif /* FREERDP_PRIMITIVES_YUV_H */
|
||||
370
libfreerdp/primitives/prim_YUV_opt.c
Normal file
370
libfreerdp/primitives/prim_YUV_opt.c
Normal file
@@ -0,0 +1,370 @@
|
||||
/** function for converting YUV420p data to the RGB format (but without any special upconverting)
|
||||
* It's completely written in nasm-x86-assembly for intel processors supporting SSSE3 and higher.
|
||||
* The target dstStep (6th parameter) must be a multiple of 16.
|
||||
* srcStep[0] must be (target dstStep) / 4 or bigger and srcStep[1] the next multiple of four
|
||||
* of the half of srcStep[0] or bigger
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <winpr/crt.h>
|
||||
#include <freerdp/types.h>
|
||||
#include <freerdp/primitives.h>
|
||||
|
||||
|
||||
#ifdef WITH_SSE2
|
||||
|
||||
#include <emmintrin.h>
|
||||
#include <tmmintrin.h>
|
||||
|
||||
pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
|
||||
BYTE *pDst, int dstStep, const prim_size_t *roi)
|
||||
{
|
||||
int lastRow, lastCol;
|
||||
BYTE *UData,*VData,*YData;
|
||||
int i,nWidth,nHeight,VaddDst,VaddY,VaddU,VaddV;
|
||||
__m128i r0,r1,r2,r3,r4,r5,r6,r7;
|
||||
__m128i *buffer;
|
||||
|
||||
/* last_line: if the last (U,V doubled) line should be skipped, set to 10B
|
||||
* last_column: if it's the last column in a line, set to 10B (for handling line-endings not multiple by four) */
|
||||
|
||||
buffer = _aligned_malloc(4 * 16, 16);
|
||||
|
||||
YData = (BYTE*) pSrc[0];
|
||||
UData = (BYTE*) pSrc[1];
|
||||
VData = (BYTE*) pSrc[2];
|
||||
|
||||
nWidth = roi->width;
|
||||
nHeight = roi->height;
|
||||
|
||||
if ((lastCol = (nWidth & 3)))
|
||||
{
|
||||
switch (lastCol)
|
||||
{
|
||||
case 1:
|
||||
r7 = _mm_set_epi32(0,0,0,0xFFFFFFFF);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
r7 = _mm_set_epi32(0,0,0xFFFFFFFF,0xFFFFFFFF);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
r7 = _mm_set_epi32(0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF);
|
||||
break;
|
||||
}
|
||||
|
||||
_mm_store_si128(buffer+3,r7);
|
||||
lastCol = 1;
|
||||
}
|
||||
|
||||
nWidth += 3;
|
||||
nWidth = nWidth >> 2;
|
||||
|
||||
lastRow = nHeight & 1;
|
||||
nHeight++;
|
||||
nHeight = nHeight >> 1;
|
||||
|
||||
VaddDst = (dstStep << 1) - (nWidth << 4);
|
||||
VaddY = (srcStep[0] << 1) - (nWidth << 2);
|
||||
VaddU = srcStep[1] - (((nWidth << 1) + 2) & 0xFFFC);
|
||||
VaddV = srcStep[2] - (((nWidth << 1) + 2) & 0xFFFC);
|
||||
|
||||
while (nHeight-- > 0)
|
||||
{
|
||||
if (nHeight == 0)
|
||||
lastRow <<= 1;
|
||||
|
||||
i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (!(i & 0x01))
|
||||
{
|
||||
/* Y-, U- and V-data is stored in different arrays.
|
||||
* We start with processing U-data.
|
||||
*
|
||||
* at first we fetch four U-values from its array and shuffle them like this:
|
||||
* 0d0d 0c0c 0b0b 0a0a
|
||||
* we've done two things: converting the values to signed words and duplicating
|
||||
* each value, because always two pixel "share" the same U- (and V-) data */
|
||||
r0 = _mm_cvtsi32_si128(*(UINT32 *)UData);
|
||||
r5 = _mm_set_epi32(0x80038003,0x80028002,0x80018001,0x80008000);
|
||||
r0 = _mm_shuffle_epi8(r0,r5);
|
||||
|
||||
UData += 4;
|
||||
|
||||
/* then we subtract 128 from each value, so we get D */
|
||||
r3 = _mm_set_epi16(128,128,128,128,128,128,128,128);
|
||||
r0 = _mm_subs_epi16(r0,r3);
|
||||
|
||||
/* we need to do two things with our D, so let's store it for later use */
|
||||
r2 = r0;
|
||||
|
||||
/* now we can multiply our D with 48 and unpack it to xmm4:xmm0
|
||||
* this is what we need to get G data later on */
|
||||
r4 = r0;
|
||||
r7 = _mm_set_epi16(48,48,48,48,48,48,48,48);
|
||||
r0 = _mm_mullo_epi16(r0,r7);
|
||||
r4 = _mm_mulhi_epi16(r4,r7);
|
||||
r7 = r0;
|
||||
r0 = _mm_unpacklo_epi16(r0,r4);
|
||||
r4 = _mm_unpackhi_epi16(r7,r4);
|
||||
|
||||
/* to get B data, we need to prepare a second value, D*475 */
|
||||
r1 = r2;
|
||||
r7 = _mm_set_epi16(475,475,475,475,475,475,475,475);
|
||||
r1 = _mm_mullo_epi16(r1,r7);
|
||||
r2 = _mm_mulhi_epi16(r2,r7);
|
||||
r7 = r1;
|
||||
r1 = _mm_unpacklo_epi16(r1,r2);
|
||||
r7 = _mm_unpackhi_epi16(r7,r2);
|
||||
|
||||
/* so we got something like this: xmm7:xmm1
|
||||
* this pair contains values for 16 pixel:
|
||||
* aabbccdd
|
||||
* aabbccdd, but we can only work on four pixel at once, so we need to save upper values */
|
||||
_mm_store_si128(buffer+1,r7);
|
||||
|
||||
/* Now we've prepared U-data. Preparing V-data is actually the same, just with other coefficients */
|
||||
r2 = _mm_cvtsi32_si128(*(UINT32 *)VData);
|
||||
r2 = _mm_shuffle_epi8(r2,r5);
|
||||
|
||||
VData += 4;
|
||||
|
||||
r2 = _mm_subs_epi16(r2,r3);
|
||||
|
||||
r5 = r2;
|
||||
|
||||
/* this is also known as E*403, we need it to convert R data */
|
||||
r3 = r2;
|
||||
r7 = _mm_set_epi16(403,403,403,403,403,403,403,403);
|
||||
r2 = _mm_mullo_epi16(r2,r7);
|
||||
r3 = _mm_mulhi_epi16(r3,r7);
|
||||
r7 = r2;
|
||||
r2 = _mm_unpacklo_epi16(r2,r3);
|
||||
r7 = _mm_unpackhi_epi16(r7,r3);
|
||||
|
||||
/* and preserve upper four values for future ... */
|
||||
_mm_store_si128(buffer+2,r7);
|
||||
|
||||
/* doing this step: E*120 */
|
||||
r3 = r5;
|
||||
r7 = _mm_set_epi16(120,120,120,120,120,120,120,120);
|
||||
r3 = _mm_mullo_epi16(r3,r7);
|
||||
r5 = _mm_mulhi_epi16(r5,r7);
|
||||
r7 = r3;
|
||||
r3 = _mm_unpacklo_epi16(r3,r5);
|
||||
r7 = _mm_unpackhi_epi16(r7,r5);
|
||||
|
||||
/* now we complete what we've begun above:
|
||||
* (48*D) + (120*E) = (48*D +120*E) */
|
||||
r0 = _mm_add_epi32(r0,r3);
|
||||
r4 = _mm_add_epi32(r4,r7);
|
||||
|
||||
/* and store to memory ! */
|
||||
_mm_store_si128(buffer,r4);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* maybe you've wondered about the conditional above ?
|
||||
* Well, we prepared UV data for eight pixel in each line, but can only process four
|
||||
* per loop. So we need to load the upper four pixel data from memory each secound loop! */
|
||||
r1 = _mm_load_si128(buffer+1);
|
||||
r2 = _mm_load_si128(buffer+2);
|
||||
r0 = _mm_load_si128(buffer);
|
||||
}
|
||||
|
||||
if (++i == nWidth)
|
||||
lastCol <<= 1;
|
||||
|
||||
/* We didn't produce any output yet, so let's do so!
|
||||
* Ok, fetch four pixel from the Y-data array and shuffle them like this:
|
||||
* 00d0 00c0 00b0 00a0, to get signed dwords and multiply by 256 */
|
||||
r4 = _mm_cvtsi32_si128(*(UINT32 *)YData);
|
||||
r7 = _mm_set_epi32(0x80800380,0x80800280,0x80800180,0x80800080);
|
||||
r4 = _mm_shuffle_epi8(r4,r7);
|
||||
|
||||
r5 = r4;
|
||||
r6 = r4;
|
||||
|
||||
/* no we can perform the "real" conversion itself and produce output! */
|
||||
r4 = _mm_add_epi32(r4,r2);
|
||||
r5 = _mm_sub_epi32(r5,r0);
|
||||
r6 = _mm_add_epi32(r6,r1);
|
||||
|
||||
/* in the end, we only need bytes for RGB values.
|
||||
* So, what do we do? right! shifting left makes values bigger and thats always good.
|
||||
* before we had dwords of data, and by shifting left and treating the result
|
||||
* as packed words, we get not only signed words, but do also divide by 256
|
||||
* imagine, data is now ordered this way: ddx0 ccx0 bbx0 aax0, and x is the least
|
||||
* significant byte, that we don't need anymore, because we've done some rounding */
|
||||
r4 = _mm_slli_epi32(r4,8);
|
||||
r5 = _mm_slli_epi32(r5,8);
|
||||
r6 = _mm_slli_epi32(r6,8);
|
||||
|
||||
/* one thing we still have to face is the clip() function ...
|
||||
* we have still signed words, and there are those min/max instructions in SSE2 ...
|
||||
* the max instruction takes always the bigger of the two operands and stores it in the first one,
|
||||
* and it operates with signs !
|
||||
* if we feed it with our values and zeros, it takes the zeros if our values are smaller than
|
||||
* zero and otherwise our values */
|
||||
r7 = _mm_set_epi32(0,0,0,0);
|
||||
r4 = _mm_max_epi16(r4,r7);
|
||||
r5 = _mm_max_epi16(r5,r7);
|
||||
r6 = _mm_max_epi16(r6,r7);
|
||||
|
||||
/* the same thing just completely different can be used to limit our values to 255,
|
||||
* but now using the min instruction and 255s */
|
||||
r7 = _mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
|
||||
r4 = _mm_min_epi16(r4,r7);
|
||||
r5 = _mm_min_epi16(r5,r7);
|
||||
r6 = _mm_min_epi16(r6,r7);
|
||||
|
||||
/* Now we got our bytes.
|
||||
* the moment has come to assemble the three channels R,G and B to the xrgb dwords
|
||||
* on Red channel we just have to and each futural dword with 00FF0000H */
|
||||
//r7=_mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
|
||||
r4 = _mm_and_si128(r4,r7);
|
||||
|
||||
/* on Green channel we have to shuffle somehow, so we get something like this:
|
||||
* 00d0 00c0 00b0 00a0 */
|
||||
r7 = _mm_set_epi32(0x80800E80,0x80800A80,0x80800680,0x80800280);
|
||||
r5 = _mm_shuffle_epi8(r5,r7);
|
||||
|
||||
/* and on Blue channel that one:
|
||||
* 000d 000c 000b 000a */
|
||||
r7 = _mm_set_epi32(0x8080800E,0x8080800A,0x80808006,0x80808002);
|
||||
r6 = _mm_shuffle_epi8(r6,r7);
|
||||
|
||||
/* and at last we or it together and get this one:
|
||||
* xrgb xrgb xrgb xrgb */
|
||||
r4 = _mm_or_si128(r4,r5);
|
||||
r4 = _mm_or_si128(r4,r6);
|
||||
|
||||
/* Only thing to do know is writing data to memory, but this gets a bit more
|
||||
* complicated if the width is not a multiple of four and it is the last column in line. */
|
||||
if (lastCol & 0x02)
|
||||
{
|
||||
/* let's say, we need to only convert six pixel in width
|
||||
* Ok, the first 4 pixel will be converted just like every 4 pixel else, but
|
||||
* if it's the last loop in line, last_column is shifted left by one (curious? have a look above),
|
||||
* and we land here. Through initialisation a mask was prepared. In this case it looks like
|
||||
* 0000FFFFH 0000FFFFH 0000FFFFH 0000FFFFH */
|
||||
r6 = _mm_load_si128(buffer+3);
|
||||
/* we and our output data with this mask to get only the valid pixel */
|
||||
r4 = _mm_and_si128(r4,r6);
|
||||
/* then we fetch memory from the destination array ... */
|
||||
r5 = _mm_lddqu_si128((__m128i *)pDst);
|
||||
/* ... and and it with the inverse mask. We get only those pixel, which should not be updated */
|
||||
r6 = _mm_andnot_si128(r6,r5);
|
||||
/* we only have to or the two values together and write it back to the destination array,
|
||||
* and only the pixel that should be updated really get changed. */
|
||||
r4 = _mm_or_si128(r4,r6);
|
||||
}
|
||||
_mm_storeu_si128((__m128i *)pDst,r4);
|
||||
|
||||
if (!(lastRow & 0x02))
|
||||
{
|
||||
/* Because UV data is the same for two lines, we can process the secound line just here,
|
||||
* in the same loop. Only thing we need to do is to add some offsets to the Y- and destination
|
||||
* pointer. These offsets are iStride[0] and the target scanline.
|
||||
* But if we don't need to process the secound line, like if we are in the last line of processing nine lines,
|
||||
* we just skip all this. */
|
||||
r4 = _mm_cvtsi32_si128(*(UINT32 *)(YData+srcStep[0]));
|
||||
r7 = _mm_set_epi32(0x80800380,0x80800280,0x80800180,0x80800080);
|
||||
r4 = _mm_shuffle_epi8(r4,r7);
|
||||
|
||||
r5 = r4;
|
||||
r6 = r4;
|
||||
|
||||
r4 = _mm_add_epi32(r4,r2);
|
||||
r5 = _mm_sub_epi32(r5,r0);
|
||||
r6 = _mm_add_epi32(r6,r1);
|
||||
|
||||
r4 = _mm_slli_epi32(r4,8);
|
||||
r5 = _mm_slli_epi32(r5,8);
|
||||
r6 = _mm_slli_epi32(r6,8);
|
||||
|
||||
r7 = _mm_set_epi32(0,0,0,0);
|
||||
r4 = _mm_max_epi16(r4,r7);
|
||||
r5 = _mm_max_epi16(r5,r7);
|
||||
r6 = _mm_max_epi16(r6,r7);
|
||||
|
||||
r7 = _mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
|
||||
r4 = _mm_min_epi16(r4,r7);
|
||||
r5 = _mm_min_epi16(r5,r7);
|
||||
r6 = _mm_min_epi16(r6,r7);
|
||||
|
||||
r7 = _mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
|
||||
r4 = _mm_and_si128(r4,r7);
|
||||
|
||||
r7 = _mm_set_epi32(0x80800E80,0x80800A80,0x80800680,0x80800280);
|
||||
r5 = _mm_shuffle_epi8(r5,r7);
|
||||
|
||||
r7 = _mm_set_epi32(0x8080800E,0x8080800A,0x80808006,0x80808002);
|
||||
r6 = _mm_shuffle_epi8(r6,r7);
|
||||
|
||||
r4 = _mm_or_si128(r4,r5);
|
||||
r4 = _mm_or_si128(r4,r6);
|
||||
|
||||
if (lastCol & 0x02)
|
||||
{
|
||||
r6 = _mm_load_si128(buffer+3);
|
||||
r4 = _mm_and_si128(r4,r6);
|
||||
r5 = _mm_lddqu_si128((__m128i *)(pDst+dstStep));
|
||||
r6 = _mm_andnot_si128(r6,r5);
|
||||
r4 = _mm_or_si128(r4,r6);
|
||||
|
||||
/* only thing is, we should shift [rbp-42] back here, because we have processed the last column,
|
||||
* and this "special condition" can be released */
|
||||
lastCol >>= 1;
|
||||
}
|
||||
_mm_storeu_si128((__m128i *)(pDst+dstStep),r4);
|
||||
}
|
||||
|
||||
/* after all we have to increase the destination- and Y-data pointer by four pixel */
|
||||
pDst += 16;
|
||||
YData += 4;
|
||||
}
|
||||
while (i < nWidth);
|
||||
|
||||
/* after each line we have to add the scanline to the destination pointer, because
|
||||
* we are processing two lines at once, but only increasing the destination pointer
|
||||
* in the first line. Well, we only have one pointer, so it's the easiest way to access
|
||||
* the secound line with the one pointer and an offset (scanline)
|
||||
* if we're not converting the full width of the scanline, like only 64 pixel, but the
|
||||
* output buffer was "designed" for 1920p HD, we have to add the remaining length for each line,
|
||||
* to get into the next line. */
|
||||
pDst += VaddDst;
|
||||
|
||||
/* same thing has to be done for Y-data, but with iStride[0] instead of the target scanline */
|
||||
YData += VaddY;
|
||||
|
||||
/* and again for UV data, but here it's enough to add the remaining length, because
|
||||
* UV data is the same for two lines and there exists only one "UV line" on two "real lines" */
|
||||
UData += VaddU;
|
||||
VData += VaddV;
|
||||
}
|
||||
|
||||
_aligned_free(buffer);
|
||||
|
||||
return PRIMITIVES_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
void primitives_init_YUV_opt(primitives_t *prims)
|
||||
{
|
||||
#ifdef WITH_SSE2
|
||||
if (IsProcessorFeaturePresentEx(PF_EX_SSSE3) && IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE))
|
||||
{
|
||||
prims->YUV420ToRGB_8u_P3AC4R = ssse3_YUV420ToRGB_8u_P3AC4R;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -39,7 +39,7 @@ pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep,
|
||||
{
|
||||
int x, y;
|
||||
INT16 R, G, B;
|
||||
double Y, Cb, Cr;
|
||||
float Y, Cb, Cr;
|
||||
BYTE* pRGB = pDst;
|
||||
const INT16* pY = pSrc[0];
|
||||
const INT16* pCb = pSrc[1];
|
||||
@@ -51,13 +51,13 @@ pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep,
|
||||
{
|
||||
for (x = 0; x < roi->width; x++)
|
||||
{
|
||||
Y = (double) ((*pY++ >> 1) + 2048);
|
||||
Cb = (double) (*pCb++ >> 1);
|
||||
Cr = (double) (*pCr++ >> 1);
|
||||
Y = (float) (pY[0] + 4096);
|
||||
Cb = (float) (pCb[0]);
|
||||
Cr = (float) (pCr[0]);
|
||||
|
||||
R = (INT16) (((int) (Y + (1.402524948120117L * Cr) + 8.0L)) >> 4);
|
||||
G = (INT16) (((int) (Y - (0.3437300026416779L * Cb) - (0.7144010066986084L * Cr) + 8.0L)) >> 4);
|
||||
B = (INT16) (((int) (Y + (1.769904971122742L * Cb) + 8.0L)) >> 4);
|
||||
R = ((INT16) (((Cr * 1.402525f) + Y + 16.0f)) >> 5);
|
||||
G = ((INT16) ((Y - (Cb * 0.343730f) - (Cr * 0.714401f) + 16.0f)) >> 5);
|
||||
B = ((INT16) (((Cb * 1.769905f) + Y + 16.0f)) >> 5);
|
||||
|
||||
if (R < 0)
|
||||
R = 0;
|
||||
@@ -78,6 +78,10 @@ pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep,
|
||||
*pRGB++ = (BYTE) G;
|
||||
*pRGB++ = (BYTE) R;
|
||||
*pRGB++ = 0xFF;
|
||||
|
||||
pY++;
|
||||
pCb++;
|
||||
pCr++;
|
||||
}
|
||||
|
||||
pY += srcPad;
|
||||
|
||||
@@ -35,54 +35,37 @@
|
||||
: _mm_load_si128((__m128i *) (_ptr_)))
|
||||
|
||||
/* Function prototypes for all the init/deinit routines. */
|
||||
extern void primitives_init_copy(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_copy(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_copy(primitives_t *prims);
|
||||
extern void primitives_deinit_copy(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_set(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_set(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_set(primitives_t *prims);
|
||||
extern void primitives_deinit_set(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_add(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_add(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_add(primitives_t *prims);
|
||||
extern void primitives_deinit_add(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_andor(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_andor(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_andor(primitives_t *prims);
|
||||
extern void primitives_deinit_andor(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_shift(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_shift(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_shift(primitives_t *prims);
|
||||
extern void primitives_deinit_shift(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_sign(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_sign(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_sign(primitives_t *prims);
|
||||
extern void primitives_deinit_sign(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_alphaComp(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_alphaComp(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_alphaComp(primitives_t *prims);
|
||||
extern void primitives_deinit_alphaComp(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_colors(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_colors(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_colors(primitives_t *prims);
|
||||
extern void primitives_deinit_colors(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_YCoCg(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_YCoCg(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_YCoCg(primitives_t *prims);
|
||||
extern void primitives_deinit_YCoCg(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_16to32bpp(
|
||||
primitives_t *prims);
|
||||
extern void primitives_deinit_16to32bpp(
|
||||
primitives_t *prims);
|
||||
extern void primitives_init_YUV(primitives_t *prims);
|
||||
extern void primitives_deinit_YUV(primitives_t *prims);
|
||||
|
||||
extern void primitives_init_16to32bpp(primitives_t *prims);
|
||||
extern void primitives_deinit_16to32bpp(primitives_t *prims);
|
||||
|
||||
#endif /* !__PRIM_INTERNAL_H_INCLUDED__ */
|
||||
|
||||
@@ -32,11 +32,11 @@ static primitives_t* pPrimitives = NULL;
|
||||
/* ------------------------------------------------------------------------- */
|
||||
void primitives_init(void)
|
||||
{
|
||||
if (pPrimitives == NULL)
|
||||
if (!pPrimitives)
|
||||
{
|
||||
pPrimitives = calloc(1, sizeof(primitives_t));
|
||||
|
||||
if (pPrimitives == NULL)
|
||||
if (!pPrimitives)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -50,13 +50,14 @@ void primitives_init(void)
|
||||
primitives_init_sign(pPrimitives);
|
||||
primitives_init_colors(pPrimitives);
|
||||
primitives_init_YCoCg(pPrimitives);
|
||||
primitives_init_YUV(pPrimitives);
|
||||
primitives_init_16to32bpp(pPrimitives);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
primitives_t* primitives_get(void)
|
||||
{
|
||||
if (pPrimitives == NULL)
|
||||
if (!pPrimitives)
|
||||
primitives_init();
|
||||
|
||||
return pPrimitives;
|
||||
@@ -65,7 +66,7 @@ primitives_t* primitives_get(void)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
void primitives_deinit(void)
|
||||
{
|
||||
if (pPrimitives == NULL)
|
||||
if (!pPrimitives)
|
||||
return;
|
||||
|
||||
/* Call each section's de-initialization routine. */
|
||||
@@ -78,6 +79,7 @@ void primitives_deinit(void)
|
||||
primitives_deinit_sign(pPrimitives);
|
||||
primitives_deinit_colors(pPrimitives);
|
||||
primitives_deinit_YCoCg(pPrimitives);
|
||||
primitives_deinit_YUV(pPrimitives);
|
||||
primitives_deinit_16to32bpp(pPrimitives);
|
||||
|
||||
free((void*) pPrimitives);
|
||||
|
||||
@@ -243,7 +243,7 @@ int test_set32u_func(void)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static inline void memset32u_naive(
|
||||
static INLINE void memset32u_naive(
|
||||
UINT32 val,
|
||||
UINT32 *dst,
|
||||
size_t count)
|
||||
@@ -275,7 +275,7 @@ int test_set32u_speed(void)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
static inline void memset32s_naive(
|
||||
static INLINE void memset32s_naive(
|
||||
INT32 val,
|
||||
INT32 *dst,
|
||||
size_t count)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "prim_test.h"
|
||||
|
||||
#include <winpr/print.h>
|
||||
#include <freerdp/codec/color.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
@@ -2075,48 +2076,227 @@ static UINT32 TEST_XRGB_IMAGE[4096] =
|
||||
0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5
|
||||
};
|
||||
|
||||
static int test_memcmp_offset(const BYTE* mem1, const BYTE* mem2, int size)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
while ((index < size) && (*mem1 == *mem2))
|
||||
{
|
||||
mem1++;
|
||||
mem2++;
|
||||
index++;
|
||||
}
|
||||
|
||||
return (index == size) ? 1 : -index;
|
||||
}
|
||||
|
||||
static int test_memcmp_count(const BYTE* mem1, const BYTE* mem2, int size)
|
||||
static int test_bmp_cmp_count(const BYTE* mem1, const BYTE* mem2, int size, int channel, int margin)
|
||||
{
|
||||
int error;
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
|
||||
size /= 4;
|
||||
mem1 += channel;
|
||||
mem2 += channel;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
{
|
||||
if (*mem1 != *mem2)
|
||||
count++;
|
||||
{
|
||||
error = (*mem1 > *mem2) ? *mem1 - *mem2 : *mem2 - *mem1;
|
||||
|
||||
mem1++;
|
||||
mem2++;
|
||||
if (error > margin)
|
||||
count++;
|
||||
}
|
||||
|
||||
mem1 += 4;
|
||||
mem2 += 4;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static int test_bmp_cmp_dump(const BYTE* actual, const BYTE* expected, int size, int channel, int margin)
|
||||
{
|
||||
int x, y;
|
||||
int error[3];
|
||||
UINT32 pixel;
|
||||
int count = 0;
|
||||
int index = 0;
|
||||
BYTE R, G, B;
|
||||
BYTE eR, eG, eB;
|
||||
INT16 Y, Cb, Cr;
|
||||
|
||||
size /= 4;
|
||||
actual += channel;
|
||||
expected += channel;
|
||||
|
||||
for (index = 0; index < size; index++)
|
||||
{
|
||||
if (*actual != *expected)
|
||||
{
|
||||
pixel = *((UINT32*) &actual[-channel]);
|
||||
GetRGB32(R, G, B, pixel);
|
||||
|
||||
pixel = *((UINT32*) &expected[-channel]);
|
||||
GetRGB32(eR, eG, eB, pixel);
|
||||
|
||||
Y = TEST_Y_COMPONENT[index];
|
||||
Cb = TEST_CB_COMPONENT[index];
|
||||
Cr = TEST_CR_COMPONENT[index];
|
||||
|
||||
x = index % 64;
|
||||
y = (index - x) / 64;
|
||||
|
||||
error[0] = (R > eR) ? R - eR : eR - R;
|
||||
error[1] = (G > eG) ? G - eG : eG - G;
|
||||
error[2] = (B > eB) ? B - eB : eB - B;
|
||||
|
||||
if ((error[0] > margin) || (error[1] > margin) || (error[2] > margin))
|
||||
{
|
||||
printf("(%2d,%2d) Y: %+5d Cb: %+5d Cr: %+5d R: %03d/%03d G: %03d/%03d B: %03d/%03d %d %d %d\n",
|
||||
x, y, Y, Cb, Cr, R, eR, G, eG, B, eB, R - eR, G - eG, B - eB);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
actual += 4;
|
||||
expected += 4;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static void test_fill_bitmap_channel(BYTE* data, int width, int height, BYTE value, int nChannel)
|
||||
{
|
||||
int x, y;
|
||||
BYTE* pChannel;
|
||||
|
||||
pChannel = data + nChannel;
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
*pChannel = value;
|
||||
pChannel += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define TEST_FP_TYPE float
|
||||
|
||||
static TEST_FP_TYPE TEST_YCbCrToRGB_01[4] = { 1.403f, 0.344f, 0.714f, 1.770f };
|
||||
static TEST_FP_TYPE TEST_YCbCrToRGB_02[4] = { 1.402525f, 0.343730f, 0.714401f, 1.769905f };
|
||||
static TEST_FP_TYPE TEST_YCbCrToRGB_03[4] = { 1.402524948120117L, 0.3437300026416779L, 0.7144010066986084L, 1.769904971122742L };
|
||||
|
||||
static INT16 TEST_YCbCr_01[3] = { +3443, -1863, +272 };
|
||||
static BYTE TEST_RGB_01[3] = { 247, 249, 132 };
|
||||
|
||||
static INT16 TEST_YCbCr_02[3] = { +1086, +1584, -2268 };
|
||||
static BYTE TEST_RGB_02[3] = { 62, 195, 249 };
|
||||
|
||||
static INT16 TEST_YCbCr_03[3] = { -576, +2002, -2179 };
|
||||
static BYTE TEST_RGB_03[3] = { 15, 137, 221 };
|
||||
|
||||
int test_YCbCr_fp(TEST_FP_TYPE coeffs[4], INT16 YCbCr[3], BYTE RGB[3])
|
||||
{
|
||||
INT16 R, G, B;
|
||||
TEST_FP_TYPE Y, Cb, Cr;
|
||||
TEST_FP_TYPE fR, fG, fB;
|
||||
TEST_FP_TYPE fR1, fR2;
|
||||
|
||||
Y = (TEST_FP_TYPE) (YCbCr[0] + 4096);
|
||||
Cb = (TEST_FP_TYPE) (YCbCr[1]);
|
||||
Cr = (TEST_FP_TYPE) (YCbCr[2]);
|
||||
|
||||
#if 1
|
||||
fR1 = Cr * coeffs[0];
|
||||
fR2 = fR1 + Y + 16.0f;
|
||||
|
||||
fR = ((Cr * coeffs[0]) + Y + 16.0f);
|
||||
fG = (Y - (Cb * coeffs[1]) - (Cr * coeffs[2]) + 16.0f);
|
||||
fB = ((Cb * coeffs[3]) + Y + 16.0f);
|
||||
|
||||
printf("fR: %f fG: %f fB: %f fY: %f\n", fR, fG, fB, Y);
|
||||
|
||||
R = (INT16) fR;
|
||||
G = (INT16) fG;
|
||||
B = (INT16) fB;
|
||||
|
||||
printf("mR: %d mG: %d mB: %d\n",
|
||||
(R - 16) % 32, (G - 16) % 32, (B - 16) % 32);
|
||||
|
||||
printf("iR: %d iG: %d iB: %d\n", R, G, B);
|
||||
|
||||
R >>= 5;
|
||||
G >>= 5;
|
||||
B >>= 5;
|
||||
|
||||
printf("R5: %d G5: %d B5: %d\n", R, G, B);
|
||||
|
||||
#else
|
||||
R = ((INT16) (((Cr * coeffs[0]) + Y + 16.0f)) >> 5);
|
||||
G = ((INT16) ((Y - (Cb * coeffs[1]) - (Cr * coeffs[2]) + 16.0f)) >> 5);
|
||||
B = ((INT16) (((Cb * coeffs[3]) + Y + 16.0f)) >> 5);
|
||||
#endif
|
||||
|
||||
if (R < 0)
|
||||
R = 0;
|
||||
else if (R > 255)
|
||||
R = 255;
|
||||
|
||||
if (G < 0)
|
||||
G = 0;
|
||||
else if (G > 255)
|
||||
G = 255;
|
||||
|
||||
if (B < 0)
|
||||
B = 0;
|
||||
else if (B > 255)
|
||||
B = 255;
|
||||
|
||||
printf("--------------------------------\n");
|
||||
printf("R: A: %3d E: %3d %s\n", R, RGB[0], (R == RGB[0]) ? "" : "***");
|
||||
printf("G: A: %3d E: %3d %s\n", G, RGB[1], (G == RGB[1]) ? "" : "***");
|
||||
printf("B: A: %3d E: %3d %s\n", B, RGB[2], (B == RGB[2]) ? "" : "***");
|
||||
printf("Y: %+5d Cb: %+5d Cr: %+5d\n", YCbCr[0], YCbCr[1], YCbCr[2]);
|
||||
//printf("[0]: %20.20lf\n", coeffs[0]);
|
||||
//printf("[1]: %20.20lf\n", coeffs[1]);
|
||||
//printf("[2]: %20.20lf\n", coeffs[2]);
|
||||
//printf("[3]: %20.20lf\n", coeffs[3]);
|
||||
printf("--------------------------------\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_YCbCr_pixels()
|
||||
{
|
||||
if (0)
|
||||
{
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_01, TEST_YCbCr_01, TEST_RGB_01);
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_01, TEST_YCbCr_02, TEST_RGB_02);
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_01, TEST_YCbCr_03, TEST_RGB_03);
|
||||
}
|
||||
|
||||
if (1)
|
||||
{
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_02, TEST_YCbCr_01, TEST_RGB_01);
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_02, TEST_YCbCr_02, TEST_RGB_02);
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_02, TEST_YCbCr_03, TEST_RGB_03);
|
||||
}
|
||||
|
||||
if (0)
|
||||
{
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_03, TEST_YCbCr_01, TEST_RGB_01);
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_03, TEST_YCbCr_02, TEST_RGB_02);
|
||||
test_YCbCr_fp(TEST_YCbCrToRGB_03, TEST_YCbCr_03, TEST_RGB_03);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TestPrimitivesYCbCr(int argc, char* argv[])
|
||||
{
|
||||
int cmp;
|
||||
int cnt;
|
||||
int size;
|
||||
int cnt[3];
|
||||
float err[3];
|
||||
BYTE* actual;
|
||||
BYTE* expected;
|
||||
int margin = 1;
|
||||
INT16* pYCbCr[3];
|
||||
const primitives_t* prims = primitives_get();
|
||||
static const prim_size_t roi_64x64 = { 64, 64 };
|
||||
|
||||
//return test_YCbCr_pixels();
|
||||
|
||||
expected = (BYTE*) TEST_XRGB_IMAGE;
|
||||
|
||||
size = 64 * 64 * 4;
|
||||
@@ -2159,21 +2339,47 @@ int TestPrimitivesYCbCr(int argc, char* argv[])
|
||||
_aligned_free(pSrcDst[2]);
|
||||
}
|
||||
|
||||
cmp = test_memcmp_offset(actual, expected, size);
|
||||
cnt = test_memcmp_count(actual, expected, size);
|
||||
|
||||
if (cmp <= 0)
|
||||
if (0)
|
||||
{
|
||||
cmp *= -1;
|
||||
float rate = ((float) cnt) / ((float) size) * 100.0f;
|
||||
test_fill_bitmap_channel(actual, 64, 64, 0, 2); /* red */
|
||||
test_fill_bitmap_channel(expected, 64, 64, 0, 2); /* red */
|
||||
}
|
||||
|
||||
printf("YCbCr to RGB conversion failure\n");
|
||||
if (0)
|
||||
{
|
||||
test_fill_bitmap_channel(actual, 64, 64, 0, 1); /* green */
|
||||
test_fill_bitmap_channel(expected, 64, 64, 0, 1); /* green */
|
||||
}
|
||||
|
||||
printf("Actual, Expected (offset: %d diff: %d/%d = %d%%):\n",
|
||||
cmp, cnt, size, (int) rate);
|
||||
if (0)
|
||||
{
|
||||
test_fill_bitmap_channel(actual, 64, 64, 0, 0); /* blue */
|
||||
test_fill_bitmap_channel(expected, 64, 64, 0, 0); /* blue */
|
||||
}
|
||||
|
||||
winpr_HexDump(&actual[cmp], 16);
|
||||
winpr_HexDump(&expected[cmp], 16);
|
||||
cnt[2] = test_bmp_cmp_count(actual, expected, size, 2, margin); /* red */
|
||||
err[2] = ((float) cnt[2]) / ((float) size / 4) * 100.0f;
|
||||
|
||||
cnt[1] = test_bmp_cmp_count(actual, expected, size, 1, margin); /* green */
|
||||
err[1] = ((float) cnt[1]) / ((float) size / 4) * 100.0f;
|
||||
|
||||
cnt[0] = test_bmp_cmp_count(actual, expected, size, 0, margin); /* blue */
|
||||
err[0] = ((float) cnt[0]) / ((float) size / 4) * 100.0f;
|
||||
|
||||
if (cnt[0] || cnt[1] || cnt[2])
|
||||
{
|
||||
printf("Red Error Dump:\n");
|
||||
test_bmp_cmp_dump(actual, expected, size, 2, margin); /* red */
|
||||
|
||||
printf("Green Error Dump:\n");
|
||||
test_bmp_cmp_dump(actual, expected, size, 1, margin); /* green */
|
||||
|
||||
printf("Blue Error Dump:\n");
|
||||
test_bmp_cmp_dump(actual, expected, size, 0, margin); /* blue */
|
||||
|
||||
printf("R: diff: %d (%f%%)\n", cnt[2], err[2]);
|
||||
printf("G: diff: %d (%f%%)\n", cnt[1], err[1]);
|
||||
printf("B: diff: %d (%f%%)\n", cnt[0], err[0]);
|
||||
}
|
||||
|
||||
_aligned_free(actual);
|
||||
|
||||
@@ -28,7 +28,7 @@ static const float TEST_TIME = 4.0;
|
||||
|
||||
extern BOOL g_TestPrimitivesPerformance;
|
||||
|
||||
extern pstatus_t general_YCoCgRToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep,
|
||||
extern pstatus_t general_YCoCgToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep,
|
||||
BYTE *pDst, INT32 dstStep, UINT32 width, UINT32 height,
|
||||
UINT8 shift, BOOL withAlpha, BOOL invert);
|
||||
extern pstatus_t ssse3_YCoCgRToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep,
|
||||
@@ -48,9 +48,9 @@ int test_YCoCgRToRGB_8u_AC4R_func(void)
|
||||
testStr[0] = '\0';
|
||||
get_random_data(in, sizeof(in));
|
||||
|
||||
general_YCoCgRToRGB_8u_AC4R((const BYTE *) (in+1), 63*4,
|
||||
general_YCoCgToRGB_8u_AC4R((const BYTE *) (in+1), 63*4,
|
||||
(BYTE *) out_c, 63*4, 63, 61, 2, TRUE, FALSE);
|
||||
general_YCoCgRToRGB_8u_AC4R((const BYTE *) (in+1), 63*4,
|
||||
general_YCoCgToRGB_8u_AC4R((const BYTE *) (in+1), 63*4,
|
||||
(BYTE *) out_c_inv, 63*4, 63, 61, 2, TRUE, TRUE);
|
||||
#ifdef WITH_SSE2
|
||||
if (IsProcessorFeaturePresentEx(PF_EX_SSSE3))
|
||||
@@ -86,7 +86,7 @@ int test_YCoCgRToRGB_8u_AC4R_func(void)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
STD_SPEED_TEST(
|
||||
ycocg_to_rgb_speed, const BYTE, BYTE, PRIM_NOP,
|
||||
TRUE, general_YCoCgRToRGB_8u_AC4R(src1, 64*4, dst, 64*4, 64, 64, 2, FALSE, FALSE),
|
||||
TRUE, general_YCoCgToRGB_8u_AC4R(src1, 64*4, dst, 64*4, 64, 64, 2, FALSE, FALSE),
|
||||
#ifdef WITH_SSE2
|
||||
TRUE, ssse3_YCoCgRToRGB_8u_AC4R(src1, 64*4, dst, 64*4, 64, 64, 2, FALSE, FALSE),
|
||||
PF_EX_SSSE3, TRUE,
|
||||
|
||||
@@ -22,10 +22,6 @@
|
||||
* Define GOOGLE_PROFILER if you want gperftools included.
|
||||
*/
|
||||
|
||||
#ifdef _GNUC_
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __MEASURE_H_INCLUDED__
|
||||
#define __MEASURE_H_INCLUDED__
|
||||
|
||||
@@ -35,9 +31,21 @@
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <winpr/crt.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define PROFILER_START(_prefix_)
|
||||
#define PROFILER_STOP
|
||||
|
||||
#define MEASURE_LOOP_START(_prefix_, _count_)
|
||||
#define MEASURE_LOOP_STOP
|
||||
#define MEASURE_GET_RESULTS(_result_)
|
||||
#define MEASURE_SHOW_RESULTS(_result_)
|
||||
#define MEASURE_SHOW_RESULTS_SCALED(_scale_, _label_)
|
||||
#define MEASURE_TIMED(_label_, _init_iter_, _test_time_, _result_, _call_)
|
||||
|
||||
#else
|
||||
|
||||
#ifdef GOOGLE_PROFILER
|
||||
#include <gperftools/profiler.h>
|
||||
@@ -122,4 +130,6 @@ extern void _floatprint(float t, char *output);
|
||||
MEASURE_SHOW_RESULTS(_result_); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // __MEASURE_H_INCLUDED__
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
|
||||
#include "prim_test.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#include <winpr/sysinfo.h>
|
||||
#include <winpr/platform.h>
|
||||
@@ -83,6 +85,10 @@ void get_random_data(void *buffer, size_t size)
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
float _delta_time(const struct timespec *t0, const struct timespec *t1) { return 0.0f; }
|
||||
#else
|
||||
float _delta_time(const struct timespec *t0, const struct timespec *t1)
|
||||
{
|
||||
INT64 secs = (INT64) (t1->tv_sec) - (INT64) (t0->tv_sec);
|
||||
@@ -98,6 +104,7 @@ float _delta_time(const struct timespec *t0, const struct timespec *t1)
|
||||
retval = (double) secs + (double) nsecs / (double) 1000000000.0;
|
||||
return (retval < 0.0) ? 0.0 : (float) retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
void _floatprint(float t, char *output)
|
||||
|
||||
@@ -13,10 +13,6 @@
|
||||
* this code may be covered by patents by HP, Microsoft, or other parties.
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#ifndef __PRIMTEST_H_INCLUDED__
|
||||
#define __PRIMTEST_H_INCLUDED__
|
||||
|
||||
@@ -34,7 +30,11 @@
|
||||
#include <ippi.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ALIGN(x) x
|
||||
#else
|
||||
#define ALIGN(x) x DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)
|
||||
#endif
|
||||
|
||||
#define ABS(_x_) ((_x_) < 0 ? (-(_x_)) : (_x_))
|
||||
#define MAX_TEST_SIZE 4096
|
||||
@@ -158,6 +158,14 @@ extern int test_or_32u_speed(void);
|
||||
|
||||
#define PRIM_NOP do {} while (0)
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define STD_SPEED_TEST( \
|
||||
_name_, _srctype_, _dsttype_, _prework_, \
|
||||
_doNormal_, _funcNormal_, \
|
||||
_doOpt_, _funcOpt_, _flagOpt_, _flagExt_, \
|
||||
_doIPP_, _funcIPP_)
|
||||
#else
|
||||
#define STD_SPEED_TEST( \
|
||||
_name_, _srctype_, _dsttype_, _prework_, \
|
||||
_doNormal_, _funcNormal_, \
|
||||
@@ -228,5 +236,6 @@ static void _name_( \
|
||||
} \
|
||||
free(resultNormal); free(resultOpt); free(resultIPP); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !__PRIMTEST_H_INCLUDED__
|
||||
|
||||
@@ -244,7 +244,7 @@ static void svc_plugin_process_terminated(rdpSvcPlugin* plugin)
|
||||
|
||||
if (plugin->data_in)
|
||||
{
|
||||
Stream_Free(plugin->data_in, TRUE);
|
||||
Stream_Release(plugin->data_in);
|
||||
plugin->data_in = NULL;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user