22#include <freerdp/config.h> 
   24#include <winpr/assert.h> 
   32#include <winpr/string.h> 
   33#include <winpr/platform.h> 
   37#include <gst/app/gstappsrc.h> 
   38#include <gst/app/gstappsink.h> 
   40#include "tsmf_constants.h" 
   41#include "tsmf_decoder.h" 
   42#include "tsmf_platform.h" 
   45#define SEEK_TOLERANCE 10 * 1000 * 1000 
   50                                             GstState desired_state);
 
   51static BOOL tsmf_gstreamer_buffer_level(ITSMFDecoder* decoder);
 
   58  switch (mdecoder->media_type)
 
   60    case TSMF_MAJOR_TYPE_VIDEO:
 
   62    case TSMF_MAJOR_TYPE_AUDIO:
 
   69static void cb_child_added(GstChildProxy* child_proxy, GObject* 
object,
 
   72  DEBUG_TSMF(
"NAME: %s", G_OBJECT_TYPE_NAME(
object));
 
   74  if (!g_strcmp0(G_OBJECT_TYPE_NAME(
object), 
"GstXvImageSink") ||
 
   75      !g_strcmp0(G_OBJECT_TYPE_NAME(
object), 
"GstXImageSink") ||
 
   76      !g_strcmp0(G_OBJECT_TYPE_NAME(
object), 
"GstFluVAAutoSink"))
 
   78    gst_base_sink_set_max_lateness((GstBaseSink*)
object, 10000000); 
 
   79    g_object_set(G_OBJECT(
object), 
"sync", TRUE, NULL);  
 
   80    g_object_set(G_OBJECT(
object), 
"async", TRUE, NULL); 
 
   83  else if (!g_strcmp0(G_OBJECT_TYPE_NAME(
object), 
"GstAlsaSink") ||
 
   84           !g_strcmp0(G_OBJECT_TYPE_NAME(
object), 
"GstPulseSink"))
 
   86    gst_base_sink_set_max_lateness((GstBaseSink*)
object, 10000000); 
 
   87    g_object_set(G_OBJECT(
object), 
"slave-method", 1, NULL);
 
   88    g_object_set(G_OBJECT(
object), 
"buffer-time", (gint64)20000, NULL);     
 
   89    g_object_set(G_OBJECT(
object), 
"drift-tolerance", (gint64)20000, NULL); 
 
   90    g_object_set(G_OBJECT(
object), 
"latency-time", (gint64)10000, NULL);    
 
   91    g_object_set(G_OBJECT(
object), 
"sync", TRUE, NULL);  
 
   92    g_object_set(G_OBJECT(
object), 
"async", TRUE, NULL); 
 
   96static void tsmf_gstreamer_enough_data(GstAppSrc* src, gpointer user_data)
 
  100  DEBUG_TSMF(
"%s", get_type(mdecoder));
 
  103static void tsmf_gstreamer_need_data(GstAppSrc* src, guint length, gpointer user_data)
 
  107  DEBUG_TSMF(
"%s length=%u", get_type(mdecoder), length);
 
  110static gboolean tsmf_gstreamer_seek_data(GstAppSrc* src, guint64 offset, gpointer user_data)
 
  114  DEBUG_TSMF(
"%s offset=%" PRIu64 
"", get_type(mdecoder), offset);
 
  119static BOOL tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume, UINT32 muted)
 
  123  if (!mdecoder || !mdecoder->pipe)
 
  126  if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  129  mdecoder->gstMuted = (BOOL)muted;
 
  130  DEBUG_TSMF(
"mute=[%" PRId32 
"]", mdecoder->gstMuted);
 
  131  mdecoder->gstVolume = (double)newVolume / (
double)10000;
 
  132  DEBUG_TSMF(
"gst_new_vol=[%f]", mdecoder->gstVolume);
 
  134  if (!mdecoder->volume)
 
  137  if (!G_IS_OBJECT(mdecoder->volume))
 
  140  g_object_set(mdecoder->volume, 
"mute", mdecoder->gstMuted, NULL);
 
  141  g_object_set(mdecoder->volume, 
"volume", mdecoder->gstVolume, NULL);
 
  146static inline GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_timestamp)
 
  151  return (GstClockTime)(ms_timestamp * 100);
 
  156  GstStateChangeReturn state_change;
 
  158  const char* sname = get_type(mdecoder);
 
  167  if (desired_state == mdecoder->state)
 
  170  name = gst_element_state_get_name(desired_state); 
 
  171  DEBUG_TSMF(
"%s to %s", sname, name);
 
  172  state_change = gst_element_set_state(mdecoder->pipe, desired_state);
 
  174  if (state_change == GST_STATE_CHANGE_FAILURE)
 
  176    WLog_ERR(TAG, 
"%s: (%s) GST_STATE_CHANGE_FAILURE.", sname, name);
 
  178  else if (state_change == GST_STATE_CHANGE_ASYNC)
 
  180    WLog_ERR(TAG, 
"%s: (%s) GST_STATE_CHANGE_ASYNC.", sname, name);
 
  181    mdecoder->state = desired_state;
 
  185    mdecoder->state = desired_state;
 
  191static GstBuffer* tsmf_get_buffer_from_data(
const void* raw_data, gsize size)
 
  202  data = g_malloc(size);
 
  206    WLog_ERR(TAG, 
"Could not allocate %" G_GSIZE_FORMAT 
" bytes of data.", size);
 
  210  CopyMemory(data, raw_data, size);
 
  212#if GST_VERSION_MAJOR > 0 
  213  buffer = gst_buffer_new_wrapped(data, size);
 
  215  buffer = gst_buffer_new();
 
  219    WLog_ERR(TAG, 
"Could not create GstBuffer");
 
  224  GST_BUFFER_MALLOCDATA(buffer) = data;
 
  225  GST_BUFFER_SIZE(buffer) = size;
 
  226  GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);
 
  232static BOOL tsmf_gstreamer_set_format(ITSMFDecoder* decoder, 
TS_AM_MEDIA_TYPE* media_type)
 
  241  switch (media_type->MajorType)
 
  243    case TSMF_MAJOR_TYPE_VIDEO:
 
  244      mdecoder->media_type = TSMF_MAJOR_TYPE_VIDEO;
 
  246    case TSMF_MAJOR_TYPE_AUDIO:
 
  247      mdecoder->media_type = TSMF_MAJOR_TYPE_AUDIO;
 
  253  switch (media_type->SubType)
 
  255    case TSMF_SUB_TYPE_WVC1:
 
  256      mdecoder->gst_caps = gst_caps_new_simple(
 
  257          "video/x-wmv", 
"bitrate", G_TYPE_UINT, media_type->BitRate, 
"width", G_TYPE_INT,
 
  258          media_type->Width, 
"height", G_TYPE_INT, media_type->Height, 
"wmvversion",
 
  260#
if GST_VERSION_MAJOR > 0
 
  261          "format", G_TYPE_STRING, 
"WVC1",
 
  263          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'W', 
'V', 
'C', 
'1'),
 
  265          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  266          media_type->SamplesPerSecond.Denominator, 
