~ubuntu-branches/ubuntu/vivid/freerdp/vivid

« back to all changes in this revision

Viewing changes to channels/tsmf/client/gstreamer/tsmf_gstreamer.c

  • Committer: Package Import Robot
  • Author(s): Iain Lane
  • Date: 2014-11-11 12:20:50 UTC
  • mfrom: (1.1.9) (9.1.17 sid)
  • Revision ID: package-import@ubuntu.com-20141111122050-wyr8hrnwco9fcmum
Tags: 1.1.0~git20140921.1.440916e+dfsg1-2ubuntu1
* Merge with Debian unstable, remaining changes
  - Disable ffmpeg support
* Disable gstreamer support, this relies on gstreamer 0.10 and we don't want
  to add any more deps on that.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * FreeRDP: A Remote Desktop Protocol Implementation
 
3
 * Video Redirection Virtual Channel - GStreamer Decoder
 
4
 *
 
5
 * (C) Copyright 2012 HP Development Company, LLC 
 
6
 * 
 
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
 
10
 *
 
11
 *     http://www.apache.org/licenses/LICENSE-2.0
 
12
 *
 
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.
 
18
*/
 
19
 
 
20
#ifdef HAVE_CONFIG_H
 
21
#include "config.h"
 
22
#endif
 
23
 
 
24
#include <X11/Xlib.h>
 
25
#include <X11/extensions/Xrandr.h>
 
26
#include <X11/extensions/shape.h>
 
27
 
 
28
#include <fcntl.h>
 
29
#include <stdio.h>
 
30
#include <stdlib.h>
 
31
#include <string.h>
 
32
#include <unistd.h>
 
33
#include <pthread.h>
 
34
 
 
35
#include <gst/gst.h>
 
36
#include <gst/app/gstappsrc.h>
 
37
#include <gst/app/gstappsink.h>
 
38
#include <gst/interfaces/xoverlay.h>
 
39
 
 
40
#include <sys/types.h>
 
41
#include <sys/shm.h>
 
42
#include <sys/mman.h>
 
43
#include <sys/stat.h>
 
44
#include <sys/syscall.h>
 
45
 
 
46
#include "tsmf_constants.h"
 
47
#include "tsmf_decoder.h"
 
48
 
 
49
#ifdef HAVE_INTTYPES_H
 
50
#include <inttypes.h>
 
51
#endif
 
52
 
 
53
#define SHARED_MEM_KEY  7777
 
54
#define TRY_DECODEBIN   0
 
55
 
 
56
typedef struct _TSMFGstreamerDecoder
 
57
{
 
58
        ITSMFDecoder iface;
 
59
 
 
60
        int media_type; /* TSMF_MAJOR_TYPE_AUDIO or TSMF_MAJOR_TYPE_VIDEO */
 
61
 
 
62
        TS_AM_MEDIA_TYPE tsmf_media_type; /* TSMF description of the media type, (without ExtraData) */
 
63
 
 
64
        pthread_t eventloop_thread;
 
65
 
 
66
        GstCaps *gst_caps;  /* Gstreamer description of the media type */
 
67
 
 
68
        GstState state;
 
69
 
 
70
        GstElement *pipe;
 
71
        GstElement *src;
 
72
        GstElement *queue;
 
73
        GstElement *decbin;
 
74
        GstElement *outbin;
 
75
        GstElement *outconv;
 
76
        GstElement *outsink;
 
77
        GstElement *aVolume;
 
78
 
 
79
        BOOL paused;
 
80
        UINT64 last_sample_end_time;
 
81
 
 
82
        Display *disp;
 
83
        int *xfwin;
 
84
        Window subwin;
 
85
        int xOffset;
 
86
        int yOffset;
 
87
        BOOL offsetObtained;
 
88
        int linked;
 
89
        double gstVolume;
 
90
        BOOL gstMuted;
 
91
 
 
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;
 
95
 
 
96
} TSMFGstreamerDecoder;
 
97
 
 
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_?";
 
104
 
 
105
static inline const GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_timestamp)
 
106
{
 
107
        /* 
 
108
         * Convert Microsoft 100ns timestamps to Gstreamer 1ns units.
 
109
         */
 
110
        return (GstClockTime)(ms_timestamp * 100);
 
111
}
 
112
 
 
113
static const char *tsmf_gstreamer_state_name(GstState state)
 
114
{
 
115
        const char *name;
 
116
 
 
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;
 
123
 
 
124
        return name;
 
125
}
 
126
 
 
127
#if 0
 
128
static void *tsmf_gstreamer_eventloop_thread_func(void * arg)
 
129
{
 
130
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) arg;
 
131
        GstBus *bus;
 
132
        GstMessage *message = NULL;
 
133
        GstState old, new, pending;
 
134
        int loop;
 
135
        
 
136
        DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: "); 
 
137
 
 
138
        bus = gst_element_get_bus(mdecoder->pipe);
 
139
        
 
140
        loop = 1;
 
141
        while (loop) 
 
142
        {
 
143
                message = gst_bus_poll (bus, GST_MESSAGE_ANY, -1);
 
144
 
 
145
                if (mdecoder->shutdown)
 
146
                {
 
147
                        loop =0; /* We are done with this stream */
 
148
                }
 
149
                else 
 
150
                {
 
151
                        switch (message->type) 
 
152
                        {
 
153
                        case GST_MESSAGE_EOS:
 
154
                                DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_EOS");
 
155
                                gst_message_unref (message);
 
156
                                break;
 
157
                
 
158
                        case GST_MESSAGE_WARNING:
 
159
                        case GST_MESSAGE_ERROR:
 
160
                        {
 
161
                                DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_ERROR");
 
162
                                /*GError *err;
 
163
                                gchar *debug;
 
164
                                gst_message_parse_error(message, &err, &debug);
 
165
                                g_print("ERROR: %s\nDEBUG:%s\n", err->message, debug);
 
166
                                g_error_free(err);
 
167
                                g_free(debug);
 
168
                                gst_message_unref(message);*/
 
169
                                break;
 
170
                        }
 
171
                        case GST_MESSAGE_STATE_CHANGED:
 
172
                        {
 
173
                                gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC(message));
 
174
        
 
175
                                gst_message_parse_state_changed (message, &old, &new, &pending);
 
176
                                
 
177
                                DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: GST_MESSAGE_STATE_CHANGED %s old %s new %s pending %s", 
 
178
                                                name,
 
179
                                                gst_element_state_get_name(old),
 
180
                                                gst_element_state_get_name(new),
 
181
                                                gst_element_state_get_name(pending));
 
182
        
 
183
                                g_free (name);
 
184
                                gst_message_unref(message);
 
185
        
 
186
                                break;
 
187
                        }
 
188
        
 
189
                        case GST_MESSAGE_REQUEST_STATE:
 
190
                        {
 
191
                                GstState state;
 
192
                                gchar *name = gst_object_get_path_string (GST_MESSAGE_SRC(message));
 
193
                        
 
194
                                gst_message_parse_request_state(message, &state);
 
195
                        
 
196
                                DEBUG_DVC("GST_MESSAGE_REQUEST_STATE: Setting %s state to %s", name, gst_element_state_get_name(state));
 
197
                        
 
198
                                gst_element_set_state (mdecoder->pipe, state);
 
199
                        
 
200
                                g_free (name);
 
201
        
 
202
                                gst_message_unref(message);
 
203
                                break;
 
204
                        }
 
205
                
 
206
                        default:
 
207
                                gst_message_unref(message);
 
208
                                break;
 
209
                        }
 
