2
* FreeRDP: A Remote Desktop Protocol Implementation
3
* Video Redirection Virtual Channel - GStreamer Decoder
5
* (C) Copyright 2012 HP Development Company, LLC
7
* Licensed under the Apache License, Version 2.0 (the "License");
8
* you may not use this file except in compliance with the License.
9
* You may obtain a copy of the License at
11
* http://www.apache.org/licenses/LICENSE-2.0
13
* Unless required by applicable law or agreed to in writing, software
14
* distributed under the License is distributed on an "AS IS" BASIS,
15
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
* See the License for the specific language governing permissions and
17
* limitations under the License.
25
#include <X11/extensions/Xrandr.h>
26
#include <X11/extensions/shape.h>
36
#include <gst/app/gstappsrc.h>
37
#include <gst/app/gstappsink.h>
38
#include <gst/interfaces/xoverlay.h>
40
#include <sys/types.h>
44
#include <sys/syscall.h>
46
#include "tsmf_constants.h"
47
#include "tsmf_decoder.h"
49
#ifdef HAVE_INTTYPES_H
53
#define SHARED_MEM_KEY 7777
54
#define TRY_DECODEBIN 0
56
typedef struct _TSMFGstreamerDecoder
60
int media_type; /* TSMF_MAJOR_TYPE_AUDIO or TSMF_MAJOR_TYPE_VIDEO */
62
TS_AM_MEDIA_TYPE tsmf_media_type; /* TSMF description of the media type, (without ExtraData) */
64
pthread_t eventloop_thread;
66
GstCaps *gst_caps; /* Gstreamer description of the media type */
80
UINT64 last_sample_end_time;
92
int pipeline_start_time_valid; /* We've set the start time and have not reset the pipeline */
93
int shutdown; /* The decoder stream is shutting down */
94
pthread_mutex_t gst_mutex;
96
} TSMFGstreamerDecoder;
98
const char *NAME_GST_STATE_PLAYING = "GST_STATE_PLAYING";
99
const char *NAME_GST_STATE_PAUSED = "GST_STATE_PAUSED";
100
const char *NAME_GST_STATE_READY = "GST_STATE_READY";
101
const char *NAME_GST_STATE_NULL = "GST_STATE_NULL";
102
const char *NAME_GST_STATE_VOID_PENDING = "GST_STATE_VOID_PENDING";
103
const char *NAME_GST_STATE_OTHER = "GST_STATE_?";
105
static inline const GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_timestamp)
108
* Convert Microsoft 100ns timestamps to Gstreamer 1ns units.
110
return (GstClockTime)(ms_timestamp * 100);
113
static const char *tsmf_gstreamer_state_name(GstState state)
117
if (state == GST_STATE_PLAYING) name = NAME_GST_STATE_PLAYING;
118
else if (state == GST_STATE_PAUSED) name = NAME_GST_STATE_PAUSED;
119
else if (state == GST_STATE_READY) name = NAME_GST_STATE_READY;
120
else if (state == GST_STATE_NULL) name = NAME_GST_STATE_NULL;
121
else if (state == GST_STATE_VOID_PENDING) name = NAME_GST_STATE_VOID_PENDING;
122
else name = NAME_GST_STATE_OTHER;
128
static void *tsmf_gstreamer_eventloop_thread_func(void * arg)
130
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) arg;
132
GstMessage *message = NULL;
133
GstState old, new, pending;
136
DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: ");
138
bus = gst_element_get_bus(mdecoder->pipe);
143
message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1);
145
if (mdecoder->shutdown)
147
loop =0; /* We are done with this stream */
151
switch (message->type)
153
case GST_MESSAGE_EOS:
154
DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_EOS");
155
gst_message_unref (message);
158
case GST_MESSAGE_WARNING:
159
case GST_MESSAGE_ERROR:
161
DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_ERROR");
164
gst_message_parse_error(message, &err, &debug);
165
g_print("ERROR: %s\nDEBUG:%s\n", err->message, debug);
168
gst_message_unref(message);*/
171
case GST_MESSAGE_STATE_CHANGED:
173
gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC(message));
175
gst_message_parse_state_changed (message, &old, &new, &pending);
177
DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_STATE_CHANGED %s old %s new %s pending %s",
179
gst_element_state_get_name(old),
180
gst_element_state_get_name(new),
181
gst_element_state_get_name(pending));
184
gst_message_unref(message);
189
case GST_MESSAGE_REQUEST_STATE:
192
gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC(message));
194
gst_message_parse_request_state(message, &state);
196
DEBUG_DVC("GST_MESSAGE_REQUEST_STATE: Setting %s state to %s", name, gst_element_state_get_name(state));
198
gst_element_set_state (mdecoder->pipe, state);
202
gst_message_unref(message);
207
gst_message_unref(message);
213
mdecoder->eventloop_thread = 0;
215
DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: EXITED");
219
static int tsmf_gstreamer_start_eventloop_thread(TSMFGstreamerDecoder *mdecoder)
221
pthread_create(&(mdecoder->eventloop_thread), 0, tsmf_gstreamer_eventloop_thread_func, mdecoder);
222
pthread_detach(mdecoder->eventloop_thread);
228
static int tsmf_gstreamer_stop_eventloop_thread(TSMFGstreamerDecoder *mdecoder)
230
DEBUG_DVC("tsmf_gstreamer_stop_eventloop_thread: ");
234
if (mdecoder->eventloop_thread != 0)
236
pthread_cancel(mdecoder->eventloop_thread);
242
static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder * mdecoder, GstState desired_state)
246
GstStateChangeReturn state_change;
249
GstState current_state;
250
GstState pending_state;
252
const char *current_name;
253
const char *pending_name;
256
return 0; /* Just in case this is called during startup or shutdown when we don't expect it */
258
if (desired_state == mdecoder->state)
259
return 0; /* Redundant request - Nothing to do */
261
name = tsmf_gstreamer_state_name(desired_state); /* For debug */
264
state_change = gst_element_set_state (mdecoder->pipe, desired_state);
266
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
267
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state_VIDEO:");
269
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state_AUDIO:");
273
if (state_change == GST_STATE_CHANGE_FAILURE)
275
DEBUG_WARN("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_FAILURE.", name);
278
else if (state_change == GST_STATE_CHANGE_SUCCESS)
280
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_SUCCESS.", name);
281
mdecoder->state = desired_state;
284
else if (state_change == GST_STATE_CHANGE_NO_PREROLL)
286
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_NO_PREROLL.", name);
289
else if (state_change == GST_STATE_CHANGE_ASYNC)
291
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_ASYNC.", name);
293
state_change = gst_element_get_state(mdecoder->pipe, ¤t_state, &pending_state, 10 * GST_MSECOND);
294
current_name = tsmf_gstreamer_state_name(current_state);
295
pending_name = tsmf_gstreamer_state_name(pending_state);
297
if (current_state == desired_state)
299
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_SUCCESS.", name);
300
mdecoder->state = desired_state;
303
else if (pending_state != desired_state)
305
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) changing to %s instead.", name, pending_name);
310
DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) Waiting - current %s pending %s.", name, current_name, pending_name);
314
To avoid RDP session hang. set timeout for changing gstreamer state to 5 seconds.
320
DEBUG_WARN("tsmf_gstreamer_pipeline_set_state: TIMED OUT - failed to change state");
329
static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE * media_type)
331
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
334
GstBuffer *gst_buf_cap_codec_data; /* Buffer to hold extra descriptive codec-specific caps data */
336
DEBUG_DVC("tsmf_gstreamer_set_format: ");
338
switch (media_type->MajorType)
340
case TSMF_MAJOR_TYPE_VIDEO:
341
mdecoder->media_type = TSMF_MAJOR_TYPE_VIDEO;
342
mdecoder->tsmf_media_type = *media_type; /* Structure copy */
344
case TSMF_MAJOR_TYPE_AUDIO:
345
mdecoder->media_type = TSMF_MAJOR_TYPE_AUDIO;
346
mdecoder->tsmf_media_type = *media_type; /* Structure copy */
352
switch (media_type->SubType)
354
case TSMF_SUB_TYPE_WVC1:
355
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
356
if (gst_buf_cap_codec_data != NULL)
358
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
359
media_type->ExtraData, media_type->ExtraDataSize);
363
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
364
media_type->ExtraDataSize);
366
mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
367
"bitrate", G_TYPE_UINT, media_type->BitRate,
368
"width", G_TYPE_INT, media_type->Width,
369
"height", G_TYPE_INT, media_type->Height,
370
"wmvversion", G_TYPE_INT, 3,
371
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
372
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
373
//"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
376
case TSMF_SUB_TYPE_MP4S:
377
if (media_type->ExtraDataSize > 0)
379
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
380
if (gst_buf_cap_codec_data != NULL)
382
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
386
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
388
mdecoder->gst_caps = gst_caps_new_simple ("video/x-divx",
389
"divxversion", G_TYPE_INT, 5,
390
"bitrate", G_TYPE_UINT, media_type->BitRate,
391
"width", G_TYPE_INT, media_type->Width,
392
"height", G_TYPE_INT, media_type->Height,
393
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
398
mdecoder->gst_caps = gst_caps_new_simple ("video/x-divx",
399
"divxversion", G_TYPE_INT, 5,
400
"bitrate", G_TYPE_UINT, media_type->BitRate,
401
"width", G_TYPE_INT, media_type->Width,
402
"height", G_TYPE_INT, media_type->Height,
406
case TSMF_SUB_TYPE_MP42:
407
mdecoder->gst_caps = gst_caps_new_simple ("video/x-msmpeg",
408
"msmpegversion", G_TYPE_INT, 42,
409
"bitrate", G_TYPE_UINT, media_type->BitRate,
410
"width", G_TYPE_INT, media_type->Width,
411
"height", G_TYPE_INT, media_type->Height,
414
case TSMF_SUB_TYPE_MP43:
415
mdecoder->gst_caps = gst_caps_new_simple ("video/x-msmpeg",
416
"bitrate", G_TYPE_UINT, media_type->BitRate,
417
"width", G_TYPE_INT, media_type->Width,
418
"height", G_TYPE_INT, media_type->Height,
419
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('M', 'P', '4', '3'),
422
case TSMF_SUB_TYPE_WMA9:
423
if (media_type->ExtraDataSize > 0)
425
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
426
if (gst_buf_cap_codec_data != NULL)
428
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
432
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
434
mdecoder->gst_caps = gst_caps_new_simple ("audio/x-wma",
435
"wmaversion", G_TYPE_INT, 3,
436
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
437
"channels", G_TYPE_INT, media_type->Channels,
438
"bitrate", G_TYPE_INT, media_type->BitRate,
439
"depth", G_TYPE_INT, media_type->BitsPerSample,
440
"width", G_TYPE_INT, media_type->BitsPerSample,
441
"block_align", G_TYPE_INT, media_type->BlockAlign,
442
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
447
mdecoder->gst_caps = gst_caps_new_simple ("audio/x-wma",
448
"wmaversion", G_TYPE_INT, 3,
449
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
450
"channels", G_TYPE_INT, media_type->Channels,
451
"bitrate", G_TYPE_INT, media_type->BitRate,
452
"depth", G_TYPE_INT, media_type->BitsPerSample,
453
"width", G_TYPE_INT, media_type->BitsPerSample,
454
"block_align", G_TYPE_INT, media_type->BlockAlign,
458
case TSMF_SUB_TYPE_WMA2:
459
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
460
if (gst_buf_cap_codec_data != NULL)
462
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
463
media_type->ExtraData, media_type->ExtraDataSize);
467
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
468
media_type->ExtraDataSize);
471
mdecoder->gst_caps = gst_caps_new_simple ("audio/x-wma",
472
"wmaversion", G_TYPE_INT, 2,
473
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
474
"channels", G_TYPE_INT, media_type->Channels,
475
"bitrate", G_TYPE_INT, media_type->BitRate,
476
"depth", G_TYPE_INT, media_type->BitsPerSample,
477
"width", G_TYPE_INT, media_type->BitsPerSample,
478
"block_align", G_TYPE_INT, media_type->BlockAlign,
479
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
482
case TSMF_SUB_TYPE_MP3:
483
mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
484
"mpegversion", G_TYPE_INT, 1,
485
"mpegaudioversion", G_TYPE_INT, 1,
486
"layer", G_TYPE_INT, 3,
487
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
488
"channels", G_TYPE_INT, media_type->Channels,
489
"parsed", G_TYPE_BOOLEAN, TRUE,
492
case TSMF_SUB_TYPE_WMV1:
493
mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
494
"bitrate", G_TYPE_UINT, media_type->BitRate,
495
"width", G_TYPE_INT, media_type->Width,
496
"height", G_TYPE_INT, media_type->Height,
497
"wmvversion", G_TYPE_INT, 1,
498
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'M', 'V', '1'),
501
case TSMF_SUB_TYPE_WMV2:
502
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
503
if (gst_buf_cap_codec_data != NULL)
505
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
506
media_type->ExtraData, media_type->ExtraDataSize);
510
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
511
media_type->ExtraDataSize);
513
mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
514
"width", G_TYPE_INT, media_type->Width,
515
"height", G_TYPE_INT, media_type->Height,
516
"wmvversion", G_TYPE_INT, 2,
517
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
518
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'M', 'V', '2'),
521
case TSMF_SUB_TYPE_WMV3:
522
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
523
if (gst_buf_cap_codec_data != NULL)
525
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
526
media_type->ExtraData, media_type->ExtraDataSize);
530
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
531
media_type->ExtraDataSize);
533
mdecoder->gst_caps = gst_caps_new_simple ("video/x-wmv",
534
"bitrate", G_TYPE_UINT, media_type->BitRate,
535
"width", G_TYPE_INT, media_type->Width,
536
"height", G_TYPE_INT, media_type->Height,
537
"wmvversion", G_TYPE_INT, 3,
538
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
539
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'M', 'V', '3'),
540
//"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
543
case TSMF_SUB_TYPE_AVC1:
544
case TSMF_SUB_TYPE_H264:
545
if (media_type->ExtraDataSize > 0)
547
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
548
if (gst_buf_cap_codec_data != NULL)
550
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
554
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
556
mdecoder->gst_caps = gst_caps_new_simple ("video/x-h264",
557
"width", G_TYPE_INT, media_type->Width,
558
"height", G_TYPE_INT, media_type->Height,
559
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
560
//"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
565
mdecoder->gst_caps = gst_caps_new_simple ("video/x-h264",
566
"width", G_TYPE_INT, media_type->Width,
567
"height", G_TYPE_INT, media_type->Height,
568
//"framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
572
case TSMF_SUB_TYPE_AC3:
573
mdecoder->gst_caps = gst_caps_new_simple ("audio/x-ac3",
574
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
575
"channels", G_TYPE_INT, media_type->Channels,
578
case TSMF_SUB_TYPE_AAC:
579
/* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
580
is at the end of it. See
581
http://msdn.microsoft.com/en-us/library/dd757806.aspx */
582
if (media_type->ExtraData)
584
media_type->ExtraData += 12;
585
media_type->ExtraDataSize -= 12;
587
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
588
if (gst_buf_cap_codec_data != NULL)
590
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data),
591
media_type->ExtraData, media_type->ExtraDataSize);
595
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.",
596
media_type->ExtraDataSize);
598
mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
599
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
600
"channels", G_TYPE_INT, media_type->Channels,
601
"mpegversion", G_TYPE_INT, 4,
602
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
605
case TSMF_SUB_TYPE_MP1A:
606
if (media_type->ExtraDataSize > 0)
608
gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
609
if (gst_buf_cap_codec_data != NULL)
611
memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
615
DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
617
mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
618
"mpegversion", G_TYPE_INT, 1,
619
"channels", G_TYPE_INT, media_type->Channels,
620
"codec_data", GST_TYPE_BUFFER, gst_buf_cap_codec_data,
625
mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
626
"mpegversion", G_TYPE_INT, 1,
627
"channels", G_TYPE_INT, media_type->Channels,
631
case TSMF_SUB_TYPE_MP1V:
632
mdecoder->gst_caps = gst_caps_new_simple ("video/mpeg",
633
"mpegversion", G_TYPE_INT, 1,
634
"width", G_TYPE_INT, media_type->Width,
635
"height", G_TYPE_INT, media_type->Height,
636
"systemstream", G_TYPE_BOOLEAN, FALSE,
639
case TSMF_SUB_TYPE_YUY2:
640
mdecoder->gst_caps = gst_caps_new_simple ("video/x-raw-yuv",
641
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
642
//"bitrate", G_TYPE_UINT, media_type->BitRate,
643
"width", G_TYPE_INT, media_type->Width,
644
"height", G_TYPE_INT, media_type->Height,
647
case TSMF_SUB_TYPE_MP2V:
648
mdecoder->gst_caps = gst_caps_new_simple ("video/mpeg",
649
//"bitrate", G_TYPE_UINT, media_type->BitRate,
650
//"width", G_TYPE_INT, media_type->Width,
651
//"height", G_TYPE_INT, media_type->Height,
652
"mpegversion", G_TYPE_INT, 2,
653
"systemstream", G_TYPE_BOOLEAN, FALSE,
656
case TSMF_SUB_TYPE_MP2A:
657
mdecoder->gst_caps = gst_caps_new_simple ("audio/mpeg",
658
"mpegversion", G_TYPE_INT, 2,
659
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
660
"channels", G_TYPE_INT, media_type->Channels,
664
case TSMF_SUB_TYPE_AC3:
668
DEBUG_WARN("tsmf_gstreamer_set_format: unknown format:(%d).", media_type->SubType);
675
static void tsmf_gstreamer_pipeline_send_end_of_stream(TSMFGstreamerDecoder * mdecoder)
677
DEBUG_DVC("tsmf_gstreamer_pipeline_send_end_of_stream: ");
679
if (mdecoder && mdecoder->src)
681
gst_app_src_end_of_stream(GST_APP_SRC(mdecoder->src));
688
/* code from TI to check whether OMX is being lock or not */
689
static BOOL tsmf_gstreamer_pipeline_omx_available()
697
struct shm_info *info = NULL;
699
shm_fd = shm_open ("gstomx", (O_CREAT | O_RDWR), (S_IREAD | S_IWRITE));
702
DEBUG_DVC("ERROR: failed to open shm");
707
ftruncate(shm_fd, sizeof(struct shm_info));
709
if ((info = mmap(0, sizeof(struct shm_info), (PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0)) == MAP_FAILED)
711
DEBUG_DVC("ERROR: failed to map");
717
DEBUG_DVC ("ERROR: omxcore is in use by '%d'", info->pid);
722
DEBUG_DVC ("omxcore is available for use");
728
munmap (info, sizeof(struct shm_info));
737
static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder * mdecoder)
739
//Cleaning up elements
745
gst_object_unref(mdecoder->src);
746
mdecoder->src = NULL;
750
gst_object_unref(mdecoder->queue);
751
mdecoder->queue = NULL;
753
if (mdecoder->decbin)
755
gst_object_unref(mdecoder->decbin);
756
mdecoder->decbin = NULL;
760
gst_object_unref(mdecoder->outbin);
761
mdecoder->outbin = NULL;
763
if (mdecoder->outconv)
765
gst_object_unref(mdecoder->outconv);
766
mdecoder->outconv = NULL;
768
if (mdecoder->outsink)
770
gst_object_unref(mdecoder->outsink);
771
mdecoder->outsink = NULL;
773
if (mdecoder->aVolume)
775
gst_object_unref(mdecoder->aVolume);
776
mdecoder->aVolume = NULL;
781
static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder * mdecoder)
787
mdecoder->pipe = gst_pipeline_new (NULL);
790
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to create new pipe");
794
BOOL OMXavailable = FALSE;
797
OMXavailable = tsmf_gstreamer_pipeline_omx_available();
801
* On Atlas without this printf, we'll see Illegal instruction only with optimization level set to -O2.
803
const char *blank = "";
806
BOOL hwaccelflu = FALSE;
807
BOOL hwaccelomx = FALSE;
809
switch (mdecoder->tsmf_media_type.SubType)
811
case TSMF_SUB_TYPE_WMA2:
812
mdecoder->decbin = gst_element_factory_make ("fluwmadec", NULL);
813
if (!mdecoder->decbin)
814
mdecoder->decbin = gst_element_factory_make ("ffdec_wmav2", NULL);
815
DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMA2");
817
case TSMF_SUB_TYPE_WMA9:
818
mdecoder->decbin = gst_element_factory_make ("fluwmadec", NULL);
819
if (!mdecoder->decbin)
820
mdecoder->decbin = gst_element_factory_make ("ffdec_wmapro", NULL);
821
DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMA9 - WMA PRO version 3");
823
case TSMF_SUB_TYPE_MP3:
824
mdecoder->decbin = gst_element_factory_make ("flump3dec", NULL);
825
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP3");
827
case TSMF_SUB_TYPE_MP4S:
830
mdecoder->decbin = gst_element_factory_make ("omx_mpeg4dec", NULL);
831
if (mdecoder->decbin)
837
mdecoder->decbin = NULL;
839
if(!mdecoder->decbin)
840
mdecoder->decbin = gst_element_factory_make ("flumpeg4vdec", NULL);
841
if(!mdecoder->decbin)
842
mdecoder->decbin = gst_element_factory_make ("ffdec_mpeg4", NULL);
843
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP4S");
845
case TSMF_SUB_TYPE_MP42:
846
mdecoder->decbin = gst_element_factory_make ("ffdec_msmpeg4v2", NULL);
847
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP42");
849
case TSMF_SUB_TYPE_MP43:
850
mdecoder->decbin = gst_element_factory_make ("ffdec_msmpeg4", NULL);
851
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP43");
853
case TSMF_SUB_TYPE_MP2V:
856
mdecoder->decbin = gst_element_factory_make ("omx_mpeg2dec", NULL);
857
if (mdecoder->decbin)
863
mdecoder->decbin = NULL;
864
if (!mdecoder->decbin)
865
mdecoder->decbin = gst_element_factory_make ("ffdec_mpeg2video", NULL);
867
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MPEG2 Video");
869
case TSMF_SUB_TYPE_WMV1:
870
mdecoder->decbin = gst_element_factory_make ("ffdec_wmv1", NULL);
871
DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV1");
873
case TSMF_SUB_TYPE_WMV2:
874
mdecoder->decbin = gst_element_factory_make ("ffdec_wmv2", NULL);
875
DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV2");
877
case TSMF_SUB_TYPE_WVC1:
878
case TSMF_SUB_TYPE_WMV3:
879
mdecoder->decbin = gst_element_factory_make ("fluvadec", NULL);
880
if (mdecoder->decbin)
888
mdecoder->decbin = gst_element_factory_make ("omx_vc1dec", NULL);
889
if (mdecoder->decbin)
893
mdecoder->decbin = NULL;
896
if (!mdecoder->decbin)
897
mdecoder->decbin = gst_element_factory_make ("fluwmvdec", NULL);
898
if (!mdecoder->decbin)
899
mdecoder->decbin = gst_element_factory_make ("ffdec_wmv3", NULL);
900
DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV3");
902
case TSMF_SUB_TYPE_AVC1:
903
case TSMF_SUB_TYPE_H264:
904
mdecoder->decbin = gst_element_factory_make ("fluvadec", NULL);
905
if (mdecoder->decbin)
913
mdecoder->decbin = gst_element_factory_make ("omx_h264dec", NULL);
914
if (mdecoder->decbin)
918
mdecoder->decbin = NULL;
920
if (!mdecoder->decbin)
921
mdecoder->decbin = gst_element_factory_make ("fluh264dec", NULL);
923
if (!mdecoder->decbin)
924
mdecoder->decbin = gst_element_factory_make ("ffdec_h264", NULL);
925
DEBUG_DVC("tsmf_gstreamer_pipeline_build: H264");
927
case TSMF_SUB_TYPE_AC3:
928
mdecoder->decbin = gst_element_factory_make ("ffdec_ac3", NULL);
929
//mdecoder->decbin = gst_element_factory_make ("ffdec_ac3", NULL);//no fluendo equivalent?
930
DEBUG_DVC("tsmf_gstreamer_pipeline_build: AC3");
932
case TSMF_SUB_TYPE_AAC:
933
mdecoder->decbin = gst_element_factory_make ("fluaacdec", NULL);
934
if (!mdecoder->decbin)
935
mdecoder->decbin = gst_element_factory_make ("faad", NULL);
936
if (!mdecoder->decbin)
937
mdecoder->decbin = gst_element_factory_make ("ffdec_aac", NULL);
938
DEBUG_DVC("tsmf_gstreamer_pipeline_build: AAC");
940
case TSMF_SUB_TYPE_MP2A:
941
mdecoder->decbin = gst_element_factory_make ("fluaacdec", NULL);
942
if (!mdecoder->decbin)
943
mdecoder->decbin = gst_element_factory_make ("faad", NULL);
944
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP2A");
946
case TSMF_SUB_TYPE_MP1A:
947
mdecoder->decbin = gst_element_factory_make ("flump3dec", NULL);
948
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP1A");
950
case TSMF_SUB_TYPE_MP1V:
951
mdecoder->decbin = gst_element_factory_make ("ffdec_mpegvideo", NULL);
952
DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP1V");
955
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Unsupported media type %d", mdecoder->tsmf_media_type.SubType);
958
if (!mdecoder->decbin)
960
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load decoder plugin");
964
switch (mdecoder->media_type)
966
case TSMF_MAJOR_TYPE_VIDEO:
968
mdecoder->outbin = gst_bin_new ("videobin");
971
mdecoder->outconv = gst_element_factory_make ("queue", "queuetosink");
972
mdecoder->outsink = gst_element_factory_make ("fluvasink", "videosink");
976
mdecoder->outconv = gst_element_factory_make ("queue", "queuetosink");
977
mdecoder->outsink = gst_element_factory_make ("gemxvimagesink", "videosink");
981
mdecoder->outconv = gst_element_factory_make ("ffmpegcolorspace", "vconv");
982
mdecoder->outsink = gst_element_factory_make ("xvimagesink", "videosink");
984
DEBUG_DVC("tsmf_gstreamer_pipeline_build: building Video Pipe");
986
if (mdecoder->xfwin == (int *) -1)
987
DEBUG_WARN("tsmf_gstreamer_entry: failed to assign pointer to the memory address - shmat()");
991
mdecoder->disp = XOpenDisplay(NULL);
993
if (!mdecoder->subwin)
995
mdecoder->subwin = XCreateSimpleWindow(mdecoder->disp, *mdecoder->xfwin, 0, 0, 1, 1, 0, 0, 0);
996
XMapWindow(mdecoder->disp, mdecoder->subwin);
997
XSync(mdecoder->disp, FALSE);
1000
mdecoder->aVolume = 0;
1003
case TSMF_MAJOR_TYPE_AUDIO:
1005
mdecoder->outbin = gst_bin_new ("audiobin");
1006
mdecoder->outconv = gst_element_factory_make ("audioconvert", "aconv");
1007
mdecoder->outsink = gst_element_factory_make ("alsasink", NULL);
1008
mdecoder->aVolume = gst_element_factory_make ("volume", "AudioVol");
1009
if (mdecoder->aVolume)
1011
g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
1012
g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
1014
DEBUG_DVC("tsmf_gstreamer_pipeline_build: building Audio Pipe");
1020
if (!mdecoder->outconv)
1022
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load media converter");
1023
tsmf_gstreamer_clean_up(mdecoder);
1026
if (!mdecoder->outsink)
1028
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load xvimagesink plugin");
1029
tsmf_gstreamer_clean_up(mdecoder);
1033
mdecoder->src = gst_element_factory_make ("appsrc", NULL);
1034
mdecoder->queue = gst_element_factory_make ("queue2", NULL);
1035
g_object_set(mdecoder->queue, "use-buffering", FALSE, NULL);
1036
g_object_set(mdecoder->queue, "use-rate-estimate", FALSE, NULL);
1037
g_object_set(mdecoder->outsink, "async", FALSE, NULL);
1038
g_object_set(mdecoder->src, "format", GST_FORMAT_TIME, NULL);
1039
gst_app_src_set_stream_type((GstAppSrc *) mdecoder->src, GST_APP_STREAM_TYPE_STREAM);
1040
gst_app_src_set_max_bytes((GstAppSrc *) mdecoder->src, 4*1024*1024); /* 32 Mbits */
1041
gst_app_src_set_caps((GstAppSrc *) mdecoder->src, mdecoder->gst_caps);
1043
out_pad = gst_element_get_static_pad(mdecoder->outconv, "sink");
1045
gboolean linkResult = FALSE;
1046
gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->outconv);
1047
gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->outsink);
1048
if (mdecoder->aVolume)
1050
gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->aVolume);
1051
linkResult = gst_element_link_many(mdecoder->outconv, mdecoder->aVolume, mdecoder->outsink, NULL);
1055
linkResult = gst_element_link(mdecoder->outconv, mdecoder->outsink);
1059
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: converter->sink");
1060
tsmf_gstreamer_clean_up(mdecoder);
1064
gst_element_add_pad(mdecoder->outbin, gst_ghost_pad_new ("sink", out_pad));
1065
gst_object_unref(out_pad);
1067
gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->src);
1068
gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->queue);
1069
gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->decbin);
1070
gst_bin_add(GST_BIN(mdecoder->pipe), mdecoder->outbin);
1072
linkResult = gst_element_link_many(mdecoder->src, mdecoder->queue, mdecoder->decbin, NULL);
1075
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: source->decoder");
1076
tsmf_gstreamer_clean_up(mdecoder);
1080
mdecoder->linked = gst_element_link(mdecoder->decbin, mdecoder->outbin);
1081
if (!mdecoder->linked)
1083
DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: decoder->output_bin");
1084
tsmf_gstreamer_clean_up(mdecoder);
1088
if (GST_IS_X_OVERLAY (mdecoder->outsink))
1090
//gst_x_overlay_set_window_handle (GST_X_OVERLAY (mdecoder->outsink), *mdecoder->xfwin);
1091
if(mdecoder->subwin)
1093
//gdk_threads_enter();
1094
gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mdecoder->outsink), mdecoder->subwin);
1095
//gdk_threads_leave();
1099
g_object_set(mdecoder->outsink, "preroll-queue-len", 10, NULL);
1103
static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder * decoder, const BYTE * data, UINT32 data_size, UINT32 extensions,
1104
UINT64 start_time, UINT64 end_time, UINT64 duration)
1106
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder*) decoder;
1113
int mutexret = pthread_mutex_lock(&mdecoder->gst_mutex);
1118
if (mdecoder->shutdown)
1120
pthread_mutex_unlock(&mdecoder->gst_mutex);
1127
* This function is always called from a stream-specific thread.
1128
* It should be alright to block here if necessary.
1129
* We don't expect to block here often, since the pipeline should
1130
* have more than enough buffering.
1133
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
1135
DEBUG_DVC("tsmf_gstreamer_decodeEx_VIDEO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
1136
start_time, end_time, duration, mdecoder->last_sample_end_time);
1140
DEBUG_DVC("tsmf_gstreamer_decodeEx_AUDIO. Start:(%"PRIu64") End:(%"PRIu64") Duration:(%"PRIu64") Last End:(%"PRIu64")",
1141
start_time, end_time, duration, mdecoder->last_sample_end_time);
1144
if (mdecoder->gst_caps == NULL)
1146
DEBUG_WARN("tsmf_gstreamer_decodeEx: tsmf_gstreamer_set_format not called or invalid format.");
1147
pthread_mutex_unlock(&mdecoder->gst_mutex);
1151
if (mdecoder->pipe == NULL)
1153
if (!tsmf_gstreamer_pipeline_build(mdecoder))
1157
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
1158
gst_object_unref(mdecoder->pipe);
1159
mdecoder->pipe = NULL;
1161
pthread_mutex_unlock(&mdecoder->gst_mutex);
1165
//tsmf_gstreamer_start_eventloop_thread(mdecoder);
1167
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
1168
mdecoder->pipeline_start_time_valid = 0;
1173
* this is to fix gstreamer's seeking forward/backward issue with live stream.
1174
* set the seeking tolerance to 1 second.
1176
if (start_time > (mdecoder->last_sample_end_time + 10000000) || (end_time + 10000000) < mdecoder->last_sample_end_time)
1178
DEBUG_DVC("tsmf_gstreamer_decodeEx: start_time=[%"PRIu64"] > last_sample_end_time=[%"PRIu64"]", start_time, mdecoder->last_sample_end_time);
1179
DEBUG_DVC("tsmf_gstreamer_decodeEx: Stream seek detected - flushing element.");
1180
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
1181
gst_object_unref(mdecoder->pipe);
1182
mdecoder->pipe = NULL;
1183
if (!tsmf_gstreamer_pipeline_build(mdecoder))
1187
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
1188
gst_object_unref(mdecoder->pipe);
1189
mdecoder->pipe = NULL;
1191
pthread_mutex_unlock(&mdecoder->gst_mutex);
1194
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
1195
mdecoder->pipeline_start_time_valid = 0;
1197
* This is to fix the discrepancy between audio/video start time during a seek
1200
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
1201
fout = fopen("/tmp/tsmf_vseek.info", "wt");
1203
fout = fopen("/tmp/tsmf_aseek.info", "wt");
1207
fprintf(fout, "%"PRIu64"\n", start_time);
1216
pthread_mutex_unlock(&mdecoder->gst_mutex);
1217
DEBUG_WARN("tsmf_gstreamer_decodeEx: failed to construct pipeline correctly. Unable to push buffer to source element.");
1221
if (GST_STATE(mdecoder->pipe) != GST_STATE_PAUSED && GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
1223
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
1224
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
1226
FILE *fout = fopen("/tmp/tsmf_video.ready", "wt");
1229
FILE *fin = fopen("/tmp/tsmf_aseek.info", "rt");
1232
UINT64 AStartTime = 0;
1233
fscanf(fin, "%"PRIu64, &AStartTime);
1235
if (start_time > AStartTime)
1237
UINT64 streamDelay = (start_time - AStartTime) / 10;
1238
usleep(streamDelay);
1240
unlink("/tmp/tsmf_aseek.info");
1243
else if (mdecoder->media_type == TSMF_MAJOR_TYPE_AUDIO)
1246
FILE *fin = fopen("/tmp/tsmf_video.ready", "rt");
1251
//wait up to 1.5 second
1252
if (timeout >= 1500)
1254
fin = fopen("/tmp/tsmf_video.ready", "rt");
1259
unlink("/tmp/tsmf_video.ready");
1263
fin = fopen("/tmp/tsmf_vseek.info", "rt");
1266
UINT64 VStartTime = 0;
1267
fscanf(fin, "%"PRIu64, &VStartTime);
1269
if (start_time > VStartTime)
1271
UINT64 streamDelay = (start_time - VStartTime) / 10;
1272
usleep(streamDelay);
1274
unlink("/tmp/tsmf_vseek.info");
1279
gst_buf = gst_buffer_try_new_and_alloc(data_size);
1280
if (gst_buf == NULL)
1282
pthread_mutex_unlock(&mdecoder->gst_mutex);
1283
DEBUG_WARN("tsmf_gstreamer_decodeEx: gst_buffer_try_new_and_alloc(%d) failed.", data_size);
1286
gst_buffer_set_caps(gst_buf, mdecoder->gst_caps);
1287
memcpy(GST_BUFFER_MALLOCDATA(gst_buf), data, data_size);
1288
GST_BUFFER_TIMESTAMP(gst_buf) = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
1289
GST_BUFFER_DURATION(gst_buf) = tsmf_gstreamer_timestamp_ms_to_gst(duration);
1291
gst_app_src_push_buffer(GST_APP_SRC(mdecoder->src), gst_buf);
1293
mdecoder->last_sample_end_time = end_time;
1295
if (!mdecoder->pipeline_start_time_valid)
1297
gst_element_set_base_time(mdecoder->pipe, tsmf_gstreamer_timestamp_ms_to_gst(start_time));
1298
gst_element_set_start_time(mdecoder->pipe, tsmf_gstreamer_timestamp_ms_to_gst(start_time));
1299
mdecoder->pipeline_start_time_valid = 1;
1302
if(GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
1304
if (!mdecoder->paused)
1306
if (mdecoder->subwin)
1308
XMapWindow(mdecoder->disp, mdecoder->subwin);
1309
XSync(mdecoder->disp, FALSE);
1311
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
1314
pthread_mutex_unlock(&mdecoder->gst_mutex);
1318
static void tsmf_gstreamer_change_volume(ITSMFDecoder * decoder, UINT32 newVolume, UINT32 muted)
1320
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
1324
if (mdecoder->shutdown)
1327
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
1330
mdecoder->gstMuted = (BOOL) muted;
1331
DEBUG_DVC("tsmf_gstreamer_change_volume: mute=[%d]", mdecoder->gstMuted);
1332
mdecoder->gstVolume = (double) newVolume / (double) 10000;
1333
DEBUG_DVC("tsmf_gstreamer_change_volume: gst_new_vol=[%f]", mdecoder->gstVolume);
1335
if (!mdecoder->aVolume)
1338
if (!G_IS_OBJECT(mdecoder->aVolume))
1341
g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
1342
g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
1345
static void tsmf_gstreamer_control(ITSMFDecoder * decoder, ITSMFControlMsg control_msg, UINT32 *arg)
1347
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
1351
if (control_msg == Control_Pause)
1353
DEBUG_DVC("tsmf_gstreamer_control: Control_Pause");
1354
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
1355
mdecoder->paused = TRUE;
1357
if (mdecoder->subwin)
1359
XUnmapWindow(mdecoder->disp, mdecoder->subwin);
1360
XSync(mdecoder->disp, FALSE);
1363
else if (control_msg == Control_Restart)
1365
DEBUG_DVC("tsmf_gstreamer_control: Control_Restart");
1366
mdecoder->paused = FALSE;
1367
if (mdecoder->subwin)
1369
XMapWindow(mdecoder->disp, mdecoder->subwin);
1370
XSync(mdecoder->disp, FALSE);
1372
if (mdecoder->pipeline_start_time_valid)
1373
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
1375
else if (control_msg == Control_Flush)
1377
DEBUG_DVC("tsmf_gstreamer_control: Control_Flush");
1378
/* Reset stamps, flush buffers, etc */
1381
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
1382
gst_object_unref(mdecoder->pipe);
1383
mdecoder->pipe = NULL;
1385
mdecoder->pipeline_start_time_valid = 0;
1386
mdecoder->paused = FALSE;
1388
if (mdecoder->subwin)
1390
XUnmapWindow(mdecoder->disp, mdecoder->subwin);
1391
XSync(mdecoder->disp, FALSE);
1394
else if (control_msg == Control_EndOfStream)
1396
mdecoder->paused = FALSE;
1397
DEBUG_DVC("tsmf_gstreamer_control: Control_EndOfStream");
1399
* The EOS may take some time to flow through the pipeline
1400
* If the server sees the client "End of Stream Processed"
1401
* notification too soon, it may shut down the stream
1402
* and clip the end of files.
1403
* If that's the case, then we'll need to change the TSMF layer
1404
* to send the "End of Stream Processed" only after the stream
1406
* (It's unlikely we can simply "wait" here for it to happen
1407
* since we don't want to hold up acks, etc.)
1409
tsmf_gstreamer_pipeline_send_end_of_stream(mdecoder);
1413
static guint tsmf_gstreamer_buffer_level(ITSMFDecoder * decoder)
1415
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
1416
DEBUG_DVC("tsmf_gstreamer_buffer_level\n");
1421
if (mdecoder->shutdown)
1424
if (!G_IS_OBJECT(mdecoder->queue))
1428
g_object_get(mdecoder->queue, "current-level-buffers", &clbuff, NULL);
1432
static void tsmf_gstreamer_free(ITSMFDecoder * decoder)
1434
TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
1435
DEBUG_DVC("tsmf_gstreamer_free\n");
1439
pthread_mutex_lock(&mdecoder->gst_mutex);
1440
mdecoder->shutdown = 1;
1443
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
1444
gst_object_unref(mdecoder->pipe);
1445
mdecoder->pipe = NULL;
1447
tsmf_gstreamer_stop_eventloop_thread(mdecoder);
1448
if (mdecoder->gst_caps)
1449
gst_caps_unref(mdecoder->gst_caps);
1451
if (mdecoder->subwin)
1453
DEBUG_DVC("destroy subwindow\n");
1454
XDestroyWindow(mdecoder->disp, mdecoder->subwin);
1455
XSync(mdecoder->disp, FALSE);
1459
XCloseDisplay(mdecoder->disp);
1461
unlink("/tmp/tsmf_aseek.info");
1462
unlink("/tmp/tsmf_vseek.info");
1463
unlink("/tmp/tsmf_video.ready");
1465
pthread_mutex_unlock(&mdecoder->gst_mutex);
1471
static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder * decoder)
1473
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
1476
if (!mdecoder->outsink)
1477
return mdecoder->last_sample_end_time;
1479
if(GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
1482
GstFormat fmt = GST_FORMAT_TIME;
1484
gst_element_query_position (mdecoder->outsink, &fmt, &pos);
1485
DEBUG_DVC("tsmf_gstreamer_current_pos=[%"PRIu64"]", pos);
1489
static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles)
1491
DEBUG_DVC("tsmf_gstreamer_update_rendering_area");
1492
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
1496
if (mdecoder->shutdown)
1499
if (GST_IS_X_OVERLAY (mdecoder->outsink))
1501
if (!mdecoder->disp)
1502
mdecoder->disp = XOpenDisplay(NULL);
1507
if (!mdecoder->offsetObtained)
1509
XSync(mdecoder->disp, FALSE);
1510
RROutput primary_output;
1511
XRRScreenResources *res = 0;
1513
res = XRRGetScreenResourcesCurrent(mdecoder->disp, RootWindow(mdecoder->disp, screen));
1516
DEBUG_DVC("number of output:%d", res->ncrtc);
1517
primary_output = XRRGetOutputPrimary(mdecoder->disp, DefaultRootWindow(mdecoder->disp));
1518
DEBUG_DVC("primary_output:%d", (int)primary_output);
1520
for (i = 0; i < res->ncrtc; i++)
1522
XRRCrtcInfo *info = XRRGetCrtcInfo(mdecoder->disp, res, res->crtcs[i]);
1525
if (info->noutput > 0)
1527
if (info->outputs[0] == primary_output || i == 0)
1529
mdecoder->xOffset = info->x;
1530
mdecoder->yOffset = info->y;
1532
DEBUG_DVC("output %d ID: %lu (x,y): (%d,%d) (w,h): (%d,%d) primary: %d", i, info->outputs[0], info->x, info->y, info->width, info->height, (info->outputs[0] == primary_output));
1534
XRRFreeCrtcInfo(info);
1538
mdecoder->offsetObtained = TRUE;
1540
anewX += mdecoder->xOffset;
1541
anewY += mdecoder->yOffset;
1543
XSync(mdecoder->disp, FALSE);
1544
//end of multi-mon test
1546
if(mdecoder->subwin)
1548
XMoveWindow(mdecoder->disp, mdecoder->subwin, anewX, anewY);
1549
if(newWidth > 0 && newHeight > 0) {
1550
XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
1552
XResizeWindow(mdecoder->disp, mdecoder->subwin, 1, 1);
1555
XSync(mdecoder->disp, FALSE);
1556
XShapeCombineRectangles (mdecoder->disp, mdecoder->subwin, ShapeBounding, 0, 0,(XRectangle*) rectangles, numRectangles, ShapeSet, Unsorted);
1557
XSync(mdecoder->disp, FALSE);
1558
//Sending Expose Event so freeRDP can do a redraw.
1560
xpose.type = Expose;
1561
xpose.display = mdecoder->disp;
1562
xpose.window = *mdecoder->xfwin;
1565
XSendEvent(mdecoder->disp, *mdecoder->xfwin, TRUE, ExposureMask, (XEvent *)&xpose);
1566
XSync(mdecoder->disp, FALSE);
1568
gst_x_overlay_expose (GST_X_OVERLAY (mdecoder->outsink));
1572
static int initialized = 0;
1574
#ifdef STATIC_CHANNELS
1575
#define freerdp_tsmf_client_decoder_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
1578
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
1580
TSMFGstreamerDecoder* decoder;
1588
decoder = malloc(sizeof(TSMFGstreamerDecoder));
1589
memset(decoder, 0, sizeof(TSMFGstreamerDecoder));
1591
decoder->iface.SetFormat = tsmf_gstreamer_set_format;
1592
decoder->iface.Decode = NULL;
1593
decoder->iface.GetDecodedData = NULL;
1594
decoder->iface.GetDecodedFormat = NULL;
1595
decoder->iface.GetDecodedDimension = NULL;
1596
decoder->iface.GetRunningTime = tsmf_gstreamer_get_running_time;
1597
decoder->iface.UpdateRenderingArea = tsmf_gstreamer_update_rendering_area;
1598
decoder->iface.Free = tsmf_gstreamer_free;
1599
decoder->iface.Control = tsmf_gstreamer_control;
1600
decoder->iface.DecodeEx = tsmf_gstreamer_decodeEx;
1601
decoder->iface.ChangeVolume = tsmf_gstreamer_change_volume;
1602
decoder->iface.BufferLevel = tsmf_gstreamer_buffer_level;
1603
decoder->paused = FALSE;
1604
decoder->subwin = 0;
1605
decoder->xOffset = 0;
1606
decoder->yOffset = 0;
1607
decoder->offsetObtained = FALSE;
1608
decoder->gstVolume = 0.5;
1609
decoder->gstMuted = FALSE;
1610
decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */
1611
pthread_mutex_init(&decoder->gst_mutex, NULL);
1613
int shmid = shmget(SHARED_MEM_KEY, sizeof(int), 0666);
1616
DEBUG_WARN("tsmf_gstreamer_entry: failed to get access to shared memory - shmget()");
1620
decoder->xfwin = shmat(shmid, NULL, 0);
1625
return (ITSMFDecoder *) decoder;