"pixel-aspect-ratio", GST_TYPE_FRACTION,
 
  269    case TSMF_SUB_TYPE_MP4S:
 
  270      mdecoder->gst_caps = gst_caps_new_simple(
 
  271          "video/x-divx", 
"divxversion", G_TYPE_INT, 5, 
"bitrate", G_TYPE_UINT,
 
  272          media_type->BitRate, 
"width", G_TYPE_INT, media_type->Width, 
"height", G_TYPE_INT,
 
  274#
if GST_VERSION_MAJOR > 0
 
  275          "format", G_TYPE_STRING, 
"MP42",
 
  277          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'M', 
'P', 
'4', 
'2'),
 
  279          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  280          media_type->SamplesPerSecond.Denominator, NULL);
 
  282    case TSMF_SUB_TYPE_MP42:
 
  283      mdecoder->gst_caps = gst_caps_new_simple(
 
  284          "video/x-msmpeg", 
"msmpegversion", G_TYPE_INT, 42, 
"bitrate", G_TYPE_UINT,
 
  285          media_type->BitRate, 
"width", G_TYPE_INT, media_type->Width, 
"height", G_TYPE_INT,
 
  287#
if GST_VERSION_MAJOR > 0
 
  288          "format", G_TYPE_STRING, 
"MP42",
 
  290          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'M', 
'P', 
'4', 
'2'),
 
  292          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  293          media_type->SamplesPerSecond.Denominator, NULL);
 
  295    case TSMF_SUB_TYPE_MP43:
 
  296      mdecoder->gst_caps = gst_caps_new_simple(
 
  297          "video/x-msmpeg", 
"msmpegversion", G_TYPE_INT, 43, 
"bitrate", G_TYPE_UINT,
 
  298          media_type->BitRate, 
"width", G_TYPE_INT, media_type->Width, 
"height", G_TYPE_INT,
 
  300#
if GST_VERSION_MAJOR > 0
 
  301          "format", G_TYPE_STRING, 
"MP43",
 
  303          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'M', 
'P', 
'4', 
'3'),
 
  305          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  306          media_type->SamplesPerSecond.Denominator, NULL);
 
  308    case TSMF_SUB_TYPE_M4S2:
 
  309      mdecoder->gst_caps = gst_caps_new_simple(
 
  310          "video/mpeg", 
"mpegversion", G_TYPE_INT, 4, 
"width", G_TYPE_INT, media_type->Width,
 
  311          "height", G_TYPE_INT, media_type->Height,
 
  312#
if GST_VERSION_MAJOR > 0
 
  313          "format", G_TYPE_STRING, 
"M4S2",
 
  315          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'M', 
'4', 
'S', 
'2'),
 
  317          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  318          media_type->SamplesPerSecond.Denominator, NULL);
 
  320    case TSMF_SUB_TYPE_WMA9:
 
  321      mdecoder->gst_caps = gst_caps_new_simple(
 
  322          "audio/x-wma", 
"wmaversion", G_TYPE_INT, 3, 
"rate", G_TYPE_INT,
 
  323          media_type->SamplesPerSecond.Numerator, 
"channels", G_TYPE_INT,
 
  324          media_type->Channels, 
"bitrate", G_TYPE_INT, media_type->BitRate, 
"depth",
 
  325          G_TYPE_INT, media_type->BitsPerSample, 
"width", G_TYPE_INT,
 
  326          media_type->BitsPerSample, 
"block_align", G_TYPE_INT, media_type->BlockAlign, NULL);
 
  328    case TSMF_SUB_TYPE_WMA1:
 
  329      mdecoder->gst_caps = gst_caps_new_simple(
 
  330          "audio/x-wma", 
"wmaversion", G_TYPE_INT, 1, 
"rate", G_TYPE_INT,
 
  331          media_type->SamplesPerSecond.Numerator, 
"channels", G_TYPE_INT,
 
  332          media_type->Channels, 
"bitrate", G_TYPE_INT, media_type->BitRate, 
"depth",
 
  333          G_TYPE_INT, media_type->BitsPerSample, 
"width", G_TYPE_INT,
 
  334          media_type->BitsPerSample, 
"block_align", G_TYPE_INT, media_type->BlockAlign, NULL);
 
  336    case TSMF_SUB_TYPE_WMA2:
 
  337      mdecoder->gst_caps = gst_caps_new_simple(
 
  338          "audio/x-wma", 
"wmaversion", G_TYPE_INT, 2, 
"rate", G_TYPE_INT,
 
  339          media_type->SamplesPerSecond.Numerator, 
"channels", G_TYPE_INT,
 
  340          media_type->Channels, 
"bitrate", G_TYPE_INT, media_type->BitRate, 
"depth",
 
  341          G_TYPE_INT, media_type->BitsPerSample, 
"width", G_TYPE_INT,
 
  342          media_type->BitsPerSample, 
"block_align", G_TYPE_INT, media_type->BlockAlign, NULL);
 
  344    case TSMF_SUB_TYPE_MP3:
 
  346          gst_caps_new_simple(
"audio/mpeg", 
"mpegversion", G_TYPE_INT, 1, 
"layer", G_TYPE_INT,
 
  347                              3, 
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
 
  348                              "channels", G_TYPE_INT, media_type->Channels, NULL);
 
  350    case TSMF_SUB_TYPE_WMV1:
 
  351      mdecoder->gst_caps = gst_caps_new_simple(
 
  352          "video/x-wmv", 
"bitrate", G_TYPE_UINT, media_type->BitRate, 
"width", G_TYPE_INT,
 
  353          media_type->Width, 
"height", G_TYPE_INT, media_type->Height, 
"wmvversion",
 
  355#
if GST_VERSION_MAJOR > 0
 
  356          "format", G_TYPE_STRING, 
"WMV1",
 
  358          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'W', 
'M', 
'V', 
'1'),
 
  360          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  361          media_type->SamplesPerSecond.Denominator, NULL);
 
  363    case TSMF_SUB_TYPE_WMV2:
 
  364      mdecoder->gst_caps = gst_caps_new_simple(
 
  365          "video/x-wmv", 
"width", G_TYPE_INT, media_type->Width, 
"height", G_TYPE_INT,
 
  366          media_type->Height, 
"wmvversion", G_TYPE_INT, 2,
 
  367#
if GST_VERSION_MAJOR > 0
 
  368          "format", G_TYPE_STRING, 
"WMV2",
 
  370          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'W', 
'M', 
'V', 
'2'),
 
  372          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  373          media_type->SamplesPerSecond.Denominator, 