210
                }
 
211
        }
 
212
 
 
213
        mdecoder->eventloop_thread = 0;
 
214
 
 
215
        DEBUG_DVC("tsmf_gstreamer_eventloop_thread_func: EXITED"); 
 
216
        return 0;
 
217
}
 
218
 
 
219
static int tsmf_gstreamer_start_eventloop_thread(TSMFGstreamerDecoder *mdecoder)
 
220
{
 
221
        pthread_create(&(mdecoder->eventloop_thread), 0, tsmf_gstreamer_eventloop_thread_func, mdecoder);
 
222
        pthread_detach(mdecoder->eventloop_thread);
 
223
 
 
224
        return 0;
 
225
}
 
226
#endif
 
227
 
 
228
static int tsmf_gstreamer_stop_eventloop_thread(TSMFGstreamerDecoder *mdecoder)
 
229
{
 
230
        DEBUG_DVC("tsmf_gstreamer_stop_eventloop_thread: ");
 
231
        if (!mdecoder)
 
232
                return 0;
 
233
 
 
234
        if (mdecoder->eventloop_thread != 0) 
 
235
        {
 
236
                 pthread_cancel(mdecoder->eventloop_thread);
 
237
        }
 
238
 
 
239
        return 0;
 
240
}
 
241
 
 
242
static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder * mdecoder, GstState desired_state)
 
243
{
 
244
        if (!mdecoder)
 
245
                return 0;
 
246
        GstStateChangeReturn state_change;
 
247
        int keep_waiting;
 
248
        int timeout;
 
249
        GstState current_state;
 
250
        GstState pending_state;
 
251
        const char *name;
 
252
        const char *current_name;
 
253
        const char *pending_name;
 
254
 
 
255
        if (!mdecoder->pipe) 
 
256
                return 0;  /* Just in case this is called during startup or shutdown when we don't expect it */
 
257
 
 
258
        if (desired_state == mdecoder->state) 
 
259
                return 0;  /* Redundant request - Nothing to do */
 
260
 
 
261
        name = tsmf_gstreamer_state_name(desired_state); /* For debug */
 
262
 
 
263
        keep_waiting = 1;
 
264
        state_change = gst_element_set_state (mdecoder->pipe, desired_state);
 
265
        timeout = 1000;
 
266
        if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
267
                DEBUG_DVC("tsmf_gstreamer_pipeline_set_state_VIDEO:");
 
268
        else
 
269
                DEBUG_DVC("tsmf_gstreamer_pipeline_set_state_AUDIO:");
 
270
 
 
271
        while (keep_waiting) 
 
272
        {
 
273
                if (state_change == GST_STATE_CHANGE_FAILURE) 
 
274
                {       
 
275
                        DEBUG_WARN("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_FAILURE.", name);
 
276
                        keep_waiting = 0;
 
277
                } 
 
278
                else if (state_change == GST_STATE_CHANGE_SUCCESS)
 
279
                {
 
280
                        DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_SUCCESS.", name);
 
281
                        mdecoder->state = desired_state;
 
282
                        keep_waiting = 0;
 
283
                }
 
284
                else if (state_change == GST_STATE_CHANGE_NO_PREROLL)
 
285
                {
 
286
                        DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_NO_PREROLL.", name);
 
287
                        keep_waiting = 0;
 
288
                }
 
289
                else if (state_change == GST_STATE_CHANGE_ASYNC)
 
290
                {
 
291
                        DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_ASYNC.", name);
 
292
        
 
293
                        state_change = gst_element_get_state(mdecoder->pipe, &current_state, &pending_state, 10 * GST_MSECOND);
 
294
                        current_name = tsmf_gstreamer_state_name(current_state);
 
295
                        pending_name = tsmf_gstreamer_state_name(pending_state);
 
296
 
 
297
                        if (current_state == desired_state)
 
298
                        {
 
299
                                DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) GST_STATE_CHANGE_SUCCESS.", name);
 
300
                                mdecoder->state = desired_state;
 
301
                                keep_waiting = 0;
 
302
                        }
 
303
                        else if (pending_state != desired_state)
 
304
                        {
 
305
                                DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) changing to %s instead.", name, pending_name);
 
306
                                keep_waiting = 0;
 
307
                        }
 
308
                        else 
 
309
                        {
 
310
                                DEBUG_DVC("tsmf_gstreamer_pipeline_set_state(%s) Waiting - current %s pending %s.", name, current_name, pending_name);
 
311
                        }
 
312
                }
 
313
                /*
 
314
                        To avoid RDP session hang. set timeout for changing gstreamer state to 5 seconds.
 
315
                */
 
316
                usleep(10000);
 
317
                timeout--;
 
318
                if (timeout <= 0)
 
319
                {
 
320
                        DEBUG_WARN("tsmf_gstreamer_pipeline_set_state: TIMED OUT - failed to change state");
 
321
                        keep_waiting = 0;
 
322
                        break;
 
323
                }
 
324
        }
 
325
        //sleep(1);
 
326
        return 0;
 
327
}
 
328
 
 
329
static BOOL tsmf_gstreamer_set_format(ITSMFDecoder * decoder, TS_AM_MEDIA_TYPE * media_type)
 
330
{
 
331
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
 
332
        if (!mdecoder)
 
333
                        return FALSE;
 
334
        GstBuffer *gst_buf_cap_codec_data; /* Buffer to hold extra descriptive codec-specific caps data */
 
335
 
 
336
        DEBUG_DVC("tsmf_gstreamer_set_format: ");
 
337
 
 
338
        switch (media_type->MajorType)
 
339
        {
 
340
                case TSMF_MAJOR_TYPE_VIDEO:
 
341
                        mdecoder->media_type = TSMF_MAJOR_TYPE_VIDEO;
 
342
                        mdecoder->tsmf_media_type = *media_type; /* Structure copy */
 
343
                        break;
 
344
                case TSMF_MAJOR_TYPE_AUDIO:
 
345
                        mdecoder->media_type = TSMF_MAJOR_TYPE_AUDIO;
 
346
                        mdecoder->tsmf_media_type = *media_type; /* Structure copy */
 
347
                        break;
 
348
                default:
 
349
                        return FALSE;
 
350
        }
 
351
 
 
352
        switch (media_type->SubType)
 
353
        {
 
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) 
 
357
                        {
 
358
                                memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), 
 
359
                                        media_type->ExtraData, media_type->ExtraDataSize);
 
