From d85a2bf3e6b2e55cb982b937f0c5ca5258a4e7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 25 Oct 2014 15:36:36 -0400 Subject: [PATCH 01/17] shadow: fix bitmap update fragmentation --- server/shadow/shadow_client.c | 46 ++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 2c7d35272..a5eb61970 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -162,6 +162,9 @@ BOOL shadow_client_post_connect(freerdp_peer* peer) if (settings->ColorDepth == 24) settings->ColorDepth = 16; /* disable 24bpp */ + if (settings->MultifragMaxRequestSize < 0x3F0000) + settings->NSCodec = FALSE; /* NSCodec compressor does not support fragmentation yet */ + WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)", peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth); @@ -595,10 +598,47 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface* if (updateSizeEstimate > maxUpdateSize) { - fprintf(stderr, "update size estimate larger than maximum update size\n"); - } + UINT32 i, j; + UINT32 updateSize; + UINT32 newUpdateSize; + BITMAP_DATA* fragBitmapData; - IFCALL(update->BitmapUpdate, context, &bitmapUpdate); + fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k); + bitmapUpdate.rectangles = fragBitmapData; + + i = j = 0; + updateSize = 1024; + + while (i < k) + { + newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16); + + if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k)) + { + CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA)); + updateSize = newUpdateSize; + } + else + { + if ((i + 1) >= k) + { + CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA)); + updateSize = newUpdateSize; + } + + bitmapUpdate.count = bitmapUpdate.number = j; + IFCALL(update->BitmapUpdate, context, &bitmapUpdate); + updateSize = 1024; + j = 0; + } + } + + free(fragBitmapData); + } + else + { + IFCALL(update->BitmapUpdate, context, &bitmapUpdate); + } free(bitmapData); From eea475b436ea44f8fc45cf9b42c41de55bdeeec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 29 Oct 2014 16:11:22 -0700 Subject: [PATCH 02/17] shadow: fix null ClientDir --- server/shadow/shadow_capture.c | 2 +- server/shadow/shadow_client.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/shadow/shadow_capture.c b/server/shadow/shadow_capture.c index 6b1ffeb76..7aa321e67 100644 --- a/server/shadow/shadow_capture.c +++ b/server/shadow/shadow_capture.c @@ -94,10 +94,10 @@ int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BY BOOL grid[1024][1024]; allEqual = TRUE; + ZeroMemory(rect, sizeof(RECTANGLE_16)); FillMemory(rows, sizeof(rows), 0xFF); FillMemory(cols, sizeof(cols), 0xFF); FillMemory(grid, sizeof(grid), 0xFF); - ZeroMemory(rect, sizeof(RECTANGLE_16)); nrow = (nHeight + 15) / 16; ncol = (nWidth + 15) / 16; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index a5eb61970..d3b8b1ebe 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -269,7 +269,7 @@ BOOL shadow_client_activate(freerdp_peer* peer) rdpSettings* settings = peer->settings; rdpShadowClient* client = (rdpShadowClient*) peer->context; - if (strcmp(settings->ClientDir, "librdp") == 0) + if (settings->ClientDir && (strcmp(settings->ClientDir, "librdp") == 0)) { /* Hack for Mac/iOS/Android Microsoft RDP clients */ From c5c9423ccf5d70d5237d2303c78fed3383eaa900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 4 Nov 2014 10:44:55 -0500 Subject: [PATCH 03/17] winpr: fix Win32 build warnings --- libfreerdp/core/listener.c | 2 +- winpr/libwinpr/environment/environment.c | 8 +++++--- winpr/libwinpr/wtsapi/wtsapi_win32.c | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c index 5920a9bbf..9f2a7e5e1 100644 --- a/libfreerdp/core/listener.c +++ b/libfreerdp/core/listener.c @@ -105,7 +105,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a if (status != 0) { #ifdef _WIN32 - WLog_ERR(_T("getaddrinfo error: %s"), gai_strerror(status)); + WLog_ERR("getaddrinfo error: %s", gai_strerrorA(status)); #else WLog_ERR(TAG, "getaddrinfo"); #endif diff --git a/winpr/libwinpr/environment/environment.c b/winpr/libwinpr/environment/environment.c index f473bcd96..70768be25 100644 --- a/winpr/libwinpr/environment/environment.c +++ b/winpr/libwinpr/environment/environment.c @@ -23,9 +23,11 @@ #include "config.h" #endif -#include +#include #include +#include + #ifndef _WIN32 #define stricmp strcasecmp @@ -326,7 +328,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge) if (mergeStringLength == mergeArraySize) { mergeArraySize += 128; - mergeStrings = (LPCSTR*) realloc(mergeStrings, mergeArraySize * sizeof(char*)); + mergeStrings = (const char**) realloc((void*) mergeStrings, mergeArraySize * sizeof(char*)); if (!mergeStrings) return NULL; @@ -441,7 +443,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge) lpszEnvironmentBlock[offset] = '\0'; - free(mergeStrings); + free((void*) mergeStrings); return lpszEnvironmentBlock; } diff --git a/winpr/libwinpr/wtsapi/wtsapi_win32.c b/winpr/libwinpr/wtsapi/wtsapi_win32.c index 252c3e26e..9a0adc697 100644 --- a/winpr/libwinpr/wtsapi/wtsapi_win32.c +++ b/winpr/libwinpr/wtsapi/wtsapi_win32.c @@ -689,7 +689,6 @@ BOOL WINAPI Win32_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLAS VOID WINAPI Win32_WTSFreeMemory(PVOID pMemory) { LocalFree(pMemory); - return TRUE; } BOOL WINAPI Win32_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries) From 92d08cf58ffe99a35bf47c094d0313689ea23919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andre=CC=81=20Moreau?= Date: Wed, 5 Nov 2014 17:14:32 -0500 Subject: [PATCH 04/17] mfreerdp: rewrite and update clipboard code --- client/Mac/CMakeLists.txt | 2 + client/Mac/Clipboard.h | 29 +++ client/Mac/Clipboard.m | 328 +++++++++++++++++++++++++++++++ client/Mac/MRDPView.h | 6 +- client/Mac/MRDPView.m | 402 +++++++++----------------------------- client/Mac/mf_client.m | 2 - client/Mac/mfreerdp.h | 11 ++ 7 files changed, 469 insertions(+), 311 deletions(-) create mode 100644 client/Mac/Clipboard.h create mode 100644 client/Mac/Clipboard.m diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 863ec827a..8f0aca4dc 100644 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -32,6 +32,7 @@ set(${MODULE_PREFIX}_OBJECTIVE_SOURCES MRDPCursor.m MRDPView.m Keyboard.m + Clipboard.m PasswordDialog.m) list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES}) @@ -42,6 +43,7 @@ set(${MODULE_PREFIX}_HEADERS MRDPCursor.h MRDPView.h Keyboard.h + Clipboard.h PasswordDialog.h) set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings") diff --git a/client/Mac/Clipboard.h b/client/Mac/Clipboard.h new file mode 100644 index 000000000..2445ab8e9 --- /dev/null +++ b/client/Mac/Clipboard.h @@ -0,0 +1,29 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "mfreerdp.h" +#import "mf_client.h" + +#import "freerdp/freerdp.h" +#import "freerdp/channels/channels.h" +#import "freerdp/client/cliprdr.h" + +int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr); + +void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr); +void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr); diff --git a/client/Mac/Clipboard.m b/client/Mac/Clipboard.m new file mode 100644 index 000000000..d0e9575b0 --- /dev/null +++ b/client/Mac/Clipboard.m @@ -0,0 +1,328 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Clipboard.h" + +int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr) +{ + UINT32 index; + UINT32 formatId; + UINT32 numFormats; + UINT32* pFormatIds; + const char* formatName; + CLIPRDR_FORMAT* formats; + CLIPRDR_FORMAT_LIST formatList; + mfContext* mfc = (mfContext*) cliprdr->custom; + + ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST)); + + pFormatIds = NULL; + numFormats = ClipboardGetFormatIds(mfc->clipboard, &pFormatIds); + + formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT)); + + if (!formats) + return -1; + + for (index = 0; index < numFormats; index++) + { + formatId = pFormatIds[index]; + formatName = ClipboardGetFormatName(mfc->clipboard, formatId); + + formats[index].formatId = formatId; + formats[index].formatName = NULL; + + if ((formatId > CF_MAX) && formatName) + formats[index].formatName = _strdup(formatName); + } + + formatList.msgFlags = CB_RESPONSE_OK; + formatList.numFormats = numFormats; + formatList.formats = formats; + + mfc->cliprdr->ClientFormatList(mfc->cliprdr, &formatList); + + free(pFormatIds); + free(formats); + + return 1; +} + +int mac_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId) +{ + CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; + mfContext* mfc = (mfContext*) cliprdr->custom; + + ZeroMemory(&formatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST)); + + formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; + formatDataRequest.msgFlags = 0; + + formatDataRequest.requestedFormatId = formatId; + mfc->requestedFormatId = formatId; + ResetEvent(mfc->clipboardRequestEvent); + + cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest); + + return 1; +} + +int mac_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr) +{ + CLIPRDR_CAPABILITIES capabilities; + CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; + + capabilities.cCapabilitiesSets = 1; + capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet); + + generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; + generalCapabilitySet.capabilitySetLength = 12; + + generalCapabilitySet.version = CB_CAPS_VERSION_2; + generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES; + + cliprdr->ClientCapabilities(cliprdr, &capabilities); + + return 1; +} + +int mac_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_READY* monitorReady) +{ + mfContext* mfc = (mfContext*) cliprdr->custom; + + mfc->clipboardSync = TRUE; + mac_cliprdr_send_client_capabilities(cliprdr); + mac_cliprdr_send_client_format_list(cliprdr); + + return 1; +} + +int mac_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPABILITIES* capabilities) +{ + UINT32 index; + CLIPRDR_CAPABILITY_SET* capabilitySet; + mfContext* mfc = (mfContext*) cliprdr->custom; + + for (index = 0; index < capabilities->cCapabilitiesSets; index++) + { + capabilitySet = &(capabilities->capabilitySets[index]); + + if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) && + (capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN)) + { + CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet + = (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet; + + mfc->clipboardCapabilities = generalCapabilitySet->generalFlags; + break; + } + } + + return 1; +} + +int mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST* formatList) +{ + UINT32 index; + CLIPRDR_FORMAT* format; + mfContext* mfc = (mfContext*) cliprdr->custom; + + if (mfc->serverFormats) + { + for (index = 0; index < mfc->numServerFormats; index++) + { + free(mfc->serverFormats[index].formatName); + } + + free(mfc->serverFormats); + mfc->serverFormats = NULL; + mfc->numServerFormats = 0; + } + + if (formatList->numFormats < 1) + return 1; + + mfc->numServerFormats = formatList->numFormats; + mfc->serverFormats = (CLIPRDR_FORMAT*) calloc(mfc->numServerFormats, sizeof(CLIPRDR_FORMAT)); + + if (!mfc->serverFormats) + return -1; + + for (index = 0; index < mfc->numServerFormats; index++) + { + mfc->serverFormats[index].formatId = formatList->formats[index].formatId; + mfc->serverFormats[index].formatName = NULL; + + if (formatList->formats[index].formatName) + mfc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName); + } + + for (index = 0; index < mfc->numServerFormats; index++) + { + format = &(mfc->serverFormats[index]); + + if (format->formatId == CF_UNICODETEXT) + { + mac_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT); + break; + } + else if (format->formatId == CF_TEXT) + { + mac_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT); + break; + } + } + + return 1; +} + +int mac_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) +{ + return 1; +} + +int mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) +{ + return 1; +} + +int mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +{ + return 1; +} + +int mac_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) +{ + BYTE* data; + UINT32 size; + UINT32 formatId; + CLIPRDR_FORMAT_DATA_RESPONSE response; + mfContext* mfc = (mfContext*) cliprdr->custom; + + ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE)); + + formatId = formatDataRequest->requestedFormatId; + data = (BYTE*) ClipboardGetData(mfc->clipboard, formatId, &size); + + response.msgFlags = CB_RESPONSE_OK; + response.dataLen = size; + response.requestedFormatData = data; + + if (!data) + { + response.msgFlags = CB_RESPONSE_FAIL; + response.dataLen = 0; + response.requestedFormatData = NULL; + } + + cliprdr->ClientFormatDataResponse(cliprdr, &response); + + free(data); + + return 1; +} + +int mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) +{ + BYTE* data; + UINT32 size; + UINT32 index; + UINT32 formatId; + CLIPRDR_FORMAT* format = NULL; + mfContext* mfc = (mfContext*) cliprdr->custom; + MRDPView* view = (MRDPView*) mfc->view; + + for (index = 0; index < mfc->numServerFormats; index++) + { + if (mfc->requestedFormatId == mfc->serverFormats[index].formatId) + format = &(mfc->serverFormats[index]); + } + + if (!format) + { + SetEvent(mfc->clipboardRequestEvent); + return -1; + } + + if (format->formatName) + formatId = ClipboardRegisterFormat(mfc->clipboard, format->formatName); + else + formatId = format->formatId; + + size = formatDataResponse->dataLen; + data = (BYTE*) malloc(size); + CopyMemory(data, formatDataResponse->requestedFormatData, size); + + ClipboardSetData(mfc->clipboard, formatId, data, size); + + SetEvent(mfc->clipboardRequestEvent); + + if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT)) + { + formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING"); + + data = (void*) ClipboardGetData(mfc->clipboard, formatId, &size); + NSString* str = [[NSString alloc] initWithBytes: (void*) data length:size encoding:NSUTF8StringEncoding]; + free(data); + + NSArray* types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil]; + [view->pasteboard_wr declareTypes:types owner:view]; + [view->pasteboard_wr setString:str forType:NSStringPboardType]; + } + + return 1; +} + +int mac_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) +{ + return 1; +} + +int mac_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) +{ + return 1; +} + +void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr) +{ + cliprdr->custom = (void*) mfc; + mfc->cliprdr = cliprdr; + + mfc->clipboard = ClipboardCreate(); + mfc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + cliprdr->MonitorReady = mac_cliprdr_monitor_ready; + cliprdr->ServerCapabilities = mac_cliprdr_server_capabilities; + cliprdr->ServerFormatList = mac_cliprdr_server_format_list; + cliprdr->ServerFormatListResponse = mac_cliprdr_server_format_list_response; + cliprdr->ServerLockClipboardData = mac_cliprdr_server_lock_clipboard_data; + cliprdr->ServerUnlockClipboardData = mac_cliprdr_server_unlock_clipboard_data; + cliprdr->ServerFormatDataRequest = mac_cliprdr_server_format_data_request; + cliprdr->ServerFormatDataResponse = mac_cliprdr_server_format_data_response; + cliprdr->ServerFileContentsRequest = mac_cliprdr_server_file_contents_request; + cliprdr->ServerFileContentsResponse = mac_cliprdr_server_file_contents_response; +} + +void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr) +{ + cliprdr->custom = NULL; + mfc->cliprdr = NULL; + + ClipboardDestroy(mfc->clipboard); + CloseHandle(mfc->clipboardRequestEvent); +} diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index 70ef3130d..7231d0657 100644 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -51,8 +51,8 @@ BOOL skipMoveWindowOnce; @public - NSPasteboard* pasteboard_rd; /* for reading from clipboard */ - NSPasteboard* pasteboard_wr; /* for writing to clipboard */ + NSPasteboard* pasteboard_rd; + NSPasteboard* pasteboard_wr; int pasteboard_changecount; int pasteboard_format; int is_connected; @@ -63,6 +63,8 @@ - (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height; - (void) onPasteboardTimerFired :(NSTimer *) timer; +- (void) pause; +- (void) resume; - (void) releaseResources; @property (assign) int is_connected; diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index ded7f9b9a..4d963253b 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -23,6 +23,7 @@ #import "mfreerdp.h" #import "MRDPView.h" #import "MRDPCursor.h" +#import "Clipboard.h" #import "PasswordDialog.h" #include @@ -39,8 +40,6 @@ #import "freerdp/gdi/dc.h" #import "freerdp/gdi/region.h" #import "freerdp/graphics.h" -#import "freerdp/utils/event.h" -#import "freerdp/client/cliprdr.h" #import "freerdp/client/file.h" #import "freerdp/client/cmdline.h" #import "freerdp/log.h" @@ -59,39 +58,9 @@ void mac_desktop_resize(rdpContext* context); static void update_activity_cb(freerdp* instance); static void input_activity_cb(freerdp* instance); -static void channel_activity_cb(freerdp* instance); - -int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data); -int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size); - -void process_cliprdr_event(freerdp* instance, wMessage* event); -void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event); -void cliprdr_send_data_request(freerdp* instance, UINT32 format); -void cliprdr_process_cb_monitor_ready_event(freerdp* inst); -void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event); -void cliprdr_process_text(freerdp* instance, BYTE* data, int len); -void cliprdr_send_supported_format_list(freerdp* instance); -int register_channel_fds(int* fds, int count, freerdp* instance); DWORD mac_client_thread(void* param); -struct cursor -{ - rdpPointer* pointer; - BYTE* cursor_data; - void* bmiRep; /* NSBitmapImageRep */ - void* nsCursor; /* NSCursor */ - void* nsImage; /* NSImage */ -}; - -struct rgba_data -{ - char red; - char green; - char blue; - char alpha; -}; - @implementation MRDPView @synthesize is_connected; @@ -183,43 +152,6 @@ DWORD mac_client_input_thread(void* param) return 0; } -DWORD mac_client_channels_thread(void* param) -{ - int status; - wMessage* event; - HANDLE channelsEvent; - rdpChannels* channels; - rdpContext* context = (rdpContext*) param; - - channels = context->channels; - channelsEvent = freerdp_channels_get_event_handle(context->instance); - - while (WaitForSingleObject(channelsEvent, INFINITE) == WAIT_OBJECT_0) - { - status = freerdp_channels_process_pending_messages(context->instance); - - if (!status) - break; - - event = freerdp_channels_pop_event(context->channels); - - if (event) - { - switch (GetMessageClass(event->id)) - { - case CliprdrChannel_Class: - process_cliprdr_event(context->instance, event); - break; - } - - freerdp_event_free(event); - } - } - - ExitThread(0); - return 0; -} - DWORD mac_client_thread(void* param) { @autoreleasepool @@ -231,7 +163,6 @@ DWORD mac_client_thread(void* param) HANDLE updateEvent; HANDLE updateThread; HANDLE channelsEvent; - HANDLE channelsThread; DWORD nCount; rdpContext* context = (rdpContext*) param; @@ -272,14 +203,7 @@ DWORD mac_client_thread(void* param) events[nCount++] = inputEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE); } - if (settings->AsyncChannels) - { - channelsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_channels_thread, context, 0, NULL); - } - else - { - events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance); - } + events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance); while (1) { @@ -307,12 +231,9 @@ DWORD mac_client_thread(void* param) } } - if (!settings->AsyncChannels) + if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0) { - if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0) - { - channel_activity_cb(instance); - } + freerdp_channels_process_pending_messages(instance); } } @@ -332,12 +253,6 @@ DWORD mac_client_thread(void* param) CloseHandle(inputThread); } - if (settings->AsyncChannels) - { - WaitForSingleObject(channelsThread, INFINITE); - CloseHandle(channelsThread); - } - ExitThread(0); return 0; } @@ -798,21 +713,87 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type) - (void) onPasteboardTimerFired :(NSTimer*) timer { - int i; - NSArray* types; + BYTE* data; + UINT32 size; + UINT32 formatId; + BOOL formatMatch; + int changeCount; + NSData* formatData; + const char* formatType; + NSPasteboardItem* item; - i = (int) [pasteboard_rd changeCount]; + changeCount = (int) [pasteboard_rd changeCount]; - if (i != pasteboard_changecount) + if (changeCount == pasteboard_changecount) + return; + + pasteboard_changecount = changeCount; + + NSArray* items = [pasteboard_rd pasteboardItems]; + + if ([items count] < 1) + return; + + item = [items objectAtIndex:0]; + + /** + * System-Declared Uniform Type Identifiers: + * https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html + */ + + formatMatch = FALSE; + + for (NSString* type in [item types]) { - pasteboard_changecount = i; - types = [NSArray arrayWithObject:NSStringPboardType]; - NSString *str = [pasteboard_rd availableTypeFromArray:types]; - if (str != nil) + formatType = [type UTF8String]; + + if (strcmp(formatType, "public.utf8-plain-text") == 0) { - cliprdr_send_supported_format_list(instance); + formatData = [item dataForType:type]; + formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING"); + + size = (UINT32) [formatData length]; + + data = (BYTE*) malloc(size); + [formatData getBytes:data length:size]; + + ClipboardSetData(mfc->clipboard, formatId, (void*) data, size); + formatMatch = TRUE; + + break; } } + + if (!formatMatch) + ClipboardEmpty(mfc->clipboard); + + if (mfc->clipboardSync) + mac_cliprdr_send_client_format_list(mfc->cliprdr); +} + +- (void) pause +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [self->pasteboard_timer invalidate]; + }); + + NSArray* trackingAreas = self.trackingAreas; + + for (NSTrackingArea* ta in trackingAreas) + { + [self removeTrackingArea:ta]; + } +} + +- (void)resume +{ + dispatch_async(dispatch_get_main_queue(), ^{ + self->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES]; + }); + + NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil]; + [self addTrackingArea:trackingArea]; + [trackingArea release]; } - (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height @@ -826,6 +807,7 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type) void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e) { rdpSettings* settings = context->settings; + mfContext* mfc = (mfContext*) context; if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { @@ -836,6 +818,10 @@ void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEve if (settings->SoftwareGdi) gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface); } + else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) + { + mac_cliprdr_init(mfc, (CliprdrClientContext*) e->pInterface); + } else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0) { @@ -845,6 +831,7 @@ void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEve void mac_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e) { rdpSettings* settings = context->settings; + mfContext* mfc = (mfContext*) context; if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0) { @@ -855,6 +842,10 @@ void mac_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnec if (settings->SoftwareGdi) gdi_graphics_pipeline_uninit(context->gdi, (RdpgfxClientContext*) e->pInterface); } + else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0) + { + mac_cliprdr_uninit(mfc, (CliprdrClientContext*) e->pInterface); + } else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0) { @@ -963,9 +954,12 @@ BOOL mac_post_connect(freerdp* instance) view->pasteboard_wr = [NSPasteboard generalPasteboard]; /* setup pasteboard for read operations */ - view->pasteboard_rd = [NSPasteboard generalPasteboard]; - view->pasteboard_changecount = (int) [view->pasteboard_rd changeCount]; - view->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:mfc->view selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES]; + dispatch_async(dispatch_get_main_queue(), ^{ + view->pasteboard_rd = [NSPasteboard generalPasteboard]; + view->pasteboard_changecount = -1; + }); + + [view resume]; mfc->appleKeyboardType = mac_detect_keyboard_type(); @@ -1272,212 +1266,6 @@ static void input_activity_cb(freerdp* instance) } } -static void channel_activity_cb(freerdp* instance) -{ - wMessage* event; - - freerdp_channels_process_pending_messages(instance); - event = freerdp_channels_pop_event(instance->context->channels); - - if (event) - { - WLog_DBG(TAG, "channel_activity_cb: message %d", event->id); - - switch (GetMessageClass(event->id)) - { - case CliprdrChannel_Class: - process_cliprdr_event(instance, event); - break; - } - - freerdp_event_free(event); - } -} - -int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data) -{ - rdpChannels* channels = (rdpChannels*) user_data; - - freerdp_channels_load_plugin(channels, settings, name, plugin_data); - - return 1; -} - -/* - * stuff related to clipboard redirection - */ - -void cliprdr_process_cb_data_request_event(freerdp* instance) -{ - int len; - NSArray* types; - RDP_CB_DATA_RESPONSE_EVENT* event; - mfContext* mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; - - event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL); - - types = [NSArray arrayWithObject:NSStringPboardType]; - NSString* str = [view->pasteboard_rd availableTypeFromArray:types]; - - if (str == nil) - { - event->data = NULL; - event->size = 0; - } - else - { - NSString* data = [view->pasteboard_rd stringForType:NSStringPboardType]; - len = (int) ([data length] * 2 + 2); - event->data = malloc(len); - [data getCString:(char *) event->data maxLength:len encoding:NSUnicodeStringEncoding]; - event->size = len; - } - - freerdp_channels_send_event(instance->context->channels, (wMessage*) event); -} - -void cliprdr_send_data_request(freerdp* instance, UINT32 format) -{ - RDP_CB_DATA_REQUEST_EVENT* event; - - event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataRequest, NULL, NULL); - - event->format = format; - freerdp_channels_send_event(instance->context->channels, (wMessage*) event); -} - -/** - * at the moment, only the following formats are supported - * CF_TEXT - * CF_UNICODETEXT - */ - -void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event) -{ - NSString* str; - NSArray* types; - mfContext* mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; - - if (event->size == 0) - return; - - if (view->pasteboard_format == CF_TEXT || view->pasteboard_format == CF_UNICODETEXT) - { - str = [[NSString alloc] initWithCharacters:(unichar *) event->data length:event->size / 2]; - types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil]; - [view->pasteboard_wr declareTypes:types owner:mfc->view]; - [view->pasteboard_wr setString:str forType:NSStringPboardType]; - } -} - -void cliprdr_process_cb_monitor_ready_event(freerdp* instance) -{ - wMessage* event; - RDP_CB_FORMAT_LIST_EVENT* format_list_event; - - event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); - - format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event; - format_list_event->num_formats = 0; - - freerdp_channels_send_event(instance->context->channels, event); -} - -/** - * list of supported clipboard formats; currently only the following are supported - * CF_TEXT - * CF_UNICODETEXT - */ - -void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event) -{ - int i; - mfContext* mfc = (mfContext*) instance->context; - MRDPView* view = (MRDPView*) mfc->view; - - if (event->num_formats == 0) - return; - - for (i = 0; i < event->num_formats; i++) - { - switch (event->formats[i]) - { - case CF_TEXT: - case CF_UNICODETEXT: - view->pasteboard_format = CF_UNICODETEXT; - cliprdr_send_data_request(instance, CF_UNICODETEXT); - return; - break; - } - } -} - -void process_cliprdr_event(freerdp* instance, wMessage* event) -{ - if (event) - { - switch (GetMessageType(event->id)) - { - /* - * Monitor Ready PDU is sent by server to indicate that it has been - * initialized and is ready. This PDU is transmitted by the server after it has sent - * Clipboard Capabilities PDU - */ - case CliprdrChannel_MonitorReady: - cliprdr_process_cb_monitor_ready_event(instance); - break; - - /* - * The Format List PDU is sent either by the client or the server when its - * local system clipboard is updated with new clipboard data. This PDU - * contains the Clipboard Format ID and name pairs of the new Clipboard - * Formats on the clipboard - */ - case CliprdrChannel_FormatList: - cliprdr_process_cb_format_list_event(instance, (RDP_CB_FORMAT_LIST_EVENT*) event); - break; - - /* - * The Format Data Request PDU is sent by the receipient of the Format List PDU. - * It is used to request the data for one of the formats that was listed in the - * Format List PDU - */ - case CliprdrChannel_DataRequest: - cliprdr_process_cb_data_request_event(instance); - break; - - /* - * The Format Data Response PDU is sent as a reply to the Format Data Request PDU. - * It is used to indicate whether processing of the Format Data Request PDU - * was successful. If the processing was successful, the Format Data Response PDU - * includes the contents of the requested clipboard data - */ - case CliprdrChannel_DataResponse: - cliprdr_process_cb_data_response_event(instance, (RDP_CB_DATA_RESPONSE_EVENT*) event); - break; - - default: - WLog_ERR(TAG, "process_cliprdr_event: unknown event type %d", GetMessageType(event->id)); - break; - } - } -} - -void cliprdr_send_supported_format_list(freerdp* instance) -{ - RDP_CB_FORMAT_LIST_EVENT* event; - - event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); - - event->formats = (UINT32*) malloc(sizeof(UINT32) * 1); - event->num_formats = 1; - event->formats[0] = CF_UNICODETEXT; - - freerdp_channels_send_event(instance->context->channels, (wMessage*) event); -} - /** * given a rect with 0,0 at the top left (windows cords) * convert it to a rect with 0,0 at the bottom left (apple cords) diff --git a/client/Mac/mf_client.m b/client/Mac/mf_client.m index 9b22e94c8..9b5427792 100644 --- a/client/Mac/mf_client.m +++ b/client/Mac/mf_client.m @@ -99,10 +99,8 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context) settings = instance->settings; settings->AsyncTransport = TRUE; - settings->AsyncUpdate = TRUE; settings->AsyncInput = TRUE; - settings->AsyncChannels = TRUE; return 0; } diff --git a/client/Mac/mfreerdp.h b/client/Mac/mfreerdp.h index 37eb3b4a6..a84a5d559 100644 --- a/client/Mac/mfreerdp.h +++ b/client/Mac/mfreerdp.h @@ -19,11 +19,13 @@ typedef struct mf_context mfContext; #include #include #include +#include #include #include #include #include +#include #include "MRDPView.h" #include "Keyboard.h" @@ -63,6 +65,15 @@ struct mf_context DWORD keyboardThreadId; BOOL disconnect; BOOL sw_gdi; + + BOOL clipboardSync; + wClipboard* clipboard; + UINT32 numServerFormats; + UINT32 requestedFormatId; + HANDLE clipboardRequestEvent; + CLIPRDR_FORMAT* serverFormats; + CliprdrClientContext* cliprdr; + UINT32 clipboardCapabilities; rdpFile* connectionRdpFile; From a538e791b3d4aad87f173cc8b8cb559639ac0b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 6 Nov 2014 17:25:41 -0500 Subject: [PATCH 05/17] shadow: add improved pointer updates --- libfreerdp/core/update.c | 37 ++++++-- server/shadow/X11/x11_shadow.c | 55 +++++++++++- server/shadow/shadow_client.c | 149 ++++++++++++++++++++++++++++++- server/shadow/shadow_subsystem.h | 22 +++++ 4 files changed, 253 insertions(+), 10 deletions(-) diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 5039e29b7..629ed9d7b 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -1506,9 +1506,25 @@ static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDAT Stream_Release(s); } +static void update_send_pointer_position(rdpContext* context, POINTER_POSITION_UPDATE* pointerPosition) +{ + wStream* s; + rdpRdp* rdp = context->rdp; + + s = fastpath_update_pdu_init(rdp->fastpath); + + Stream_EnsureRemainingCapacity(s, 16); + + Stream_Write_UINT16(s, pointerPosition->xPos); /* xPos (2 bytes) */ + Stream_Write_UINT16(s, pointerPosition->yPos); /* yPos (2 bytes) */ + + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s); + Stream_Release(s); +} + static void update_write_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color) { - Stream_EnsureRemainingCapacity(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask); + Stream_EnsureRemainingCapacity(s, 32 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask); Stream_Write_UINT16(s, pointer_color->cacheIndex); Stream_Write_UINT16(s, pointer_color->xPos); @@ -1544,8 +1560,12 @@ static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* poi rdpRdp* rdp = context->rdp; s = fastpath_update_pdu_init(rdp->fastpath); + + Stream_EnsureRemainingCapacity(s, 16); + Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */ update_write_pointer_color(s, &pointer_new->colorPtrAttr); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s); Stream_Release(s); } @@ -1614,14 +1634,14 @@ BOOL update_read_suppress_output(rdpUpdate* update, wStream* s) static void update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags) { - wStream* s; - rdpRdp* rdp = context->rdp; + wStream* s; + rdpRdp* rdp = context->rdp; - s = rdp_data_pdu_init(rdp); - Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */ - Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */ - rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId); - Stream_Release(s); + s = rdp_data_pdu_init(rdp); + Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */ + Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */ + rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId); + Stream_Release(s); } void update_register_server_callbacks(rdpUpdate* update) @@ -1655,6 +1675,7 @@ void update_register_server_callbacks(rdpUpdate* update) update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order; update->altsec->SwitchSurface = update_send_switch_surface_order; update->pointer->PointerSystem = update_send_pointer_system; + update->pointer->PointerPosition = update_send_pointer_position; update->pointer->PointerColor = update_send_pointer_color; update->pointer->PointerNew = update_send_pointer_new; update->pointer->PointerCached = update_send_pointer_cached; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 943bc0b63..c3187bfd9 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -341,6 +341,55 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 #endif } +int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem) +{ + SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg; + UINT32 msgId = SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID; + wMessagePipe* MsgPipe = subsystem->MsgPipe; + + msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) calloc(1, sizeof(SHADOW_MSG_OUT_POINTER_POSITION_UPDATE)); + + if (!msg) + return -1; + + msg->xPos = subsystem->cursorX; + msg->yPos = subsystem->cursorY; + + MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL); + + return 1; +} + +int x11_shadow_pointer_alpha_update(x11ShadowSubsystem* subsystem) +{ + SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg; + UINT32 msgId = SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID; + wMessagePipe* MsgPipe = subsystem->MsgPipe; + + msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) calloc(1, sizeof(SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE)); + + if (!msg) + return -1; + + msg->xHot = subsystem->cursorHotX; + msg->yHot = subsystem->cursorHotY; + msg->width = subsystem->cursorWidth; + msg->height = subsystem->cursorHeight; + msg->scanline = msg->width * 4; + + msg->pixels = (BYTE*) malloc(msg->scanline * msg->height); + + if (!msg->pixels) + return -1; + + CopyMemory(msg->pixels, subsystem->cursorPixels, msg->scanline * msg->height); + msg->premultiplied = TRUE; + + MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL); + + return 1; +} + int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) { int x, y, n, k; @@ -385,6 +434,8 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) } XFree(ci); + + x11_shadow_pointer_alpha_update(subsystem); #endif } else @@ -407,6 +458,8 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) subsystem->cursorX = x; subsystem->cursorY = y; + x11_shadow_pointer_position_update(subsystem); + return 1; } @@ -633,7 +686,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem) (BYTE*) image->data, PIXEL_FORMAT_XRGB32, image->bytes_per_line, x, y, NULL); - x11_shadow_blend_cursor(subsystem); + //x11_shadow_blend_cursor(subsystem); count = ArrayList_Count(server->clients); diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index d3b8b1ebe..32cb1152d 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -736,10 +736,144 @@ int shadow_client_surface_update(rdpShadowClient* client, REGION16* region) return 1; } +int shadow_client_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied, + UINT32 width, UINT32 height, POINTER_COLOR_UPDATE* pointerColor) +{ + UINT32 x, y; + BYTE* pSrc8; + BYTE* pDst8; + int xorStep; + int andStep; + UINT32 andBit; + BYTE* andBits; + UINT32 andPixel; + BYTE A, R, G, B; + + xorStep = (width * 3); + xorStep += (xorStep % 2); + + andStep = ((width + 7) / 8); + andStep += (andStep % 2); + + pointerColor->lengthXorMask = height * xorStep; + pointerColor->xorMaskData = (BYTE*) calloc(1, pointerColor->lengthXorMask); + + if (!pointerColor->xorMaskData) + return -1; + + pointerColor->lengthAndMask = height * andStep; + pointerColor->andMaskData = (BYTE*) calloc(1, pointerColor->lengthAndMask); + + if (!pointerColor->andMaskData) + return -1; + + for (y = 0; y < height; y++) + { + pSrc8 = &pixels[(width * 4) * (height - 1 - y)]; + pDst8 = &(pointerColor->xorMaskData[y * xorStep]); + + andBit = 0x80; + andBits = &(pointerColor->andMaskData[andStep * y]); + + for (x = 0; x < width; x++) + { + B = *pSrc8++; + G = *pSrc8++; + R = *pSrc8++; + A = *pSrc8++; + + andPixel = 0; + + if (A < 64) + A = 0; /* pixel cannot be partially transparent */ + + if (!A) + { + /* transparent pixel: XOR = black, AND = 1 */ + andPixel = 1; + B = G = R = 0; + } + else + { + if (premultiplied) + { + B = (B * 0xFF ) / A; + G = (G * 0xFF ) / A; + R = (R * 0xFF ) / A; + } + } + + *pDst8++ = B; + *pDst8++ = G; + *pDst8++ = R; + + if (andPixel) *andBits |= andBit; + if (!(andBit >>= 1)) { andBits++; andBit = 0x80; } + } + } + + return 1; +} + +int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message) +{ + rdpContext* context = (rdpContext*) client; + rdpUpdate* update = context->update; + + /* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */ + + if (message->id == SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID) + { + POINTER_POSITION_UPDATE pointerPosition; + SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) message->wParam; + + pointerPosition.xPos = msg->xPos; + pointerPosition.yPos = msg->yPos; + + if (0) + { + IFCALL(update->pointer->PointerPosition, context, &pointerPosition); + } + + free(msg); + } + else if (message->id == SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID) + { + POINTER_NEW_UPDATE pointerNew; + POINTER_COLOR_UPDATE* pointerColor; + SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam; + + ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE)); + + pointerNew.xorBpp = 24; + pointerColor = &(pointerNew.colorPtrAttr); + + pointerColor->cacheIndex = 0; + pointerColor->xPos = msg->xHot; + pointerColor->yPos = msg->yHot; + pointerColor->width = msg->width; + pointerColor->height = msg->height; + + shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied, + msg->width, msg->height, pointerColor); + + if (0) + { + IFCALL(update->pointer->PointerNew, context, &pointerNew); + } + + free(msg->pixels); + free(msg); + } + + return 1; +} + void* shadow_client_thread(rdpShadowClient* client) { DWORD status; DWORD nCount; + wMessage message; HANDLE events[32]; HANDLE StopEvent; HANDLE ClientEvent; @@ -752,6 +886,7 @@ void* shadow_client_thread(rdpShadowClient* client) rdpShadowScreen* screen; rdpShadowEncoder* encoder; rdpShadowSubsystem* subsystem; + wMessagePipe* MsgPipe = client->subsystem->MsgPipe; server = client->server; screen = server->screen; @@ -786,6 +921,7 @@ void* shadow_client_thread(rdpShadowClient* client) events[nCount++] = UpdateEvent; events[nCount++] = ClientEvent; events[nCount++] = ChannelEvent; + events[nCount++] = MessageQueue_Event(MsgPipe->Out); status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); @@ -833,12 +969,23 @@ void* shadow_client_thread(rdpShadowClient* client) if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0) { - if (WTSVirtualChannelManagerCheckFileDescriptor(client->vcm) != TRUE) + if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm)) { WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure"); break; } } + + if (WaitForSingleObject(MessageQueue_Event(MsgPipe->Out), 0) == WAIT_OBJECT_0) + { + if (MessageQueue_Peek(MsgPipe->Out, &message, TRUE)) + { + if (message.id == WMQ_QUIT) + break; + + shadow_client_subsystem_process_message(client, &message); + } + } } peer->Disconnect(peer); diff --git a/server/shadow/shadow_subsystem.h b/server/shadow/shadow_subsystem.h index 2ddbce864..9ad710475 100644 --- a/server/shadow/shadow_subsystem.h +++ b/server/shadow/shadow_subsystem.h @@ -41,6 +41,28 @@ struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT }; typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT; +#define SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID 2001 +#define SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID 2002 + +struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE +{ + UINT32 xPos; + UINT32 yPos; +}; +typedef struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE SHADOW_MSG_OUT_POINTER_POSITION_UPDATE; + +struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE +{ + UINT32 xHot; + UINT32 yHot; + UINT32 width; + UINT32 height; + BYTE* pixels; + int scanline; + BOOL premultiplied; +}; +typedef struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE; + #ifdef __cplusplus extern "C" { #endif From 04299bb18b7e4395890910f705d98cf3603c7ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 7 Nov 2014 13:51:10 -0500 Subject: [PATCH 06/17] shadow: improve pointer updates --- include/freerdp/server/shadow.h | 5 +++ server/shadow/X11/x11_shadow.c | 54 +++++++++++++++++++++------------ server/shadow/X11/x11_shadow.h | 2 -- server/shadow/shadow_client.c | 19 +++++++++--- server/shadow/shadow_input.c | 18 +++++++++++ 5 files changed, 72 insertions(+), 26 deletions(-) diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index a3ff1b4b0..4a0164d68 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -87,6 +87,9 @@ struct rdp_shadow_client rdpShadowEncoder* encoder; rdpShadowSubsystem* subsystem; + UINT32 pointerX; + UINT32 pointerY; + HANDLE vcm; EncomspServerContext* encomsp; RemdeskServerContext* remdesk; @@ -145,6 +148,8 @@ struct _RDP_SHADOW_ENTRY_POINTS REGION16 invalidRegion; \ wMessagePipe* MsgPipe; \ SYNCHRONIZATION_BARRIER barrier; \ + UINT32 pointerX; \ + UINT32 pointerY; \ \ pfnShadowSynchronizeEvent SynchronizeEvent; \ pfnShadowKeyboardEvent KeyboardEvent; \ diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index c3187bfd9..3f1a96408 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -231,11 +231,13 @@ void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags XTestGrabControl(subsystem->display, True); if (flags & KBD_FLAGS_DOWN) - XTestFakeKeyEvent(subsystem->display, keycode, True, 0); + XTestFakeKeyEvent(subsystem->display, keycode, True, CurrentTime); else if (flags & KBD_FLAGS_RELEASE) - XTestFakeKeyEvent(subsystem->display, keycode, False, 0); + XTestFakeKeyEvent(subsystem->display, keycode, False, CurrentTime); XTestGrabControl(subsystem->display, False); + + XFlush(subsystem->display); } #endif } @@ -276,13 +278,13 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U button = (negative) ? 5 : 4; - XTestFakeButtonEvent(subsystem->display, button, True, 0); - XTestFakeButtonEvent(subsystem->display, button, False, 0); + XTestFakeButtonEvent(subsystem->display, button, True, CurrentTime); + XTestFakeButtonEvent(subsystem->display, button, False, CurrentTime); } else { if (flags & PTR_FLAGS_MOVE) - XTestFakeMotionEvent(subsystem->display, 0, x, y, 0); + XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime); if (flags & PTR_FLAGS_BUTTON1) button = 1; @@ -295,10 +297,12 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U down = TRUE; if (button) - XTestFakeButtonEvent(subsystem->display, button, down, 0); + XTestFakeButtonEvent(subsystem->display, button, down, CurrentTime); } XTestGrabControl(subsystem->display, False); + + XFlush(subsystem->display); #endif } @@ -335,9 +339,11 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16 down = TRUE; if (button) - XTestFakeButtonEvent(subsystem->display, button, down, 0); + XTestFakeButtonEvent(subsystem->display, button, down, CurrentTime); XTestGrabControl(subsystem->display, False); + + XFlush(subsystem->display); #endif } @@ -352,8 +358,8 @@ int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem) if (!msg) return -1; - msg->xPos = subsystem->cursorX; - msg->yPos = subsystem->cursorY; + msg->xPos = subsystem->pointerX; + msg->yPos = subsystem->pointerY; MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL); @@ -407,6 +413,9 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) ci = XFixesGetCursorImage(subsystem->display); + if (!ci) + return -1; + x = ci->x; y = ci->y; @@ -455,10 +464,13 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage) y = root_y; } - subsystem->cursorX = x; - subsystem->cursorY = y; + if ((x != subsystem->pointerX) || (y != subsystem->pointerY)) + { + subsystem->pointerX = x; + subsystem->pointerY = y; - x11_shadow_pointer_position_update(subsystem); + x11_shadow_pointer_position_update(subsystem); + } return 1; } @@ -469,13 +481,16 @@ int x11_shadow_handle_xevent(x11ShadowSubsystem* subsystem, XEvent* xevent) { } - #ifdef WITH_XFIXES - if (xevent->type == subsystem->xfixes_cursor_notify_event) + else if (xevent->type == subsystem->xfixes_cursor_notify_event) { x11_shadow_query_cursor(subsystem, TRUE); } #endif + else + { + + } return 1; } @@ -526,8 +541,8 @@ int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem) nWidth = subsystem->cursorWidth; nHeight = subsystem->cursorHeight; - nXDst = subsystem->cursorX - surface->x - subsystem->cursorHotX; - nYDst = subsystem->cursorY - surface->y - subsystem->cursorHotY; + nXDst = subsystem->pointerX - surface->x - subsystem->cursorHotX; + nYDst = subsystem->pointerY - surface->y - subsystem->cursorHotY; if (nXDst >= surface->width) return 1; @@ -820,8 +835,8 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem) if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime)) { - x11_shadow_query_cursor(subsystem, FALSE); x11_shadow_screen_grab(subsystem); + x11_shadow_query_cursor(subsystem, FALSE); dwInterval = 1000 / subsystem->captureFrameRate; frameTime += dwInterval; @@ -857,7 +872,7 @@ int x11_shadow_subsystem_base_init(x11ShadowSubsystem* subsystem) subsystem->depth = DefaultDepthOfScreen(subsystem->screen); subsystem->width = WidthOfScreen(subsystem->screen); subsystem->height = HeightOfScreen(subsystem->screen); - subsystem->root_window = DefaultRootWindow(subsystem->display); + subsystem->root_window = RootWindow(subsystem->display, subsystem->number); return 1; } @@ -877,7 +892,8 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem) subsystem->xfixes_cursor_notify_event = xfixes_event + XFixesCursorNotify; - XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask); + XFixesSelectCursorInput(subsystem->display, subsystem->root_window, + XFixesDisplayCursorNotifyMask); return 1; #else diff --git a/server/shadow/X11/x11_shadow.h b/server/shadow/X11/x11_shadow.h index 31233e233..fbb247496 100644 --- a/server/shadow/X11/x11_shadow.h +++ b/server/shadow/X11/x11_shadow.h @@ -80,8 +80,6 @@ struct x11_shadow_subsystem Window root_window; XShmSegmentInfo fb_shm_info; - int cursorX; - int cursorY; int cursorHotX; int cursorHotY; int cursorWidth; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 32cb1152d..63d0b9e97 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -56,6 +56,8 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client) settings->DrawAllowColorSubsampling = TRUE; settings->DrawAllowDynamicColorFidelity = TRUE; + settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6; + settings->RdpSecurity = TRUE; settings->TlsSecurity = TRUE; settings->NlaSecurity = FALSE; @@ -830,9 +832,12 @@ int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* m pointerPosition.xPos = msg->xPos; pointerPosition.yPos = msg->yPos; - if (0) + if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY)) { IFCALL(update->pointer->PointerPosition, context, &pointerPosition); + + client->pointerX = msg->xPos; + client->pointerY = msg->yPos; } free(msg); @@ -841,6 +846,7 @@ int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* m { POINTER_NEW_UPDATE pointerNew; POINTER_COLOR_UPDATE* pointerColor; + POINTER_CACHED_UPDATE pointerCached; SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam; ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE)); @@ -854,13 +860,16 @@ int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* m pointerColor->width = msg->width; pointerColor->height = msg->height; + pointerCached.cacheIndex = pointerColor->cacheIndex; + shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied, msg->width, msg->height, pointerColor); - if (0) - { - IFCALL(update->pointer->PointerNew, context, &pointerNew); - } + IFCALL(update->pointer->PointerNew, context, &pointerNew); + IFCALL(update->pointer->PointerCached, context, &pointerCached); + + free(pointerColor->xorMaskData); + free(pointerColor->andMaskData); free(msg->pixels); free(msg); diff --git a/server/shadow/shadow_input.c b/server/shadow/shadow_input.c index f5cc078dc..b3e732036 100644 --- a/server/shadow/shadow_input.c +++ b/server/shadow/shadow_input.c @@ -69,6 +69,21 @@ void shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y) rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; + if (!(flags & PTR_FLAGS_WHEEL)) + { + client->pointerX = x; + client->pointerY = y; + + if ((client->pointerX == subsystem->pointerX) && + (client->pointerY == subsystem->pointerY)) + { + flags &= ~PTR_FLAGS_MOVE; + + if (!(flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))) + return; + } + } + if (!client->mayInteract) return; @@ -83,6 +98,9 @@ void shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, rdpShadowClient* client = (rdpShadowClient*) input->context; rdpShadowSubsystem* subsystem = client->server->subsystem; + client->pointerX = x; + client->pointerY = y; + if (!client->mayInteract) return; From c719fc88b991a6fd42924693f74ca8bd7bb610b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 7 Nov 2014 15:25:37 -0500 Subject: [PATCH 07/17] client/Sample: update code --- client/Sample/freerdp.c | 187 ++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 95 deletions(-) diff --git a/client/Sample/freerdp.c b/client/Sample/freerdp.c index d426bbc85..9b5e486ae 100644 --- a/client/Sample/freerdp.c +++ b/client/Sample/freerdp.c @@ -50,28 +50,12 @@ #define TAG CLIENT_TAG("sample") -struct tf_info -{ - void* data; -}; -typedef struct tf_info tfInfo; - struct tf_context { rdpContext _p; - - tfInfo* tfi; }; typedef struct tf_context tfContext; -HANDLE g_sem; -static int g_thread_count = 0; - -struct thread_data -{ - freerdp* instance; -}; - int tf_context_new(freerdp* instance, rdpContext* context) { context->channels = freerdp_channels_new(); @@ -97,59 +81,12 @@ void tf_end_paint(rdpContext* context) return; } -int tf_receive_channel_data(freerdp* instance, UINT16 channelId, BYTE* data, int size, int flags, int total_size) -{ - return freerdp_channels_data(instance, channelId, data, size, flags, total_size); -} - -void tf_process_cb_monitor_ready_event(rdpChannels* channels, freerdp* instance) -{ - wMessage* event; - RDP_CB_FORMAT_LIST_EVENT* format_list_event; - - event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL); - - format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event; - format_list_event->num_formats = 0; - - freerdp_channels_send_event(channels, event); -} - -void tf_process_channel_event(rdpChannels* channels, freerdp* instance) -{ - wMessage* event; - - event = freerdp_channels_pop_event(channels); - - if (event) - { - switch (GetMessageType(event->id)) - { - case CliprdrChannel_MonitorReady: - tf_process_cb_monitor_ready_event(channels, instance); - break; - - default: - WLog_ERR(TAG, "unknown event type %d", GetMessageType(event->id)); - break; - } - - freerdp_event_free(event); - } -} - BOOL tf_pre_connect(freerdp* instance) { - tfInfo* tfi; - tfContext* context; + tfContext* tfc; rdpSettings* settings; - context = (tfContext*) instance->context; - - tfi = (tfInfo*) malloc(sizeof(tfInfo)); - ZeroMemory(tfi, sizeof(tfInfo)); - - context->tfi = tfi; + tfc = (tfContext*) instance->context; settings = instance->settings; @@ -220,12 +157,14 @@ int tfreerdp_run(freerdp* instance) ZeroMemory(rfds, sizeof(rfds)); ZeroMemory(wfds, sizeof(wfds)); - if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE) + + if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get FreeRDP file descriptor"); break; } - if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE) + + if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount)) { WLog_ERR(TAG, "Failed to get channel manager file descriptor"); break; @@ -261,17 +200,17 @@ int tfreerdp_run(freerdp* instance) } } - if (freerdp_check_fds(instance) != TRUE) + if (!freerdp_check_fds(instance)) { WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); break; } - if (freerdp_channels_check_fds(channels, instance) != TRUE) + + if (!freerdp_channels_check_fds(channels, instance)) { WLog_ERR(TAG, "Failed to check channel manager file descriptor"); break; } - tf_process_channel_event(channels, instance); } freerdp_channels_close(channels, instance); @@ -281,21 +220,89 @@ int tfreerdp_run(freerdp* instance) return 0; } -void* thread_func(void* param) +void* tf_client_thread_proc(freerdp* instance) { - struct thread_data* data; - data = (struct thread_data*) param; + int i; + int fds; + int max_fds; + int rcount; + int wcount; + void* rfds[32]; + void* wfds[32]; + fd_set rfds_set; + fd_set wfds_set; + rdpChannels* channels; - tfreerdp_run(data->instance); + channels = instance->context->channels; - free(data); + freerdp_connect(instance); - pthread_detach(pthread_self()); + while (1) + { + rcount = 0; + wcount = 0; - g_thread_count--; + ZeroMemory(rfds, sizeof(rfds)); + ZeroMemory(wfds, sizeof(wfds)); - if (g_thread_count < 1) - ReleaseSemaphore(g_sem, 1, NULL); + if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount)) + { + WLog_ERR(TAG, "Failed to get FreeRDP file descriptor"); + break; + } + + if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount)) + { + WLog_ERR(TAG, "Failed to get channel manager file descriptor"); + break; + } + + max_fds = 0; + FD_ZERO(&rfds_set); + FD_ZERO(&wfds_set); + + for (i = 0; i < rcount; i++) + { + fds = (int)(long)(rfds[i]); + + if (fds > max_fds) + max_fds = fds; + + FD_SET(fds, &rfds_set); + } + + if (max_fds == 0) + break; + + if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1) + { + /* these are not really errors */ + if (!((errno == EAGAIN) || + (errno == EWOULDBLOCK) || + (errno == EINPROGRESS) || + (errno == EINTR))) /* signal occurred */ + { + WLog_ERR(TAG, "tfreerdp_run: select failed"); + break; + } + } + + if (!freerdp_check_fds(instance)) + { + WLog_ERR(TAG, "Failed to check FreeRDP file descriptor"); + break; + } + + if (!freerdp_channels_check_fds(channels, instance)) + { + WLog_ERR(TAG, "Failed to check channel manager file descriptor"); + break; + } + } + + freerdp_channels_close(channels, instance); + freerdp_channels_free(channels); + freerdp_free(instance); ExitThread(0); return NULL; @@ -304,17 +311,13 @@ void* thread_func(void* param) int main(int argc, char* argv[]) { int status; - pthread_t thread; + HANDLE thread; freerdp* instance; rdpChannels* channels; - struct thread_data* data; - - g_sem = CreateSemaphore(NULL, 0, 1, NULL); instance = freerdp_new(); instance->PreConnect = tf_pre_connect; instance->PostConnect = tf_post_connect; - instance->ReceiveChannelData = tf_receive_channel_data; instance->ContextSize = sizeof(tfContext); instance->ContextNew = tf_context_new; @@ -326,22 +329,16 @@ int main(int argc, char* argv[]) status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv); if (status < 0) + { exit(0); + } freerdp_client_load_addins(instance->context->channels, instance->settings); - data = (struct thread_data*) malloc(sizeof(struct thread_data)); - ZeroMemory(data, sizeof(sizeof(struct thread_data))); + thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) + tf_client_thread_proc, instance, 0, NULL); - data->instance = instance; - - g_thread_count++; - pthread_create(&thread, 0, thread_func, data); - - while (g_thread_count > 0) - { - WaitForSingleObject(g_sem, INFINITE); - } + WaitForSingleObject(thread, INFINITE); return 0; } From bfdd3bd606a19f8c86fa25e12b46e65c17c46a59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 7 Nov 2014 17:19:46 -0500 Subject: [PATCH 08/17] libfreerdp-gdi: fix bitmap update scanline size --- libfreerdp/gdi/gdi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index 5ce219024..34fdf9b55 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -528,7 +528,7 @@ static void gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate) pSrcData = gdi->bitmap_buffer; } - nSrcStep = nWidth * 4; + nSrcStep = nWidth * gdi->bytesPerPixel; pDstData = gdi->primary_buffer; nDstStep = gdi->width * gdi->bytesPerPixel; From a6bb1857601b252a7a6a38c7e11027f8456e091c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 7 Nov 2014 18:33:45 -0500 Subject: [PATCH 09/17] channels/tsmf: add new callback interface --- channels/tsmf/client/tsmf_main.c | 130 ++++++++------- channels/tsmf/client/tsmf_main.h | 42 ++++- channels/tsmf/client/tsmf_media.c | 69 +++++--- client/X11/xf_tsmf.c | 257 +++++++++++++++--------------- include/freerdp/channels/tsmf.h | 43 +---- include/freerdp/client/tsmf.h | 40 ++++- libfreerdp/utils/event.c | 7 +- 7 files changed, 317 insertions(+), 271 deletions(-) diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 65ce35b4c..6548fe546 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -21,14 +21,11 @@ #include "config.h" #endif -#include -#include -#include - #include +#include #include -#include +#include #include "tsmf_types.h" #include "tsmf_constants.h" @@ -37,43 +34,6 @@ #include "tsmf_main.h" -typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK; - -typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK; - -typedef struct _TSMF_PLUGIN TSMF_PLUGIN; - -struct _TSMF_LISTENER_CALLBACK -{ - IWTSListenerCallback iface; - - IWTSPlugin *plugin; - IWTSVirtualChannelManager *channel_mgr; -}; - -struct _TSMF_CHANNEL_CALLBACK -{ - IWTSVirtualChannelCallback iface; - - IWTSPlugin *plugin; - IWTSVirtualChannelManager *channel_mgr; - IWTSVirtualChannel *channel; - - BYTE presentation_id[GUID_SIZE]; - UINT32 stream_id; -}; - -struct _TSMF_PLUGIN -{ - IWTSPlugin iface; - - TSMF_LISTENER_CALLBACK *listener_callback; - - const char *decoder_name; - const char *audio_name; - const char *audio_device; -}; - void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, UINT32 message_id, UINT64 duration, UINT32 data_size) { @@ -322,41 +282,58 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallbac int *pbAccept, IWTSVirtualChannelCallback **ppCallback) { - TSMF_CHANNEL_CALLBACK *callback; - TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback; + TSMF_CHANNEL_CALLBACK* callback; + TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback; + DEBUG_TSMF(""); - callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK)); - ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK)); + + callback = (TSMF_CHANNEL_CALLBACK*) calloc(1, sizeof(TSMF_CHANNEL_CALLBACK)); + + if (!callback) + return -1; + callback->iface.OnDataReceived = tsmf_on_data_received; callback->iface.OnClose = tsmf_on_close; callback->iface.OnOpen = NULL; callback->plugin = listener_callback->plugin; callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; - *ppCallback = (IWTSVirtualChannelCallback *) callback; + + *ppCallback = (IWTSVirtualChannelCallback*) callback; + return 0; } -static int tsmf_plugin_initialize(IWTSPlugin *pPlugin, IWTSVirtualChannelManager *pChannelMgr) +static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { - TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin; + TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; + DEBUG_TSMF(""); - tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(sizeof(TSMF_LISTENER_CALLBACK)); - ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK)); + + tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) calloc(1, sizeof(TSMF_LISTENER_CALLBACK)); + + if (!tsmf->listener_callback) + return -1; + tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection; tsmf->listener_callback->plugin = pPlugin; tsmf->listener_callback->channel_mgr = pChannelMgr; + return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0, - (IWTSListenerCallback *) tsmf->listener_callback, NULL); + (IWTSListenerCallback*) tsmf->listener_callback, NULL); } -static int tsmf_plugin_terminated(IWTSPlugin *pPlugin) +static int tsmf_plugin_terminated(IWTSPlugin* pPlugin) { - TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin; + TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; + DEBUG_TSMF(""); - if(tsmf->listener_callback) + + if (tsmf->listener_callback) free(tsmf->listener_callback); + free(tsmf); + return 0; } @@ -372,12 +349,15 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) { int status; DWORD flags; - COMMAND_LINE_ARGUMENT_A *arg; - TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin; + COMMAND_LINE_ARGUMENT_A* arg; + TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv, - tsmf_args, flags, tsmf, NULL, NULL); + tsmf_args, flags, tsmf, NULL, NULL); arg = tsmf_args; + do { if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) @@ -407,25 +387,41 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) #define DVCPluginEntry tsmf_DVCPluginEntry #endif -int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS *pEntryPoints) +int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { int status = 0; - TSMF_PLUGIN *tsmf; - tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf"); - if(tsmf == NULL) + TSMF_PLUGIN* tsmf; + TsmfClientContext* context; + + tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf"); + + if (!tsmf) { - tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN)); - ZeroMemory(tsmf, sizeof(TSMF_PLUGIN)); + tsmf = (TSMF_PLUGIN*) calloc(1, sizeof(TSMF_PLUGIN)); + + if (!tsmf) + return -1; + tsmf->iface.Initialize = tsmf_plugin_initialize; tsmf->iface.Connected = NULL; tsmf->iface.Disconnected = NULL; tsmf->iface.Terminated = tsmf_plugin_terminated; - status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf); + + status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf); + + context = (TsmfClientContext*) calloc(1, sizeof(TsmfClientContext)); + + context->handle = (void*) context; + + tsmf->iface.pInterface = (void*) context; + tsmf_media_init(); } - if(status == 0) + + if (status == 0) { - tsmf_process_addin_args((IWTSPlugin *) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); + tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); } + return status; } diff --git a/channels/tsmf/client/tsmf_main.h b/channels/tsmf/client/tsmf_main.h index d5de07f09..bc265da52 100644 --- a/channels/tsmf/client/tsmf_main.h +++ b/channels/tsmf/client/tsmf_main.h @@ -20,10 +20,46 @@ #ifndef __TSMF_MAIN_H #define __TSMF_MAIN_H +typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK; + +typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK; + +typedef struct _TSMF_PLUGIN TSMF_PLUGIN; + +struct _TSMF_LISTENER_CALLBACK +{ + IWTSListenerCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; +}; + +struct _TSMF_CHANNEL_CALLBACK +{ + IWTSVirtualChannelCallback iface; + + IWTSPlugin* plugin; + IWTSVirtualChannelManager* channel_mgr; + IWTSVirtualChannel* channel; + + BYTE presentation_id[GUID_SIZE]; + UINT32 stream_id; +}; + +struct _TSMF_PLUGIN +{ + IWTSPlugin iface; + + TSMF_LISTENER_CALLBACK* listener_callback; + + const char* decoder_name; + const char* audio_name; + const char* audio_device; +}; + void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, - UINT32 message_id, UINT64 duration, UINT32 data_size); -BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, - wMessage* event); + UINT32 message_id, UINT64 duration, UINT32 data_size); +BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event); #endif diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index 6538983f6..429bb2b17 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -220,13 +220,13 @@ static void tsmf_sample_free(void *arg) free(sample); } -static void tsmf_sample_ack(TSMF_SAMPLE *sample) +static void tsmf_sample_ack(TSMF_SAMPLE* sample) { assert(sample); tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size); } -static void tsmf_sample_queue_ack(TSMF_SAMPLE *sample) +static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample) { assert(sample); assert(sample->stream); @@ -262,7 +262,7 @@ finally: return rc; } -TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback) +TSMF_PRESENTATION* tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback) { TSMF_PRESENTATION *presentation; assert(guid); @@ -325,12 +325,14 @@ TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid) return (found) ? presentation : NULL; } -static void tsmf_sample_playback_video(TSMF_SAMPLE *sample) +static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) { UINT64 t; - RDP_VIDEO_FRAME_EVENT *vevent; - TSMF_STREAM *stream = sample->stream; - TSMF_PRESENTATION *presentation = stream->presentation; + TSMF_STREAM* stream = sample->stream; + TSMF_PRESENTATION* presentation = stream->presentation; + TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) sample->channel_callback; + TsmfClientContext* tsmf = (TsmfClientContext*) callback->plugin->pInterface; + DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.", sample->sample_id, (int)sample->end_time, sample->data_size); @@ -346,20 +348,46 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE *sample) } stream->next_start_time = t + sample->duration - 50000; - vevent = (RDP_VIDEO_FRAME_EVENT *) freerdp_event_new(TsmfChannel_Class, TsmfChannel_VideoFrame, - NULL, NULL); - vevent->frame_data = sample->data; - vevent->frame_size = sample->decoded_size; - vevent->frame_pixfmt = sample->pixfmt; - vevent->frame_width = sample->stream->width; - vevent->frame_height = sample->stream->height; - /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ - sample->data = NULL; - sample->decoded_size = 0; - if (!tsmf_push_event(sample->channel_callback, (wMessage *) vevent)) + if (!tsmf->custom) { - freerdp_event_free((wMessage *) vevent); + RDP_VIDEO_FRAME_EVENT* vevent; + + vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(TsmfChannel_Class, + TsmfChannel_VideoFrame, NULL, NULL); + + vevent->frame_data = sample->data; + vevent->frame_size = sample->decoded_size; + vevent->frame_pixfmt = sample->pixfmt; + vevent->frame_width = sample->stream->width; + vevent->frame_height = sample->stream->height; + /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ + sample->data = NULL; + sample->decoded_size = 0; + + if (!tsmf_push_event(sample->channel_callback, (wMessage*) vevent)) + { + freerdp_event_free((wMessage*) vevent); + } + } + else + { + TSMF_VIDEO_FRAME_EVENT event; + + ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT)); + + event.frameData = sample->data; + event.frameSize = sample->decoded_size; + event.framePixFmt = sample->pixfmt; + event.frameWidth = sample->stream->width; + event.frameHeight = sample->stream->height; + + /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ + sample->data = NULL; + sample->decoded_size = 0; + + if (tsmf->FrameEvent) + tsmf->FrameEvent(tsmf, &event); } #if 0 @@ -396,8 +424,7 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample) if (sample->stream->audio && sample->data) { - sample->stream->audio->Play(sample->stream->audio, - sample->data, sample->decoded_size); + sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size); sample->data = NULL; sample->decoded_size = 0; diff --git a/client/X11/xf_tsmf.c b/client/X11/xf_tsmf.c index 62d322a8a..15b9fd58d 100644 --- a/client/X11/xf_tsmf.c +++ b/client/X11/xf_tsmf.c @@ -65,127 +65,7 @@ struct xf_xv_context #define DEBUG_XV(fmt, ...) do { } while (0) #endif -void xf_tsmf_init(xfContext* xfc, long xv_port) -{ - int ret; - unsigned int i; - unsigned int version; - unsigned int release; - unsigned int event_base; - unsigned int error_base; - unsigned int request_base; - unsigned int num_adaptors; - xfXvContext* xv; - XvAdaptorInfo* ai; - XvAttribute* attr; - XvImageFormatValues* fo; - - xv = (xfXvContext*) malloc(sizeof(xfXvContext)); - ZeroMemory(xv, sizeof(xfXvContext)); - - xfc->xv_context = xv; - - xv->xv_colorkey_atom = None; - xv->xv_image_size = 0; - xv->xv_port = xv_port; - - if (!XShmQueryExtension(xfc->display)) - { - DEBUG_XV("no shmem available."); - return; - } - - ret = XvQueryExtension(xfc->display, &version, &release, &request_base, &event_base, &error_base); - if (ret != Success) - { - DEBUG_XV("XvQueryExtension failed %d.", ret); - return; - } - DEBUG_XV("version %u release %u", version, release); - - ret = XvQueryAdaptors(xfc->display, DefaultRootWindow(xfc->display), - &num_adaptors, &ai); - if (ret != Success) - { - DEBUG_XV("XvQueryAdaptors failed %d.", ret); - return; - } - - for (i = 0; i < num_adaptors; i++) - { - DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id, - ai[i].base_id + ai[i].num_ports - 1, ai[i].name); - if (xv->xv_port == 0 && i == num_adaptors - 1) - xv->xv_port = ai[i].base_id; - } - - if (num_adaptors > 0) - XvFreeAdaptorInfo(ai); - - if (xv->xv_port == 0) - { - DEBUG_XV("no adapter selected, video frames will not be processed."); - return; - } - DEBUG_XV("selected %ld", xv->xv_port); - - attr = XvQueryPortAttributes(xfc->display, xv->xv_port, &ret); - for (i = 0; i < (unsigned int)ret; i++) - { - if (strcmp(attr[i].name, "XV_COLORKEY") == 0) - { - xv->xv_colorkey_atom = XInternAtom(xfc->display, "XV_COLORKEY", FALSE); - XvSetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, attr[i].min_value + 1); - break; - } - } - XFree(attr); - -#ifdef WITH_DEBUG_XV - WLog_DBG(TAG, "xf_tsmf_init: pixel format "); -#endif - fo = XvListImageFormats(xfc->display, xv->xv_port, &ret); - if (ret > 0) - { - xv->xv_pixfmts = (UINT32*) malloc((ret + 1) * sizeof(UINT32)); - ZeroMemory(xv->xv_pixfmts, (ret + 1) * sizeof(UINT32)); - - for (i = 0; i < ret; i++) - { - xv->xv_pixfmts[i] = fo[i].id; -#ifdef WITH_DEBUG_XV - WLog_DBG(TAG, "%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1], - ((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]); -#endif - } - xv->xv_pixfmts[i] = 0; - } - XFree(fo); -} - -void xf_tsmf_uninit(xfContext* xfc) -{ - xfXvContext* xv = (xfXvContext*) xfc->xv_context; - - if (xv) - { - if (xv->xv_image_size > 0) - { - shmdt(xv->xv_shmaddr); - shmctl(xv->xv_shmid, IPC_RMID, NULL); - } - if (xv->xv_pixfmts) - { - free(xv->xv_pixfmts); - xv->xv_pixfmts = NULL; - } - free(xv); - xfc->xv_context = NULL; - } -} - -static BOOL -xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt) +static BOOL xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt) { int i; @@ -367,12 +247,12 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV XFree(image); } -static void xf_process_tsmf_redraw_event(xfContext* xfc, RDP_REDRAW_EVENT* revent) +int xf_tsmf_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT* event) { - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, - revent->x, revent->y, revent->width, revent->height, revent->x, revent->y); + //xfContext* xfc = (xfContext*) tsmf->custom; + //xfXvContext* xv = (xfXvContext*) xfc->xv_context; + + return 1; } void xf_process_tsmf_event(xfContext* xfc, wMessage* event) @@ -380,13 +260,134 @@ void xf_process_tsmf_event(xfContext* xfc, wMessage* event) switch (GetMessageType(event->id)) { case TsmfChannel_VideoFrame: + fprintf(stderr, "TsmfVideoFrame\n"); xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event); break; + } +} - case TsmfChannel_Redraw: - xf_process_tsmf_redraw_event(xfc, (RDP_REDRAW_EVENT*) event); +void xf_tsmf_init(xfContext* xfc, long xv_port) +{ + int ret; + unsigned int i; + unsigned int version; + unsigned int release; + unsigned int event_base; + unsigned int error_base; + unsigned int request_base; + unsigned int num_adaptors; + xfXvContext* xv; + XvAdaptorInfo* ai; + XvAttribute* attr; + XvImageFormatValues* fo; + + xv = (xfXvContext*) calloc(1, sizeof(xfXvContext)); + + if (!xv) + return; + + xfc->xv_context = xv; + + xv->xv_colorkey_atom = None; + xv->xv_image_size = 0; + xv->xv_port = xv_port; + + if (!XShmQueryExtension(xfc->display)) + { + DEBUG_XV("no xshm available."); + return; + } + + ret = XvQueryExtension(xfc->display, &version, &release, &request_base, &event_base, &error_base); + + if (ret != Success) + { + DEBUG_XV("XvQueryExtension failed %d.", ret); + return; + } + + DEBUG_XV("version %u release %u", version, release); + + ret = XvQueryAdaptors(xfc->display, DefaultRootWindow(xfc->display), + &num_adaptors, &ai); + + if (ret != Success) + { + DEBUG_XV("XvQueryAdaptors failed %d.", ret); + return; + } + + for (i = 0; i < num_adaptors; i++) + { + DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id, + ai[i].base_id + ai[i].num_ports - 1, ai[i].name); + if (xv->xv_port == 0 && i == num_adaptors - 1) + xv->xv_port = ai[i].base_id; + } + + if (num_adaptors > 0) + XvFreeAdaptorInfo(ai); + + if (xv->xv_port == 0) + { + DEBUG_XV("no adapter selected, video frames will not be processed."); + return; + } + DEBUG_XV("selected %ld", xv->xv_port); + + attr = XvQueryPortAttributes(xfc->display, xv->xv_port, &ret); + + for (i = 0; i < (unsigned int)ret; i++) + { + if (strcmp(attr[i].name, "XV_COLORKEY") == 0) + { + xv->xv_colorkey_atom = XInternAtom(xfc->display, "XV_COLORKEY", FALSE); + XvSetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, attr[i].min_value + 1); break; + } + } + XFree(attr); +#ifdef WITH_DEBUG_XV + WLog_DBG(TAG, "xf_tsmf_init: pixel format "); +#endif + fo = XvListImageFormats(xfc->display, xv->xv_port, &ret); + if (ret > 0) + { + xv->xv_pixfmts = (UINT32*) malloc((ret + 1) * sizeof(UINT32)); + ZeroMemory(xv->xv_pixfmts, (ret + 1) * sizeof(UINT32)); + + for (i = 0; i < ret; i++) + { + xv->xv_pixfmts[i] = fo[i].id; +#ifdef WITH_DEBUG_XV + WLog_DBG(TAG, "%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1], + ((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]); +#endif + } + xv->xv_pixfmts[i] = 0; + } + XFree(fo); +} + +void xf_tsmf_uninit(xfContext* xfc) +{ + xfXvContext* xv = (xfXvContext*) xfc->xv_context; + + if (xv) + { + if (xv->xv_image_size > 0) + { + shmdt(xv->xv_shmaddr); + shmctl(xv->xv_shmid, IPC_RMID, NULL); + } + if (xv->xv_pixfmts) + { + free(xv->xv_pixfmts); + xv->xv_pixfmts = NULL; + } + free(xv); + xfc->xv_context = NULL; } } diff --git a/include/freerdp/channels/tsmf.h b/include/freerdp/channels/tsmf.h index f6a7ef4c2..3ef76d40f 100644 --- a/include/freerdp/channels/tsmf.h +++ b/include/freerdp/channels/tsmf.h @@ -18,46 +18,11 @@ * limitations under the License. */ -#ifndef _TSMF_H_ -#define _TSMF_H_ +#ifndef FREERDP_CHANNEL_TSMF_H +#define FREERDP_CHANNEL_TSMF_H #include -/* Callback function setup order: - * - * When the channel is loaded, it calls TSMF_REGISTER to register the - * decoder handle with the client. - * The client then stores the handle and calls TSMF_REGISTER_INSTANCE - * to give the channel the current handle to the session necessary - * to call other functions. - * After this initial setup the other functions can be used. - */ -/* Functions called from client -> registered by channel */ -#define TSMF_GET_INSTANCE "tsmf_get_instance" -typedef void (*tsmf_get_instance)(void *instance, void *decoder); - -#define TSMF_ADD_WINDOW_HANDLE "tsmf_add_window_handle" -typedef void (*tsmf_add_window_handle)(void *instance, void *decoder, void *window); - -#define TSMF_DEL_WINDOW_HANDLE "tsmf_del_window_handle" -typedef void (*tsmf_del_window_handle)(void *instance, void *decoder); - -/* Functions called from channel -> registered by client */ -#define TSMF_REGISTER "tsmf_register" -typedef void (*tsmf_register)(void *instance, void *decoder); - -#define TSMF_DESTROY "tsmf_destroy" -typedef void (*tsmf_destroy)(void *instance, void *decoder); - -#define TSMF_PLAY "tsmf_play" -typedef void (*tsmf_play)(void *instance, void *decoder); - -#define TSMF_PAUSE "tsmf_pause" -typedef void (*tsmf_pause)(void *instance, void *decoder); - -#define TSMF_RESIZE_WINDOW "tsmf_resize_window" -typedef void (*tsmf_resize_window)(void *instance, void *decoder, int x, int y, int width, - int height, int nr_rect, RDP_RECT *visible); - -#endif +#define TSMF_DVC_CHANNEL_NAME "TSMF" +#endif /* FREERDP_CHANNEL_TSMF_H */ diff --git a/include/freerdp/client/tsmf.h b/include/freerdp/client/tsmf.h index d8b884f94..2978f2d1d 100644 --- a/include/freerdp/client/tsmf.h +++ b/include/freerdp/client/tsmf.h @@ -20,6 +20,15 @@ #ifndef FREERDP_CHANNEL_CLIENT_TSMF_H #define FREERDP_CHANNEL_CLIENT_TSMF_H +#include + +#include + +/* RDP_VIDEO_FRAME_EVENT.frame_pixfmt */ +/* http://www.fourcc.org/yuv.php */ +#define RDP_PIXFMT_I420 0x30323449 +#define RDP_PIXFMT_YV12 0x32315659 + struct _RDP_VIDEO_FRAME_EVENT { wMessage event; @@ -37,19 +46,36 @@ struct _RDP_VIDEO_FRAME_EVENT }; typedef struct _RDP_VIDEO_FRAME_EVENT RDP_VIDEO_FRAME_EVENT; -struct _RDP_REDRAW_EVENT +struct _TSMF_VIDEO_FRAME_EVENT { - wMessage event; + BYTE* frameData; + UINT32 frameSize; + UINT32 framePixFmt; + INT16 frameWidth; + INT16 frameHeight; INT16 x; INT16 y; INT16 width; INT16 height; + UINT16 numVisibleRects; + RECTANGLE_16* visibleRects; }; -typedef struct _RDP_REDRAW_EVENT RDP_REDRAW_EVENT; +typedef struct _TSMF_VIDEO_FRAME_EVENT TSMF_VIDEO_FRAME_EVENT; -/* RDP_VIDEO_FRAME_EVENT.frame_pixfmt */ -/* http://www.fourcc.org/yuv.php */ -#define RDP_PIXFMT_I420 0x30323449 -#define RDP_PIXFMT_YV12 0x32315659 +/** + * Client Interface + */ + +typedef struct _tsmf_client_context TsmfClientContext; + +typedef int (*pcTsmfFrameEvent)(TsmfClientContext* context, TSMF_VIDEO_FRAME_EVENT* event); + +struct _tsmf_client_context +{ + void* handle; + void* custom; + + pcTsmfFrameEvent FrameEvent; +}; #endif /* FREERDP_CHANNEL_CLIENT_TSMF_H */ diff --git a/libfreerdp/utils/event.c b/libfreerdp/utils/event.c index d8cd80d80..081b6e4b3 100644 --- a/libfreerdp/utils/event.c +++ b/libfreerdp/utils/event.c @@ -118,6 +118,7 @@ static wMessage* freerdp_tsmf_event_new(UINT16 event_type) } event; event.m = NULL; + switch (event_type) { case TsmfChannel_VideoFrame: @@ -125,12 +126,6 @@ static wMessage* freerdp_tsmf_event_new(UINT16 event_type) ZeroMemory(event.v, sizeof(RDP_VIDEO_FRAME_EVENT)); event.m->id = MakeMessageId(TsmfChannel, VideoFrame); break; - - case TsmfChannel_Redraw: - event.v = malloc(sizeof(RDP_REDRAW_EVENT)); - ZeroMemory(event.v, sizeof(RDP_REDRAW_EVENT)); - event.m->id = MakeMessageId(TsmfChannel, Redraw); - break; } return event.v; From f9814379cd3db34ce970e7316f22f1793abae876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Nov 2014 11:15:37 -0500 Subject: [PATCH 10/17] xfreerdp: remove usage of XAllocColor (slow) --- client/X11/xf_gdi.c | 35 +---------------------------------- client/X11/xf_graphics.c | 3 --- client/X11/xfreerdp.h | 2 -- 3 files changed, 1 insertion(+), 39 deletions(-) diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index 78d536f48..17d7363db 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -217,28 +217,6 @@ BOOL xf_set_rop3(xfContext* xfc, int rop3) return TRUE; } -unsigned long xf_gdi_get_color(xfContext* xfc, GDI_COLOR color) -{ - XColor x11_color; - - x11_color.flags = DoRed | DoGreen | DoBlue; - GetRGB32(x11_color.red, x11_color.green, x11_color.blue, color); - x11_color.red = x11_color.red << 8; - x11_color.green = x11_color.green << 8; - x11_color.blue = x11_color.blue << 8; - - if (XAllocColor(xfc->display, xfc->colormap, &x11_color) != 0) - { - XFreeColors(xfc->display, xfc->colormap, &x11_color.pixel, 1, 0); - } - else - { - x11_color.pixel = BlackPixel(xfc->display, xfc->screen_number); - } - - return x11_color.pixel; -} - Pixmap xf_brush_new(xfContext* xfc, int width, int height, int bpp, BYTE* data) { GC gc; @@ -488,9 +466,7 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt) xf_set_rop3(xfc, gdi_rop3_code(patblt->bRop)); foreColor = freerdp_convert_gdi_order_color(patblt->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette); - foreColor = xf_gdi_get_color(xfc, foreColor); backColor = freerdp_convert_gdi_order_color(patblt->backColor, context->settings->ColorDepth, xfc->format, xfc->palette); - backColor = xf_gdi_get_color(xfc, backColor); if (brush->style == GDI_BS_SOLID) { @@ -610,7 +586,6 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect) xf_lock_x11(xfc, FALSE); color = freerdp_convert_gdi_order_color(opaque_rect->color, context->settings->ColorDepth, xfc->format, xfc->palette); - color = xf_gdi_get_color(xfc, color); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); @@ -646,7 +621,6 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult xf_lock_x11(xfc, FALSE); color = freerdp_convert_gdi_order_color(multi_opaque_rect->color, context->settings->ColorDepth, xfc->format, xfc->palette); - color = xf_gdi_get_color(xfc, color); XSetFunction(xfc->display, xfc->gc, GXcopy); XSetFillStyle(xfc->display, xfc->gc, FillSolid); @@ -689,7 +663,6 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to) xf_set_rop2(xfc, line_to->bRop2); color = freerdp_convert_gdi_order_color(line_to->penColor, context->settings->ColorDepth, xfc->format, xfc->palette); - color = xf_gdi_get_color(xfc, color); XSetFillStyle(xfc->display, xfc->gc, FillSolid); XSetForeground(xfc->display, xfc->gc, color); @@ -741,7 +714,6 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline) xf_set_rop2(xfc, polyline->bRop2); color = freerdp_convert_gdi_order_color(polyline->penColor, context->settings->ColorDepth, xfc->format, xfc->palette); - color = xf_gdi_get_color(xfc, color); XSetFillStyle(xfc->display, xfc->gc, FillSolid); XSetForeground(xfc->display, xfc->gc, color); @@ -841,9 +813,7 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt) bitmap = (xfBitmap*) mem3blt->bitmap; xf_set_rop3(xfc, gdi_rop3_code(mem3blt->bRop)); foreColor = freerdp_convert_gdi_order_color(mem3blt->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette); - foreColor = xf_gdi_get_color(xfc, foreColor); backColor = freerdp_convert_gdi_order_color(mem3blt->backColor, context->settings->ColorDepth, xfc->format, xfc->palette); - backColor = xf_gdi_get_color(xfc, backColor); if (brush->style == GDI_BS_PATTERN) { @@ -916,7 +886,6 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc) xf_set_rop2(xfc, polygon_sc->bRop2); brush_color = freerdp_convert_gdi_order_color(polygon_sc->brushColor, context->settings->ColorDepth, xfc->format, xfc->palette); - brush_color = xf_gdi_get_color(xfc, brush_color); npoints = polygon_sc->numPoints + 1; points = malloc(sizeof(XPoint) * npoints); @@ -978,9 +947,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) brush = &(polygon_cb->brush); xf_set_rop2(xfc, polygon_cb->bRop2); foreColor = freerdp_convert_gdi_order_color(polygon_cb->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette); - foreColor = xf_gdi_get_color(xfc, foreColor); backColor = freerdp_convert_gdi_order_color(polygon_cb->backColor, context->settings->ColorDepth, xfc->format, xfc->palette); - backColor = xf_gdi_get_color(xfc, backColor); npoints = polygon_cb->numPoints + 1; points = malloc(sizeof(XPoint) * npoints); @@ -1005,7 +972,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb) break; default: - WLog_ERR(TAG, "PolygonCB unknown fillMode: %d", polygon_cb->fillMode); + WLog_ERR(TAG, "PolygonCB unknown fillMode: %d", polygon_cb->fillMode); break; } diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 18f8d0c08..e73833aed 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -386,9 +386,6 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height xf_lock_x11(xfc, FALSE); - fgcolor = xf_gdi_get_color(xfc, fgcolor); - bgcolor = xf_gdi_get_color(xfc, bgcolor); - XSetFunction(xfc->display, xfc->gc, GXcopy); if (width && height) diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index bb222a964..4c66e2408 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -248,8 +248,6 @@ void xf_unlock_x11(xfContext* xfc, BOOL display); void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale); void xf_transform_window(xfContext* xfc); -unsigned long xf_gdi_get_color(xfContext* xfc, GDI_COLOR color); - FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason); #endif /* __XFREERDP_H */ From 71b8bfac300af34d1007329596566ee8d65d9817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Nov 2014 11:31:28 -0500 Subject: [PATCH 11/17] libwinpr-smartcard: fix PCSC structure padding that was recently broken --- winpr/libwinpr/smartcard/smartcard_pcsc.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.h b/winpr/libwinpr/smartcard/smartcard_pcsc.h index 7c83e2a3c..a25dd64be 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.h +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.h @@ -78,7 +78,14 @@ typedef long PCSC_LONG; #define PCSC_SCARD_CTL_CODE(code) (0x42000000 + (code)) #define PCSC_CM_IOCTL_GET_FEATURE_REQUEST SCARD_CTL_CODE(3400) +/** + * pcsc-lite defines SCARD_READERSTATE, SCARD_IO_REQUEST as packed + * on Mac OS X only and uses default packing everywhere else. + */ + +#ifdef __APPLE__ #pragma pack(push, 1) +#endif typedef struct { @@ -97,6 +104,12 @@ typedef struct PCSC_DWORD cbPciLength; } PCSC_SCARD_IO_REQUEST; +#ifdef __APPLE__ +#pragma pack(pop) +#endif + +#pragma pack(push, 1) + typedef struct { BYTE tag; From 129582e67f69863ef14555afdf5964ab20472d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Nov 2014 14:02:54 -0500 Subject: [PATCH 12/17] channels/tsmf: cleanup --- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 136 +++++----- channels/tsmf/client/gstreamer/tsmf_X11.c | 112 +++++--- .../tsmf/client/gstreamer/tsmf_gstreamer.c | 120 +++++---- .../tsmf/client/gstreamer/tsmf_platform.h | 28 +- channels/tsmf/client/tsmf_audio.c | 4 +- channels/tsmf/client/tsmf_decoder.c | 30 ++- channels/tsmf/client/tsmf_ifman.c | 240 ++++++++++++------ channels/tsmf/client/tsmf_main.c | 107 +++++--- channels/tsmf/client/tsmf_media.c | 233 +++++++++-------- client/X11/xf_tsmf.c | 25 +- 10 files changed, 631 insertions(+), 404 deletions(-) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index 657ac29c7..460faa4c3 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -83,11 +83,11 @@ typedef struct _TSMFFFmpegDecoder UINT32 decoded_size_max; } TSMFFFmpegDecoder; -static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder) +static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context = avcodec_alloc_context3(NULL); - if(!mdecoder->codec_context) + if (!mdecoder->codec_context) { WLog_ERR(TAG, "avcodec_alloc_context failed."); return FALSE; @@ -95,9 +95,9 @@ static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder) return TRUE; } -static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context->width = media_type->Width; mdecoder->codec_context->height = media_type->Height; mdecoder->codec_context->bit_rate = media_type->BitRate; @@ -107,9 +107,9 @@ static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MED return TRUE; } -static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator; mdecoder->codec_context->bit_rate = media_type->BitRate; mdecoder->codec_context->channels = media_type->Channels; @@ -134,34 +134,34 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MED return TRUE; } -static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type) { BYTE *p; UINT32 size; const BYTE *s; - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); - if(!mdecoder->codec) + if (!mdecoder->codec) { WLog_ERR(TAG, "avcodec_find_decoder failed."); return FALSE; } mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_type = mdecoder->media_type; - if(mdecoder->media_type == AVMEDIA_TYPE_VIDEO) + if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO) { - if(!tsmf_ffmpeg_init_video_stream(decoder, media_type)) + if (!tsmf_ffmpeg_init_video_stream(decoder, media_type)) return FALSE; } else - if(mdecoder->media_type == AVMEDIA_TYPE_AUDIO) + if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO) { - if(!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) + if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) return FALSE; } - if(media_type->ExtraData) + if (media_type->ExtraData) { - if(media_type->SubType == TSMF_SUB_TYPE_AVC1 && + if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. @@ -195,15 +195,15 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYP memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); } } - if(mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) + if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; return TRUE; } -static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder) +static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; - if(avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0) + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0) { WLog_ERR(TAG, "avcodec_open2 failed."); return FALSE; @@ -212,9 +212,9 @@ static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder) return TRUE; } -static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE *media_type) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; switch(media_type->MajorType) { case TSMF_MAJOR_TYPE_VIDEO: @@ -254,7 +254,7 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *medi /* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data is at the end of it. See http://msdn.microsoft.com/en-us/library/dd757806.aspx */ - if(media_type->ExtraData) + if (media_type->ExtraData) { media_type->ExtraData += 12; media_type->ExtraDataSize -= 12; @@ -270,18 +270,18 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *medi default: return FALSE; } - if(!tsmf_ffmpeg_init_context(decoder)) + if (!tsmf_ffmpeg_init_context(decoder)) return FALSE; - if(!tsmf_ffmpeg_init_stream(decoder, media_type)) + if (!tsmf_ffmpeg_init_stream(decoder, media_type)) return FALSE; - if(!tsmf_ffmpeg_prepare(decoder)) + if (!tsmf_ffmpeg_prepare(decoder)) return FALSE; return TRUE; } -static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) +static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; int decoded; int len; AVFrame *frame; @@ -294,12 +294,12 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UI av_init_packet(&pkt); pkt.data = (BYTE *) data; pkt.size = data_size; - if(extensions & TSMM_SAMPLE_EXT_CLEANPOINT) + if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT) pkt.flags |= AV_PKT_FLAG_KEY; len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt); } #endif - if(len < 0) + if (len < 0) { WLog_ERR(TAG, "data_size %d, avcodec_decode_video failed (%d)", data_size, len); ret = FALSE; @@ -334,9 +334,9 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UI return ret; } -static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) +static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; int len; int frame_size; UINT32 src_size; @@ -349,11 +349,11 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI for(i = 0; i < data_size; i++) { WLog_DBG(TAG, ("%02X ", data[i])); - if(i % 16 == 15) + if (i % 16 == 15) WLog_DBG(TAG, ("\n")); } #endif - if(mdecoder->decoded_size_max == 0) + if (mdecoder->decoded_size_max == 0) mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16; mdecoder->decoded_data = malloc(mdecoder->decoded_size_max); ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max); @@ -365,12 +365,12 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI while(src_size > 0) { /* Ensure enough space for decoding */ - if(mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE) + if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE) { mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16; mdecoder->decoded_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max); dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F); - if(dst - mdecoder->decoded_data != dst_offset) + if (dst - mdecoder->decoded_data != dst_offset) { /* re-align the memory if the alignment has changed after realloc */ memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); @@ -391,7 +391,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI pkt.data = (BYTE *) src; pkt.size = src_size; len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt); - if(len >= 0 && got_frame) + if (len >= 0 && got_frame) { frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels, decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1); @@ -400,7 +400,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI av_free(decoded_frame); } #endif - if(len <= 0 || frame_size <= 0) + if (len <= 0 || frame_size <= 0) { WLog_ERR(TAG, "error decoding"); break; @@ -410,13 +410,13 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI mdecoder->decoded_size += frame_size; dst += frame_size; } - if(mdecoder->decoded_size == 0) + if (mdecoder->decoded_size == 0) { free(mdecoder->decoded_data); mdecoder->decoded_data = NULL; } else - if(dst_offset) + if (dst_offset) { /* move the aligned decoded data to original place */ memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size); @@ -426,10 +426,10 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI return TRUE; } -static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) +static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; - if(mdecoder->decoded_data) + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + if (mdecoder->decoded_data) { free(mdecoder->decoded_data); mdecoder->decoded_data = NULL; @@ -447,10 +447,10 @@ static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 d } } -static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder *decoder, UINT32 *size) +static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32 *size) { BYTE *buf; - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; *size = mdecoder->decoded_size; buf = mdecoder->decoded_data; mdecoder->decoded_data = NULL; @@ -458,10 +458,11 @@ static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder *decoder, UINT32 *size) return buf; } -static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder) +static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; - switch(mdecoder->codec_context->pix_fmt) + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + + switch (mdecoder->codec_context->pix_fmt) { case PIX_FMT_YUV420P: return RDP_PIXFMT_I420; @@ -472,10 +473,11 @@ static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder) } } -static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height) +static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32 *width, UINT32 *height) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; - if(mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0) + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + + if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0) { *width = mdecoder->codec_context->width; *height = mdecoder->codec_context->height; @@ -487,18 +489,18 @@ static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *wid } } -static void tsmf_ffmpeg_free(ITSMFDecoder *decoder) +static void tsmf_ffmpeg_free(ITSMFDecoder* decoder) { - TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder; - if(mdecoder->frame) + TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + if (mdecoder->frame) av_free(mdecoder->frame); - if(mdecoder->decoded_data) + if (mdecoder->decoded_data) free(mdecoder->decoded_data); - if(mdecoder->codec_context) + if (mdecoder->codec_context) { - if(mdecoder->prepared) + if (mdecoder->prepared) avcodec_close(mdecoder->codec_context); - if(mdecoder->codec_context->extradata) + if (mdecoder->codec_context->extradata) free(mdecoder->codec_context->extradata); av_free(mdecoder->codec_context); } @@ -511,23 +513,29 @@ static BOOL initialized = FALSE; #define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry #endif -ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void) +ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) { - TSMFFFmpegDecoder *decoder; - if(!initialized) + TSMFFFmpegDecoder* decoder; + + if (!initialized) { avcodec_register_all(); initialized = TRUE; } WLog_DBG(TAG, "TSMFDecoderEntry FFMPEG"); - decoder = (TSMFFFmpegDecoder*) malloc(sizeof(TSMFFFmpegDecoder)); - ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder)); + + decoder = (TSMFFFmpegDecoder*) calloc(1, sizeof(TSMFFFmpegDecoder)); + + if (!decoder) + return NULL; + decoder->iface.SetFormat = tsmf_ffmpeg_set_format; decoder->iface.Decode = tsmf_ffmpeg_decode; decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data; decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format; decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension; decoder->iface.Free = tsmf_ffmpeg_free; - return (ITSMFDecoder *) decoder; + + return (ITSMFDecoder*) decoder; } diff --git a/channels/tsmf/client/gstreamer/tsmf_X11.c b/channels/tsmf/client/gstreamer/tsmf_X11.c index 1bfc11e51..d4cbcb486 100644 --- a/channels/tsmf/client/gstreamer/tsmf_X11.c +++ b/channels/tsmf/client/gstreamer/tsmf_X11.c @@ -18,8 +18,6 @@ * limitations under the License. */ -#include - #include #include #include @@ -61,29 +59,34 @@ struct X11Handle Window subwin; }; -static const char *get_shm_id() +static const char* get_shm_id() { static char shm_id[64]; snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId()); return shm_id; } -const char *tsmf_platform_get_video_sink(void) +const char* tsmf_platform_get_video_sink(void) { return "xvimagesink"; } -const char *tsmf_platform_get_audio_sink(void) +const char* tsmf_platform_get_audio_sink(void) { return "autoaudiosink"; } -int tsmf_platform_create(TSMFGstreamerDecoder *decoder) +int tsmf_platform_create(TSMFGstreamerDecoder* decoder) { - struct X11Handle *hdl; - assert(decoder); - assert(!decoder->platform); - hdl = malloc(sizeof(struct X11Handle)); + struct X11Handle* hdl; + + if (!decoder) + return -1; + + if (decoder->platform) + return -1; + + hdl = calloc(1, sizeof(struct X11Handle)); if (!hdl) { @@ -91,7 +94,6 @@ int tsmf_platform_create(TSMFGstreamerDecoder *decoder) return -1; } - memset(hdl, 0, sizeof(struct X11Handle)); decoder->platform = hdl; hdl->shmid = shm_open(get_shm_id(), O_RDWR, PROT_READ | PROT_WRITE);; @@ -101,9 +103,11 @@ int tsmf_platform_create(TSMFGstreamerDecoder *decoder) return -2; } else + { hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0); + } - if (hdl->xfwin == (int *)-1) + if (hdl->xfwin == (int*)-1) { WLog_ERR(TAG, "shmat failed!"); return -3; @@ -120,22 +124,30 @@ int tsmf_platform_create(TSMFGstreamerDecoder *decoder) return 0; } -int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder) +int tsmf_platform_set_format(TSMFGstreamerDecoder* decoder) { - assert(decoder); + if (!decoder) + return -1; if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO) { + } return 0; } -int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder) +int tsmf_platform_register_handler(TSMFGstreamerDecoder* decoder) { - assert(decoder); - assert(decoder->pipe); - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe)); + GstBus* bus; + + if (!decoder) + return -1; + + if (!decoder->pipe) + return -1; + + bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe)); if (!bus) { @@ -146,9 +158,9 @@ int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder) return 0; } -int tsmf_platform_free(TSMFGstreamerDecoder *decoder) +int tsmf_platform_free(TSMFGstreamerDecoder* decoder) { - struct X11Handle *hdl = decoder->platform; + struct X11Handle* hdl = decoder->platform; if (!hdl) return -1; @@ -157,18 +169,21 @@ int tsmf_platform_free(TSMFGstreamerDecoder *decoder) XCloseDisplay(hdl->disp); if (hdl->xfwin) - munmap(0, sizeof(void *)); + munmap(0, sizeof(void*)); if (hdl->shmid >= 0) close(hdl->shmid); free(hdl); decoder->platform = NULL; + return 0; } -int tsmf_window_create(TSMFGstreamerDecoder *decoder) +int tsmf_window_create(TSMFGstreamerDecoder* decoder) { + struct X11Handle* hdl; + if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO) { decoder->ready = TRUE; @@ -181,9 +196,14 @@ int tsmf_window_create(TSMFGstreamerDecoder *decoder) #else GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink); #endif - struct X11Handle *hdl = (struct X11Handle *)decoder->platform; - assert(decoder); - assert(hdl); + + if (!decoder) + return -1; + + if (!decoder->platform) + return -1; + + hdl = (struct X11Handle*) decoder->platform; if (!hdl->subwin) { @@ -217,11 +237,15 @@ int tsmf_window_create(TSMFGstreamerDecoder *decoder) } } -int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width, +int tsmf_window_resize(TSMFGstreamerDecoder* decoder, int x, int y, int width, int height, int nr_rects, RDP_RECT *rects) { + struct X11Handle* hdl; + if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO) + { return -3; + } else { #if GST_VERSION_MAJOR > 0 @@ -229,10 +253,15 @@ int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width, #else GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink); #endif - struct X11Handle *hdl = (struct X11Handle *)decoder->platform; + if (!decoder) + return -1; + + if (!decoder->platform) + return -1; + + hdl = (struct X11Handle*) decoder->platform; DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height); - assert(decoder); - assert(hdl); + #if GST_VERSION_MAJOR > 0 if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height)) @@ -280,28 +309,37 @@ int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width, } } -int tsmf_window_pause(TSMFGstreamerDecoder *decoder) +int tsmf_window_pause(TSMFGstreamerDecoder* decoder) { - assert(decoder); + if (!decoder) + return -1; + return 0; } -int tsmf_window_resume(TSMFGstreamerDecoder *decoder) +int tsmf_window_resume(TSMFGstreamerDecoder* decoder) { - assert(decoder); + if (!decoder) + return -1; + return 0; } -int tsmf_window_destroy(TSMFGstreamerDecoder *decoder) +int tsmf_window_destroy(TSMFGstreamerDecoder* decoder) { - struct X11Handle *hdl = (struct X11Handle *)decoder->platform; + struct X11Handle* hdl; decoder->ready = FALSE; if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO) return -3; - assert(decoder); - assert(hdl); + if (!decoder) + return -1; + + if (!decoder->platform) + return -1; + + hdl = (struct X11Handle*) decoder->platform; if (hdl->subwin) { diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c index 0139b8996..713edeba2 100644 --- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c +++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c @@ -43,14 +43,15 @@ #include #endif -static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder); -static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder *mdecoder); -static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder, +static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder* mdecoder); +static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder* mdecoder); +static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder* mdecoder, GstState desired_state); -const char *get_type(TSMFGstreamerDecoder *mdecoder) +const char* get_type(TSMFGstreamerDecoder* mdecoder) { - assert(mdecoder); + if (!mdecoder) + return NULL; if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO) return "VIDEO"; @@ -60,28 +61,28 @@ const char *get_type(TSMFGstreamerDecoder *mdecoder) static void tsmf_gstreamer_enough_data(GstAppSrc *src, gpointer user_data) { - TSMFGstreamerDecoder *mdecoder = user_data; - (void)mdecoder; + TSMFGstreamerDecoder* mdecoder = user_data; + (void) mdecoder; DEBUG_TSMF("%s", get_type(mdecoder)); } static void tsmf_gstreamer_need_data(GstAppSrc *src, guint length, gpointer user_data) { - TSMFGstreamerDecoder *mdecoder = user_data; - (void)mdecoder; + TSMFGstreamerDecoder* mdecoder = user_data; + (void) mdecoder; DEBUG_TSMF("%s length=%lu", get_type(mdecoder), length); } static gboolean tsmf_gstreamer_seek_data(GstAppSrc *src, guint64 offset, gpointer user_data) { - TSMFGstreamerDecoder *mdecoder = user_data; - (void)mdecoder; + TSMFGstreamerDecoder* mdecoder = user_data; + (void) mdecoder; DEBUG_TSMF("%s offset=%llu", get_type(mdecoder), offset); if (!mdecoder->paused) tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED); - gst_app_src_end_of_stream((GstAppSrc *)mdecoder->src); + gst_app_src_end_of_stream((GstAppSrc*) mdecoder->src); if (!mdecoder->paused) tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING); @@ -100,11 +101,11 @@ static inline const GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_ti return (GstClockTime)(ms_timestamp * 100); } -int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder, GstState desired_state) +int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder* mdecoder, GstState desired_state) { GstStateChangeReturn state_change; - const char *name; - const char *sname = get_type(mdecoder); + const char* name; + const char* sname = get_type(mdecoder); if (!mdecoder) return 0; @@ -120,24 +121,33 @@ int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder, GstState d state_change = gst_element_set_state(mdecoder->pipe, desired_state); if (state_change == GST_STATE_CHANGE_FAILURE) + { WLog_ERR(TAG, "%s: (%s) GST_STATE_CHANGE_FAILURE.", sname, name); + } else if (state_change == GST_STATE_CHANGE_ASYNC) { WLog_ERR(TAG, "%s: (%s) GST_STATE_CHANGE_ASYNC.", sname, name); mdecoder->state = desired_state; } else + { mdecoder->state = desired_state; + } return 0; } -static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size) +static GstBuffer* tsmf_get_buffer_from_data(const void* raw_data, gsize size) { - GstBuffer *buffer; + GstBuffer* buffer; gpointer data; - assert(raw_data); - assert(size > 0); + + if (!raw_data) + return NULL; + + if (size < 1) + return NULL; + data = g_malloc(size); if (!data) @@ -146,7 +156,8 @@ static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size) return NULL; } - memcpy(data, raw_data, size); + CopyMemory(data, raw_data, size); + #if GST_VERSION_MAJOR > 0 buffer = gst_buffer_new_wrapped(data, size); #else @@ -163,12 +174,13 @@ static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size) GST_BUFFER_SIZE(buffer) = size; GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer); #endif + return buffer; } -static BOOL tsmf_gstreamer_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type) +static BOOL tsmf_gstreamer_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder*) decoder; if (!mdecoder) return FALSE; @@ -377,7 +389,6 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *m void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder* mdecoder) { - //Cleaning up elements if (!mdecoder || !mdecoder->pipe) return; @@ -393,11 +404,11 @@ void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder* mdecoder) mdecoder->src = NULL; } -BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder) +BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder* mdecoder) { - const char *appsrc = "appsrc name=source ! decodebin name=decoder !"; - const char *video = "autovideoconvert ! videoscale !"; - const char *audio = "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !"; + const char* appsrc = "appsrc name=source ! decodebin name=decoder !"; + const char* video = "autovideoconvert ! videoscale !"; + const char* audio = "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !"; char pipeline[1024]; if (!mdecoder) @@ -467,16 +478,16 @@ BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder) mdecoder->pipeline_start_time_valid = 0; mdecoder->shutdown = 0; - GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(mdecoder->pipe), GST_DEBUG_GRAPH_SHOW_ALL, get_type(mdecoder)); + GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(mdecoder->pipe), GST_DEBUG_GRAPH_SHOW_ALL, get_type(mdecoder)); return TRUE; } -static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions, +static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions, UINT64 start_time, UINT64 end_time, UINT64 duration) { GstBuffer *gst_buf; - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; UINT64 sample_time = tsmf_gstreamer_timestamp_ms_to_gst(start_time); UINT64 sample_duration = tsmf_gstreamer_timestamp_ms_to_gst(duration); @@ -570,9 +581,9 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder *decoder, const BYTE *data, UIN return TRUE; } -static void tsmf_gstreamer_change_volume(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted) +static void tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume, UINT32 muted) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; if (!mdecoder || !mdecoder->pipe) return; @@ -595,9 +606,9 @@ static void tsmf_gstreamer_change_volume(ITSMFDecoder *decoder, UINT32 newVolume g_object_set(mdecoder->volume, "volume", mdecoder->gstVolume, NULL); } -static void tsmf_gstreamer_control(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg) +static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg control_msg, UINT32 *arg) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; if (!mdecoder) return; @@ -659,9 +670,9 @@ static void tsmf_gstreamer_control(ITSMFDecoder *decoder, ITSMFControlMsg contro WLog_ERR(TAG, "Unknown control message %08x", control_msg); } -static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder *decoder) +static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder* decoder) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; DEBUG_TSMF(""); if (!mdecoder) @@ -673,9 +684,9 @@ static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder *decoder) return clbuff >= buff_max ? TRUE : FALSE; } -static void tsmf_gstreamer_free(ITSMFDecoder *decoder) +static void tsmf_gstreamer_free(ITSMFDecoder* decoder) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; DEBUG_TSMF("%s", get_type(mdecoder)); if (mdecoder) @@ -687,15 +698,15 @@ static void tsmf_gstreamer_free(ITSMFDecoder *decoder) gst_caps_unref(mdecoder->gst_caps); tsmf_platform_free(mdecoder); - memset(mdecoder, 0, sizeof(TSMFGstreamerDecoder)); + ZeroMemory(mdecoder, sizeof(TSMFGstreamerDecoder)); free(mdecoder); mdecoder = NULL; } } -static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder *decoder) +static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder* decoder) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; if (!mdecoder) return 0; @@ -716,31 +727,33 @@ static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder *decoder) return pos/100; } -static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder *decoder, +static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder* decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; DEBUG_TSMF("x=%d, y=%d, w=%d, h=%d, rect=%d", newX, newY, newWidth, newHeight, numRectangles); if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO) + { tsmf_window_resize(mdecoder, newX, newY, newWidth, newHeight, numRectangles, rectangles); + } } -BOOL tsmf_gstreamer_ack(ITSMFDecoder *decoder, BOOL (*cb)(void *, BOOL), void *stream) +BOOL tsmf_gstreamer_ack(ITSMFDecoder* decoder, BOOL (*cb)(void *, BOOL), void *stream) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; DEBUG_TSMF(""); mdecoder->ack_cb = cb; mdecoder->stream = stream; return TRUE; } -BOOL tsmf_gstreamer_sync(ITSMFDecoder *decoder, void (*cb)(void *), void *stream) +BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, void (*cb)(void *), void *stream) { - TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder; + TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; DEBUG_TSMF(""); mdecoder->sync_cb = NULL; mdecoder->stream = stream; @@ -751,7 +764,7 @@ BOOL tsmf_gstreamer_sync(ITSMFDecoder *decoder, void (*cb)(void *), void *stream #define freerdp_tsmf_client_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry #endif -ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void) +ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) { TSMFGstreamerDecoder *decoder; @@ -760,8 +773,11 @@ ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void) gst_init(NULL, NULL); } - decoder = malloc(sizeof(TSMFGstreamerDecoder)); - memset(decoder, 0, sizeof(TSMFGstreamerDecoder)); + decoder = calloc(1, sizeof(TSMFGstreamerDecoder)); + + if (!decoder) + return NULL; + decoder->iface.SetFormat = tsmf_gstreamer_set_format; decoder->iface.Decode = NULL; decoder->iface.GetDecodedData = NULL; @@ -780,6 +796,8 @@ ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void) decoder->gstVolume = 0.5; decoder->gstMuted = FALSE; decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */ + tsmf_platform_create(decoder); - return (ITSMFDecoder *) decoder; + + return (ITSMFDecoder*) decoder; } diff --git a/channels/tsmf/client/gstreamer/tsmf_platform.h b/channels/tsmf/client/gstreamer/tsmf_platform.h index 32484236e..6748f4ea8 100644 --- a/channels/tsmf/client/gstreamer/tsmf_platform.h +++ b/channels/tsmf/client/gstreamer/tsmf_platform.h @@ -59,25 +59,25 @@ typedef struct _TSMFGstreamerDecoder } TSMFGstreamerDecoder; -const char *get_type(TSMFGstreamerDecoder *mdecoder); +const char* get_type(TSMFGstreamerDecoder* mdecoder); -const char *tsmf_platform_get_video_sink(void); -const char *tsmf_platform_get_audio_sink(void); +const char* tsmf_platform_get_video_sink(void); +const char* tsmf_platform_get_audio_sink(void); -int tsmf_platform_create(TSMFGstreamerDecoder *decoder); -int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder); -int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder); -int tsmf_platform_free(TSMFGstreamerDecoder *decoder); +int tsmf_platform_create(TSMFGstreamerDecoder* decoder); +int tsmf_platform_set_format(TSMFGstreamerDecoder* decoder); +int tsmf_platform_register_handler(TSMFGstreamerDecoder* decoder); +int tsmf_platform_free(TSMFGstreamerDecoder* decoder); -int tsmf_window_create(TSMFGstreamerDecoder *decoder); -int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, +int tsmf_window_create(TSMFGstreamerDecoder* decoder); +int tsmf_window_resize(TSMFGstreamerDecoder* decoder, int x, int y, int width, int height, int nr_rect, RDP_RECT *visible); -int tsmf_window_destroy(TSMFGstreamerDecoder *decoder); +int tsmf_window_destroy(TSMFGstreamerDecoder* decoder); -int tsmf_window_pause(TSMFGstreamerDecoder *decoder); -int tsmf_window_resume(TSMFGstreamerDecoder *decoder); +int tsmf_window_pause(TSMFGstreamerDecoder* decoder); +int tsmf_window_resume(TSMFGstreamerDecoder* decoder); -BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder *mdecoder); -void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder *mdecoder); +BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder* mdecoder); +void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder* mdecoder); #endif diff --git a/channels/tsmf/client/tsmf_audio.c b/channels/tsmf/client/tsmf_audio.c index d03ebbcef..5b4e7fdb9 100644 --- a/channels/tsmf/client/tsmf_audio.c +++ b/channels/tsmf/client/tsmf_audio.c @@ -34,12 +34,12 @@ static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "audio", 0); - if (entry == NULL) + if (!entry) return NULL; audio = entry(); - if (audio == NULL) + if (!audio) { WLog_ERR(TAG, "failed to call export function in %s", name); return NULL; diff --git a/channels/tsmf/client/tsmf_decoder.c b/channels/tsmf/client/tsmf_decoder.c index 0067cd548..164e0d8be 100644 --- a/channels/tsmf/client/tsmf_decoder.c +++ b/channels/tsmf/client/tsmf_decoder.c @@ -32,41 +32,51 @@ #include "tsmf_constants.h" #include "tsmf_decoder.h" -static ITSMFDecoder *tsmf_load_decoder_by_name(const char *name, TS_AM_MEDIA_TYPE *media_type) +static ITSMFDecoder* tsmf_load_decoder_by_name(const char *name, TS_AM_MEDIA_TYPE *media_type) { - ITSMFDecoder *decoder; + ITSMFDecoder* decoder; TSMF_DECODER_ENTRY entry; + entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0); - if(entry == NULL) + + if (!entry) return NULL; + decoder = entry(); - if(decoder == NULL) + + if (!decoder) { WLog_ERR(TAG, "failed to call export function in %s", name); return NULL; } - if(!decoder->SetFormat(decoder, media_type)) + + if (!decoder->SetFormat(decoder, media_type)) { decoder->Free(decoder); decoder = NULL; } + return decoder; } -ITSMFDecoder *tsmf_load_decoder(const char *name, TS_AM_MEDIA_TYPE *media_type) +ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type) { - ITSMFDecoder *decoder = NULL; - if(name) + ITSMFDecoder* decoder = NULL; + + if (name) { decoder = tsmf_load_decoder_by_name(name, media_type); } + #if defined(WITH_GSTREAMER_1_0) || defined(WITH_GSTREAMER_0_10) - if(!decoder) + if (!decoder) decoder = tsmf_load_decoder_by_name("gstreamer", media_type); #endif + #if defined(WITH_FFMPEG) - if(!decoder) + if (!decoder) decoder = tsmf_load_decoder_by_name("ffmpeg", media_type); #endif + return decoder; } diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index 18c654b27..4d4dc7ea3 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -37,18 +37,22 @@ #include "tsmf_ifman.h" -int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN *ifman) +int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman) { UINT32 CapabilityValue; + Stream_Read_UINT32(ifman->input, CapabilityValue); + DEBUG_TSMF("server CapabilityValue %d", CapabilityValue); + Stream_EnsureRemainingCapacity(ifman->output, 8); Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */ Stream_Write_UINT32(ifman->output, 0); /* Result */ + return 0; } -int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman) +int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) { UINT32 i; UINT32 v; @@ -56,17 +60,20 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman) UINT32 CapabilityType; UINT32 cbCapabilityLength; UINT32 numHostCapabilities; + pos = Stream_GetPosition(ifman->output); Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4); Stream_Copy(ifman->output, ifman->input, ifman->input_size); Stream_SetPosition(ifman->output, pos); Stream_Read_UINT32(ifman->output, numHostCapabilities); - for(i = 0; i < numHostCapabilities; i++) + + for (i = 0; i < numHostCapabilities; i++) { Stream_Read_UINT32(ifman->output, CapabilityType); Stream_Read_UINT32(ifman->output, cbCapabilityLength); pos = Stream_GetPosition(ifman->output); - switch(CapabilityType) + + switch (CapabilityType) { case 1: /* Protocol version request */ Stream_Read_UINT32(ifman->output, v); @@ -76,8 +83,7 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman) Stream_Peek_UINT32(ifman->output, v); DEBUG_TSMF("server supported platform %d", v); /* Claim that we support both MF and DShow platforms. */ - Stream_Write_UINT32(ifman->output, - MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); + Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); break; default: WLog_ERR(TAG, "unknown capability type %d", CapabilityType); @@ -85,63 +91,81 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman) } Stream_SetPosition(ifman->output, pos + cbCapabilityLength); } + Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; + return 0; } -int tsmf_ifman_check_format_support_request(TSMF_IFMAN *ifman) +int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) { UINT32 numMediaType; UINT32 PlatformCookie; UINT32 FormatSupported = 1; + Stream_Read_UINT32(ifman->input, PlatformCookie); Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */ Stream_Read_UINT32(ifman->input, numMediaType); + DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType); - if(!tsmf_codec_check_media_type(ifman->input)) + + if (!tsmf_codec_check_media_type(ifman->input)) FormatSupported = 0; - if(FormatSupported) + + if (FormatSupported) DEBUG_TSMF("format ok."); + Stream_EnsureRemainingCapacity(ifman->output, 12); Stream_Write_UINT32(ifman->output, FormatSupported); Stream_Write_UINT32(ifman->output, PlatformCookie); Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; + return 0; } -int tsmf_ifman_on_new_presentation(TSMF_IFMAN *ifman) +int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman) { int status = 0; - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) { DEBUG_TSMF("Presentation already exists"); ifman->output_pending = FALSE; return 0; } + presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback); - if(presentation == NULL) + + if (!presentation) status = 1; else tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device); + ifman->output_pending = TRUE; + return status; } -int tsmf_ifman_add_stream(TSMF_IFMAN *ifman) +int tsmf_ifman_add_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; int status = 0; - TSMF_STREAM *stream; - TSMF_PRESENTATION *presentation; + TSMF_STREAM* stream; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, 16); - if(presentation == NULL) + + if (!presentation) { status = 1; } @@ -150,14 +174,14 @@ int tsmf_ifman_add_stream(TSMF_IFMAN *ifman) Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numMediaType */ stream = tsmf_stream_new(presentation, StreamId); - if(stream) + if (stream) tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input); } ifman->output_pending = TRUE; return status; } -int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman) +int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); Stream_EnsureRemainingCapacity(ifman->output, 8); @@ -167,16 +191,20 @@ int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman) return 0; } -int tsmf_ifman_remove_stream(TSMF_IFMAN *ifman) +int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman) { int status = 0; UINT32 StreamId; - TSMF_STREAM *stream; - TSMF_PRESENTATION *presentation; + TSMF_STREAM* stream; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); + Stream_Seek(ifman->input, 16); - if(presentation == NULL) + + if (!presentation) { status = 1; } @@ -184,12 +212,15 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN *ifman) { Stream_Read_UINT32(ifman->input, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId); - if(stream) + + if (stream) tsmf_stream_free(stream); else status = 1; } + ifman->output_pending = TRUE; + return status; } @@ -202,16 +233,20 @@ float tsmf_stream_read_float(wStream *s) return fValue; } -int tsmf_ifman_set_source_video_rect(TSMF_IFMAN *ifman) +int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman) { int status = 0; float Left, Top; float Right, Bottom; - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); + Stream_Seek(ifman->input, 16); - if(!presentation) + + if (!presentation) { status = 1; } @@ -224,31 +259,39 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN *ifman) DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f", Left, Top, Right, Bottom); } + ifman->output_pending = TRUE; + return status; } -int tsmf_ifman_shutdown_presentation(TSMF_IFMAN *ifman) +int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) tsmf_presentation_free(presentation); else WLog_ERR(TAG, "unknown presentation id"); + Stream_EnsureRemainingCapacity(ifman->output, 4); Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; + return 0; } -int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman) +int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; DEBUG_TSMF("on stream volume"); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) { UINT32 newVolume; UINT32 muted; @@ -263,16 +306,21 @@ int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman) { WLog_ERR(TAG, "unknown presentation id"); } + ifman->output_pending = TRUE; + return 0; } -int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman) +int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF("on channel volume"); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) { UINT32 channelVolume; UINT32 changedChannel; @@ -282,20 +330,22 @@ int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman) Stream_Read_UINT32(ifman->input, changedChannel); DEBUG_TSMF("on stream volume: changed channel=[%d]", changedChannel); } + ifman->output_pending = TRUE; + return 0; } -int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman) +int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); ifman->output_pending = TRUE; return 0; } -int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman) +int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; UINT32 numGeometryInfo; UINT32 Left; UINT32 Top; @@ -321,17 +371,17 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman) num_rects = cbVisibleRect / 16; DEBUG_TSMF("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d", numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects); - if(presentation == NULL) + if (presentation == NULL) { error = 1; } else { - if(num_rects > 0) + if (num_rects > 0) { - rects = (RDP_RECT *) malloc(sizeof(RDP_RECT) * num_rects); - ZeroMemory(rects, sizeof(RDP_RECT) * num_rects); - for(i = 0; i < num_rects; i++) + rects = (RDP_RECT*) calloc(num_rects, sizeof(RDP_RECT)); + + for (i = 0; i < num_rects; i++) { Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */ Stream_Seek_UINT16(ifman->input); @@ -347,36 +397,40 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman) rects[i].x, rects[i].y, rects[i].width, rects[i].height); } } + tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects); } + ifman->output_pending = TRUE; + return error; } -int tsmf_ifman_set_allocator(TSMF_IFMAN *ifman) +int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); ifman->output_pending = TRUE; return 0; } -int tsmf_ifman_notify_preroll(TSMF_IFMAN *ifman) +int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); ifman->output_pending = TRUE; return 0; } -int tsmf_ifman_on_sample(TSMF_IFMAN *ifman) +int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; - TSMF_STREAM *stream; + TSMF_PRESENTATION* presentation; + TSMF_STREAM* stream; UINT32 StreamId; UINT64 SampleStartTime; UINT64 SampleEndTime; UINT64 ThrottleDuration; UINT32 SampleExtensions; UINT32 cbData; + Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numSample */ @@ -386,62 +440,81 @@ int tsmf_ifman_on_sample(TSMF_IFMAN *ifman) Stream_Seek_UINT32(ifman->input); /* SampleFlags */ Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, cbData); + DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d " "ThrottleDuration %d SampleExtensions %d cbData %d", ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime, (int)ThrottleDuration, SampleExtensions, cbData); + presentation = tsmf_presentation_find_by_id(ifman->presentation_id); - if(presentation == NULL) + + if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); return 1; } + stream = tsmf_stream_find_by_id(presentation, StreamId); - if(stream == NULL) + + if (!stream) { WLog_ERR(TAG, "unknown stream id"); return 1; } + tsmf_stream_push_sample(stream, ifman->channel_callback, - ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, - cbData, Stream_Pointer(ifman->input)); + ifman->message_id, SampleStartTime, SampleEndTime, + ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input)); + tsmf_presentation_sync(presentation); ifman->output_pending = TRUE; + return 0; } -int tsmf_ifman_on_flush(TSMF_IFMAN *ifman) +int tsmf_ifman_on_flush(TSMF_IFMAN* ifman) { UINT32 StreamId; - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); + DEBUG_TSMF("StreamId %d", StreamId); + presentation = tsmf_presentation_find_by_id(ifman->presentation_id); - if(presentation == NULL) + + if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); return 1; } + tsmf_presentation_flush(presentation); ifman->output_pending = TRUE; + return 0; } -int tsmf_ifman_on_end_of_stream(TSMF_IFMAN *ifman) +int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; - TSMF_STREAM *stream; - TSMF_PRESENTATION *presentation; + TSMF_STREAM* stream; + TSMF_PRESENTATION* presentation; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); + Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); - if(presentation) + + if (presentation) { stream = tsmf_stream_find_by_id(presentation, StreamId); - if(stream) + + if (stream) tsmf_stream_end(stream); } + DEBUG_TSMF("StreamId %d", StreamId); Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ @@ -449,74 +522,93 @@ int tsmf_ifman_on_end_of_stream(TSMF_IFMAN *ifman) Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; + return 0; } -int tsmf_ifman_on_playback_started(TSMF_IFMAN *ifman) +int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) tsmf_presentation_start(presentation); else WLog_ERR(TAG, "unknown presentation id"); + Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; + return 0; } -int tsmf_ifman_on_playback_paused(TSMF_IFMAN *ifman) +int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); ifman->output_pending = TRUE; + /* Added pause control so gstreamer pipeline can be paused accordingly */ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) tsmf_presentation_paused(presentation); else WLog_ERR(TAG, "unknown presentation id"); + return 0; } -int tsmf_ifman_on_playback_restarted(TSMF_IFMAN *ifman) +int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); ifman->output_pending = TRUE; + /* Added restart control so gstreamer pipeline can be resumed accordingly */ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) tsmf_presentation_restarted(presentation); else WLog_ERR(TAG, "unknown presentation id"); + return 0; } -int tsmf_ifman_on_playback_stopped(TSMF_IFMAN *ifman) +int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman) { - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; + DEBUG_TSMF(""); + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if(presentation) + + if (presentation) tsmf_presentation_stop(presentation); else WLog_ERR(TAG, "unknown presentation id"); + Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; + return 0; } -int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN *ifman) +int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); Stream_EnsureRemainingCapacity(ifman->output, 16); diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 6548fe546..fe23cb04b 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -35,42 +35,55 @@ #include "tsmf_main.h" void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, - UINT32 message_id, UINT64 duration, UINT32 data_size) + UINT32 message_id, UINT64 duration, UINT32 data_size) { wStream *s; int status = -1; TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; + s = Stream_New(NULL, 32); + Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY); Stream_Write_UINT32(s, message_id); Stream_Write_UINT32(s, PLAYBACK_ACK); /* FunctionId */ Stream_Write_UINT32(s, callback->stream_id); /* StreamId */ Stream_Write_UINT64(s, duration); /* DataDuration */ Stream_Write_UINT64(s, data_size); /* cbData */ + DEBUG_TSMF("response size %d", (int) Stream_GetPosition(s)); - if(!callback || !callback->channel || !callback->channel->Write) + + if (!callback || !callback->channel || !callback->channel->Write) + { WLog_ERR(TAG, "callback=%p, channel=%p, write=%p", callback, callback->channel, callback->channel->Write); + } else + { status = callback->channel->Write(callback->channel, - Stream_GetPosition(s), Stream_Buffer(s), NULL); - if(status) + Stream_GetPosition(s), Stream_Buffer(s), NULL); + } + + if (status) { WLog_ERR(TAG, "response error %d", status); } + Stream_Free(s, TRUE); } -BOOL tsmf_push_event(IWTSVirtualChannelCallback *pChannelCallback, wMessage *event) +BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event) { int status; - TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; + TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; + status = callback->channel_mgr->PushEvent(callback->channel_mgr, event); - if(status) + + if (status) { WLog_ERR(TAG, "response error %d", status); return FALSE; } + return TRUE; } @@ -88,7 +101,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w UINT32 cbSize = Stream_GetRemainingLength(data); /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */ - if(cbSize < 12) + if (cbSize < 12) { WLog_ERR(TAG, "invalid size. cbSize=%d", cbSize); return 1; @@ -97,17 +110,19 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w input = data; output = Stream_New(NULL, 256); Stream_Seek(output, 8); - Stream_Read_UINT32(input, InterfaceId); - Stream_Read_UINT32(input, MessageId); - Stream_Read_UINT32(input, FunctionId); + Stream_Read_UINT32(input, InterfaceId); /* InterfaceId (4 bytes) */ + Stream_Read_UINT32(input, MessageId); /* MessageId (4 bytes) */ + Stream_Read_UINT32(input, FunctionId); /* FunctionId (4 bytes) */ + DEBUG_TSMF("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X", cbSize, InterfaceId, MessageId, FunctionId); - memset(&ifman, 0, sizeof(TSMF_IFMAN)); + + ZeroMemory(&ifman, sizeof(TSMF_IFMAN)); ifman.channel_callback = pChannelCallback; - ifman.decoder_name = ((TSMF_PLUGIN *) callback->plugin)->decoder_name; - ifman.audio_name = ((TSMF_PLUGIN *) callback->plugin)->audio_name; - ifman.audio_device = ((TSMF_PLUGIN *) callback->plugin)->audio_device; - memcpy(ifman.presentation_id, callback->presentation_id, GUID_SIZE); + ifman.decoder_name = ((TSMF_PLUGIN*) callback->plugin)->decoder_name; + ifman.audio_name = ((TSMF_PLUGIN*) callback->plugin)->audio_name; + ifman.audio_device = ((TSMF_PLUGIN*) callback->plugin)->audio_device; + CopyMemory(ifman.presentation_id, callback->presentation_id, GUID_SIZE); ifman.stream_id = callback->stream_id; ifman.message_id = MessageId; ifman.input = input; @@ -115,23 +130,30 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w ifman.output = output; ifman.output_pending = FALSE; ifman.output_interface_id = InterfaceId; - switch(InterfaceId) + + //fprintf(stderr, "InterfaceId: 0x%04X MessageId: 0x%04X FunctionId: 0x%04X\n", InterfaceId, MessageId, FunctionId); + + switch (InterfaceId) { case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE: - switch(FunctionId) + switch (FunctionId) { case RIM_EXCHANGE_CAPABILITY_REQUEST: status = tsmf_ifman_rim_exchange_capability_request(&ifman); break; + case RIMCALL_RELEASE: + case RIMCALL_QUERYINTERFACE: + break; default: break; } break; + case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY: - switch(FunctionId) + switch (FunctionId) { case SET_CHANNEL_PARAMS: - memcpy(callback->presentation_id, Stream_Pointer(input), GUID_SIZE); + CopyMemory(callback->presentation_id, Stream_Pointer(input), GUID_SIZE); Stream_Seek(input, GUID_SIZE); Stream_Read_UINT32(input, callback->stream_id); DEBUG_TSMF("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id); @@ -204,19 +226,24 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w case ON_PLAYBACK_RATE_CHANGED: status = tsmf_ifman_on_playback_rate_changed(&ifman); break; + case RIMCALL_RELEASE: + case RIMCALL_QUERYINTERFACE: + break; default: break; } break; + default: break; } input = NULL; ifman.input = NULL; - if(status == -1) + + if (status == -1) { - switch(FunctionId) + switch (FunctionId) { case RIMCALL_RELEASE: /* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE) @@ -230,15 +257,17 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w status = 0; break; } - if(status == -1) + + if (status == -1) { - WLog_ERR(TAG, "InterfaceId 0x%X FunctionId 0x%X not processed.", - InterfaceId, FunctionId); + WLog_ERR(TAG, "Unknown InterfaceId: 0x%04X MessageId: 0x%04X FunctionId: 0x%04X\n", InterfaceId, MessageId, FunctionId); /* When a request is not implemented we return empty response indicating error */ } + status = 0; } - if(status == 0 && !ifman.output_pending) + + if (status == 0 && !ifman.output_pending) { /* Response packet does not have FunctionId */ length = Stream_GetPosition(output); @@ -247,31 +276,37 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w Stream_Write_UINT32(output, MessageId); DEBUG_TSMF("response size %d", length); status = callback->channel->Write(callback->channel, length, Stream_Buffer(output), NULL); - if(status) + + if (status) { WLog_ERR(TAG, "response error %d", status); } } + Stream_Free(output, TRUE); return status; } static int tsmf_on_close(IWTSVirtualChannelCallback *pChannelCallback) { - TSMF_STREAM *stream; - TSMF_PRESENTATION *presentation; - TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; + TSMF_STREAM* stream; + TSMF_PRESENTATION* presentation; + TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; + DEBUG_TSMF(""); - if(callback->stream_id) + + if (callback->stream_id) { presentation = tsmf_presentation_find_by_id(callback->presentation_id); - if(presentation) + + if (presentation) { stream = tsmf_stream_find_by_id(presentation, callback->stream_id); - if(stream) + if (stream) tsmf_stream_free(stream); } } + free(pChannelCallback); return 0; } @@ -354,13 +389,13 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; - status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv, + status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, tsmf_args, flags, tsmf, NULL, NULL); arg = tsmf_args; do { - if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) + if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "audio") @@ -380,7 +415,7 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) } CommandLineSwitchEnd(arg) } - while((arg = CommandLineFindNextArgumentA(arg)) != NULL); + while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); } #ifdef STATIC_CHANNELS diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index 429bb2b17..effd1b247 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -22,8 +22,6 @@ #include "config.h" #endif -#include - #include #include #include @@ -87,7 +85,7 @@ struct _TSMF_STREAM { UINT32 stream_id; - TSMF_PRESENTATION *presentation; + TSMF_PRESENTATION* presentation; ITSMFDecoder *decoder; @@ -127,7 +125,7 @@ struct _TSMF_SAMPLE UINT32 decoded_size; UINT32 pixfmt; - TSMF_STREAM *stream; + TSMF_STREAM* stream; IWTSVirtualChannelCallback *channel_callback; UINT64 ack_time; }; @@ -135,8 +133,8 @@ struct _TSMF_SAMPLE static wArrayList *presentation_list = NULL; static int TERMINATING = 0; -static void _tsmf_presentation_free(TSMF_PRESENTATION *presentation); -static void _tsmf_stream_free(TSMF_STREAM *stream); +static void _tsmf_presentation_free(TSMF_PRESENTATION* presentation); +static void _tsmf_stream_free(TSMF_STREAM* stream); static UINT64 get_current_time(void) { @@ -145,15 +143,17 @@ static UINT64 get_current_time(void) return ((UINT64)tp.tv_sec) * 10000000LL + ((UINT64)tp.tv_usec) * 10LL; } -static TSMF_SAMPLE *tsmf_stream_pop_sample(TSMF_STREAM *stream, int sync) +static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync) { UINT32 index; UINT32 count; TSMF_STREAM *s; - TSMF_SAMPLE *sample; + TSMF_SAMPLE* sample; BOOL pending = FALSE; - TSMF_PRESENTATION *presentation = stream->presentation; - assert(stream); + TSMF_PRESENTATION* presentation = stream->presentation; + + if (!stream) + return NULL; if (Queue_Count(stream->sample_list) < 1) return NULL; @@ -211,8 +211,10 @@ static TSMF_SAMPLE *tsmf_stream_pop_sample(TSMF_STREAM *stream, int sync) static void tsmf_sample_free(void *arg) { - TSMF_SAMPLE *sample = arg; - assert(sample); + TSMF_SAMPLE* sample = arg; + + if (!sample) + return; if (sample->data) free(sample->data); @@ -222,26 +224,35 @@ static void tsmf_sample_free(void *arg) static void tsmf_sample_ack(TSMF_SAMPLE* sample) { - assert(sample); + if (!sample) + return; + tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size); } static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample) { - assert(sample); - assert(sample->stream); + if (!sample) + return; + + if (!sample->stream) + return; + Queue_Enqueue(sample->stream->sample_ack_list, sample); } -static BOOL tsmf_stream_process_ack(void *arg, BOOL force) +static BOOL tsmf_stream_process_ack(void* arg, BOOL force) { - TSMF_STREAM *stream = arg; - TSMF_SAMPLE *sample; + TSMF_STREAM* stream = arg; + TSMF_SAMPLE* sample; UINT64 ack_time; BOOL rc = FALSE; - assert(stream); + + if (!stream) + return FALSE; + Queue_Lock(stream->sample_ack_list); - sample = (TSMF_SAMPLE *) Queue_Peek(stream->sample_ack_list); + sample = (TSMF_SAMPLE*) Queue_Peek(stream->sample_ack_list); if (!sample) goto finally; @@ -257,17 +268,20 @@ static BOOL tsmf_stream_process_ack(void *arg, BOOL force) sample = Queue_Dequeue(stream->sample_ack_list); tsmf_sample_ack(sample); tsmf_sample_free(sample); + finally: Queue_Unlock(stream->sample_ack_list); return rc; } -TSMF_PRESENTATION* tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback) +TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback) { - TSMF_PRESENTATION *presentation; - assert(guid); - assert(pChannelCallback); - presentation = (TSMF_PRESENTATION *) calloc(1, sizeof(TSMF_PRESENTATION)); + TSMF_PRESENTATION* presentation; + + if (!guid || !pChannelCallback) + return NULL; + + presentation = (TSMF_PRESENTATION*) calloc(1, sizeof(TSMF_PRESENTATION)); if (!presentation) { @@ -280,15 +294,18 @@ TSMF_PRESENTATION* tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCal presentation->volume = 5000; /* 50% */ presentation->stream_list = ArrayList_New(TRUE); ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_stream_free; + ArrayList_Add(presentation_list, presentation); + return presentation; } -static char *guid_to_string(const BYTE *guid, char *str, size_t len) +static char* guid_to_string(const BYTE* guid, char* str, size_t len) { int i; - assert(guid); - assert(str); + + if (!guid || !str) + return NULL; for (i=0; i 2*i; i++) snprintf(str + (2*i), len - 2*i, "%02X", guid[i]); @@ -296,19 +313,20 @@ static char *guid_to_string(const BYTE *guid, char *str, size_t len) return str; } -TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid) +TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE *guid) { - char guid_str[GUID_SIZE * 2 + 1]; UINT32 index; UINT32 count; BOOL found = FALSE; - TSMF_PRESENTATION *presentation; + char guid_str[GUID_SIZE * 2 + 1]; + TSMF_PRESENTATION* presentation; + ArrayList_Lock(presentation_list); count = ArrayList_Count(presentation_list); for (index = 0; index < count; index++) { - presentation = (TSMF_PRESENTATION *) ArrayList_GetItem(presentation_list, index); + presentation = (TSMF_PRESENTATION*) ArrayList_GetItem(presentation_list, index); if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0) { @@ -415,10 +433,11 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) } } -static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample) +static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample) { UINT64 latency = 0; - TSMF_STREAM *stream = sample->stream; + TSMF_STREAM* stream = sample->stream; + DEBUG_TSMF("MessageId %d EndTime %d consumed.", sample->sample_id, (int)sample->end_time); @@ -442,21 +461,25 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample) stream->presentation->audio_end_time = sample->end_time + latency; } -static void tsmf_sample_playback(TSMF_SAMPLE *sample) +static void tsmf_sample_playback(TSMF_SAMPLE* sample) { BOOL ret = FALSE; UINT32 width; UINT32 height; UINT32 pixfmt = 0; - TSMF_STREAM *stream = sample->stream; + TSMF_STREAM* stream = sample->stream; if (stream->decoder) { if (stream->decoder->DecodeEx) + { ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size, sample->extensions, - sample->start_time, sample->end_time, sample->duration); + sample->start_time, sample->end_time, sample->duration); + } else + { ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions); + } } if (!ret) @@ -483,7 +506,7 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample) sample->pixfmt = pixfmt; } - ret = FALSE ; + ret = FALSE; if (stream->decoder->GetDecodedDimension) { @@ -517,7 +540,7 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample) } else { - TSMF_STREAM *stream = sample->stream; + TSMF_STREAM* stream = sample->stream; UINT64 ack_anticipation_time = get_current_time(); UINT64 currentRunningTime = sample->start_time; BOOL buffer_filled = TRUE; @@ -548,7 +571,9 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample) } } else + { ack_anticipation_time += sample->duration / 2; + } switch (sample->stream->major_type) { @@ -568,11 +593,12 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample) } } -static void *tsmf_stream_ack_func(void *arg) +static void* tsmf_stream_ack_func(void *arg) { - TSMF_STREAM *stream = (TSMF_STREAM *) arg; HANDLE hdl[2]; + TSMF_STREAM* stream = (TSMF_STREAM*) arg; DEBUG_TSMF("in %d", stream->stream_id); + hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_ack_list); @@ -598,12 +624,13 @@ static void *tsmf_stream_ack_func(void *arg) return NULL; } -static void *tsmf_stream_playback_func(void *arg) +static void* tsmf_stream_playback_func(void *arg) { HANDLE hdl[2]; - TSMF_SAMPLE *sample; - TSMF_STREAM *stream = (TSMF_STREAM *) arg; - TSMF_PRESENTATION *presentation = stream->presentation; + TSMF_SAMPLE* sample; + TSMF_STREAM* stream = (TSMF_STREAM *) arg; + TSMF_PRESENTATION* presentation = stream->presentation; + DEBUG_TSMF("in %d", stream->stream_id); if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && @@ -614,13 +641,12 @@ static void *tsmf_stream_playback_func(void *arg) if (stream->decoder->GetDecodedData) { stream->audio = tsmf_load_audio_device( - presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL, - presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL); + presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL, + presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL); if (stream->audio) { - stream->audio->SetFormat(stream->audio, - stream->sample_rate, stream->channels, stream->bits_per_sample); + stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels, stream->bits_per_sample); } } } @@ -648,7 +674,7 @@ static void *tsmf_stream_playback_func(void *arg) return NULL; } -static void tsmf_stream_start(TSMF_STREAM *stream) +static void tsmf_stream_start(TSMF_STREAM* stream) { if (!stream || !stream->presentation || !stream->decoder) return; @@ -659,7 +685,7 @@ static void tsmf_stream_start(TSMF_STREAM *stream) } } -static void tsmf_stream_stop(TSMF_STREAM *stream) +static void tsmf_stream_stop(TSMF_STREAM* stream) { if (!stream || !stream->decoder) return; @@ -670,7 +696,7 @@ static void tsmf_stream_stop(TSMF_STREAM *stream) } } -static void tsmf_stream_pause(TSMF_STREAM *stream) +static void tsmf_stream_pause(TSMF_STREAM* stream) { if (!stream || !stream->decoder) return; @@ -681,7 +707,7 @@ static void tsmf_stream_pause(TSMF_STREAM *stream) } } -static void tsmf_stream_restart(TSMF_STREAM *stream) +static void tsmf_stream_restart(TSMF_STREAM* stream) { if (!stream || !stream->decoder) return; @@ -692,7 +718,7 @@ static void tsmf_stream_restart(TSMF_STREAM *stream) } } -static void tsmf_stream_change_volume(TSMF_STREAM *stream, UINT32 newVolume, UINT32 muted) +static void tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted) { if (!stream || !stream->decoder) return; @@ -707,11 +733,11 @@ static void tsmf_stream_change_volume(TSMF_STREAM *stream, UINT32 newVolume, UIN } } -void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted) +void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; presentation->volume = newVolume; presentation->muted = muted; ArrayList_Lock(presentation->stream_list); @@ -726,11 +752,11 @@ void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 ne ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_paused(TSMF_PRESENTATION *presentation) +void tsmf_presentation_paused(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); @@ -743,11 +769,11 @@ void tsmf_presentation_paused(TSMF_PRESENTATION *presentation) ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation) +void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); @@ -760,11 +786,11 @@ void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation) ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_start(TSMF_PRESENTATION *presentation) +void tsmf_presentation_start(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); @@ -777,7 +803,7 @@ void tsmf_presentation_start(TSMF_PRESENTATION *presentation) ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_sync(TSMF_PRESENTATION *presentation) +void tsmf_presentation_sync(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; @@ -786,18 +812,18 @@ void tsmf_presentation_sync(TSMF_PRESENTATION *presentation) for (index = 0; index < count; index++) { - TSMF_STREAM *stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); + TSMF_STREAM* stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); WaitForSingleObject(stream->ready, 500); } ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_stop(TSMF_PRESENTATION *presentation) +void tsmf_presentation_stop(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; tsmf_presentation_flush(presentation); ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); @@ -811,12 +837,12 @@ void tsmf_presentation_stop(TSMF_PRESENTATION *presentation) ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation, +void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT *rects) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; /* The server may send messages with invalid width / height. * Ignore those messages. */ @@ -839,7 +865,7 @@ void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation, presentation->rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects); if (presentation->rects) - memcpy(presentation->rects, rects, sizeof(RDP_RECT) * num_rects); + CopyMemory(presentation->rects, rects, sizeof(RDP_RECT) * num_rects); ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); @@ -860,13 +886,13 @@ void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation, ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation, const char *name, const char *device) +void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char *name, const char *device) { presentation->audio_name = name; presentation->audio_device = device; } -static void tsmf_stream_flush(TSMF_STREAM *stream) +static void tsmf_stream_flush(TSMF_STREAM* stream) { //TSMF_SAMPLE* sample; /* TODO: free lists */ @@ -884,17 +910,17 @@ static void tsmf_stream_flush(TSMF_STREAM *stream) } } -void tsmf_presentation_flush(TSMF_PRESENTATION *presentation) +void tsmf_presentation_flush(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; - TSMF_STREAM *stream; + TSMF_STREAM* stream; ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); for (index = 0; index < count; index++) { - stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); + stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index); tsmf_stream_flush(stream); } @@ -904,7 +930,7 @@ void tsmf_presentation_flush(TSMF_PRESENTATION *presentation) presentation->audio_end_time = 0; } -void _tsmf_presentation_free(TSMF_PRESENTATION *presentation) +void _tsmf_presentation_free(TSMF_PRESENTATION* presentation) { tsmf_presentation_stop(presentation); ArrayList_Clear(presentation->stream_list); @@ -913,18 +939,18 @@ void _tsmf_presentation_free(TSMF_PRESENTATION *presentation) if (presentation->rects) free(presentation->rects); - memset(presentation, 0, sizeof(TSMF_PRESENTATION)); + ZeroMemory(presentation, sizeof(TSMF_PRESENTATION)); free(presentation); } -void tsmf_presentation_free(TSMF_PRESENTATION *presentation) +void tsmf_presentation_free(TSMF_PRESENTATION* presentation) { ArrayList_Remove(presentation_list, presentation); } -TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id) +TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id) { - TSMF_STREAM *stream; + TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) @@ -933,7 +959,7 @@ TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id) return NULL; } - stream = (TSMF_STREAM *) calloc(1, sizeof(TSMF_STREAM)); + stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { @@ -949,26 +975,27 @@ TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id) stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_ack_list = Queue_New(TRUE, -1, -1); stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free; - stream->play_thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE)tsmf_stream_playback_func, stream, 0, NULL); - stream->ack_thread = CreateThread(NULL, 0, - (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL); + stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, 0, NULL); + stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL); + ArrayList_Add(presentation->stream_list, stream); + return stream; } -TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id) +TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id) { UINT32 index; UINT32 count; BOOL found = FALSE; - TSMF_STREAM *stream; + TSMF_STREAM* stream; + ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); for (index = 0; index < count; index++) { - stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index); + stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index); if (stream->stream_id == stream_id) { @@ -983,11 +1010,11 @@ TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stre static void tsmf_stream_resync(void *arg) { - TSMF_STREAM *stream = arg; + TSMF_STREAM* stream = arg; ResetEvent(stream->ready); } -void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s) +void tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s) { TS_AM_MEDIA_TYPE mediatype; @@ -1035,16 +1062,20 @@ void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s) stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream); } -void tsmf_stream_end(TSMF_STREAM *stream) +void tsmf_stream_end(TSMF_STREAM* stream) { - assert(stream); + if (!stream) + return; + stream->eos = 1; stream->presentation->eos = 1; } -void _tsmf_stream_free(TSMF_STREAM *stream) +void _tsmf_stream_free(TSMF_STREAM* stream) { - assert(stream); + if (!stream) + return; + tsmf_stream_stop(stream); tsmf_stream_flush(stream); SetEvent(stream->stopEvent); @@ -1074,27 +1105,27 @@ void _tsmf_stream_free(TSMF_STREAM *stream) CloseHandle(stream->stopEvent); CloseHandle(stream->ready); - memset(stream, 0, sizeof(TSMF_STREAM)); + ZeroMemory(stream, sizeof(TSMF_STREAM)); free(stream); } -void tsmf_stream_free(TSMF_STREAM *stream) +void tsmf_stream_free(TSMF_STREAM* stream) { - TSMF_PRESENTATION *presentation = stream->presentation; + TSMF_PRESENTATION* presentation = stream->presentation; ArrayList_Remove(presentation->stream_list, stream); } -void tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback, - UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions, - UINT32 data_size, BYTE *data) +void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pChannelCallback, + UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions, + UINT32 data_size, BYTE *data) { - TSMF_SAMPLE *sample; + TSMF_SAMPLE* sample; SetEvent(stream->ready); if (TERMINATING) return; - sample = (TSMF_SAMPLE *) calloc(1, sizeof(TSMF_SAMPLE)); + sample = (TSMF_SAMPLE*) calloc(1, sizeof(TSMF_SAMPLE)); if (!sample) { diff --git a/client/X11/xf_tsmf.c b/client/X11/xf_tsmf.c index 15b9fd58d..efe71f982 100644 --- a/client/X11/xf_tsmf.c +++ b/client/X11/xf_tsmf.c @@ -21,9 +21,7 @@ #include "config.h" #endif -#include -#include -#include +#include #include #include @@ -33,8 +31,6 @@ #include #include -#include - #include #include #include @@ -179,7 +175,7 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV /* Y */ if (image->pitches[0] == vevent->frame_width) { - memcpy(image->data + image->offsets[0], + CopyMemory(image->data + image->offsets[0], vevent->frame_data, vevent->frame_width * vevent->frame_height); } @@ -187,7 +183,7 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV { for (i = 0; i < vevent->frame_height; i++) { - memcpy(image->data + image->offsets[0] + i * image->pitches[0], + CopyMemory(image->data + image->offsets[0] + i * image->pitches[0], vevent->frame_data + i * vevent->frame_width, vevent->frame_width); } @@ -209,10 +205,10 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV } if (image->pitches[1] * 2 == vevent->frame_width) { - memcpy(image->data + image->offsets[1], + CopyMemory(image->data + image->offsets[1], data1, vevent->frame_width * vevent->frame_height / 4); - memcpy(image->data + image->offsets[2], + CopyMemory(image->data + image->offsets[2], data2, vevent->frame_width * vevent->frame_height / 4); } @@ -220,10 +216,10 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV { for (i = 0; i < vevent->frame_height / 2; i++) { - memcpy(image->data + image->offsets[1] + i * image->pitches[1], + CopyMemory(image->data + image->offsets[1] + i * image->pitches[1], data1 + i * vevent->frame_width / 2, vevent->frame_width / 2); - memcpy(image->data + image->offsets[2] + i * image->pitches[2], + CopyMemory(image->data + image->offsets[2] + i * image->pitches[2], data2 + i * vevent->frame_width / 2, vevent->frame_width / 2); } @@ -231,7 +227,7 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV break; default: - memcpy(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ? + CopyMemory(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ? image->data_size : vevent->frame_size); break; } @@ -260,7 +256,6 @@ void xf_process_tsmf_event(xfContext* xfc, wMessage* event) switch (GetMessageType(event->id)) { case TsmfChannel_VideoFrame: - fprintf(stderr, "TsmfVideoFrame\n"); xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event); break; } @@ -352,10 +347,10 @@ void xf_tsmf_init(xfContext* xfc, long xv_port) WLog_DBG(TAG, "xf_tsmf_init: pixel format "); #endif fo = XvListImageFormats(xfc->display, xv->xv_port, &ret); + if (ret > 0) { - xv->xv_pixfmts = (UINT32*) malloc((ret + 1) * sizeof(UINT32)); - ZeroMemory(xv->xv_pixfmts, (ret + 1) * sizeof(UINT32)); + xv->xv_pixfmts = (UINT32*) calloc((ret + 1), sizeof(UINT32)); for (i = 0; i < ret; i++) { From a8ceed9dda9f6904b9cb715df7a9e8cbadced3b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Nov 2014 14:18:23 -0500 Subject: [PATCH 13/17] channels/tsmf: integrate pull request #2012 --- channels/tsmf/client/tsmf_codec.c | 65 +++++++++++++++++++++------ channels/tsmf/client/tsmf_codec.h | 2 +- channels/tsmf/client/tsmf_constants.h | 7 +++ channels/tsmf/client/tsmf_ifman.c | 2 +- 4 files changed, 61 insertions(+), 15 deletions(-) diff --git a/channels/tsmf/client/tsmf_codec.c b/channels/tsmf/client/tsmf_codec.c index 5657a8dd0..e4ae51a30 100644 --- a/channels/tsmf/client/tsmf_codec.c +++ b/channels/tsmf/client/tsmf_codec.c @@ -22,13 +22,11 @@ #include "config.h" #endif -#include -#include -#include - +#include #include #include +#include "tsmf_decoder.h" #include "tsmf_constants.h" #include "tsmf_types.h" @@ -176,40 +174,64 @@ static const TSMFMediaTypeMap tsmf_sub_type_map[] = }, /* E436EB81-524F-11CE-9F53-0020AF0BA770 */ - /* { { 0x81, 0xEB, 0x36, 0xE4, 0x4F, 0x52, 0xCE, 0x11, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 }, "MEDIASUBTYPE_MP1V", TSMF_SUB_TYPE_MP1V }, - */ /* 00000050-0000-0010-8000-00AA00389B71 */ - /* { { 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_MP1A", TSMF_SUB_TYPE_MP1A }, - */ /* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */ - /* { { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA }, "MEDIASUBTYPE_DOLBY_AC3", TSMF_SUB_TYPE_AC3 }, - */ /* 32595559-0000-0010-8000-00AA00389B71 */ - /* { { 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 }, "MEDIASUBTYPE_YUY2", TSMF_SUB_TYPE_YUY2 }, - */ + + /* Opencodec IDS */ + { + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}, + "MEDIASUBTYPE_FLAC", + TSMF_SUB_TYPE_FLAC + }, + + { + {0x61, 0x34, 0x70, 0x6D, 0x7A, 0x76, 0x4D, 0x49, 0xB4, 0x78, 0xF2, 0x9D, 0x25, 0xDC, 0x90, 0x37}, + "MEDIASUBTYPE_OGG", + TSMF_SUB_TYPE_OGG + }, + + { + {0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}, + "MEDIASUBTYPE_H263", + TSMF_SUB_TYPE_H263 + }, + + /* WebMMF codec IDS */ + { + {0x56, 0x50, 0x38, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71}, + "MEDIASUBTYPE_VP8", + TSMF_SUB_TYPE_VP8 + }, + + { + {0x0B, 0xD1, 0x2F, 0x8D, 0x41, 0x58, 0x6B, 0x4A, 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE, 0xD9}, + "MEDIASUBTYPE_OGG", + TSMF_SUB_TYPE_OGG + }, { { 0 }, @@ -525,13 +547,30 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s) return ret; } -BOOL tsmf_codec_check_media_type(wStream* s) +BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s) { BYTE* m; BOOL ret; TS_AM_MEDIA_TYPE mediatype; + Stream_GetPointer(s, m); ret = tsmf_codec_parse_media_type(&mediatype, s); Stream_SetPointer(s, m); + + if (ret) + { + ITSMFDecoder* decoder = tsmf_load_decoder(decoder_name, &mediatype); + + if (!decoder) + { + WLog_WARN(TAG, "Format not supported by decoder %s", decoder_name); + ret = FALSE; + } + else + { + decoder->Free(decoder); + } + } + return ret; } diff --git a/channels/tsmf/client/tsmf_codec.h b/channels/tsmf/client/tsmf_codec.h index 5fc3a0a13..0dd419837 100644 --- a/channels/tsmf/client/tsmf_codec.h +++ b/channels/tsmf/client/tsmf_codec.h @@ -23,7 +23,7 @@ #include "tsmf_types.h" BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s); -BOOL tsmf_codec_check_media_type(wStream* s); +BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s); #endif diff --git a/channels/tsmf/client/tsmf_constants.h b/channels/tsmf/client/tsmf_constants.h index 4e3a666a5..1fee13a67 100644 --- a/channels/tsmf/client/tsmf_constants.h +++ b/channels/tsmf/client/tsmf_constants.h @@ -118,6 +118,13 @@ #define TSMF_SUB_TYPE_MP43 17 #define TSMF_SUB_TYPE_MP4S 18 #define TSMF_SUB_TYPE_MP42 19 +#define TSMF_SUB_TYPE_OGG 20 +#define TSMF_SUB_TYPE_SPEEX 21 +#define TSMF_SUB_TYPE_THEORA 22 +#define TSMF_SUB_TYPE_FLAC 23 +#define TSMF_SUB_TYPE_VP8 24 +#define TSMF_SUB_TYPE_VP9 25 +#define TSMF_SUB_TYPE_H263 26 /* FormatType */ #define TSMF_FORMAT_TYPE_UNKNOWN 0 diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index 4d4dc7ea3..a982efdd0 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -110,7 +110,7 @@ int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType); - if (!tsmf_codec_check_media_type(ifman->input)) + if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input)) FormatSupported = 0; if (FormatSupported) From edd4aa797cf629b1d69552dc08444ae22a2f8e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Nov 2014 16:23:04 -0500 Subject: [PATCH 14/17] xfreerdp/tsmf: migrate to callback interface --- channels/tsmf/client/tsmf_main.c | 17 +- channels/tsmf/client/tsmf_main.h | 1 + channels/tsmf/client/tsmf_media.c | 2 +- client/X11/xf_channels.c | 9 + client/X11/xf_channels.h | 1 + client/X11/xf_client.c | 4 +- client/X11/xf_tsmf.c | 375 +++++++++++++++++++++++++----- client/X11/xf_tsmf.h | 5 +- client/X11/xfreerdp.h | 1 + 9 files changed, 348 insertions(+), 67 deletions(-) diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index fe23cb04b..fc8d7a215 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -341,6 +341,7 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallbac static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { + int status; TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin; DEBUG_TSMF(""); @@ -354,8 +355,12 @@ static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager tsmf->listener_callback->plugin = pPlugin; tsmf->listener_callback->channel_mgr = pChannelMgr; - return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0, - (IWTSListenerCallback*) tsmf->listener_callback, NULL); + status = pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0, + (IWTSListenerCallback*) tsmf->listener_callback, &(tsmf->listener)); + + tsmf->listener->pInterface = tsmf->iface.pInterface; + + return status; } static int tsmf_plugin_terminated(IWTSPlugin* pPlugin) @@ -442,15 +447,17 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) tsmf->iface.Disconnected = NULL; tsmf->iface.Terminated = tsmf_plugin_terminated; - status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf); - context = (TsmfClientContext*) calloc(1, sizeof(TsmfClientContext)); - context->handle = (void*) context; + if (!context) + return -1; + context->handle = (void*) tsmf; tsmf->iface.pInterface = (void*) context; tsmf_media_init(); + + status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf); } if (status == 0) diff --git a/channels/tsmf/client/tsmf_main.h b/channels/tsmf/client/tsmf_main.h index bc265da52..e11820fa3 100644 --- a/channels/tsmf/client/tsmf_main.h +++ b/channels/tsmf/client/tsmf_main.h @@ -50,6 +50,7 @@ struct _TSMF_PLUGIN { IWTSPlugin iface; + IWTSListener* listener; TSMF_LISTENER_CALLBACK* listener_callback; const char* decoder_name; diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index effd1b247..446dfd726 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -352,7 +352,7 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) TsmfClientContext* tsmf = (TsmfClientContext*) callback->plugin->pInterface; DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.", - sample->sample_id, (int)sample->end_time, sample->data_size); + sample->sample_id, (int) sample->end_time, sample->data_size); if (sample->data) { diff --git a/client/X11/xf_channels.c b/client/X11/xf_channels.c index dc787bde6..9fb8d595b 100644 --- a/client/X11/xf_channels.c +++ b/client/X11/xf_channels.c @@ -27,6 +27,7 @@ #include "xfreerdp.h" #include "xf_gfx.h" +#include "xf_tsmf.h" #include "xf_cliprdr.h" void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e) @@ -38,6 +39,10 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven { xfc->rdpei = (RdpeiClientContext*) e->pInterface; } + else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0) + { + xf_tsmf_init(xfc, (TsmfClientContext*) e->pInterface); + } else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { if (settings->SoftwareGdi) @@ -64,6 +69,10 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect { xfc->rdpei = NULL; } + else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0) + { + xf_tsmf_uninit(xfc, (TsmfClientContext*) e->pInterface); + } else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0) { if (settings->SoftwareGdi) diff --git a/client/X11/xf_channels.h b/client/X11/xf_channels.h index 96fd3e52d..18db6c532 100644 --- a/client/X11/xf_channels.h +++ b/client/X11/xf_channels.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 7ca8c1a83..4c8fadec8 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -104,7 +104,6 @@ #include #define TAG CLIENT_TAG("x11") -static long xv_port = 0; static const size_t password_size = 512; void xf_transform_window(xfContext *xfc) @@ -1020,7 +1019,6 @@ BOOL xf_post_connect(freerdp *instance) xfc->clipboard = xf_clipboard_new(xfc); freerdp_channels_post_connect(channels, instance); - xf_tsmf_init(xfc, xv_port); EventArgsInit(&e, "xfreerdp"); e.width = settings->DesktopWidth; @@ -1195,7 +1193,7 @@ void xf_window_free(xfContext *xfc) if (xfc->xv_context) { - xf_tsmf_uninit(xfc); + xf_tsmf_uninit(xfc, NULL); xfc->xv_context = NULL; } diff --git a/client/X11/xf_tsmf.c b/client/X11/xf_tsmf.c index efe71f982..9bd448a0c 100644 --- a/client/X11/xf_tsmf.c +++ b/client/X11/xf_tsmf.c @@ -42,7 +42,7 @@ #include #include -typedef struct xf_xv_context xfXvContext; +static long xv_port = 0; struct xf_xv_context { @@ -53,13 +53,9 @@ struct xf_xv_context char* xv_shmaddr; UINT32* xv_pixfmts; }; +typedef struct xf_xv_context xfXvContext; #define TAG CLIENT_TAG("x11") -#ifdef WITH_DEBUG_XV -#define DEBUG_XV(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__) -#else -#define DEBUG_XV(fmt, ...) do { } while (0) -#endif static BOOL xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt) { @@ -77,7 +73,7 @@ static BOOL xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt) return FALSE; } -static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EVENT* vevent) +static int xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EVENT* vevent) { int i; BYTE* data1; @@ -91,11 +87,13 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV xfXvContext* xv = (xfXvContext*) xfc->xv_context; if (xv->xv_port == 0) - return; + return -1001; /* In case the player is minimized */ - if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects <= 0) - return; + if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects < 0) + { + return -1002; + } if (xv->xv_colorkey_atom != None) { @@ -104,19 +102,36 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV XSetFillStyle(xfc->display, xfc->gc, FillSolid); XSetForeground(xfc->display, xfc->gc, colorkey); - for (i = 0; i < vevent->num_visible_rects; i++) + if (vevent->num_visible_rects < 1) { - XFillRectangle(xfc->display, xfc->window->handle, xfc->gc, - vevent->x + vevent->visible_rects[i].x, - vevent->y + vevent->visible_rects[i].y, - vevent->visible_rects[i].width, - vevent->visible_rects[i].height); + XSetClipMask(xfc->display, xfc->gc, None); + } + else + { + for (i = 0; i < vevent->num_visible_rects; i++) + { + XFillRectangle(xfc->display, xfc->window->handle, xfc->gc, + vevent->x + vevent->visible_rects[i].x, + vevent->y + vevent->visible_rects[i].y, + vevent->visible_rects[i].width, + vevent->visible_rects[i].height); + } } } else { - XSetClipRectangles(xfc->display, xfc->gc, vevent->x, vevent->y, - (XRectangle*) vevent->visible_rects, vevent->num_visible_rects, YXBanded); + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + if (vevent->num_visible_rects < 1) + { + XSetClipMask(xfc->display, xfc->gc, None); + } + else + { + XSetClipRectangles(xfc->display, xfc->gc, vevent->x, vevent->y, + (XRectangle*) vevent->visible_rects, vevent->num_visible_rects, YXBanded); + } } pixfmt = vevent->frame_pixfmt; @@ -137,8 +152,8 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV } else { - DEBUG_XV("pixel format 0x%X not supported by hardware.", pixfmt); - return; + WLog_DBG(TAG, "pixel format 0x%X not supported by hardware.", pixfmt); + return -1003; } image = XvShmCreateImage(xfc->display, xv->xv_port, @@ -151,10 +166,12 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV shmdt(xv->xv_shmaddr); shmctl(xv->xv_shmid, IPC_RMID, NULL); } + xv->xv_image_size = image->data_size; xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777); xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0); } + shminfo.shmid = xv->xv_shmid; shminfo.shmaddr = image->data = xv->xv_shmaddr; shminfo.readOnly = FALSE; @@ -162,8 +179,8 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV if (!XShmAttach(xfc->display, &shminfo)) { XFree(image); - DEBUG_XV("XShmAttach failed."); - return; + WLog_DBG(TAG, "XShmAttach failed."); + return -1004; } /* The video driver may align each line to a different size @@ -190,7 +207,7 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV } /* UV */ /* Conversion between I420 and YV12 is to simply swap U and V */ - if (converti420yv12 == FALSE) + if (!converti420yv12) { data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height; data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height + @@ -203,6 +220,7 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV vevent->frame_width * vevent->frame_height / 4; image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420; } + if (image->pitches[1] * 2 == vevent->frame_width) { CopyMemory(image->data + image->offsets[1], @@ -232,36 +250,250 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV break; } - XvShmPutImage(xfc->display, xv->xv_port, xfc->window->handle, xfc->gc, image, - 0, 0, image->width, image->height, - vevent->x, vevent->y, vevent->width, vevent->height, FALSE); + XvShmPutImage(xfc->display, xv->xv_port, xfc->window->handle, xfc->gc, + image, 0, 0, image->width, image->height, + vevent->x, vevent->y, vevent->width, vevent->height, FALSE); + if (xv->xv_colorkey_atom == None) XSetClipMask(xfc->display, xfc->gc, None); + XSync(xfc->display, FALSE); XShmDetach(xfc->display, &shminfo); XFree(image); -} - -int xf_tsmf_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT* event) -{ - //xfContext* xfc = (xfContext*) tsmf->custom; - //xfXvContext* xv = (xfXvContext*) xfc->xv_context; return 1; } -void xf_process_tsmf_event(xfContext* xfc, wMessage* event) +int xf_tsmf_xv_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT* event) { + int i; + int x, y; + UINT32 width; + UINT32 height; + BYTE* data1; + BYTE* data2; + UINT32 pixfmt; + UINT32 xvpixfmt; + XvImage * image; + int colorkey = 0; + int numRects = 0; + XRectangle* xrects; + XShmSegmentInfo shminfo; + BOOL converti420yv12 = FALSE; + xfContext* xfc = (xfContext*) tsmf->custom; + xfXvContext* xv = (xfXvContext*) xfc->xv_context; + + if (xv->xv_port == 0) + return -1001; + + /* In case the player is minimized */ + if (event->x < -2048 || event->y < -2048 || event->numVisibleRects < 0) + { + return -1002; + } + + xrects = NULL; + numRects = event->numVisibleRects; + + if (numRects > 0) + { + xrects = (XRectangle*) calloc(numRects, sizeof(XRectangle)); + + if (!xrects) + return -1; + + for (i = 0; i < numRects; i++) + { + x = event->x + event->visibleRects[i].left; + y = event->y + event->visibleRects[i].top; + width = event->visibleRects[i].right - event->visibleRects[i].left; + height = event->visibleRects[i].bottom - event->visibleRects[i].top; + + xrects[i].x = x; + xrects[i].y = y; + xrects[i].width = width; + xrects[i].height = height; + } + } + + if (xv->xv_colorkey_atom != None) + { + XvGetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, &colorkey); + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + XSetForeground(xfc->display, xfc->gc, colorkey); + + if (event->numVisibleRects < 1) + { + XSetClipMask(xfc->display, xfc->gc, None); + } + else + { + XFillRectangles(xfc->display, xfc->window->handle, xfc->gc, xrects, numRects); + } + } + else + { + XSetFunction(xfc->display, xfc->gc, GXcopy); + XSetFillStyle(xfc->display, xfc->gc, FillSolid); + + if (event->numVisibleRects < 1) + { + XSetClipMask(xfc->display, xfc->gc, None); + } + else + { + XSetClipRectangles(xfc->display, xfc->gc, 0, 0, xrects, numRects, YXBanded); + } + } + + pixfmt = event->framePixFmt; + + if (xf_tsmf_is_format_supported(xv, pixfmt)) + { + xvpixfmt = pixfmt; + } + else if (pixfmt == RDP_PIXFMT_I420 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_YV12)) + { + xvpixfmt = RDP_PIXFMT_YV12; + converti420yv12 = TRUE; + } + else if (pixfmt == RDP_PIXFMT_YV12 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_I420)) + { + xvpixfmt = RDP_PIXFMT_I420; + converti420yv12 = TRUE; + } + else + { + WLog_DBG(TAG, "pixel format 0x%X not supported by hardware.", pixfmt); + return -1003; + } + + image = XvShmCreateImage(xfc->display, xv->xv_port, + xvpixfmt, 0, event->frameWidth, event->frameHeight, &shminfo); + + if (xv->xv_image_size != image->data_size) + { + if (xv->xv_image_size > 0) + { + shmdt(xv->xv_shmaddr); + shmctl(xv->xv_shmid, IPC_RMID, NULL); + } + + xv->xv_image_size = image->data_size; + xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777); + xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0); + } + + shminfo.shmid = xv->xv_shmid; + shminfo.shmaddr = image->data = xv->xv_shmaddr; + shminfo.readOnly = FALSE; + + if (!XShmAttach(xfc->display, &shminfo)) + { + XFree(image); + WLog_DBG(TAG, "XShmAttach failed."); + return -1004; + } + + /* The video driver may align each line to a different size + and we need to convert our original image data. */ + switch (pixfmt) + { + case RDP_PIXFMT_I420: + case RDP_PIXFMT_YV12: + /* Y */ + if (image->pitches[0] == event->frameWidth) + { + CopyMemory(image->data + image->offsets[0], + event->frameData, + event->frameWidth * event->frameHeight); + } + else + { + for (i = 0; i < event->frameHeight; i++) + { + CopyMemory(image->data + image->offsets[0] + i * image->pitches[0], + event->frameData + i * event->frameWidth, + event->frameWidth); + } + } + /* UV */ + /* Conversion between I420 and YV12 is to simply swap U and V */ + if (!converti420yv12) + { + data1 = event->frameData + event->frameWidth * event->frameHeight; + data2 = event->frameData + event->frameWidth * event->frameHeight + + event->frameWidth * event->frameHeight / 4; + } + else + { + data2 = event->frameData + event->frameWidth * event->frameHeight; + data1 = event->frameData + event->frameWidth * event->frameHeight + + event->frameWidth * event->frameHeight / 4; + image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420; + } + + if (image->pitches[1] * 2 == event->frameWidth) + { + CopyMemory(image->data + image->offsets[1], + data1, + event->frameWidth * event->frameHeight / 4); + CopyMemory(image->data + image->offsets[2], + data2, + event->frameWidth * event->frameHeight / 4); + } + else + { + for (i = 0; i < event->frameHeight / 2; i++) + { + CopyMemory(image->data + image->offsets[1] + i * image->pitches[1], + data1 + i * event->frameWidth / 2, + event->frameWidth / 2); + CopyMemory(image->data + image->offsets[2] + i * image->pitches[2], + data2 + i * event->frameWidth / 2, + event->frameWidth / 2); + } + } + break; + + default: + CopyMemory(image->data, event->frameData, image->data_size <= event->frameSize ? + image->data_size : event->frameSize); + break; + } + + XvShmPutImage(xfc->display, xv->xv_port, xfc->window->handle, xfc->gc, + image, 0, 0, image->width, image->height, + event->x, event->y, event->width, event->height, FALSE); + + if (xv->xv_colorkey_atom == None) + XSetClipMask(xfc->display, xfc->gc, None); + + XSync(xfc->display, FALSE); + + XShmDetach(xfc->display, &shminfo); + XFree(image); + + free(xrects); + + return 1; +} + +void xf_tsmf_xv_process_event(xfContext* xfc, wMessage* event) +{ + int status = -1; + switch (GetMessageType(event->id)) { case TsmfChannel_VideoFrame: - xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event); + status = xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event); break; } } -void xf_tsmf_init(xfContext* xfc, long xv_port) +int xf_tsmf_xv_init(xfContext* xfc, TsmfClientContext* tsmf) { int ret; unsigned int i; @@ -276,10 +508,13 @@ void xf_tsmf_init(xfContext* xfc, long xv_port) XvAttribute* attr; XvImageFormatValues* fo; + if (xfc->xv_context) + return 1; /* context already created */ + xv = (xfXvContext*) calloc(1, sizeof(xfXvContext)); if (!xv) - return; + return -1; xfc->xv_context = xv; @@ -289,33 +524,34 @@ void xf_tsmf_init(xfContext* xfc, long xv_port) if (!XShmQueryExtension(xfc->display)) { - DEBUG_XV("no xshm available."); - return; + WLog_DBG(TAG, "no xshm available."); + return -1; } ret = XvQueryExtension(xfc->display, &version, &release, &request_base, &event_base, &error_base); if (ret != Success) { - DEBUG_XV("XvQueryExtension failed %d.", ret); - return; + WLog_DBG(TAG, "XvQueryExtension failed %d.", ret); + return -1; } - DEBUG_XV("version %u release %u", version, release); + WLog_DBG(TAG, "version %u release %u", version, release); ret = XvQueryAdaptors(xfc->display, DefaultRootWindow(xfc->display), &num_adaptors, &ai); if (ret != Success) { - DEBUG_XV("XvQueryAdaptors failed %d.", ret); - return; + WLog_DBG(TAG, "XvQueryAdaptors failed %d.", ret); + return -1; } for (i = 0; i < num_adaptors; i++) { - DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id, + WLog_DBG(TAG, "adapter port %ld-%ld (%s)", ai[i].base_id, ai[i].base_id + ai[i].num_ports - 1, ai[i].name); + if (xv->xv_port == 0 && i == num_adaptors - 1) xv->xv_port = ai[i].base_id; } @@ -325,10 +561,10 @@ void xf_tsmf_init(xfContext* xfc, long xv_port) if (xv->xv_port == 0) { - DEBUG_XV("no adapter selected, video frames will not be processed."); - return; + WLog_DBG(TAG, "no adapter selected, video frames will not be processed."); + return -1; } - DEBUG_XV("selected %ld", xv->xv_port); + WLog_DBG(TAG, "selected %ld", xv->xv_port); attr = XvQueryPortAttributes(xfc->display, xv->xv_port, &ret); @@ -343,9 +579,8 @@ void xf_tsmf_init(xfContext* xfc, long xv_port) } XFree(attr); -#ifdef WITH_DEBUG_XV WLog_DBG(TAG, "xf_tsmf_init: pixel format "); -#endif + fo = XvListImageFormats(xfc->display, xv->xv_port, &ret); if (ret > 0) @@ -355,17 +590,25 @@ void xf_tsmf_init(xfContext* xfc, long xv_port) for (i = 0; i < ret; i++) { xv->xv_pixfmts[i] = fo[i].id; -#ifdef WITH_DEBUG_XV WLog_DBG(TAG, "%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1], ((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]); -#endif } xv->xv_pixfmts[i] = 0; } XFree(fo); + + if (tsmf) + { + xfc->tsmf = tsmf; + tsmf->custom = (void*) xfc; + + tsmf->FrameEvent = xf_tsmf_xv_video_frame_event; + } + + return 1; } -void xf_tsmf_uninit(xfContext* xfc) +int xf_tsmf_xv_uninit(xfContext* xfc, TsmfClientContext* tsmf) { xfXvContext* xv = (xfXvContext*) xfc->xv_context; @@ -384,20 +627,40 @@ void xf_tsmf_uninit(xfContext* xfc) free(xv); xfc->xv_context = NULL; } + + if (xfc->tsmf) + { + xfc->tsmf->custom = NULL; + xfc->tsmf = NULL; + } + + return 1; } -#else /* WITH_XV */ +#endif -void xf_tsmf_init(xfContext* xfc, long xv_port) +int xf_tsmf_init(xfContext* xfc, TsmfClientContext* tsmf) { +#ifdef WITH_XV + return xf_tsmf_xv_init(xfc, tsmf); +#endif + + return 1; } -void xf_tsmf_uninit(xfContext* xfc) +int xf_tsmf_uninit(xfContext* xfc, TsmfClientContext* tsmf) { +#ifdef WITH_XV + return xf_tsmf_xv_uninit(xfc, tsmf); +#endif + + return 1; } void xf_process_tsmf_event(xfContext* xfc, wMessage* event) { +#ifdef WITH_XV + return xf_tsmf_xv_process_event(xfc, event); +#endif } -#endif /* WITH_XV */ diff --git a/client/X11/xf_tsmf.h b/client/X11/xf_tsmf.h index eb7981851..7e1274b67 100644 --- a/client/X11/xf_tsmf.h +++ b/client/X11/xf_tsmf.h @@ -23,8 +23,9 @@ #include "xf_client.h" #include "xfreerdp.h" -void xf_tsmf_init(xfContext* xfc, long xv_port); -void xf_tsmf_uninit(xfContext* xfc); +int xf_tsmf_init(xfContext* xfc, TsmfClientContext* tsmf); +int xf_tsmf_uninit(xfContext* xfc, TsmfClientContext* tsmf); + void xf_process_tsmf_event(xfContext* xfc, wMessage* event); #endif /* __XF_TSMF_H */ diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h index 4c66e2408..c972d0778 100644 --- a/client/X11/xfreerdp.h +++ b/client/X11/xfreerdp.h @@ -158,6 +158,7 @@ struct xf_context BOOL complex_regions; VIRTUAL_SCREEN vscreen; void* xv_context; + TsmfClientContext* tsmf; xfClipboard* clipboard; CliprdrClientContext* cliprdr; From ee7299ec3f3641e793630fb2e0f38bfc67d0e9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 10 Nov 2014 16:33:34 -0500 Subject: [PATCH 15/17] channels/tsmf: remove dependency on deprecated eventing system --- channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 1 - channels/tsmf/client/tsmf_main.c | 16 -- channels/tsmf/client/tsmf_main.h | 1 - channels/tsmf/client/tsmf_media.c | 50 ++--- client/X11/xf_client.c | 4 - client/X11/xf_tsmf.c | 230 ++-------------------- client/X11/xf_tsmf.h | 2 - include/freerdp/client/tsmf.h | 17 -- libfreerdp/utils/event.c | 54 ----- 9 files changed, 28 insertions(+), 347 deletions(-) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index 460faa4c3..f047693e1 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -28,7 +28,6 @@ #include #include -#include #include #include diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index fc8d7a215..68e05e43a 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -71,22 +71,6 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, Stream_Free(s, TRUE); } -BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event) -{ - int status; - TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; - - status = callback->channel_mgr->PushEvent(callback->channel_mgr, event); - - if (status) - { - WLog_ERR(TAG, "response error %d", status); - return FALSE; - } - - return TRUE; -} - static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) { int length; diff --git a/channels/tsmf/client/tsmf_main.h b/channels/tsmf/client/tsmf_main.h index e11820fa3..8c287c932 100644 --- a/channels/tsmf/client/tsmf_main.h +++ b/channels/tsmf/client/tsmf_main.h @@ -60,7 +60,6 @@ struct _TSMF_PLUGIN void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, UINT32 message_id, UINT64 duration, UINT32 data_size); -BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event); #endif diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index 446dfd726..fa4e06f12 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -41,7 +41,6 @@ #include #include -#include #include #include "tsmf_constants.h" @@ -346,6 +345,7 @@ TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE *guid) static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) { UINT64 t; + TSMF_VIDEO_FRAME_EVENT event; TSMF_STREAM* stream = sample->stream; TSMF_PRESENTATION* presentation = stream->presentation; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) sample->channel_callback; @@ -367,46 +367,20 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) stream->next_start_time = t + sample->duration - 50000; - if (!tsmf->custom) - { - RDP_VIDEO_FRAME_EVENT* vevent; + ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT)); - vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(TsmfChannel_Class, - TsmfChannel_VideoFrame, NULL, NULL); + event.frameData = sample->data; + event.frameSize = sample->decoded_size; + event.framePixFmt = sample->pixfmt; + event.frameWidth = sample->stream->width; + event.frameHeight = sample->stream->height; - vevent->frame_data = sample->data; - vevent->frame_size = sample->decoded_size; - vevent->frame_pixfmt = sample->pixfmt; - vevent->frame_width = sample->stream->width; - vevent->frame_height = sample->stream->height; - /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ - sample->data = NULL; - sample->decoded_size = 0; + /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ + sample->data = NULL; + sample->decoded_size = 0; - if (!tsmf_push_event(sample->channel_callback, (wMessage*) vevent)) - { - freerdp_event_free((wMessage*) vevent); - } - } - else - { - TSMF_VIDEO_FRAME_EVENT event; - - ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT)); - - event.frameData = sample->data; - event.frameSize = sample->decoded_size; - event.framePixFmt = sample->pixfmt; - event.frameWidth = sample->stream->width; - event.frameHeight = sample->stream->height; - - /* The frame data ownership is passed to the event object, and is freed after the event is processed. */ - sample->data = NULL; - sample->decoded_size = 0; - - if (tsmf->FrameEvent) - tsmf->FrameEvent(tsmf, &event); - } + if (tsmf->FrameEvent) + tsmf->FrameEvent(tsmf, &event); #if 0 /* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4c8fadec8..34a67bcd6 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1119,10 +1119,6 @@ void xf_process_channel_event(rdpChannels* channels, freerdp* instance) xf_process_rail_event(xfc, channels, event); break; - case TsmfChannel_Class: - xf_process_tsmf_event(xfc, event); - break; - default: break; } diff --git a/client/X11/xf_tsmf.c b/client/X11/xf_tsmf.c index 9bd448a0c..3a9350d43 100644 --- a/client/X11/xf_tsmf.c +++ b/client/X11/xf_tsmf.c @@ -73,198 +73,6 @@ static BOOL xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt) return FALSE; } -static int xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EVENT* vevent) -{ - int i; - BYTE* data1; - BYTE* data2; - UINT32 pixfmt; - UINT32 xvpixfmt; - BOOL converti420yv12 = FALSE; - XvImage * image; - int colorkey = 0; - XShmSegmentInfo shminfo; - xfXvContext* xv = (xfXvContext*) xfc->xv_context; - - if (xv->xv_port == 0) - return -1001; - - /* In case the player is minimized */ - if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects < 0) - { - return -1002; - } - - if (xv->xv_colorkey_atom != None) - { - XvGetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, &colorkey); - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - XSetForeground(xfc->display, xfc->gc, colorkey); - - if (vevent->num_visible_rects < 1) - { - XSetClipMask(xfc->display, xfc->gc, None); - } - else - { - for (i = 0; i < vevent->num_visible_rects; i++) - { - XFillRectangle(xfc->display, xfc->window->handle, xfc->gc, - vevent->x + vevent->visible_rects[i].x, - vevent->y + vevent->visible_rects[i].y, - vevent->visible_rects[i].width, - vevent->visible_rects[i].height); - } - } - } - else - { - XSetFunction(xfc->display, xfc->gc, GXcopy); - XSetFillStyle(xfc->display, xfc->gc, FillSolid); - - if (vevent->num_visible_rects < 1) - { - XSetClipMask(xfc->display, xfc->gc, None); - } - else - { - XSetClipRectangles(xfc->display, xfc->gc, vevent->x, vevent->y, - (XRectangle*) vevent->visible_rects, vevent->num_visible_rects, YXBanded); - } - } - - pixfmt = vevent->frame_pixfmt; - - if (xf_tsmf_is_format_supported(xv, pixfmt)) - { - xvpixfmt = pixfmt; - } - else if (pixfmt == RDP_PIXFMT_I420 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_YV12)) - { - xvpixfmt = RDP_PIXFMT_YV12; - converti420yv12 = TRUE; - } - else if (pixfmt == RDP_PIXFMT_YV12 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_I420)) - { - xvpixfmt = RDP_PIXFMT_I420; - converti420yv12 = TRUE; - } - else - { - WLog_DBG(TAG, "pixel format 0x%X not supported by hardware.", pixfmt); - return -1003; - } - - image = XvShmCreateImage(xfc->display, xv->xv_port, - xvpixfmt, 0, vevent->frame_width, vevent->frame_height, &shminfo); - - if (xv->xv_image_size != image->data_size) - { - if (xv->xv_image_size > 0) - { - shmdt(xv->xv_shmaddr); - shmctl(xv->xv_shmid, IPC_RMID, NULL); - } - - xv->xv_image_size = image->data_size; - xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777); - xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0); - } - - shminfo.shmid = xv->xv_shmid; - shminfo.shmaddr = image->data = xv->xv_shmaddr; - shminfo.readOnly = FALSE; - - if (!XShmAttach(xfc->display, &shminfo)) - { - XFree(image); - WLog_DBG(TAG, "XShmAttach failed."); - return -1004; - } - - /* The video driver may align each line to a different size - and we need to convert our original image data. */ - switch (pixfmt) - { - case RDP_PIXFMT_I420: - case RDP_PIXFMT_YV12: - /* Y */ - if (image->pitches[0] == vevent->frame_width) - { - CopyMemory(image->data + image->offsets[0], - vevent->frame_data, - vevent->frame_width * vevent->frame_height); - } - else - { - for (i = 0; i < vevent->frame_height; i++) - { - CopyMemory(image->data + image->offsets[0] + i * image->pitches[0], - vevent->frame_data + i * vevent->frame_width, - vevent->frame_width); - } - } - /* UV */ - /* Conversion between I420 and YV12 is to simply swap U and V */ - if (!converti420yv12) - { - data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height; - data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height + - vevent->frame_width * vevent->frame_height / 4; - } - else - { - data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height; - data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height + - vevent->frame_width * vevent->frame_height / 4; - image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420; - } - - if (image->pitches[1] * 2 == vevent->frame_width) - { - CopyMemory(image->data + image->offsets[1], - data1, - vevent->frame_width * vevent->frame_height / 4); - CopyMemory(image->data + image->offsets[2], - data2, - vevent->frame_width * vevent->frame_height / 4); - } - else - { - for (i = 0; i < vevent->frame_height / 2; i++) - { - CopyMemory(image->data + image->offsets[1] + i * image->pitches[1], - data1 + i * vevent->frame_width / 2, - vevent->frame_width / 2); - CopyMemory(image->data + image->offsets[2] + i * image->pitches[2], - data2 + i * vevent->frame_width / 2, - vevent->frame_width / 2); - } - } - break; - - default: - CopyMemory(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ? - image->data_size : vevent->frame_size); - break; - } - - XvShmPutImage(xfc->display, xv->xv_port, xfc->window->handle, xfc->gc, - image, 0, 0, image->width, image->height, - vevent->x, vevent->y, vevent->width, vevent->height, FALSE); - - if (xv->xv_colorkey_atom == None) - XSetClipMask(xfc->display, xfc->gc, None); - - XSync(xfc->display, FALSE); - - XShmDetach(xfc->display, &shminfo); - XFree(image); - - return 1; -} - int xf_tsmf_xv_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT* event) { int i; @@ -275,14 +83,27 @@ int xf_tsmf_xv_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT BYTE* data2; UINT32 pixfmt; UINT32 xvpixfmt; - XvImage * image; + XvImage* image; int colorkey = 0; int numRects = 0; + xfContext* xfc; + xfXvContext* xv; XRectangle* xrects; XShmSegmentInfo shminfo; BOOL converti420yv12 = FALSE; - xfContext* xfc = (xfContext*) tsmf->custom; - xfXvContext* xv = (xfXvContext*) xfc->xv_context; + + if (!tsmf) + return -1; + + xfc = (xfContext*) tsmf->custom; + + if (!xfc) + return -1; + + xv = (xfXvContext*) xfc->xv_context; + + if (!xv) + return -1; if (xv->xv_port == 0) return -1001; @@ -481,18 +302,6 @@ int xf_tsmf_xv_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT return 1; } -void xf_tsmf_xv_process_event(xfContext* xfc, wMessage* event) -{ - int status = -1; - - switch (GetMessageType(event->id)) - { - case TsmfChannel_VideoFrame: - status = xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event); - break; - } -} - int xf_tsmf_xv_init(xfContext* xfc, TsmfClientContext* tsmf) { int ret; @@ -657,10 +466,3 @@ int xf_tsmf_uninit(xfContext* xfc, TsmfClientContext* tsmf) return 1; } -void xf_process_tsmf_event(xfContext* xfc, wMessage* event) -{ -#ifdef WITH_XV - return xf_tsmf_xv_process_event(xfc, event); -#endif -} - diff --git a/client/X11/xf_tsmf.h b/client/X11/xf_tsmf.h index 7e1274b67..0469d6860 100644 --- a/client/X11/xf_tsmf.h +++ b/client/X11/xf_tsmf.h @@ -26,6 +26,4 @@ int xf_tsmf_init(xfContext* xfc, TsmfClientContext* tsmf); int xf_tsmf_uninit(xfContext* xfc, TsmfClientContext* tsmf); -void xf_process_tsmf_event(xfContext* xfc, wMessage* event); - #endif /* __XF_TSMF_H */ diff --git a/include/freerdp/client/tsmf.h b/include/freerdp/client/tsmf.h index 2978f2d1d..674a9c737 100644 --- a/include/freerdp/client/tsmf.h +++ b/include/freerdp/client/tsmf.h @@ -29,23 +29,6 @@ #define RDP_PIXFMT_I420 0x30323449 #define RDP_PIXFMT_YV12 0x32315659 -struct _RDP_VIDEO_FRAME_EVENT -{ - wMessage event; - BYTE* frame_data; - UINT32 frame_size; - UINT32 frame_pixfmt; - INT16 frame_width; - INT16 frame_height; - INT16 x; - INT16 y; - INT16 width; - INT16 height; - UINT16 num_visible_rects; - RDP_RECT* visible_rects; -}; -typedef struct _RDP_VIDEO_FRAME_EVENT RDP_VIDEO_FRAME_EVENT; - struct _TSMF_VIDEO_FRAME_EVENT { BYTE* frameData; diff --git a/libfreerdp/utils/event.c b/libfreerdp/utils/event.c index 081b6e4b3..c8772c905 100644 --- a/libfreerdp/utils/event.c +++ b/libfreerdp/utils/event.c @@ -21,16 +21,11 @@ #include "config.h" #endif -#include -#include -#include - #include #include #include #include -#include #include static wMessage* freerdp_cliprdr_event_new(UINT16 event_type) @@ -109,28 +104,6 @@ static wMessage* freerdp_cliprdr_event_new(UINT16 event_type) return event.m; } -static wMessage* freerdp_tsmf_event_new(UINT16 event_type) -{ - union - { - void *v; - wMessage* m; - } event; - - event.m = NULL; - - switch (event_type) - { - case TsmfChannel_VideoFrame: - event.v = malloc(sizeof(RDP_VIDEO_FRAME_EVENT)); - ZeroMemory(event.v, sizeof(RDP_VIDEO_FRAME_EVENT)); - event.m->id = MakeMessageId(TsmfChannel, VideoFrame); - break; - } - - return event.v; -} - static wMessage* freerdp_rail_event_new(UINT16 event_type) { wMessage* event = NULL; @@ -148,19 +121,10 @@ wMessage* freerdp_event_new(UINT16 event_class, UINT16 event_type, switch (event_class) { - case DebugChannel_Class: - event = (wMessage*) malloc(sizeof(wMessage)); - ZeroMemory(event, sizeof(wMessage)); - break; - case CliprdrChannel_Class: event = freerdp_cliprdr_event_new(event_type); break; - case TsmfChannel_Class: - event = freerdp_tsmf_event_new(event_type); - break; - case RailChannel_Class: event = freerdp_rail_event_new(event_type); break; @@ -197,20 +161,6 @@ static void freerdp_cliprdr_event_free(wMessage* event) } } -static void freerdp_tsmf_event_free(wMessage* event) -{ - switch (GetMessageType(event->id)) - { - case TsmfChannel_VideoFrame: - { - RDP_VIDEO_FRAME_EVENT* vevent = (RDP_VIDEO_FRAME_EVENT*)event; - free(vevent->frame_data); - free(vevent->visible_rects); - } - break; - } -} - static void freerdp_rail_event_free(wMessage* event) { @@ -229,10 +179,6 @@ void freerdp_event_free(wMessage* event) freerdp_cliprdr_event_free(event); break; - case TsmfChannel_Class: - freerdp_tsmf_event_free(event); - break; - case RailChannel_Class: freerdp_rail_event_free(event); break; From 68ee5df7d9786b465dd79cebf684e2f33a200293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 11 Nov 2014 11:21:34 -0500 Subject: [PATCH 16/17] winpr: fix build warnings --- libfreerdp/core/update.c | 2 +- winpr/libwinpr/pool/pool.c | 3 --- winpr/libwinpr/thread/thread.c | 12 ++++++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 42bfd44f8..0adfbeb8f 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -1518,7 +1518,7 @@ static void update_send_pointer_position(rdpContext* context, POINTER_POSITION_U Stream_Write_UINT16(s, pointerPosition->xPos); /* xPos (2 bytes) */ Stream_Write_UINT16(s, pointerPosition->yPos); /* yPos (2 bytes) */ - fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s); + fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE); Stream_Release(s); } diff --git a/winpr/libwinpr/pool/pool.c b/winpr/libwinpr/pool/pool.c index df5c17087..0b097e81d 100644 --- a/winpr/libwinpr/pool/pool.c +++ b/winpr/libwinpr/pool/pool.c @@ -181,9 +181,6 @@ VOID CloseThreadpool(PTP_POOL ptpp) if (pCloseThreadpool) pCloseThreadpool(ptpp); #else - int index; - HANDLE thread; - SetEvent(ptpp->TerminateEvent); ArrayList_Free(ptpp->Threads); diff --git a/winpr/libwinpr/thread/thread.c b/winpr/libwinpr/thread/thread.c index b9107f7bd..461f5765b 100644 --- a/winpr/libwinpr/thread/thread.c +++ b/winpr/libwinpr/thread/thread.c @@ -267,7 +267,7 @@ exit: if (thread->detached || !thread->started) cleanup_handle(thread); - pthread_exit(thread->dwExitCode); + pthread_exit((void*) (size_t) thread->dwExitCode); return rc; } @@ -426,12 +426,13 @@ VOID ExitThread(DWORD dwExitCode) { pthread_t tid = pthread_self(); - if (NULL == thread_list) + if (!thread_list) { WLog_ERR(TAG, "function called without existing thread list!"); #if defined(WITH_DEBUG_THREADS) DumpThreadHandles(); #endif + pthread_exit(0); } else if (!ListDictionary_Contains(thread_list, &tid)) { @@ -439,12 +440,15 @@ VOID ExitThread(DWORD dwExitCode) #if defined(WITH_DEBUG_THREADS) DumpThreadHandles(); #endif + pthread_exit(0); } else { - WINPR_THREAD *thread; + WINPR_THREAD* thread; + ListDictionary_Lock(thread_list); thread = ListDictionary_GetItemValue(thread_list, &tid); + assert(thread); thread->exited = TRUE; thread->dwExitCode = dwExitCode; @@ -457,7 +461,7 @@ VOID ExitThread(DWORD dwExitCode) if (thread->detached || !thread->started) cleanup_handle(thread); - pthread_exit(thread->dwExitCode); + pthread_exit((void*) (size_t) thread->dwExitCode); } } From d4bdf52b07a50616f038ed0c5299c23586c591de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 11 Nov 2014 11:46:59 -0500 Subject: [PATCH 17/17] libwinpr-smartcard: re-enable SCardGetStatusChange status filtering --- winpr/libwinpr/smartcard/smartcard_pcsc.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c index ebf4420be..a0d14c998 100644 --- a/winpr/libwinpr/smartcard/smartcard_pcsc.c +++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c @@ -1382,6 +1382,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext { int i, j; int* map; + DWORD dwEventState; + BOOL stateChanged = FALSE; PCSC_DWORD cMappedReaders; PCSC_SCARD_READERSTATE* states; LONG status = SCARD_S_SUCCESS; @@ -1469,11 +1471,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext rgReaderStates[i].dwCurrentState = states[j].dwCurrentState; rgReaderStates[i].cbAtr = states[j].cbAtr; CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[j].rgbAtr), PCSC_MAX_ATR_SIZE); - /** - * Why we should interpret and modify the results of pcsc-lite ScardGetStatusChange ? - * Should not we just act as a pass-through between the client and the remote smartcard subsystem ? - */ -#if 0 + /* pcsc-lite puts an event count in the higher bits of dwEventState */ states[j].dwEventState &= 0xFFFF; dwEventState = states[j].dwEventState & ~SCARD_STATE_CHANGED; @@ -1497,19 +1495,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext if (rgReaderStates[i].dwCurrentState & SCARD_STATE_IGNORE) rgReaderStates[i].dwEventState = SCARD_STATE_IGNORE; -#endif + rgReaderStates[i].dwEventState = states[j].dwEventState; } - /** - * Why we should interpret and modify the results of pcsc-lite ScardGetStatusChange ? - * Should not we just act as a pass-through between the client and the remote smartcard subsystem ? - */ -#if 0 + if ((status == SCARD_S_SUCCESS) && !stateChanged) status = SCARD_E_TIMEOUT; else if ((status == SCARD_E_TIMEOUT) && stateChanged) return SCARD_S_SUCCESS; -#endif free(states); free(map);