23#include <freerdp/config.h>
35#include <winpr/synch.h>
36#include <winpr/string.h>
37#include <winpr/thread.h>
38#include <winpr/stream.h>
39#include <winpr/collections.h>
41#include <freerdp/freerdp.h>
42#include <freerdp/client/tsmf.h>
44#include "tsmf_constants.h"
45#include "tsmf_types.h"
46#include "tsmf_decoder.h"
47#include "tsmf_audio.h"
49#include "tsmf_codec.h"
50#include "tsmf_media.h"
52#define AUDIO_TOLERANCE 10000000LL
55#define VIDEO_ADJUST_MAX (10ULL * 1000ULL * 1000ULL)
57#define MAX_ACK_TIME 666667
59#define AUDIO_MIN_BUFFER_LEVEL 3
60#define AUDIO_MAX_BUFFER_LEVEL 6
62#define VIDEO_MIN_BUFFER_LEVEL 10
63#define VIDEO_MAX_BUFFER_LEVEL 30
65struct S_TSMF_PRESENTATION
67 BYTE presentation_id[GUID_SIZE];
69 const char* audio_name;
70 const char* audio_device;
72 IWTSVirtualChannelCallback* channel_callback;
74 UINT64 audio_start_time;
75 UINT64 audio_end_time;
80 wArrayList* stream_list;
92 TSMF_PRESENTATION* presentation;
94 ITSMFDecoder* decoder;
98 UINT32 eos_message_id;
99 IWTSVirtualChannelCallback* eos_channel_callback;
104 ITSMFAudioDevice* audio;
107 UINT32 bits_per_sample;
110 UINT64 last_start_time;
112 UINT64 last_end_time;
114 UINT64 next_start_time;
116 UINT32 minBufferLevel;
117 UINT32 maxBufferLevel;
118 UINT32 currentBufferLevel;
126 wQueue* sample_ack_list;
127 rdpContext* rdpcontext;
144 BOOL invalidTimestamps;
147 IWTSVirtualChannelCallback* channel_callback;
151static wArrayList* presentation_list = NULL;
152static int TERMINATING = 0;
154static void s_tsmf_presentation_free(
void* obj);
155static void s_tsmf_stream_free(
void* obj);
157static UINT64 get_current_time(
void)
160 gettimeofday(&tp, 0);
161 return ((UINT64)tp.tv_sec) * 10000000LL + ((UINT64)tp.tv_usec) * 10LL;
164static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream,
int sync)
166 TSMF_SAMPLE* sample = NULL;
167 BOOL pending = FALSE;
172 TSMF_PRESENTATION* presentation = stream->presentation;
174 if (Queue_Count(stream->sample_list) < 1)
181 if (stream->decoder->GetDecodedData)
183 if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
190 if (stream->last_start_time > AUDIO_TOLERANCE)
192 ArrayList_Lock(presentation->stream_list);
193 const size_t count = ArrayList_Count(presentation->stream_list);
195 for (
size_t index = 0; index < count; index++)
198 (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
203 if (s != stream && !s->eos && s->last_start_time &&
204 s->last_start_time < stream->last_start_time - AUDIO_TOLERANCE)
206 DEBUG_TSMF(
"Pending due to audio tolerance");
212 ArrayList_Unlock(presentation->stream_list);
220 if (stream->last_start_time > presentation->audio_start_time)
222 DEBUG_TSMF(
"Pending due to stream start time > audio start time");
233 sample = (TSMF_SAMPLE*)Queue_Dequeue(stream->sample_list);
237 if (sample && (sample->end_time > stream->last_end_time) && (!sample->invalidTimestamps))
238 stream->last_end_time = sample->end_time;
242 if (sample && (sample->start_time > stream->last_start_time) && (!sample->invalidTimestamps))
243 stream->last_start_time = sample->start_time;
248static void tsmf_sample_free(
void* arg)
250 TSMF_SAMPLE* sample = arg;
259static BOOL tsmf_sample_ack(TSMF_SAMPLE* sample)
264 return tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration,
268static BOOL tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
276 return Queue_Enqueue(sample->stream->sample_ack_list, sample);
282static BOOL tsmf_stream_process_ack(
void* arg, BOOL force)
284 TSMF_STREAM* stream = arg;
285 TSMF_SAMPLE* sample = NULL;
292 Queue_Lock(stream->sample_ack_list);
293 sample = (TSMF_SAMPLE*)Queue_Peek(stream->sample_ack_list);
304 if (stream->decoder && stream->decoder->BufferLevel)
307 if (stream->currentBufferLevel > stream->maxBufferLevel)
310 else if (stream->currentBufferLevel < stream->minBufferLevel)
315 ack_time = get_current_time();
317 if (sample->ack_time > ack_time)
322 sample = Queue_Dequeue(stream->sample_ack_list);
326 tsmf_sample_ack(sample);
327 tsmf_sample_free(sample);
331 Queue_Unlock(stream->sample_ack_list);
335TSMF_PRESENTATION* tsmf_presentation_new(
const BYTE* guid,
336 IWTSVirtualChannelCallback* pChannelCallback)
339 TSMF_PRESENTATION* presentation = NULL;
341 if (!guid || !pChannelCallback)
344 presentation = (TSMF_PRESENTATION*)calloc(1,
sizeof(TSMF_PRESENTATION));
348 WLog_ERR(TAG,
"calloc failed");
352 CopyMemory(presentation->presentation_id, guid, GUID_SIZE);
353 presentation->channel_callback = pChannelCallback;
354 presentation->volume = 5000;
355 presentation->muted = 0;
357 if (!(presentation->stream_list = ArrayList_New(TRUE)))
358 goto error_stream_list;
360 obj = ArrayList_Object(presentation->stream_list);
363 obj->fnObjectFree = s_tsmf_stream_free;
365 if (!ArrayList_Append(presentation_list, presentation))
370 ArrayList_Free(presentation->stream_list);
376static char* guid_to_string(
const BYTE* guid,
char* str,
size_t len)
381 for (
size_t i = 0; i < GUID_SIZE && (len > 2 * i); i++)
382 (
void)sprintf_s(str + (2 * i), len - 2 * i,
"%02" PRIX8
"", guid[i]);
387TSMF_PRESENTATION* tsmf_presentation_find_by_id(
const BYTE* guid)
390 char guid_str[GUID_SIZE * 2 + 1] = { 0 };
391 TSMF_PRESENTATION* presentation = NULL;
392 ArrayList_Lock(presentation_list);
393 const size_t count = ArrayList_Count(presentation_list);
395 for (
size_t index = 0; index < count; index++)
397 presentation = (TSMF_PRESENTATION*)ArrayList_GetItem(presentation_list, index);
399 if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0)
406 ArrayList_Unlock(presentation_list);
409 WLog_WARN(TAG,
"presentation id %s not found",
410 guid_to_string(guid, guid_str,
sizeof(guid_str)));
412 return (found) ? presentation : NULL;
415static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
417 WINPR_ASSERT(sample);
419 TSMF_STREAM* stream = sample->stream;
420 TSMF_PRESENTATION* presentation = stream->presentation;
422 TsmfClientContext* tsmf = (TsmfClientContext*)callback->plugin->pInterface;
423 DEBUG_TSMF(
"MessageId %" PRIu32
" EndTime %" PRIu64
" data_size %" PRIu32
" consumed.",
424 sample->sample_id, sample->end_time, sample->data_size);
428 const UINT64 t = get_current_time();
433 if (stream->next_start_time > t &&
434 ((sample->start_time >= presentation->audio_start_time) ||
435 ((sample->start_time < stream->last_start_time) && (!sample->invalidTimestamps))))
437 size_t delay = (stream->next_start_time - t) / 10;
440 const UINT32 d = (delay > UINT32_MAX) ? UINT32_MAX : (UINT32)delay;
446 if (sample->stream->width > INT16_MAX)
448 if (sample->stream->height > INT16_MAX)
450 if (presentation->rect.left > INT16_MAX)
452 if (presentation->rect.top > INT16_MAX)
454 if (presentation->rect.width > INT16_MAX)
456 if (presentation->rect.height > INT16_MAX)
458 if (presentation->nr_rects > UINT16_MAX)
461 stream->next_start_time = t + sample->duration - 50000;
464 event.frameData = sample->data;
465 event.frameSize = sample->decoded_size;
466 event.framePixFmt = sample->pixfmt;
467 event.frameWidth = (INT16)sample->stream->width;
468 event.frameHeight = (INT16)sample->stream->height;
469 event.x = (INT16)presentation->rect.left;
470 event.y = (INT16)presentation->rect.top;
471 event.width = (INT16)presentation->rect.width;
472 event.height = (INT16)presentation->rect.height;
474 if (presentation->nr_rects > 0)
476 event.numVisibleRects = (UINT16)presentation->nr_rects;
479 if (!event.visibleRects)
481 WLog_ERR(TAG,
"can't allocate memory for copy rectangles");
485 for (
size_t x = 0; x < presentation->nr_rects; x++)
489 if ((cur->left > UINT16_MAX) || (cur->top > UINT16_MAX) ||
490 (cur->width > UINT16_MAX) || (cur->height > UINT16_MAX))
492 free(event.visibleRects);
495 dst->right = dst->left = (UINT16)cur->left;
496 dst->bottom = dst->top = (UINT16)cur->top;
497 dst->right += (UINT16)cur->width;
498 dst->bottom += (UINT16)cur->height;
500 memcpy(event.visibleRects, presentation->rects,
502 presentation->nr_rects = 0;
508 sample->decoded_size = 0;
510 if (tsmf->FrameEvent)
511 tsmf->FrameEvent(tsmf, &event);
513 free(event.frameData);
514 free(event.visibleRects);
520static BOOL tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
523 TSMF_STREAM* stream = sample->stream;
525 DEBUG_TSMF(
"MessageId %" PRIu32
" EndTime %" PRIu64
" consumed.", sample->sample_id,
528 if (stream->audio && sample->data)
531 sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size);
534 sample->decoded_size = 0;
536 if (stream->audio->GetLatency)
537 latency = stream->audio->GetLatency(stream->audio);
545 sample->ack_time = latency + get_current_time();
548 if (!sample->invalidTimestamps)
550 stream->last_start_time = sample->start_time + latency;
551 stream->last_end_time = sample->end_time + latency;
552 stream->presentation->audio_start_time = sample->start_time + latency;
553 stream->presentation->audio_end_time = sample->end_time + latency;
559static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
565 TSMF_STREAM* stream = sample->stream;
569 if (stream->decoder->DecodeEx)
576 if (stream->major_type == TSMF_MAJOR_TYPE_VIDEO)
578 TSMF_STREAM* temp_stream = NULL;
579 TSMF_PRESENTATION* presentation = stream->presentation;
580 ArrayList_Lock(presentation->stream_list);
581 const size_t count = ArrayList_Count(presentation->stream_list);
583 for (
size_t index = 0; index < count; index++)
585 UINT64 time_diff = 0;
586 temp_stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
588 if (temp_stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
590 UINT64 video_time = stream->decoder->GetRunningTime(stream->decoder);
592 temp_stream->decoder->GetRunningTime(temp_stream->decoder);
593 UINT64 max_adjust = VIDEO_ADJUST_MAX;
595 if (video_time < audio_time)
596 max_adjust = -VIDEO_ADJUST_MAX;
598 if (video_time > audio_time)
599 time_diff = video_time - audio_time;
601 time_diff = audio_time - video_time;
603 time_diff = time_diff < VIDEO_ADJUST_MAX ? time_diff : max_adjust;
604 sample->start_time += time_diff;
605 sample->end_time += time_diff;
610 ArrayList_Unlock(presentation->stream_list);
613 ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size,
614 sample->extensions, sample->start_time,
615 sample->end_time, sample->duration);
619 ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size,
626 WLog_ERR(TAG,
"decode error, queue ack anyways");
628 if (!tsmf_sample_queue_ack(sample))
630 WLog_ERR(TAG,
"error queuing sample for ack");
640 if (stream->major_type == TSMF_MAJOR_TYPE_VIDEO)
642 if (stream->decoder->GetDecodedFormat)
644 pixfmt = stream->decoder->GetDecodedFormat(stream->decoder);
646 if (pixfmt == ((UINT32)-1))
648 WLog_ERR(TAG,
"unable to decode video format");
650 if (!tsmf_sample_queue_ack(sample))
652 WLog_ERR(TAG,
"error queuing sample for ack");
658 sample->pixfmt = pixfmt;
661 if (stream->decoder->GetDecodedDimension)
663 ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height);
665 if (ret && (width != stream->width || height != stream->height))
667 DEBUG_TSMF(
"video dimension changed to %" PRIu32
" x %" PRIu32
"", width, height);
668 stream->width = width;
669 stream->height = height;
674 if (stream->decoder->GetDecodedData)
676 sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size);
678 switch (sample->stream->major_type)
680 case TSMF_MAJOR_TYPE_VIDEO:
681 ret = tsmf_sample_playback_video(sample) && tsmf_sample_queue_ack(sample);
684 case TSMF_MAJOR_TYPE_AUDIO:
685 ret = tsmf_sample_playback_audio(sample) && tsmf_sample_queue_ack(sample);
693 UINT64 ack_anticipation_time = get_current_time();
695 ack_anticipation_time +=
696 (sample->duration / 2 < MAX_ACK_TIME) ? sample->duration / 2 : MAX_ACK_TIME;
698 switch (sample->stream->major_type)
700 case TSMF_MAJOR_TYPE_VIDEO:
705 case TSMF_MAJOR_TYPE_AUDIO:
713 sample->ack_time = ack_anticipation_time;
715 if (!tsmf_sample_queue_ack(sample))
717 WLog_ERR(TAG,
"error queuing sample for ack");
725static DWORD WINAPI tsmf_stream_ack_func(LPVOID arg)
728 TSMF_STREAM* stream = (TSMF_STREAM*)arg;
729 UINT error = CHANNEL_RC_OK;
730 DEBUG_TSMF(
"in %" PRIu32
"", stream->stream_id);
731 hdl[0] = stream->stopEvent;
732 hdl[1] = Queue_Event(stream->sample_ack_list);
736 DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, 1000);
738 if (ev == WAIT_FAILED)
740 error = GetLastError();
741 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
746 if (stream->decoder->BufferLevel)
747 stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
751 while ((stream->currentBufferLevel > 0) && !(tsmf_stream_process_ack(stream, TRUE)))
753 DEBUG_TSMF(
"END OF STREAM PROCESSING!");
755 if (stream->decoder && stream->decoder->BufferLevel)
756 stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
758 stream->currentBufferLevel = 1;
763 tsmf_send_eos_response(stream->eos_channel_callback, stream->eos_message_id);
766 if (stream->delayed_stop)
768 DEBUG_TSMF(
"Finishing delayed stream stop, now that eos has processed.");
769 tsmf_stream_flush(stream);
771 if (stream->decoder && stream->decoder->Control)
772 stream->decoder->Control(stream->decoder, Control_Stop, NULL);
777 if (ev == WAIT_OBJECT_0)
779 DEBUG_TSMF(
"ack: Stream stopped!");
783 if (tsmf_stream_process_ack(stream, TRUE))
792 if (tsmf_stream_process_ack(stream, FALSE))
795 if (stream->currentBufferLevel > stream->minBufferLevel)
799 if (error && stream->rdpcontext)
800 setChannelError(stream->rdpcontext, error,
"tsmf_stream_ack_func reported an error");
802 DEBUG_TSMF(
"out %" PRIu32
"", stream->stream_id);
807static DWORD WINAPI tsmf_stream_playback_func(LPVOID arg)
810 TSMF_SAMPLE* sample = NULL;
811 TSMF_STREAM* stream = (TSMF_STREAM*)arg;
812 TSMF_PRESENTATION* presentation = stream->presentation;
813 UINT error = CHANNEL_RC_OK;
815 DEBUG_TSMF(
"in %" PRIu32
"", stream->stream_id);
817 if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && stream->sample_rate && stream->channels &&
818 stream->bits_per_sample)
822 if (stream->decoder->GetDecodedData)
824 stream->audio = tsmf_load_audio_device(
825 presentation->audio_name && presentation->audio_name[0]
826 ? presentation->audio_name
828 presentation->audio_device && presentation->audio_device[0]
829 ? presentation->audio_device
834 stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels,
835 stream->bits_per_sample);
841 hdl[0] = stream->stopEvent;
842 hdl[1] = Queue_Event(stream->sample_list);
846 status = WaitForMultipleObjects(2, hdl, FALSE, 1000);
848 if (status == WAIT_FAILED)
850 error = GetLastError();
851 WLog_ERR(TAG,
"WaitForMultipleObjects failed with error %" PRIu32
"!", error);
855 status = WaitForSingleObject(stream->stopEvent, 0);
857 if (status == WAIT_FAILED)
859 error = GetLastError();
860 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
864 if (status == WAIT_OBJECT_0)
868 if (stream->decoder->BufferLevel)
869 stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
871 sample = tsmf_stream_pop_sample(stream, 0);
873 if (sample && !tsmf_sample_playback(sample))
875 WLog_ERR(TAG,
"error playing sample");
876 error = ERROR_INTERNAL_ERROR;
880 if (stream->currentBufferLevel > stream->minBufferLevel)
886 stream->audio->Free(stream->audio);
887 stream->audio = NULL;
890 if (error && stream->rdpcontext)
891 setChannelError(stream->rdpcontext, error,
"tsmf_stream_playback_func reported an error");
893 DEBUG_TSMF(
"out %" PRIu32
"", stream->stream_id);
898static BOOL tsmf_stream_start(TSMF_STREAM* stream)
900 if (!stream || !stream->presentation || !stream->decoder || !stream->decoder->Control)
904 return stream->decoder->Control(stream->decoder, Control_Restart, NULL);
907static BOOL tsmf_stream_stop(TSMF_STREAM* stream)
909 if (!stream || !stream->decoder || !stream->decoder->Control)
918 DEBUG_TSMF(
"Setting up a delayed stop for once the eos has been processed.");
919 stream->delayed_stop = 1;
925 DEBUG_TSMF(
"Stop with no pending eos response, so do it immediately.");
926 tsmf_stream_flush(stream);
927 return stream->decoder->Control(stream->decoder, Control_Stop, NULL);
931static BOOL tsmf_stream_pause(TSMF_STREAM* stream)
933 if (!stream || !stream->decoder || !stream->decoder->Control)
936 return stream->decoder->Control(stream->decoder, Control_Pause, NULL);
939static BOOL tsmf_stream_restart(TSMF_STREAM* stream)
941 if (!stream || !stream->decoder || !stream->decoder->Control)
945 return stream->decoder->Control(stream->decoder, Control_Restart, NULL);
948static BOOL tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted)
950 if (!stream || !stream->decoder)
953 if (stream->decoder != NULL && stream->decoder->ChangeVolume)
955 return stream->decoder->ChangeVolume(stream->decoder, newVolume, muted);
957 else if (stream->audio != NULL && stream->audio->ChangeVolume)
959 return stream->audio->ChangeVolume(stream->audio, newVolume, muted);
965BOOL tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume,
968 TSMF_STREAM* stream = NULL;
970 presentation->volume = newVolume;
971 presentation->muted = muted;
972 ArrayList_Lock(presentation->stream_list);
973 size_t count = ArrayList_Count(presentation->stream_list);
975 for (
size_t index = 0; index < count; index++)
977 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
978 ret &= tsmf_stream_change_volume(stream, newVolume, muted);
981 ArrayList_Unlock(presentation->stream_list);
985BOOL tsmf_presentation_paused(TSMF_PRESENTATION* presentation)
987 TSMF_STREAM* stream = NULL;
989 ArrayList_Lock(presentation->stream_list);
990 size_t count = ArrayList_Count(presentation->stream_list);
992 for (
size_t index = 0; index < count; index++)
994 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
995 ret &= tsmf_stream_pause(stream);
998 ArrayList_Unlock(presentation->stream_list);
1002BOOL tsmf_presentation_restarted(TSMF_PRESENTATION* presentation)
1004 TSMF_STREAM* stream = NULL;
1006 ArrayList_Lock(presentation->stream_list);
1007 size_t count = ArrayList_Count(presentation->stream_list);
1009 for (
size_t index = 0; index < count; index++)
1011 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1012 ret &= tsmf_stream_restart(stream);
1015 ArrayList_Unlock(presentation->stream_list);
1019BOOL tsmf_presentation_start(TSMF_PRESENTATION* presentation)
1021 TSMF_STREAM* stream = NULL;
1023 ArrayList_Lock(presentation->stream_list);
1024 size_t count = ArrayList_Count(presentation->stream_list);
1026 for (
size_t index = 0; index < count; index++)
1028 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1029 ret &= tsmf_stream_start(stream);
1032 ArrayList_Unlock(presentation->stream_list);
1041UINT tsmf_presentation_sync(TSMF_PRESENTATION* presentation)
1044 ArrayList_Lock(presentation->stream_list);
1045 size_t count = ArrayList_Count(presentation->stream_list);
1047 for (
size_t index = 0; index < count; index++)
1049 TSMF_STREAM* stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1051 if (WaitForSingleObject(stream->ready, 500) == WAIT_FAILED)
1053 error = GetLastError();
1054 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", error);
1059 ArrayList_Unlock(presentation->stream_list);
1060 return CHANNEL_RC_OK;
1063BOOL tsmf_presentation_stop(TSMF_PRESENTATION* presentation)
1065 TSMF_STREAM* stream = NULL;
1067 ArrayList_Lock(presentation->stream_list);
1068 size_t count = ArrayList_Count(presentation->stream_list);
1070 for (
size_t index = 0; index < count; index++)
1072 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1073 ret &= tsmf_stream_stop(stream);
1076 ArrayList_Unlock(presentation->stream_list);
1077 presentation->audio_start_time = 0;
1078 presentation->audio_end_time = 0;
1082BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, UINT32 x, UINT32 y,
1083 UINT32 width, UINT32 height, UINT32 num_rects,
1086 TSMF_STREAM* stream = NULL;
1091 if (!width || !height)
1099 presentation->rect.left = x;
1100 presentation->rect.top = y;
1101 presentation->rect.width = width;
1102 presentation->rect.height = height;
1103 void* tmp_rects = realloc(presentation->rects,
sizeof(
RECTANGLE_32) * num_rects);
1105 if (!tmp_rects && num_rects)
1108 presentation->nr_rects = num_rects;
1110 if (presentation->rects)
1111 CopyMemory(presentation->rects, rects,
sizeof(
RECTANGLE_32) * num_rects);
1112 ArrayList_Lock(presentation->stream_list);
1113 size_t count = ArrayList_Count(presentation->stream_list);
1115 for (
size_t index = 0; index < count; index++)
1117 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1119 if (!stream->decoder)
1122 if (stream->decoder->UpdateRenderingArea)
1124 ret = stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height,
1129 ArrayList_Unlock(presentation->stream_list);
1133void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation,
const char* name,
1136 presentation->audio_name = name;
1137 presentation->audio_device = device;
1140BOOL tsmf_stream_flush(TSMF_STREAM* stream)
1147 ret = stream->audio->Flush(stream->audio);
1150 stream->eos_message_id = 0;
1151 stream->eos_channel_callback = NULL;
1152 stream->delayed_stop = 0;
1153 stream->last_end_time = 0;
1154 stream->next_start_time = 0;
1156 if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
1158 stream->presentation->audio_start_time = 0;
1159 stream->presentation->audio_end_time = 0;
1165void s_tsmf_presentation_free(
void* obj)
1167 TSMF_PRESENTATION* presentation = (TSMF_PRESENTATION*)obj;
1171 tsmf_presentation_stop(presentation);
1172 ArrayList_Clear(presentation->stream_list);
1173 ArrayList_Free(presentation->stream_list);
1174 free(presentation->rects);
1175 ZeroMemory(presentation,
sizeof(TSMF_PRESENTATION));
1180void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
1182 ArrayList_Remove(presentation_list, presentation);
1185TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
1186 rdpContext* rdpcontext)
1189 TSMF_STREAM* stream = NULL;
1190 stream = tsmf_stream_find_by_id(presentation, stream_id);
1194 WLog_ERR(TAG,
"duplicated stream id %" PRIu32
"!", stream_id);
1198 stream = (TSMF_STREAM*)calloc(1,
sizeof(TSMF_STREAM));
1202 WLog_ERR(TAG,
"Calloc failed");
1206 stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL;
1207 stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL;
1208 stream->currentBufferLevel = 1;
1209 stream->seeking = FALSE;
1211 stream->eos_message_id = 0;
1212 stream->eos_channel_callback = NULL;
1213 stream->stream_id = stream_id;
1214 stream->presentation = presentation;
1215 stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1217 if (!stream->stopEvent)
1218 goto error_stopEvent;
1220 stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL);
1225 stream->sample_list = Queue_New(TRUE, -1, -1);
1227 if (!stream->sample_list)
1228 goto error_sample_list;
1230 obj = Queue_Object(stream->sample_list);
1232 goto error_sample_ack_list;
1233 obj->fnObjectFree = tsmf_sample_free;
1235 stream->sample_ack_list = Queue_New(TRUE, -1, -1);
1237 if (!stream->sample_ack_list)
1238 goto error_sample_ack_list;
1240 obj = Queue_Object(stream->sample_ack_list);
1242 goto error_play_thread;
1243 obj->fnObjectFree = tsmf_sample_free;
1245 stream->play_thread =
1246 CreateThread(NULL, 0, tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
1248 if (!stream->play_thread)
1249 goto error_play_thread;
1251 stream->ack_thread =
1252 CreateThread(NULL, 0, tsmf_stream_ack_func, stream, CREATE_SUSPENDED, NULL);
1254 if (!stream->ack_thread)
1255 goto error_ack_thread;
1257 if (!ArrayList_Append(presentation->stream_list, stream))
1260 stream->rdpcontext = rdpcontext;
1263 (void)SetEvent(stream->stopEvent);
1265 if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED)
1266 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", GetLastError());
1269 (void)SetEvent(stream->stopEvent);
1271 if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED)
1272 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", GetLastError());
1275 Queue_Free(stream->sample_ack_list);
1276error_sample_ack_list:
1277 Queue_Free(stream->sample_list);
1279 (void)CloseHandle(stream->ready);
1281 (void)CloseHandle(stream->stopEvent);
1287void tsmf_stream_start_threads(TSMF_STREAM* stream)
1289 ResumeThread(stream->play_thread);
1290 ResumeThread(stream->ack_thread);
1293TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id)
1296 TSMF_STREAM* stream = NULL;
1297 ArrayList_Lock(presentation->stream_list);
1298 size_t count = ArrayList_Count(presentation->stream_list);
1300 for (
size_t index = 0; index < count; index++)
1302 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1304 if (stream->stream_id == stream_id)
1311 ArrayList_Unlock(presentation->stream_list);
1312 return (found) ? stream : NULL;
1315static void tsmf_stream_resync(
void* arg)
1317 TSMF_STREAM* stream = arg;
1318 (void)ResetEvent(stream->ready);
1321BOOL tsmf_stream_set_format(TSMF_STREAM* stream,
const char* name,
wStream* s)
1326 if (stream->decoder)
1328 WLog_ERR(TAG,
"duplicated call");
1332 if (!tsmf_codec_parse_media_type(&mediatype, s))
1334 WLog_ERR(TAG,
"unable to parse media type");
1338 if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO)
1340 DEBUG_TSMF(
"video width %" PRIu32
" height %" PRIu32
" bit_rate %" PRIu32
1341 " frame_rate %f codec_data %" PRIu32
"",
1342 mediatype.Width, mediatype.Height, mediatype.BitRate,
1343 (
double)mediatype.SamplesPerSecond.Numerator /
1344 (
double)mediatype.SamplesPerSecond.Denominator,
1345 mediatype.ExtraDataSize);
1346 stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL;
1347 stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL;
1349 else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO)
1351 DEBUG_TSMF(
"audio channel %" PRIu32
" sample_rate %" PRIu32
" bits_per_sample %" PRIu32
1352 " codec_data %" PRIu32
"",
1353 mediatype.Channels, mediatype.SamplesPerSecond.Numerator,
1354 mediatype.BitsPerSample, mediatype.ExtraDataSize);
1355 stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
1356 stream->channels = mediatype.Channels;
1357 stream->bits_per_sample = mediatype.BitsPerSample;
1359 if (stream->bits_per_sample == 0)
1360 stream->bits_per_sample = 16;
1362 stream->minBufferLevel = AUDIO_MIN_BUFFER_LEVEL;
1363 stream->maxBufferLevel = AUDIO_MAX_BUFFER_LEVEL;
1366 stream->major_type = mediatype.MajorType;
1367 stream->width = mediatype.Width;
1368 stream->height = mediatype.Height;
1369 stream->decoder = tsmf_load_decoder(name, &mediatype);
1370 ret &= tsmf_stream_change_volume(stream, stream->presentation->volume,
1371 stream->presentation->muted);
1373 if (!stream->decoder)
1376 if (stream->decoder->SetAckFunc)
1377 ret &= stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack, stream);
1379 if (stream->decoder->SetSyncFunc)
1380 ret &= stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream);
1385void tsmf_stream_end(TSMF_STREAM* stream, UINT32 message_id,
1386 IWTSVirtualChannelCallback* pChannelCallback)
1392 stream->eos_message_id = message_id;
1393 stream->eos_channel_callback = pChannelCallback;
1396void s_tsmf_stream_free(
void* obj)
1398 TSMF_STREAM* stream = (TSMF_STREAM*)obj;
1403 tsmf_stream_stop(stream);
1404 (void)SetEvent(stream->stopEvent);
1406 if (stream->play_thread)
1408 if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED)
1410 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", GetLastError());
1414 (void)CloseHandle(stream->play_thread);
1415 stream->play_thread = NULL;
1418 if (stream->ack_thread)
1420 if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED)
1422 WLog_ERR(TAG,
"WaitForSingleObject failed with error %" PRIu32
"!", GetLastError());
1426 (void)CloseHandle(stream->ack_thread);
1427 stream->ack_thread = NULL;
1430 Queue_Free(stream->sample_list);
1431 Queue_Free(stream->sample_ack_list);
1433 if (stream->decoder && stream->decoder->Free)
1435 stream->decoder->Free(stream->decoder);
1436 stream->decoder = NULL;
1439 (void)CloseHandle(stream->stopEvent);
1440 (void)CloseHandle(stream->ready);
1441 ZeroMemory(stream,
sizeof(TSMF_STREAM));
1445void tsmf_stream_free(TSMF_STREAM* stream)
1447 TSMF_PRESENTATION* presentation = stream->presentation;
1448 ArrayList_Remove(presentation->stream_list, stream);
1451BOOL tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
1452 UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration,
1453 UINT32 extensions, UINT32 data_size, BYTE* data)
1455 (void)SetEvent(stream->ready);
1460 TSMF_SAMPLE* sample = (TSMF_SAMPLE*)calloc(1,
sizeof(TSMF_SAMPLE));
1464 WLog_ERR(TAG,
"calloc sample failed!");
1468 sample->sample_id = sample_id;
1469 sample->start_time = start_time;
1470 sample->end_time = end_time;
1471 sample->duration = duration;
1472 sample->extensions = extensions;
1474 if ((sample->extensions & 0x00000080) || (sample->extensions & 0x00000040))
1475 sample->invalidTimestamps = TRUE;
1477 sample->invalidTimestamps = FALSE;
1479 sample->stream = stream;
1480 sample->channel_callback = pChannelCallback;
1481 sample->data_size = data_size;
1482 sample->data = calloc(1, data_size + TSMF_BUFFER_PADDING_SIZE);
1487 CopyMemory(sample->data, data, data_size);
1488 if (!Queue_Enqueue(stream->sample_list, sample))
1503static void tsmf_signal_handler(
int s)
1506 ArrayList_Free(presentation_list);
1510 (void)signal(s, SIG_DFL);
1513 else if (s == SIGUSR1)
1515 (void)signal(s, SIG_DFL);
1521BOOL tsmf_media_init(
void)
1525 struct sigaction sigtrap;
1526 sigtrap.sa_handler = tsmf_signal_handler;
1527 sigemptyset(&sigtrap.sa_mask);
1528 sigtrap.sa_flags = 0;
1529 sigaction(SIGINT, &sigtrap, 0);
1530 sigaction(SIGUSR1, &sigtrap, 0);
1533 if (!presentation_list)
1535 presentation_list = ArrayList_New(TRUE);
1537 if (!presentation_list)
1540 obj = ArrayList_Object(presentation_list);
1543 obj->fnObjectFree = s_tsmf_presentation_free;
This struct contains function pointer to initialize/free objects.