From 8ca74a27666e659f1a979d26c38c055272d6f5f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 7 Aug 2013 21:47:03 -0400 Subject: [PATCH 01/25] libfreerdp-core: add support for server-side bitmap updates --- libfreerdp/core/fastpath.c | 2 +- libfreerdp/core/update.c | 144 ++++++++++++++++++++++++++++--------- 2 files changed, 110 insertions(+), 36 deletions(-) diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 844816024..67106c7b7 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -178,7 +178,7 @@ static BOOL fastpath_recv_update_common(rdpFastPath* fastpath, wStream* s) switch (updateType) { case UPDATE_TYPE_BITMAP: - if (!update_read_bitmap(update, s, &update->bitmap_update)) + if (!update_read_bitmap_update(update, s, &update->bitmap_update)) return FALSE; IFCALL(update->BitmapUpdate, context, &update->bitmap_update); break; diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 442139d9a..ce03d7c5e 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -68,80 +68,139 @@ BOOL update_recv_orders(rdpUpdate* update, wStream* s) return TRUE; } -BOOL update_read_bitmap_data(wStream* s, BITMAP_DATA* bitmap_data) +BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData) { if (Stream_GetRemainingLength(s) < 18) return FALSE; - Stream_Read_UINT16(s, bitmap_data->destLeft); - Stream_Read_UINT16(s, bitmap_data->destTop); - Stream_Read_UINT16(s, bitmap_data->destRight); - Stream_Read_UINT16(s, bitmap_data->destBottom); - Stream_Read_UINT16(s, bitmap_data->width); - Stream_Read_UINT16(s, bitmap_data->height); - Stream_Read_UINT16(s, bitmap_data->bitsPerPixel); - Stream_Read_UINT16(s, bitmap_data->flags); - Stream_Read_UINT16(s, bitmap_data->bitmapLength); + Stream_Read_UINT16(s, bitmapData->destLeft); + Stream_Read_UINT16(s, bitmapData->destTop); + Stream_Read_UINT16(s, bitmapData->destRight); + Stream_Read_UINT16(s, bitmapData->destBottom); + Stream_Read_UINT16(s, bitmapData->width); + Stream_Read_UINT16(s, bitmapData->height); + Stream_Read_UINT16(s, bitmapData->bitsPerPixel); + Stream_Read_UINT16(s, bitmapData->flags); + Stream_Read_UINT16(s, bitmapData->bitmapLength); - if (bitmap_data->flags & BITMAP_COMPRESSION) + if (bitmapData->flags & BITMAP_COMPRESSION) { - if (!(bitmap_data->flags & NO_BITMAP_COMPRESSION_HDR)) + if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR)) { - Stream_Read_UINT16(s, bitmap_data->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ - Stream_Read_UINT16(s, bitmap_data->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ - Stream_Read_UINT16(s, bitmap_data->cbScanWidth); /* cbScanWidth (2 bytes) */ - Stream_Read_UINT16(s, bitmap_data->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ - bitmap_data->bitmapLength = bitmap_data->cbCompMainBodySize; + Stream_Read_UINT16(s, bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ + Stream_Read_UINT16(s, bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ + Stream_Read_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */ + Stream_Read_UINT16(s, bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ + bitmapData->bitmapLength = bitmapData->cbCompMainBodySize; } - bitmap_data->compressed = TRUE; - Stream_GetPointer(s, bitmap_data->bitmapDataStream); - Stream_Seek(s, bitmap_data->bitmapLength); + bitmapData->compressed = TRUE; + Stream_GetPointer(s, bitmapData->bitmapDataStream); + Stream_Seek(s, bitmapData->bitmapLength); } else { - if (Stream_GetRemainingLength(s) < bitmap_data->bitmapLength) + if (Stream_GetRemainingLength(s) < bitmapData->bitmapLength) return FALSE; - bitmap_data->compressed = FALSE; - Stream_GetPointer(s, bitmap_data->bitmapDataStream); - Stream_Seek(s, bitmap_data->bitmapLength); + + bitmapData->compressed = FALSE; + Stream_GetPointer(s, bitmapData->bitmapDataStream); + Stream_Seek(s, bitmapData->bitmapLength); } return TRUE; } -BOOL update_read_bitmap(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmap_update) +BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapData) +{ + Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength); + + Stream_Write_UINT16(s, bitmapData->destLeft); + Stream_Write_UINT16(s, bitmapData->destTop); + Stream_Write_UINT16(s, bitmapData->destRight); + Stream_Write_UINT16(s, bitmapData->destBottom); + Stream_Write_UINT16(s, bitmapData->width); + Stream_Write_UINT16(s, bitmapData->height); + Stream_Write_UINT16(s, bitmapData->bitsPerPixel); + Stream_Write_UINT16(s, bitmapData->flags); + Stream_Write_UINT16(s, bitmapData->bitmapLength); + + if (bitmapData->compressed) + bitmapData->flags |= BITMAP_COMPRESSION; + + if (update->context->settings->NoBitmapCompressionHeader) + bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR; + + if (bitmapData->flags & BITMAP_COMPRESSION) + { + if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR)) + { + Stream_Write_UINT16(s, bitmapData->cbCompFirstRowSize); /* cbCompFirstRowSize (2 bytes) */ + Stream_Write_UINT16(s, bitmapData->cbCompMainBodySize); /* cbCompMainBodySize (2 bytes) */ + Stream_Write_UINT16(s, bitmapData->cbScanWidth); /* cbScanWidth (2 bytes) */ + Stream_Write_UINT16(s, bitmapData->cbUncompressedSize); /* cbUncompressedSize (2 bytes) */ + } + + Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength); + } + else + { + Stream_Write(s, bitmapData->bitmapDataStream, bitmapData->bitmapLength); + } + + return TRUE; +} + +BOOL update_read_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate) { int i; if (Stream_GetRemainingLength(s) < 2) return FALSE; - Stream_Read_UINT16(s, bitmap_update->number); /* numberRectangles (2 bytes) */ + Stream_Read_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */ - if (bitmap_update->number > bitmap_update->count) + if (bitmapUpdate->number > bitmapUpdate->count) { UINT16 count; - count = bitmap_update->number * 2; + count = bitmapUpdate->number * 2; - bitmap_update->rectangles = (BITMAP_DATA*) realloc(bitmap_update->rectangles, + bitmapUpdate->rectangles = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles, sizeof(BITMAP_DATA) * count); - memset(&bitmap_update->rectangles[bitmap_update->count], 0, - sizeof(BITMAP_DATA) * (count - bitmap_update->count)); + memset(&bitmapUpdate->rectangles[bitmapUpdate->count], 0, + sizeof(BITMAP_DATA) * (count - bitmapUpdate->count)); - bitmap_update->count = count; + bitmapUpdate->count = count; } /* rectangles */ - for (i = 0; i < (int) bitmap_update->number; i++) + for (i = 0; i < (int) bitmapUpdate->number; i++) { - if (!update_read_bitmap_data(s, &bitmap_update->rectangles[i])) + if (!update_read_bitmap_data(update, s, &bitmapUpdate->rectangles[i])) return FALSE; } return TRUE; } +BOOL update_write_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate) +{ + int i; + + Stream_EnsureRemainingCapacity(s, 32); + + Stream_Write_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */ + + /* rectangles */ + for (i = 0; i < (int) bitmapUpdate->number; i++) + { + if (!update_write_bitmap_data(update, s, &bitmapUpdate->rectangles[i])) + return FALSE; + } + + return TRUE; +} + BOOL update_read_palette(rdpUpdate* update, wStream* s, PALETTE_UPDATE* palette_update) { int i; @@ -369,7 +428,7 @@ BOOL update_recv(rdpUpdate* update, wStream* s) break; case UPDATE_TYPE_BITMAP: - if (!update_read_bitmap(update, s, &update->bitmap_update)) + if (!update_read_bitmap_update(update, s, &update->bitmap_update)) return FALSE; IFCALL(update->BitmapUpdate, context, &update->bitmap_update); break; @@ -793,6 +852,20 @@ static void update_send_desktop_resize(rdpContext* context) rdp_server_reactivate(context->rdp); } +static void update_send_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate) +{ + wStream* s; + rdpRdp* rdp = context->rdp; + rdpUpdate* update = context->update; + + s = fastpath_update_pdu_init(rdp->fastpath); + + update_write_bitmap_update(update, s, bitmapUpdate); + + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s); + Stream_Release(s); +} + /** * Primary Drawing Orders */ @@ -1423,6 +1496,7 @@ void update_register_server_callbacks(rdpUpdate* update) update->SetBounds = update_set_bounds; update->Synchronize = update_send_synchronize; update->DesktopResize = update_send_desktop_resize; + update->BitmapUpdate = update_send_bitmap_update; update->SurfaceBits = update_send_surface_bits; update->SurfaceFrameMarker = update_send_surface_frame_marker; update->SurfaceCommand = update_send_surface_command; From f1c0ffb130d7c45531b6569bd6b3b9ecaed3b8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 7 Aug 2013 23:46:17 -0400 Subject: [PATCH 02/25] libfreerdp-core: fix sending of bitmap updates --- libfreerdp/core/update.c | 36 +++++++++++++++++++++++------------- libfreerdp/core/update.h | 2 +- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index ce03d7c5e..bf6829174 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -34,15 +34,13 @@ #include #include -/* -static const char* const UPDATE_TYPE_STRINGS[] = +const char* const UPDATE_TYPE_STRINGS[] = { "Orders", "Bitmap", "Palette", "Synchronize" }; -*/ extern const BYTE PRIMARY_DRAWING_ORDER_FIELD_BYTES[]; @@ -107,6 +105,7 @@ BOOL update_read_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmapD Stream_GetPointer(s, bitmapData->bitmapDataStream); Stream_Seek(s, bitmapData->bitmapLength); } + return TRUE; } @@ -114,6 +113,18 @@ BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmap { Stream_EnsureRemainingCapacity(s, 64 + bitmapData->bitmapLength); + bitmapData->flags = 0; + bitmapData->cbCompFirstRowSize = 0; + + if (bitmapData->compressed) + bitmapData->flags |= BITMAP_COMPRESSION; + + if (update->context->settings->NoBitmapCompressionHeader) + { + bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR; + bitmapData->cbCompMainBodySize = bitmapData->bitmapLength; + } + Stream_Write_UINT16(s, bitmapData->destLeft); Stream_Write_UINT16(s, bitmapData->destTop); Stream_Write_UINT16(s, bitmapData->destRight); @@ -124,12 +135,6 @@ BOOL update_write_bitmap_data(rdpUpdate* update, wStream* s, BITMAP_DATA* bitmap Stream_Write_UINT16(s, bitmapData->flags); Stream_Write_UINT16(s, bitmapData->bitmapLength); - if (bitmapData->compressed) - bitmapData->flags |= BITMAP_COMPRESSION; - - if (update->context->settings->NoBitmapCompressionHeader) - bitmapData->flags |= NO_BITMAP_COMPRESSION_HDR; - if (bitmapData->flags & BITMAP_COMPRESSION) { if (!(bitmapData->flags & NO_BITMAP_COMPRESSION_HDR)) @@ -168,7 +173,7 @@ BOOL update_read_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bit bitmapUpdate->rectangles = (BITMAP_DATA*) realloc(bitmapUpdate->rectangles, sizeof(BITMAP_DATA) * count); - memset(&bitmapUpdate->rectangles[bitmapUpdate->count], 0, + ZeroMemory(&bitmapUpdate->rectangles[bitmapUpdate->count], sizeof(BITMAP_DATA) * (count - bitmapUpdate->count)); bitmapUpdate->count = count; @@ -189,6 +194,8 @@ BOOL update_write_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bi Stream_EnsureRemainingCapacity(s, 32); + Stream_Write_UINT16(s, UPDATE_TYPE_BITMAP); /* updateType */ + Stream_Write_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */ /* rectangles */ @@ -413,7 +420,7 @@ BOOL update_recv(rdpUpdate* update, wStream* s) Stream_Read_UINT16(s, updateType); /* updateType (2 bytes) */ - //fprintf(stderr, "%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); + //printf("%s Update Data PDU\n", UPDATE_TYPE_STRINGS[updateType]); IFCALL(update->BeginPaint, context); @@ -858,11 +865,14 @@ static void update_send_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap rdpRdp* rdp = context->rdp; rdpUpdate* update = context->update; + update_force_flush(context); + s = fastpath_update_pdu_init(rdp->fastpath); - update_write_bitmap_update(update, s, bitmapUpdate); - fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_BITMAP, s); + + update_force_flush(context); + Stream_Release(s); } diff --git a/libfreerdp/core/update.h b/libfreerdp/core/update.h index c3088f299..8c4dd8704 100644 --- a/libfreerdp/core/update.h +++ b/libfreerdp/core/update.h @@ -45,7 +45,7 @@ void update_free_bitmap(BITMAP_UPDATE* bitmap_update); void update_reset_state(rdpUpdate* update); void update_post_connect(rdpUpdate* update); -BOOL update_read_bitmap(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmap_update); +BOOL update_read_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bitmapUpdate); BOOL update_read_palette(rdpUpdate* update, wStream* s, PALETTE_UPDATE* palette_update); BOOL update_recv_play_sound(rdpUpdate* update, wStream* s); BOOL update_recv_pointer(rdpUpdate* update, wStream* s); From 1d1d04149cd58431e9c20e00e71ff1aa766f496c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 8 Aug 2013 15:49:24 -0400 Subject: [PATCH 03/25] mfreerdp: cleanup makefiles --- client/Mac/CMakeLists.txt | 45 ++++++++++++++++++-------------- client/Mac/MRDPView.m | 4 --- client/Mac/cli/CMakeLists.txt | 48 +++++++++++++++++------------------ 3 files changed, 49 insertions(+), 48 deletions(-) diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 20ce92d82..6f2627460 100755 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -1,10 +1,10 @@ + project(MacFreeRDP-library) set(MODULE_NAME "MacFreeRDP-library") set(MODULE_OUTPUT_NAME "MacFreeRDP") -set(MODULE_PREFIX "FREERDP_CLIENT_MAC-LIB") +set(MODULE_PREFIX "FREERDP_CLIENT_MAC_LIBRARY") -# Import frameworks find_library(FOUNDATION_LIBRARY Foundation) find_library(COCOA_LIBRARY Cocoa) find_library(APPKIT_LIBRARY AppKit) @@ -21,34 +21,45 @@ set(MACOSX_BUNDLE_SHORT_VERSION_STRING 1.1.0) set(MACOSX_BUNDLE_BUNDLE_VERSION 1.1.0) set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013. All Rights Reserved.") -set(${MODULE_NAME}_RESOURCES "en.lproj/InfoPlist.strings") +set(${MODULE_PREFIX}_XIBS PasswordDialog.xib) -# OS X Interface Builder files -file(GLOB ${MODULE_NAME}_XIBS *.xib) +set(${MODULE_PREFIX}_SOURCES "") -# source files -file(GLOB ${MODULE_NAME}_SRC *.c *.m) +set(${MODULE_PREFIX}_OBJECTIVE_SOURCES + main.m + mf_client.m + MRDPCursor.m + MRDPView.m + PasswordDialog.m) -# header files -file(GLOB ${MODULE_NAME}_HEADERS *.h) +list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES}) + +set(${MODULE_PREFIX}_HEADERS + mfreerdp.h + mf_client.h + MRDPCursor.h + MRDPView.h + PasswordDialog.h) + +set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings") # Include XIB file in Xcode resources. if("${CMAKE_GENERATOR}" MATCHES "Xcode") message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}") - set(${MODULE_NAME}_RESOURCES ${${MODULE_NAME}_RESOURCES} ${${MODULE_NAME}_XIBS}) + set(${MODULE_PREFIX}_RESOURCES ${${MODULE_PREFIX}_RESOURCES} ${${MODULE_PREFIX}_XIBS}) endif() add_library(${MODULE_NAME} SHARED ../common/client.c - ${${MODULE_NAME}_SRC} - ${${MODULE_NAME}_HEADERS} - ${${MODULE_NAME}_RESOURCES}) + ${${MODULE_PREFIX}_SOURCES} + ${${MODULE_PREFIX}_HEADERS} + ${${MODULE_PREFIX}_RESOURCES}) set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAME}") # configures the framework to always be looked for in the application bundle in the Frameworks sub-folder. -SET_TARGET_PROPERTIES(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_INSTALL_PATH @executable_path/../Frameworks/) +set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_INSTALL_PATH @executable_path/../Frameworks/) set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH} @@ -57,10 +68,6 @@ set_target_properties(${MODULE_NAME} PROPERTIES # Support for automatic reference counting requires non-fragile abi. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") -set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)") - -set(MODULE_VERSION, 1.1.0) - set_target_properties(${MODULE_NAME} PROPERTIES FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER com.awakecoding.${MODULE_NAME} @@ -159,7 +166,7 @@ endif() # endif() # Copy the public header files into the framework -foreach(HEADER ${${MODULE_NAME}_HEADERS}) +foreach(HEADER ${${MODULE_PREFIX}_HEADERS}) # message("adding post-build dependency: ${LIB}") add_custom_command(TARGET ${MODULE_NAME} POST_BUILD COMMAND ditto ${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/ diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 8facc7d1b..d12f2da3a 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -65,7 +65,6 @@ #import "freerdp/client/file.h" #import "freerdp/client/cmdline.h" - /****************************************** Forward declarations ******************************************/ @@ -804,9 +803,6 @@ BOOL mac_pre_connect(freerdp* instance) instance->update->EndPaint = mac_end_paint; instance->update->SetBounds = mac_set_bounds; //instance->update->BitmapUpdate = mac_bitmap_update; - - mfContext *mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; settings = instance->settings; diff --git a/client/Mac/cli/CMakeLists.txt b/client/Mac/cli/CMakeLists.txt index 81f940d1d..09933a33c 100644 --- a/client/Mac/cli/CMakeLists.txt +++ b/client/Mac/cli/CMakeLists.txt @@ -1,4 +1,5 @@ -project(MacFreeRDP-client) + +project(MacFreeRDP) set(MODULE_NAME "MacFreeRDP") set(MODULE_OUTPUT_NAME "MacFreeRDP") @@ -9,7 +10,6 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min find_library(FOUNDATION_LIBRARY Foundation) find_library(COCOA_LIBRARY Cocoa) find_library(APPKIT_LIBRARY AppKit) -#find_library(FREERDP_LIBRARY NAMES MacFreeRDP PATHS ${CMAKE_CURRENT_BINARY_DIR}/../${CONFIGURATION}) set(MACOSX_BUNDLE_INFO_STRING "MacFreeRDP") set(MACOSX_BUNDLE_ICON_FILE "FreeRDP.icns") @@ -27,28 +27,32 @@ set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication") mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY) set(APP_TYPE MACOSX_BUNDLE) -# OS X Interface Builder files -file(GLOB ${MODULE_NAME}_XIBS *.xib) +set(${MODULE_PREFIX}_XIBS MainMenu.xib) -set(${MODULE_NAME}_RESOURCES ${MACOSX_BUNDLE_ICON_FILE}) +set(${MODULE_PREFIX}_SOURCES "") + +set(${MODULE_PREFIX}_OBJECTIVE_SOURCES + main.m + AppDelegate.m) + +list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES}) + +set(${MODULE_PREFIX}_HEADERS + AppDelegate.h) + +set(${MODULE_PREFIX}_RESOURCES ${MACOSX_BUNDLE_ICON_FILE}) # Include XIB file in Xcode resources. if("${CMAKE_GENERATOR}" MATCHES "Xcode") message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}") - set(${MODULE_NAME}_RESOURCES ${${MODULE_NAME}_RESOURCES} ${${MODULE_NAME}_XIBS}) -endif("${CMAKE_GENERATOR}" MATCHES "Xcode") - -# Headers -file(GLOB ${MODULE_NAME}_HEADERS *.h) - -# Source -file(GLOB ${MODULE_NAME}_SOURCES *.m) + set(${MODULE_PREFIX}_RESOURCES ${${MODULE_PREFIX}_RESOURCES} ${${MODULE_PREFIX}_XIBS}) +endif() add_executable(${MODULE_NAME} ${APP_TYPE} - ${${MODULE_NAME}_HEADERS} - ${${MODULE_NAME}_SOURCES} - ${${MODULE_NAME}_RESOURCES}) + ${${MODULE_PREFIX}_HEADERS} + ${${MODULE_PREFIX}_SOURCES} + ${${MODULE_PREFIX}_RESOURCES}) set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAME}") @@ -56,11 +60,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_OUTPUT_NAM configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) # This allows for automatic xib to nib ibitool -set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_NAME}_RESOURCES}") - -# Automatic ref counting -# temporary turn off for x86_64 build issue -# set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES) +set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_PREFIX}_RESOURCES}") # Support for automatic reference counting requires non-fragile abi. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") @@ -72,8 +72,6 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F../") set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "${XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS} ${CMAKE_CURRENT_BINARY_DIR}/../$(CONFIGURATION)") -set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)") - # Set the info plist to the custom instance set_target_properties(${MODULE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) @@ -106,7 +104,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") add_custom_command(TARGET ${MODULE_NAME} PRE_BUILD COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${MODULE_OUTPUT_NAME}.app/Contents/Resources) # Compile the .xib files using the 'ibtool' program with the destination being the app package - foreach(xib ${${MODULE_NAME}_XIBS}) + foreach(xib ${${MODULE_PREFIX}_XIBS}) get_filename_component(XIB_WE ${xib} NAME_WE) add_custom_command (TARGET ${MODULE_NAME} POST_BUILD @@ -115,4 +113,4 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") COMMENT "Compiling ${xib}") endforeach() -endif("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") +endif() From b164453d75931968a347420d2c64a052aa0b50e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 8 Aug 2013 16:10:23 -0400 Subject: [PATCH 04/25] mfreerdp: fix 32-bit and universal build --- CMakeLists.txt | 5 +---- client/Mac/CMakeLists.txt | 3 --- client/Mac/cli/CMakeLists.txt | 4 ---- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dce790c54..3ee222e56 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -231,17 +231,14 @@ if(APPLE) include_directories(/opt/local/include) link_directories(/opt/local/lib) endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.5") endif() + if(WITH_CLANG) set(CMAKE_C_COMPILER "clang") endif() if (WITH_VERBOSE) - # Support for automatic reference counting requires non-fragile abi. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v") - - # Tell the compiler where to look for the FreeRDP framework set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v") endif() endif() diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 6f2627460..ffb565c4a 100755 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -65,9 +65,6 @@ set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH} RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH}) -# Support for automatic reference counting requires non-fragile abi. -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") - set_target_properties(${MODULE_NAME} PROPERTIES FRAMEWORK TRUE MACOSX_FRAMEWORK_IDENTIFIER com.awakecoding.${MODULE_NAME} diff --git a/client/Mac/cli/CMakeLists.txt b/client/Mac/cli/CMakeLists.txt index 09933a33c..2d14e370a 100644 --- a/client/Mac/cli/CMakeLists.txt +++ b/client/Mac/cli/CMakeLists.txt @@ -4,7 +4,6 @@ project(MacFreeRDP) set(MODULE_NAME "MacFreeRDP") set(MODULE_OUTPUT_NAME "MacFreeRDP") set(MODULE_PREFIX "FREERDP_CLIENT_MAC_CLIENT") -set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min=10.5") # Import libraries find_library(FOUNDATION_LIBRARY Foundation) @@ -62,9 +61,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR # This allows for automatic xib to nib ibitool set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_PREFIX}_RESOURCES}") -# Support for automatic reference counting requires non-fragile abi. -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") - # Tell the compiler where to look for the FreeRDP framework set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F../") From 2847c8819eb819c0f976405f67ecd7644a11d7b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 8 Aug 2013 16:38:50 -0400 Subject: [PATCH 05/25] mfreerdp: fix out of source build --- client/Mac/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index ffb565c4a..a556fd071 100755 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -166,7 +166,7 @@ endif() foreach(HEADER ${${MODULE_PREFIX}_HEADERS}) # message("adding post-build dependency: ${LIB}") add_custom_command(TARGET ${MODULE_NAME} POST_BUILD - COMMAND ditto ${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/ + COMMAND ditto ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER} ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Headers/ COMMENT Copying public header files to ${MODULE_NAME}) endforeach() From d9a4b350afd5d8d75de9243972f33bd38f5ce28c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 8 Aug 2013 21:24:07 -0400 Subject: [PATCH 06/25] libfreerdp-core: fix leak in listener --- libfreerdp/core/listener.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c index b67703b1d..fb49bf3d4 100644 --- a/libfreerdp/core/listener.c +++ b/libfreerdp/core/listener.c @@ -234,6 +234,7 @@ static void freerdp_listener_close(freerdp_listener* instance) for (i = 0; i < listener->num_sockfds; i++) { close(listener->sockfds[i]); + CloseHandle(listener->events[i]); } listener->num_sockfds = 0; From bb30ceb006b60577534f72163bcd4cf7ffb52b11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 9 Aug 2013 21:23:08 -0400 Subject: [PATCH 07/25] mfreerdp: cleanup --- CMakeLists.txt | 6 ++++++ client/Mac/CMakeLists.txt | 2 +- client/Mac/cli/CMakeLists.txt | 2 +- winpr/include/winpr/spec.h | 2 +- winpr/libwinpr/thread/process.c | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ee222e56..840a20581 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,12 @@ if(APPLE) set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_IOS_EXTERNAL_SSL_PATH}) set_property(GLOBAL PROPERTY XCODE_ATTRIBUTE_SKIP_INSTALL YES) else() + set(CMAKE_OSX_DEPLOYMENT_TARGET 10.6) + + if(NOT DEFINED CMAKE_OSX_ARCHITECTURES) + set(CMAKE_OSX_ARCHITECTURES i386 x86_64) + endif() + if(IS_DIRECTORY /opt/local/include) include_directories(/opt/local/include) link_directories(/opt/local/lib) diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index a556fd071..2344f46a1 100755 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -157,7 +157,7 @@ endif() add_custom_command (TARGET ${MODULE_NAME} POST_BUILD COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text - --compile ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources/${XIB_WE}.nib ${xib} + --compile ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources/${XIB_WE}.nib ${CMAKE_CURRENT_SOURCE_DIR}/${xib} COMMENT "Compiling ${xib}") endforeach() # endif() diff --git a/client/Mac/cli/CMakeLists.txt b/client/Mac/cli/CMakeLists.txt index 2d14e370a..e8033e2f5 100644 --- a/client/Mac/cli/CMakeLists.txt +++ b/client/Mac/cli/CMakeLists.txt @@ -105,7 +105,7 @@ if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles") add_custom_command (TARGET ${MODULE_NAME} POST_BUILD COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text - --compile ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${MODULE_OUTPUT_NAME}.app/Contents/Resources/${XIB_WE}.nib ${xib} + --compile ${CMAKE_CURRENT_BINARY_DIR}/\${CONFIGURATION}/${MODULE_OUTPUT_NAME}.app/Contents/Resources/${XIB_WE}.nib ${CMAKE_CURRENT_SOURCE_DIR}/${xib} COMMENT "Compiling ${xib}") endforeach() diff --git a/winpr/include/winpr/spec.h b/winpr/include/winpr/spec.h index 37b80f08f..917e8af82 100644 --- a/winpr/include/winpr/spec.h +++ b/winpr/include/winpr/spec.h @@ -53,7 +53,7 @@ #endif #ifndef DECLSPEC_NORETURN -#if (defined(__GNUC__) || defined(_MSC_VER)) +#if (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__)) #define DECLSPEC_NORETURN __declspec(noreturn) #else #define DECLSPEC_NORETURN diff --git a/winpr/libwinpr/thread/process.c b/winpr/libwinpr/thread/process.c index b5cc87858..76c4f127e 100644 --- a/winpr/libwinpr/thread/process.c +++ b/winpr/libwinpr/thread/process.c @@ -87,7 +87,7 @@ BOOL CreateProcessAsUserW(HANDLE hToken, LPCWSTR lpApplicationName, LPWSTR lpCom return TRUE; } -VOID ExitProcess(UINT uExitCode) +DECLSPEC_NORETURN VOID ExitProcess(UINT uExitCode) { } From e91f2516e53cff575570f23d9714990a34048ae4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 12 Aug 2013 13:13:27 -0400 Subject: [PATCH 08/25] libfreerdp-codec: fix automatic growing of the encode stream size --- libfreerdp/codec/rfx.c | 19 +++++++++++++------ libfreerdp/codec/rfx_encode.c | 6 +++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 54a71bcfd..a2cb064ae 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -1177,7 +1177,7 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, params[i].tile_width = tileWidth; params[i].tile_height = tileHeight; params[i].rowstride = rowstride; - params[i].quantVals = (UINT32*)quantVals; + params[i].quantVals = (UINT32*) quantVals; params[i].quantIdxY = quantIdxY; params[i].quantIdxCb = quantIdxCb; params[i].quantIdxCr = quantIdxCr; @@ -1199,13 +1199,20 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, if (context->priv->UseThreads) { - for (i = 0; i < numTiles; i++) + for (yIdx = 0; yIdx < numTilesY; yIdx++) { - WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); - CloseThreadpoolWork(work_objects[i]); - Stream_Write(s, Stream_Buffer(params[i].s), Stream_GetPosition(params[i].s)); - StreamPool_Return(context->priv->EncoderStreamPool, params[i].s); + for (xIdx = 0; xIdx < numTilesX; xIdx++) + { + i = yIdx * numTilesX + xIdx; + + WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); + Stream_EnsureRemainingCapacity(s, Stream_GetPosition(params[i].s)); + Stream_Write(s, Stream_Buffer(params[i].s), Stream_GetPosition(params[i].s)); + CloseThreadpoolWork(work_objects[i]); + Stream_Release(params[i].s); + } } + free(work_objects); free(params); } diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index 2b758988f..0bed64925 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -174,9 +174,9 @@ static void rfx_encode_format_rgb(const BYTE* rgb_data, int width, int height, i while (y_exceed > 0) { - memcpy(r_buf, r_last, 64 * sizeof(INT16)); - memcpy(g_buf, g_last, 64 * sizeof(INT16)); - memcpy(b_buf, b_last, 64 * sizeof(INT16)); + CopyMemory(r_buf, r_last, 64 * sizeof(INT16)); + CopyMemory(g_buf, g_last, 64 * sizeof(INT16)); + CopyMemory(b_buf, b_last, 64 * sizeof(INT16)); r_buf += 64; g_buf += 64; b_buf += 64; From f8e870a2580bbafedf7c1d882de884f505bc6f53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 12 Aug 2013 17:48:32 -0400 Subject: [PATCH 09/25] libwinpr-utils: implement asynchronous mode for ListDictionary --- include/freerdp/update.h | 8 + .../utils/collections/ListDictionary.c | 202 +++++++++++------- .../libwinpr/utils/test/TestListDictionary.c | 2 +- 3 files changed, 138 insertions(+), 74 deletions(-) diff --git a/include/freerdp/update.h b/include/freerdp/update.h index db6f36bb9..a6aa8caa9 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -134,6 +134,14 @@ enum SURFCMD_FRAMEACTION SURFACECMD_FRAMEACTION_END = 0x0001 }; +struct _SURFACE_FRAME +{ + UINT32 frameId; + UINT32 commandCount; + SURFACE_BITS_COMMAND* commands; +}; +typedef struct _SURFACE_FRAME SURFACE_FRAME; + /* defined inside libfreerdp-core */ typedef struct rdp_update_proxy rdpUpdateProxy; diff --git a/winpr/libwinpr/utils/collections/ListDictionary.c b/winpr/libwinpr/utils/collections/ListDictionary.c index d097035ef..cb7ba420a 100644 --- a/winpr/libwinpr/utils/collections/ListDictionary.c +++ b/winpr/libwinpr/utils/collections/ListDictionary.c @@ -43,17 +43,23 @@ int ListDictionary_Count(wListDictionary* listDictionary) int count = 0; wListDictionaryItem* item; - if (!listDictionary->head) - return 0; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); - item = listDictionary->head; - - while (item) + if (listDictionary->head) { - count++; - item = item->next; + item = listDictionary->head; + + while (item) + { + count++; + item = item->next; + } } + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); + return count; } @@ -97,6 +103,9 @@ void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value) wListDictionaryItem* item; wListDictionaryItem* lastItem; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); + item = (wListDictionaryItem*) malloc(sizeof(wListDictionaryItem)); item->key = key; @@ -107,15 +116,19 @@ void ListDictionary_Add(wListDictionary* listDictionary, void* key, void* value) if (!listDictionary->head) { listDictionary->head = item; - return; + } + else + { + lastItem = listDictionary->head; + + while (lastItem->next) + lastItem = lastItem->next; + + lastItem->next = item; } - lastItem = listDictionary->head; - - while (lastItem->next) - lastItem = lastItem->next; - - lastItem->next = item; + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); } /** @@ -127,19 +140,25 @@ void ListDictionary_Clear(wListDictionary* listDictionary) wListDictionaryItem* item; wListDictionaryItem* nextItem; - if (!listDictionary->head) - return; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); - item = listDictionary->head; - - while (item) + if (listDictionary->head) { - nextItem = item->next; - free(item); - item = nextItem; + item = listDictionary->head; + + while (item) + { + nextItem = item->next; + free(item); + item = nextItem; + } + + listDictionary->head = NULL; } - listDictionary->head = NULL; + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); } /** @@ -148,22 +167,31 @@ void ListDictionary_Clear(wListDictionary* listDictionary) BOOL ListDictionary_Contains(wListDictionary* listDictionary, void* key) { + BOOL status = FALSE; wListDictionaryItem* item; - if (!listDictionary->head) - return FALSE; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); - item = listDictionary->head; - - while (item) + if (listDictionary->head) { - if (item->key == key) - break; + item = listDictionary->head; - item = item->next; + while (item) + { + if (item->key == key) + break; + + item = item->next; + } + + status = (item) ? TRUE : FALSE; } - return (item) ? TRUE : FALSE; + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); + + return status; } /** @@ -175,35 +203,42 @@ void ListDictionary_Remove(wListDictionary* listDictionary, void* key) wListDictionaryItem* item; wListDictionaryItem* prevItem; - if (!listDictionary->head) - return; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); - item = listDictionary->head; - - if (listDictionary->head->key == key) + if (listDictionary->head) { - listDictionary->head = listDictionary->head->next; - free(item); - return; - } + item = listDictionary->head; - if (!item->next) - return; - - prevItem = item; - item = item->next; - - while (item) - { - if (item->key == key) + if (listDictionary->head->key == key) { - prevItem->next = item->next; + listDictionary->head = listDictionary->head->next; free(item); - break; } + else + { + if (item->next) + { + prevItem = item; + item = item->next; - item = item->next; + while (item) + { + if (item->key == key) + { + prevItem->next = item->next; + free(item); + break; + } + + item = item->next; + } + } + } } + + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); } /** @@ -212,22 +247,31 @@ void ListDictionary_Remove(wListDictionary* listDictionary, void* key) void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key) { + void* value = NULL; wListDictionaryItem* item; - if (!listDictionary->head) - return NULL; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); - item = listDictionary->head; - - while (item) + if (listDictionary->head) { - if (item->key == key) - break; + item = listDictionary->head; - item = item->next; + while (item) + { + if (item->key == key) + break; + + item = item->next; + } } - return (item) ? item->value : NULL; + value = (item) ? item->value : NULL; + + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); + + return value; } /** @@ -236,25 +280,34 @@ void* ListDictionary_GetItemValue(wListDictionary* listDictionary, void* key) BOOL ListDictionary_SetItemValue(wListDictionary* listDictionary, void* key, void* value) { + BOOL status = FALSE; wListDictionaryItem* item; - if (!listDictionary->head) - return FALSE; + if (listDictionary->synchronized) + EnterCriticalSection(&listDictionary->lock); - item = listDictionary->head; - - while (item) + if (listDictionary->head) { - if (item->key == key) - break; + item = listDictionary->head; - item = item->next; + while (item) + { + if (item->key == key) + break; + + item = item->next; + } + + if (item) + item->value = value; + + status = (item) ? TRUE : FALSE; } - if (item) - item->value = value; + if (listDictionary->synchronized) + LeaveCriticalSection(&listDictionary->lock); - return (item) ? TRUE : FALSE; + return status; } /** @@ -272,6 +325,8 @@ wListDictionary* ListDictionary_New(BOOL synchronized) listDictionary->synchronized = synchronized; listDictionary->head = NULL; + + InitializeCriticalSectionAndSpinCount(&listDictionary->lock, 4000); } return listDictionary; @@ -282,6 +337,7 @@ void ListDictionary_Free(wListDictionary* listDictionary) if (listDictionary) { ListDictionary_Clear(listDictionary); + DeleteCriticalSection(&listDictionary->lock); free(listDictionary); } } diff --git a/winpr/libwinpr/utils/test/TestListDictionary.c b/winpr/libwinpr/utils/test/TestListDictionary.c index 133271c23..c47ec3f5b 100644 --- a/winpr/libwinpr/utils/test/TestListDictionary.c +++ b/winpr/libwinpr/utils/test/TestListDictionary.c @@ -17,7 +17,7 @@ int TestListDictionary(int argc, char* argv[]) char* value; wListDictionary* list; - list = ListDictionary_New(FALSE); + list = ListDictionary_New(TRUE); ListDictionary_Add(list, key1, val1); ListDictionary_Add(list, key2, val2); From b972830841c4be29f8db4e26897f56ac3a217cf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 09:34:15 -0400 Subject: [PATCH 10/25] libfreerdp-codec: make use of ObjectPool for tiles --- include/freerdp/codec/rfx.h | 1 + libfreerdp/codec/rfx.c | 69 +++++++++++-------- libfreerdp/codec/rfx_types.h | 2 +- winpr/include/winpr/collections.h | 4 ++ winpr/libwinpr/utils/collections/ObjectPool.c | 6 ++ 5 files changed, 54 insertions(+), 28 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 97f5763d9..7e47616d0 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -22,6 +22,7 @@ #include #include +#include #include #include diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index a2cb064ae..9ed0d8dbe 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -138,6 +138,39 @@ static void rfx_profiler_print(RFX_CONTEXT* context) PROFILER_PRINT_FOOTER; } +void rfx_tile_init(RFX_TILE* tile) +{ + if (tile) + { + tile->x = 0; + tile->y = 0; + } +} + +RFX_TILE* rfx_tile_new() +{ + RFX_TILE* tile = NULL; + + tile = (RFX_TILE*) malloc(sizeof(RFX_TILE)); + + if (tile) + { + ZeroMemory(tile, sizeof(RFX_TILE)); + + tile->data = (BYTE*) malloc(4096 * 4); /* 64x64 * 4 */ + } + + return tile; +} + +void rfx_tile_free(RFX_TILE* tile) +{ + if (tile) + { + free(tile->data); + free(tile); + } +} RFX_CONTEXT* rfx_context_new(void) { @@ -155,7 +188,10 @@ RFX_CONTEXT* rfx_context_new(void) context->priv = (RFX_CONTEXT_PRIV*) malloc(sizeof(RFX_CONTEXT_PRIV)); ZeroMemory(context->priv, sizeof(RFX_CONTEXT_PRIV)); - context->priv->TilePool = Queue_New(TRUE, -1, -1); + context->priv->TilePool = ObjectPool_New(TRUE); + ObjectPool_Object(context->priv->TilePool)->fnObjectNew = (OBJECT_NEW_FN) rfx_tile_new; + ObjectPool_Object(context->priv->TilePool)->fnObjectInit = (OBJECT_INIT_FN) rfx_tile_init; + ObjectPool_Object(context->priv->TilePool)->fnObjectFree = (OBJECT_FREE_FN) rfx_tile_free; /* * align buffers to 16 byte boundary (needed for SSE/NEON instructions) @@ -254,7 +290,7 @@ void rfx_context_free(RFX_CONTEXT* context) { free(context->quants); - Queue_Free(context->priv->TilePool); + ObjectPool_Free(context->priv->TilePool); rfx_profiler_print(context); rfx_profiler_free(context); @@ -311,29 +347,6 @@ void rfx_context_reset(RFX_CONTEXT* context) context->frame_idx = 0; } -RFX_TILE* rfx_tile_pool_take(RFX_CONTEXT* context) -{ - RFX_TILE* tile = NULL; - - tile = Queue_Dequeue(context->priv->TilePool); - - if (!tile) - { - tile = (RFX_TILE*) malloc(sizeof(RFX_TILE)); - - tile->x = tile->y = 0; - tile->data = (BYTE*) malloc(4096 * 4); /* 64x64 * 4 */ - } - - return tile; -} - -int rfx_tile_pool_return(RFX_CONTEXT* context, RFX_TILE* tile) -{ - Queue_Enqueue(context->priv->TilePool, tile); - return 0; -} - static BOOL rfx_process_message_sync(RFX_CONTEXT* context, wStream* s) { UINT32 magic; @@ -724,7 +737,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa break; } - message->tiles[i] = rfx_tile_pool_take(context); + message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); if (context->priv->UseThreads) { @@ -885,7 +898,9 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) if (message->tiles) { for (i = 0; i < message->num_tiles; i++) - rfx_tile_pool_return(context, message->tiles[i]); + { + ObjectPool_Return(context->priv->TilePool, (void*) message->tiles[i]); + } free(message->tiles); } diff --git a/libfreerdp/codec/rfx_types.h b/libfreerdp/codec/rfx_types.h index 5b875bdba..2675d35ad 100644 --- a/libfreerdp/codec/rfx_types.h +++ b/libfreerdp/codec/rfx_types.h @@ -39,7 +39,7 @@ struct _RFX_CONTEXT_PRIV { - wQueue* TilePool; + wObjectPool* TilePool; BOOL UseThreads; DWORD MinThreadCount; diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index d493a59b2..8901fe7b6 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -35,12 +35,16 @@ extern "C" { #endif typedef void* (*OBJECT_NEW_FN)(void); +typedef void (*OBJECT_INIT_FN)(void* obj); +typedef void (*OBJECT_UNINIT_FN)(void* obj); typedef void (*OBJECT_FREE_FN)(void* obj); typedef void (*OBJECT_EQUALS_FN)(void* objA, void* objB); struct _wObject { OBJECT_NEW_FN fnObjectNew; + OBJECT_INIT_FN fnObjectInit; + OBJECT_UNINIT_FN fnObjectUninit; OBJECT_FREE_FN fnObjectFree; OBJECT_EQUALS_FN fnObjectEquals; }; diff --git a/winpr/libwinpr/utils/collections/ObjectPool.c b/winpr/libwinpr/utils/collections/ObjectPool.c index c0e36266f..bca31edfd 100644 --- a/winpr/libwinpr/utils/collections/ObjectPool.c +++ b/winpr/libwinpr/utils/collections/ObjectPool.c @@ -54,6 +54,9 @@ void* ObjectPool_Take(wObjectPool* pool) obj = pool->object.fnObjectNew(); } + if (pool->object.fnObjectInit) + pool->object.fnObjectInit(obj); + if (pool->synchronized) LeaveCriticalSection(&pool->lock); @@ -77,6 +80,9 @@ void ObjectPool_Return(wObjectPool* pool, void* obj) pool->array[(pool->size)++] = obj; + if (pool->object.fnObjectUninit) + pool->object.fnObjectUninit(obj); + if (pool->synchronized) LeaveCriticalSection(&pool->lock); } From 3e4dc732805498d07c422f50afb7819a0e1da131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 10:09:32 -0400 Subject: [PATCH 11/25] libfreerdp-codec: split stream parsing from tile decoding --- include/freerdp/codec/rfx.h | 12 +++++ libfreerdp/codec/rfx.c | 65 +++++++++----------------- libfreerdp/codec/rfx_decode.c | 87 ++++------------------------------- libfreerdp/codec/rfx_decode.h | 6 +-- 4 files changed, 45 insertions(+), 125 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 7e47616d0..22517e793 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -52,6 +52,18 @@ struct _RFX_TILE UINT16 x; UINT16 y; BYTE* data; + + BYTE quantIdxY; + BYTE quantIdxCb; + BYTE quantIdxCr; + UINT16 xIdx; + UINT16 yIdx; + UINT16 YLen; + UINT16 CbLen; + UINT16 CrLen; + BYTE* YData; + BYTE* CbData; + BYTE* CrData; }; typedef struct _RFX_TILE RFX_TILE; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 9ed0d8dbe..9706aca2e 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -561,46 +561,8 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag return TRUE; } -static BOOL rfx_process_message_tile(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s) -{ - BYTE quantIdxY; - BYTE quantIdxCb; - BYTE quantIdxCr; - UINT16 xIdx, yIdx; - UINT16 YLen, CbLen, CrLen; - - if (Stream_GetRemainingLength(s) < 13) - { - DEBUG_WARN("RfxMessageTile packet too small"); - return FALSE; - } - - /* RFX_TILE */ - Stream_Read_UINT8(s, quantIdxY); /* quantIdxY (1 byte) */ - Stream_Read_UINT8(s, quantIdxCb); /* quantIdxCb (1 byte) */ - Stream_Read_UINT8(s, quantIdxCr); /* quantIdxCr (1 byte) */ - Stream_Read_UINT16(s, xIdx); /* xIdx (2 bytes) */ - Stream_Read_UINT16(s, yIdx); /* yIdx (2 bytes) */ - Stream_Read_UINT16(s, YLen); /* YLen (2 bytes) */ - Stream_Read_UINT16(s, CbLen); /* CbLen (2 bytes) */ - Stream_Read_UINT16(s, CrLen); /* CrLen (2 bytes) */ - - DEBUG_RFX("quantIdxY:%d quantIdxCb:%d quantIdxCr:%d xIdx:%d yIdx:%d YLen:%d CbLen:%d CrLen:%d", - quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx, YLen, CbLen, CrLen); - - tile->x = xIdx * 64; - tile->y = yIdx * 64; - - return rfx_decode_rgb(context, s, - YLen, context->quants + (quantIdxY * 10), - CbLen, context->quants + (quantIdxCb * 10), - CrLen, context->quants + (quantIdxCr * 10), - tile->data, 64 * 4); -} - struct _RFX_TILE_PROCESS_WORK_PARAM { - wStream s; RFX_TILE* tile; RFX_CONTEXT* context; }; @@ -609,7 +571,7 @@ typedef struct _RFX_TILE_PROCESS_WORK_PARAM RFX_TILE_PROCESS_WORK_PARAM; void CALLBACK rfx_process_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { RFX_TILE_PROCESS_WORK_PARAM* param = (RFX_TILE_PROCESS_WORK_PARAM*) context; - rfx_process_message_tile(param->context, param->tile, &(param->s)); + rfx_decode_rgb(param->context, param->tile, param->tile->data, 64 * 4); } static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* message, wStream* s) @@ -617,6 +579,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa int i; int pos; BYTE quant; + RFX_TILE* tile; UINT32* quants; UINT16 subtype; UINT32 blockLen; @@ -713,6 +676,8 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa /* tiles */ for (i = 0; i < message->num_tiles; i++) { + tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); + /* RFX_TILE */ if (Stream_GetRemainingLength(s) < 6) { @@ -737,13 +702,29 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa break; } - message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); + Stream_Read_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */ + Stream_Read_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */ + Stream_Read_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */ + Stream_Read_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */ + Stream_Read_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */ + Stream_Read_UINT16(s, tile->YLen); /* YLen (2 bytes) */ + Stream_Read_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */ + Stream_Read_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */ + + Stream_GetPointer(s, tile->YData); + Stream_Seek(s, tile->YLen); + Stream_GetPointer(s, tile->CbData); + Stream_Seek(s, tile->CbLen); + Stream_GetPointer(s, tile->CrData); + Stream_Seek(s, tile->CrLen); + + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; if (context->priv->UseThreads) { params[i].context = context; params[i].tile = message->tiles[i]; - CopyMemory(&(params[i].s), s, sizeof(wStream)); work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_process_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); @@ -752,7 +733,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa } else { - rfx_process_message_tile(context, message->tiles[i], s); + rfx_decode_rgb(context, tile, tile->data, 64 * 4); } Stream_SetPosition(s, pos); diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index ff6161590..2a642f9da 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -125,98 +125,29 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio /* rfx_decode_ycbcr_to_rgb code now resides in the primitives library. */ -struct _RFX_COMPONENT_WORK_PARAM -{ - int size; - INT16* buffer; - const BYTE* data; - RFX_CONTEXT* context; - const UINT32* quantization_values; -}; -typedef struct _RFX_COMPONENT_WORK_PARAM RFX_COMPONENT_WORK_PARAM; - -void CALLBACK rfx_decode_component_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) -{ - RFX_COMPONENT_WORK_PARAM* param = (RFX_COMPONENT_WORK_PARAM*) context; - rfx_decode_component(param->context, param->quantization_values, param->data, param->size, param->buffer); -} - /* stride is bytes between rows in the output buffer. */ -BOOL rfx_decode_rgb(RFX_CONTEXT* context, wStream* data_in, - int y_size, const UINT32* y_quants, - int cb_size, const UINT32* cb_quants, - int cr_size, const UINT32* cr_quants, BYTE* rgb_buffer, int stride) +BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride) { INT16* pSrcDst[3]; + UINT32 *y_quants, *cb_quants, *cr_quants; static const prim_size_t roi_64x64 = { 64, 64 }; const primitives_t *prims = primitives_get(); PROFILER_ENTER(context->priv->prof_rfx_decode_rgb); + y_quants = context->quants + (tile->quantIdxY * 10); + cb_quants = context->quants + (tile->quantIdxCb * 10); + cr_quants = context->quants + (tile->quantIdxCr * 10); + pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */ pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */ pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */ -#if 0 - if (context->priv->UseThreads) - { - PTP_WORK work_objects[3]; - RFX_COMPONENT_WORK_PARAM params[3]; + rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */ - params[0].context = context; - params[0].quantization_values = y_quants; - params[0].buffer = Stream_Pointer(data_in); - params[0].capacity = y_size; - params[0].buffer = pSrcDst[0]; - Stream_Seek(data_in, y_size); + rfx_decode_component(context, cb_quants, tile->CbData, tile->CbLen, pSrcDst[1]); /* CbData */ - params[1].context = context; - params[1].quantization_values = cb_quants; - params[1].buffer = Stream_Pointer(data_in); - params[1].capacity = cb_size; - params[1].buffer = pSrcDst[1]; - Stream_Seek(data_in, cb_size); - - params[2].context = context; - params[2].quantization_values = cr_quants; - params[2].buffer = Stream_Pointer(data_in); - params[2].capacity = cr_size; - params[2].buffer = pSrcDst[2]; - Stream_Seek(data_in, cr_size); - - work_objects[0] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_decode_component_work_callback, - (void*) ¶ms[0], &context->priv->ThreadPoolEnv); - work_objects[1] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_decode_component_work_callback, - (void*) ¶ms[1], &context->priv->ThreadPoolEnv); - work_objects[2] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_decode_component_work_callback, - (void*) ¶ms[2], &context->priv->ThreadPoolEnv); - - SubmitThreadpoolWork(work_objects[0]); - SubmitThreadpoolWork(work_objects[1]); - SubmitThreadpoolWork(work_objects[2]); - - WaitForThreadpoolWorkCallbacks(work_objects[0], FALSE); - WaitForThreadpoolWorkCallbacks(work_objects[1], FALSE); - WaitForThreadpoolWorkCallbacks(work_objects[2], FALSE); - } - else -#endif - { - if (Stream_GetRemainingLength(data_in) < y_size + cb_size + cr_size) - { - DEBUG_WARN("rfx_decode_rgb: packet too small for y_size+cb_size+cr_size"); - return FALSE; - } - - rfx_decode_component(context, y_quants, Stream_Pointer(data_in), y_size, pSrcDst[0]); /* YData */ - Stream_Seek(data_in, y_size); - - rfx_decode_component(context, cb_quants, Stream_Pointer(data_in), cb_size, pSrcDst[1]); /* CbData */ - Stream_Seek(data_in, cb_size); - - rfx_decode_component(context, cr_quants, Stream_Pointer(data_in), cr_size, pSrcDst[2]); /* CrData */ - Stream_Seek(data_in, cr_size); - } + rfx_decode_component(context, cr_quants, tile->CrData, tile->CrLen, pSrcDst[2]); /* CrData */ PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb); prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), diff --git a/libfreerdp/codec/rfx_decode.h b/libfreerdp/codec/rfx_decode.h index 469c2a576..f5da4f933 100644 --- a/libfreerdp/codec/rfx_decode.h +++ b/libfreerdp/codec/rfx_decode.h @@ -23,11 +23,7 @@ #include /* stride is bytes between rows in the output buffer. */ -BOOL rfx_decode_rgb(RFX_CONTEXT* context, wStream* data_in, - int y_size, const UINT32 * y_quants, - int cb_size, const UINT32 * cb_quants, - int cr_size, const UINT32 * cr_quants, BYTE* rgb_buffer, - int stride); +BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int stride); #endif /* __RFX_DECODE_H */ From 916a4eee4b3d8b0bb4c57b20b31f16cf51ec8d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 10:30:22 -0400 Subject: [PATCH 12/25] libfreerdp-codec: start making use of RFX_TILE structure for encoding --- include/freerdp/codec/rfx.h | 2 ++ libfreerdp/codec/rfx.c | 70 +++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 22517e793..f82445b74 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -51,6 +51,8 @@ struct _RFX_TILE { UINT16 x; UINT16 y; + int width; + int height; BYTE* data; BYTE quantIdxY; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 9706aca2e..32cfcec0f 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -1045,36 +1045,31 @@ static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, struct _RFX_TILE_COMPOSE_WORK_PARAM { + RFX_TILE* tile; RFX_CONTEXT* context; - wStream *s; - BYTE* tile_data; - int tile_width; - int tile_height; + + wStream* s; int rowstride; UINT32* quantVals; - int quantIdxY; - int quantIdxCb; - int quantIdxCr; - int xIdx; - int yIdx; }; typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { + RFX_TILE* tile; RFX_TILE_COMPOSE_WORK_PARAM* param = (RFX_TILE_COMPOSE_WORK_PARAM*) context; + tile = param->tile; + /** - * Some component of the encoder chain (I suspect the rlgr encoder) expects - * the output buffer to be zeroed. The multithreaded RemoteFX encoder uses - * wStreams from the StreamPool which are reused and not zeroed out of - * course. For now, in order to prevent data corruption we clear the stream. + * We need to clear the stream as the RLGR encoder expects it to be initialized to zero. + * This allows simplifying and improving the performance of the encoding process. */ Stream_Clear(param->s); rfx_compose_message_tile(param->context, param->s, - param->tile_data, param->tile_width, param->tile_height, param->rowstride, - param->quantVals, param->quantIdxY, param->quantIdxCb, param->quantIdxCr, param->xIdx, param->yIdx); + tile->data, tile->width, tile->height, param->rowstride, + param->quantVals, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx); } static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, @@ -1082,6 +1077,7 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, { int i; int size; + RFX_TILE* tile; int start_pos, end_pos; int numQuants; const UINT32* quantVals; @@ -1095,9 +1091,6 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, int xIdx; int yIdx; int tilesDataSize; - BYTE* tileData; - int tileWidth; - int tileHeight; PTP_WORK* work_objects = NULL; RFX_TILE_COMPOSE_WORK_PARAM* params = NULL; @@ -1159,26 +1152,32 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, { for (xIdx = 0; xIdx < numTilesX; xIdx++) { - tileData = image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel; - tileWidth = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; - tileHeight = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; + i = yIdx * numTilesX + xIdx; + + tile = params[i].tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); + + tile->data = image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel; + tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; + tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; + + tile->quantIdxY = quantIdxY; + tile->quantIdxCb = quantIdxCb; + tile->quantIdxCr = quantIdxCr; + tile->xIdx = xIdx; + tile->yIdx = yIdx; + tile->YLen = 0; + tile->CbLen = 0; + tile->CrLen = 0; + tile->YData = NULL; + tile->CbData = NULL; + tile->CrData = NULL; if (context->priv->UseThreads) { - i = yIdx * numTilesX + xIdx; - params[i].context = context; params[i].s = StreamPool_Take(context->priv->EncoderStreamPool, 0); - params[i].tile_data = tileData; - params[i].tile_width = tileWidth; - params[i].tile_height = tileHeight; params[i].rowstride = rowstride; params[i].quantVals = (UINT32*) quantVals; - params[i].quantIdxY = quantIdxY; - params[i].quantIdxCb = quantIdxCb; - params[i].quantIdxCr = quantIdxCr; - params[i].xIdx = xIdx; - params[i].yIdx = yIdx; work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); @@ -1187,8 +1186,9 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, } else { - rfx_compose_message_tile(context, s, tileData, tileWidth, tileHeight, - rowstride, quantVals, quantIdxY, quantIdxCb, quantIdxCr, xIdx, yIdx); + rfx_compose_message_tile(context, s, tile->data, tile->width, tile->height, + rowstride, quantVals, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, + tile->xIdx, tile->yIdx); } } } @@ -1202,9 +1202,11 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, i = yIdx * numTilesX + xIdx; WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); + CloseThreadpoolWork(work_objects[i]); + Stream_EnsureRemainingCapacity(s, Stream_GetPosition(params[i].s)); Stream_Write(s, Stream_Buffer(params[i].s), Stream_GetPosition(params[i].s)); - CloseThreadpoolWork(work_objects[i]); + ObjectPool_Return(context->priv->TilePool, (void*) params[i].tile); Stream_Release(params[i].s); } } From 482e836ad882f82f546dc3427ab3709da0f0c974 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 11:09:54 -0400 Subject: [PATCH 13/25] libfreerdp-codec: refactor internal rfx_compose_message_tile --- include/freerdp/codec/rfx.h | 8 +-- libfreerdp/codec/rfx.c | 91 +++++++++++++---------------------- libfreerdp/codec/rfx_encode.c | 35 +++++++++----- libfreerdp/codec/rfx_encode.h | 4 +- 4 files changed, 60 insertions(+), 78 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index f82445b74..d735adaa4 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -110,11 +110,11 @@ struct _RFX_CONTEXT /* temporary data within a frame */ UINT32 frame_idx; BOOL header_processed; - BYTE num_quants; + BYTE numQuant; UINT32* quants; - BYTE quant_idx_y; - BYTE quant_idx_cb; - BYTE quant_idx_cr; + BYTE quantIdxY; + BYTE quantIdxCb; + BYTE quantIdxCr; /* routines */ void (*quantization_decode)(INT16* buffer, const UINT32* quantization_values); diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 32cfcec0f..bd744ee7f 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -605,10 +605,10 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa Stream_Seek_UINT16(s); /* idx (2 bytes), must be set to 0x0000 */ Stream_Seek_UINT16(s); /* properties (2 bytes) */ - Stream_Read_UINT8(s, context->num_quants); /* numQuant (1 byte) */ + Stream_Read_UINT8(s, context->numQuant); /* numQuant (1 byte) */ Stream_Seek_UINT8(s); /* tileSize (1 byte), must be set to 0x40 */ - if (context->num_quants < 1) + if (context->numQuant < 1) { DEBUG_WARN("no quantization value."); return TRUE; @@ -625,19 +625,19 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa Stream_Read_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */ if (context->quants != NULL) - context->quants = (UINT32*) realloc((void*) context->quants, context->num_quants * 10 * sizeof(UINT32)); + context->quants = (UINT32*) realloc((void*) context->quants, context->numQuant * 10 * sizeof(UINT32)); else - context->quants = (UINT32*) malloc(context->num_quants * 10 * sizeof(UINT32)); + context->quants = (UINT32*) malloc(context->numQuant * 10 * sizeof(UINT32)); quants = context->quants; /* quantVals */ - if (Stream_GetRemainingLength(s) < context->num_quants * 5) + if (Stream_GetRemainingLength(s) < context->numQuant * 5) { - DEBUG_WARN("RfxMessageTileSet packet too small for num_quants=%d", context->num_quants); + DEBUG_WARN("RfxMessageTileSet packet too small for num_quants=%d", context->numQuant); return FALSE; } - for (i = 0; i < context->num_quants; i++) + for (i = 0; i < context->numQuant; i++) { /* RFX_CODEC_QUANT */ Stream_Read_UINT8(s, quant); @@ -1000,14 +1000,8 @@ static void rfx_compose_message_region(RFX_CONTEXT* context, wStream* s, Stream_Write_UINT16(s, 1); /* numTilesets */ } -static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, - BYTE* tile_data, int tile_width, int tile_height, int rowstride, - const UINT32* quantVals, int quantIdxY, int quantIdxCb, int quantIdxCr, - int xIdx, int yIdx) +static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile, int rowstride) { - int YLen = 0; - int CbLen = 0; - int CrLen = 0; int start_pos, end_pos; Stream_EnsureRemainingCapacity(s, 19); @@ -1015,29 +1009,27 @@ static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType */ Stream_Seek_UINT32(s); /* set BlockT.blockLen later */ - Stream_Write_UINT8(s, quantIdxY); - Stream_Write_UINT8(s, quantIdxCb); - Stream_Write_UINT8(s, quantIdxCr); - Stream_Write_UINT16(s, xIdx); - Stream_Write_UINT16(s, yIdx); + Stream_Write_UINT8(s, tile->quantIdxY); + Stream_Write_UINT8(s, tile->quantIdxCb); + Stream_Write_UINT8(s, tile->quantIdxCr); + Stream_Write_UINT16(s, tile->xIdx); + Stream_Write_UINT16(s, tile->yIdx); Stream_Seek(s, 6); /* YLen, CbLen, CrLen */ - rfx_encode_rgb(context, tile_data, tile_width, tile_height, rowstride, - quantVals + quantIdxY * 10, quantVals + quantIdxCb * 10, quantVals + quantIdxCr * 10, - s, &YLen, &CbLen, &CrLen); + rfx_encode_rgb(context, tile, rowstride, s); DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", - xIdx, yIdx, tile_width, tile_height, YLen, CbLen, CrLen); + tile->xIdx, tile->yIdx, tile->width, tile->height, tile->YLen, tile->CbLen, tile->CrLen); end_pos = Stream_GetPosition(s); Stream_SetPosition(s, start_pos + 2); - Stream_Write_UINT32(s, 19 + YLen + CbLen + CrLen); /* BlockT.blockLen */ + Stream_Write_UINT32(s, 19 + tile->YLen + tile->CbLen + tile->CrLen); /* BlockT.blockLen */ Stream_SetPosition(s, start_pos + 13); - Stream_Write_UINT16(s, YLen); - Stream_Write_UINT16(s, CbLen); - Stream_Write_UINT16(s, CrLen); + Stream_Write_UINT16(s, tile->YLen); + Stream_Write_UINT16(s, tile->CbLen); + Stream_Write_UINT16(s, tile->CrLen); Stream_SetPosition(s, end_pos); } @@ -1050,26 +1042,20 @@ struct _RFX_TILE_COMPOSE_WORK_PARAM wStream* s; int rowstride; - UINT32* quantVals; }; typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { - RFX_TILE* tile; RFX_TILE_COMPOSE_WORK_PARAM* param = (RFX_TILE_COMPOSE_WORK_PARAM*) context; - tile = param->tile; - /** * We need to clear the stream as the RLGR encoder expects it to be initialized to zero. * This allows simplifying and improving the performance of the encoding process. */ Stream_Clear(param->s); - rfx_compose_message_tile(param->context, param->s, - tile->data, tile->width, tile->height, param->rowstride, - param->quantVals, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx); + rfx_compose_message_tile(param->context, param->s, param->tile, param->rowstride); } static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, @@ -1082,9 +1068,6 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, int numQuants; const UINT32* quantVals; const UINT32* quantValsPtr; - int quantIdxY; - int quantIdxCb; - int quantIdxCr; int numTiles; int numTilesX; int numTilesY; @@ -1094,23 +1077,18 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, PTP_WORK* work_objects = NULL; RFX_TILE_COMPOSE_WORK_PARAM* params = NULL; - if (context->num_quants == 0) + if (!context->numQuant) { - numQuants = 1; - quantVals = rfx_default_quantization_values; - quantIdxY = 0; - quantIdxCb = 0; - quantIdxCr = 0; - } - else - { - numQuants = context->num_quants; - quantVals = context->quants; - quantIdxY = context->quant_idx_y; - quantIdxCb = context->quant_idx_cb; - quantIdxCr = context->quant_idx_cr; + context->numQuant = 1; + context->quants = (UINT32*) rfx_default_quantization_values; + context->quantIdxY = 0; + context->quantIdxCb = 0; + context->quantIdxCr = 0; } + numQuants = context->numQuant; + quantVals = context->quants; + numTilesX = (width + 63) / 64; numTilesY = (height + 63) / 64; numTiles = numTilesX * numTilesY; @@ -1160,9 +1138,9 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; - tile->quantIdxY = quantIdxY; - tile->quantIdxCb = quantIdxCb; - tile->quantIdxCr = quantIdxCr; + tile->quantIdxY = context->quantIdxY; + tile->quantIdxCb = context->quantIdxCb; + tile->quantIdxCr = context->quantIdxCr; tile->xIdx = xIdx; tile->yIdx = yIdx; tile->YLen = 0; @@ -1177,7 +1155,6 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, params[i].context = context; params[i].s = StreamPool_Take(context->priv->EncoderStreamPool, 0); params[i].rowstride = rowstride; - params[i].quantVals = (UINT32*) quantVals; work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); @@ -1186,9 +1163,7 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, } else { - rfx_compose_message_tile(context, s, tile->data, tile->width, tile->height, - rowstride, quantVals, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, - tile->xIdx, tile->yIdx); + rfx_compose_message_tile(context, s, tile, rowstride); } } } diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index 0bed64925..a97215deb 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -217,14 +217,19 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio BufferPool_Return(context->priv->BufferPool, dwt_buffer); } -void rfx_encode_rgb(RFX_CONTEXT* context, const BYTE* rgb_data, int width, int height, int rowstride, - const UINT32* y_quants, const UINT32* cb_quants, const UINT32* cr_quants, - wStream* data_out, int* y_size, int* cb_size, int* cr_size) +void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, int rowstride, wStream* s) { INT16* pSrcDst[3]; + int YLen, CbLen, CrLen; + UINT32 *y_quants, *cb_quants, *cr_quants; primitives_t* prims = primitives_get(); static const prim_size_t roi_64x64 = { 64, 64 }; + YLen = CbLen = CrLen = 0; + y_quants = context->quants + (tile->quantIdxY * 10); + cb_quants = context->quants + (tile->quantIdxCb * 10); + cr_quants = context->quants + (tile->quantIdxCr * 10); + pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */ pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */ pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */ @@ -232,7 +237,7 @@ void rfx_encode_rgb(RFX_CONTEXT* context, const BYTE* rgb_data, int width, int h PROFILER_ENTER(context->priv->prof_rfx_encode_rgb); PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb); - rfx_encode_format_rgb(rgb_data, width, height, rowstride, + rfx_encode_format_rgb(tile->data, tile->width, tile->height, rowstride, context->pixel_format, context->palette, pSrcDst[0], pSrcDst[1], pSrcDst[2]); PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb); @@ -242,21 +247,25 @@ void rfx_encode_rgb(RFX_CONTEXT* context, const BYTE* rgb_data, int width, int h PROFILER_EXIT(context->priv->prof_rfx_rgb_to_ycbcr); /* Ensure the buffer is reasonably large enough */ - Stream_EnsureRemainingCapacity(data_out, 4096); + Stream_EnsureRemainingCapacity(s, 4096); rfx_encode_component(context, y_quants, pSrcDst[0], - Stream_Pointer(data_out), Stream_GetRemainingLength(data_out), y_size); - Stream_Seek(data_out, *y_size); + Stream_Pointer(s), Stream_GetRemainingLength(s), &YLen); + Stream_Seek(s, YLen); - Stream_EnsureRemainingCapacity(data_out, 4096); + Stream_EnsureRemainingCapacity(s, 4096); rfx_encode_component(context, cb_quants, pSrcDst[1], - Stream_Pointer(data_out), Stream_GetRemainingLength(data_out), cb_size); - Stream_Seek(data_out, *cb_size); + Stream_Pointer(s), Stream_GetRemainingLength(s), &CbLen); + Stream_Seek(s, CbLen); - Stream_EnsureRemainingCapacity(data_out, 4096); + Stream_EnsureRemainingCapacity(s, 4096); rfx_encode_component(context, cr_quants, pSrcDst[2], - Stream_Pointer(data_out), Stream_GetRemainingLength(data_out), cr_size); - Stream_Seek(data_out, *cr_size); + Stream_Pointer(s), Stream_GetRemainingLength(s), &CrLen); + Stream_Seek(s, CrLen); + + tile->YLen = (UINT16) YLen; + tile->CbLen = (UINT16) CbLen; + tile->CrLen = (UINT16) CrLen; PROFILER_EXIT(context->priv->prof_rfx_encode_rgb); diff --git a/libfreerdp/codec/rfx_encode.h b/libfreerdp/codec/rfx_encode.h index e329bded2..ff1197b7f 100644 --- a/libfreerdp/codec/rfx_encode.h +++ b/libfreerdp/codec/rfx_encode.h @@ -22,9 +22,7 @@ #include -void rfx_encode_rgb(RFX_CONTEXT* context, const BYTE* rgb_data, int width, int height, int rowstride, - const UINT32* y_quants, const UINT32* cb_quants, const UINT32* cr_quants, - wStream* data_out, int* y_size, int* cb_size, int* cr_size); +void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, int rowstride, wStream* s); #endif From 4e6f1f5a4b511caeee8806350e38c19c46b46430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 13:45:28 -0400 Subject: [PATCH 14/25] libfreerdp-codec: use pooled buffers for channel encoding --- include/freerdp/codec/rfx.h | 1 + libfreerdp/codec/rfx.c | 29 +++++++------------ libfreerdp/codec/rfx_encode.c | 53 ++++++++++++++++++++++------------- libfreerdp/codec/rfx_encode.h | 2 +- 4 files changed, 45 insertions(+), 40 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index d735adaa4..d2ecfd204 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -54,6 +54,7 @@ struct _RFX_TILE int width; int height; BYTE* data; + int scanline; BYTE quantIdxY; BYTE quantIdxCb; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index bd744ee7f..c0e165e3d 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -263,10 +263,10 @@ RFX_CONTEXT* rfx_context_new(void) if (context->priv->MaxThreadCount) SetThreadpoolThreadMaximum(context->priv->ThreadPool, context->priv->MaxThreadCount); - - context->priv->EncoderStreamPool = StreamPool_New(TRUE, 64*64*3+19); } + context->priv->EncoderStreamPool = StreamPool_New(TRUE, 64*64*3+19); + /* initialize the default pixel format */ rfx_context_set_pixel_format(context, RDP_PIXEL_FORMAT_B8G8R8A8); @@ -1000,7 +1000,7 @@ static void rfx_compose_message_region(RFX_CONTEXT* context, wStream* s, Stream_Write_UINT16(s, 1); /* numTilesets */ } -static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile, int rowstride) +static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) { int start_pos, end_pos; @@ -1017,7 +1017,7 @@ static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* Stream_Seek(s, 6); /* YLen, CbLen, CrLen */ - rfx_encode_rgb(context, tile, rowstride, s); + rfx_encode_rgb(context, tile, s); DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", tile->xIdx, tile->yIdx, tile->width, tile->height, tile->YLen, tile->CbLen, tile->CrLen); @@ -1039,27 +1039,18 @@ struct _RFX_TILE_COMPOSE_WORK_PARAM { RFX_TILE* tile; RFX_CONTEXT* context; - wStream* s; - int rowstride; }; typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { RFX_TILE_COMPOSE_WORK_PARAM* param = (RFX_TILE_COMPOSE_WORK_PARAM*) context; - - /** - * We need to clear the stream as the RLGR encoder expects it to be initialized to zero. - * This allows simplifying and improving the performance of the encoding process. - */ - Stream_Clear(param->s); - - rfx_compose_message_tile(param->context, param->s, param->tile, param->rowstride); + rfx_compose_message_tile(param->context, param->s, param->tile); } static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, - BYTE* image_data, int width, int height, int rowstride) + BYTE* image_data, int width, int height, int scanline) { int i; int size; @@ -1116,7 +1107,7 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, quantValsPtr += 2; } - DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, rowstride); + DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, scanline); end_pos = Stream_GetPosition(s); @@ -1134,7 +1125,8 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, tile = params[i].tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); - tile->data = image_data + yIdx * 64 * rowstride + xIdx * 8 * context->bits_per_pixel; + tile->scanline = scanline; + tile->data = image_data + yIdx * 64 * scanline + xIdx * 8 * context->bits_per_pixel; tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; @@ -1154,7 +1146,6 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, { params[i].context = context; params[i].s = StreamPool_Take(context->priv->EncoderStreamPool, 0); - params[i].rowstride = rowstride; work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); @@ -1163,7 +1154,7 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, } else { - rfx_compose_message_tile(context, s, tile, rowstride); + rfx_compose_message_tile(context, s, tile); } } } diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index a97215deb..61d994e1a 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -217,18 +217,22 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio BufferPool_Return(context->priv->BufferPool, dwt_buffer); } -void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, int rowstride, wStream* s) +void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s) { INT16* pSrcDst[3]; int YLen, CbLen, CrLen; - UINT32 *y_quants, *cb_quants, *cr_quants; + UINT32 *YQuant, *CbQuant, *CrQuant; primitives_t* prims = primitives_get(); static const prim_size_t roi_64x64 = { 64, 64 }; YLen = CbLen = CrLen = 0; - y_quants = context->quants + (tile->quantIdxY * 10); - cb_quants = context->quants + (tile->quantIdxCb * 10); - cr_quants = context->quants + (tile->quantIdxCr * 10); + YQuant = context->quants + (tile->quantIdxY * 10); + CbQuant = context->quants + (tile->quantIdxCb * 10); + CrQuant = context->quants + (tile->quantIdxCr * 10); + + tile->YData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + tile->CbData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + tile->CrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */ pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */ @@ -237,7 +241,7 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, int rowstride, wStream PROFILER_ENTER(context->priv->prof_rfx_encode_rgb); PROFILER_ENTER(context->priv->prof_rfx_encode_format_rgb); - rfx_encode_format_rgb(tile->data, tile->width, tile->height, rowstride, + rfx_encode_format_rgb(tile->data, tile->width, tile->height, tile->scanline, context->pixel_format, context->palette, pSrcDst[0], pSrcDst[1], pSrcDst[2]); PROFILER_EXIT(context->priv->prof_rfx_encode_format_rgb); @@ -246,30 +250,39 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, int rowstride, wStream pSrcDst, 64 * sizeof(INT16), &roi_64x64); PROFILER_EXIT(context->priv->prof_rfx_rgb_to_ycbcr); - /* Ensure the buffer is reasonably large enough */ - Stream_EnsureRemainingCapacity(s, 4096); + /** + * We need to clear the buffers as the RLGR encoder expects it to be initialized to zero. + * This allows simplifying and improving the performance of the encoding process. + */ - rfx_encode_component(context, y_quants, pSrcDst[0], - Stream_Pointer(s), Stream_GetRemainingLength(s), &YLen); - Stream_Seek(s, YLen); + ZeroMemory(tile->YData, 4096); + ZeroMemory(tile->CbData, 4096); + ZeroMemory(tile->CrData, 4096); - Stream_EnsureRemainingCapacity(s, 4096); - rfx_encode_component(context, cb_quants, pSrcDst[1], - Stream_Pointer(s), Stream_GetRemainingLength(s), &CbLen); - Stream_Seek(s, CbLen); - - Stream_EnsureRemainingCapacity(s, 4096); - rfx_encode_component(context, cr_quants, pSrcDst[2], - Stream_Pointer(s), Stream_GetRemainingLength(s), &CrLen); - Stream_Seek(s, CrLen); + rfx_encode_component(context, YQuant, pSrcDst[0], tile->YData, 4096, &YLen); + rfx_encode_component(context, CbQuant, pSrcDst[1], tile->CbData, 4096, &CbLen); + rfx_encode_component(context, CrQuant, pSrcDst[2], tile->CrData, 4096, &CrLen); tile->YLen = (UINT16) YLen; tile->CbLen = (UINT16) CbLen; tile->CrLen = (UINT16) CrLen; + Stream_EnsureRemainingCapacity(s, tile->YLen); + Stream_Write(s, tile->YData, tile->YLen); + + Stream_EnsureRemainingCapacity(s, tile->CbLen); + Stream_Write(s, tile->CbData, tile->CbLen); + + Stream_EnsureRemainingCapacity(s, tile->CrLen); + Stream_Write(s, tile->CrData, tile->CrLen); + PROFILER_EXIT(context->priv->prof_rfx_encode_rgb); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16); + + BufferPool_Return(context->priv->BufferPool, tile->YData); + BufferPool_Return(context->priv->BufferPool, tile->CbData); + BufferPool_Return(context->priv->BufferPool, tile->CrData); } diff --git a/libfreerdp/codec/rfx_encode.h b/libfreerdp/codec/rfx_encode.h index ff1197b7f..90e484988 100644 --- a/libfreerdp/codec/rfx_encode.h +++ b/libfreerdp/codec/rfx_encode.h @@ -22,7 +22,7 @@ #include -void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, int rowstride, wStream* s); +void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s); #endif From c8b85e19a4f5e80e1f1fde6228e9a571580ed651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 14:13:05 -0400 Subject: [PATCH 15/25] libfreerdp-codec: separate tile encoding from writing --- libfreerdp/codec/rfx.c | 124 +++++++++++++++------------------- libfreerdp/codec/rfx_encode.c | 19 +----- libfreerdp/codec/rfx_encode.h | 2 +- libfreerdp/codec/rfx_types.h | 1 - 4 files changed, 58 insertions(+), 88 deletions(-) diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index c0e165e3d..39e048daf 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -265,8 +265,6 @@ RFX_CONTEXT* rfx_context_new(void) SetThreadpoolThreadMaximum(context->priv->ThreadPool, context->priv->MaxThreadCount); } - context->priv->EncoderStreamPool = StreamPool_New(TRUE, 64*64*3+19); - /* initialize the default pixel format */ rfx_context_set_pixel_format(context, RDP_PIXEL_FORMAT_B8G8R8A8); @@ -299,7 +297,6 @@ void rfx_context_free(RFX_CONTEXT* context) { CloseThreadpool(context->priv->ThreadPool); DestroyThreadpoolEnvironment(&context->priv->ThreadPoolEnv); - StreamPool_Free(context->priv->EncoderStreamPool); #ifdef WITH_PROFILER fprintf(stderr, "\nWARNING: Profiling results probably unusable with multithreaded RemoteFX codec!\n"); #endif @@ -1000,53 +997,39 @@ static void rfx_compose_message_region(RFX_CONTEXT* context, wStream* s, Stream_Write_UINT16(s, 1); /* numTilesets */ } -static void rfx_compose_message_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) +static void rfx_write_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) { - int start_pos, end_pos; + UINT32 blockLen; - Stream_EnsureRemainingCapacity(s, 19); - start_pos = Stream_GetPosition(s); + blockLen = 19 + tile->YLen + tile->CbLen + tile->CrLen; + Stream_EnsureRemainingCapacity(s, blockLen); - Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType */ - Stream_Seek_UINT32(s); /* set BlockT.blockLen later */ - Stream_Write_UINT8(s, tile->quantIdxY); - Stream_Write_UINT8(s, tile->quantIdxCb); - Stream_Write_UINT8(s, tile->quantIdxCr); - Stream_Write_UINT16(s, tile->xIdx); - Stream_Write_UINT16(s, tile->yIdx); - - Stream_Seek(s, 6); /* YLen, CbLen, CrLen */ - - rfx_encode_rgb(context, tile, s); - - DEBUG_RFX("xIdx=%d yIdx=%d width=%d height=%d YLen=%d CbLen=%d CrLen=%d", - tile->xIdx, tile->yIdx, tile->width, tile->height, tile->YLen, tile->CbLen, tile->CrLen); - - end_pos = Stream_GetPosition(s); - - Stream_SetPosition(s, start_pos + 2); - Stream_Write_UINT32(s, 19 + tile->YLen + tile->CbLen + tile->CrLen); /* BlockT.blockLen */ - Stream_SetPosition(s, start_pos + 13); - Stream_Write_UINT16(s, tile->YLen); - Stream_Write_UINT16(s, tile->CbLen); - Stream_Write_UINT16(s, tile->CrLen); - - Stream_SetPosition(s, end_pos); + Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType (2 bytes) */ + Stream_Write_UINT32(s, blockLen); /* BlockT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */ + Stream_Write_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */ + Stream_Write_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */ + Stream_Write_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */ + Stream_Write_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */ + Stream_Write_UINT16(s, tile->YLen); /* YLen (2 bytes) */ + Stream_Write_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */ + Stream_Write_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */ + Stream_Write(s, tile->YData, tile->YLen); /* YData */ + Stream_Write(s, tile->CbData, tile->CbLen); /* CbData */ + Stream_Write(s, tile->CrData, tile->CrLen); /* CrData */ } - struct _RFX_TILE_COMPOSE_WORK_PARAM { RFX_TILE* tile; RFX_CONTEXT* context; - wStream* s; }; typedef struct _RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE instance, void* context, PTP_WORK work) { RFX_TILE_COMPOSE_WORK_PARAM* param = (RFX_TILE_COMPOSE_WORK_PARAM*) context; - rfx_compose_message_tile(param->context, param->s, param->tile); + rfx_encode_rgb(param->context, param->tile); } static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, @@ -1054,16 +1037,16 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, { int i; int size; + int xIdx; + int yIdx; + int numTiles; + int numTilesX; + int numTilesY; RFX_TILE* tile; int start_pos, end_pos; int numQuants; const UINT32* quantVals; const UINT32* quantValsPtr; - int numTiles; - int numTilesX; - int numTilesY; - int xIdx; - int yIdx; int tilesDataSize; PTP_WORK* work_objects = NULL; RFX_TILE_COMPOSE_WORK_PARAM* params = NULL; @@ -1107,15 +1090,14 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, quantValsPtr += 2; } - DEBUG_RFX("width:%d height:%d rowstride:%d", width, height, scanline); + DEBUG_RFX("width:%d height:%d scanline:%d", width, height, scanline); end_pos = Stream_GetPosition(s); if (context->priv->UseThreads) - { work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * numTiles); - params = (RFX_TILE_COMPOSE_WORK_PARAM*) malloc(sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * numTiles); - } + + params = (RFX_TILE_COMPOSE_WORK_PARAM*) malloc(sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * numTiles); for (yIdx = 0; yIdx < numTilesY; yIdx++) { @@ -1138,14 +1120,13 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, tile->YLen = 0; tile->CbLen = 0; tile->CrLen = 0; - tile->YData = NULL; - tile->CbData = NULL; - tile->CrData = NULL; + tile->YData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + tile->CbData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); + tile->CrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); if (context->priv->UseThreads) { params[i].context = context; - params[i].s = StreamPool_Take(context->priv->EncoderStreamPool, 0); work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); @@ -1154,32 +1135,39 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, } else { - rfx_compose_message_tile(context, s, tile); + rfx_encode_rgb(context, tile); } } } + for (yIdx = 0; yIdx < numTilesY; yIdx++) + { + for (xIdx = 0; xIdx < numTilesX; xIdx++) + { + i = yIdx * numTilesX + xIdx; + + tile = params[i].tile; + + if (context->priv->UseThreads) + { + WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); + CloseThreadpoolWork(work_objects[i]); + } + + rfx_write_tile(context, s, tile); + + BufferPool_Return(context->priv->BufferPool, tile->YData); + BufferPool_Return(context->priv->BufferPool, tile->CbData); + BufferPool_Return(context->priv->BufferPool, tile->CrData); + + ObjectPool_Return(context->priv->TilePool, (void*) params[i].tile); + } + } + if (context->priv->UseThreads) - { - for (yIdx = 0; yIdx < numTilesY; yIdx++) - { - for (xIdx = 0; xIdx < numTilesX; xIdx++) - { - i = yIdx * numTilesX + xIdx; - - WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); - CloseThreadpoolWork(work_objects[i]); - - Stream_EnsureRemainingCapacity(s, Stream_GetPosition(params[i].s)); - Stream_Write(s, Stream_Buffer(params[i].s), Stream_GetPosition(params[i].s)); - ObjectPool_Return(context->priv->TilePool, (void*) params[i].tile); - Stream_Release(params[i].s); - } - } - free(work_objects); - free(params); - } + + free(params); tilesDataSize = Stream_GetPosition(s) - end_pos; size += tilesDataSize; diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index 61d994e1a..f484e58fd 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -217,7 +217,7 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio BufferPool_Return(context->priv->BufferPool, dwt_buffer); } -void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s) +void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile) { INT16* pSrcDst[3]; int YLen, CbLen, CrLen; @@ -230,10 +230,6 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s) CbQuant = context->quants + (tile->quantIdxCb * 10); CrQuant = context->quants + (tile->quantIdxCr * 10); - tile->YData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); - tile->CbData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); - tile->CrData = (BYTE*) BufferPool_Take(context->priv->BufferPool, -1); - pSrcDst[0] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* y_r_buffer */ pSrcDst[1] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cb_g_buffer */ pSrcDst[2] = (INT16*)((BYTE*)BufferPool_Take(context->priv->BufferPool, -1) + 16); /* cr_b_buffer */ @@ -267,22 +263,9 @@ void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s) tile->CbLen = (UINT16) CbLen; tile->CrLen = (UINT16) CrLen; - Stream_EnsureRemainingCapacity(s, tile->YLen); - Stream_Write(s, tile->YData, tile->YLen); - - Stream_EnsureRemainingCapacity(s, tile->CbLen); - Stream_Write(s, tile->CbData, tile->CbLen); - - Stream_EnsureRemainingCapacity(s, tile->CrLen); - Stream_Write(s, tile->CrData, tile->CrLen); - PROFILER_EXIT(context->priv->prof_rfx_encode_rgb); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[0] - 16); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[1] - 16); BufferPool_Return(context->priv->BufferPool, (BYTE*)pSrcDst[2] - 16); - - BufferPool_Return(context->priv->BufferPool, tile->YData); - BufferPool_Return(context->priv->BufferPool, tile->CbData); - BufferPool_Return(context->priv->BufferPool, tile->CrData); } diff --git a/libfreerdp/codec/rfx_encode.h b/libfreerdp/codec/rfx_encode.h index 90e484988..28bc96651 100644 --- a/libfreerdp/codec/rfx_encode.h +++ b/libfreerdp/codec/rfx_encode.h @@ -22,7 +22,7 @@ #include -void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, wStream* s); +void rfx_encode_rgb(RFX_CONTEXT* context, RFX_TILE* tile); #endif diff --git a/libfreerdp/codec/rfx_types.h b/libfreerdp/codec/rfx_types.h index 2675d35ad..fbb4df837 100644 --- a/libfreerdp/codec/rfx_types.h +++ b/libfreerdp/codec/rfx_types.h @@ -49,7 +49,6 @@ struct _RFX_CONTEXT_PRIV TP_CALLBACK_ENVIRON ThreadPoolEnv; wBufferPool* BufferPool; - wStreamPool* EncoderStreamPool; /* profilers */ PROFILER_DEFINE(prof_rfx_decode_rgb); From fe2530365608d248c3675b474ea727ab1fc43066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 17:18:59 -0400 Subject: [PATCH 16/25] libfreerdp-codec: internal refactoring --- client/Windows/wf_gdi.c | 6 +- client/X11/xf_gdi.c | 6 +- cunit/test_rfx.c | 2 +- include/freerdp/codec/rfx.h | 25 +++- libfreerdp/codec/rfx.c | 290 ++++++++++++++++++++---------------- libfreerdp/gdi/gdi.c | 6 +- server/Windows/wf_update.c | 2 +- 7 files changed, 195 insertions(+), 142 deletions(-) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 7b497cf82..a11c5b107 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -575,14 +575,14 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); /* blit each tile */ - for (i = 0; i < message->num_tiles; i++) + 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; freerdp_image_convert(message->tiles[i]->data, wfc->tile->pdata, 64, 64, 32, 32, wfc->clrconv); - for (j = 0; j < message->num_rects; j++) + for (j = 0; j < message->numRects; j++) { wf_set_clip_rgn(wfc, surface_bits_command->destLeft + message->rects[j].x, @@ -596,7 +596,7 @@ void wf_gdi_surface_bits(wfContext* wfc, SURFACE_BITS_COMMAND* surface_bits_comm wf_set_null_clip_rgn(wfc); /* invalidate regions */ - for (i = 0; i < message->num_rects; i++) + for (i = 0; i < message->numRects; i++) { tx = surface_bits_command->destLeft + message->rects[i].x; ty = surface_bits_command->destTop + message->rects[i].y; diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index acdc0da47..e24bdac84 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -950,10 +950,10 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits XSetClipRectangles(xfc->display, xfc->gc, surface_bits_command->destLeft, surface_bits_command->destTop, - (XRectangle*) message->rects, message->num_rects, YXBanded); + (XRectangle*) message->rects, message->numRects, YXBanded); /* Draw the tiles to primary surface, each is 64x64. */ - for (i = 0; i < message->num_tiles; i++) + for (i = 0; i < message->numTiles; i++) { image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, (char*) message->tiles[i]->data, 64, 64, 32, 0); @@ -966,7 +966,7 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits } /* Copy the updated region from backstore to the window. */ - for (i = 0; i < message->num_rects; i++) + for (i = 0; i < message->numRects; i++) { tx = message->rects[i].x + surface_bits_command->destLeft; ty = message->rects[i].y + surface_bits_command->destTop; diff --git a/cunit/test_rfx.c b/cunit/test_rfx.c index aae5b2472..153c7cc64 100644 --- a/cunit/test_rfx.c +++ b/cunit/test_rfx.c @@ -404,7 +404,7 @@ void test_message(void) message = rfx_process_message(context, s->pointer, s->capacity); if (i == 0) { - for (j = 0; j < message->num_tiles; j++) + for (j = 0; j < message->numTiles; j++) { dump_ppm_image(message->tiles[j]->data); } diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index d2ecfd204..865311f0a 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -76,7 +76,7 @@ struct _RFX_MESSAGE * The rects array represents the updated region of the frame. The UI * requires to clip drawing destination base on the union of the rects. */ - UINT16 num_rects; + UINT16 numRects; RFX_RECT* rects; /** @@ -85,15 +85,33 @@ struct _RFX_MESSAGE * rects described above) are valid. Pixels outside of the region may * contain arbitrary data. */ - UINT16 num_tiles; + UINT16 numTiles; RFX_TILE** tiles; + + UINT16 numQuant; + UINT32* quantVals; + + UINT32 tilesDataSize; }; typedef struct _RFX_MESSAGE RFX_MESSAGE; typedef struct _RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV; +enum _RFX_STATE +{ + RFX_STATE_INITIAL, + RFX_STATE_SERVER_UNINITIALIZED, + RFX_STATE_SEND_HEADERS, + RFX_STATE_SEND_FRAME_DATA, + RFX_STATE_FRAME_DATA_SENT, + RFX_STATE_FINAL +}; +typedef enum _RFX_STATE RFX_STATE; + struct _RFX_CONTEXT { + RFX_STATE state; + UINT16 flags; UINT16 properties; UINT16 width; @@ -109,8 +127,7 @@ struct _RFX_CONTEXT const BYTE* palette; /* temporary data within a frame */ - UINT32 frame_idx; - BOOL header_processed; + UINT32 frameIdx; BYTE numQuant; UINT32* quants; BYTE quantIdxY; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 39e048daf..c3a838cd3 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -144,6 +144,12 @@ void rfx_tile_init(RFX_TILE* tile) { tile->x = 0; tile->y = 0; + tile->YLen = 0; + tile->YData = NULL; + tile->CbLen = 0; + tile->CbData = NULL; + tile->CrLen = 0; + tile->CrData = NULL; } } @@ -281,6 +287,8 @@ RFX_CONTEXT* rfx_context_new(void) RFX_INIT_SIMD(context); + context->state = RFX_STATE_SEND_HEADERS; + return context; } @@ -340,8 +348,8 @@ void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_f void rfx_context_reset(RFX_CONTEXT* context) { - context->header_processed = FALSE; - context->frame_idx = 0; + context->state = RFX_STATE_SEND_HEADERS; + context->frameIdx = 0; } static BOOL rfx_process_message_sync(RFX_CONTEXT* context, wStream* s) @@ -524,27 +532,27 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag } Stream_Seek_UINT8(s); /* regionFlags (1 byte) */ - Stream_Read_UINT16(s, message->num_rects); /* numRects (2 bytes) */ + Stream_Read_UINT16(s, message->numRects); /* numRects (2 bytes) */ - if (message->num_rects < 1) + if (message->numRects < 1) { DEBUG_WARN("no rects."); return TRUE; } - if (Stream_GetRemainingLength(s) < 8 * message->num_rects) + if (Stream_GetRemainingLength(s) < 8 * message->numRects) { - DEBUG_WARN("RfxMessageRegion packet too small for num_rects=%d", message->num_rects); + DEBUG_WARN("RfxMessageRegion packet too small for num_rects=%d", message->numRects); return FALSE; } if (message->rects != NULL) - message->rects = (RFX_RECT*) realloc(message->rects, message->num_rects * sizeof(RFX_RECT)); + message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT)); else - message->rects = (RFX_RECT*) malloc(message->num_rects * sizeof(RFX_RECT)); + message->rects = (RFX_RECT*) malloc(message->numRects * sizeof(RFX_RECT)); /* rects */ - for (i = 0; i < message->num_rects; i++) + for (i = 0; i < message->numRects; i++) { /* RFX_RECT */ Stream_Read_UINT16(s, message->rects[i].x); /* x (2 bytes) */ @@ -611,9 +619,9 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa return TRUE; } - Stream_Read_UINT16(s, message->num_tiles); /* numTiles (2 bytes) */ + Stream_Read_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ - if (message->num_tiles < 1) + if (message->numTiles < 1) { DEBUG_WARN("no tiles."); return TRUE; @@ -661,24 +669,24 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa context->quants[i * 10 + 8], context->quants[i * 10 + 9]); } - message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->num_tiles); - ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->num_tiles); + message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles); + ZeroMemory(message->tiles, sizeof(RFX_TILE*) * message->numTiles); if (context->priv->UseThreads) { - work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->num_tiles); - params = (RFX_TILE_PROCESS_WORK_PARAM*) malloc(sizeof(RFX_TILE_PROCESS_WORK_PARAM) * message->num_tiles); + work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->numTiles); + params = (RFX_TILE_PROCESS_WORK_PARAM*) malloc(sizeof(RFX_TILE_PROCESS_WORK_PARAM) * message->numTiles); } /* tiles */ - for (i = 0; i < message->num_tiles; i++) + for (i = 0; i < message->numTiles; i++) { tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); /* RFX_TILE */ if (Stream_GetRemainingLength(s) < 6) { - DEBUG_WARN("RfxMessageTileSet packet too small to read tile %d/%d", i, message->num_tiles); + DEBUG_WARN("RfxMessageTileSet packet too small to read tile %d/%d", i, message->numTiles); return FALSE; } @@ -687,7 +695,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa if (Stream_GetRemainingLength(s) < blockLen - 6) { - DEBUG_WARN("RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->num_tiles, blockLen); + DEBUG_WARN("RfxMessageTileSet not enough bytes to read tile %d/%d with blocklen=%d", i, message->numTiles, blockLen); return FALSE; } @@ -738,7 +746,7 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa if (context->priv->UseThreads) { - for (i = 0; i < message->num_tiles; i++) + for (i = 0; i < message->numTiles; i++) { WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); CloseThreadpoolWork(work_objects[i]); @@ -747,6 +755,14 @@ static BOOL rfx_process_message_tileset(RFX_CONTEXT* context, RFX_MESSAGE* messa free(work_objects); free(params); } + + for (i = 0; i < message->numTiles; i++) + { + tile = message->tiles[i]; + tile->YLen = tile->CbLen = tile->CrLen = 0; + tile->YData = tile->CbData = tile->CrData = NULL; + } + return TRUE; } @@ -847,7 +863,7 @@ RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length UINT16 rfx_message_get_tile_count(RFX_MESSAGE* message) { - return message->num_tiles; + return message->numTiles; } RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index) @@ -857,7 +873,7 @@ RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index) UINT16 rfx_message_get_rect_count(RFX_MESSAGE* message) { - return message->num_rects; + return message->numRects; } RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index) @@ -868,16 +884,31 @@ RFX_RECT* rfx_message_get_rect(RFX_MESSAGE* message, int index) void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) { int i; + RFX_TILE* tile; - if (message != NULL) + if (message) { - free(message->rects); + if (message->rects) + { + free(message->rects); + } if (message->tiles) { - for (i = 0; i < message->num_tiles; i++) + for (i = 0; i < message->numTiles; i++) { - ObjectPool_Return(context->priv->TilePool, (void*) message->tiles[i]); + tile = message->tiles[i]; + + if (tile->YData) + BufferPool_Return(context->priv->BufferPool, tile->YData); + + if (tile->CbData) + BufferPool_Return(context->priv->BufferPool, tile->CbData); + + if (tile->CrData) + BufferPool_Return(context->priv->BufferPool, tile->CrData); + + ObjectPool_Return(context->priv->TilePool, (void*) tile); } free(message->tiles); @@ -951,8 +982,6 @@ void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s) rfx_compose_message_context(context, s); rfx_compose_message_codec_versions(context, s); rfx_compose_message_channels(context, s); - - context->header_processed = TRUE; } static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, wStream* s) @@ -963,29 +992,29 @@ static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, wStream* s) Stream_Write_UINT32(s, 14); /* CodecChannelT.blockLen */ Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ - Stream_Write_UINT32(s, context->frame_idx); /* frameIdx */ + Stream_Write_UINT32(s, context->frameIdx); /* frameIdx */ Stream_Write_UINT16(s, 1); /* numRegions */ - context->frame_idx++; + context->frameIdx++; } static void rfx_compose_message_region(RFX_CONTEXT* context, wStream* s, - const RFX_RECT* rects, int num_rects) + const RFX_RECT* rects, int numRects) { - int size; int i; + UINT32 blockLen; - size = 15 + num_rects * 8; - Stream_EnsureRemainingCapacity(s, size); + blockLen = 15 + (numRects * 8); + Stream_EnsureRemainingCapacity(s, blockLen); - Stream_Write_UINT16(s, WBT_REGION); /* CodecChannelT.blockType */ - Stream_Write_UINT32(s, size); /* set CodecChannelT.blockLen later */ - Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ - Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ - Stream_Write_UINT8(s, 1); /* regionFlags */ - Stream_Write_UINT16(s, num_rects); /* numRects */ + Stream_Write_UINT16(s, WBT_REGION); /* CodecChannelT.blockType (2 bytes) */ + Stream_Write_UINT32(s, blockLen); /* set CodecChannelT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId (1 byte) */ + Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId (1 byte) */ + Stream_Write_UINT8(s, 1); /* regionFlags (1 byte) */ + Stream_Write_UINT16(s, numRects); /* numRects (2 bytes) */ - for (i = 0; i < num_rects; i++) + for (i = 0; i < numRects; i++) { Stream_Write_UINT16(s, rects[i].x); Stream_Write_UINT16(s, rects[i].y); @@ -993,15 +1022,20 @@ static void rfx_compose_message_region(RFX_CONTEXT* context, wStream* s, Stream_Write_UINT16(s, rects[i].height); } - Stream_Write_UINT16(s, CBT_REGION); /* regionType */ - Stream_Write_UINT16(s, 1); /* numTilesets */ + Stream_Write_UINT16(s, CBT_REGION); /* regionType (2 bytes) */ + Stream_Write_UINT16(s, 1); /* numTilesets (2 bytes) */ +} + +static int rfx_tile_length(RFX_TILE* tile) +{ + return 19 + tile->YLen + tile->CbLen + tile->CrLen; } static void rfx_write_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) { UINT32 blockLen; - blockLen = 19 + tile->YLen + tile->CbLen + tile->CrLen; + blockLen = rfx_tile_length(tile); Stream_EnsureRemainingCapacity(s, blockLen); Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType (2 bytes) */ @@ -1032,25 +1066,21 @@ void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE insta rfx_encode_rgb(param->context, param->tile); } -static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, - BYTE* image_data, int width, int height, int scanline) +RFX_MESSAGE* rfx_compose_message_full(RFX_CONTEXT* context, BYTE* data, int width, int height, int scanline) { int i; - int size; int xIdx; int yIdx; - int numTiles; int numTilesX; int numTilesY; RFX_TILE* tile; - int start_pos, end_pos; - int numQuants; - const UINT32* quantVals; - const UINT32* quantValsPtr; - int tilesDataSize; + RFX_MESSAGE* message = NULL; PTP_WORK* work_objects = NULL; RFX_TILE_COMPOSE_WORK_PARAM* params = NULL; + message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); + ZeroMemory(message, sizeof(RFX_MESSAGE)); + if (!context->numQuant) { context->numQuant = 1; @@ -1060,44 +1090,23 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, context->quantIdxCr = 0; } - numQuants = context->numQuant; - quantVals = context->quants; + message->numQuant = context->numQuant; + message->quantVals = context->quants; numTilesX = (width + 63) / 64; numTilesY = (height + 63) / 64; - numTiles = numTilesX * numTilesY; - size = 22 + numQuants * 5; - Stream_EnsureRemainingCapacity(s, size); - start_pos = Stream_GetPosition(s); + message->numTiles = numTilesX * numTilesY; + message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE) * message->numTiles); + ZeroMemory(message->tiles, sizeof(RFX_TILE) * message->numTiles); - Stream_Write_UINT16(s, WBT_EXTENSION); /* CodecChannelT.blockType */ - Stream_Seek_UINT32(s); /* set CodecChannelT.blockLen later */ - Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ - Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ - Stream_Write_UINT16(s, CBT_TILESET); /* subtype */ - Stream_Write_UINT16(s, 0); /* idx */ - Stream_Write_UINT16(s, context->properties); /* properties */ - Stream_Write_UINT8(s, numQuants); /* numQuants */ - Stream_Write_UINT8(s, 0x40); /* tileSize */ - Stream_Write_UINT16(s, numTiles); /* numTiles */ - Stream_Seek_UINT32(s); /* set tilesDataSize later */ - - quantValsPtr = quantVals; - for (i = 0; i < numQuants * 5; i++) - { - Stream_Write_UINT8(s, quantValsPtr[0] + (quantValsPtr[1] << 4)); - quantValsPtr += 2; - } - - DEBUG_RFX("width:%d height:%d scanline:%d", width, height, scanline); - - end_pos = Stream_GetPosition(s); + DEBUG_RFX("width: %d height: %d scanline: %d", width, height, scanline); if (context->priv->UseThreads) - work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * numTiles); - - params = (RFX_TILE_COMPOSE_WORK_PARAM*) malloc(sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * numTiles); + { + work_objects = (PTP_WORK*) malloc(sizeof(PTP_WORK) * message->numTiles); + params = (RFX_TILE_COMPOSE_WORK_PARAM*) malloc(sizeof(RFX_TILE_COMPOSE_WORK_PARAM) * message->numTiles); + } for (yIdx = 0; yIdx < numTilesY; yIdx++) { @@ -1105,10 +1114,10 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, { i = yIdx * numTilesX + xIdx; - tile = params[i].tile = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); + tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); tile->scanline = scanline; - tile->data = image_data + yIdx * 64 * scanline + xIdx * 8 * context->bits_per_pixel; + tile->data = data + yIdx * 64 * scanline + xIdx * 8 * context->bits_per_pixel; tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; @@ -1127,6 +1136,7 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, if (context->priv->UseThreads) { params[i].context = context; + params[i].tile = tile; work_objects[i] = CreateThreadpoolWork((PTP_WORK_CALLBACK) rfx_compose_message_tile_work_callback, (void*) ¶ms[i], &context->priv->ThreadPoolEnv); @@ -1140,45 +1150,68 @@ static void rfx_compose_message_tileset(RFX_CONTEXT* context, wStream* s, } } - for (yIdx = 0; yIdx < numTilesY; yIdx++) + message->tilesDataSize = 0; + + for (i = 0; i < message->numTiles; i++) { - for (xIdx = 0; xIdx < numTilesX; xIdx++) + tile = message->tiles[i]; + + if (context->priv->UseThreads) { - i = yIdx * numTilesX + xIdx; - - tile = params[i].tile; - - if (context->priv->UseThreads) - { - WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); - CloseThreadpoolWork(work_objects[i]); - } - - rfx_write_tile(context, s, tile); - - BufferPool_Return(context->priv->BufferPool, tile->YData); - BufferPool_Return(context->priv->BufferPool, tile->CbData); - BufferPool_Return(context->priv->BufferPool, tile->CrData); - - ObjectPool_Return(context->priv->TilePool, (void*) params[i].tile); + WaitForThreadpoolWorkCallbacks(work_objects[i], FALSE); + CloseThreadpoolWork(work_objects[i]); } + + message->tilesDataSize += rfx_tile_length(tile); } if (context->priv->UseThreads) + { free(work_objects); + free(params); + } - free(params); + return message; +} - tilesDataSize = Stream_GetPosition(s) - end_pos; - size += tilesDataSize; - end_pos = Stream_GetPosition(s); +static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +{ + int i; + RFX_TILE* tile; + UINT32 blockLen; + UINT32* quantVals; - Stream_SetPosition(s, start_pos + 2); - Stream_Write_UINT32(s, size); /* CodecChannelT.blockLen */ - Stream_SetPosition(s, start_pos + 18); - Stream_Write_UINT32(s, tilesDataSize); + blockLen = 22 + (message->numQuant * 5) + message->tilesDataSize; + Stream_EnsureRemainingCapacity(s, blockLen); - Stream_SetPosition(s, end_pos); + Stream_Write_UINT16(s, WBT_EXTENSION); /* CodecChannelT.blockType (2 bytes) */ + Stream_Write_UINT32(s, blockLen); /* set CodecChannelT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId (1 byte) */ + Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId (1 byte) */ + Stream_Write_UINT16(s, CBT_TILESET); /* subtype (2 bytes) */ + Stream_Write_UINT16(s, 0); /* idx (2 bytes) */ + Stream_Write_UINT16(s, context->properties); /* properties (2 bytes) */ + Stream_Write_UINT8(s, message->numQuant); /* numQuant (1 byte) */ + Stream_Write_UINT8(s, 0x40); /* tileSize (1 byte) */ + Stream_Write_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ + Stream_Write_UINT32(s, message->tilesDataSize); /* set tilesDataSize later */ + + quantVals = message->quantVals; + + for (i = 0; i < message->numQuant * 5; i++) + { + Stream_Write_UINT8(s, quantVals[0] + (quantVals[1] << 4)); + quantVals += 2; + } + + for (i = 0; i < message->numTiles; i++) + { + tile = message->tiles[i]; + rfx_write_tile(context, s, tile); + } + + DEBUG_RFX("numQuant: %d numTiles: %d tilesDataSize: %d", + message->numQuant, message->numTiles, message->tilesDataSize); } static void rfx_compose_message_frame_end(RFX_CONTEXT* context, wStream* s) @@ -1191,22 +1224,25 @@ static void rfx_compose_message_frame_end(RFX_CONTEXT* context, wStream* s) Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ } -static void rfx_compose_message_data(RFX_CONTEXT* context, wStream* s, - const RFX_RECT* rects, int num_rects, BYTE* image_data, int width, int height, int rowstride) -{ - rfx_compose_message_frame_begin(context, s); - rfx_compose_message_region(context, s, rects, num_rects); - rfx_compose_message_tileset(context, s, image_data, width, height, rowstride); - rfx_compose_message_frame_end(context, s); -} - FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s, - const RFX_RECT* rects, int num_rects, BYTE* image_data, int width, int height, int rowstride) + const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline) { - /* Only the first frame should send the RemoteFX header */ - if (context->frame_idx == 0 && !context->header_processed) - rfx_compose_message_header(context, s); + RFX_MESSAGE* message; - rfx_compose_message_data(context, s, rects, num_rects, image_data, width, height, rowstride); + if ((context->frameIdx == 0) && (context->state == RFX_STATE_SEND_HEADERS)) + { + rfx_compose_message_header(context, s); + context->state = RFX_STATE_SEND_FRAME_DATA; + } + + rfx_compose_message_frame_begin(context, s); + rfx_compose_message_region(context, s, rects, numRects); + + message = rfx_compose_message_full(context, data, width, height, scanline); + rfx_write_message_tileset(context, s, message); + + rfx_compose_message_frame_end(context, s); + + rfx_message_free(context, message); } diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 6a9cea2f3..d6e271dc5 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -789,10 +789,10 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co message = rfx_process_message(rfx_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); - DEBUG_GDI("num_rects %d num_tiles %d", message->num_rects, message->num_tiles); + DEBUG_GDI("num_rects %d num_tiles %d", message->numRects, message->numTiles); /* blit each tile */ - for (i = 0; i < message->num_tiles; i++) + 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; @@ -805,7 +805,7 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co #endif - for (j = 0; j < message->num_rects; j++) + for (j = 0; j < message->numRects; j++) { gdi_SetClipRgn(gdi->primary->hdc, surface_bits_command->destLeft + message->rects[j].x, diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index c8e8dc796..e6daf5c57 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -138,7 +138,7 @@ void wf_update_encode(wfInfo* wfi) rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, pDataBits, width, height, stride); - wfi->frame_idx = wfi->rfx_context->frame_idx; + wfi->frame_idx = wfi->rfx_context->frameIdx; cmd->destLeft = wfi->invalid.left; cmd->destTop = wfi->invalid.top; From dfbd4cb9fbd7f53b0f6d0e9ed96f1daad4bf5d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 13 Aug 2013 17:50:05 -0400 Subject: [PATCH 17/25] libfreerdp-codec: refactor encoder to use message-centric interface --- include/freerdp/codec/rfx.h | 2 + libfreerdp/codec/rfx.c | 101 +++++++++++++++++++----------------- 2 files changed, 55 insertions(+), 48 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 865311f0a..891f65a97 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -72,6 +72,8 @@ typedef struct _RFX_TILE RFX_TILE; struct _RFX_MESSAGE { + UINT32 frameIdx; + /** * The rects array represents the updated region of the frame. The UI * requires to clip drawing destination base on the union of the rects. diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index c3a838cd3..db4cfb09b 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -984,48 +984,6 @@ void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s) rfx_compose_message_channels(context, s); } -static void rfx_compose_message_frame_begin(RFX_CONTEXT* context, wStream* s) -{ - Stream_EnsureRemainingCapacity(s, 14); - - Stream_Write_UINT16(s, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */ - Stream_Write_UINT32(s, 14); /* CodecChannelT.blockLen */ - Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ - Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ - Stream_Write_UINT32(s, context->frameIdx); /* frameIdx */ - Stream_Write_UINT16(s, 1); /* numRegions */ - - context->frameIdx++; -} - -static void rfx_compose_message_region(RFX_CONTEXT* context, wStream* s, - const RFX_RECT* rects, int numRects) -{ - int i; - UINT32 blockLen; - - blockLen = 15 + (numRects * 8); - Stream_EnsureRemainingCapacity(s, blockLen); - - Stream_Write_UINT16(s, WBT_REGION); /* CodecChannelT.blockType (2 bytes) */ - Stream_Write_UINT32(s, blockLen); /* set CodecChannelT.blockLen (4 bytes) */ - Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId (1 byte) */ - Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId (1 byte) */ - Stream_Write_UINT8(s, 1); /* regionFlags (1 byte) */ - Stream_Write_UINT16(s, numRects); /* numRects (2 bytes) */ - - for (i = 0; i < numRects; i++) - { - Stream_Write_UINT16(s, rects[i].x); - Stream_Write_UINT16(s, rects[i].y); - Stream_Write_UINT16(s, rects[i].width); - Stream_Write_UINT16(s, rects[i].height); - } - - Stream_Write_UINT16(s, CBT_REGION); /* regionType (2 bytes) */ - Stream_Write_UINT16(s, 1); /* numTilesets (2 bytes) */ -} - static int rfx_tile_length(RFX_TILE* tile) { return 19 + tile->YLen + tile->CbLen + tile->CrLen; @@ -1066,7 +1024,8 @@ void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE insta rfx_encode_rgb(param->context, param->tile); } -RFX_MESSAGE* rfx_compose_message_full(RFX_CONTEXT* context, BYTE* data, int width, int height, int scanline) +RFX_MESSAGE* rfx_compose_message_full(RFX_CONTEXT* context, const RFX_RECT* rects, + int numRects, BYTE* data, int width, int height, int scanline) { int i; int xIdx; @@ -1081,6 +1040,11 @@ RFX_MESSAGE* rfx_compose_message_full(RFX_CONTEXT* context, BYTE* data, int widt message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); ZeroMemory(message, sizeof(RFX_MESSAGE)); + message->frameIdx = context->frameIdx++; + + message->numRects = numRects; + message->rects = (RFX_RECT*) rects; + if (!context->numQuant) { context->numQuant = 1; @@ -1214,7 +1178,46 @@ static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESS message->numQuant, message->numTiles, message->tilesDataSize); } -static void rfx_compose_message_frame_end(RFX_CONTEXT* context, wStream* s) +void rfx_write_message_frame_begin(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +{ + Stream_EnsureRemainingCapacity(s, 14); + + Stream_Write_UINT16(s, WBT_FRAME_BEGIN); /* CodecChannelT.blockType */ + Stream_Write_UINT32(s, 14); /* CodecChannelT.blockLen */ + Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ + Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ + Stream_Write_UINT32(s, message->frameIdx); /* frameIdx */ + Stream_Write_UINT16(s, 1); /* numRegions */ +} + +void rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) +{ + int i; + UINT32 blockLen; + + blockLen = 15 + (message->numRects * 8); + Stream_EnsureRemainingCapacity(s, blockLen); + + Stream_Write_UINT16(s, WBT_REGION); /* CodecChannelT.blockType (2 bytes) */ + Stream_Write_UINT32(s, blockLen); /* set CodecChannelT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId (1 byte) */ + Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId (1 byte) */ + Stream_Write_UINT8(s, 1); /* regionFlags (1 byte) */ + Stream_Write_UINT16(s, message->numRects); /* numRects (2 bytes) */ + + for (i = 0; i < message->numRects; i++) + { + Stream_Write_UINT16(s, message->rects[i].x); + Stream_Write_UINT16(s, message->rects[i].y); + Stream_Write_UINT16(s, message->rects[i].width); + Stream_Write_UINT16(s, message->rects[i].height); + } + + Stream_Write_UINT16(s, CBT_REGION); /* regionType (2 bytes) */ + Stream_Write_UINT16(s, 1); /* numTilesets (2 bytes) */ +} + +void rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { Stream_EnsureRemainingCapacity(s, 8); @@ -1235,13 +1238,15 @@ FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s, context->state = RFX_STATE_SEND_FRAME_DATA; } - rfx_compose_message_frame_begin(context, s); - rfx_compose_message_region(context, s, rects, numRects); + message = rfx_compose_message_full(context, rects, numRects, data, width, height, scanline); - message = rfx_compose_message_full(context, data, width, height, scanline); + rfx_write_message_frame_begin(context, s, message); + rfx_write_message_region(context, s, message); rfx_write_message_tileset(context, s, message); + rfx_write_message_frame_end(context, s, message); - rfx_compose_message_frame_end(context, s); + message->rects = NULL; + message->numRects = 0; rfx_message_free(context, message); } From 5e6325d62c7a838d289bd75a822243f9456a582d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 14 Aug 2013 10:14:47 -0400 Subject: [PATCH 18/25] libfreerdp-codec: start exporting split encode/write rfx api --- include/freerdp/codec/rfx.h | 5 ++ libfreerdp/codec/rfx.c | 134 ++++++++++++++++++++---------------- 2 files changed, 79 insertions(+), 60 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 891f65a97..d1ee72d3a 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -80,6 +80,7 @@ struct _RFX_MESSAGE */ UINT16 numRects; RFX_RECT* rects; + BOOL freeRects; /** * The tiles array represents the actual frame data. Each tile is always @@ -165,6 +166,10 @@ FREERDP_API void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s); FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects, int num_rects, BYTE* image_data, int width, int height, int rowstride); +FREERDP_API RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, + int numRects, BYTE* data, int width, int height, int scanline); +FREERDP_API void rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message); + #ifdef __cplusplus } #endif diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index db4cfb09b..1a465f0db 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -777,6 +777,8 @@ RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); ZeroMemory(message, sizeof(RFX_MESSAGE)); + message->freeRects = TRUE; + s = Stream_New(data, length); while (Stream_GetRemainingLength(s) > 6) @@ -888,7 +890,7 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) if (message) { - if (message->rects) + if ((message->rects) && (message->freeRects)) { free(message->rects); } @@ -918,52 +920,10 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) } } -static void rfx_compose_message_sync(RFX_CONTEXT* context, wStream* s) -{ - Stream_Write_UINT16(s, WBT_SYNC); /* BlockT.blockType */ - Stream_Write_UINT32(s, 12); /* BlockT.blockLen */ - Stream_Write_UINT32(s, WF_MAGIC); /* magic */ - Stream_Write_UINT16(s, WF_VERSION_1_0); /* version */ -} - -static void rfx_compose_message_codec_versions(RFX_CONTEXT* context, wStream* s) -{ - Stream_Write_UINT16(s, WBT_CODEC_VERSIONS); /* BlockT.blockType */ - Stream_Write_UINT32(s, 10); /* BlockT.blockLen */ - Stream_Write_UINT8(s, 1); /* numCodecs */ - Stream_Write_UINT8(s, 1); /* codecs.codecId */ - Stream_Write_UINT16(s, WF_VERSION_1_0); /* codecs.version */ -} - -static void rfx_compose_message_channels(RFX_CONTEXT* context, wStream* s) -{ - Stream_Write_UINT16(s, WBT_CHANNELS); /* BlockT.blockType */ - Stream_Write_UINT32(s, 12); /* BlockT.blockLen */ - Stream_Write_UINT8(s, 1); /* numChannels */ - Stream_Write_UINT8(s, 0); /* Channel.channelId */ - Stream_Write_UINT16(s, context->width); /* Channel.width */ - Stream_Write_UINT16(s, context->height); /* Channel.height */ -} - -static void rfx_compose_message_context(RFX_CONTEXT* context, wStream* s) +static void rfx_update_context_properties(RFX_CONTEXT* context) { UINT16 properties; - Stream_Write_UINT16(s, WBT_CONTEXT); /* CodecChannelT.blockType */ - Stream_Write_UINT32(s, 13); /* CodecChannelT.blockLen */ - Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId */ - Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ - Stream_Write_UINT8(s, 0); /* ctxId */ - Stream_Write_UINT16(s, CT_TILE_64x64); /* tileSize */ - - /* properties */ - properties = context->flags; /* flags */ - properties |= (COL_CONV_ICT << 3); /* cct */ - properties |= (CLW_XFORM_DWT_53_A << 5); /* xft */ - properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 9); /* et */ - properties |= (SCALAR_QUANTIZATION << 13); /* qt */ - Stream_Write_UINT16(s, properties); - /* properties in tilesets: note that this has different format from the one in TS_RFX_CONTEXT */ properties = 1; /* lt */ properties |= (context->flags << 1); /* flags */ @@ -971,17 +931,67 @@ static void rfx_compose_message_context(RFX_CONTEXT* context, wStream* s) properties |= (CLW_XFORM_DWT_53_A << 6); /* xft */ properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 10); /* et */ properties |= (SCALAR_QUANTIZATION << 14); /* qt */ + context->properties = properties; } +static void rfx_write_message_sync(RFX_CONTEXT* context, wStream* s) +{ + Stream_Write_UINT16(s, WBT_SYNC); /* BlockT.blockType (2 bytes) */ + Stream_Write_UINT32(s, 12); /* BlockT.blockLen (4 bytes) */ + Stream_Write_UINT32(s, WF_MAGIC); /* magic (4 bytes) */ + Stream_Write_UINT16(s, WF_VERSION_1_0); /* version (2 bytes) */ +} + +static void rfx_write_message_codec_versions(RFX_CONTEXT* context, wStream* s) +{ + Stream_Write_UINT16(s, WBT_CODEC_VERSIONS); /* BlockT.blockType (2 bytes) */ + Stream_Write_UINT32(s, 10); /* BlockT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, 1); /* numCodecs (1 byte) */ + Stream_Write_UINT8(s, 1); /* codecs.codecId (1 byte) */ + Stream_Write_UINT16(s, WF_VERSION_1_0); /* codecs.version (2 bytes) */ +} + +static void rfx_write_message_channels(RFX_CONTEXT* context, wStream* s) +{ + Stream_Write_UINT16(s, WBT_CHANNELS); /* BlockT.blockType (2 bytes) */ + Stream_Write_UINT32(s, 12); /* BlockT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, 1); /* numChannels (1 byte) */ + Stream_Write_UINT8(s, 0); /* Channel.channelId (1 byte) */ + Stream_Write_UINT16(s, context->width); /* Channel.width (2 bytes) */ + Stream_Write_UINT16(s, context->height); /* Channel.height (2 bytes) */ +} + +static void rfx_write_message_context(RFX_CONTEXT* context, wStream* s) +{ + UINT16 properties; + + Stream_Write_UINT16(s, WBT_CONTEXT); /* CodecChannelT.blockType (2 bytes) */ + Stream_Write_UINT32(s, 13); /* CodecChannelT.blockLen (4 bytes) */ + Stream_Write_UINT8(s, 1); /* CodecChannelT.codecId (1 byte) */ + Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId (1 byte) */ + Stream_Write_UINT8(s, 0); /* ctxId (1 byte) */ + Stream_Write_UINT16(s, CT_TILE_64x64); /* tileSize (2 bytes) */ + + /* properties */ + properties = context->flags; /* flags */ + properties |= (COL_CONV_ICT << 3); /* cct */ + properties |= (CLW_XFORM_DWT_53_A << 5); /* xft */ + properties |= ((context->mode == RLGR1 ? CLW_ENTROPY_RLGR1 : CLW_ENTROPY_RLGR3) << 9); /* et */ + properties |= (SCALAR_QUANTIZATION << 13); /* qt */ + Stream_Write_UINT16(s, properties); /* properties (2 bytes) */ + + rfx_update_context_properties(context); +} + void rfx_compose_message_header(RFX_CONTEXT* context, wStream* s) { Stream_EnsureRemainingCapacity(s, 12 + 10 + 12 + 13); - rfx_compose_message_sync(context, s); - rfx_compose_message_context(context, s); - rfx_compose_message_codec_versions(context, s); - rfx_compose_message_channels(context, s); + rfx_write_message_sync(context, s); + rfx_write_message_context(context, s); + rfx_write_message_codec_versions(context, s); + rfx_write_message_channels(context, s); } static int rfx_tile_length(RFX_TILE* tile) @@ -1024,7 +1034,7 @@ void CALLBACK rfx_compose_message_tile_work_callback(PTP_CALLBACK_INSTANCE insta rfx_encode_rgb(param->context, param->tile); } -RFX_MESSAGE* rfx_compose_message_full(RFX_CONTEXT* context, const RFX_RECT* rects, +RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline) { int i; @@ -1040,6 +1050,9 @@ RFX_MESSAGE* rfx_compose_message_full(RFX_CONTEXT* context, const RFX_RECT* rect message = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE)); ZeroMemory(message, sizeof(RFX_MESSAGE)); + if (context->state == RFX_STATE_SEND_HEADERS) + rfx_update_context_properties(context); + message->frameIdx = context->frameIdx++; message->numRects = numRects; @@ -1158,7 +1171,7 @@ static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESS Stream_Write_UINT8(s, message->numQuant); /* numQuant (1 byte) */ Stream_Write_UINT8(s, 0x40); /* tileSize (1 byte) */ Stream_Write_UINT16(s, message->numTiles); /* numTiles (2 bytes) */ - Stream_Write_UINT32(s, message->tilesDataSize); /* set tilesDataSize later */ + Stream_Write_UINT32(s, message->tilesDataSize); /* tilesDataSize (4 bytes) */ quantVals = message->quantVals; @@ -1227,27 +1240,28 @@ void rfx_write_message_frame_end(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* Stream_Write_UINT8(s, 0); /* CodecChannelT.channelId */ } -FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s, - const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline) +void rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { - RFX_MESSAGE* message; - - if ((context->frameIdx == 0) && (context->state == RFX_STATE_SEND_HEADERS)) + if (context->state == RFX_STATE_SEND_HEADERS) { rfx_compose_message_header(context, s); context->state = RFX_STATE_SEND_FRAME_DATA; } - message = rfx_compose_message_full(context, rects, numRects, data, width, height, scanline); - rfx_write_message_frame_begin(context, s, message); rfx_write_message_region(context, s, message); rfx_write_message_tileset(context, s, message); rfx_write_message_frame_end(context, s, message); +} - message->rects = NULL; - message->numRects = 0; +void rfx_compose_message(RFX_CONTEXT* context, wStream* s, + const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline) +{ + RFX_MESSAGE* message; + + message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); + + rfx_write_message(context, s, message); rfx_message_free(context, message); } - From 2d3d5acf1ebfd493d4dbbd90e8f3c9ca623b6c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 14 Aug 2013 13:19:01 -0400 Subject: [PATCH 19/25] libfreerdp-codec: initial support for RemoteFX fragmented encoding --- include/freerdp/codec/rfx.h | 4 +++ libfreerdp/codec/rfx.c | 60 ++++++++++++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index d1ee72d3a..254cadfb5 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -95,6 +95,8 @@ struct _RFX_MESSAGE UINT32* quantVals; UINT32 tilesDataSize; + + BOOL freeArray; }; typedef struct _RFX_MESSAGE RFX_MESSAGE; @@ -168,6 +170,8 @@ FREERDP_API void rfx_compose_message(RFX_CONTEXT* context, wStream* s, FREERDP_API RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, BYTE* data, int width, int height, int scanline); +FREERDP_API RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, + BYTE* data, int width, int height, int scanline, int* numMessages, int maxDataSize); FREERDP_API void rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message); #ifdef __cplusplus diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 1a465f0db..b43f7c7e6 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -916,7 +916,8 @@ void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message) free(message->tiles); } - free(message); + if (!message->freeArray) + free(message); } } @@ -1151,6 +1152,63 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, return message; } +RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* numMessages, int maxDataSize) +{ + int i, j; + UINT32 tileDataSize; + RFX_MESSAGE* messages; + + maxDataSize -= 1024; /* reserve enough space for headers */ + + *numMessages = ((message->tilesDataSize + maxDataSize) / maxDataSize) * 4; + + messages = (RFX_MESSAGE*) malloc(sizeof(RFX_MESSAGE) * (*numMessages)); + ZeroMemory(messages, sizeof(RFX_MESSAGE) * (*numMessages)); + + j = 0; + + for (i = 0; i < message->numTiles; i++) + { + tileDataSize = rfx_tile_length(message->tiles[i]); + + if ((messages[j].tilesDataSize + tileDataSize) > maxDataSize) + j++; + + if (!messages[j].numTiles) + { + messages[j].frameIdx = message->frameIdx + j; + messages[j].numQuant = message->numQuant; + messages[j].quantVals = message->quantVals; + messages[j].numRects = message->numRects; + messages[j].rects = message->rects; + messages[j].tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles); + messages[j].freeArray = TRUE; + } + + messages[j].tilesDataSize += tileDataSize; + messages[j].tiles[messages[j].numTiles++] = message->tiles[i]; + message->tiles[i] = NULL; + } + + *numMessages = j + 1; + message->numTiles = 0; + + return messages; +} + +RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, int numRects, + BYTE* data, int width, int height, int scanline, int* numMessages, int maxDataSize) +{ + RFX_MESSAGE* message; + RFX_MESSAGE* messages; + + message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); + messages = rfx_split_message(context, message, numMessages, maxDataSize); + rfx_message_free(context, message); + + return messages; +} + static void rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message) { int i; From 08dce6e090fa8589e77029d0dd1fbd519e8f47da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 14 Aug 2013 20:35:00 -0400 Subject: [PATCH 20/25] libfreerdp-codec: add support for passing pointer to beginning of buffer for RemoteFX encoding --- libfreerdp/codec/rfx.c | 52 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index b43f7c7e6..5d6bbe7a1 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -546,7 +546,7 @@ static BOOL rfx_process_message_region(RFX_CONTEXT* context, RFX_MESSAGE* messag return FALSE; } - if (message->rects != NULL) + if (message->rects) message->rects = (RFX_RECT*) realloc(message->rects, message->numRects * sizeof(RFX_RECT)); else message->rects = (RFX_RECT*) malloc(message->numRects * sizeof(RFX_RECT)); @@ -1043,7 +1043,10 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, int yIdx; int numTilesX; int numTilesY; + UINT16 ax, ay; RFX_TILE* tile; + RFX_RECT* rect; + int BytesPerPixel; RFX_MESSAGE* message = NULL; PTP_WORK* work_objects = NULL; RFX_TILE_COMPOSE_WORK_PARAM* params = NULL; @@ -1068,6 +1071,9 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, context->quantIdxCr = 0; } + rect = (RFX_RECT*) &rects[0]; + BytesPerPixel = (context->bits_per_pixel / 8); + message->numQuant = context->numQuant; message->quantVals = context->quants; @@ -1078,7 +1084,8 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, message->tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE) * message->numTiles); ZeroMemory(message->tiles, sizeof(RFX_TILE) * message->numTiles); - DEBUG_RFX("width: %d height: %d scanline: %d", width, height, scanline); + DEBUG_RFX("x: %d y: %d width: %d height: %d scanline: %d BytesPerPixel: %d", + rect->x, rect->y, width, height, scanline, BytesPerPixel); if (context->priv->UseThreads) { @@ -1094,16 +1101,22 @@ RFX_MESSAGE* rfx_encode_message(RFX_CONTEXT* context, const RFX_RECT* rects, tile = message->tiles[i] = (RFX_TILE*) ObjectPool_Take(context->priv->TilePool); + tile->xIdx = xIdx; + tile->yIdx = yIdx; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; tile->scanline = scanline; - tile->data = data + yIdx * 64 * scanline + xIdx * 8 * context->bits_per_pixel; tile->width = (xIdx < numTilesX - 1) ? 64 : width - xIdx * 64; tile->height = (yIdx < numTilesY - 1) ? 64 : height - yIdx * 64; + ax = rect->x + tile->x; + ay = rect->y + tile->y; + tile->data = &data[(ay * scanline) + (ax * BytesPerPixel)]; + tile->quantIdxY = context->quantIdxY; tile->quantIdxCb = context->quantIdxCb; tile->quantIdxCr = context->quantIdxCr; - tile->xIdx = xIdx; - tile->yIdx = yIdx; + tile->YLen = 0; tile->CbLen = 0; tile->CrLen = 0; @@ -1182,6 +1195,7 @@ RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* messages[j].numRects = message->numRects; messages[j].rects = message->rects; messages[j].tiles = (RFX_TILE**) malloc(sizeof(RFX_TILE*) * message->numTiles); + messages[j].freeRects = FALSE; messages[j].freeArray = TRUE; } @@ -1191,8 +1205,17 @@ RFX_MESSAGE* rfx_split_message(RFX_CONTEXT* context, RFX_MESSAGE* message, int* } *numMessages = j + 1; + context->frameIdx += j; message->numTiles = 0; + for (i = 0; i < *numMessages; i++) + { + for (j = 0; j < messages[i].numTiles; j++) + { + + } + } + return messages; } @@ -1202,6 +1225,9 @@ RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, in RFX_MESSAGE* message; RFX_MESSAGE* messages; + printf("rfx_encode_messages: numRects: %d maxDataSize: %d x: %d y: %d w: %d/%d h: %d/%d\n", numRects, maxDataSize, + rects[0].x, rects[0].y, rects[0].width, width, rects[0].height, height); + message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); messages = rfx_split_message(context, message, numMessages, maxDataSize); rfx_message_free(context, message); @@ -1278,10 +1304,18 @@ void rfx_write_message_region(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* mes for (i = 0; i < message->numRects; i++) { - Stream_Write_UINT16(s, message->rects[i].x); - Stream_Write_UINT16(s, message->rects[i].y); - Stream_Write_UINT16(s, message->rects[i].width); - Stream_Write_UINT16(s, message->rects[i].height); + /* Clipping rectangles are relative to destLeft, destTop */ + +#if 1 + Stream_Write_UINT16(s, 0); /* x (2 bytes) */ + Stream_Write_UINT16(s, 0); /* y (2 bytes) */ +#else + Stream_Write_UINT16(s, message->rects[i].x); /* x (2 bytes) */ + Stream_Write_UINT16(s, message->rects[i].y); /* y (2 bytes) */ +#endif + + Stream_Write_UINT16(s, message->rects[i].width); /* width (2 bytes) */ + Stream_Write_UINT16(s, message->rects[i].height); /* height (2 bytes) */ } Stream_Write_UINT16(s, CBT_REGION); /* regionType (2 bytes) */ From e35dae462b6b71b841f858886298626d859caff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 14 Aug 2013 20:57:16 -0400 Subject: [PATCH 21/25] libfreerdp-codec: refactor NSCodec code --- libfreerdp/codec/nsc.c | 53 +++++++++++++++-------- libfreerdp/codec/nsc_encode.c | 80 ++++++++++++++++++++++------------- 2 files changed, 85 insertions(+), 48 deletions(-) diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index ba435a0c8..fe8ff32c9 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -79,7 +79,9 @@ static void nsc_decode(NSC_CONTEXT* context) coplane = context->priv->plane_buf[1] + y * context->width; /* Co */ cgplane = context->priv->plane_buf[2] + y * context->width; /* Cg */ } + aplane = context->priv->plane_buf[3] + y * context->width; /* A */ + for (x = 0; x < context->width; x++) { y_val = (INT16) *yplane; @@ -100,13 +102,14 @@ static void nsc_decode(NSC_CONTEXT* context) } } -static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz) +static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize) { UINT32 len; UINT32 left; BYTE value; - left = origsz; + left = originalSize; + while (left > 4) { value = *in++; @@ -119,6 +122,7 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz) else if (value == *in) { in++; + if (*in < 0xFF) { len = (UINT32) *in++; @@ -130,7 +134,8 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz) len = *((UINT32*) in); in += 4; } - memset(out, value, len); + + FillMemory(out, len, value); out += len; left -= len; } @@ -148,24 +153,24 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context) { UINT16 i; BYTE* rle; - UINT32 origsize; - UINT32 planesize; + UINT32 planeSize; + UINT32 originalSize; rle = context->nsc_stream.Planes; for (i = 0; i < 4; i++) { - origsize = context->OrgByteCount[i]; - planesize = context->nsc_stream.PlaneByteCount[i]; + originalSize = context->OrgByteCount[i]; + planeSize = context->nsc_stream.PlaneByteCount[i]; - if (planesize == 0) - memset(context->priv->plane_buf[i], 0xff, origsize); - else if (planesize < origsize) - nsc_rle_decode(rle, context->priv->plane_buf[i], origsize); + if (planeSize == 0) + FillMemory(context->priv->plane_buf[i], originalSize, 0xFF); + else if (planeSize < originalSize) + nsc_rle_decode(rle, context->priv->plane_buf[i], originalSize); else - memcpy(context->priv->plane_buf[i], rle, origsize); + CopyMemory(context->priv->plane_buf[i], rle, originalSize); - rle += planesize; + rle += planeSize; } } @@ -192,7 +197,8 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s) nsc_stream_initialize(context, s); length = context->width * context->height * 4; - if (context->bmpdata == NULL) + + if (!context->bmpdata) { context->bmpdata = malloc(length + 16); ZeroMemory(context->bmpdata, length + 16); @@ -206,12 +212,15 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s) tempWidth = ROUND_UP_TO(context->width, 8); tempHeight = ROUND_UP_TO(context->height, 2); + /* The maximum length a decoded plane can reach in all cases */ length = tempWidth * tempHeight; + if (length > context->priv->plane_buf_length) { for (i = 0; i < 4; i++) context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length); + context->priv->plane_buf_length = length; } @@ -250,6 +259,7 @@ void nsc_context_free(NSC_CONTEXT* context) context->priv->plane_buf[i] = NULL; } } + if (context->bmpdata) free(context->bmpdata); @@ -266,15 +276,17 @@ void nsc_context_free(NSC_CONTEXT* context) NSC_CONTEXT* nsc_context_new(void) { - NSC_CONTEXT* nsc_context; UINT8 i; + NSC_CONTEXT* nsc_context; nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT)); nsc_context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV)); - for (i=0; i < 5; ++i) + + for (i = 0; i < 5; ++i) { nsc_context->priv->plane_buf[i] = NULL; } + nsc_context->bmpdata = NULL; nsc_context->decode = nsc_decode; @@ -298,34 +310,39 @@ NSC_CONTEXT* nsc_context_new(void) void nsc_context_set_pixel_format(NSC_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format) { context->pixel_format = pixel_format; + switch (pixel_format) { case RDP_PIXEL_FORMAT_B8G8R8A8: case RDP_PIXEL_FORMAT_R8G8B8A8: context->bpp = 32; break; + case RDP_PIXEL_FORMAT_B8G8R8: case RDP_PIXEL_FORMAT_R8G8B8: context->bpp = 24; break; + case RDP_PIXEL_FORMAT_B5G6R5_LE: case RDP_PIXEL_FORMAT_R5G6B5_LE: context->bpp = 16; break; + case RDP_PIXEL_FORMAT_P4_PLANER: context->bpp = 4; break; + case RDP_PIXEL_FORMAT_P8: context->bpp = 8; break; + default: context->bpp = 0; break; } } -void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, - UINT16 width, UINT16 height, BYTE* data, UINT32 length) +void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, UINT16 width, UINT16 height, BYTE* data, UINT32 length) { wStream* s; diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index 143e44dc5..9c016814e 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -28,6 +28,8 @@ #include #endif +#include + #include #include "nsc_types.h" @@ -42,12 +44,15 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context) tempWidth = ROUND_UP_TO(context->width, 8); tempHeight = ROUND_UP_TO(context->height, 2); + /* The maximum length a decoded plane can reach in all cases */ length = tempWidth * tempHeight + 16; + if (length > context->priv->plane_buf_length) { for (i = 0; i < 5; i++) context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length); + context->priv->plane_buf_length = length; } @@ -101,6 +106,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r coplane = context->priv->plane_buf[1] + y * rw; cgplane = context->priv->plane_buf[2] + y * rw; aplane = context->priv->plane_buf[3] + y * context->width; + for (x = 0; x < context->width; x++) { switch (context->pixel_format) @@ -111,24 +117,28 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r r_val = *src++; a_val = *src++; break; + case RDP_PIXEL_FORMAT_R8G8B8A8: r_val = *src++; g_val = *src++; b_val = *src++; a_val = *src++; break; + case RDP_PIXEL_FORMAT_B8G8R8: b_val = *src++; g_val = *src++; r_val = *src++; a_val = 0xFF; break; + case RDP_PIXEL_FORMAT_R8G8B8: r_val = *src++; g_val = *src++; b_val = *src++; a_val = 0xFF; break; + case RDP_PIXEL_FORMAT_B5G6R5_LE: b_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); @@ -136,6 +146,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r a_val = 0xFF; src += 2; break; + case RDP_PIXEL_FORMAT_R5G6B5_LE: r_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); @@ -143,6 +154,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r a_val = 0xFF; src += 2; break; + case RDP_PIXEL_FORMAT_P4_PLANER: { int shift; @@ -162,6 +174,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r } a_val = 0xFF; break; + case RDP_PIXEL_FORMAT_P8: { int idx = (*src) * 3; @@ -173,16 +186,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r } a_val = 0xFF; break; + default: r_val = g_val = b_val = a_val = 0; break; } + *yplane++ = (BYTE) ((r_val >> 2) + (g_val >> 1) + (b_val >> 2)); + /* Perform color loss reduction here */ *coplane++ = (BYTE) ((r_val - b_val) >> ccl); *cgplane++ = (BYTE) ((-(r_val >> 1) + g_val - (b_val >> 1)) >> ccl); *aplane++ = a_val; } + if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 1) { *yplane = *(yplane - 1); @@ -190,11 +207,12 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r *cgplane = *(cgplane - 1); } } + if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1) { - memcpy(yplane + rw, yplane, rw); - memcpy(coplane + rw, coplane, rw); - memcpy(cgplane + rw, cgplane, rw); + CopyMemory(yplane + rw, yplane, rw); + CopyMemory(coplane + rw, coplane, rw); + CopyMemory(cgplane + rw, cgplane, rw); } } @@ -222,6 +240,7 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context) co_src1 = co_src0 + tempWidth; cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth; cg_src1 = cg_src0 + tempWidth; + for (x = 0; x < tempWidth >> 1; x++) { *co_dst++ = (BYTE) (((INT16) *co_src0 + (INT16) *(co_src0 + 1) + @@ -239,24 +258,25 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context) void nsc_encode(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride) { nsc_encode_argb_to_aycocg(context, bmpdata, rowstride); + if (context->nsc_stream.ChromaSubSamplingLevel > 0) { nsc_encode_subsampling(context); } } -static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz) +static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize) { UINT32 left; UINT32 runlength = 1; - UINT32 planesize = 0; + UINT32 planeSize = 0; - left = origsz; + left = originalSize; /** * We quit the loop if the running compressed size is larger than the original. * In such cases data will be sent uncompressed. */ - while (left > 4 && planesize < origsz - 4) + while (left > 4 && planeSize < originalSize - 4) { if (left > 5 && *in == *(in + 1)) { @@ -265,7 +285,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz) else if (runlength == 1) { *out++ = *in; - planesize++; + planeSize++; } else if (runlength < 256) { @@ -273,7 +293,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz) *out++ = *in; *out++ = runlength - 2; runlength = 1; - planesize += 3; + planeSize += 3; } else { @@ -285,52 +305,52 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz) *out++ = (runlength & 0x00FF0000) >> 16; *out++ = (runlength & 0xFF000000) >> 24; runlength = 1; - planesize += 7; + planeSize += 7; } in++; left--; } - if (planesize < origsz - 4) - { - memcpy(out, in, 4); - } - planesize += 4; - return planesize; + if (planeSize < originalSize - 4) + CopyMemory(out, in, 4); + + planeSize += 4; + + return planeSize; } static void nsc_rle_compress_data(NSC_CONTEXT* context) { UINT16 i; BYTE* rle; - UINT32 origsize; - UINT32 planesize; + UINT32 planeSize; + UINT32 originalSize; rle = context->nsc_stream.Planes; for (i = 0; i < 4; i++) { - origsize = context->OrgByteCount[i]; - if (origsize == 0) + originalSize = context->OrgByteCount[i]; + + if (originalSize == 0) { - planesize = 0; + planeSize = 0; } else { - planesize = nsc_rle_encode(context->priv->plane_buf[i], - context->priv->plane_buf[4], origsize); - if (planesize < origsize) - memcpy(context->priv->plane_buf[i], context->priv->plane_buf[4], planesize); + planeSize = nsc_rle_encode(context->priv->plane_buf[i], context->priv->plane_buf[4], originalSize); + + if (planeSize < originalSize) + CopyMemory(context->priv->plane_buf[i], context->priv->plane_buf[4], planeSize); else - planesize = origsize; + planeSize = originalSize; } - context->nsc_stream.PlaneByteCount[i] = planesize; + context->nsc_stream.PlaneByteCount[i] = planeSize; } } -void nsc_compose_message(NSC_CONTEXT* context, wStream* s, - BYTE* bmpdata, int width, int height, int rowstride) +void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int width, int height, int scanline) { int i; @@ -340,7 +360,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s, /* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */ PROFILER_ENTER(context->priv->prof_nsc_encode); - context->encode(context, bmpdata, rowstride); + context->encode(context, bmpdata, scanline); PROFILER_EXIT(context->priv->prof_nsc_encode); /* RLE encode */ From 1e5118116dae5a08f61e9f13eb2dff6d90e2326c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 14 Aug 2013 23:16:13 -0400 Subject: [PATCH 22/25] libfreerdp-codec: start implementing split NSCodec encoder --- client/Windows/wf_gdi.c | 2 +- client/X11/xf_gdi.c | 2 +- include/freerdp/codec/nsc.h | 21 ++++- libfreerdp/codec/nsc.c | 127 ++++++++++++++-------------- libfreerdp/codec/nsc_encode.c | 151 +++++++++++++++++++++++++++++----- libfreerdp/codec/nsc_sse2.c | 59 ++++++++----- libfreerdp/codec/nsc_types.h | 9 +- libfreerdp/gdi/gdi.c | 2 +- libfreerdp/gdi/graphics.c | 2 +- 9 files changed, 263 insertions(+), 112 deletions(-) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index a11c5b107..15e9b4363 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -618,7 +618,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->bmpdata, &bitmap_info, DIB_RGB_COLORS); + nsc_context->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); } diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index e24bdac84..158c61778 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -988,7 +988,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(nsc_context->bmpdata, xfc->bmp_codec_nsc, + freerdp_image_flip(nsc_context->BitmapData, xfc->bmp_codec_nsc, surface_bits_command->width, surface_bits_command->height, 32); image = XCreateImage(xfc->display, xfc->visual, 24, ZPixmap, 0, diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h index 16fc580f1..78952d442 100644 --- a/include/freerdp/codec/nsc.h +++ b/include/freerdp/codec/nsc.h @@ -42,9 +42,24 @@ struct _NSC_STREAM }; typedef struct _NSC_STREAM NSC_STREAM; +struct _NSC_MESSAGE +{ + int x; + int y; + UINT32 width; + UINT32 height; + BYTE* data; + int scanline; + UINT32 MaxPlaneSize; + UINT32 OrgByteCount[4]; + BYTE* PlaneBuffers[4]; +}; +typedef struct _NSC_MESSAGE NSC_MESSAGE; + typedef struct _NSC_CONTEXT_PRIV NSC_CONTEXT_PRIV; typedef struct _NSC_CONTEXT NSC_CONTEXT; + struct _NSC_CONTEXT { UINT32 OrgByteCount[4]; /* original byte length of luma, chroma orange, chroma green, alpha variable in order */ @@ -52,15 +67,15 @@ struct _NSC_CONTEXT UINT16 bpp; UINT16 width; UINT16 height; - BYTE* bmpdata; /* final argb values in little endian order */ - UINT32 bmpdata_length; /* the maximum length of the buffer that bmpdata points to */ + BYTE* BitmapData; /* final argb values in little endian order */ + UINT32 BitmapDataLength; /* the maximum length of the buffer that bmpdata points to */ RDP_PIXEL_FORMAT pixel_format; /* color palette allocated by the application */ const BYTE* palette; void (*decode)(NSC_CONTEXT* context); - void (*encode)(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride); + void (*encode)(NSC_CONTEXT* context, BYTE* BitmapData, int rowstride); NSC_CONTEXT_PRIV* priv; }; diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index fe8ff32c9..b869b028f 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -61,7 +61,7 @@ static void nsc_decode(NSC_CONTEXT* context) INT16 b_val; BYTE* bmpdata; - bmpdata = context->bmpdata; + bmpdata = context->BitmapData; rw = ROUND_UP_TO(context->width, 8); shift = context->nsc_stream.ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */ @@ -69,18 +69,18 @@ static void nsc_decode(NSC_CONTEXT* context) { if (context->nsc_stream.ChromaSubSamplingLevel > 0) { - yplane = context->priv->plane_buf[0] + y * rw; /* Y */ - coplane = context->priv->plane_buf[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */ - cgplane = context->priv->plane_buf[2] + (y >> 1) * (rw >> 1); /* Cg, supersampled */ + yplane = context->priv->PlaneBuffers[0] + y * rw; /* Y */ + coplane = context->priv->PlaneBuffers[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */ + cgplane = context->priv->PlaneBuffers[2] + (y >> 1) * (rw >> 1); /* Cg, supersampled */ } else { - yplane = context->priv->plane_buf[0] + y * context->width; /* Y */ - coplane = context->priv->plane_buf[1] + y * context->width; /* Co */ - cgplane = context->priv->plane_buf[2] + y * context->width; /* Cg */ + yplane = context->priv->PlaneBuffers[0] + y * context->width; /* Y */ + coplane = context->priv->PlaneBuffers[1] + y * context->width; /* Co */ + cgplane = context->priv->PlaneBuffers[2] + y * context->width; /* Cg */ } - aplane = context->priv->plane_buf[3] + y * context->width; /* A */ + aplane = context->priv->PlaneBuffers[3] + y * context->width; /* A */ for (x = 0; x < context->width; x++) { @@ -164,11 +164,11 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context) planeSize = context->nsc_stream.PlaneByteCount[i]; if (planeSize == 0) - FillMemory(context->priv->plane_buf[i], originalSize, 0xFF); + FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF); else if (planeSize < originalSize) - nsc_rle_decode(rle, context->priv->plane_buf[i], originalSize); + nsc_rle_decode(rle, context->priv->PlaneBuffers[i], originalSize); else - CopyMemory(context->priv->plane_buf[i], rle, originalSize); + CopyMemory(context->priv->PlaneBuffers[i], rle, originalSize); rle += planeSize; } @@ -198,16 +198,16 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s) nsc_stream_initialize(context, s); length = context->width * context->height * 4; - if (!context->bmpdata) + if (!context->BitmapData) { - context->bmpdata = malloc(length + 16); - ZeroMemory(context->bmpdata, length + 16); - context->bmpdata_length = length; + context->BitmapData = malloc(length + 16); + ZeroMemory(context->BitmapData, length + 16); + context->BitmapDataLength = length; } - else if (length > context->bmpdata_length) + else if (length > context->BitmapDataLength) { - context->bmpdata = realloc(context->bmpdata, length + 16); - context->bmpdata_length = length; + context->BitmapData = realloc(context->BitmapData, length + 16); + context->BitmapDataLength = length; } tempWidth = ROUND_UP_TO(context->width, 8); @@ -216,16 +216,18 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s) /* The maximum length a decoded plane can reach in all cases */ length = tempWidth * tempHeight; - if (length > context->priv->plane_buf_length) + if (length > context->priv->PlaneBuffersLength) { for (i = 0; i < 4; i++) - context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length); + context->priv->PlaneBuffers[i] = (BYTE*) realloc(context->priv->PlaneBuffers[i], length); - context->priv->plane_buf_length = length; + context->priv->PlaneBuffersLength = length; } for (i = 0; i < 4; i++) - context->OrgByteCount[i]=context->width * context->height; + { + context->OrgByteCount[i] = context->width * context->height; + } if (context->nsc_stream.ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */ { @@ -247,21 +249,58 @@ static void nsc_profiler_print(NSC_CONTEXT* context) PROFILER_PRINT_FOOTER; } +NSC_CONTEXT* nsc_context_new(void) +{ + UINT8 i; + NSC_CONTEXT* context; + + context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT)); + context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV)); + + for (i = 0; i < 5; ++i) + { + context->priv->PlaneBuffers[i] = NULL; + } + + context->BitmapData = NULL; + + context->decode = nsc_decode; + context->encode = nsc_encode; + + context->priv->PlanePool = BufferPool_New(TRUE, 0, 16); + + PROFILER_CREATE(context->priv->prof_nsc_rle_decompress_data, "nsc_rle_decompress_data"); + PROFILER_CREATE(context->priv->prof_nsc_decode, "nsc_decode"); + PROFILER_CREATE(context->priv->prof_nsc_rle_compress_data, "nsc_rle_compress_data"); + PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode"); + + /* Default encoding parameters */ + context->nsc_stream.ColorLossLevel = 3; + context->nsc_stream.ChromaSubSamplingLevel = 1; + + /* init optimized methods */ + NSC_INIT_SIMD(context); + + return context; +} + void nsc_context_free(NSC_CONTEXT* context) { int i; for (i = 0; i < 4; i++) { - if (context->priv->plane_buf[i]) + if (context->priv->PlaneBuffers[i]) { - free(context->priv->plane_buf[i]); - context->priv->plane_buf[i] = NULL; + free(context->priv->PlaneBuffers[i]); + context->priv->PlaneBuffers[i] = NULL; } } - if (context->bmpdata) - free(context->bmpdata); + if (context->BitmapData) + free(context->BitmapData); + + BufferPool_Free(context->priv->PlanePool); nsc_profiler_print(context); PROFILER_FREE(context->priv->prof_nsc_rle_decompress_data); @@ -271,40 +310,6 @@ void nsc_context_free(NSC_CONTEXT* context) free(context->priv); free(context); - context = NULL; -} - -NSC_CONTEXT* nsc_context_new(void) -{ - UINT8 i; - NSC_CONTEXT* nsc_context; - - nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT)); - nsc_context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV)); - - for (i = 0; i < 5; ++i) - { - nsc_context->priv->plane_buf[i] = NULL; - } - - nsc_context->bmpdata = NULL; - - nsc_context->decode = nsc_decode; - nsc_context->encode = nsc_encode; - - PROFILER_CREATE(nsc_context->priv->prof_nsc_rle_decompress_data, "nsc_rle_decompress_data"); - PROFILER_CREATE(nsc_context->priv->prof_nsc_decode, "nsc_decode"); - PROFILER_CREATE(nsc_context->priv->prof_nsc_rle_compress_data, "nsc_rle_compress_data"); - PROFILER_CREATE(nsc_context->priv->prof_nsc_encode, "nsc_encode"); - - /* Default encoding parameters */ - nsc_context->nsc_stream.ColorLossLevel = 3; - nsc_context->nsc_stream.ChromaSubSamplingLevel = 1; - - /* init optimized methods */ - NSC_INIT_SIMD(nsc_context); - - return nsc_context; } void nsc_context_set_pixel_format(NSC_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format) diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index 9c016814e..f49566417 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -48,12 +48,12 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context) /* The maximum length a decoded plane can reach in all cases */ length = tempWidth * tempHeight + 16; - if (length > context->priv->plane_buf_length) + if (length > context->priv->PlaneBuffersLength) { for (i = 0; i < 5; i++) - context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length); + context->priv->PlaneBuffers[i] = (BYTE*) realloc(context->priv->PlaneBuffers[i], length); - context->priv->plane_buf_length = length; + context->priv->PlaneBuffersLength = length; } if (context->nsc_stream.ChromaSubSamplingLevel > 0) @@ -94,18 +94,18 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r tempHeight = ROUND_UP_TO(context->height, 2); rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width); ccl = context->nsc_stream.ColorLossLevel; - yplane = context->priv->plane_buf[0]; - coplane = context->priv->plane_buf[1]; - cgplane = context->priv->plane_buf[2]; - aplane = context->priv->plane_buf[3]; + yplane = context->priv->PlaneBuffers[0]; + coplane = context->priv->PlaneBuffers[1]; + cgplane = context->priv->PlaneBuffers[2]; + aplane = context->priv->PlaneBuffers[3]; for (y = 0; y < context->height; y++) { src = bmpdata + (context->height - 1 - y) * rowstride; - yplane = context->priv->plane_buf[0] + y * rw; - coplane = context->priv->plane_buf[1] + y * rw; - cgplane = context->priv->plane_buf[2] + y * rw; - aplane = context->priv->plane_buf[3] + y * context->width; + yplane = context->priv->PlaneBuffers[0] + y * rw; + coplane = context->priv->PlaneBuffers[1] + y * rw; + cgplane = context->priv->PlaneBuffers[2] + y * rw; + aplane = context->priv->PlaneBuffers[3] + y * context->width; for (x = 0; x < context->width; x++) { @@ -234,11 +234,11 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context) for (y = 0; y < tempHeight >> 1; y++) { - co_dst = context->priv->plane_buf[1] + y * (tempWidth >> 1); - cg_dst = context->priv->plane_buf[2] + y * (tempWidth >> 1); - co_src0 = (INT8*) context->priv->plane_buf[1] + (y << 1) * tempWidth; + co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1); + cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1); + co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth; co_src1 = co_src0 + tempWidth; - cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth; + cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth; cg_src1 = cg_src0 + tempWidth; for (x = 0; x < tempWidth >> 1; x++) @@ -338,10 +338,10 @@ static void nsc_rle_compress_data(NSC_CONTEXT* context) } else { - planeSize = nsc_rle_encode(context->priv->plane_buf[i], context->priv->plane_buf[4], originalSize); + planeSize = nsc_rle_encode(context->priv->PlaneBuffers[i], context->priv->PlaneBuffers[4], originalSize); if (planeSize < originalSize) - CopyMemory(context->priv->plane_buf[i], context->priv->plane_buf[4], planeSize); + CopyMemory(context->priv->PlaneBuffers[i], context->priv->PlaneBuffers[4], planeSize); else planeSize = originalSize; } @@ -350,7 +350,118 @@ static void nsc_rle_compress_data(NSC_CONTEXT* context) } } -void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int width, int height, int scanline) +UINT32 nsc_compute_byte_count(NSC_CONTEXT* context, UINT32* ByteCount, UINT32 width, UINT32 height) +{ + UINT32 tempWidth; + UINT32 tempHeight; + UINT32 maxPlaneSize; + + tempWidth = ROUND_UP_TO(width, 8); + tempHeight = ROUND_UP_TO(height, 2); + + maxPlaneSize = tempWidth * tempHeight + 16; + + if (context->nsc_stream.ChromaSubSamplingLevel > 0) + { + ByteCount[0] = tempWidth * height; + ByteCount[1] = tempWidth * tempHeight / 4; + ByteCount[2] = tempWidth * tempHeight / 4; + ByteCount[3] = width * height; + } + else + { + ByteCount[0] = width * height; + ByteCount[1] = width * height; + ByteCount[2] = width * height; + ByteCount[3] = width * height; + } + + return maxPlaneSize; +} + +NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y, + int width, int height, int scanline, int* numMessages, int maxDataSize) +{ + int step; + int i, j; + UINT32 ByteCount[4]; + UINT32 MaxPlaneSize; + UINT32 MaxMessageSize; + NSC_MESSAGE* messages; + + MaxPlaneSize = nsc_compute_byte_count(context, (UINT32*) ByteCount, width, height); + MaxMessageSize = MaxPlaneSize + 20; + + maxDataSize -= 1024; /* reserve enough space for headers */ + + if (MaxMessageSize > maxDataSize) + *numMessages = MaxMessageSize / maxDataSize; + + if (*numMessages < 1) + *numMessages = 1; + + messages = (NSC_MESSAGE*) malloc(sizeof(NSC_MESSAGE) * (*numMessages)); + ZeroMemory(messages, sizeof(sizeof(NSC_MESSAGE) * (*numMessages))); + + if (width > height) + { + /** + * Horizontal Split + */ + + step = height / *numMessages; + step += (step % 4); + + for (i = 0; i < *numMessages; i++) + { + messages[i].x = x; + messages[i].width = width; + messages[i].data = data; + messages[i].scanline = scanline; + + messages[i].y = y + (i * step); + messages[i].height = height - (i * step); + + messages[i].MaxPlaneSize = nsc_compute_byte_count(context, + (UINT32*) messages[i].OrgByteCount, messages[i].width, messages[i].height); + } + } + else + { + /** + * Vertical Split + */ + + step = width / *numMessages; + step += (step % 4); + + for (i = 0; i < *numMessages; i++) + { + messages[i].y = y; + messages[i].height = height; + messages[i].data = data; + messages[i].scanline = scanline; + + messages[i].x = x + (i * step); + messages[i].width = width - (i * step); + + messages[i].MaxPlaneSize = nsc_compute_byte_count(context, + (UINT32*) messages[i].OrgByteCount, messages[i].width, messages[i].height); + } + } + + for (i = 0; i < *numMessages; i++) + { + for (j = 0; j < 4; j++) + { + messages[i].PlaneBuffers[j] = NULL; + } + } + + return messages; +} + +void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width, int height, int scanline) { int i; @@ -360,7 +471,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int wi /* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */ PROFILER_ENTER(context->priv->prof_nsc_encode); - context->encode(context, bmpdata, scanline); + context->encode(context, data, scanline); PROFILER_EXIT(context->priv->prof_nsc_encode); /* RLE encode */ @@ -383,7 +494,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int wi if (context->nsc_stream.PlaneByteCount[i] > 0) { Stream_EnsureRemainingCapacity(s, (int) context->nsc_stream.PlaneByteCount[i]); - Stream_Write(s, context->priv->plane_buf[i], context->nsc_stream.PlaneByteCount[i]); + Stream_Write(s, context->priv->PlaneBuffers[i], context->nsc_stream.PlaneByteCount[i]); } } } diff --git a/libfreerdp/codec/nsc_sse2.c b/libfreerdp/codec/nsc_sse2.c index f1a033fc4..f4f1eb1bf 100644 --- a/libfreerdp/codec/nsc_sse2.c +++ b/libfreerdp/codec/nsc_sse2.c @@ -28,10 +28,12 @@ #include #include +#include + #include "nsc_types.h" #include "nsc_sse2.h" -static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride) +static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int scanline) { UINT16 x; UINT16 y; @@ -56,18 +58,19 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, tempHeight = ROUND_UP_TO(context->height, 2); rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width); ccl = context->nsc_stream.ColorLossLevel; - yplane = context->priv->plane_buf[0]; - coplane = context->priv->plane_buf[1]; - cgplane = context->priv->plane_buf[2]; - aplane = context->priv->plane_buf[3]; + yplane = context->priv->PlaneBuffers[0]; + coplane = context->priv->PlaneBuffers[1]; + cgplane = context->priv->PlaneBuffers[2]; + aplane = context->priv->PlaneBuffers[3]; for (y = 0; y < context->height; y++) { - src = bmpdata + (context->height - 1 - y) * rowstride; - yplane = context->priv->plane_buf[0] + y * rw; - coplane = context->priv->plane_buf[1] + y * rw; - cgplane = context->priv->plane_buf[2] + y * rw; - aplane = context->priv->plane_buf[3] + y * context->width; + src = data + (context->height - 1 - y) * scanline; + yplane = context->priv->PlaneBuffers[0] + y * rw; + coplane = context->priv->PlaneBuffers[1] + y * rw; + cgplane = context->priv->PlaneBuffers[2] + y * rw; + aplane = context->priv->PlaneBuffers[3] + y * context->width; + for (x = 0; x < context->width; x += 8) { switch (context->pixel_format) @@ -79,6 +82,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19), *(src + 15), *(src + 11), *(src + 7), *(src + 3)); src += 32; break; + case RDP_PIXEL_FORMAT_R8G8B8A8: r_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16), *(src + 12), *(src + 8), *(src + 4), *src); g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17), *(src + 13), *(src + 9), *(src + 5), *(src + 1)); @@ -86,6 +90,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19), *(src + 15), *(src + 11), *(src + 7), *(src + 3)); src += 32; break; + case RDP_PIXEL_FORMAT_B8G8R8: b_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12), *(src + 9), *(src + 6), *(src + 3), *src); g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13), *(src + 10), *(src + 7), *(src + 4), *(src + 1)); @@ -93,6 +98,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, a_val = _mm_set1_epi16(0xFF); src += 24; break; + case RDP_PIXEL_FORMAT_R8G8B8: r_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12), *(src + 9), *(src + 6), *(src + 3), *src); g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13), *(src + 10), *(src + 7), *(src + 4), *(src + 1)); @@ -100,6 +106,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, a_val = _mm_set1_epi16(0xFF); src += 24; break; + case RDP_PIXEL_FORMAT_B5G6R5_LE: b_val = _mm_set_epi16( (((*(src + 15)) & 0xF8) | ((*(src + 15)) >> 5)), @@ -131,6 +138,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, a_val = _mm_set1_epi16(0xFF); src += 16; break; + case RDP_PIXEL_FORMAT_R5G6B5_LE: r_val = _mm_set_epi16( (((*(src + 15)) & 0xF8) | ((*(src + 15)) >> 5)), @@ -162,6 +170,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, a_val = _mm_set1_epi16(0xFF); src += 16; break; + case RDP_PIXEL_FORMAT_P4_PLANER: { int shift; @@ -206,6 +215,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, } a_val = _mm_set1_epi16(0xFF); break; + case RDP_PIXEL_FORMAT_P8: { r_val = _mm_set_epi16( @@ -239,6 +249,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, } a_val = _mm_set1_epi16(0xFF); break; + default: r_val = g_val = b_val = a_val = _mm_set1_epi16(0); break; @@ -266,18 +277,20 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* bmpdata, cgplane += 8; aplane += 8; } + if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (context->width % 2) == 1) { - context->priv->plane_buf[0][y * rw + context->width] = context->priv->plane_buf[0][y * rw + context->width - 1]; - context->priv->plane_buf[1][y * rw + context->width] = context->priv->plane_buf[1][y * rw + context->width - 1]; - context->priv->plane_buf[2][y * rw + context->width] = context->priv->plane_buf[2][y * rw + context->width - 1]; + context->priv->PlaneBuffers[0][y * rw + context->width] = context->priv->PlaneBuffers[0][y * rw + context->width - 1]; + context->priv->PlaneBuffers[1][y * rw + context->width] = context->priv->PlaneBuffers[1][y * rw + context->width - 1]; + context->priv->PlaneBuffers[2][y * rw + context->width] = context->priv->PlaneBuffers[2][y * rw + context->width - 1]; } } + if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1) { - memcpy(yplane + rw, yplane, rw); - memcpy(coplane + rw, coplane, rw); - memcpy(cgplane + rw, cgplane, rw); + CopyMemory(yplane + rw, yplane, rw); + CopyMemory(coplane + rw, coplane, rw); + CopyMemory(cgplane + rw, cgplane, rw); } } @@ -302,12 +315,13 @@ static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context) for (y = 0; y < tempHeight >> 1; y++) { - co_dst = context->priv->plane_buf[1] + y * (tempWidth >> 1); - cg_dst = context->priv->plane_buf[2] + y * (tempWidth >> 1); - co_src0 = (INT8*) context->priv->plane_buf[1] + (y << 1) * tempWidth; + co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1); + cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1); + co_src0 = (INT8*) context->priv->PlaneBuffers[1] + (y << 1) * tempWidth; co_src1 = co_src0 + tempWidth; - cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth; + cg_src0 = (INT8*) context->priv->PlaneBuffers[2] + (y << 1) * tempWidth; cg_src1 = cg_src0 + tempWidth; + for (x = 0; x < tempWidth >> 1; x += 8) { t = _mm_loadu_si128((__m128i*) co_src0); @@ -333,9 +347,10 @@ static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context) } } -static void nsc_encode_sse2(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride) +static void nsc_encode_sse2(NSC_CONTEXT* context, BYTE* data, int scanline) { - nsc_encode_argb_to_aycocg_sse2(context, bmpdata, rowstride); + nsc_encode_argb_to_aycocg_sse2(context, data, scanline); + if (context->nsc_stream.ChromaSubSamplingLevel > 0) { nsc_encode_subsampling_sse2(context); diff --git a/libfreerdp/codec/nsc_types.h b/libfreerdp/codec/nsc_types.h index 060b89daa..0964167a2 100644 --- a/libfreerdp/codec/nsc_types.h +++ b/libfreerdp/codec/nsc_types.h @@ -25,6 +25,9 @@ #include "config.h" #endif +#include +#include + #include #include @@ -33,8 +36,10 @@ struct _NSC_CONTEXT_PRIV { - BYTE* plane_buf[5]; /* Decompressed Plane Buffers in the respective order */ - UINT32 plane_buf_length; /* Lengths of each plane buffer */ + wBufferPool* PlanePool; + + BYTE* PlaneBuffers[5]; /* Decompressed Plane Buffers in the respective order */ + UINT32 PlaneBuffersLength; /* Lengths of each plane buffer */ /* profilers */ PROFILER_DEFINE(prof_nsc_rle_decompress_data); diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index d6e271dc5..95443ab57 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -828,7 +828,7 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp; gdi->image->bitmap->bytesPerPixel = gdi->image->bitmap->bitsPerPixel / 8; gdi->image->bitmap->data = (BYTE*) realloc(gdi->image->bitmap->data, gdi->image->bitmap->width * gdi->image->bitmap->height * 4); - freerdp_image_flip(nsc_context->bmpdata, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, 32); + freerdp_image_flip(nsc_context->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); } else if (surface_bits_command->codecID == RDP_CODEC_ID_NONE) diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index 3bd5f2801..2be36a50a 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -119,7 +119,7 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, 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)->bmpdata, bitmap->data, width, height, bpp); + freerdp_image_flip(((NSC_CONTEXT*)gdi->nsc_context)->BitmapData, bitmap->data, width, height, bpp); break; case RDP_CODEC_ID_REMOTEFX: gdi = context->gdi; From c149ede6f2f7d1871e2245deb8df83a786568675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 15 Aug 2013 00:01:42 -0400 Subject: [PATCH 23/25] libwinpr-utils: add support for variable size buffer pool --- winpr/include/winpr/collections.h | 25 +- winpr/libwinpr/utils/collections/BufferPool.c | 224 +++++++++++++++--- winpr/libwinpr/utils/test/CMakeLists.txt | 1 + winpr/libwinpr/utils/test/TestBufferPool.c | 78 ++++++ 4 files changed, 294 insertions(+), 34 deletions(-) create mode 100644 winpr/libwinpr/utils/test/TestBufferPool.c diff --git a/winpr/include/winpr/collections.h b/winpr/include/winpr/collections.h index 8901fe7b6..2730ffeca 100644 --- a/winpr/include/winpr/collections.h +++ b/winpr/include/winpr/collections.h @@ -312,18 +312,33 @@ WINPR_API void CountdownEvent_Free(wCountdownEvent* countdown); /* BufferPool */ -struct _wBufferPool +struct _wBufferPoolItem { int size; - int capacity; - void** array; - CRITICAL_SECTION lock; - int fixedSize; + void* buffer; +}; +typedef struct _wBufferPoolItem wBufferPoolItem; + +struct _wBufferPool +{ + int defaultSize; DWORD alignment; BOOL synchronized; + CRITICAL_SECTION lock; + + int aSize; + int aCapacity; + wBufferPoolItem* aArray; + + int uSize; + int uCapacity; + wBufferPoolItem* uArray; }; typedef struct _wBufferPool wBufferPool; +WINPR_API int BufferPool_GetPoolSize(wBufferPool* pool); +WINPR_API int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer); + WINPR_API void* BufferPool_Take(wBufferPool* pool, int bufferSize); WINPR_API void BufferPool_Return(wBufferPool* pool, void* buffer); WINPR_API void BufferPool_Clear(wBufferPool* pool); diff --git a/winpr/libwinpr/utils/collections/BufferPool.c b/winpr/libwinpr/utils/collections/BufferPool.c index b4f22b712..0c075d90f 100644 --- a/winpr/libwinpr/utils/collections/BufferPool.c +++ b/winpr/libwinpr/utils/collections/BufferPool.c @@ -34,35 +34,167 @@ * Methods */ +void BufferPool_ShiftAvailable(wBufferPool* pool, int index, int count) +{ + if (count > 0) + { + if (pool->aSize + count > pool->aCapacity) + { + pool->aCapacity *= 2; + pool->aArray = (wBufferPoolItem*) realloc(pool->aArray, sizeof(wBufferPoolItem) * pool->aCapacity); + } + + MoveMemory(&pool->aArray[index + count], &pool->aArray[index], (pool->aSize - index) * sizeof(wBufferPoolItem)); + pool->aSize += count; + } + else if (count < 0) + { + MoveMemory(&pool->aArray[index], &pool->aArray[index - count], (pool->aSize - index) * sizeof(wBufferPoolItem)); + pool->aSize += count; + } +} + +void BufferPool_ShiftUsed(wBufferPool* pool, int index, int count) +{ + if (count > 0) + { + if (pool->uSize + count > pool->uCapacity) + { + pool->uCapacity *= 2; + pool->uArray = (wBufferPoolItem*) realloc(pool->uArray, sizeof(wBufferPoolItem) * pool->uCapacity); + } + + MoveMemory(&pool->uArray[index + count], &pool->uArray[index], (pool->uSize - index) * sizeof(wBufferPoolItem)); + pool->uSize += count; + } + else if (count < 0) + { + MoveMemory(&pool->uArray[index], &pool->uArray[index - count], (pool->uSize - index) * sizeof(wBufferPoolItem)); + pool->uSize += count; + } +} + +/** + * Get the buffer pool size + */ + +int BufferPool_GetPoolSize(wBufferPool* pool) +{ + int size; + + if (pool->synchronized) + EnterCriticalSection(&pool->lock); + + size = pool->uSize; + + if (pool->synchronized) + LeaveCriticalSection(&pool->lock); + + return size; +} + +/** + * Get the size of a pooled buffer + */ + +int BufferPool_GetBufferSize(wBufferPool* pool, void* buffer) +{ + int size = 0; + int index = 0; + BOOL found = FALSE; + + if (pool->synchronized) + EnterCriticalSection(&pool->lock); + + for (index = 0; index < pool->uSize; index++) + { + if (pool->uArray[index].buffer == buffer) + { + size = pool->uArray[index].size; + found = TRUE; + break; + } + } + + if (pool->synchronized) + LeaveCriticalSection(&pool->lock); + + return (found) ? size : -1; +} + /** * Gets a buffer of at least the specified size from the pool. */ -void* BufferPool_Take(wBufferPool* pool, int bufferSize) +void* BufferPool_Take(wBufferPool* pool, int size) { + int index; + int maxSize; + int maxIndex; + int foundIndex; + BOOL found = FALSE; void* buffer = NULL; if (pool->synchronized) EnterCriticalSection(&pool->lock); - if (pool->fixedSize) - { - if (pool->size > 0) - buffer = pool->array[--(pool->size)]; + maxSize = 0; + maxIndex = 0; - if (!buffer) + if (size < 1) + size = pool->defaultSize; + + for (index = 0; index < pool->aSize; index++) + { + if (pool->aArray[index].size > maxSize) + { + maxSize = pool->aArray[index].size; + maxIndex = index; + } + + if (pool->aArray[index].size >= size) + { + foundIndex = index; + found = TRUE; + break; + } + } + + if (!found) + { + if (!maxSize) { if (pool->alignment) - buffer = _aligned_malloc(pool->fixedSize, pool->alignment); + buffer = _aligned_malloc(size, pool->alignment); else - buffer = malloc(pool->fixedSize); + buffer = malloc(size); + } + else + { + buffer = pool->aArray[maxIndex].buffer; + + if (pool->alignment) + buffer = _aligned_realloc(buffer, size, pool->alignment); + else + buffer = realloc(buffer, size); } } else { - fprintf(stderr, "Variable-size BufferPool not yet implemented\n"); + buffer = pool->aArray[index].buffer; + BufferPool_ShiftAvailable(pool, foundIndex, -1); } + if (pool->uSize + 1 > pool->uCapacity) + { + pool->uCapacity *= 2; + pool->uArray = (wBufferPoolItem*) realloc(pool->uArray, sizeof(wBufferPoolItem) * pool->uCapacity); + } + + pool->uArray[pool->uSize].buffer = buffer; + pool->uArray[pool->uSize].size = size; + (pool->uSize)++; + if (pool->synchronized) LeaveCriticalSection(&pool->lock); @@ -75,16 +207,40 @@ void* BufferPool_Take(wBufferPool* pool, int bufferSize) void BufferPool_Return(wBufferPool* pool, void* buffer) { + int size = 0; + int index = 0; + BOOL found = FALSE; + if (pool->synchronized) EnterCriticalSection(&pool->lock); - if ((pool->size + 1) >= pool->capacity) + for (index = 0; index < pool->uSize; index++) { - pool->capacity *= 2; - pool->array = (void**) realloc(pool->array, sizeof(void*) * pool->capacity); + if (pool->uArray[index].buffer == buffer) + { + found = TRUE; + break; + } } - pool->array[(pool->size)++] = buffer; + if (found) + { + size = pool->uArray[index].size; + BufferPool_ShiftUsed(pool, index, -1); + } + + if (size) + { + if ((pool->aSize + 1) >= pool->aCapacity) + { + pool->aCapacity *= 2; + pool->aArray = (wBufferPoolItem*) realloc(pool->aArray, sizeof(wBufferPoolItem) * pool->aCapacity); + } + + pool->aArray[pool->aSize].buffer = buffer; + pool->aArray[pool->aSize].size = size; + (pool->aSize)++; + } if (pool->synchronized) LeaveCriticalSection(&pool->lock); @@ -99,14 +255,24 @@ void BufferPool_Clear(wBufferPool* pool) if (pool->synchronized) EnterCriticalSection(&pool->lock); - while (pool->size > 0) + while (pool->aSize > 0) { - (pool->size)--; + (pool->aSize)--; if (pool->alignment) - _aligned_free(pool->array[pool->size]); + _aligned_free(pool->aArray[pool->aSize].buffer); else - free(pool->array[pool->size]); + free(pool->aArray[pool->aSize].buffer); + } + + while (pool->uSize > 0) + { + (pool->uSize)--; + + if (pool->alignment) + _aligned_free(pool->uArray[pool->uSize].buffer); + else + free(pool->uArray[pool->uSize].buffer); } if (pool->synchronized) @@ -117,7 +283,7 @@ void BufferPool_Clear(wBufferPool* pool) * Construction, Destruction */ -wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment) +wBufferPool* BufferPool_New(BOOL synchronized, int defaultSize, DWORD alignment) { wBufferPool* pool = NULL; @@ -125,10 +291,10 @@ wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment) if (pool) { - pool->fixedSize = fixedSize; + pool->defaultSize = defaultSize; - if (pool->fixedSize < 0) - pool->fixedSize = 0; + if (pool->defaultSize < 0) + pool->defaultSize = 0; pool->alignment = alignment; pool->synchronized = synchronized; @@ -136,14 +302,13 @@ wBufferPool* BufferPool_New(BOOL synchronized, int fixedSize, DWORD alignment) if (pool->synchronized) InitializeCriticalSectionAndSpinCount(&pool->lock, 4000); - if (!pool->fixedSize) - { - fprintf(stderr, "Variable-size BufferPool not yet implemented\n"); - } + pool->aSize = 0; + pool->aCapacity = 32; + pool->aArray = (wBufferPoolItem*) malloc(sizeof(wBufferPoolItem) * pool->aCapacity); - pool->size = 0; - pool->capacity = 32; - pool->array = (void**) malloc(sizeof(void*) * pool->capacity); + pool->uSize = 0; + pool->uCapacity = 32; + pool->uArray = (wBufferPoolItem*) malloc(sizeof(wBufferPoolItem) * pool->uCapacity); } return pool; @@ -158,7 +323,8 @@ void BufferPool_Free(wBufferPool* pool) if (pool->synchronized) DeleteCriticalSection(&pool->lock); - free(pool->array); + free(pool->aArray); + free(pool->uArray); free(pool); } diff --git a/winpr/libwinpr/utils/test/CMakeLists.txt b/winpr/libwinpr/utils/test/CMakeLists.txt index 46af971bf..31d1de762 100644 --- a/winpr/libwinpr/utils/test/CMakeLists.txt +++ b/winpr/libwinpr/utils/test/CMakeLists.txt @@ -12,6 +12,7 @@ set(${MODULE_PREFIX}_TESTS TestLinkedList.c TestListDictionary.c TestCmdLine.c + TestBufferPool.c TestStreamPool.c TestMessageQueue.c TestMessagePipe.c) diff --git a/winpr/libwinpr/utils/test/TestBufferPool.c b/winpr/libwinpr/utils/test/TestBufferPool.c new file mode 100644 index 000000000..710bc61dd --- /dev/null +++ b/winpr/libwinpr/utils/test/TestBufferPool.c @@ -0,0 +1,78 @@ + +#include +#include +#include + +int TestBufferPool(int argc, char* argv[]) +{ + int PoolSize; + int BufferSize; + int DefaultSize; + wBufferPool* pool; + BYTE* Buffers[10]; + + DefaultSize = 1234; + + pool = BufferPool_New(TRUE, DefaultSize, 16); + + Buffers[0] = BufferPool_Take(pool, -1); + Buffers[1] = BufferPool_Take(pool, 0); + Buffers[2] = BufferPool_Take(pool, 2048); + + PoolSize = BufferPool_GetPoolSize(pool); + + if (PoolSize != 3) + { + printf("BufferPool_GetPoolSize failure: Actual: %d Expected: %d\n", PoolSize, 3); + return -1; + } + + BufferSize = BufferPool_GetBufferSize(pool, Buffers[0]); + + if (BufferSize != DefaultSize) + { + printf("BufferPool_GetBufferSize failure: Actual: %d Expected: %d\n", BufferSize, DefaultSize); + return -1; + } + + BufferSize = BufferPool_GetBufferSize(pool, Buffers[1]); + + if (BufferSize != DefaultSize) + { + printf("BufferPool_GetBufferSize failure: Actual: %d Expected: %d\n", BufferSize, DefaultSize); + return -1; + } + + BufferSize = BufferPool_GetBufferSize(pool, Buffers[2]); + + if (BufferSize != 2048) + { + printf("BufferPool_GetBufferSize failure: Actual: %d Expected: %d\n", BufferSize, 2048); + return -1; + } + + BufferPool_Return(pool, Buffers[1]); + + PoolSize = BufferPool_GetPoolSize(pool); + + if (PoolSize != 2) + { + printf("BufferPool_GetPoolSize failure: Actual: %d Expected: %d\n", PoolSize, 2); + return -1; + } + + BufferPool_Clear(pool); + + PoolSize = BufferPool_GetPoolSize(pool); + + if (PoolSize != 0) + { + printf("BufferPool_GetPoolSize failure: Actual: %d Expected: %d\n", PoolSize, 0); + return -1; + } + + BufferPool_Free(pool); + + return 0; +} + From 9f25c4fc2549c04e8e5d382469abbc1a5eeecfc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 15 Aug 2013 13:13:02 -0400 Subject: [PATCH 24/25] libfreerdp-codec: initial working fragmented NSCodec encoder --- include/freerdp/codec/nsc.h | 8 +- libfreerdp/codec/nsc_encode.c | 161 ++++++++++++------ winpr/libwinpr/crt/alignment.c | 25 +-- winpr/libwinpr/utils/collections/BufferPool.c | 31 ++-- 4 files changed, 144 insertions(+), 81 deletions(-) diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h index 78952d442..9601fb8c2 100644 --- a/include/freerdp/codec/nsc.h +++ b/include/freerdp/codec/nsc.h @@ -51,8 +51,9 @@ struct _NSC_MESSAGE BYTE* data; int scanline; UINT32 MaxPlaneSize; + BYTE* PlaneBuffers[5]; UINT32 OrgByteCount[4]; - BYTE* PlaneBuffers[4]; + UINT32 PlaneByteCount[4]; }; typedef struct _NSC_MESSAGE NSC_MESSAGE; @@ -88,6 +89,11 @@ FREERDP_API void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int width, int height, int rowstride); FREERDP_API void nsc_context_free(NSC_CONTEXT* context); +FREERDP_API NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y, + int width, int height, int scanline, int* numMessages, int maxDataSize); +FREERDP_API int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message); +FREERDP_API int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message); + #ifdef __cplusplus } #endif diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index f49566417..627d032f4 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -24,6 +24,7 @@ #include #include #include + #ifdef HAVE_STDINT_H #include #endif @@ -72,7 +73,7 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context) } } -static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride) +static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scanline) { UINT16 x; UINT16 y; @@ -101,7 +102,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r for (y = 0; y < context->height; y++) { - src = bmpdata + (context->height - 1 - y) * rowstride; + src = data + (context->height - 1 - y) * scanline; yplane = context->priv->PlaneBuffers[0] + y * rw; coplane = context->priv->PlaneBuffers[1] + y * rw; cgplane = context->priv->PlaneBuffers[2] + y * rw; @@ -322,12 +323,9 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize) static void nsc_rle_compress_data(NSC_CONTEXT* context) { UINT16 i; - BYTE* rle; UINT32 planeSize; UINT32 originalSize; - rle = context->nsc_stream.Planes; - for (i = 0; i < 4; i++) { originalSize = context->OrgByteCount[i]; @@ -382,83 +380,136 @@ UINT32 nsc_compute_byte_count(NSC_CONTEXT* context, UINT32* ByteCount, UINT32 wi NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y, int width, int height, int scanline, int* numMessages, int maxDataSize) { - int step; - int i, j; + int i, j, k; + int dataOffset; + int rows, cols; + int BytesPerPixel; + int MaxRegionWidth; + int MaxRegionHeight; UINT32 ByteCount[4]; UINT32 MaxPlaneSize; UINT32 MaxMessageSize; NSC_MESSAGE* messages; + k = 0; + MaxRegionWidth = 64 * 4; + MaxRegionHeight = 64 * 2; + BytesPerPixel = (context->bpp / 8); + + rows = (width + (MaxRegionWidth - (width % MaxRegionWidth))) / MaxRegionWidth; + cols = (height + (MaxRegionHeight - (height % MaxRegionHeight))) / MaxRegionHeight; + *numMessages = rows * cols; + MaxPlaneSize = nsc_compute_byte_count(context, (UINT32*) ByteCount, width, height); - MaxMessageSize = MaxPlaneSize + 20; + MaxMessageSize = ByteCount[0] + ByteCount[1] + ByteCount[2] + ByteCount[3] + 20; maxDataSize -= 1024; /* reserve enough space for headers */ - if (MaxMessageSize > maxDataSize) - *numMessages = MaxMessageSize / maxDataSize; - - if (*numMessages < 1) - *numMessages = 1; - messages = (NSC_MESSAGE*) malloc(sizeof(NSC_MESSAGE) * (*numMessages)); ZeroMemory(messages, sizeof(sizeof(NSC_MESSAGE) * (*numMessages))); - if (width > height) + for (i = 0; i < rows; i++) { - /** - * Horizontal Split - */ - - step = height / *numMessages; - step += (step % 4); - - for (i = 0; i < *numMessages; i++) + for (j = 0; j < cols; j++) { - messages[i].x = x; - messages[i].width = width; - messages[i].data = data; - messages[i].scanline = scanline; + messages[k].x = x + (i * MaxRegionWidth); + messages[k].y = y + (j * MaxRegionHeight); + messages[k].width = (i < (rows - 1)) ? MaxRegionWidth : width - (i * MaxRegionWidth); + messages[k].height = (j < (cols - 1)) ? MaxRegionHeight : height - (j * MaxRegionHeight); + messages[k].data = data; + messages[k].scanline = scanline; - messages[i].y = y + (i * step); - messages[i].height = height - (i * step); + messages[k].MaxPlaneSize = nsc_compute_byte_count(context, + (UINT32*) messages[k].OrgByteCount, messages[k].width, messages[k].height); - messages[i].MaxPlaneSize = nsc_compute_byte_count(context, - (UINT32*) messages[i].OrgByteCount, messages[i].width, messages[i].height); + k++; } } - else + + *numMessages = k; + + for (i = 0; i < *numMessages; i++) { - /** - * Vertical Split - */ - - step = width / *numMessages; - step += (step % 4); - - for (i = 0; i < *numMessages; i++) - { - messages[i].y = y; - messages[i].height = height; - messages[i].data = data; - messages[i].scanline = scanline; - - messages[i].x = x + (i * step); - messages[i].width = width - (i * step); - - messages[i].MaxPlaneSize = nsc_compute_byte_count(context, - (UINT32*) messages[i].OrgByteCount, messages[i].width, messages[i].height); - } + messages[i].PlaneBuffers[0] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); + messages[i].PlaneBuffers[1] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); + messages[i].PlaneBuffers[2] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); + messages[i].PlaneBuffers[3] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); + messages[i].PlaneBuffers[4] = (BYTE*) BufferPool_Take(context->priv->PlanePool, messages[i].MaxPlaneSize); } for (i = 0; i < *numMessages; i++) { - for (j = 0; j < 4; j++) + context->width = messages[i].width; + context->height = messages[i].height; + context->OrgByteCount[0] = messages[i].OrgByteCount[0]; + context->OrgByteCount[1] = messages[i].OrgByteCount[1]; + context->OrgByteCount[2] = messages[i].OrgByteCount[2]; + context->OrgByteCount[3] = messages[i].OrgByteCount[3]; + context->priv->PlaneBuffersLength = messages[i].MaxPlaneSize; + context->priv->PlaneBuffers[0] = messages[i].PlaneBuffers[0]; + context->priv->PlaneBuffers[1] = messages[i].PlaneBuffers[1]; + context->priv->PlaneBuffers[2] = messages[i].PlaneBuffers[2]; + context->priv->PlaneBuffers[3] = messages[i].PlaneBuffers[3]; + context->priv->PlaneBuffers[4] = messages[i].PlaneBuffers[4]; + + dataOffset = (messages[i].y * messages[i].scanline) + (messages[i].x * BytesPerPixel); + + PROFILER_ENTER(context->priv->prof_nsc_encode); + context->encode(context, &data[dataOffset], scanline); + PROFILER_EXIT(context->priv->prof_nsc_encode); + + PROFILER_ENTER(context->priv->prof_nsc_rle_compress_data); + nsc_rle_compress_data(context); + PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data); + + messages[i].PlaneByteCount[0] = context->nsc_stream.PlaneByteCount[0]; + messages[i].PlaneByteCount[1] = context->nsc_stream.PlaneByteCount[1]; + messages[i].PlaneByteCount[2] = context->nsc_stream.PlaneByteCount[2]; + messages[i].PlaneByteCount[3] = context->nsc_stream.PlaneByteCount[3]; + } + + context->priv->PlaneBuffers[0] = NULL; + context->priv->PlaneBuffers[1] = NULL; + context->priv->PlaneBuffers[2] = NULL; + context->priv->PlaneBuffers[3] = NULL; + context->priv->PlaneBuffers[4] = NULL; + + return messages; +} + +int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message) +{ + int i; + + Stream_EnsureRemainingCapacity(s, 20); + Stream_Write_UINT32(s, message->PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */ + Stream_Write_UINT32(s, message->PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */ + Stream_Write_UINT32(s, message->PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */ + Stream_Write_UINT32(s, message->PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */ + Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */ + Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */ + Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */ + + for (i = 0; i < 4; i++) + { + if (message->PlaneByteCount[i] > 0) { - messages[i].PlaneBuffers[j] = NULL; + Stream_EnsureRemainingCapacity(s, (int) message->PlaneByteCount[i]); + Stream_Write(s, message->PlaneBuffers[i], message->PlaneByteCount[i]); } } - return messages; + return 0; +} + +int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message) +{ + BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[0]); + BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[1]); + BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[2]); + BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[3]); + BufferPool_Return(context->priv->PlanePool, message->PlaneBuffers[4]); + return 0; } void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width, int height, int scanline) diff --git a/winpr/libwinpr/crt/alignment.c b/winpr/libwinpr/crt/alignment.c index 1ee3d3850..bf01e6ba6 100644 --- a/winpr/libwinpr/crt/alignment.c +++ b/winpr/libwinpr/crt/alignment.c @@ -35,12 +35,12 @@ #include #endif -struct _aligned_meminfo { +struct _aligned_meminfo +{ size_t size; - void *base_addr; + void* base_addr; }; - void* _aligned_malloc(size_t size, size_t alignment) { return _aligned_offset_malloc(size, alignment, 0); @@ -75,13 +75,13 @@ void* _aligned_offset_malloc(size_t size, size_t alignment, size_t offset) /* malloc size + alignment to make sure we can align afterwards */ tmpptr = malloc(size + alignment + sizeof(struct _aligned_meminfo)); + if (!tmpptr) return NULL; - memptr = (void *)((((size_t)((PBYTE)tmpptr + alignment + offset + sizeof(struct _aligned_meminfo)) & ~(alignment - 1)) - offset)); - ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memptr - sizeof(struct _aligned_meminfo)))); + ameminfo = (struct _aligned_meminfo*) (((size_t)((PBYTE)memptr - sizeof(struct _aligned_meminfo)))); ameminfo->base_addr = tmpptr; ameminfo->size = size; @@ -90,8 +90,8 @@ void* _aligned_offset_malloc(size_t size, size_t alignment, size_t offset) void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, size_t offset) { - struct _aligned_meminfo *ameminfo; - void *newmem; + void* newmem; + struct _aligned_meminfo* ameminfo; if (!memblock) return _aligned_offset_malloc(size, alignment, offset); @@ -101,15 +101,17 @@ void* _aligned_offset_realloc(void* memblock, size_t size, size_t alignment, siz _aligned_free(memblock); return NULL; } + /* The following is not very performant but a simple and working solution */ newmem = _aligned_offset_malloc(size, alignment, offset); if (!newmem) return NULL; - ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo)))); - memcpy(newmem, memblock, ameminfo->size); + ameminfo = (struct _aligned_meminfo*) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo)))); + CopyMemory(newmem, memblock, ameminfo->size); _aligned_free(memblock); + return newmem; } @@ -125,11 +127,12 @@ size_t _aligned_msize(void* memblock, size_t alignment, size_t offset) void _aligned_free(void* memblock) { - struct _aligned_meminfo *ameminfo; + struct _aligned_meminfo* ameminfo; + if (!memblock) return; - ameminfo = (struct _aligned_meminfo *) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo)))); + ameminfo = (struct _aligned_meminfo*) (((size_t)((PBYTE)memblock - sizeof(struct _aligned_meminfo)))); free(ameminfo->base_addr); } diff --git a/winpr/libwinpr/utils/collections/BufferPool.c b/winpr/libwinpr/utils/collections/BufferPool.c index 0c075d90f..e5b39114f 100644 --- a/winpr/libwinpr/utils/collections/BufferPool.c +++ b/winpr/libwinpr/utils/collections/BufferPool.c @@ -148,8 +148,8 @@ void* BufferPool_Take(wBufferPool* pool, int size) { if (pool->aArray[index].size > maxSize) { - maxSize = pool->aArray[index].size; maxIndex = index; + maxSize = pool->aArray[index].size; } if (pool->aArray[index].size >= size) @@ -160,28 +160,31 @@ void* BufferPool_Take(wBufferPool* pool, int size) } } + if (!found && maxSize) + { + foundIndex = maxIndex; + found = TRUE; + } + if (!found) { - if (!maxSize) - { - if (pool->alignment) - buffer = _aligned_malloc(size, pool->alignment); - else - buffer = malloc(size); - } + if (pool->alignment) + buffer = _aligned_malloc(size, pool->alignment); else - { - buffer = pool->aArray[maxIndex].buffer; + buffer = malloc(size); + } + else + { + buffer = pool->aArray[index].buffer; + if (maxSize < size) + { if (pool->alignment) buffer = _aligned_realloc(buffer, size, pool->alignment); else buffer = realloc(buffer, size); } - } - else - { - buffer = pool->aArray[index].buffer; + BufferPool_ShiftAvailable(pool, foundIndex, -1); } From 319496795722b9af7ef82aadd274d9c3ebc3f4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 15 Aug 2013 13:25:29 -0400 Subject: [PATCH 25/25] xfreerdp: fix monolithic build --- client/X11/.gitignore | 2 ++ client/X11/CMakeLists.txt | 46 ++++++++++++++++++++++++--------------- 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 client/X11/.gitignore diff --git a/client/X11/.gitignore b/client/X11/.gitignore new file mode 100644 index 000000000..de7ef2209 --- /dev/null +++ b/client/X11/.gitignore @@ -0,0 +1,2 @@ +*.xml +generate_argument_docbook diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 1ccfaea17..907200733 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -80,31 +80,43 @@ if(WITH_MANPAGES) configure_file(xfreerdp.1.xml.in xfreerdp.1.xml @ONLY IMMEDIATE) - add_executable(generate_argument_docbook - generate_argument_docbook.c) - target_link_libraries(generate_argument_docbook winpr-utils freerdp-core freerdp-utils freerdp-client) + add_executable(generate_argument_docbook generate_argument_docbook.c) + + set(GAD_LIBS freerdp-client) + + set_complex_link_libraries(VARIABLE GAD_LIBS MONOLITHIC ${MONOLITHIC_BUILD} + MODULE winpr + MODULES winpr-utils) + + set_complex_link_libraries(VARIABLE GAD_LIBS MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-core freerdp-utils) + + message(WARNING "GAD_LIBS: ${GAD_LIBS}") + + target_link_libraries(generate_argument_docbook ${GAD_LIBS}) add_custom_command(OUTPUT xfreerdp.1 - COMMAND generate_argument_docbook - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml ${CMAKE_CURRENT_BINARY_DIR} - COMMAND ${XSLTPROC_EXECUTABLE} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl xfreerdp.1.xml - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS - ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml - ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml - generate_argument_docbook) + COMMAND generate_argument_docbook + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml ${CMAKE_CURRENT_BINARY_DIR} + COMMAND ${XSLTPROC_EXECUTABLE} ${DOCBOOKXSL_DIR}/manpages/docbook.xsl xfreerdp.1.xml + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-examples.1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/xfreerdp-channels.1.xml + generate_argument_docbook) add_custom_target(xfreerdp.manpage ALL DEPENDS xfreerdp.1) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/xfreerdp.1 DESTINATION share/man/man1) - else(DOCBOOKXSL_FOUND AND XSLTPROC_EXECUTABLE) + else() message(WARNING "WITH_MANPAGES was set, but xsltproc was not found. man-pages will not be installed") - endif(DOCBOOKXSL_FOUND AND XSLTPROC_EXECUTABLE) + endif() endif(WITH_MANPAGES) set(XSHM_FEATURE_TYPE "REQUIRED")