23 #include <freerdp/config.h>
30 #include <winpr/crt.h>
32 #include <winpr/stream.h>
34 #include "tsmf_types.h"
35 #include "tsmf_constants.h"
36 #include "tsmf_media.h"
37 #include "tsmf_codec.h"
39 #include "tsmf_ifman.h"
46 UINT tsmf_ifman_rim_exchange_capability_request(
TSMF_IFMAN* ifman)
48 UINT32 CapabilityValue = 0;
50 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 4))
51 return ERROR_INVALID_DATA;
53 Stream_Read_UINT32(ifman->input, CapabilityValue);
54 DEBUG_TSMF(
"server CapabilityValue %" PRIu32
"", CapabilityValue);
56 if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
57 return ERROR_INVALID_DATA;
59 Stream_Write_UINT32(ifman->output, 1);
60 Stream_Write_UINT32(ifman->output, 0);
69 UINT tsmf_ifman_exchange_capability_request(
TSMF_IFMAN* ifman)
71 UINT32 CapabilityType = 0;
72 UINT32 cbCapabilityLength = 0;
73 UINT32 numHostCapabilities = 0;
76 if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4))
77 return ERROR_OUTOFMEMORY;
79 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, ifman->input_size))
80 return ERROR_INVALID_DATA;
82 const size_t xpos = Stream_GetPosition(ifman->output);
83 Stream_Copy(ifman->input, ifman->output, ifman->input_size);
84 Stream_SetPosition(ifman->output, xpos);
86 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 4))
87 return ERROR_INVALID_DATA;
89 Stream_Read_UINT32(ifman->output, numHostCapabilities);
91 for (UINT32 i = 0; i < numHostCapabilities; i++)
93 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 8))
94 return ERROR_INVALID_DATA;
96 Stream_Read_UINT32(ifman->output, CapabilityType);
97 Stream_Read_UINT32(ifman->output, cbCapabilityLength);
99 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, cbCapabilityLength))
100 return ERROR_INVALID_DATA;
102 const size_t pos = Stream_GetPosition(ifman->output);
104 switch (CapabilityType)
108 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 4))
109 return ERROR_INVALID_DATA;
111 const UINT32 v = Stream_Get_UINT32(ifman->output);
113 DEBUG_TSMF(
"server protocol version %" PRIu32
"", v);
119 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->output, 4))
120 return ERROR_INVALID_DATA;
122 const UINT32 v = Stream_Get_UINT32(ifman->output);
124 DEBUG_TSMF(
"server supported platform %" PRIu32
"", v);
126 Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF |
127 MMREDIR_CAPABILITY_PLATFORM_DSHOW);
132 WLog_ERR(TAG,
"skipping unknown capability type %" PRIu32
"", CapabilityType);
136 Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
139 Stream_Write_UINT32(ifman->output, 0);
140 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
141 return CHANNEL_RC_OK;
149 UINT tsmf_ifman_check_format_support_request(
TSMF_IFMAN* ifman)
151 UINT32 numMediaType = 0;
152 UINT32 PlatformCookie = 0;
153 UINT32 FormatSupported = 1;
155 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 12))
156 return ERROR_INVALID_DATA;
158 Stream_Read_UINT32(ifman->input, PlatformCookie);
159 Stream_Seek_UINT32(ifman->input);
160 Stream_Read_UINT32(ifman->input, numMediaType);
161 DEBUG_TSMF(
"PlatformCookie %" PRIu32
" numMediaType %" PRIu32
"", PlatformCookie, numMediaType);
163 if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input))
167 DEBUG_TSMF(
"format ok.");
169 if (!Stream_EnsureRemainingCapacity(ifman->output, 12))
172 Stream_Write_UINT32(ifman->output, FormatSupported);
173 Stream_Write_UINT32(ifman->output, PlatformCookie);
174 Stream_Write_UINT32(ifman->output, 0);
175 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
176 return CHANNEL_RC_OK;
184 UINT tsmf_ifman_on_new_presentation(
TSMF_IFMAN* ifman)
186 UINT status = CHANNEL_RC_OK;
187 TSMF_PRESENTATION* presentation = NULL;
190 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE))
191 return ERROR_INVALID_DATA;
193 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
197 DEBUG_TSMF(
"Presentation already exists");
198 ifman->output_pending = FALSE;
199 return CHANNEL_RC_OK;
202 presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
205 status = ERROR_OUTOFMEMORY;
207 tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
209 ifman->output_pending = TRUE;
218 UINT tsmf_ifman_add_stream(
TSMF_IFMAN* ifman, rdpContext* rdpcontext)
221 UINT status = CHANNEL_RC_OK;
222 TSMF_STREAM* stream = NULL;
223 TSMF_PRESENTATION* presentation = NULL;
226 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 8))
227 return ERROR_INVALID_DATA;
229 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
230 Stream_Seek(ifman->input, GUID_SIZE);
234 WLog_ERR(TAG,
"unknown presentation id");
235 status = ERROR_NOT_FOUND;
239 Stream_Read_UINT32(ifman->input, StreamId);
240 Stream_Seek_UINT32(ifman->input);
241 stream = tsmf_stream_new(presentation, StreamId, rdpcontext);
245 WLog_ERR(TAG,
"failed to create stream");
246 return ERROR_OUTOFMEMORY;
249 if (!tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input))
251 WLog_ERR(TAG,
"failed to set stream format");
252 return ERROR_OUTOFMEMORY;
255 tsmf_stream_start_threads(stream);
258 ifman->output_pending = TRUE;
267 UINT tsmf_ifman_set_topology_request(
TSMF_IFMAN* ifman)
271 if (!Stream_EnsureRemainingCapacity(ifman->output, 8))
272 return ERROR_OUTOFMEMORY;
274 Stream_Write_UINT32(ifman->output, 1);
275 Stream_Write_UINT32(ifman->output, 0);
276 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
277 return CHANNEL_RC_OK;
285 UINT tsmf_ifman_remove_stream(
TSMF_IFMAN* ifman)
287 int status = CHANNEL_RC_OK;
289 TSMF_STREAM* stream = NULL;
290 TSMF_PRESENTATION* presentation = NULL;
293 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 20))
294 return ERROR_INVALID_DATA;
296 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
297 Stream_Seek(ifman->input, GUID_SIZE);
301 status = ERROR_NOT_FOUND;
305 Stream_Read_UINT32(ifman->input, StreamId);
306 stream = tsmf_stream_find_by_id(presentation, StreamId);
309 tsmf_stream_free(stream);
311 status = ERROR_NOT_FOUND;
314 ifman->output_pending = TRUE;
318 static float tsmf_stream_read_float(
wStream* s)
322 Stream_Read_UINT32(s, iValue);
323 CopyMemory(&fValue, &iValue, 4);
332 UINT tsmf_ifman_set_source_video_rect(
TSMF_IFMAN* ifman)
334 UINT status = CHANNEL_RC_OK;
339 TSMF_PRESENTATION* presentation = NULL;
342 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 32))
343 return ERROR_INVALID_DATA;
345 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
346 Stream_Seek(ifman->input, GUID_SIZE);
350 status = ERROR_NOT_FOUND;
354 Left = tsmf_stream_read_float(ifman->input);
355 Top = tsmf_stream_read_float(ifman->input);
356 Right = tsmf_stream_read_float(ifman->input);
357 Bottom = tsmf_stream_read_float(ifman->input);
358 DEBUG_TSMF(
"SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f", Left, Top, Right,
362 ifman->output_pending = TRUE;
371 UINT tsmf_ifman_shutdown_presentation(
TSMF_IFMAN* ifman)
373 TSMF_PRESENTATION* presentation = NULL;
376 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE))
377 return ERROR_INVALID_DATA;
379 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
382 tsmf_presentation_free(presentation);
385 WLog_ERR(TAG,
"unknown presentation id");
386 return ERROR_NOT_FOUND;
389 if (!Stream_EnsureRemainingCapacity(ifman->output, 4))
390 return ERROR_OUTOFMEMORY;
392 Stream_Write_UINT32(ifman->output, 0);
393 ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
394 return CHANNEL_RC_OK;
402 UINT tsmf_ifman_on_stream_volume(
TSMF_IFMAN* ifman)
404 TSMF_PRESENTATION* presentation = NULL;
405 UINT32 newVolume = 0;
407 DEBUG_TSMF(
"on stream volume");
409 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 8))
410 return ERROR_INVALID_DATA;
412 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
416 WLog_ERR(TAG,
"unknown presentation id");
417 return ERROR_NOT_FOUND;
420 Stream_Seek(ifman->input, 16);
421 Stream_Read_UINT32(ifman->input, newVolume);
422 DEBUG_TSMF(
"on stream volume: new volume=[%" PRIu32
"]", newVolume);
423 Stream_Read_UINT32(ifman->input, muted);
424 DEBUG_TSMF(
"on stream volume: muted=[%" PRIu32
"]", muted);
426 if (!tsmf_presentation_volume_changed(presentation, newVolume, muted))
427 return ERROR_INVALID_OPERATION;
429 ifman->output_pending = TRUE;
438 UINT tsmf_ifman_on_channel_volume(
TSMF_IFMAN* ifman)
440 TSMF_PRESENTATION* presentation = NULL;
441 DEBUG_TSMF(
"on channel volume");
443 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 8))
444 return ERROR_INVALID_DATA;
446 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
450 UINT32 channelVolume = 0;
451 UINT32 changedChannel = 0;
452 Stream_Seek(ifman->input, 16);
453 Stream_Read_UINT32(ifman->input, channelVolume);
454 DEBUG_TSMF(
"on channel volume: channel volume=[%" PRIu32
"]", channelVolume);
455 Stream_Read_UINT32(ifman->input, changedChannel);
456 DEBUG_TSMF(
"on stream volume: changed channel=[%" PRIu32
"]", changedChannel);
459 ifman->output_pending = TRUE;
460 return CHANNEL_RC_OK;
468 UINT tsmf_ifman_set_video_window(
TSMF_IFMAN* ifman)
471 ifman->output_pending = TRUE;
472 return CHANNEL_RC_OK;
480 UINT tsmf_ifman_update_geometry_info(
TSMF_IFMAN* ifman)
482 TSMF_PRESENTATION* presentation = NULL;
483 UINT32 numGeometryInfo = 0;
488 UINT32 cbVisibleRect = 0;
490 UINT error = CHANNEL_RC_OK;
493 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, GUID_SIZE + 32))
494 return ERROR_INVALID_DATA;
496 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
499 return ERROR_NOT_FOUND;
501 Stream_Seek(ifman->input, 16);
502 Stream_Read_UINT32(ifman->input, numGeometryInfo);
503 pos = Stream_GetPosition(ifman->input);
504 Stream_Seek(ifman->input, 12);
505 Stream_Read_UINT32(ifman->input, Width);
506 Stream_Read_UINT32(ifman->input, Height);
507 Stream_Read_UINT32(ifman->input, Left);
508 Stream_Read_UINT32(ifman->input, Top);
509 Stream_SetPosition(ifman->input, pos + numGeometryInfo);
510 Stream_Read_UINT32(ifman->input, cbVisibleRect);
511 const UINT32 num_rects = cbVisibleRect / 16;
512 DEBUG_TSMF(
"numGeometryInfo %" PRIu32
" Width %" PRIu32
" Height %" PRIu32
" Left %" PRIu32
513 " Top %" PRIu32
" cbVisibleRect %" PRIu32
" num_rects %d",
514 numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
520 for (
size_t i = 0; i < num_rects; i++)
522 Stream_Read_UINT32(ifman->input, rects[i].top);
523 Stream_Read_UINT32(ifman->input, rects[i].left);
524 Stream_Read_UINT32(ifman->input, rects[i].height);
525 Stream_Read_UINT32(ifman->input, rects[i].width);
526 rects[i].width -= rects[i].left;
527 rects[i].height -= rects[i].top;
528 DEBUG_TSMF(
"rect %d: %" PRId16
" %" PRId16
" %" PRId16
" %" PRId16
"", i, rects[i].x,
529 rects[i].y, rects[i].width, rects[i].height);
533 const BOOL rc = tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height,
537 return ERROR_INVALID_OPERATION;
539 ifman->output_pending = TRUE;
548 UINT tsmf_ifman_set_allocator(
TSMF_IFMAN* ifman)
551 ifman->output_pending = TRUE;
552 return CHANNEL_RC_OK;
560 UINT tsmf_ifman_notify_preroll(
TSMF_IFMAN* ifman)
563 tsmf_ifman_on_playback_paused(ifman);
564 ifman->output_pending = TRUE;
565 return CHANNEL_RC_OK;
575 TSMF_PRESENTATION* presentation = NULL;
576 TSMF_STREAM* stream = NULL;
578 UINT64 SampleStartTime = 0;
579 UINT64 SampleEndTime = 0;
580 UINT64 ThrottleDuration = 0;
581 UINT32 SampleExtensions = 0;
585 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 60))
586 return ERROR_INVALID_DATA;
588 Stream_Seek(ifman->input, 16);
589 Stream_Read_UINT32(ifman->input, StreamId);
590 Stream_Seek_UINT32(ifman->input);
591 Stream_Read_UINT64(ifman->input, SampleStartTime);
592 Stream_Read_UINT64(ifman->input, SampleEndTime);
593 Stream_Read_UINT64(ifman->input, ThrottleDuration);
594 Stream_Seek_UINT32(ifman->input);
595 Stream_Read_UINT32(ifman->input, SampleExtensions);
596 Stream_Read_UINT32(ifman->input, cbData);
598 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, cbData))
599 return ERROR_INVALID_DATA;
601 DEBUG_TSMF(
"MessageId %" PRIu32
" StreamId %" PRIu32
" SampleStartTime %" PRIu64
602 " SampleEndTime %" PRIu64
" "
603 "ThrottleDuration %" PRIu64
" SampleExtensions %" PRIu32
" cbData %" PRIu32
"",
604 ifman->message_id, StreamId, SampleStartTime, SampleEndTime, ThrottleDuration,
605 SampleExtensions, cbData);
606 presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
610 WLog_ERR(TAG,
"unknown presentation id");
611 return ERROR_NOT_FOUND;
614 stream = tsmf_stream_find_by_id(presentation, StreamId);
618 WLog_ERR(TAG,
"unknown stream id");
619 return ERROR_NOT_FOUND;
622 if (!tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id,
623 SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
624 cbData, Stream_Pointer(ifman->input)))
626 WLog_ERR(TAG,
"unable to push sample");
627 return ERROR_OUTOFMEMORY;
630 if ((error = tsmf_presentation_sync(presentation)))
632 WLog_ERR(TAG,
"tsmf_presentation_sync failed with error %" PRIu32
"", error);
636 ifman->output_pending = TRUE;
637 return CHANNEL_RC_OK;
648 TSMF_PRESENTATION* presentation = NULL;
649 TSMF_STREAM* stream = NULL;
651 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 20))
652 return ERROR_INVALID_DATA;
654 Stream_Seek(ifman->input, 16);
655 Stream_Read_UINT32(ifman->input, StreamId);
656 DEBUG_TSMF(
"StreamId %" PRIu32
"", StreamId);
657 presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
661 WLog_ERR(TAG,
"unknown presentation id");
662 return ERROR_NOT_FOUND;
668 stream = tsmf_stream_find_by_id(presentation, StreamId);
672 if (!tsmf_stream_flush(stream))
673 return ERROR_INVALID_OPERATION;
676 WLog_ERR(TAG,
"unknown stream id");
678 ifman->output_pending = TRUE;
679 return CHANNEL_RC_OK;
687 UINT tsmf_ifman_on_end_of_stream(
TSMF_IFMAN* ifman)
690 TSMF_STREAM* stream = NULL;
691 TSMF_PRESENTATION* presentation = NULL;
693 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 20))
694 return ERROR_INVALID_DATA;
696 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
697 Stream_Seek(ifman->input, 16);
698 Stream_Read_UINT32(ifman->input, StreamId);
702 stream = tsmf_stream_find_by_id(presentation, StreamId);
705 tsmf_stream_end(stream, ifman->message_id, ifman->channel_callback);
708 DEBUG_TSMF(
"StreamId %" PRIu32
"", StreamId);
709 ifman->output_pending = TRUE;
710 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
711 return CHANNEL_RC_OK;
719 UINT tsmf_ifman_on_playback_started(
TSMF_IFMAN* ifman)
721 TSMF_PRESENTATION* presentation = NULL;
724 if (!Stream_CheckAndLogRequiredLength(TAG, ifman->input, 16))
725 return ERROR_INVALID_DATA;
727 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
730 tsmf_presentation_start(presentation);
732 WLog_ERR(TAG,
"unknown presentation id");
734 if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
735 return ERROR_OUTOFMEMORY;
737 Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION);
738 Stream_Write_UINT32(ifman->output, 0);
739 Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED);
740 Stream_Write_UINT32(ifman->output, 0);
741 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
742 return CHANNEL_RC_OK;
750 UINT tsmf_ifman_on_playback_paused(
TSMF_IFMAN* ifman)
752 TSMF_PRESENTATION* presentation = NULL;
754 ifman->output_pending = TRUE;
756 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
760 if (!tsmf_presentation_paused(presentation))
761 return ERROR_INVALID_OPERATION;
764 WLog_ERR(TAG,
"unknown presentation id");
766 return CHANNEL_RC_OK;
774 UINT tsmf_ifman_on_playback_restarted(
TSMF_IFMAN* ifman)
776 TSMF_PRESENTATION* presentation = NULL;
778 ifman->output_pending = TRUE;
780 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
784 if (!tsmf_presentation_restarted(presentation))
785 return ERROR_INVALID_OPERATION;
788 WLog_ERR(TAG,
"unknown presentation id");
790 return CHANNEL_RC_OK;
798 UINT tsmf_ifman_on_playback_stopped(
TSMF_IFMAN* ifman)
800 TSMF_PRESENTATION* presentation = NULL;
802 presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
806 if (!tsmf_presentation_stop(presentation))
807 return ERROR_INVALID_OPERATION;
810 WLog_ERR(TAG,
"unknown presentation id");
812 if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
813 return ERROR_OUTOFMEMORY;
815 Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION);
816 Stream_Write_UINT32(ifman->output, 0);
817 Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED);
818 Stream_Write_UINT32(ifman->output, 0);
819 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
820 return CHANNEL_RC_OK;
828 UINT tsmf_ifman_on_playback_rate_changed(
TSMF_IFMAN* ifman)
832 if (!Stream_EnsureRemainingCapacity(ifman->output, 16))
833 return ERROR_OUTOFMEMORY;
835 Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION);
836 Stream_Write_UINT32(ifman->output, 0);
837 Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED);
838 Stream_Write_UINT32(ifman->output, 0);
839 ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
840 return CHANNEL_RC_OK;