{
UINT32 CapabilityValue;
- Stream_Read_UINT32(ifman->input, CapabilityValue);
+ if (Stream_GetRemainingLength(ifman->input) < 4)
+ return ERROR_INVALID_DATA;
- Stream_Read_UINT32(ifman->input, CapabilityValue);
- DEBUG_TSMF("server CapabilityValue %d", CapabilityValue);
++ Stream_Read_UINT32(ifman->input, CapabilityValue);
+ DEBUG_TSMF("server CapabilityValue %"PRIu32"", CapabilityValue);
if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
- return -1;
+ return ERROR_INVALID_DATA;
++
Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */
Stream_Write_UINT32(ifman->output, 0); /* Result */
--
- return 0;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
{
UINT32 i;
UINT32 v;
UINT32 numHostCapabilities;
if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4))
- return -1;
+ return ERROR_OUTOFMEMORY;
++
pos = Stream_GetPosition(ifman->output);
- Stream_Copy(ifman->output, ifman->input, ifman->input_size);
+ Stream_Copy(ifman->input, ifman->output, ifman->input_size);
Stream_SetPosition(ifman->output, pos);
+
+ if (Stream_GetRemainingLength(ifman->output) < 4)
+ return ERROR_INVALID_DATA;
++
Stream_Read_UINT32(ifman->output, numHostCapabilities);
for (i = 0; i < numHostCapabilities; i++)
switch (CapabilityType)
{
case 1: /* Protocol version request */
+ if (Stream_GetRemainingLength(ifman->output) < 4)
+ return ERROR_INVALID_DATA;
+
Stream_Read_UINT32(ifman->output, v);
- DEBUG_TSMF("server protocol version %d", v);
+ DEBUG_TSMF("server protocol version %"PRIu32"", v);
break;
++
case 2: /* Supported platform */
+ if (Stream_GetRemainingLength(ifman->output) < 4)
+ return ERROR_INVALID_DATA;
+
Stream_Peek_UINT32(ifman->output, v);
- DEBUG_TSMF("server supported platform %d", v);
+ DEBUG_TSMF("server supported platform %"PRIu32"", 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);
+ WLog_ERR(TAG, "skipping unknown capability type %"PRIu32"", CapabilityType);
break;
}
++
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;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
{
UINT32 numMediaType;
UINT32 PlatformCookie;
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);
+ DEBUG_TSMF("PlatformCookie %"PRIu32" numMediaType %"PRIu32"", PlatformCookie, numMediaType);
if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input))
FormatSupported = 0;
if (!Stream_EnsureRemainingCapacity(ifman->output, 12))
return -1;
++
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;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
{
- int status = 0;
+ UINT status = CHANNEL_RC_OK;
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
+ if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
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)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_add_stream(TSMF_IFMAN* ifman, rdpContext* rdpcontext)
{
UINT32 StreamId;
- int status = 0;
+ UINT status = CHANNEL_RC_OK;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
+ if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
- Stream_Seek(ifman->input, 16);
+ Stream_Seek(ifman->input, GUID_SIZE);
if (!presentation)
{
{
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numMediaType */
- stream = tsmf_stream_new(presentation, StreamId);
- if (stream)
- tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
+ stream = tsmf_stream_new(presentation, StreamId, rdpcontext);
++
+ if (!stream)
+ {
+ WLog_ERR(TAG, "failed to create stream");
+ return ERROR_OUTOFMEMORY;
+ }
+
+ if (!tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input))
+ {
+ WLog_ERR(TAG, "failed to set stream format");
+ return ERROR_OUTOFMEMORY;
+ }
++
+ tsmf_stream_start_threads(stream);
}
+
ifman->output_pending = TRUE;
return status;
}
-int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
++
if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
- return -1;
+ return ERROR_OUTOFMEMORY;
+
Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
UINT32 StreamId;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
- presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+ if (Stream_GetRemainingLength(ifman->input) < 20)
+ return ERROR_INVALID_DATA;
- Stream_Seek(ifman->input, 16);
+ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
+ Stream_Seek(ifman->input, GUID_SIZE);
if (!presentation)
{
}
ifman->output_pending = TRUE;
--
return status;
}
--float tsmf_stream_read_float(wStream *s)
++float tsmf_stream_read_float(wStream* s)
{
float fValue;
UINT32 iValue;
float Left, Top;
float Right, Bottom;
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
- presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+ if (Stream_GetRemainingLength(ifman->input) < 32)
+ return ERROR_INVALID_DATA;
- Stream_Seek(ifman->input, 16);
+ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
-
+ Stream_Seek(ifman->input, GUID_SIZE);
if (!presentation)
{
Right = tsmf_stream_read_float(ifman->input); /* Right (4 bytes) */
Bottom = tsmf_stream_read_float(ifman->input); /* Bottom (4 bytes) */
DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
-- Left, Top, Right, Bottom);
++ Left, Top, Right, Bottom);
}
ifman->output_pending = TRUE;
--
return status;
}
-int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
+ if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+
if (presentation)
tsmf_presentation_free(presentation);
else
+ {
WLog_ERR(TAG, "unknown presentation id");
+ return ERROR_NOT_FOUND;
+ }
if (!Stream_EnsureRemainingCapacity(ifman->output, 4))
- return -1;
+ return ERROR_OUTOFMEMORY;
+
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
--
- return 0;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION* presentation;
-
+ UINT32 newVolume;
+ UINT32 muted;
DEBUG_TSMF("on stream volume");
+
+ if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
- if (presentation)
- {
- UINT32 newVolume;
- UINT32 muted;
- Stream_Seek(ifman->input, 16);
- Stream_Read_UINT32(ifman->input, newVolume);
- DEBUG_TSMF("on stream volume: new volume=[%d]", newVolume);
- Stream_Read_UINT32(ifman->input, muted);
- DEBUG_TSMF("on stream volume: muted=[%d]", muted);
- tsmf_presentation_volume_changed(presentation, newVolume, muted);
- }
- else
+ if (!presentation)
{
WLog_ERR(TAG, "unknown presentation id");
+ return ERROR_NOT_FOUND;
}
- ifman->output_pending = TRUE;
+ Stream_Seek(ifman->input, 16);
+ Stream_Read_UINT32(ifman->input, newVolume);
+ DEBUG_TSMF("on stream volume: new volume=[%"PRIu32"]", newVolume);
+ Stream_Read_UINT32(ifman->input, muted);
+ DEBUG_TSMF("on stream volume: muted=[%"PRIu32"]", muted);
+
+ if (!tsmf_presentation_volume_changed(presentation, newVolume, muted))
+ return ERROR_INVALID_OPERATION;
-
+ ifman->output_pending = TRUE;
return 0;
}
-int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("on channel volume");
+ if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+
if (presentation)
{
UINT32 channelVolume;
}
ifman->output_pending = TRUE;
--
- return 0;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
ifman->output_pending = TRUE;
UINT32 Width;
UINT32 Height;
UINT32 cbVisibleRect;
-- RDP_RECT *rects = NULL;
++ RDP_RECT* rects = NULL;
int num_rects = 0;
- int error = 0;
+ UINT error = CHANNEL_RC_OK;
int i;
int pos;
+
+ if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 32)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
++
+ if (!presentation)
+ return ERROR_NOT_FOUND;
+
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, numGeometryInfo);
pos = Stream_GetPosition(ifman->input);
Stream_SetPosition(ifman->input, pos + numGeometryInfo);
Stream_Read_UINT32(ifman->input, cbVisibleRect);
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)
- {
- error = 1;
- }
- else
+ DEBUG_TSMF("numGeometryInfo %"PRIu32" Width %"PRIu32" Height %"PRIu32" Left %"PRIu32" Top %"PRIu32" cbVisibleRect %"PRIu32" num_rects %d",
- numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
++ numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
+
+ if (num_rects > 0)
{
- if (num_rects > 0)
+ rects = (RDP_RECT*) calloc(num_rects, sizeof(RDP_RECT));
+
+ 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);
- Stream_Read_UINT16(ifman->input, rects[i].x); /* Left */
- Stream_Seek_UINT16(ifman->input);
- Stream_Read_UINT16(ifman->input, rects[i].height); /* Bottom */
- Stream_Seek_UINT16(ifman->input);
- Stream_Read_UINT16(ifman->input, rects[i].width); /* Right */
- Stream_Seek_UINT16(ifman->input);
- rects[i].width -= rects[i].x;
- rects[i].height -= rects[i].y;
- DEBUG_TSMF("rect %d: %d %d %d %d", i,
- rects[i].x, rects[i].y, rects[i].width, rects[i].height);
- }
+ Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
+ Stream_Seek_UINT16(ifman->input);
+ Stream_Read_UINT16(ifman->input, rects[i].x); /* Left */
+ Stream_Seek_UINT16(ifman->input);
+ Stream_Read_UINT16(ifman->input, rects[i].height); /* Bottom */
+ Stream_Seek_UINT16(ifman->input);
+ Stream_Read_UINT16(ifman->input, rects[i].width); /* Right */
+ Stream_Seek_UINT16(ifman->input);
+ rects[i].width -= rects[i].x;
+ rects[i].height -= rects[i].y;
+ DEBUG_TSMF("rect %d: %"PRId16" %"PRId16" %"PRId16" %"PRId16"", i,
- rects[i].x, rects[i].y, rects[i].width, rects[i].height);
++ 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;
+ if (!tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects))
+ return ERROR_INVALID_OPERATION;
-
+ ifman->output_pending = TRUE;
return error;
}
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_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);
+ if (Stream_GetRemainingLength(ifman->input) < cbData)
+ return ERROR_INVALID_DATA;
- "ThrottleDuration %"PRIu64" SampleExtensions %"PRIu32" cbData %"PRIu32"",
- ifman->message_id, StreamId, SampleStartTime, SampleEndTime,
- ThrottleDuration, SampleExtensions, cbData);
-
+ DEBUG_TSMF("MessageId %"PRIu32" StreamId %"PRIu32" SampleStartTime %"PRIu64" SampleEndTime %"PRIu64" "
++ "ThrottleDuration %"PRIu64" SampleExtensions %"PRIu32" cbData %"PRIu32"",
++ ifman->message_id, StreamId, SampleStartTime, SampleEndTime,
++ ThrottleDuration, SampleExtensions, cbData);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
if (!presentation)
if (!stream)
{
WLog_ERR(TAG, "unknown stream id");
- return 1;
+ return ERROR_NOT_FOUND;
}
- tsmf_stream_push_sample(stream, ifman->channel_callback,
- ifman->message_id, SampleStartTime, SampleEndTime,
- ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input));
+ if (!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)))
+ {
+ WLog_ERR(TAG, "unable to push sample");
+ return ERROR_OUTOFMEMORY;
+ }
- tsmf_presentation_sync(presentation);
- ifman->output_pending = TRUE;
+ if ((error = tsmf_presentation_sync(presentation)))
- {
- WLog_ERR(TAG, "tsmf_presentation_sync failed with error %"PRIu32"", error);
- return error;
- }
- ifman->output_pending = TRUE;
++ {
++ WLog_ERR(TAG, "tsmf_presentation_sync failed with error %"PRIu32"", error);
++ return error;
++ }
- return 0;
++ ifman->output_pending = TRUE;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
{
UINT32 StreamId;
TSMF_PRESENTATION* presentation;
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
-
- DEBUG_TSMF("StreamId %d", StreamId);
--
+ DEBUG_TSMF("StreamId %"PRIu32"", StreamId);
-
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
+
if (!presentation)
{
WLog_ERR(TAG, "unknown presentation id");
- return 1;
+ return ERROR_NOT_FOUND;
}
- tsmf_presentation_flush(presentation);
- ifman->output_pending = TRUE;
+ /* 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);
+
- return 0;
+ 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)
+/**
+ * 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;
+ TSMF_STREAM* stream = NULL;
TSMF_PRESENTATION* presentation;
- presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+ 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);
stream = tsmf_stream_find_by_id(presentation, StreamId);
if (stream)
- tsmf_stream_end(stream, ifman->message_id, ifman->channel_callback);
- tsmf_stream_end(stream);
++ tsmf_stream_end(stream, ifman->message_id, ifman->channel_callback);
}
- DEBUG_TSMF("StreamId %d", StreamId);
- if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
- return -1;
- 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 */
+ DEBUG_TSMF("StreamId %"PRIu32"", StreamId);
-
+ ifman->output_pending = TRUE;
-
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
-
- return 0;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
+ if (Stream_GetRemainingLength(ifman->input) < 16)
+ return ERROR_INVALID_DATA;
+
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if (presentation)
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;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
{
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));
else
WLog_ERR(TAG, "unknown presentation id");
- return 0;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
{
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)
- tsmf_presentation_restarted(presentation);
+ {
+ if (!tsmf_presentation_restarted(presentation))
+ return ERROR_INVALID_OPERATION;
+ }
else
WLog_ERR(TAG, "unknown presentation id");
- return 0;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION* presentation;
--
DEBUG_TSMF("");
--
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
+
if (presentation)
- tsmf_presentation_stop(presentation);
+ {
+ if (!tsmf_presentation_stop(presentation))
+ return ERROR_INVALID_OPERATION;
+ }
else
WLog_ERR(TAG, "unknown presentation id");
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;
+ return CHANNEL_RC_OK;
}
-int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman)
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+UINT tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
+
if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
- return -1;
+ return ERROR_OUTOFMEMORY;
+
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */
event.framePixFmt = sample->pixfmt;
event.frameWidth = sample->stream->width;
event.frameHeight = sample->stream->height;
-
+ event.x = presentation->x;
+ event.y = presentation->y;
+ event.width = presentation->width;
+ event.height = presentation->height;
+
+ if (presentation->nr_rects > 0)
+ {
+ event.numVisibleRects = presentation->nr_rects;
+ event.visibleRects = (RECTANGLE_16*) calloc(1, event.numVisibleRects * sizeof(RECTANGLE_16));
++
+ if (!event.visibleRects)
+ {
+ WLog_ERR(TAG, "can't allocate memory for copy rectangles");
+ return;
+ }
++
+ memcpy(event.visibleRects, presentation->rects, presentation->nr_rects * sizeof(RDP_RECT));
+ presentation->nr_rects = 0;
+ }
+
#if 0
/* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we
extract the Y values to create a grayscale image. */
tsmf->FrameEvent(tsmf, &event);
free(event.frameData);
- if(event.visibleRects != NULL)
+
++ if (event.visibleRects != NULL)
+ free(event.visibleRects);
}
+
+ return TRUE;
}
-static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
+static BOOL tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
{
UINT64 latency = 0;
TSMF_STREAM* stream = sample->stream;
{
HANDLE hdl[2];
TSMF_STREAM* stream = (TSMF_STREAM*) arg;
- DEBUG_TSMF("in %d", stream->stream_id);
-
+ UINT error = CHANNEL_RC_OK;
+ DEBUG_TSMF("in %"PRIu32"", stream->stream_id);
-
hdl[0] = stream->stopEvent;
hdl[1] = Queue_Event(stream->sample_ack_list);
presentation->y = y;
presentation->width = width;
presentation->height = height;
-
tmp_rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects);
- if(!num_rects)
- presentation->rects=NULL;
+
- if (!tmp_rects&&num_rects)
++ if (!num_rects)
++ presentation->rects = NULL;
+
++ if (!tmp_rects && num_rects)
+ return;
+
presentation->nr_rects = num_rects;
presentation->rects = tmp_rects;
-
CopyMemory(presentation->rects, rects, sizeof(RDP_RECT) * num_rects);
-
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
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);
++ stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func,
++ stream, CREATE_SUSPENDED, 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);
++ stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream,
++ CREATE_SUSPENDED, NULL);
- 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);
+ if (!stream->ack_thread)
+ goto error_ack_thread;
- ArrayList_Add(presentation->stream_list, stream);
+ if (ArrayList_Add(presentation->stream_list, stream) < 0)
+ goto error_add;
+ 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 %"PRIu32"!", GetLastError());
+
+error_ack_thread:
+ SetEvent(stream->stopEvent);
+
+ if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED)
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", 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;
}
-void tsmf_stream_start_threads (TSMF_STREAM* stream)
++void tsmf_stream_start_threads(TSMF_STREAM* stream)
+ {
+ ResumeThread(stream->play_thread);
+ ResumeThread(stream->ack_thread);
+ }
+
-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;