360
                        }
 
361
                        else
 
362
                        { 
 
363
                                DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", 
 
364
                                        media_type->ExtraDataSize);
 
365
                        } 
 
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,
 
374
                                NULL);
 
375
                        break;
 
376
                case TSMF_SUB_TYPE_MP4S:
 
377
                        if (media_type->ExtraDataSize > 0)
 
378
                        {
 
379
                                gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
 
380
                                if (gst_buf_cap_codec_data != NULL) 
 
381
                                {
 
382
                                        memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
 
383
                                }
 
384
                                else
 
385
                                { 
 
386
                                        DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
 
387
                                } 
 
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,
 
394
                                        NULL);
 
395
                        }
 
396
                        else
 
397
                        {
 
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,
 
403
                                        NULL);
 
404
                        }
 
405
                        break;
 
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,
 
412
                                NULL);
 
413
                        break;
 
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'),
 
420
                                NULL);
 
421
                        break;
 
422
                case TSMF_SUB_TYPE_WMA9:
 
423
                        if (media_type->ExtraDataSize > 0)
 
424
                        {
 
425
                                gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
 
426
                                if (gst_buf_cap_codec_data != NULL) 
 
427
                                {
 
428
                                        memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
 
429
                                }
 
430
                                else
 
431
                                { 
 
432
                                        DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
 
433
                                } 
 
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,
 
443
                                        NULL);
 
444
                        }
 
445
                        else
 
446
                        {
 
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,
 
455
                                        NULL);                  
 
456
                        }
 
457
                        break;
 
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) 
 
461
                        {
 
462
                                memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), 
 
463
                                        media_type->ExtraData, media_type->ExtraDataSize);
 
464
                        }
 
465
                        else
 
466
                        { 
 
467
                                DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", 
 
468
                                        media_type->ExtraDataSize);
 
469
                        } 
 
470
                        
 
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,
 
480
                                NULL);
 
481
                        break;
 
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,
 
490
                                NULL);
 
491
                        break;
 
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'),
 
499
                                NULL);
 
500
                        break;
 
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) 
 
504
                        {
 
505
                                memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), 
 
506
                                        media_type->ExtraData, media_type->ExtraDataSize);
 
507
                        }
 
508
                        else
 
509
                        { 
 
510
                                DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", 
 
511
                                        media_type->ExtraDataSize);
 
512
                        } 
 
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'),
 
519
                                NULL);
 
520
                        break;
 
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) 
 
524
                        {
 
525
                                memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), 
 
526
                                        media_type->ExtraData, media_type->ExtraDataSize);
 
527
                        }
 
528
                        else
 
529
                        { 
 
530
                                DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", 
 
531
                                        media_type->ExtraDataSize);
 
532
                        } 
 
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,
 
541
                                NULL);
 
542
                        break;
 
543
                case TSMF_SUB_TYPE_AVC1:
 
544
                case TSMF_SUB_TYPE_H264:
 
545
                        if (media_type->ExtraDataSize > 0)
 
546
                        {
 
547
                                gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
 
548
                                if (gst_buf_cap_codec_data != NULL) 
 
549
                                {
 
550
                                        memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
 
551
                                }
 
552
                                else
 
553
                                { 
 
554
                                        DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
 
555
                                } 
 
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,
 
561
                                        NULL);
 
562
                        }
 
563
                        else
 
564
                        {
 
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,
 
569
                                        NULL);
 
570
                        }
 
571
                        break;
 
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,
 
576
                                NULL);
 
577
                        break;
 
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)
 
583
                        {
 
584
                                media_type->ExtraData += 12;
 
585
                                media_type->ExtraDataSize -= 12;
 
586
                        }
 
587
                        gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
 
588
                        if (gst_buf_cap_codec_data != NULL) 
 
589
                        {
 
590
                                memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), 
 
591
                                        media_type->ExtraData, media_type->ExtraDataSize);
 
592
                        }
 
593
                        else
 
594
                        { 
 
595
                                DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", 
 
596
                                        media_type->ExtraDataSize);
 
597
                        } 
 
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,
 
603
                                NULL);
 
604
                        break;
 
605
                case TSMF_SUB_TYPE_MP1A:
 
606
                        if (media_type->ExtraDataSize > 0)
 
607
                        {
 
608
                                gst_buf_cap_codec_data = gst_buffer_try_new_and_alloc(media_type->ExtraDataSize);
 
609
                                if (gst_buf_cap_codec_data != NULL) 
 
610
                                {
 
611
                                        memcpy(GST_BUFFER_MALLOCDATA(gst_buf_cap_codec_data), media_type->ExtraData, media_type->ExtraDataSize);
 
612
                                }
 
613
                                else
 
614
                                { 
 
615
                                        DEBUG_WARN("tsmf_gstreamer_set_format: gst_buffer_try_new_and_alloc(%d) failed.", media_type->ExtraDataSize);
 
616
                                } 
 
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,
 
621
                                        NULL);
 
622
                        }
 
623
                        else
 
624
                        {
 
625
                                mdecoder->gst_caps =  gst_caps_new_simple ("audio/mpeg",
 
626
                                        "mpegversion", G_TYPE_INT, 1,
 
627
                                        "channels", G_TYPE_INT, media_type->Channels,
 
628
                                NULL);
 
629
                        }
 
630
                        break;
 
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,
 
637
                                NULL);
 
638
                        break;
 
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,
 
645
                                NULL);
 
646
                        break;
 
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,
 
654
                                NULL);
 
655
                        break;
 
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,
 
661
                                NULL);
 
662
                        break;
 
663
#if 0
 
664
                case TSMF_SUB_TYPE_AC3:
 
665
                        break;
 
666
#endif
 
667
                default:
 
668
                        DEBUG_WARN("tsmf_gstreamer_set_format: unknown format:(%d).", media_type->SubType);
 
669
                        return FALSE;
 
670
        }
 
671
 
 
672
        return TRUE;
 
673
}
 
674
 
 
675
static void tsmf_gstreamer_pipeline_send_end_of_stream(TSMFGstreamerDecoder * mdecoder)
 
676
{
 
677
        DEBUG_DVC("tsmf_gstreamer_pipeline_send_end_of_stream: ");
 
678
 
 
679
        if (mdecoder && mdecoder->src)
 
680
        {
 
681
                gst_app_src_end_of_stream(GST_APP_SRC(mdecoder->src));
 
682
        }
 
683
 
 
684
        return;
 
685
}
 
