/* generate queries to adaptive demux */
static gboolean
testQueryCheckDataReceived (GstAdaptiveDemuxTestEngine * engine,
    GstAdaptiveDemuxTestOutputStream * stream,
    GstBuffer * buffer, gpointer user_data)
{
  GList *pads;
  GstPad *pad;
  GstQuery *query;
  gboolean ret;
  gint64 duration;
  gboolean seekable;
  gint64 segment_start;
  gint64 segment_end;
  gchar *uri;
  gchar *redirect_uri;
  gboolean redirect_permanent;

  pads = GST_ELEMENT_PADS (stream->appsink);

  /* AppSink should have only 1 pad */
  fail_unless (pads != NULL);
  fail_unless (g_list_length (pads) == 1);
  pad = GST_PAD (pads->data);

  query = gst_query_new_duration (GST_FORMAT_TIME);
  ret = gst_pad_peer_query (pad, query);
  fail_unless (ret == TRUE);
  gst_query_parse_duration (query, NULL, &duration);
  fail_unless (duration == 135743 * GST_MSECOND);
  gst_query_unref (query);

  query = gst_query_new_seeking (GST_FORMAT_TIME);
  ret = gst_pad_peer_query (pad, query);
  fail_unless (ret == TRUE);
  gst_query_parse_seeking (query, NULL, &seekable, &segment_start,
      &segment_end);
  fail_unless (seekable == TRUE);
  fail_unless (segment_start == 0);
  fail_unless (segment_end == duration);
  gst_query_unref (query);

  query = gst_query_new_uri ();
  ret = gst_pad_peer_query (pad, query);
  fail_unless (ret == TRUE);
  gst_query_parse_uri (query, &uri);
  gst_query_parse_uri_redirection (query, &redirect_uri);
  gst_query_parse_uri_redirection_permanent (query, &redirect_permanent);
  fail_unless (strcmp (uri, "http://unit.test/test.mpd") == 0);
  /* adaptive demux does not reply with redirect information */
  fail_unless (redirect_uri == NULL);
  fail_unless (redirect_permanent == FALSE);
  g_free (uri);
  g_free (redirect_uri);
  gst_query_unref (query);

  return gst_adaptive_demux_test_check_received_data (engine,
      stream, buffer, user_data);
}
Exemple #2
0
static gboolean
gst_y4m_dec_src_query (GstPad * pad, GstQuery * query)
{
  GstY4mDec *y4mdec = GST_Y4M_DEC (gst_pad_get_parent (pad));
  gboolean res = FALSE;

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_DURATION:
    {
      GstFormat format;
      GstPad *peer;

      GST_DEBUG ("duration query");

      gst_query_parse_duration (query, &format, NULL);

      if (format != GST_FORMAT_TIME) {
        res = FALSE;
        GST_DEBUG_OBJECT (y4mdec, "not handling duration query in format %d",
            format);
        break;
      }

      peer = gst_pad_get_peer (y4mdec->sinkpad);
      if (peer) {
        GstQuery *peer_query = gst_query_new_duration (GST_FORMAT_BYTES);

        res = gst_pad_query (peer, peer_query);
        if (res) {
          gint64 duration;
          int n_frames;

          gst_query_parse_duration (peer_query, &format, &duration);

          n_frames = gst_y4m_dec_bytes_to_frames (y4mdec, duration);
          GST_DEBUG ("duration in frames %d", n_frames);

          duration = gst_y4m_dec_frames_to_timestamp (y4mdec, n_frames);
          GST_DEBUG ("duration in time %" GST_TIME_FORMAT,
              GST_TIME_ARGS (duration));

          gst_query_set_duration (query, GST_FORMAT_TIME, duration);
          res = TRUE;
        }

        gst_query_unref (peer_query);
        gst_object_unref (peer);
      }
      break;
    }
    default:
      res = gst_pad_query_default (pad, query);
      break;
  }

  gst_object_unref (y4mdec);
  return res;
}
Exemple #3
0
static VALUE
duration_initialize(VALUE self, VALUE format)
{
    GstQuery *query;

    query = gst_query_new_duration(RVAL2GST_FORMAT(format));

    G_INITIALIZE(self, query);
    return Qnil;
}
Exemple #4
0
static gboolean
impl_seekable (RBPlayer *player)
{
	RBPlayerGst *mp = RB_PLAYER_GST (player);
	gboolean can_seek = TRUE;
	GstQuery *query;

	if (mp->priv->playbin == NULL)
		return FALSE;

	query = gst_query_new_seeking (GST_FORMAT_TIME);
	if (gst_element_query (mp->priv->playbin, query)) {
		gst_query_parse_seeking (query, NULL, &can_seek, NULL, NULL);
	} else {
		gst_query_unref (query);

		query = gst_query_new_duration (GST_FORMAT_TIME);
		can_seek = gst_element_query (mp->priv->playbin, query);
	}
	gst_query_unref (query);

	return can_seek;
}
static gboolean
gst_raw_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
{
  GstRawParse *rp = GST_RAW_PARSE (parent);
  gboolean ret = FALSE;

  GST_DEBUG ("src_query %s", gst_query_type_get_name (GST_QUERY_TYPE (query)));

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_POSITION:
    {
      GstFormat format;
      gint64 time, value;

      GST_LOG ("query position");

      gst_query_parse_position (query, &format, NULL);

      time = rp->segment.position;
      ret = gst_raw_parse_convert (rp, GST_FORMAT_TIME, time, format, &value);

      gst_query_set_position (query, format, value);

      break;
    }
    case GST_QUERY_DURATION:{
      gint64 duration;
      GstFormat format;
      GstQuery *bquery;

      GST_LOG ("query duration");
      ret = gst_pad_peer_query (rp->sinkpad, query);
      if (ret)
        goto done;

      gst_query_parse_duration (query, &format, NULL);
      /* We only handle TIME and DEFAULT format */
      if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT)
        goto error;

      bquery = gst_query_new_duration (GST_FORMAT_BYTES);
      ret = gst_pad_peer_query (rp->sinkpad, bquery);
      if (!ret) {
        gst_query_unref (bquery);
        goto error;
      }

      gst_query_parse_duration (bquery, NULL, &duration);
      gst_query_unref (bquery);

      ret =
          gst_raw_parse_convert (rp, GST_FORMAT_BYTES, duration, format,
          &duration);
      if (ret)
        gst_query_set_duration (query, format, duration);

      break;
    }
    case GST_QUERY_CONVERT:
    {
      GstFormat src_fmt, dest_fmt;
      gint64 src_val, dest_val;

      GST_LOG ("query convert");

      gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
      ret = gst_raw_parse_convert (rp, src_fmt, src_val, dest_fmt, &dest_val);
      if (!ret)
        goto error;
      gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
      break;
    }
    case GST_QUERY_SEEKING:{
      GstFormat fmt;

      ret = TRUE;
      gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
      if (fmt != GST_FORMAT_TIME && fmt != GST_FORMAT_DEFAULT
          && fmt != GST_FORMAT_BYTES) {
        gst_query_set_seeking (query, fmt, FALSE, -1, -1);
      } else if (rp->mode == GST_PAD_MODE_PUSH) {
        GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
        gboolean seekable;

        seekable = gst_pad_peer_query (rp->sinkpad, peerquery);
        if (seekable)
          gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);

        gst_query_unref (peerquery);
        gst_query_set_seeking (query, fmt, seekable, seekable ? 0 : -1, -1);
      } else {
        gst_query_set_seeking (query, fmt, TRUE, 0, -1);
      }
      break;
    }
    default:
      /* else forward upstream */
      ret = gst_pad_query_default (rp->sinkpad, parent, query);
      break;
  }

