1 /**
2 * FreeRDP: A Remote Desktop Protocol Implementation
3 * Video Redirection Virtual Channel - Media Container
4 *
5 * Copyright 2010-2011 Vic Lee
6 * Copyright 2012 Hewlett-Packard Development Company, L.P.
7 * Copyright 2015 Thincast Technologies GmbH
8 * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
9 *
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <signal.h>
31
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35
36 #ifndef _WIN32
37 #include <sys/time.h>
38 #endif
39
40 #include <winpr/crt.h>
41 #include <winpr/synch.h>
42 #include <winpr/string.h>
43 #include <winpr/thread.h>
44 #include <winpr/stream.h>
45 #include <winpr/collections.h>
46
47 #include <freerdp/client/tsmf.h>
48
49 #include "tsmf_constants.h"
50 #include "tsmf_types.h"
51 #include "tsmf_decoder.h"
52 #include "tsmf_audio.h"
53 #include "tsmf_main.h"
54 #include "tsmf_codec.h"
55 #include "tsmf_media.h"
56
57 #define AUDIO_TOLERANCE 10000000LL
58
59 /* 1 second = 10,000,000 100ns units*/
60 #define VIDEO_ADJUST_MAX 10 * 1000 * 1000
61
62 #define MAX_ACK_TIME 666667
63
64 #define AUDIO_MIN_BUFFER_LEVEL 3
65 #define AUDIO_MAX_BUFFER_LEVEL 6
66
67 #define VIDEO_MIN_BUFFER_LEVEL 10
68 #define VIDEO_MAX_BUFFER_LEVEL 30
69
70 struct _TSMF_PRESENTATION
71 {
72 BYTE presentation_id[GUID_SIZE];
73
74 const char* audio_name;
75 const char* audio_device;
76
77 IWTSVirtualChannelCallback* channel_callback;
78
79 UINT64 audio_start_time;
80 UINT64 audio_end_time;
81
82 UINT32 volume;
83 UINT32 muted;
84
85 wArrayList* stream_list;
86
87 int x;
88 int y;
89 int width;
90 int height;
91
92 int nr_rects;
93 void* rects;
94 };
95
96 struct _TSMF_STREAM
97 {
98 UINT32 stream_id;
99
100 TSMF_PRESENTATION* presentation;
101
102 ITSMFDecoder* decoder;
103
104 int major_type;
105 int eos;
106 UINT32 eos_message_id;
107 IWTSVirtualChannelCallback* eos_channel_callback;
108 int delayed_stop;
109 UINT32 width;
110 UINT32 height;
111
112 ITSMFAudioDevice* audio;
113 UINT32 sample_rate;
114 UINT32 channels;
115 UINT32 bits_per_sample;
116
117 /* The start time of last played sample */
118 UINT64 last_start_time;
119 /* The end_time of last played sample */
120 UINT64 last_end_time;
121 /* Next sample should not start before this system time. */
122 UINT64 next_start_time;
123
124 UINT32 minBufferLevel;
125 UINT32 maxBufferLevel;
126 UINT32 currentBufferLevel;
127
128 HANDLE play_thread;
129 HANDLE ack_thread;
130 HANDLE stopEvent;
131 HANDLE ready;
132
133 wQueue* sample_list;
134 wQueue* sample_ack_list;
135 rdpContext* rdpcontext;
136
137 BOOL seeking;
138 };
139
140 struct _TSMF_SAMPLE
141 {
142 UINT32 sample_id;
143 UINT64 start_time;
144 UINT64 end_time;
145 UINT64 duration;
146 UINT32 extensions;
147 UINT32 data_size;
148 BYTE* data;
149 UINT32 decoded_size;
150 UINT32 pixfmt;
151
152 BOOL invalidTimestamps;
153
154 TSMF_STREAM* stream;
155 IWTSVirtualChannelCallback* channel_callback;
156 UINT64 ack_time;
157 };
158
159 static wArrayList* presentation_list = NULL;
160 static int TERMINATING = 0;
161
162 static void _tsmf_presentation_free(void* obj);
163 static void _tsmf_stream_free(void* obj);
164
get_current_time(void)165 static UINT64 get_current_time(void)
166 {
167 struct timeval tp;
168 gettimeofday(&tp, 0);
169 return ((UINT64)tp.tv_sec) * 10000000LL + ((UINT64)tp.tv_usec) * 10LL;
170 }
171
tsmf_stream_pop_sample(TSMF_STREAM * stream,int sync)172 static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
173 {
174 UINT32 index;
175 UINT32 count;
176 TSMF_STREAM* s;
177 TSMF_SAMPLE* sample;
178 BOOL pending = FALSE;
179 TSMF_PRESENTATION* presentation = NULL;
180
181 if (!stream)
182 return NULL;
183
184 presentation = stream->presentation;
185
186 if (Queue_Count(stream->sample_list) < 1)
187 return NULL;
188
189 if (sync)
190 {
191 if (stream->decoder)
192 {
193 if (stream->decoder->GetDecodedData)
194 {
195 if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
196 {
197 /* Check if some other stream has earlier sample that needs to be played first
198 */
199 /* Start time is more reliable than end time as some stream types seem to have
200 * incorrect end times from the server
201 */
202 if (stream->last_start_time > AUDIO_TOLERANCE)
203 {
204 ArrayList_Lock(presentation->stream_list);
205 count = ArrayList_Count(presentation->stream_list);
206
207 for (index = 0; index < count; index++)
208 {
209 s = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
210
211 /* Start time is more reliable than end time as some stream types seem
212 * to have incorrect end times from the server
213 */
214 if (s != stream && !s->eos && s->last_start_time &&
215 s->last_start_time < stream->last_start_time - AUDIO_TOLERANCE)
216 {
217 DEBUG_TSMF("Pending due to audio tolerance");
218 pending = TRUE;
219 break;
220 }
221 }
222
223 ArrayList_Unlock(presentation->stream_list);
224 }
225 }
226 else
227 {
228 /* Start time is more reliable than end time as some stream types seem to have
229 * incorrect end times from the server
230 */
231 if (stream->last_start_time > presentation->audio_start_time)
232 {
233 DEBUG_TSMF("Pending due to stream start time > audio start time");
234 pending = TRUE;
235 }
236 }
237 }
238 }
239 }
240
241 if (pending)
242 return NULL;
243
244 sample = (TSMF_SAMPLE*)Queue_Dequeue(stream->sample_list);
245
246 /* Only update stream last end time if the sample end time is valid and greater than the current
247 * stream end time */
248 if (sample && (sample->end_time > stream->last_end_time) && (!sample->invalidTimestamps))
249 stream->last_end_time = sample->end_time;
250
251 /* Only update stream last start time if the sample start time is valid and greater than the
252 * current stream start time */
253 if (sample && (sample->start_time > stream->last_start_time) && (!sample->invalidTimestamps))
254 stream->last_start_time = sample->start_time;
255
256 return sample;
257 }
258
tsmf_sample_free(void * arg)259 static void tsmf_sample_free(void* arg)
260 {
261 TSMF_SAMPLE* sample = arg;
262
263 if (!sample)
264 return;
265
266 free(sample->data);
267 free(sample);
268 }
269
tsmf_sample_ack(TSMF_SAMPLE * sample)270 static BOOL tsmf_sample_ack(TSMF_SAMPLE* sample)
271 {
272 if (!sample)
273 return FALSE;
274
275 return tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration,
276 sample->data_size);
277 }
278
tsmf_sample_queue_ack(TSMF_SAMPLE * sample)279 static BOOL tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
280 {
281 if (!sample)
282 return FALSE;
283
284 if (!sample->stream)
285 return FALSE;
286
287 return Queue_Enqueue(sample->stream->sample_ack_list, sample);
288 }
289
290 /* Returns TRUE if no more samples are currently available
291 * Returns FALSE otherwise
292 */
tsmf_stream_process_ack(void * arg,BOOL force)293 static BOOL tsmf_stream_process_ack(void* arg, BOOL force)
294 {
295 TSMF_STREAM* stream = arg;
296 TSMF_SAMPLE* sample;
297 UINT64 ack_time;
298 BOOL rc = FALSE;
299
300 if (!stream)
301 return TRUE;
302
303 Queue_Lock(stream->sample_ack_list);
304 sample = (TSMF_SAMPLE*)Queue_Peek(stream->sample_ack_list);
305
306 if (!sample)
307 {
308 rc = TRUE;
309 goto finally;
310 }
311
312 if (!force)
313 {
314 /* Do some min/max ack limiting if we have access to Buffer level information */
315 if (stream->decoder && stream->decoder->BufferLevel)
316 {
317 /* Try to keep buffer level below max by withholding acks */
318 if (stream->currentBufferLevel > stream->maxBufferLevel)
319 goto finally;
320 /* Try to keep buffer level above min by pushing acks through quickly */
321 else if (stream->currentBufferLevel < stream->minBufferLevel)
322 goto dequeue;
323 }
324
325 /* Time based acks only */
326 ack_time = get_current_time();
327
328 if (sample->ack_time > ack_time)
329 goto finally;
330 }
331
332 dequeue:
333 sample = Queue_Dequeue(stream->sample_ack_list);
334
335 if (sample)
336 {
337 tsmf_sample_ack(sample);
338 tsmf_sample_free(sample);
339 }
340
341 finally:
342 Queue_Unlock(stream->sample_ack_list);
343 return rc;
344 }
345
tsmf_presentation_new(const BYTE * guid,IWTSVirtualChannelCallback * pChannelCallback)346 TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid,
347 IWTSVirtualChannelCallback* pChannelCallback)
348 {
349 TSMF_PRESENTATION* presentation;
350
351 if (!guid || !pChannelCallback)
352 return NULL;
353
354 presentation = (TSMF_PRESENTATION*)calloc(1, sizeof(TSMF_PRESENTATION));
355
356 if (!presentation)
357 {
358 WLog_ERR(TAG, "calloc failed");
359 return NULL;
360 }
361
362 CopyMemory(presentation->presentation_id, guid, GUID_SIZE);
363 presentation->channel_callback = pChannelCallback;
364 presentation->volume = 5000; /* 50% */
365 presentation->muted = 0;
366
367 if (!(presentation->stream_list = ArrayList_New(TRUE)))
368 goto error_stream_list;
369
370 ArrayList_Object(presentation->stream_list)->fnObjectFree = _tsmf_stream_free;
371
372 if (ArrayList_Add(presentation_list, presentation) < 0)
373 goto error_add;
374
375 return presentation;
376 error_add:
377 ArrayList_Free(presentation->stream_list);
378 error_stream_list:
379 free(presentation);
380 return NULL;
381 }
382
guid_to_string(const BYTE * guid,char * str,size_t len)383 static char* guid_to_string(const BYTE* guid, char* str, size_t len)
384 {
385 size_t i;
386
387 if (!guid || !str)
388 return NULL;
389
390 for (i = 0; i < GUID_SIZE && (len > 2 * i); i++)
391 sprintf_s(str + (2 * i), len - 2 * i, "%02" PRIX8 "", guid[i]);
392
393 return str;
394 }
395
tsmf_presentation_find_by_id(const BYTE * guid)396 TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE* guid)
397 {
398 UINT32 index;
399 UINT32 count;
400 BOOL found = FALSE;
401 char guid_str[GUID_SIZE * 2 + 1];
402 TSMF_PRESENTATION* presentation;
403 ArrayList_Lock(presentation_list);
404 count = ArrayList_Count(presentation_list);
405
406 for (index = 0; index < count; index++)
407 {
408 presentation = (TSMF_PRESENTATION*)ArrayList_GetItem(presentation_list, index);
409
410 if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0)
411 {
412 found = TRUE;
413 break;
414 }
415 }
416
417 ArrayList_Unlock(presentation_list);
418
419 if (!found)
420 WLog_WARN(TAG, "presentation id %s not found",
421 guid_to_string(guid, guid_str, sizeof(guid_str)));
422
423 return (found) ? presentation : NULL;
424 }
425
tsmf_sample_playback_video(TSMF_SAMPLE * sample)426 static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample)
427 {
428 UINT64 t;
429 TSMF_VIDEO_FRAME_EVENT event;
430 TSMF_STREAM* stream = sample->stream;
431 TSMF_PRESENTATION* presentation = stream->presentation;
432 TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*)sample->channel_callback;
433 TsmfClientContext* tsmf = (TsmfClientContext*)callback->plugin->pInterface;
434 DEBUG_TSMF("MessageId %" PRIu32 " EndTime %" PRIu64 " data_size %" PRIu32 " consumed.",
435 sample->sample_id, sample->end_time, sample->data_size);
436
437 if (sample->data)
438 {
439 t = get_current_time();
440
441 /* Start time is more reliable than end time as some stream types seem to have incorrect
442 * end times from the server
443 */
444 if (stream->next_start_time > t &&
445 ((sample->start_time >= presentation->audio_start_time) ||
446 ((sample->start_time < stream->last_start_time) && (!sample->invalidTimestamps))))
447 {
448 USleep((stream->next_start_time - t) / 10);
449 }
450
451 stream->next_start_time = t + sample->duration - 50000;
452 ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT));
453 event.frameData = sample->data;
454 event.frameSize = sample->decoded_size;
455 event.framePixFmt = sample->pixfmt;
456 event.frameWidth = sample->stream->width;
457 event.frameHeight = sample->stream->height;
458 event.x = presentation->x;
459 event.y = presentation->y;
460 event.width = presentation->width;
461 event.height = presentation->height;
462
463 if (presentation->nr_rects > 0)
464 {
465 event.numVisibleRects = presentation->nr_rects;
466 event.visibleRects = (RECTANGLE_16*)calloc(event.numVisibleRects, sizeof(RECTANGLE_16));
467
468 if (!event.visibleRects)
469 {
470 WLog_ERR(TAG, "can't allocate memory for copy rectangles");
471 return FALSE;
472 }
473
474 memcpy(event.visibleRects, presentation->rects,
475 presentation->nr_rects * sizeof(RDP_RECT));
476 presentation->nr_rects = 0;
477 }
478
479 #if 0
480 /* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we
481 extract the Y values to create a grayscale image. */
482 static int frame_id = 0;
483 char buf[100];
484 FILE* fp;
485
486 if ((frame_id % 30) == 0)
487 {
488 sprintf_s(buf, sizeof(buf), "/tmp/FreeRDP_Frame_%d.ppm", frame_id);
489 fp = fopen(buf, "wb");
490 fwrite("P5\n", 1, 3, fp);
491 sprintf_s(buf, sizeof(buf), "%"PRIu32" %"PRIu32"\n", sample->stream->width,
492 sample->stream->height);
493 fwrite(buf, 1, strnlen(buf, sizeof(buf)), fp);
494 fwrite("255\n", 1, 4, fp);
495 fwrite(sample->data, 1, sample->stream->width * sample->stream->height, fp);
496 fflush(fp);
497 fclose(fp);
498 }
499
500 frame_id++;
501 #endif
502 /* The frame data ownership is passed to the event object, and is freed after the event is
503 * processed. */
504 sample->data = NULL;
505 sample->decoded_size = 0;
506
507 if (tsmf->FrameEvent)
508 tsmf->FrameEvent(tsmf, &event);
509
510 free(event.frameData);
511
512 if (event.visibleRects != NULL)
513 free(event.visibleRects);
514 }
515
516 return TRUE;
517 }
518
tsmf_sample_playback_audio(TSMF_SAMPLE * sample)519 static BOOL tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
520 {
521 UINT64 latency = 0;
522 TSMF_STREAM* stream = sample->stream;
523 BOOL ret;
524 DEBUG_TSMF("MessageId %" PRIu32 " EndTime %" PRIu64 " consumed.", sample->sample_id,
525 sample->end_time);
526
527 if (stream->audio && sample->data)
528 {
529 ret =
530 sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size);
531 free(sample->data);
532 sample->data = NULL;
533 sample->decoded_size = 0;
534
535 if (stream->audio->GetLatency)
536 latency = stream->audio->GetLatency(stream->audio);
537 }
538 else
539 {
540 ret = TRUE;
541 latency = 0;
542 }
543
544 sample->ack_time = latency + get_current_time();
545
546 /* Only update stream times if the sample timestamps are valid */
547 if (!sample->invalidTimestamps)
548 {
549 stream->last_start_time = sample->start_time + latency;
550 stream->last_end_time = sample->end_time + latency;
551 stream->presentation->audio_start_time = sample->start_time + latency;
552 stream->presentation->audio_end_time = sample->end_time + latency;
553 }
554
555 return ret;
556 }
557
tsmf_sample_playback(TSMF_SAMPLE * sample)558 static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
559 {
560 BOOL ret = FALSE;
561 UINT32 width;
562 UINT32 height;
563 UINT32 pixfmt = 0;
564 TSMF_STREAM* stream = sample->stream;
565
566 if (stream->decoder)
567 {
568 if (stream->decoder->DecodeEx)
569 {
570 /* Try to "sync" video buffers to audio buffers by looking at the running time for each
571 * stream The difference between the two running times causes an offset between audio
572 * and video actual render times. So, we try to adjust timestamps on the video buffer to
573 * match those on the audio buffer.
574 */
575 if (stream->major_type == TSMF_MAJOR_TYPE_VIDEO)
576 {
577 TSMF_STREAM* temp_stream = NULL;
578 TSMF_PRESENTATION* presentation = stream->presentation;
579 ArrayList_Lock(presentation->stream_list);
580 int count = ArrayList_Count(presentation->stream_list);
581 int index = 0;
582
583 for (index = 0; index < count; index++)
584 {
585 UINT64 time_diff;
586 temp_stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
587
588 if (temp_stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
589 {
590 UINT64 video_time =
591 (UINT64)stream->decoder->GetRunningTime(stream->decoder);
592 UINT64 audio_time =
593 (UINT64)temp_stream->decoder->GetRunningTime(temp_stream->decoder);
594 UINT64 max_adjust = VIDEO_ADJUST_MAX;
595
596 if (video_time < audio_time)
597 max_adjust = -VIDEO_ADJUST_MAX;
598
599 if (video_time > audio_time)
600 time_diff = video_time - audio_time;
601 else
602 time_diff = audio_time - video_time;
603
604 time_diff = time_diff < VIDEO_ADJUST_MAX ? time_diff : max_adjust;
605 sample->start_time += time_diff;
606 sample->end_time += time_diff;
607 break;
608 }
609 }
610
611 ArrayList_Unlock(presentation->stream_list);
612 }
613
614 ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size,
615 sample->extensions, sample->start_time,
616 sample->end_time, sample->duration);
617 }
618 else
619 {
620 ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size,
621 sample->extensions);
622 }
623 }
624
625 if (!ret)
626 {
627 WLog_ERR(TAG, "decode error, queue ack anyways");
628
629 if (!tsmf_sample_queue_ack(sample))
630 {
631 WLog_ERR(TAG, "error queuing sample for ack");
632 return FALSE;
633 }
634
635 return TRUE;
636 }
637
638 free(sample->data);
639 sample->data = NULL;
640
641 if (stream->major_type == TSMF_MAJOR_TYPE_VIDEO)
642 {
643 if (stream->decoder->GetDecodedFormat)
644 {
645 pixfmt = stream->decoder->GetDecodedFormat(stream->decoder);
646
647 if (pixfmt == ((UINT32)-1))
648 {
649 WLog_ERR(TAG, "unable to decode video format");
650
651 if (!tsmf_sample_queue_ack(sample))
652 {
653 WLog_ERR(TAG, "error queuing sample for ack");
654 }
655
656 return FALSE;
657 }
658
659 sample->pixfmt = pixfmt;
660 }
661
662 if (stream->decoder->GetDecodedDimension)
663 {
664 ret = stream->decoder->GetDecodedDimension(stream->decoder, &width, &height);
665
666 if (ret && (width != stream->width || height != stream->height))
667 {
668 DEBUG_TSMF("video dimension changed to %" PRIu32 " x %" PRIu32 "", width, height);
669 stream->width = width;
670 stream->height = height;
671 }
672 }
673 }
674
675 if (stream->decoder->GetDecodedData)
676 {
677 sample->data = stream->decoder->GetDecodedData(stream->decoder, &sample->decoded_size);
678
679 switch (sample->stream->major_type)
680 {
681 case TSMF_MAJOR_TYPE_VIDEO:
682 ret = tsmf_sample_playback_video(sample) && tsmf_sample_queue_ack(sample);
683 break;
684
685 case TSMF_MAJOR_TYPE_AUDIO:
686 ret = tsmf_sample_playback_audio(sample) && tsmf_sample_queue_ack(sample);
687 break;
688 }
689 }
690 else
691 {
692 TSMF_STREAM* stream = sample->stream;
693 UINT64 ack_anticipation_time = get_current_time();
694 BOOL buffer_filled = TRUE;
695
696 /* Classify the buffer as filled once it reaches minimum level */
697 if (stream->decoder->BufferLevel)
698 {
699 if (stream->currentBufferLevel < stream->minBufferLevel)
700 buffer_filled = FALSE;
701 }
702
703 ack_anticipation_time +=
704 (sample->duration / 2 < MAX_ACK_TIME) ? sample->duration / 2 : MAX_ACK_TIME;
705
706 switch (sample->stream->major_type)
707 {
708 case TSMF_MAJOR_TYPE_VIDEO:
709 {
710 break;
711 }
712
713 case TSMF_MAJOR_TYPE_AUDIO:
714 {
715 break;
716 }
717 }
718
719 sample->ack_time = ack_anticipation_time;
720
721 if (!tsmf_sample_queue_ack(sample))
722 {
723 WLog_ERR(TAG, "error queuing sample for ack");
724 ret = FALSE;
725 }
726 }
727
728 return ret;
729 }
730
tsmf_stream_ack_func(LPVOID arg)731 static DWORD WINAPI tsmf_stream_ack_func(LPVOID arg)
732 {
733 HANDLE hdl[2];
734 TSMF_STREAM* stream = (TSMF_STREAM*)arg;
735 UINT error = CHANNEL_RC_OK;
736 DEBUG_TSMF("in %" PRIu32 "", stream->stream_id);
737 hdl[0] = stream->stopEvent;
738 hdl[1] = Queue_Event(stream->sample_ack_list);
739
740 while (1)
741 {
742 DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, 1000);
743
744 if (ev == WAIT_FAILED)
745 {
746 error = GetLastError();
747 WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
748 break;
749 }
750
751 if (stream->decoder)
752 if (stream->decoder->BufferLevel)
753 stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
754
755 if (stream->eos)
756 {
757 while ((stream->currentBufferLevel > 0) && !(tsmf_stream_process_ack(stream, TRUE)))
758 {
759 DEBUG_TSMF("END OF STREAM PROCESSING!");
760
761 if (stream->decoder && stream->decoder->BufferLevel)
762 stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
763 else
764 stream->currentBufferLevel = 1;
765
766 USleep(1000);
767 }
768
769 tsmf_send_eos_response(stream->eos_channel_callback, stream->eos_message_id);
770 stream->eos = 0;
771
772 if (stream->delayed_stop)
773 {
774 DEBUG_TSMF("Finishing delayed stream stop, now that eos has processed.");
775 tsmf_stream_flush(stream);
776
777 if (stream->decoder && stream->decoder->Control)
778 stream->decoder->Control(stream->decoder, Control_Stop, NULL);
779 }
780 }
781
782 /* Stream stopped force all of the acks to happen */
783 if (ev == WAIT_OBJECT_0)
784 {
785 DEBUG_TSMF("ack: Stream stopped!");
786
787 while (1)
788 {
789 if (tsmf_stream_process_ack(stream, TRUE))
790 break;
791
792 USleep(1000);
793 }
794
795 break;
796 }
797
798 if (tsmf_stream_process_ack(stream, FALSE))
799 continue;
800
801 if (stream->currentBufferLevel > stream->minBufferLevel)
802 USleep(1000);
803 }
804
805 if (error && stream->rdpcontext)
806 setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error");
807
808 DEBUG_TSMF("out %" PRIu32 "", stream->stream_id);
809 ExitThread(error);
810 return error;
811 }
812
tsmf_stream_playback_func(LPVOID arg)813 static DWORD WINAPI tsmf_stream_playback_func(LPVOID arg)
814 {
815 HANDLE hdl[2];
816 TSMF_SAMPLE* sample = NULL;
817 TSMF_STREAM* stream = (TSMF_STREAM*)arg;
818 TSMF_PRESENTATION* presentation = stream->presentation;
819 UINT error = CHANNEL_RC_OK;
820 DWORD status;
821 DEBUG_TSMF("in %" PRIu32 "", stream->stream_id);
822
823 if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO && stream->sample_rate && stream->channels &&
824 stream->bits_per_sample)
825 {
826 if (stream->decoder)
827 {
828 if (stream->decoder->GetDecodedData)
829 {
830 stream->audio = tsmf_load_audio_device(
831 presentation->audio_name && presentation->audio_name[0]
832 ? presentation->audio_name
833 : NULL,
834 presentation->audio_device && presentation->audio_device[0]
835 ? presentation->audio_device
836 : NULL);
837
838 if (stream->audio)
839 {
840 stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels,
841 stream->bits_per_sample);
842 }
843 }
844 }
845 }
846
847 hdl[0] = stream->stopEvent;
848 hdl[1] = Queue_Event(stream->sample_list);
849
850 while (1)
851 {
852 status = WaitForMultipleObjects(2, hdl, FALSE, 1000);
853
854 if (status == WAIT_FAILED)
855 {
856 error = GetLastError();
857 WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
858 break;
859 }
860
861 status = WaitForSingleObject(stream->stopEvent, 0);
862
863 if (status == WAIT_FAILED)
864 {
865 error = GetLastError();
866 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error);
867 break;
868 }
869
870 if (status == WAIT_OBJECT_0)
871 break;
872
873 if (stream->decoder)
874 if (stream->decoder->BufferLevel)
875 stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder);
876
877 sample = tsmf_stream_pop_sample(stream, 0);
878
879 if (sample && !tsmf_sample_playback(sample))
880 {
881 WLog_ERR(TAG, "error playing sample");
882 error = ERROR_INTERNAL_ERROR;
883 break;
884 }
885
886 if (stream->currentBufferLevel > stream->minBufferLevel)
887 USleep(1000);
888 }
889
890 if (stream->audio)
891 {
892 stream->audio->Free(stream->audio);
893 stream->audio = NULL;
894 }
895
896 if (error && stream->rdpcontext)
897 setChannelError(stream->rdpcontext, error, "tsmf_stream_playback_func reported an error");
898
899 DEBUG_TSMF("out %" PRIu32 "", stream->stream_id);
900 ExitThread(error);
901 return error;
902 }
903
tsmf_stream_start(TSMF_STREAM * stream)904 static BOOL tsmf_stream_start(TSMF_STREAM* stream)
905 {
906 if (!stream || !stream->presentation || !stream->decoder || !stream->decoder->Control)
907 return TRUE;
908
909 stream->eos = 0;
910 return stream->decoder->Control(stream->decoder, Control_Restart, NULL);
911 }
912
tsmf_stream_stop(TSMF_STREAM * stream)913 static BOOL tsmf_stream_stop(TSMF_STREAM* stream)
914 {
915 if (!stream || !stream->decoder || !stream->decoder->Control)
916 return TRUE;
917
918 /* If stopping after eos - we delay until the eos has been processed
919 * this allows us to process any buffers that have been acked even though
920 * they have not actually been completely processes by the decoder
921 */
922 if (stream->eos)
923 {
924 DEBUG_TSMF("Setting up a delayed stop for once the eos has been processed.");
925 stream->delayed_stop = 1;
926 return TRUE;
927 }
928 /* Otherwise force stop immediately */
929 else
930 {
931 DEBUG_TSMF("Stop with no pending eos response, so do it immediately.");
932 tsmf_stream_flush(stream);
933 return stream->decoder->Control(stream->decoder, Control_Stop, NULL);
934 }
935 }
936
tsmf_stream_pause(TSMF_STREAM * stream)937 static BOOL tsmf_stream_pause(TSMF_STREAM* stream)
938 {
939 if (!stream || !stream->decoder || !stream->decoder->Control)
940 return TRUE;
941
942 return stream->decoder->Control(stream->decoder, Control_Pause, NULL);
943 }
944
tsmf_stream_restart(TSMF_STREAM * stream)945 static BOOL tsmf_stream_restart(TSMF_STREAM* stream)
946 {
947 if (!stream || !stream->decoder || !stream->decoder->Control)
948 return TRUE;
949
950 stream->eos = 0;
951 return stream->decoder->Control(stream->decoder, Control_Restart, NULL);
952 }
953
tsmf_stream_change_volume(TSMF_STREAM * stream,UINT32 newVolume,UINT32 muted)954 static BOOL tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted)
955 {
956 if (!stream || !stream->decoder)
957 return TRUE;
958
959 if (stream->decoder != NULL && stream->decoder->ChangeVolume)
960 {
961 return stream->decoder->ChangeVolume(stream->decoder, newVolume, muted);
962 }
963 else if (stream->audio != NULL && stream->audio->ChangeVolume)
964 {
965 return stream->audio->ChangeVolume(stream->audio, newVolume, muted);
966 }
967
968 return TRUE;
969 }
970
tsmf_presentation_volume_changed(TSMF_PRESENTATION * presentation,UINT32 newVolume,UINT32 muted)971 BOOL tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume,
972 UINT32 muted)
973 {
974 UINT32 index;
975 UINT32 count;
976 TSMF_STREAM* stream;
977 BOOL ret = TRUE;
978 presentation->volume = newVolume;
979 presentation->muted = muted;
980 ArrayList_Lock(presentation->stream_list);
981 count = ArrayList_Count(presentation->stream_list);
982
983 for (index = 0; index < count; index++)
984 {
985 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
986 ret &= tsmf_stream_change_volume(stream, newVolume, muted);
987 }
988
989 ArrayList_Unlock(presentation->stream_list);
990 return ret;
991 }
992
tsmf_presentation_paused(TSMF_PRESENTATION * presentation)993 BOOL tsmf_presentation_paused(TSMF_PRESENTATION* presentation)
994 {
995 UINT32 index;
996 UINT32 count;
997 TSMF_STREAM* stream;
998 BOOL ret = TRUE;
999 ArrayList_Lock(presentation->stream_list);
1000 count = ArrayList_Count(presentation->stream_list);
1001
1002 for (index = 0; index < count; index++)
1003 {
1004 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1005 ret &= tsmf_stream_pause(stream);
1006 }
1007
1008 ArrayList_Unlock(presentation->stream_list);
1009 return ret;
1010 }
1011
tsmf_presentation_restarted(TSMF_PRESENTATION * presentation)1012 BOOL tsmf_presentation_restarted(TSMF_PRESENTATION* presentation)
1013 {
1014 UINT32 index;
1015 UINT32 count;
1016 TSMF_STREAM* stream;
1017 BOOL ret = TRUE;
1018 ArrayList_Lock(presentation->stream_list);
1019 count = ArrayList_Count(presentation->stream_list);
1020
1021 for (index = 0; index < count; index++)
1022 {
1023 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1024 ret &= tsmf_stream_restart(stream);
1025 }
1026
1027 ArrayList_Unlock(presentation->stream_list);
1028 return ret;
1029 }
1030
tsmf_presentation_start(TSMF_PRESENTATION * presentation)1031 BOOL tsmf_presentation_start(TSMF_PRESENTATION* presentation)
1032 {
1033 UINT32 index;
1034 UINT32 count;
1035 TSMF_STREAM* stream;
1036 BOOL ret = TRUE;
1037 ArrayList_Lock(presentation->stream_list);
1038 count = ArrayList_Count(presentation->stream_list);
1039
1040 for (index = 0; index < count; index++)
1041 {
1042 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1043 ret &= tsmf_stream_start(stream);
1044 }
1045
1046 ArrayList_Unlock(presentation->stream_list);
1047 return ret;
1048 }
1049
1050 /**
1051 * Function description
1052 *
1053 * @return 0 on success, otherwise a Win32 error code
1054 */
tsmf_presentation_sync(TSMF_PRESENTATION * presentation)1055 UINT tsmf_presentation_sync(TSMF_PRESENTATION* presentation)
1056 {
1057 UINT32 index;
1058 UINT32 count;
1059 UINT error;
1060 ArrayList_Lock(presentation->stream_list);
1061 count = ArrayList_Count(presentation->stream_list);
1062
1063 for (index = 0; index < count; index++)
1064 {
1065 TSMF_STREAM* stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1066
1067 if (WaitForSingleObject(stream->ready, 500) == WAIT_FAILED)
1068 {
1069 error = GetLastError();
1070 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error);
1071 return error;
1072 }
1073 }
1074
1075 ArrayList_Unlock(presentation->stream_list);
1076 return CHANNEL_RC_OK;
1077 }
1078
tsmf_presentation_stop(TSMF_PRESENTATION * presentation)1079 BOOL tsmf_presentation_stop(TSMF_PRESENTATION* presentation)
1080 {
1081 UINT32 index;
1082 UINT32 count;
1083 TSMF_STREAM* stream;
1084 BOOL ret = TRUE;
1085 ArrayList_Lock(presentation->stream_list);
1086 count = ArrayList_Count(presentation->stream_list);
1087
1088 for (index = 0; index < count; index++)
1089 {
1090 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1091 ret &= tsmf_stream_stop(stream);
1092 }
1093
1094 ArrayList_Unlock(presentation->stream_list);
1095 presentation->audio_start_time = 0;
1096 presentation->audio_end_time = 0;
1097 return ret;
1098 }
1099
tsmf_presentation_set_geometry_info(TSMF_PRESENTATION * presentation,UINT32 x,UINT32 y,UINT32 width,UINT32 height,int num_rects,RDP_RECT * rects)1100 BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, UINT32 x, UINT32 y,
1101 UINT32 width, UINT32 height, int num_rects,
1102 RDP_RECT* rects)
1103 {
1104 UINT32 index;
1105 UINT32 count;
1106 TSMF_STREAM* stream;
1107 void* tmp_rects = NULL;
1108 BOOL ret = TRUE;
1109
1110 /* The server may send messages with invalid width / height.
1111 * Ignore those messages. */
1112 if (!width || !height)
1113 return TRUE;
1114
1115 /* Streams can be added/removed from the presentation and the server will resend geometry info
1116 * when a new stream is added to the presentation. Also, num_rects is used to indicate whether
1117 * or not the window is visible. So, always process a valid message with unchanged position/size
1118 * and/or no visibility rects.
1119 */
1120 presentation->x = x;
1121 presentation->y = y;
1122 presentation->width = width;
1123 presentation->height = height;
1124 tmp_rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects);
1125
1126 if (!tmp_rects && num_rects)
1127 return FALSE;
1128
1129 presentation->nr_rects = num_rects;
1130 presentation->rects = tmp_rects;
1131 if (presentation->rects)
1132 CopyMemory(presentation->rects, rects, sizeof(RDP_RECT) * num_rects);
1133 ArrayList_Lock(presentation->stream_list);
1134 count = ArrayList_Count(presentation->stream_list);
1135
1136 for (index = 0; index < count; index++)
1137 {
1138 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1139
1140 if (!stream->decoder)
1141 continue;
1142
1143 if (stream->decoder->UpdateRenderingArea)
1144 {
1145 ret = stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height,
1146 num_rects, rects);
1147 }
1148 }
1149
1150 ArrayList_Unlock(presentation->stream_list);
1151 return ret;
1152 }
1153
tsmf_presentation_set_audio_device(TSMF_PRESENTATION * presentation,const char * name,const char * device)1154 void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char* name,
1155 const char* device)
1156 {
1157 presentation->audio_name = name;
1158 presentation->audio_device = device;
1159 }
1160
tsmf_stream_flush(TSMF_STREAM * stream)1161 BOOL tsmf_stream_flush(TSMF_STREAM* stream)
1162 {
1163 BOOL ret = TRUE;
1164
1165 // TSMF_SAMPLE* sample;
1166 /* TODO: free lists */
1167 if (stream->audio)
1168 ret = stream->audio->Flush(stream->audio);
1169
1170 stream->eos = 0;
1171 stream->eos_message_id = 0;
1172 stream->eos_channel_callback = NULL;
1173 stream->delayed_stop = 0;
1174 stream->last_end_time = 0;
1175 stream->next_start_time = 0;
1176
1177 if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO)
1178 {
1179 stream->presentation->audio_start_time = 0;
1180 stream->presentation->audio_end_time = 0;
1181 }
1182
1183 return TRUE;
1184 }
1185
_tsmf_presentation_free(void * obj)1186 void _tsmf_presentation_free(void* obj)
1187 {
1188 TSMF_PRESENTATION* presentation = (TSMF_PRESENTATION*)obj;
1189
1190 if (presentation)
1191 {
1192 tsmf_presentation_stop(presentation);
1193 ArrayList_Clear(presentation->stream_list);
1194 ArrayList_Free(presentation->stream_list);
1195 free(presentation->rects);
1196 ZeroMemory(presentation, sizeof(TSMF_PRESENTATION));
1197 free(presentation);
1198 }
1199 }
1200
tsmf_presentation_free(TSMF_PRESENTATION * presentation)1201 void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
1202 {
1203 ArrayList_Remove(presentation_list, presentation);
1204 }
1205
tsmf_stream_new(TSMF_PRESENTATION * presentation,UINT32 stream_id,rdpContext * rdpcontext)1206 TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id,
1207 rdpContext* rdpcontext)
1208 {
1209 TSMF_STREAM* stream;
1210 stream = tsmf_stream_find_by_id(presentation, stream_id);
1211
1212 if (stream)
1213 {
1214 WLog_ERR(TAG, "duplicated stream id %" PRIu32 "!", stream_id);
1215 return NULL;
1216 }
1217
1218 stream = (TSMF_STREAM*)calloc(1, sizeof(TSMF_STREAM));
1219
1220 if (!stream)
1221 {
1222 WLog_ERR(TAG, "Calloc failed");
1223 return NULL;
1224 }
1225
1226 stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL;
1227 stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL;
1228 stream->currentBufferLevel = 1;
1229 stream->seeking = FALSE;
1230 stream->eos = 0;
1231 stream->eos_message_id = 0;
1232 stream->eos_channel_callback = NULL;
1233 stream->stream_id = stream_id;
1234 stream->presentation = presentation;
1235 stream->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1236
1237 if (!stream->stopEvent)
1238 goto error_stopEvent;
1239
1240 stream->ready = CreateEvent(NULL, TRUE, TRUE, NULL);
1241
1242 if (!stream->ready)
1243 goto error_ready;
1244
1245 stream->sample_list = Queue_New(TRUE, -1, -1);
1246
1247 if (!stream->sample_list)
1248 goto error_sample_list;
1249
1250 stream->sample_list->object.fnObjectFree = tsmf_sample_free;
1251 stream->sample_ack_list = Queue_New(TRUE, -1, -1);
1252
1253 if (!stream->sample_ack_list)
1254 goto error_sample_ack_list;
1255
1256 stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
1257 stream->play_thread =
1258 CreateThread(NULL, 0, tsmf_stream_playback_func, stream, CREATE_SUSPENDED, NULL);
1259
1260 if (!stream->play_thread)
1261 goto error_play_thread;
1262
1263 stream->ack_thread =
1264 CreateThread(NULL, 0, tsmf_stream_ack_func, stream, CREATE_SUSPENDED, NULL);
1265
1266 if (!stream->ack_thread)
1267 goto error_ack_thread;
1268
1269 if (ArrayList_Add(presentation->stream_list, stream) < 0)
1270 goto error_add;
1271
1272 stream->rdpcontext = rdpcontext;
1273 return stream;
1274 error_add:
1275 SetEvent(stream->stopEvent);
1276
1277 if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED)
1278 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", GetLastError());
1279
1280 error_ack_thread:
1281 SetEvent(stream->stopEvent);
1282
1283 if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED)
1284 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", GetLastError());
1285
1286 error_play_thread:
1287 Queue_Free(stream->sample_ack_list);
1288 error_sample_ack_list:
1289 Queue_Free(stream->sample_list);
1290 error_sample_list:
1291 CloseHandle(stream->ready);
1292 error_ready:
1293 CloseHandle(stream->stopEvent);
1294 error_stopEvent:
1295 free(stream);
1296 return NULL;
1297 }
1298
tsmf_stream_start_threads(TSMF_STREAM * stream)1299 void tsmf_stream_start_threads(TSMF_STREAM* stream)
1300 {
1301 ResumeThread(stream->play_thread);
1302 ResumeThread(stream->ack_thread);
1303 }
1304
tsmf_stream_find_by_id(TSMF_PRESENTATION * presentation,UINT32 stream_id)1305 TSMF_STREAM* tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id)
1306 {
1307 UINT32 index;
1308 UINT32 count;
1309 BOOL found = FALSE;
1310 TSMF_STREAM* stream;
1311 ArrayList_Lock(presentation->stream_list);
1312 count = ArrayList_Count(presentation->stream_list);
1313
1314 for (index = 0; index < count; index++)
1315 {
1316 stream = (TSMF_STREAM*)ArrayList_GetItem(presentation->stream_list, index);
1317
1318 if (stream->stream_id == stream_id)
1319 {
1320 found = TRUE;
1321 break;
1322 }
1323 }
1324
1325 ArrayList_Unlock(presentation->stream_list);
1326 return (found) ? stream : NULL;
1327 }
1328
tsmf_stream_resync(void * arg)1329 static void tsmf_stream_resync(void* arg)
1330 {
1331 TSMF_STREAM* stream = arg;
1332 ResetEvent(stream->ready);
1333 }
1334
tsmf_stream_set_format(TSMF_STREAM * stream,const char * name,wStream * s)1335 BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char* name, wStream* s)
1336 {
1337 TS_AM_MEDIA_TYPE mediatype;
1338 BOOL ret = TRUE;
1339
1340 if (stream->decoder)
1341 {
1342 WLog_ERR(TAG, "duplicated call");
1343 return FALSE;
1344 }
1345
1346 if (!tsmf_codec_parse_media_type(&mediatype, s))
1347 {
1348 WLog_ERR(TAG, "unable to parse media type");
1349 return FALSE;
1350 }
1351
1352 if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO)
1353 {
1354 DEBUG_TSMF("video width %" PRIu32 " height %" PRIu32 " bit_rate %" PRIu32
1355 " frame_rate %f codec_data %" PRIu32 "",
1356 mediatype.Width, mediatype.Height, mediatype.BitRate,
1357 (double)mediatype.SamplesPerSecond.Numerator /
1358 (double)mediatype.SamplesPerSecond.Denominator,
1359 mediatype.ExtraDataSize);
1360 stream->minBufferLevel = VIDEO_MIN_BUFFER_LEVEL;
1361 stream->maxBufferLevel = VIDEO_MAX_BUFFER_LEVEL;
1362 }
1363 else if (mediatype.MajorType == TSMF_MAJOR_TYPE_AUDIO)
1364 {
1365 DEBUG_TSMF("audio channel %" PRIu32 " sample_rate %" PRIu32 " bits_per_sample %" PRIu32
1366 " codec_data %" PRIu32 "",
1367 mediatype.Channels, mediatype.SamplesPerSecond.Numerator,
1368 mediatype.BitsPerSample, mediatype.ExtraDataSize);
1369 stream->sample_rate = mediatype.SamplesPerSecond.Numerator;
1370 stream->channels = mediatype.Channels;
1371 stream->bits_per_sample = mediatype.BitsPerSample;
1372
1373 if (stream->bits_per_sample == 0)
1374 stream->bits_per_sample = 16;
1375
1376 stream->minBufferLevel = AUDIO_MIN_BUFFER_LEVEL;
1377 stream->maxBufferLevel = AUDIO_MAX_BUFFER_LEVEL;
1378 }
1379
1380 stream->major_type = mediatype.MajorType;
1381 stream->width = mediatype.Width;
1382 stream->height = mediatype.Height;
1383 stream->decoder = tsmf_load_decoder(name, &mediatype);
1384 ret &= tsmf_stream_change_volume(stream, stream->presentation->volume,
1385 stream->presentation->muted);
1386
1387 if (!stream->decoder)
1388 return FALSE;
1389
1390 if (stream->decoder->SetAckFunc)
1391 ret &= stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack, stream);
1392
1393 if (stream->decoder->SetSyncFunc)
1394 ret &= stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream);
1395
1396 return ret;
1397 }
1398
tsmf_stream_end(TSMF_STREAM * stream,UINT32 message_id,IWTSVirtualChannelCallback * pChannelCallback)1399 void tsmf_stream_end(TSMF_STREAM* stream, UINT32 message_id,
1400 IWTSVirtualChannelCallback* pChannelCallback)
1401 {
1402 if (!stream)
1403 return;
1404
1405 stream->eos = 1;
1406 stream->eos_message_id = message_id;
1407 stream->eos_channel_callback = pChannelCallback;
1408 }
1409
_tsmf_stream_free(void * obj)1410 void _tsmf_stream_free(void* obj)
1411 {
1412 TSMF_STREAM* stream = (TSMF_STREAM*)obj;
1413
1414 if (!stream)
1415 return;
1416
1417 tsmf_stream_stop(stream);
1418 SetEvent(stream->stopEvent);
1419
1420 if (stream->play_thread)
1421 {
1422 if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED)
1423 {
1424 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", GetLastError());
1425 return;
1426 }
1427
1428 CloseHandle(stream->play_thread);
1429 stream->play_thread = NULL;
1430 }
1431
1432 if (stream->ack_thread)
1433 {
1434 if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED)
1435 {
1436 WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", GetLastError());
1437 return;
1438 }
1439
1440 CloseHandle(stream->ack_thread);
1441 stream->ack_thread = NULL;
1442 }
1443
1444 Queue_Free(stream->sample_list);
1445 Queue_Free(stream->sample_ack_list);
1446
1447 if (stream->decoder && stream->decoder->Free)
1448 {
1449 stream->decoder->Free(stream->decoder);
1450 stream->decoder = NULL;
1451 }
1452
1453 CloseHandle(stream->stopEvent);
1454 CloseHandle(stream->ready);
1455 ZeroMemory(stream, sizeof(TSMF_STREAM));
1456 free(stream);
1457 }
1458
tsmf_stream_free(TSMF_STREAM * stream)1459 void tsmf_stream_free(TSMF_STREAM* stream)
1460 {
1461 TSMF_PRESENTATION* presentation = stream->presentation;
1462 ArrayList_Remove(presentation->stream_list, stream);
1463 }
1464
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)1465 BOOL tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback* pChannelCallback,
1466 UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration,
1467 UINT32 extensions, UINT32 data_size, BYTE* data)
1468 {
1469 TSMF_SAMPLE* sample;
1470 SetEvent(stream->ready);
1471
1472 if (TERMINATING)
1473 return TRUE;
1474
1475 sample = (TSMF_SAMPLE*)calloc(1, sizeof(TSMF_SAMPLE));
1476
1477 if (!sample)
1478 {
1479 WLog_ERR(TAG, "calloc sample failed!");
1480 return FALSE;
1481 }
1482
1483 sample->sample_id = sample_id;
1484 sample->start_time = start_time;
1485 sample->end_time = end_time;
1486 sample->duration = duration;
1487 sample->extensions = extensions;
1488
1489 if ((sample->extensions & 0x00000080) || (sample->extensions & 0x00000040))
1490 sample->invalidTimestamps = TRUE;
1491 else
1492 sample->invalidTimestamps = FALSE;
1493
1494 sample->stream = stream;
1495 sample->channel_callback = pChannelCallback;
1496 sample->data_size = data_size;
1497 sample->data = calloc(1, data_size + TSMF_BUFFER_PADDING_SIZE);
1498
1499 if (!sample->data)
1500 {
1501 WLog_ERR(TAG, "calloc sample->data failed!");
1502 free(sample);
1503 return FALSE;
1504 }
1505
1506 CopyMemory(sample->data, data, data_size);
1507 return Queue_Enqueue(stream->sample_list, sample);
1508 }
1509
1510 #ifndef _WIN32
1511
tsmf_signal_handler(int s)1512 static void tsmf_signal_handler(int s)
1513 {
1514 TERMINATING = 1;
1515 ArrayList_Free(presentation_list);
1516
1517 if (s == SIGINT)
1518 {
1519 signal(s, SIG_DFL);
1520 kill(getpid(), s);
1521 }
1522 else if (s == SIGUSR1)
1523 {
1524 signal(s, SIG_DFL);
1525 }
1526 }
1527
1528 #endif
1529
tsmf_media_init(void)1530 BOOL tsmf_media_init(void)
1531 {
1532 #ifndef _WIN32
1533 struct sigaction sigtrap;
1534 sigtrap.sa_handler = tsmf_signal_handler;
1535 sigemptyset(&sigtrap.sa_mask);
1536 sigtrap.sa_flags = 0;
1537 sigaction(SIGINT, &sigtrap, 0);
1538 sigaction(SIGUSR1, &sigtrap, 0);
1539 #endif
1540
1541 if (!presentation_list)
1542 {
1543 presentation_list = ArrayList_New(TRUE);
1544
1545 if (!presentation_list)
1546 return FALSE;
1547
1548 ArrayList_Object(presentation_list)->fnObjectFree = _tsmf_presentation_free;
1549 }
1550
1551 return TRUE;
1552 }
1553