686
 
 
687
#ifdef __arm__
 
688
/* code from TI to check whether OMX is being lock or not */
 
689
static BOOL tsmf_gstreamer_pipeline_omx_available()
 
690
{
 
691
        BOOL ret = TRUE;
 
692
        int shm_fd = 0;
 
693
        struct shm_info
 
694
        {
 
695
                pid_t pid;
 
696
        }shm_info;
 
697
        struct shm_info *info = NULL;
 
698
 
 
699
        shm_fd = shm_open ("gstomx", (O_CREAT | O_RDWR), (S_IREAD | S_IWRITE));
 
700
        if (shm_fd < 0)
 
701
        {
 
702
                DEBUG_DVC("ERROR: failed to open shm");
 
703
                goto exit;
 
704
        }
 
705
 
 
706
        /* set file size */
 
707
        ftruncate(shm_fd, sizeof(struct shm_info));
 
708
 
 
709
        if ((info = mmap(0, sizeof(struct shm_info), (PROT_READ | PROT_WRITE), MAP_SHARED, shm_fd, 0)) == MAP_FAILED)
 
710
        {
 
711
                DEBUG_DVC("ERROR: failed to map");
 
712
                goto exit;
 
713
        }
 
714
 
 
715
        if (info->pid)
 
716
        {
 
717
                DEBUG_DVC ("ERROR: omxcore is in use by '%d'", info->pid);
 
718
                ret = FALSE;
 
719
        }
 
720
        else
 
721
        {
 
722
                DEBUG_DVC ("omxcore is available for use");
 
723
        }
 
724
 
 
725
 
 
726
        exit:
 
727
        if (info)
 
728
                munmap (info, sizeof(struct shm_info));
 
729
 
 
730
        if (shm_fd)
 
731
                close (shm_fd);
 
732
 
 
733
        return ret;
 
734
}
 
735
#endif
 
736
 
 
737
static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder * mdecoder)
 
738
{
 
739
        //Cleaning up elements
 
740
        if (!mdecoder)
 
741
                return;
 
742
 
 
743
        if (mdecoder->src)
 
744
        {
 
745
                gst_object_unref(mdecoder->src);
 
746
                mdecoder->src = NULL;
 
747
        }
 
748
        if (mdecoder->queue)
 
749
        {
 
750
                gst_object_unref(mdecoder->queue);
 
751
                mdecoder->queue = NULL;
 
752
        }
 
753
        if (mdecoder->decbin)
 
754
        {
 
755
                gst_object_unref(mdecoder->decbin);
 
756
                mdecoder->decbin = NULL;
 
757
        }
 
758
        if(mdecoder->outbin)
 
759
        {
 
760
                gst_object_unref(mdecoder->outbin);
 
761
                mdecoder->outbin = NULL;
 
762
        }
 
763
        if (mdecoder->outconv)
 
764
        {
 
765
                gst_object_unref(mdecoder->outconv);
 
766
                mdecoder->outconv = NULL;
 
767
        }
 
768
        if (mdecoder->outsink)
 
769
        {
 
770
                gst_object_unref(mdecoder->outsink);
 
771
                mdecoder->outsink = NULL;
 
772
        }
 
773
        if (mdecoder->aVolume)
 
774
        {
 
775
                gst_object_unref(mdecoder->aVolume);
 
776
                mdecoder->aVolume = NULL;
 
777
        }
 
778
}
 
779
 
 
780
 
 
781
static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder * mdecoder)
 
782
{
 
783
        if (!mdecoder)
 
784
                return FALSE;
 
785
 
 
786
        GstPad *out_pad;
 
787
        mdecoder->pipe = gst_pipeline_new (NULL);
 
788
        if (!mdecoder->pipe)
 
789
        {
 
790
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to create new pipe");
 
791
                return FALSE;
 
792
        }
 
793
 
 
794
        BOOL OMXavailable = FALSE;
 
795
 
 
796
#ifdef __arm__
 
797
        OMXavailable = tsmf_gstreamer_pipeline_omx_available();
 
798
#endif
 
799
 
 
800
        /*
 
801
         * On Atlas without this printf, we'll see Illegal instruction only with optimization level set to -O2.
 
802
        */
 
803
        const char *blank = ""; 
 
804
        printf("%s", blank);
 
805
 
 
806
        BOOL hwaccelflu = FALSE;
 
807
        BOOL hwaccelomx = FALSE;
 
808
 
 
809
        switch (mdecoder->tsmf_media_type.SubType)
 
810
        {
 
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");
 
816
                        break;
 
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");
 
822
                        break;
 
823
                case TSMF_SUB_TYPE_MP3:
 
824
                        mdecoder->decbin = gst_element_factory_make ("flump3dec", NULL);
 
825
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP3");
 
826
                        break;
 
827
                case TSMF_SUB_TYPE_MP4S:
 
828
                        if (OMXavailable)
 
829
                        {
 
830
                                mdecoder->decbin = gst_element_factory_make ("omx_mpeg4dec", NULL);
 
831
                                if (mdecoder->decbin)
 
832
                                {
 
833
                                        hwaccelomx = TRUE;
 
834
                                }
 
835
                        }
 
836
                        else
 
837
                                mdecoder->decbin = NULL;
 
838
 
 
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");
 
844
                        break;
 
845
                case TSMF_SUB_TYPE_MP42:
 
846
                        mdecoder->decbin = gst_element_factory_make ("ffdec_msmpeg4v2", NULL);
 
847
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP42");
 
848
                        break;
 
849
                case TSMF_SUB_TYPE_MP43:
 
850
                        mdecoder->decbin = gst_element_factory_make ("ffdec_msmpeg4", NULL);
 
851
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP43");
 
852
                        break;
 
853
                case TSMF_SUB_TYPE_MP2V:
 
854
                        if (OMXavailable)
 
855
                        {
 
856
                                mdecoder->decbin = gst_element_factory_make ("omx_mpeg2dec", NULL);
 
857
                                if (mdecoder->decbin)
 
858
                                {
 
859
                                        hwaccelomx = TRUE;
 
860
                                }
 
861
                        }
 
862
                        else
 
863
                                mdecoder->decbin = NULL;
 
864
                        if (!mdecoder->decbin)
 
865
                                mdecoder->decbin = gst_element_factory_make ("ffdec_mpeg2video", NULL);
 
866
 
 
867
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: MPEG2 Video");
 
868
                        break;
 
869
                case TSMF_SUB_TYPE_WMV1:
 
870
                        mdecoder->decbin = gst_element_factory_make ("ffdec_wmv1", NULL);
 
871
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV1");
 
872
                        break;
 
873
                case TSMF_SUB_TYPE_WMV2:
 
874
                        mdecoder->decbin = gst_element_factory_make ("ffdec_wmv2", NULL);
 
875
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: WMV2");
 
876
                        break;
 
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)
 
881
                        {
 
882
                                hwaccelflu = TRUE;
 
883
                        }
 
884
                        else
 
885
                        {
 
886
                                if (OMXavailable)
 
887
                                {
 
888
                                        mdecoder->decbin = gst_element_factory_make ("omx_vc1dec", NULL);
 
889
                                        if (mdecoder->decbin)
 
890
                                                hwaccelomx = TRUE;
 
891
                                }
 
892
                                else
 
893
                                        mdecoder->decbin = NULL;
 
894
                        }
 
895
 
 
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");
 
901
                        break;
 
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)
 