"pixel-aspect-ratio", GST_TYPE_FRACTION,
 
  376    case TSMF_SUB_TYPE_WMV3:
 
  377      mdecoder->gst_caps = gst_caps_new_simple(
 
  378          "video/x-wmv", 
"bitrate", G_TYPE_UINT, media_type->BitRate, 
"width", G_TYPE_INT,
 
  379          media_type->Width, 
"height", G_TYPE_INT, media_type->Height, 
"wmvversion",
 
  381#
if GST_VERSION_MAJOR > 0
 
  382          "format", G_TYPE_STRING, 
"WMV3",
 
  384          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC(
'W', 
'M', 
'V', 
'3'),
 
  386          "framerate", GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  387          media_type->SamplesPerSecond.Denominator, 
"pixel-aspect-ratio", GST_TYPE_FRACTION,
 
  390    case TSMF_SUB_TYPE_AVC1:
 
  391    case TSMF_SUB_TYPE_H264:
 
  392      mdecoder->gst_caps = gst_caps_new_simple(
 
  393          "video/x-h264", 
"width", G_TYPE_INT, media_type->Width, 
"height", G_TYPE_INT,
 
  394          media_type->Height, 
"framerate", GST_TYPE_FRACTION,
 
  395          media_type->SamplesPerSecond.Numerator, media_type->SamplesPerSecond.Denominator,
 
  396          "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, 
"stream-format", G_TYPE_STRING,
 
  397          "byte-stream", 
"alignment", G_TYPE_STRING, 
"nal", NULL);
 
  399    case TSMF_SUB_TYPE_AC3:
 
  400      mdecoder->gst_caps = gst_caps_new_simple(
 
  401          "audio/x-ac3", 
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
 
  402          "channels", G_TYPE_INT, media_type->Channels, NULL);
 
  404    case TSMF_SUB_TYPE_AAC:
 
  409      if (media_type->ExtraData)
 
  411        if (media_type->ExtraDataSize < 12)
 
  413        media_type->ExtraData += 12;
 
  414        media_type->ExtraDataSize -= 12;
 
  417      mdecoder->gst_caps = gst_caps_new_simple(
 
  418          "audio/mpeg", 
"rate", G_TYPE_INT, media_type->SamplesPerSecond.Numerator,
 
  419          "channels", G_TYPE_INT, media_type->Channels, 
"mpegversion", G_TYPE_INT, 4,
 
  420          "framed", G_TYPE_BOOLEAN, TRUE, 
"stream-format", G_TYPE_STRING, 
"raw", NULL);
 
  422    case TSMF_SUB_TYPE_MP1A:
 
  424          gst_caps_new_simple(
"audio/mpeg", 
"mpegversion", G_TYPE_INT, 1, 
"channels",
 
  425                              G_TYPE_INT, media_type->Channels, NULL);
 
  427    case TSMF_SUB_TYPE_MP1V:
 
  429          gst_caps_new_simple(
"video/mpeg", 
"mpegversion", G_TYPE_INT, 1, 
"width", G_TYPE_INT,
 
  430                              media_type->Width, 
"height", G_TYPE_INT, media_type->Height,
 
  431                              "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
 
  433    case TSMF_SUB_TYPE_YUY2:
 
  434#if GST_VERSION_MAJOR > 0 
  435      mdecoder->gst_caps = gst_caps_new_simple(
 
  436          "video/x-raw", 
"format", G_TYPE_STRING, 
"YUY2", 
"width", G_TYPE_INT,
 
  437          media_type->Width, 
"height", G_TYPE_INT, media_type->Height, NULL);
 
  439      mdecoder->gst_caps = gst_caps_new_simple(
 
  440          "video/x-raw-yuv", 
"format", G_TYPE_STRING, 
"YUY2", 
"width", G_TYPE_INT,
 
  441          media_type->Width, 
"height", G_TYPE_INT, media_type->Height, 
"framerate",
 
  442          GST_TYPE_FRACTION, media_type->SamplesPerSecond.Numerator,
 
  443          media_type->SamplesPerSecond.Denominator, NULL);
 
  446    case TSMF_SUB_TYPE_MP2V:
 
  447      mdecoder->gst_caps = gst_caps_new_simple(
"video/mpeg", 
"mpegversion", G_TYPE_INT, 2,
 
  448                                               "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
 
  450    case TSMF_SUB_TYPE_MP2A:
 
  452          gst_caps_new_simple(
"audio/mpeg", 
"mpegversion", G_TYPE_INT, 1, 
"rate", G_TYPE_INT,
 
  453                              media_type->SamplesPerSecond.Numerator, 
"channels", G_TYPE_INT,
 
  454                              media_type->Channels, NULL);
 
  456    case TSMF_SUB_TYPE_FLAC:
 
  457      mdecoder->gst_caps = gst_caps_new_simple(
"audio/x-flac", 
"", NULL);
 
  460      WLog_ERR(TAG, 
"unknown format:(%d).", media_type->SubType);
 
  464  if (media_type->ExtraDataSize > 0)
 
  467    DEBUG_TSMF(
"Extra data available (%" PRIu32 
")", media_type->ExtraDataSize);
 
  468    buffer = tsmf_get_buffer_from_data(media_type->ExtraData, media_type->ExtraDataSize);
 
  472      WLog_ERR(TAG, 
"could not allocate GstBuffer!");
 
  476    gst_caps_set_simple(mdecoder->gst_caps, 
"codec_data", GST_TYPE_BUFFER, buffer, NULL);
 
  479  DEBUG_TSMF(
"%p format '%s'", (
void*)mdecoder, gst_caps_to_string(mdecoder->gst_caps));
 
  480  tsmf_platform_set_format(mdecoder);
 
  483  if (!tsmf_gstreamer_pipeline_build(mdecoder))
 
  491  if (!mdecoder || !mdecoder->pipe)
 
  494  if (mdecoder->pipe && GST_OBJECT_REFCOUNT_VALUE(mdecoder->pipe) > 0)
 
  496    tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
 
  497    gst_object_unref(mdecoder->pipe);
 
  500  mdecoder->ready = FALSE;
 
  501  mdecoder->paused = FALSE;
 
  503  mdecoder->pipe = NULL;
 
  504  mdecoder->src = NULL;
 
  505  mdecoder->queue = NULL;
 
  510#if GST_VERSION_MAJOR > 0 
  512      "appsrc name=videosource ! queue2 name=videoqueue ! decodebin name=videodecoder !";
 
  514      "appsrc name=audiosource ! queue2 name=audioqueue ! decodebin name=audiodecoder ! " 
  515      "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !";
 
  518      "appsrc name=videosource ! queue2 name=videoqueue ! decodebin2 name=videodecoder !";
 
  520      "appsrc name=audiosource ! queue2 name=audioqueue ! decodebin2 name=audiodecoder ! " 
  521      "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !";
 
  531  if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  532    sprintf_s(pipeline, 
sizeof(pipeline), 
"%s %s name=videosink", video,
 
  533              tsmf_platform_get_video_sink());
 
  535    sprintf_s(pipeline, 
sizeof(pipeline), 
"%s %s name=audiosink", audio,
 
  536              tsmf_platform_get_audio_sink());
 
  538  DEBUG_TSMF(
"pipeline=%s", pipeline);
 
  539  mdecoder->pipe = gst_parse_launch(pipeline, NULL);
 
  543    WLog_ERR(TAG, 
"Failed to create new pipe");
 
  547  if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  548    mdecoder->src = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"videosource");
 
  550    mdecoder->src = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"audiosource");
 
  554    WLog_ERR(TAG, 
"Failed to get appsrc");
 
  558  if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  559    mdecoder->queue = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"videoqueue");
 
  561    mdecoder->queue = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"audioqueue");
 
  563  if (!mdecoder->queue)
 
  565    WLog_ERR(TAG, 
"Failed to get queue");
 
  569  if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  570    mdecoder->outsink = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"videosink");
 
  572    mdecoder->outsink = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"audiosink");
 
  574  if (!mdecoder->outsink)
 
  576    WLog_ERR(TAG, 
"Failed to get sink");
 
  580  g_signal_connect(mdecoder->outsink, 
"child-added", G_CALLBACK(cb_child_added), mdecoder);
 
  582  if (mdecoder->media_type == TSMF_MAJOR_TYPE_AUDIO)
 
  584    mdecoder->volume = gst_bin_get_by_name(GST_BIN(mdecoder->pipe), 
"audiovolume");
 
  586    if (!mdecoder->volume)
 
  588      WLog_ERR(TAG, 
"Failed to get volume");
 
  592    tsmf_gstreamer_change_volume((ITSMFDecoder*)mdecoder, mdecoder->gstVolume * ((
double)10000),
 
  596  tsmf_platform_register_handler(mdecoder);
 
  598  GstAppSrcCallbacks callbacks = {
 
  599    tsmf_gstreamer_need_data, tsmf_gstreamer_enough_data, tsmf_gstreamer_seek_data, { NULL }
 
  601  g_object_set(mdecoder->src, 
"format", GST_FORMAT_TIME, NULL);
 
  602  g_object_set(mdecoder->src, 
"is-live", FALSE, NULL);
 
  603  g_object_set(mdecoder->src, 
"block", FALSE, NULL);
 
  604  g_object_set(mdecoder->src, 
"blocksize", 1024, NULL);
 
  605  gst_app_src_set_caps((GstAppSrc*)mdecoder->src, mdecoder->gst_caps);
 
  606  gst_app_src_set_callbacks((GstAppSrc*)mdecoder->src, &callbacks, mdecoder, NULL);
 
  607  gst_app_src_set_stream_type((GstAppSrc*)mdecoder->src, GST_APP_STREAM_TYPE_SEEKABLE);
 
  608  gst_app_src_set_latency((GstAppSrc*)mdecoder->src, 0, -1);
 
  609  gst_app_src_set_max_bytes((GstAppSrc*)mdecoder->src, (guint64)0); 
 
  610  g_object_set(G_OBJECT(mdecoder->queue), 
"use-buffering", FALSE, NULL);
 
  611  g_object_set(G_OBJECT(mdecoder->queue), 
"use-rate-estimate", FALSE, NULL);
 
  612  g_object_set(G_OBJECT(mdecoder->queue), 
"max-size-buffers", 0, NULL);
 
  613  g_object_set(G_OBJECT(mdecoder->queue), 
"max-size-bytes", 0, NULL);
 
  614  g_object_set(G_OBJECT(mdecoder->queue), 
"max-size-time", (guint64)0, NULL);
 
  618  if (!g_strcmp0(G_OBJECT_TYPE_NAME(mdecoder->outsink), 
"GstAutoVideoSink") &&
 
  619      !g_strcmp0(G_OBJECT_TYPE_NAME(mdecoder->outsink), 
"GstAutoAudioSink"))
 
  621    if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  623      gst_base_sink_set_max_lateness((GstBaseSink*)mdecoder->outsink,
 
  628      gst_base_sink_set_max_lateness((GstBaseSink*)mdecoder->outsink,
 
  630      g_object_set(G_OBJECT(mdecoder->outsink), 
"buffer-time", (gint64)20000,
 
  632      g_object_set(G_OBJECT(mdecoder->outsink), 
"drift-tolerance", (gint64)20000,
 
  634      g_object_set(G_OBJECT(mdecoder->outsink), 
"latency-time", (gint64)10000,
 
  636      g_object_set(G_OBJECT(mdecoder->outsink), 
"slave-method", 1, NULL);
 
  638    g_object_set(G_OBJECT(mdecoder->outsink), 
"sync", TRUE,
 
  640    g_object_set(G_OBJECT(mdecoder->outsink), 
"async", TRUE, NULL); 
 
  643  tsmf_window_create(mdecoder);
 
  644  tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_READY);
 
  645  tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
 
  646  mdecoder->pipeline_start_time_valid = 0;
 
  647  mdecoder->shutdown = 0;
 
  648  mdecoder->paused = FALSE;
 
  650  GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(mdecoder->pipe), GST_DEBUG_GRAPH_SHOW_ALL,
 
  656static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder* decoder, 
const BYTE* data, UINT32 data_size,
 
  657                                    UINT32 extensions, UINT64 start_time, UINT64 end_time,
 
  662  UINT64 sample_time = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
 
  663  BOOL useTimestamps = TRUE;
 
  667    WLog_ERR(TAG, 
"Decoder not initialized!");
 
  678      "%s. Start:(%" PRIu64 
") End:(%" PRIu64 
") Duration:(%" PRIu64 
") Last Start:(%" PRIu64 
")",
 
  679      get_type(mdecoder), start_time, end_time, duration, mdecoder->last_sample_start_time);
 
  681  if (mdecoder->shutdown)
 
  683    WLog_ERR(TAG, 
"decodeEx called on shutdown decoder");
 
  687  if (mdecoder->gst_caps == NULL)
 
  689    WLog_ERR(TAG, 
"tsmf_gstreamer_set_format not called or invalid format.");
 
  694    tsmf_gstreamer_pipeline_build(mdecoder);
 
  700        "failed to construct pipeline correctly. Unable to push buffer to source element.");
 
  704  gst_buf = tsmf_get_buffer_from_data(data, data_size);
 
  708    WLog_ERR(TAG, 
"tsmf_get_buffer_from_data(%p, %" PRIu32 
") failed.", (
void*)data, data_size);
 
  715  if (extensions & 0x00000080)
 
  717    DEBUG_TSMF(
"Ignoring the timestamps - relative - bit 8");
 
  718    useTimestamps = FALSE;
 
  722  if (extensions & 0x00000040)
 
  724    DEBUG_TSMF(
"Ignoring the timestamps - none - bit 7");
 
  725    useTimestamps = FALSE;
 
  729  if (mdecoder->seeking)
 
  731    mdecoder->seeking = FALSE;
 
  732    tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
 
  733    mdecoder->pipeline_start_time_valid = 0;
 
  736  if (mdecoder->pipeline_start_time_valid)
 
  738    DEBUG_TSMF(
"%s start time %" PRIu64 
"", get_type(mdecoder), start_time);
 
  744    UINT64 minTime = mdecoder->last_sample_start_time - (UINT64)SEEK_TOLERANCE;
 
  745    UINT64 maxTime = mdecoder->last_sample_start_time + (UINT64)SEEK_TOLERANCE;
 
  748    if (mdecoder->last_sample_start_time < (UINT64)SEEK_TOLERANCE)
 
  753    if (((start_time > maxTime) || (start_time < minTime)) && useTimestamps)
 
  755      DEBUG_TSMF(
"tsmf_gstreamer_decodeEx: start_time=[%" PRIu64
 
  756                 "] > last_sample_start_time=[%" PRIu64 
"] OR ",
 
  757                 start_time, mdecoder->last_sample_start_time);
 
  758      DEBUG_TSMF(
"tsmf_gstreamer_decodeEx: start_time=[%" PRIu64
 
  759                 "] < last_sample_start_time=[%" PRIu64 
"] with",
 
  760                 start_time, mdecoder->last_sample_start_time);
 
  762          "tsmf_gstreamer_decodeEX: a tolerance of more than [%lu] from the last sample",
 
  764      DEBUG_TSMF(
"tsmf_gstreamer_decodeEX: minTime=[%" PRIu64 
"] maxTime=[%" PRIu64 
"]",
 
  767      mdecoder->seeking = TRUE;
 
  772      mdecoder->seek_offset = start_time;
 
  777    DEBUG_TSMF(
"%s start time %" PRIu64 
"", get_type(mdecoder), start_time);
 
  782    gst_element_set_base_time(mdecoder->pipe, tsmf_gstreamer_timestamp_ms_to_gst(0));
 
  783    gst_element_set_start_time(mdecoder->pipe, tsmf_gstreamer_timestamp_ms_to_gst(0));
 
  784    mdecoder->pipeline_start_time_valid = 1;
 
  788      mdecoder->seek_offset = start_time;
 
  790    if (!gst_element_seek(mdecoder->pipe, 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
 
  791                          GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE))
 
  793      WLog_ERR(TAG, 
"seek failed");
 
  797#if GST_VERSION_MAJOR > 0 
  799    GST_BUFFER_PTS(gst_buf) =
 
  800        sample_time - tsmf_gstreamer_timestamp_ms_to_gst(mdecoder->seek_offset);
 
  802    GST_BUFFER_PTS(gst_buf) = GST_CLOCK_TIME_NONE;
 
  805    GST_BUFFER_TIMESTAMP(gst_buf) =
 
  806        sample_time - tsmf_gstreamer_timestamp_ms_to_gst(mdecoder->seek_offset);
 
  808    GST_BUFFER_TIMESTAMP(gst_buf) = GST_CLOCK_TIME_NONE;
 
  810  GST_BUFFER_DURATION(gst_buf) = GST_CLOCK_TIME_NONE;
 
  811  GST_BUFFER_OFFSET(gst_buf) = GST_BUFFER_OFFSET_NONE;
 
  812#if GST_VERSION_MAJOR > 0 
  814  gst_buffer_set_caps(gst_buf, mdecoder->gst_caps);
 
  816  gst_app_src_push_buffer(GST_APP_SRC(mdecoder->src), gst_buf);
 
  821    mdecoder->last_sample_start_time = start_time;
 
  822    mdecoder->last_sample_end_time = end_time;
 
  825  if (mdecoder->pipe && (GST_STATE(mdecoder->pipe) != GST_STATE_PLAYING))
 
  827    DEBUG_TSMF(
"%s: state=%s", get_type(mdecoder),
 
  828               gst_element_state_get_name(GST_STATE(mdecoder->pipe)));
 
  830    DEBUG_TSMF(
"%s Paused: %" PRIi32 
"   Shutdown: %i   Ready: %" PRIi32 
"", get_type(mdecoder),
 
  831               mdecoder->paused, mdecoder->shutdown, mdecoder->ready);
 
  832    if (!mdecoder->paused && !mdecoder->shutdown && mdecoder->ready)
 
  833      tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
 
  839static BOOL tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg control_msg, UINT32* arg)
 
  845    WLog_ERR(TAG, 
"Control called with no decoder!");
 
  849  if (control_msg == Control_Pause)
 
  851    DEBUG_TSMF(
"Control_Pause %s", get_type(mdecoder));
 
  853    if (mdecoder->paused)
 
  855      WLog_ERR(TAG, 
"%s: Ignoring Control_Pause, already received!", get_type(mdecoder));
 
  859    tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
 
  860    mdecoder->shutdown = 0;
 
  861    mdecoder->paused = TRUE;
 
  863  else if (control_msg == Control_Resume)
 
  865    DEBUG_TSMF(
"Control_Resume %s", get_type(mdecoder));
 
  867    if (!mdecoder->paused && !mdecoder->shutdown)
 
  869      WLog_ERR(TAG, 
"%s: Ignoring Control_Resume, already received!", get_type(mdecoder));
 
  873    mdecoder->shutdown = 0;
 
  874    mdecoder->paused = FALSE;
 
  876  else if (control_msg == Control_Stop)
 
  878    DEBUG_TSMF(
"Control_Stop %s", get_type(mdecoder));
 
  880    if (mdecoder->shutdown)
 
  882      WLog_ERR(TAG, 
"%s: Ignoring Control_Stop, already received!", get_type(mdecoder));
 
  889      tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_NULL);
 
  890      tsmf_window_destroy(mdecoder);
 
  891      tsmf_gstreamer_clean_up(mdecoder);
 
  893    mdecoder->seek_offset = 0;
 
  894    mdecoder->pipeline_start_time_valid = 0;
 
  895    mdecoder->shutdown = 1;
 
  897  else if (control_msg == Control_Restart)
 
  899    DEBUG_TSMF(
"Control_Restart %s", get_type(mdecoder));
 
  900    mdecoder->shutdown = 0;
 
  901    mdecoder->paused = FALSE;
 
  903    if (mdecoder->pipeline_start_time_valid)
 
  904      tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
 
  907    WLog_ERR(TAG, 
"Unknown control message %08x", control_msg);
 
  912static BOOL tsmf_gstreamer_buffer_level(ITSMFDecoder* decoder)
 
  922  if (G_IS_OBJECT(mdecoder->queue))
 
  923    g_object_get(mdecoder->queue, 
"current-level-buffers", &clbuff, NULL);
 
  925  DEBUG_TSMF(
"%s buffer level %u", get_type(mdecoder), clbuff);
 
  929static void tsmf_gstreamer_free(ITSMFDecoder* decoder)
 
  932  DEBUG_TSMF(
"%s", get_type(mdecoder));
 
  936    tsmf_window_destroy(mdecoder);
 
  937    tsmf_gstreamer_clean_up(mdecoder);
 
  939    if (mdecoder->gst_caps)
 
  940      gst_caps_unref(mdecoder->gst_caps);
 
  942    tsmf_platform_free(mdecoder);
 
  949static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder* decoder)
 
  956  if (!mdecoder->outsink)
 
  957    return mdecoder->last_sample_start_time;
 
  962  GstFormat fmt = GST_FORMAT_TIME;
 
  964#if GST_VERSION_MAJOR > 0 
  965  gst_element_query_position(mdecoder->pipe, fmt, &pos);
 
  967  gst_element_query_position(mdecoder->pipe, &fmt, &pos);
 
  969  return (UINT64)(pos / 100 + mdecoder->seek_offset);
 
  972static BOOL tsmf_gstreamer_update_rendering_area(ITSMFDecoder* decoder, 
int newX, 
int newY,
 
  973                                                 int newWidth, 
int newHeight, 
int numRectangles,
 
  977  DEBUG_TSMF(
"x=%d, y=%d, w=%d, h=%d, rect=%d", newX, newY, newWidth, newHeight, numRectangles);
 
  979  if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
 
  981    return tsmf_window_resize(mdecoder, newX, newY, newWidth, newHeight, numRectangles,
 
  988static BOOL tsmf_gstreamer_ack(ITSMFDecoder* decoder, BOOL (*cb)(
void*, BOOL), 
void* stream)
 
  992  mdecoder->ack_cb = NULL;
 
  993  mdecoder->stream = stream;
 
  997static BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, 
void (*cb)(
void*), 
void* stream)
 
 1001  mdecoder->sync_cb = NULL;
 
 1002  mdecoder->stream = stream;
 
 1006FREERDP_ENTRY_POINT(UINT VCAPITYPE gstreamer_freerdp_tsmf_client_decoder_subsystem_entry(
void* ptr))
 
 1008  ITSMFDecoder** sptr = (ITSMFDecoder**)ptr;
 
 1012#if GST_CHECK_VERSION(0, 10, 31) 
 1013  if (!gst_is_initialized())
 
 1015    gst_init(NULL, NULL);
 
 1018  gst_init(NULL, NULL);
 
 1025    return ERROR_OUTOFMEMORY;
 
 1027  decoder->iface.SetFormat = tsmf_gstreamer_set_format;
 
 1028  decoder->iface.Decode = NULL;
 
 1029  decoder->iface.GetDecodedData = NULL;
 
 1030  decoder->iface.GetDecodedFormat = NULL;
 
 1031  decoder->iface.GetDecodedDimension = NULL;
 
 1032  decoder->iface.GetRunningTime = tsmf_gstreamer_get_running_time;
 
 1033  decoder->iface.UpdateRenderingArea = tsmf_gstreamer_update_rendering_area;
 
 1034  decoder->iface.Free = tsmf_gstreamer_free;
 
 1035  decoder->iface.Control = tsmf_gstreamer_control;
 
 1036  decoder->iface.DecodeEx = tsmf_gstreamer_decodeEx;
 
 1037  decoder->iface.ChangeVolume = tsmf_gstreamer_change_volume;
 
 1038  decoder->iface.BufferLevel = tsmf_gstreamer_buffer_level;
 
 1039  decoder->iface.SetAckFunc = tsmf_gstreamer_ack;
 
 1040  decoder->iface.SetSyncFunc = tsmf_gstreamer_sync;
 
 1041  decoder->paused = FALSE;
 
 1042  decoder->gstVolume = 0.5;
 
 1043  decoder->gstMuted = FALSE;
 
 1044  decoder->state = GST_STATE_VOID_PENDING; 
 
 1045  decoder->last_sample_start_time = 0;
 
 1046  decoder->last_sample_end_time = 0;
 
 1047  decoder->seek_offset = 0;
 
 1048  decoder->seeking = FALSE;
 
 1050  if (tsmf_platform_create(decoder) < 0)
 
 1053    return ERROR_INTERNAL_ERROR;
 
 1056  *sptr = &decoder->iface;
 
 1057  return CHANNEL_RC_OK;