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