906
                        {
 
907
                                hwaccelflu = TRUE;
 
908
                        }
 
909
                        else
 
910
                        {
 
911
                                if (OMXavailable)
 
912
                                {
 
913
                                        mdecoder->decbin = gst_element_factory_make ("omx_h264dec", NULL);
 
914
                                        if (mdecoder->decbin)
 
915
                                                hwaccelomx = TRUE;
 
916
                                }
 
917
                                else
 
918
                                        mdecoder->decbin = NULL;
 
919
                        }
 
920
                        if (!mdecoder->decbin)
 
921
                                mdecoder->decbin = gst_element_factory_make ("fluh264dec", NULL);
 
922
 
 
923
                        if (!mdecoder->decbin)
 
924
                                mdecoder->decbin = gst_element_factory_make ("ffdec_h264", NULL);
 
925
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: H264");
 
926
                        break;
 
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");
 
931
                        break;
 
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");
 
939
                        break;
 
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");
 
945
                        break;
 
946
                case TSMF_SUB_TYPE_MP1A:
 
947
                        mdecoder->decbin = gst_element_factory_make ("flump3dec", NULL);
 
948
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP1A");
 
949
                        break;
 
950
                case TSMF_SUB_TYPE_MP1V:
 
951
                        mdecoder->decbin = gst_element_factory_make ("ffdec_mpegvideo", NULL);
 
952
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: MP1V");
 
953
                        break;
 
954
                default:
 
955
                        DEBUG_WARN("tsmf_gstreamer_pipeline_build: Unsupported media type %d", mdecoder->tsmf_media_type.SubType);
 
956
                        return FALSE;
 
957
        }
 
958
        if (!mdecoder->decbin)
 
959
        {
 
960
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load decoder plugin");
 
961
                return FALSE;
 
962
        }
 
963
 
 
964
        switch (mdecoder->media_type)
 
965
        {
 
966
                case TSMF_MAJOR_TYPE_VIDEO:
 
967
                {
 
968
                        mdecoder->outbin = gst_bin_new ("videobin");
 
969
                        if (hwaccelflu)
 
970
                        {
 
971
                                mdecoder->outconv = gst_element_factory_make ("queue", "queuetosink"); 
 
972
                                mdecoder->outsink = gst_element_factory_make ("fluvasink", "videosink");
 
973
                        }
 
974
                        else if(hwaccelomx)
 
975
                        {
 
976
                                mdecoder->outconv = gst_element_factory_make ("queue", "queuetosink"); 
 
977
                                mdecoder->outsink = gst_element_factory_make ("gemxvimagesink", "videosink");
 
978
                        }
 
979
                        else
 
980
                        {
 
981
                                mdecoder->outconv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); 
 
982
                                mdecoder->outsink = gst_element_factory_make ("xvimagesink", "videosink");
 
983
                        }
 
984
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: building Video Pipe");
 
985
 
 
986
                        if (mdecoder->xfwin == (int *) -1)
 
987
                                DEBUG_WARN("tsmf_gstreamer_entry: failed to assign pointer to the memory address - shmat()");
 
988
                        else
 
989
                        {
 
990
                                if (!mdecoder->disp)
 
991
                                        mdecoder->disp = XOpenDisplay(NULL);
 
992
 
 
993
                                if (!mdecoder->subwin)
 
994
                                {
 
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);
 
998
                                }
 
999
                        }
 
1000
                        mdecoder->aVolume = 0;
 
1001
                        break;
 
1002
                }
 
1003
                case TSMF_MAJOR_TYPE_AUDIO:
 
1004
                {
 
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)
 
1010
                        {
 
1011
                                g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
 
1012
                                g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
 
1013
                        }
 
1014
                        DEBUG_DVC("tsmf_gstreamer_pipeline_build: building Audio Pipe");
 
1015
                        break;
 
1016
                }
 
1017
                default:
 
1018
                break;
 
1019
        }
 
1020
        if (!mdecoder->outconv)
 
1021
        {
 
1022
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load media converter");
 
1023
                tsmf_gstreamer_clean_up(mdecoder);
 
1024
                return FALSE;
 
1025
        }
 
1026
        if (!mdecoder->outsink)
 
1027
        {
 
1028
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to load xvimagesink plugin");
 
1029
                tsmf_gstreamer_clean_up(mdecoder);
 
1030
                return FALSE;
 
1031
        }
 
1032
 
 
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);
 
1042
 
 
1043
        out_pad = gst_element_get_static_pad(mdecoder->outconv, "sink");
 
1044
 
 
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)
 
1049
        {
 
1050
                gst_bin_add(GST_BIN(mdecoder->outbin), mdecoder->aVolume);
 
1051
                linkResult = gst_element_link_many(mdecoder->outconv, mdecoder->aVolume, mdecoder->outsink, NULL);
 
1052
        }
 
1053
        else
 
1054
        {
 
1055
                linkResult = gst_element_link(mdecoder->outconv, mdecoder->outsink);
 
1056
        }
 
1057
        if (!linkResult)
 
1058
        {
 
1059
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: converter->sink");
 
1060
                tsmf_gstreamer_clean_up(mdecoder);
 
1061
                return FALSE;
 
1062
        }
 
1063
 
 
1064
        gst_element_add_pad(mdecoder->outbin, gst_ghost_pad_new ("sink", out_pad));
 
1065
        gst_object_unref(out_pad);
 
1066
 
 
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);
 
1071
 
 
1072
        linkResult = gst_element_link_many(mdecoder->src, mdecoder->queue, mdecoder->decbin, NULL);
 
1073
        if (!linkResult)
 
1074
        {
 
1075
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: source->decoder");
 
1076
                tsmf_gstreamer_clean_up(mdecoder);
 
1077
                return FALSE;
 
1078
        }
 
1079
 
 
1080
        mdecoder->linked = gst_element_link(mdecoder->decbin, mdecoder->outbin);
 
1081
        if (!mdecoder->linked)
 
1082
        {
 
1083
                DEBUG_WARN("tsmf_gstreamer_pipeline_build: Failed to link these elements: decoder->output_bin");
 
1084
                tsmf_gstreamer_clean_up(mdecoder);
 
1085
                return FALSE;
 
1086
        }
 
