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