TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { DEBUG_WARN("duplicated stream id %d!", stream_id); return NULL; } stream = (TSMF_STREAM*) malloc(sizeof(TSMF_STREAM)); ZeroMemory(stream, sizeof(TSMF_STREAM)); stream->stream_id = stream_id; stream->presentation = presentation; stream->started = FALSE; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); stream->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL); stream->sample_list = Queue_New(TRUE, -1, -1); stream->sample_ack_list = Queue_New(TRUE, -1, -1); WaitForSingleObject(presentation->mutex, INFINITE); list_enqueue(presentation->stream_list, stream); ReleaseMutex(presentation->mutex); return stream; }
TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id) { TSMF_STREAM *stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { CLOG_ERR("duplicated stream id %d!", stream_id); return NULL; } stream = (TSMF_STREAM *) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { CLOG_ERR("Calloc failed"); return NULL; } stream->stream_id = stream_id; stream->presentation = presentation; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); stream->sample_list = Queue_New(TRUE, -1, -1); 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); ArrayList_Add(presentation->stream_list, stream); return stream; }
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; 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) { stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) tsmf_stream_end(stream); } DEBUG_DVC("StreamId %d", StreamId); Stream_EnsureRemainingCapacity(ifman->output, 16); Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, StreamId); /* StreamId */ 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_remove_stream(TSMF_IFMAN* ifman) { int status = 0; UINT32 StreamId; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_DVC(""); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, 16); if (presentation == NULL) { status = 1; } else { Stream_Read_UINT32(ifman->input, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) tsmf_stream_free(stream); else status = 1; } ifman->output_pending = TRUE; return status; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; TSMF_STREAM* stream = NULL; TSMF_PRESENTATION* presentation; if (Stream_GetRemainingLength(ifman->input) < 20) return ERROR_INVALID_DATA; presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); if (presentation) { stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) tsmf_stream_end(stream, ifman->message_id, ifman->channel_callback); } DEBUG_TSMF("StreamId %d", StreamId); ifman->output_pending = TRUE; ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; return CHANNEL_RC_OK; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_remove_stream(TSMF_IFMAN* ifman) { int status = CHANNEL_RC_OK; UINT32 StreamId; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); if (Stream_GetRemainingLength(ifman->input) < 20) return ERROR_INVALID_DATA; presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, GUID_SIZE); if (!presentation) { status = ERROR_NOT_FOUND; } else { Stream_Read_UINT32(ifman->input, StreamId); stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) tsmf_stream_free(stream); else status = ERROR_NOT_FOUND; } ifman->output_pending = TRUE; return status; }
int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { 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 */ Stream_Read_UINT64(ifman->input, SampleStartTime); Stream_Read_UINT64(ifman->input, SampleEndTime); Stream_Read_UINT64(ifman->input, ThrottleDuration); Stream_Seek_UINT32(ifman->input); /* SampleFlags */ Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, cbData); DEBUG_DVC("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) { DEBUG_WARN("unknown presentation id"); return 1; } stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream == NULL) { DEBUG_WARN("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->output_pending = TRUE; return 0; }
int tsmf_ifman_on_sample(TSMF_IFMAN * ifman) { TSMF_PRESENTATION * presentation; TSMF_STREAM * stream; uint32 StreamId; uint64 SampleStartTime; uint64 SampleEndTime; uint64 ThrottleDuration; uint32 SampleExtensions; uint32 cbData; StreamId = GET_UINT32(ifman->input_buffer, 16); SampleStartTime = GET_UINT64(ifman->input_buffer, 24); SampleEndTime = GET_UINT64(ifman->input_buffer, 32); ThrottleDuration = GET_UINT64(ifman->input_buffer, 40); SampleExtensions = GET_UINT32(ifman->input_buffer, 52); cbData = GET_UINT32(ifman->input_buffer, 56); LLOGLN(10, ("tsmf_ifman_on_sample: 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) { LLOGLN(0, ("tsmf_ifman_on_sample: unknown presentation id")); return 1; } stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream == NULL) { LLOGLN(0, ("tsmf_ifman_on_sample: unknown stream id")); return 1; } tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, cbData, ifman->input_buffer + 60); ifman->output_pending = 1; return 0; }
static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback) { TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback; DEBUG_DVC(""); if (callback->stream_id) { presentation = tsmf_presentation_find_by_id(callback->presentation_id); if (presentation) { stream = tsmf_stream_find_by_id(presentation, callback->stream_id); if (stream) tsmf_stream_free(stream); } } xfree(pChannelCallback); return 0; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_on_flush(TSMF_IFMAN* ifman) { UINT32 StreamId; TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; if (Stream_GetRemainingLength(ifman->input) < 20) return ERROR_INVALID_DATA; 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) { WLog_ERR(TAG, "unknown presentation id"); return ERROR_NOT_FOUND; } /* Flush message is for a stream, not the entire presentation * therefore we only flush the stream as intended per the MS-RDPEV spec */ stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) { if (!tsmf_stream_flush(stream)) return ERROR_INVALID_OPERATION; } else WLog_ERR(TAG, "unknown stream id"); ifman->output_pending = TRUE; return CHANNEL_RC_OK; }
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN * ifman) { TSMF_PRESENTATION * presentation; TSMF_STREAM * stream; uint32 StreamId; presentation = tsmf_presentation_find_by_id(ifman->input_buffer); StreamId = GET_UINT32(ifman->input_buffer, 16); stream = tsmf_stream_find_by_id(presentation, StreamId); tsmf_stream_end(stream); LLOGLN(0, ("tsmf_ifman_on_end_of_stream: StreamId %d", StreamId)); ifman->output_buffer_size = 16; ifman->output_buffer = malloc(16); SET_UINT32(ifman->output_buffer, 0, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ SET_UINT32(ifman->output_buffer, 4, StreamId); /* StreamId */ SET_UINT32(ifman->output_buffer, 8, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */ SET_UINT32(ifman->output_buffer, 12, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; return 0; }
int tsmf_ifman_remove_stream(TSMF_IFMAN * ifman) { TSMF_PRESENTATION * presentation; TSMF_STREAM * stream; uint32 StreamId; int error = 0; LLOGLN(0, ("tsmf_ifman_remove_stream:")); presentation = tsmf_presentation_find_by_id(ifman->input_buffer); if (presentation == NULL) error = 1; else { StreamId = GET_UINT32(ifman->input_buffer, 16); stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) tsmf_stream_free(stream); else error = 1; } ifman->output_pending = 1; return error; }
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id, rdpContext* rdpcontext) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { WLog_ERR(TAG, "duplicated stream id %d!", stream_id); return NULL; } stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { WLog_ERR(TAG, "Calloc failed"); return NULL; } stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL; stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL; stream->currentBufferLevel = 1; stream->seeking = FALSE; stream->eos = 0; stream->eos_message_id = 0; stream->eos_channel_callback = NULL; stream->stream_id = stream_id; stream->presentation = presentation; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!stream->stopEvent) goto error_stopEvent; stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); if (!stream->ready) goto error_ready; stream->sample_list = Queue_New(TRUE, -1, -1); if (!stream->sample_list) goto error_sample_list; stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_ack_list = Queue_New(TRUE, -1, -1); if (!stream->sample_ack_list) goto error_sample_ack_list; stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free; stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL); stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, CREATE_SUSPENDED, NULL); stream->rdpcontext = rdpcontext; return stream; error_add: SetEvent(stream->stopEvent); if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED) WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); error_ack_thread: SetEvent(stream->stopEvent); if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED) WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); error_play_thread: Queue_Free(stream->sample_ack_list); error_sample_ack_list: Queue_Free(stream->sample_list); error_sample_list: CloseHandle(stream->ready); error_ready: CloseHandle(stream->stopEvent); error_stopEvent: free(stream); return NULL; }
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id) { TSMF_STREAM* stream; stream = tsmf_stream_find_by_id(presentation, stream_id); if (stream) { WLog_ERR(TAG, "duplicated stream id %d!", stream_id); return NULL; } stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM)); if (!stream) { WLog_ERR(TAG, "Calloc failed"); return NULL; } stream->stream_id = stream_id; stream->presentation = presentation; stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!stream->stopEvent) goto error_stopEvent; stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL); if (!stream->ready) goto error_ready; stream->sample_list = Queue_New(TRUE, -1, -1); if (!stream->sample_list) goto error_sample_list; stream->sample_list->object.fnObjectFree = tsmf_sample_free; stream->sample_ack_list = Queue_New(TRUE, -1, -1); if (!stream->sample_ack_list) goto error_sample_ack_list; 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); if (!stream->play_thread) goto error_play_thread; stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL); if (!stream->ack_thread) goto error_ack_thread; if (ArrayList_Add(presentation->stream_list, stream) < 0) goto error_add; return stream; error_add: SetEvent(stream->stopEvent); WaitForSingleObject(stream->ack_thread, INFINITE); error_ack_thread: SetEvent(stream->stopEvent); WaitForSingleObject(stream->play_thread, INFINITE); error_play_thread: Queue_Free(stream->sample_ack_list); error_sample_ack_list: Queue_Free(stream->sample_list); error_sample_list: CloseHandle(stream->ready); error_ready: CloseHandle(stream->stopEvent); error_stopEvent: free(stream); return NULL; }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; UINT32 StreamId; UINT64 SampleStartTime; UINT64 SampleEndTime; UINT64 ThrottleDuration; UINT32 SampleExtensions; UINT32 cbData; UINT error; if (Stream_GetRemainingLength(ifman->input) < 60) return ERROR_INVALID_DATA; Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numSample */ Stream_Read_UINT64(ifman->input, SampleStartTime); Stream_Read_UINT64(ifman->input, SampleEndTime); Stream_Read_UINT64(ifman->input, ThrottleDuration); Stream_Seek_UINT32(ifman->input); /* SampleFlags */ Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, cbData); if (Stream_GetRemainingLength(ifman->input) < cbData) return ERROR_INVALID_DATA; DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %lu SampleEndTime %lu " "ThrottleDuration %d SampleExtensions %d cbData %d", ifman->message_id, StreamId, SampleStartTime, SampleEndTime, (int)ThrottleDuration, SampleExtensions, cbData); presentation = tsmf_presentation_find_by_id(ifman->presentation_id); if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); return ERROR_NOT_FOUND; } stream = tsmf_stream_find_by_id(presentation, StreamId); if (!stream) { WLog_ERR(TAG, "unknown stream id"); return ERROR_NOT_FOUND; } if (!tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input))) { WLog_ERR(TAG, "unable to push sample"); return ERROR_OUTOFMEMORY; } if ((error = tsmf_presentation_sync(presentation))) { WLog_ERR(TAG, "tsmf_presentation_sync failed with error %lu", error); return error; } ifman->output_pending = TRUE; return CHANNEL_RC_OK; }