1087
        
 
1088
        if (GST_IS_X_OVERLAY (mdecoder->outsink))
 
1089
        {
 
1090
                //gst_x_overlay_set_window_handle (GST_X_OVERLAY (mdecoder->outsink), *mdecoder->xfwin);
 
1091
                if(mdecoder->subwin)
 
1092
                {
 
1093
                        //gdk_threads_enter();
 
1094
                        gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (mdecoder->outsink), mdecoder->subwin);
 
1095
                        //gdk_threads_leave();
 
1096
                }
 
1097
        }
 
1098
 
 
1099
        g_object_set(mdecoder->outsink, "preroll-queue-len", 10, NULL);
 
1100
        return TRUE;
 
1101
}
 
1102
 
 
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)
 
1105
{
 
1106
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder*) decoder;
 
1107
 
 
1108
        if (!mdecoder)
 
1109
        {
 
1110
                return FALSE;
 
1111
        }
 
1112
 
 
1113
        int mutexret = pthread_mutex_lock(&mdecoder->gst_mutex);
 
1114
 
 
1115
        if (mutexret != 0)
 
1116
                return FALSE;
 
1117
 
 
1118
        if (mdecoder->shutdown)
 
1119
        {
 
1120
                pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1121
                return FALSE;
 
1122
        }
 
1123
 
 
1124
        GstBuffer *gst_buf;
 
1125
 
 
1126
        /* 
 
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.
 
1131
         */
 
1132
 
 
1133
        if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
1134
        {
 
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);
 
1137
        }
 
1138
        else
 
1139
        {
 
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);
 
1142
        }
 
1143
 
 
1144
        if (mdecoder->gst_caps == NULL) 
 
1145
        {
 
1146
                DEBUG_WARN("tsmf_gstreamer_decodeEx: tsmf_gstreamer_set_format not called or invalid format.");
 
1147
                pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1148
                return FALSE;
 
1149
        }
 
1150
 
 
1151
        if (mdecoder->pipe == NULL) 
 
1152
        {
 
1153
                if (!tsmf_gstreamer_pipeline_build(mdecoder))
 
1154
                {
 
1155
                        if (mdecoder->pipe)
 
1156
                        {
 
1157
                                tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
 
1158
                                gst_object_unref(mdecoder->pipe);
 
1159
                                mdecoder->pipe = NULL;
 
1160
                        }
 
1161
                        pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1162
                        return FALSE;
 
1163
                }
 
1164
 
 
1165
                //tsmf_gstreamer_start_eventloop_thread(mdecoder);
 
1166
 
 
1167
                tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
 
1168
                mdecoder->pipeline_start_time_valid = 0;
 
1169
        }
 
1170
        else
 
1171
        {
 
1172
                /*
 
1173
                 *  this is to fix gstreamer's seeking forward/backward issue with live stream.
 
1174
                 *  set the seeking tolerance to 1 second.
 
1175
                */
 
1176
                if (start_time > (mdecoder->last_sample_end_time + 10000000) || (end_time + 10000000) < mdecoder->last_sample_end_time)
 
1177
                {
 
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))
 
1184
                        {
 
1185
                                if (mdecoder->pipe)
 
1186
                                {
 
1187
                                        tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
 
1188
                                        gst_object_unref(mdecoder->pipe);
 
1189
                                        mdecoder->pipe = NULL;
 
1190
                                }
 
1191
                                pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1192
                                return FALSE;
 
1193
                        }
 
1194
                        tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
 
1195
                        mdecoder->pipeline_start_time_valid = 0;
 
1196
                        /*
 
1197
                         * This is to fix the discrepancy between audio/video start time during a seek
 
1198
                        */
 
1199
                        FILE *fout = NULL;
 
1200
                        if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
1201
                                fout = fopen("/tmp/tsmf_vseek.info", "wt");
 
1202
                        else
 
1203
                                fout = fopen("/tmp/tsmf_aseek.info", "wt");
 
1204
 
 
1205
                        if (fout)
 
1206
                        {
 
1207
                                fprintf(fout, "%"PRIu64"\n", start_time);
 
1208
                                fclose(fout);
 
1209
                        }
 
1210
 
 
1211
                }
 
1212
        }
 
1213
 
 
1214
        if (!mdecoder->src)
 
1215
        {
 
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.");
 
1218
                return FALSE;
 
1219
        }
 
1220
 
 
1221
        if (GST_STATE(mdecoder->pipe) != GST_STATE_PAUSED && GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
 
1222
        {
 
1223
                tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
 
1224
                if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
1225
                {
 
1226
                        FILE *fout = fopen("/tmp/tsmf_video.ready", "wt");
 
1227
                        if (fout)
 
1228
                                fclose(fout);
 
1229
                        FILE *fin = fopen("/tmp/tsmf_aseek.info", "rt");
 
1230
                        if (fin)
 
1231
                        {
 
1232
                                UINT64 AStartTime = 0;
 
1233
                                fscanf(fin, "%"PRIu64, &AStartTime);
 
1234
                                fclose(fin);
 
1235
                                if (start_time > AStartTime)
 
1236
                                {
 
1237
                                        UINT64 streamDelay = (start_time - AStartTime) / 10;
 
1238
                                        usleep(streamDelay);
 
1239
                                }
 
1240
                                unlink("/tmp/tsmf_aseek.info");
 
1241
                        }
 
1242
                }
 
1243
                else if (mdecoder->media_type == TSMF_MAJOR_TYPE_AUDIO)
 
1244
                {
 
1245
                        int timeout = 0;
 
1246
                        FILE *fin = fopen("/tmp/tsmf_video.ready", "rt");
 
1247
                        while (fin == NULL)
 
1248
                        {
 
1249
                                timeout++;
 
1250
                                usleep(1000);
 
1251
                                //wait up to 1.5 second
 
1252
                                if (timeout >= 1500)
 
1253
                                        break;
 
1254
                                fin = fopen("/tmp/tsmf_video.ready", "rt");
 
1255
                        }
 
1256
                        if (fin)
 
1257
                        {
 
1258
                                fclose(fin);
 
1259
                                unlink("/tmp/tsmf_video.ready");
 
1260
                                fin = NULL;
 
1261
                        }
 
1262
 
 
1263
                        fin = fopen("/tmp/tsmf_vseek.info", "rt");
 
1264
                        if (fin)
 
1265
                        {
 
1266
                                UINT64 VStartTime = 0;
 
1267
                                fscanf(fin, "%"PRIu64, &VStartTime);
 
1268
                                fclose(fin);
 
1269
                                if (start_time > VStartTime)
 
1270
                                {
 
1271
                                        UINT64 streamDelay = (start_time - VStartTime) / 10;
 
1272
                                        usleep(streamDelay);
 
1273
                                }
 
1274
                                unlink("/tmp/tsmf_vseek.info");
 
1275
                        }
 
1276
                }
 
1277
        }
 
1278
 
 
1279
        gst_buf = gst_buffer_try_new_and_alloc(data_size);
 
1280
        if (gst_buf == NULL) 
 
1281
        {
 
1282
                pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1283
                DEBUG_WARN("tsmf_gstreamer_decodeEx: gst_buffer_try_new_and_alloc(%d) failed.", data_size);
 
1284
                return FALSE; 
 
1285
        }
 
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);
 