done:
  return ret;

  /* ERRORS */
error:
  {
    GST_DEBUG_OBJECT (rp, "query failed");
    goto done;
  }
}
static void
test_queries (InsanityTest * test)
{
  GstQuery *query = gst_query_new_seeking (GST_FORMAT_TIME);

  if (gst_element_query (glob_pipeline, query)) {
    GstFormat fmt;
    gboolean seekable, known_seekable;

    gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
    if (glob_media_desc_parser == NULL) {
      insanity_test_validate_checklist_item (test, "seekable-detection",
          TRUE, "No media-descriptor file, result not verified against it");

      glob_seekable = seekable;
    } else {
      known_seekable =
          media_descriptor_parser_get_seekable (glob_media_desc_parser);

      insanity_test_validate_checklist_item (test, "seekable-detection",
          known_seekable == seekable, NULL);
      glob_seekable = known_seekable;
    }
  } else {
    if (glob_media_desc_parser != NULL)
      glob_seekable =
          media_descriptor_parser_get_seekable (glob_media_desc_parser);

    LOG (test,
        "%s Does not handle seeking queries (seekable-detection \"SKIP\")",
        gst_element_factory_get_metadata (gst_element_get_factory
            (glob_demuxer), GST_ELEMENT_METADATA_LONGNAME));
  }

  gst_query_unref (query);
  query = gst_query_new_duration (GST_FORMAT_TIME);
  if (gst_element_query (glob_pipeline, query)) {
    GstFormat fmt;
    gchar *validate_msg = NULL;
    gint64 duration;

    if (glob_media_desc_parser == NULL) {
      gst_query_parse_duration (query, &fmt, &duration);
      validate_msg =
          g_strdup_printf ("Found duration %" GST_TIME_FORMAT
          " No media-descriptor file, result not verified against it",
          GST_TIME_ARGS (duration));
      insanity_test_validate_checklist_item (test, "duration-detection",
          TRUE, validate_msg);

      g_free (validate_msg);

      glob_duration = duration;
    } else {
      glob_duration =
          media_descriptor_parser_get_duration (glob_media_desc_parser);
      gst_query_parse_duration (query, &fmt, &duration);

      if (glob_duration != duration) {
        validate_msg =
            g_strdup_printf ("Found time %" GST_TIME_FORMAT "-> %"
            GST_TIME_FORMAT, GST_TIME_ARGS (duration),
            GST_TIME_ARGS (glob_duration));

        insanity_test_validate_checklist_item (test, "duration-detection",
            glob_duration == duration, validate_msg);

        g_free (validate_msg);
      } else {
        insanity_test_validate_checklist_item (test, "duration-detection",
            TRUE, NULL);
      }
    }

  } else {
    if (glob_media_desc_parser != NULL)
      glob_duration =
          media_descriptor_parser_get_seekable (glob_media_desc_parser);

    LOG (test, "%s Does not handle duration queries "
        "(duration-detection \"SKIP\")",
        gst_element_factory_get_metadata (gst_element_get_factory
            (glob_demuxer), GST_ELEMENT_METADATA_LONGNAME));
  }

  if (GST_CLOCK_TIME_IS_VALID (glob_duration) &&
      glob_playback_duration > glob_duration) {
    LOG (test, "playback_duration > media duration, setting it"
        "to media_duration != 2");

    glob_playback_duration = glob_duration / 2;
  }
  gst_query_unref (query);


  next_test (test);
}
gint
main (gint argc, gchar * argv[])
{
  GstElement *pipeline, *filesrc, *decodebin;
  GstStateChangeReturn res;
  GstIterator *it;
  GstBus *bus;
  GValue data = { 0, };

  gst_init (&argc, &argv);

  pipeline = gst_pipeline_new ("pipeline");

  filesrc = gst_element_factory_make ("filesrc", "filesrc");
  g_assert (filesrc);

  decodebin = gst_element_factory_make ("decodebin", "decodebin");
  g_assert (decodebin);

  gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL);
  gst_element_link (filesrc, decodebin);

  if (argc < 2) {
    g_print ("usage: %s <filenames>\n", argv[0]);
    exit (-1);
  }

  if (!g_str_has_prefix (argv[1], "file://")) {
    g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL);
  } else {
    g_object_set (G_OBJECT (filesrc), "location", argv[1] + 7, NULL);
  }

  /* we've got to connect fakesinks to newly decoded pads to make sure
   * buffers have actually been flowing over those pads and caps have
   * been set on them. decodebin might insert internal queues and
   * without fakesinks it's pot-luck what caps we get from the pad, because
   * it depends on whether the queues have started pushing buffers yet or not.
   * With fakesinks we make sure that the pipeline doesn't go to PAUSED state
   * before each fakesink has a buffer queued. */
  g_signal_connect (decodebin, "new-decoded-pad",
      G_CALLBACK (new_decoded_pad_cb), pipeline);

  bus = gst_element_get_bus (pipeline);

  g_print ("pause..\n");
  res = gst_element_set_state (pipeline, GST_STATE_PAUSED);
  if (res == GST_STATE_CHANGE_FAILURE) {
    show_error ("Could not go to PAUSED state", bus);
    exit (-1);
  }
  g_print ("waiting..\n");
  res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE);
  if (res != GST_STATE_CHANGE_SUCCESS) {
    show_error ("Failed to complete state change to PAUSED", bus);
    exit (-1);
  }
  g_print ("stats..\n");

  it = gst_element_iterate_src_pads (decodebin);
  while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) {
    GstPad *pad = g_value_get_object (&data);
    GstCaps *caps;
    gchar *str;
    GstQuery *query;

    g_print ("stream %s:\n", GST_OBJECT_NAME (pad));

    caps = gst_pad_query_caps (pad, NULL);
    str = gst_caps_to_string (caps);
    g_print (" caps: %s\n", str);
    g_free (str);
    gst_caps_unref (caps);

    query = gst_query_new_duration (GST_FORMAT_TIME);
    if (gst_pad_query (pad, query)) {
      gint64 duration;

      gst_query_parse_duration (query, NULL, &duration);

      g_print (" duration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (duration));
    }
    gst_query_unref (query);

    g_value_reset (&data);
  }
  g_value_unset (&data);
  gst_iterator_free (it);

  return 0;
}
Exemple #8
0
void create_queries()
{
  GstQuery *query;

  /* POSITION */
  {
    GstFormat format;
    gint64 position;
		xmlfile = "gstquery_create_queries";
		std_log(LOG_FILENAME_LINE, "Test Started create_queries");
    query = gst_query_new_position (GST_FORMAT_TIME);
    fail_if (query == NULL);
    fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_POSITION);

    gst_query_parse_position (query, &format, NULL);
    fail_if (format != GST_FORMAT_TIME);

    gst_query_set_position (query, GST_FORMAT_TIME, 0xdeadbeaf);

    gst_query_parse_position (query, &format, &position);
    fail_if (format != GST_FORMAT_TIME);
    fail_if (position != 0xdeadbeaf);

    gst_query_unref (query);
  }
  /* DURATION */
  {
    GstFormat format;
    gint64 duration;

    query = gst_query_new_duration (GST_FORMAT_TIME);
    fail_if (query == NULL);
    fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_DURATION);

    gst_query_parse_duration (query, &format, NULL);
    fail_if (format != GST_FORMAT_TIME);

    gst_query_set_duration (query, GST_FORMAT_TIME, 0xdeadbeaf);

    gst_query_parse_duration (query, &format, &duration);
    fail_if (format != GST_FORMAT_TIME);
    fail_if (duration != 0xdeadbeaf);

    gst_query_unref (query);
  }
  {
    /* FIXME make tests for:
     *
     * LATENCY
     * JITTER
     * RATE
     * SEEKING
     * SEGMENT
     * CONVERT
     */
  }
  /* SEGMENT */
  {
    gdouble rate;
    GstFormat format;
    gint64 start, stop;

    format = GST_FORMAT_BYTES;
    query = gst_query_new_segment (format);

    fail_if (query == NULL);
    fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_SEGMENT);

    gst_query_parse_segment (query, &rate, &format, &start, &stop);

    /* see if empty gives undefined formats */
    fail_if (rate != 0.0);
    fail_if (format != GST_FORMAT_BYTES);
    fail_if (start != -1);
    fail_if (stop != -1);

    /* change all values */
    gst_query_set_segment (query, 2.0, GST_FORMAT_TIME, 1 * GST_SECOND,
        3 * GST_SECOND);

    gst_query_parse_segment (query, &rate, &format, &start, &stop);

    /* see if the values were changed */
    fail_if (rate != 2.0);
    fail_if (format != GST_FORMAT_TIME);
    fail_if (start != 1 * GST_SECOND);
    fail_if (stop != 3 * GST_SECOND);

    gst_query_unref (query);
  }

  /* FORMATS */
  {
    guint size;
    GstFormat format;

    query = gst_query_new_formats ();
    fail_if (query == NULL);
    fail_unless (GST_QUERY_TYPE (query) == GST_QUERY_FORMATS);

    /* empty */
    gst_query_parse_formats_length (query, &size);
    fail_if (size != 0);

    /* see if empty gives undefined formats */
    gst_query_parse_formats_nth (query, 0, &format);
    fail_if (format != GST_FORMAT_UNDEFINED);
    gst_query_parse_formats_nth (query, 1, &format);
    fail_if (format != GST_FORMAT_UNDEFINED);

    /* set 2 formats */
    gst_query_set_formats (query, 2, GST_FORMAT_TIME, GST_FORMAT_BYTES);

    gst_query_parse_formats_length (query, &size);
    fail_if (size != 2);

    format = GST_FORMAT_UNDEFINED;

    gst_query_parse_formats_nth (query, 0, &format);
    fail_if (format != GST_FORMAT_TIME);
    gst_query_parse_formats_nth (query, 1, &format);
    fail_if (format != GST_FORMAT_BYTES);

    /* out of bounds, should return UNDEFINED */
    gst_query_parse_formats_nth (query, 2, &format);
    fail_if (format != GST_FORMAT_UNDEFINED);

    /* overwrite with 3 formats */
    gst_query_set_formats (query, 3, GST_FORMAT_TIME, GST_FORMAT_BYTES,
        GST_FORMAT_PERCENT);

    gst_query_parse_formats_length (query, &size);
    fail_if (size != 3);

    gst_query_parse_formats_nth (query, 2, &format);
    fail_if (format != GST_FORMAT_PERCENT);

    /* create one from an array */
    {
      static GstFormat formats[] = {
        GST_FORMAT_TIME,
        GST_FORMAT_BYTES,
        GST_FORMAT_PERCENT
      };
      gst_query_set_formatsv (query, 3, formats);

      gst_query_parse_formats_length (query, &size);
      fail_if (size != 3);

      gst_query_parse_formats_nth (query, 0, &format);
      fail_if (format != GST_FORMAT_TIME);
      gst_query_parse_formats_nth (query, 2, &format);
      fail_if (format != GST_FORMAT_PERCENT);
    }
    gst_query_unref (query);
  }
	std_log(LOG_FILENAME_LINE, "Test Successful");
	create_xml(0);


}
Exemple #9
0
void test_queries()
{
  GstBin *bin;
  GstElement *src, *sink;
  GstStateChangeReturn ret;
  GstPad *pad;
  GstQuery *dur, *pos;
	xmlfile = "gstquery_test_queries";
  std_log(LOG_FILENAME_LINE, "Test Started test_queries");
  fail_unless ((bin = (GstBin *) gst_pipeline_new (NULL)) != NULL,
      "Could not create pipeline");
  fail_unless ((src = gst_element_factory_make ("fakesrc", NULL)) != NULL,
      "Could not create fakesrc");
  g_object_set (src, "datarate", 200, "sizetype", 2, NULL);

  fail_unless ((sink = gst_element_factory_make ("fakesink", NULL)) != NULL,
      "Could not create fakesink");
  g_object_set (sink, "sync", TRUE, NULL);
  fail_unless ((dur = gst_query_new_duration (GST_FORMAT_BYTES)) != NULL,
      "Could not prepare duration query");
  fail_unless ((pos = gst_query_new_position (GST_FORMAT_BYTES)) != NULL,
      "Could not prepare position query");

  fail_unless (gst_bin_add (bin, src), "Could not add src to bin");
  fail_unless (gst_bin_add (bin, sink), "Could not add sink to bin");
  fail_unless (gst_element_link (src, sink), "could not link src and sink");

  ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
  fail_if (ret == GST_STATE_CHANGE_FAILURE, "Failed to set pipeline PLAYING");
  if (ret == GST_STATE_CHANGE_ASYNC)
    gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);

  /* Query the bin */
  fail_unless (gst_element_query (GST_ELEMENT (bin), pos),
      "Could not query pipeline position");
  fail_unless (gst_element_query (GST_ELEMENT (bin), dur),
      "Could not query pipeline duration");

  /* Query elements */
  fail_unless (gst_element_query (GST_ELEMENT (src), pos),
      "Could not query position of fakesrc");
  fail_unless (gst_element_query (GST_ELEMENT (src), pos),
      "Could not query duration of fakesrc");

  fail_unless (gst_element_query (GST_ELEMENT (sink), pos),
      "Could not query position of fakesink");
  fail_unless (gst_element_query (GST_ELEMENT (sink), pos),
      "Could not query duration of fakesink");

  /* Query pads */
  fail_unless ((pad = gst_element_get_pad (src, "src")) != NULL,
      "Could not get source pad of fakesrc");
  fail_unless (gst_pad_query (pad, pos),
      "Could not query position of fakesrc src pad");
  fail_unless (gst_pad_query (pad, dur),
      "Could not query duration of fakesrc src pad");
  gst_object_unref (pad);

  /* We don't query the sink pad of fakesink, it doesn't 
   * handle downstream queries atm, but it might later, who knows? */

  ret = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
  fail_if (ret == GST_STATE_CHANGE_FAILURE, "Failed to set pipeline NULL");
  if (ret == GST_STATE_CHANGE_ASYNC)
    gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_CLOCK_TIME_NONE);

  gst_query_unref (dur);
  gst_query_unref (pos);
  gst_object_unref (bin);
	std_log(LOG_FILENAME_LINE, "Test Successful");
	create_xml(0);

}
Exemple #10
0
DurationQueryPtr DurationQuery::create(Format format)
{
    return DurationQueryPtr::wrap(gst_query_new_duration(static_cast<GstFormat>(format)), false);
}
Exemple #11
0
gint64 gstreamer_get_position(gboolean *error) {
	gint64 pos, len;

	if (end_of_stream) {
#if GST_CHECK_VERSION(1, 0, 0)
		if (gst_element_query_duration(pipeline, GST_FORMAT_TIME, &len)) {
#else
		GstFormat format = GST_FORMAT_TIME;
		if (gst_element_query_duration(pipeline, &format, &len)) {
#endif
			if (error != NULL)
				*error = FALSE;
			return len;
		}
		if (error != NULL)
			*error = TRUE;
		return 0;
	}

#if GST_CHECK_VERSION(1, 0, 0)
	if (gst_element_query_position(pipeline, GST_FORMAT_TIME, &pos)) {
		if (gst_element_query_duration (pipeline, GST_FORMAT_TIME, &len)) {
#else
	GstFormat format = GST_FORMAT_TIME;
	if (gst_element_query_position(pipeline, &format, &pos)) {
		GstFormat format2 = GST_FORMAT_TIME;
		if (gst_element_query_duration(pipeline, &format2, &len)) {
#endif
			if (error != NULL)
				*error = FALSE;
			return pos;
		}
	}
//	printf("gstplay: Could not succesfully query current position.\n");
	if (error != NULL)
		*error = TRUE;
	return 0;
}

gint64 gstreamer_get_duration() {
	GstQuery *query;
	gboolean res;
	query = gst_query_new_duration (GST_FORMAT_TIME);
	res = gst_element_query (pipeline, query);
	gint64 duration;
	if (res) {
		gst_query_parse_duration(query, NULL, &duration);
	}
	else
		duration = 0;
	gst_query_unref (query);
	return duration;
}

const gchar *gstreamer_get_duration_str() {
	gint64 duration = gstreamer_get_duration();
	char s[80];
	sprintf(s, "%u:%02u:%02u", GST_TIME_ARGS(duration));
	return strdup(s);
}

static gboolean seek_to_time_cb(gpointer data) {
	gstreamer_seek_to_time(requested_position);
	gstreamer_set_volume(suspended_audio_volume);
	return FALSE;
}

void gstreamer_seek_to_time(gint64 time_nanoseconds) {
	end_of_stream = FALSE;
	if (!gst_element_seek_simple(pipeline, GST_FORMAT_TIME,
	GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, time_nanoseconds)) {
		printf("gstplay: Seek failed!.n");
	}
}