1290
 
 
1291
        gst_app_src_push_buffer(GST_APP_SRC(mdecoder->src), gst_buf);
 
1292
 
 
1293
        mdecoder->last_sample_end_time = end_time;
 
1294
        
 
1295
        if (!mdecoder->pipeline_start_time_valid) 
 
1296
        {
 
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;
 
1300
        }
 
1301
 
 
1302
        if(GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
 
1303
        {
 
1304
                if (!mdecoder->paused)
 
1305
                {
 
1306
                        if (mdecoder->subwin)
 
1307
                        {
 
1308
                                XMapWindow(mdecoder->disp, mdecoder->subwin);
 
1309
                                XSync(mdecoder->disp, FALSE);
 
1310
                        }
 
1311
                        tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
 
1312
                }
 
1313
        }
 
1314
        pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1315
        return TRUE;
 
1316
}
 
1317
 
 
1318
static void tsmf_gstreamer_change_volume(ITSMFDecoder * decoder, UINT32 newVolume, UINT32 muted)
 
1319
{
 
1320
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
 
1321
        if (!mdecoder)
 
1322
                return;
 
1323
 
 
1324
        if (mdecoder->shutdown)
 
1325
                return;
 
1326
 
 
1327
        if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
1328
                return;
 
1329
 
 
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);
 
1334
 
 
1335
        if (!mdecoder->aVolume)
 
1336
                return;
 
1337
 
 
1338
        if (!G_IS_OBJECT(mdecoder->aVolume))
 
1339
                return;
 
1340
 
 
1341
        g_object_set(mdecoder->aVolume, "mute", mdecoder->gstMuted, NULL);
 
1342
        g_object_set(mdecoder->aVolume, "volume", mdecoder->gstVolume, NULL);
 
1343
}
 
1344
 
 
1345
static void tsmf_gstreamer_control(ITSMFDecoder * decoder, ITSMFControlMsg control_msg, UINT32 *arg)
 
1346
{
 
1347
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
 
1348
        if (!mdecoder)
 
1349
                return;
 
1350
 
 
1351
        if (control_msg == Control_Pause) 
 
1352
        {
 
1353
                DEBUG_DVC("tsmf_gstreamer_control: Control_Pause");
 
1354
                tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
 
1355
                mdecoder->paused = TRUE;
 
1356
 
 
1357
                if (mdecoder->subwin)
 
1358
                {
 
1359
                        XUnmapWindow(mdecoder->disp, mdecoder->subwin);
 
1360
                        XSync(mdecoder->disp, FALSE);
 
1361
                }
 
1362
        }
 
1363
        else if (control_msg == Control_Restart) 
 
1364
        {
 
1365
                DEBUG_DVC("tsmf_gstreamer_control: Control_Restart");
 
1366
                mdecoder->paused = FALSE;
 
1367
                if (mdecoder->subwin)
 
1368
                {
 
1369
                        XMapWindow(mdecoder->disp, mdecoder->subwin);
 
1370
                        XSync(mdecoder->disp, FALSE);
 
1371
                }
 
1372
                if (mdecoder->pipeline_start_time_valid)
 
1373
                        tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
 
1374
        }
 
1375
        else if (control_msg == Control_Flush) 
 
1376
        {
 
1377
                DEBUG_DVC("tsmf_gstreamer_control: Control_Flush");
 
1378
                /* Reset stamps, flush buffers, etc */
 
1379
                if (mdecoder->pipe) 
 
1380
                {
 
1381
                        tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
 
1382
                        gst_object_unref(mdecoder->pipe);
 
1383
                        mdecoder->pipe = NULL;
 
1384
                }
 
1385
                mdecoder->pipeline_start_time_valid = 0;
 
1386
                mdecoder->paused = FALSE;
 
1387
                
 
1388
                if (mdecoder->subwin)
 
1389
                {
 
1390
                        XUnmapWindow(mdecoder->disp, mdecoder->subwin);
 
1391
                        XSync(mdecoder->disp, FALSE);
 
1392
                }
 
1393
        }
 
1394
        else if (control_msg == Control_EndOfStream) 
 
1395
        {
 
1396
                mdecoder->paused = FALSE;
 
1397
                DEBUG_DVC("tsmf_gstreamer_control: Control_EndOfStream");
 
1398
                /* 
 
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
 
1405
                 *       is truly EOS.
 
1406
                 *       (It's unlikely we can simply "wait" here for it to happen
 
1407
                 *       since we don't want to hold up acks, etc.)
 
1408
                 */ 
 
1409
                tsmf_gstreamer_pipeline_send_end_of_stream(mdecoder);
 
1410
        }
 
1411
}
 
1412
 
 
1413
static guint tsmf_gstreamer_buffer_level(ITSMFDecoder * decoder)
 
1414
{
 
1415
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
 
1416
        DEBUG_DVC("tsmf_gstreamer_buffer_level\n");
 
1417
 
 
1418
        if (!mdecoder)
 
1419
                return 0;
 
1420
 
 
1421
        if (mdecoder->shutdown)
 
1422
                return 0;
 
1423
 
 
1424
        if (!G_IS_OBJECT(mdecoder->queue))
 
1425
                return 0;
 
1426
 
 
1427
        guint clbuff = 0;
 
1428
        g_object_get(mdecoder->queue, "current-level-buffers", &clbuff, NULL);
 
1429
        return clbuff;
 
1430
}
 
1431
 
 
1432
static void tsmf_gstreamer_free(ITSMFDecoder * decoder)
 
1433
{
 
1434
        TSMFGstreamerDecoder * mdecoder = (TSMFGstreamerDecoder *) decoder;
 
1435
        DEBUG_DVC("tsmf_gstreamer_free\n");
 
1436
 
 
1437
        if (mdecoder)
 
1438
        {
 
1439
                pthread_mutex_lock(&mdecoder->gst_mutex);
 
1440
                mdecoder->shutdown = 1;
 
1441
                if (mdecoder->pipe)
 
1442
                {
 
1443
                        tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
 
1444
                        gst_object_unref(mdecoder->pipe);
 
1445
                        mdecoder->pipe = NULL;
 
1446
                }
 
1447
                tsmf_gstreamer_stop_eventloop_thread(mdecoder);
 
1448
                if (mdecoder->gst_caps)
 
1449
                        gst_caps_unref(mdecoder->gst_caps);
 
1450
 
 
1451
                if (mdecoder->subwin)
 
1452
                {
 
1453
                        DEBUG_DVC("destroy subwindow\n");
 
1454
                        XDestroyWindow(mdecoder->disp, mdecoder->subwin);
 
1455
                        XSync(mdecoder->disp, FALSE);
 
1456
                }
 
1457
                
 
1458
                if (mdecoder->disp)
 
1459
                        XCloseDisplay(mdecoder->disp);
 
1460
 
 
1461
                unlink("/tmp/tsmf_aseek.info");
 
1462
                unlink("/tmp/tsmf_vseek.info");
 
1463
                unlink("/tmp/tsmf_video.ready");
 
1464
 
 
1465
                pthread_mutex_unlock(&mdecoder->gst_mutex);
 
1466
                free(mdecoder);
 
1467
                mdecoder = 0;
 
1468
        }
 
1469
}
 
1470
 
 
1471
static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder * decoder)
 
1472
{
 
1473
        TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
 
1474
        if (!mdecoder)
 
1475
                return 0;
 
1476
        if (!mdecoder->outsink)
 
1477
                return mdecoder->last_sample_end_time;
 
1478
 
 
1479
        if(GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING)
 
1480
                return 0;
 
1481
 
 
1482
        GstFormat fmt = GST_FORMAT_TIME;
 
1483
        gint64 pos = 0;
 
1484
        gst_element_query_position (mdecoder->outsink, &fmt, &pos);
 
1485
        DEBUG_DVC("tsmf_gstreamer_current_pos=[%"PRIu64"]", pos);
 
1486
        return pos/100;
 
1487
}
 
1488
 
 
1489
static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder * decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles)
 
1490
{
 
1491
        DEBUG_DVC("tsmf_gstreamer_update_rendering_area");
 
1492
        TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
 
1493
        if (!mdecoder)
 
1494
                return;
 
1495
 
 
1496
        if (mdecoder->shutdown)
 
1497
                return;
 
1498
 
 
1499
        if (GST_IS_X_OVERLAY (mdecoder->outsink))
 
1500
        {
 
1501
                if (!mdecoder->disp)
 
1502
                        mdecoder->disp = XOpenDisplay(NULL);
 
1503
 
 
1504
                //multi-mon test
 
1505
                int anewX = newX;
 
1506
                int anewY = newY;
 
1507
                if (!mdecoder->offsetObtained)
 
1508
                {
 
1509
                        XSync(mdecoder->disp, FALSE);
 
1510
                        RROutput primary_output;
 
1511
                        XRRScreenResources *res = 0;
 
1512
                        int screen = 0;
 
1513
                        res = XRRGetScreenResourcesCurrent(mdecoder->disp, RootWindow(mdecoder->disp, screen));
 
1514
                        if (res)
 
1515
                        {
 
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);
 
1519
                                int i = 0;
 
1520
                                for (i = 0; i < res->ncrtc; i++)
 
1521
                                {
 
1522
                                        XRRCrtcInfo *info = XRRGetCrtcInfo(mdecoder->disp, res, res->crtcs[i]);
 
1523
                                        if (info)
 
1524
                                        {
 
1525
                                                if (info->noutput > 0)
 
1526
                                                {
 
1527
                                                        if (info->outputs[0] == primary_output || i == 0)
 
1528
                                                        {
 
1529
                                                                mdecoder->xOffset = info->x;
 
1530
                                                                mdecoder->yOffset = info->y;
 
1531
                                                        }
 
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));
 
1533
                                                }
 
1534
                                                XRRFreeCrtcInfo(info);
 
1535
                                        }
 
1536
                                }
 
1537
                        }
 
1538
                        mdecoder->offsetObtained = TRUE;
 
1539
                }
 
1540
                anewX += mdecoder->xOffset;
 
1541
                anewY += mdecoder->yOffset;
 
1542
                
 
1543
                XSync(mdecoder->disp, FALSE);
 
1544
                //end of multi-mon test
 
1545
 
 
1546
                if(mdecoder->subwin)
 
1547
                {
 
1548
                        XMoveWindow(mdecoder->disp, mdecoder->subwin, anewX, anewY);
 
1549
                        if(newWidth > 0 && newHeight > 0) {
 
1550
                                XResizeWindow(mdecoder->disp, mdecoder->subwin, newWidth, newHeight);
 
1551
                        } else {
 
1552
                                XResizeWindow(mdecoder->disp, mdecoder->subwin, 1, 1);
 
1553
                        }
 
1554
 
 
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.
 
1559
                        XExposeEvent xpose;
 
1560
                        xpose.type = Expose;
 
1561
                        xpose.display = mdecoder->disp;
 
1562
                        xpose.window = *mdecoder->xfwin;
 
1563
                        xpose.x = 0;
 
1564
                        xpose.y = 0;
 
1565
                        XSendEvent(mdecoder->disp, *mdecoder->xfwin, TRUE, ExposureMask, (XEvent *)&xpose);
 
1566
                        XSync(mdecoder->disp, FALSE);
 
1567
                }
 
1568
                gst_x_overlay_expose (GST_X_OVERLAY (mdecoder->outsink));
 
1569
        }
 
1570
}
 
1571
 
 
1572
static int initialized = 0;
 
1573
 
 
1574
#ifdef STATIC_CHANNELS
 
1575
#define freerdp_tsmf_client_decoder_subsystem_entry     gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
 
1576
#endif
 
1577
 
 
1578
ITSMFDecoder* freerdp_tsmf_client_decoder_subsystem_entry(void)
 
1579
{
 
1580
        TSMFGstreamerDecoder* decoder;
 
1581
 
 
1582
        if (!initialized)
 
1583
        {
 
1584
                gst_init(0, 0);
 
1585
                initialized = 1;
 
1586
        }
 
1587
 
 
1588
        decoder = malloc(sizeof(TSMFGstreamerDecoder));
 
1589
        memset(decoder, 0, sizeof(TSMFGstreamerDecoder));
 
1590
 
 
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);
 
1612
 
 
1613
        int shmid = shmget(SHARED_MEM_KEY, sizeof(int), 0666);
 
1614
        if (shmid < 0)
 
1615
        {
 
1616
                DEBUG_WARN("tsmf_gstreamer_entry: failed to get access to shared memory - shmget()");
 
1617
        }
 
1618
        else
 
1619
        {
 
1620
                decoder->xfwin = shmat(shmid, NULL, 0);
 
1621
        }
 
1622
 
 
1623
        XInitThreads();
 
1624
 
 
1625
        return (ITSMFDecoder *) decoder;
 
1626
}