static gboolean
kms_base_hub_create_and_link_ghost_pad (KmsBaseHub * mixer,
    GstPad * src_pad, const gchar * gp_name, const gchar * gp_template_name,
    GstPad * target)
{
  GstPadTemplate *templ;
  GstPad *gp;
  gboolean ret;

  templ =
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS
      (G_OBJECT_GET_CLASS (mixer)), gp_template_name);
  gp = gst_ghost_pad_new_from_template (gp_name, target, templ);

  if (GST_STATE (mixer) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (mixer) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (mixer) >= GST_STATE_PAUSED) {
    gst_pad_set_active (gp, TRUE);
  }

  ret = gst_element_add_pad (GST_ELEMENT (mixer), gp);

  if (ret) {
    gst_pad_link (src_pad, gp);
  } else {
    g_object_unref (gp);
  }

  return ret;
}
Exemple #2
0
static GstPad *
kms_hub_port_generate_sink_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps,
    GstElement * output)
{
  GstPad *output_pad, *pad;

  output_pad = gst_element_get_static_pad (output, "sink");
  pad = gst_ghost_pad_new_from_template (name, output_pad, templ);
  g_object_unref (output_pad);

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (element) >= GST_STATE_PAUSED) {
    gst_pad_set_active (pad, TRUE);
  }

  if (gst_element_add_pad (element, pad))
    return pad;

  GST_ERROR_OBJECT (element, "Cannot add pad %" GST_PTR_FORMAT, pad);
  g_object_unref (pad);

  return NULL;
}
Exemple #3
0
static void
pragha_backend_set_target_state (PraghaBackend *backend, GstState target_state)
{
	GstStateChangeReturn ret;
	PraghaBackendPrivate *priv = backend->priv;

	GstState old_state = priv->target_state;
	priv->target_state = target_state;

	ret = gst_element_set_state(priv->pipeline, target_state);

	switch (ret) {
		case GST_STATE_CHANGE_SUCCESS:
			if (target_state == GST_STATE_READY)
				pragha_backend_evaluate_state(old_state,
							      GST_STATE (priv->pipeline),
							      GST_STATE_PENDING (priv->pipeline),
							      backend);
			break;
		case GST_STATE_CHANGE_NO_PREROLL:
			if (target_state == GST_STATE_PLAYING)
				priv->is_live = TRUE;
			break;
		default:
			break;
	}

	g_object_notify_by_pspec (G_OBJECT (backend), properties[PROP_TARGET_STATE]);
}
Exemple #4
0
static void
kms_audio_mixer_remove_sometimes_src_pad (KmsAudioMixer * self,
    GstElement * adder)
{
  GstProxyPad *internal;
  GstPad *srcpad, *peer;

  srcpad = gst_element_get_static_pad (adder, "src");
  peer = gst_pad_get_peer (srcpad);
  if (peer == NULL)
    goto end_phase_1;

  internal = gst_proxy_pad_get_internal ((GstProxyPad *) peer);
  if (internal == NULL)
    goto end_phase_2;

  gst_ghost_pad_set_target (GST_GHOST_PAD (internal), NULL);

  if (GST_STATE (self) < GST_STATE_PAUSED
      || GST_STATE_PENDING (self) < GST_STATE_PAUSED
      || GST_STATE_TARGET (self) < GST_STATE_PAUSED) {
    gst_pad_set_active (GST_PAD (internal), FALSE);
  }

  GST_DEBUG ("Removing source pad %" GST_PTR_FORMAT, internal);

  gst_element_remove_pad (GST_ELEMENT (self), GST_PAD (internal));
  gst_object_unref (internal);

end_phase_2:
  gst_object_unref (peer);

end_phase_1:
  gst_object_unref (srcpad);
}
static void
kms_element_release_pad (GstElement * element, GstPad * pad)
{
  GstElement *agnosticbin;
  GstPad *target;

  if (g_str_has_prefix (GST_OBJECT_NAME (pad), "audio_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->audio_agnosticbin;
  } else if (g_str_has_prefix (GST_OBJECT_NAME (pad), "video_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->video_agnosticbin;
  } else {
    return;
  }

  // TODO: Remove pad if is a sinkpad

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  if (target != NULL && agnosticbin != NULL)
    gst_element_release_request_pad (agnosticbin, target);

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED)
    gst_pad_set_active (pad, FALSE);

  gst_element_remove_pad (element, pad);
}
Exemple #6
0
static void
kms_hub_port_start_media_type (KmsElement * self, KmsElementPadType type,
    GstPadTemplate * templ, const gchar * pad_name)
{
  GstElement *capsfilter = gst_element_factory_make ("capsfilter", NULL);
  GstPad *src = gst_element_get_static_pad (capsfilter, "src");
  GstPad *internal_src;

  gst_bin_add (GST_BIN (self), capsfilter);
  gst_element_sync_state_with_parent (capsfilter);

  internal_src = gst_ghost_pad_new_from_template (pad_name, src, templ);

  g_object_set_qdata_full (G_OBJECT (internal_src), key_elem_data_quark (),
      g_object_ref (capsfilter), g_object_unref);
  g_object_set_qdata (G_OBJECT (internal_src), key_type_data_quark (),
      GINT_TO_POINTER (type));

  g_signal_connect (internal_src, "linked",
      G_CALLBACK (kms_hub_port_internal_src_pad_linked), NULL);

  if (GST_STATE (self) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (self) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (self) >= GST_STATE_PAUSED) {
    gst_pad_set_active (internal_src, TRUE);
  }

  gst_element_add_pad (GST_ELEMENT (self), internal_src);
  g_object_unref (src);
}
static gboolean
kms_base_hub_link_src_pad (KmsBaseHub * mixer, const gchar * gp_name,
    const gchar * template_name, GstElement * internal_element,
    const gchar * pad_name, gboolean remove_on_unlink)
{
  GstPad *gp, *target;
  gboolean ret;

  if (GST_OBJECT_PARENT (internal_element) != GST_OBJECT (mixer)) {
    GST_ERROR_OBJECT (mixer, "Cannot link %" GST_PTR_FORMAT " wrong hierarchy",
        internal_element);
    return FALSE;
  }

  target = gst_element_get_static_pad (internal_element, pad_name);
  if (target == NULL) {
    target = gst_element_get_request_pad (internal_element, pad_name);

    if (target != NULL && remove_on_unlink) {
      g_signal_connect (G_OBJECT (target), "unlinked",
          G_CALLBACK (remove_unlinked_pad), NULL);
    }
  }

  if (target == NULL) {
    GST_ERROR_OBJECT (mixer, "Cannot get target pad");
    return FALSE;
  }

  gp = gst_element_get_static_pad (GST_ELEMENT (mixer), gp_name);

  if (gp == NULL) {
    GstPadTemplate *templ;

    templ =
        gst_element_class_get_pad_template (GST_ELEMENT_CLASS
        (G_OBJECT_GET_CLASS (mixer)), template_name);
    gp = gst_ghost_pad_new_from_template (gp_name, target, templ);

    if (GST_STATE (mixer) >= GST_STATE_PAUSED
        || GST_STATE_PENDING (mixer) >= GST_STATE_PAUSED
        || GST_STATE_TARGET (mixer) >= GST_STATE_PAUSED) {
      gst_pad_set_active (gp, TRUE);
    }

    ret = gst_element_add_pad (GST_ELEMENT (mixer), gp);
    if (!ret) {
      g_object_unref (gp);
    }
  } else {
    ret = set_target (gp, target);
    g_object_unref (gp);
  }

  g_object_unref (target);

  return ret;
}
static gboolean
do_toggle_element (GstGConfVideoSrc * src)
{
  GstPad *targetpad;
  gchar *new_gconf_str;
  GstState cur, next;

  new_gconf_str = gst_gconf_get_string (GST_GCONF_AUDIOSRC_KEY);
  if (new_gconf_str != NULL && src->gconf_str != NULL &&
      (strlen (new_gconf_str) == 0 ||
          strcmp (src->gconf_str, new_gconf_str) == 0)) {
    g_free (new_gconf_str);
    GST_DEBUG_OBJECT (src, "GConf key was updated, but it didn't change");
    return TRUE;
  }

  GST_OBJECT_LOCK (src);
  cur = GST_STATE (src);
  next = GST_STATE_PENDING (src);
  GST_OBJECT_UNLOCK (src);

  if (cur >= GST_STATE_READY || next == GST_STATE_PAUSED) {
    GST_DEBUG_OBJECT (src, "already running, ignoring GConf change");
    g_free (new_gconf_str);
    return TRUE;
  }

  g_free (src->gconf_str);
  src->gconf_str = new_gconf_str;

  /* kill old element */
  if (src->kid) {
    GST_DEBUG_OBJECT (src, "Removing old kid");
    gst_element_set_state (src->kid, GST_STATE_NULL);
    gst_bin_remove (GST_BIN (src), src->kid);
    src->kid = NULL;
  }

  GST_DEBUG_OBJECT (src, "Creating new kid");
  if (!(src->kid = gst_gconf_get_default_video_src ())) {
    GST_ELEMENT_ERROR (src, LIBRARY, SETTINGS, (NULL),
        ("Failed to render video source from GConf"));
    g_free (src->gconf_str);
    src->gconf_str = NULL;
    return FALSE;
  }
  gst_element_set_state (src->kid, GST_STATE (src));
  gst_bin_add (GST_BIN (src), src->kid);

  /* re-attach ghostpad */
  GST_DEBUG_OBJECT (src, "Creating new ghostpad");
  targetpad = gst_element_get_static_pad (src->kid, "src");
  gst_ghost_pad_set_target (GST_GHOST_PAD (src->pad), targetpad);
  gst_object_unref (targetpad);
  GST_DEBUG_OBJECT (src, "done changing gconf video source");

  return TRUE;
}
static void
gst_sctp_base_sink_release_pad (GstElement * element, GstPad * pad)
{
  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED)
    gst_pad_set_active (pad, FALSE);

  gst_element_remove_pad (element, pad);
}
Exemple #10
0
static GstStateChangeReturn
gst_mikmod_change_state (GstElement * element, GstStateChange transition)
{
  GstMikMod *mikmod;

  g_return_val_if_fail (GST_IS_MIKMOD (element), GST_STATE_CHANGE_FAILURE);

  mikmod = GST_MIKMOD (element);

  GST_DEBUG ("state pending %d", GST_STATE_PENDING (element));

  if (GST_STATE_PENDING (element) == GST_STATE_READY) {
    gst_mikmod_setup (mikmod);

    if (Player_Active ()) {
      Player_TogglePause ();
      Player_SetPosition (0);
    }
    mikmod->initialized = FALSE;
  }

  if (GST_STATE_PENDING (element) == GST_STATE_PLAYING) {
    if (Player_Active () && Player_Paused ())
      Player_TogglePause ();
    else if (!Player_Active ())
      Player_Start (module);

  }

  if (GST_STATE_PENDING (element) == GST_STATE_PAUSED)
    if (Player_Active () && !Player_Paused ())
      Player_TogglePause ();

  if (GST_STATE_PENDING (element) == GST_STATE_NULL)
    MikMod_Exit ();


  if (GST_ELEMENT_CLASS (parent_class)->change_state)
    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  return GST_STATE_CHANGE_SUCCESS;
}
static void
gst_decklink_video_src_start_streams (GstElement * element)
{
  GstDecklinkVideoSrc *self = GST_DECKLINK_VIDEO_SRC_CAST (element);
  HRESULT res;

  if (self->input->video_enabled && (!self->input->audiosrc
          || self->input->audio_enabled)
      && (GST_STATE (self) == GST_STATE_PLAYING
          || GST_STATE_PENDING (self) == GST_STATE_PLAYING)) {
    GstClock *clock;

    clock = gst_element_get_clock (element);
    if (!clock) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL),
          ("Streams supposed to start but we have no clock"));
      return;
    }

    GST_DEBUG_OBJECT (self, "Starting streams");

    res = self->input->input->StartStreams ();
    if (res != S_OK) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          (NULL), ("Failed to start streams: 0x%08x", res));
      gst_object_unref (clock);
      return;
    }

    self->input->started = TRUE;
    self->input->clock_restart = TRUE;

    // Need to unlock to get the clock time
    g_mutex_unlock (&self->input->lock);

    // Current times of internal and external clock when we go to
    // playing. We need this to convert the pipeline running time
    // to the running time of the hardware
    //
    // We can't use the normal base time for the external clock
    // because we might go to PLAYING later than the pipeline
    self->internal_base_time = gst_clock_get_internal_time (self->input->clock);
    self->external_base_time = gst_clock_get_internal_time (clock);

    gst_object_unref (clock);
    g_mutex_lock (&self->input->lock);
  } else {
    GST_DEBUG_OBJECT (self, "Not starting streams yet");
  }
}
Exemple #12
0
GstPad *
kms_element_connect_sink_target_full (KmsElement * self, GstPad * target,
    KmsElementPadType type, const gchar * description)
{
  GstPad *pad;
  gchar *pad_name;
  GstPadTemplate *templ;

  templ = gst_static_pad_template_get (&sink_factory);

  pad_name = get_pad_name (type, description);

  pad = gst_ghost_pad_new_from_template (pad_name, target, templ);
  g_free (pad_name);
  g_object_unref (templ);

  if (type == KMS_ELEMENT_PAD_TYPE_VIDEO) {
    kms_utils_drop_until_keyframe (pad, TRUE);
    kms_utils_manage_gaps (pad);
  }

  gst_pad_set_query_function (pad, kms_element_pad_query);
  gst_pad_add_probe (pad,
      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_FLUSH,
      accept_eos_probe, self, NULL);
  g_signal_connect (G_OBJECT (pad), "unlinked",
      G_CALLBACK (send_flush_on_unlink), NULL);

  if (GST_STATE (self) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (self) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (self) >= GST_STATE_PAUSED) {
    gst_pad_set_active (pad, TRUE);
  }

  if (gst_element_add_pad (GST_ELEMENT (self), pad)) {
    kms_element_set_sink_input_stats (self, pad, type);
    return pad;
  }

  g_object_unref (pad);

  return NULL;
}
Exemple #13
0
static void
kms_element_release_pad (GstElement * element, GstPad * pad)
{
  GstElement *agnosticbin;
  GstPad *target;
  GstPad *peer;

  if (g_str_has_prefix (GST_OBJECT_NAME (pad), "audio_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->audio_agnosticbin;
  } else if (g_str_has_prefix (GST_OBJECT_NAME (pad), "video_src")) {
    agnosticbin = KMS_ELEMENT (element)->priv->video_agnosticbin;
  } else {
    return;
  }

  // TODO: Remove pad if is a sinkpad

  target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));

  if (target != NULL) {
    if (agnosticbin != NULL) {
      gst_element_release_request_pad (agnosticbin, target);
    }
    g_object_unref (target);
  }

  peer = gst_pad_get_peer (pad);

  gst_pad_push_event (pad, gst_event_new_flush_start ());

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED) {
    gst_pad_set_active (pad, FALSE);
  }

  if (peer) {
    gst_pad_send_event (peer, gst_event_new_flush_stop (FALSE));
    g_object_unref (peer);
  }

  gst_element_remove_pad (element, pad);
}
Exemple #14
0
static GstStateChangeReturn
gst_artsdsink_change_state (GstElement * element, GstStateChange transition)
{
  g_return_val_if_fail (GST_IS_ARTSDSINK (element), FALSE);

  /* if going down into NULL state, close the stream if it's open */
  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
    if (GST_OBJECT_FLAG_IS_SET (element, GST_ARTSDSINK_OPEN))
      gst_artsdsink_close_audio (GST_ARTSDSINK (element));
    /* otherwise (READY or higher) we need to open the stream */
  } else {
    if (!GST_OBJECT_FLAG_IS_SET (element, GST_ARTSDSINK_OPEN)) {
      if (!gst_artsdsink_open_audio (GST_ARTSDSINK (element)))
        return GST_STATE_CHANGE_FAILURE;
    }
  }

  if (GST_ELEMENT_CLASS (parent_class)->change_state)
    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  return GST_STATE_CHANGE_SUCCESS;
}
Exemple #15
0
static GstStateChangeReturn
gst_festival_change_state (GstElement * element, GstStateChange transition)
{
  g_return_val_if_fail (GST_IS_FESTIVAL (element), GST_STATE_CHANGE_FAILURE);

  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
    if (GST_OBJECT_FLAG_IS_SET (element, GST_FESTIVAL_OPEN)) {
      GST_DEBUG ("Closing connection ");
      gst_festival_close (GST_FESTIVAL (element));
    }
  } else {
    if (!GST_OBJECT_FLAG_IS_SET (element, GST_FESTIVAL_OPEN)) {
      GST_DEBUG ("Opening connection ");
      if (!gst_festival_open (GST_FESTIVAL (element)))
        return GST_STATE_CHANGE_FAILURE;
    }
  }

  if (GST_ELEMENT_CLASS (parent_class)->change_state)
    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  return GST_STATE_CHANGE_SUCCESS;
}
static GstStateChangeReturn
dxr3audiosink_change_state (GstElement * element, GstStateChange transition)
{
  g_return_val_if_fail (GST_IS_DXR3AUDIOSINK (element),
      GST_STATE_CHANGE_FAILURE);

  if (GST_STATE_PENDING (element) == GST_STATE_NULL) {
    if (GST_OBJECT_FLAG_IS_SET (element, DXR3AUDIOSINK_OPEN)) {
      dxr3audiosink_close (DXR3AUDIOSINK (element));
    }
  } else {
    if (!GST_OBJECT_FLAG_IS_SET (element, DXR3AUDIOSINK_OPEN)) {
      if (!dxr3audiosink_open (DXR3AUDIOSINK (element))) {
        return GST_STATE_CHANGE_FAILURE;
      }
    }
  }

  if (GST_ELEMENT_CLASS (parent_class)->change_state) {
    return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  }

  return GST_STATE_CHANGE_SUCCESS;
}
Exemple #17
0
static void
kms_element_add_src_pad (KmsElement * self, GstElement * element,
    const gchar * pad_name, const gchar * templ_name)
{
  GstPad *srcpad;

  srcpad =
      gst_ghost_pad_new_no_target_from_template (pad_name,
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS
          (G_OBJECT_GET_CLASS (self)), templ_name));

  if (GST_STATE (self) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (self) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (self) >= GST_STATE_PAUSED)
    gst_pad_set_active (srcpad, TRUE);

  g_signal_connect (srcpad, "linked",
      G_CALLBACK (kms_element_set_target_on_linked), element);

  g_signal_connect (srcpad, "unlinked",
      G_CALLBACK (kms_element_remove_target_on_unlinked), element);

  gst_element_add_pad (GST_ELEMENT (self), srcpad);
}
static GstStateChangeReturn
cdplayer_change_state (GstElement * element, GstStateChange transition)
{
  CDPlayer *cdp;
  GstState state = GST_STATE (element);
  GstState pending = GST_STATE_PENDING (element);

  g_return_val_if_fail (GST_IS_CDPLAYER (element), GST_STATE_CHANGE_FAILURE);

  cdp = CDPLAYER (element);

  switch (pending) {
    case GST_STATE_READY:
      if (state != GST_STATE_PAUSED) {
        if (cd_init (CDPLAYER_CD (cdp), cdp->device) == FALSE) {
          return GST_STATE_CHANGE_FAILURE;
        }
        cdp->num_tracks = cdp->cd.num_tracks;
        cdp->cddb_discid = cd_cddb_discid (CDPLAYER_CD (cdp));
      }
      break;
    case GST_STATE_PAUSED:
      /* ready->paused is not useful */
      if (state != GST_STATE_READY) {
        if (cd_pause (CDPLAYER_CD (cdp)) == FALSE) {
          return GST_STATE_CHANGE_FAILURE;
        }

        cdp->paused = TRUE;
      }

      break;
    case GST_STATE_PLAYING:
      if (cdp->paused == TRUE) {
        if (cd_resume (CDPLAYER_CD (cdp)) == FALSE) {
          return GST_STATE_CHANGE_FAILURE;
        }

        cdp->paused = FALSE;
      } else {
        if (cd_start (CDPLAYER_CD (cdp), cdp->start_track,
                cdp->end_track) == FALSE) {
          return GST_STATE_CHANGE_FAILURE;
        }
      }

      break;
    case GST_STATE_NULL:
      /* stop & close fd */
      if (cd_stop (CDPLAYER_CD (cdp)) == FALSE
          || cd_close (CDPLAYER_CD (cdp)) == FALSE) {
        return GST_STATE_CHANGE_FAILURE;
      }

      break;
    default:
      break;
  }

  if (GST_ELEMENT_CLASS (parent_class)->change_state) {
    GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  }

  return GST_STATE_CHANGE_SUCCESS;
}
static GstPad *
gst_sctp_base_sink_request_new_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  GstSCTPBaseSink *self = GST_SCTP_BASE_SINK (element);
  GstPad *sinkpad, *ghostpad;
  GstElement *sctpclientsink;
  gchar *padname;
  gchar *pad_id;
  gint64 val;
  guint16 id;

  GST_SCTP_BASE_SINK_LOCK (self);
  if (self->priv->num_ostreams < self->priv->streams) {
    GST_SCTP_BASE_SINK_UNLOCK (self);
    GST_WARNING ("No more available streams");
    return NULL;
  }

  pad_id = get_stream_id_from_padname (name);
  if (pad_id == NULL) {
    GST_SCTP_BASE_SINK_UNLOCK (self);
    GST_WARNING
        ("Link of elements without using pad names is not yet supported");
    return NULL;
  }

  val = g_ascii_strtoll (pad_id, NULL, 10);
  g_free (pad_id);

  if (val > G_MAXUINT32) {
    GST_SCTP_BASE_SINK_UNLOCK (self);
    GST_ERROR ("SCTP stream id %" G_GINT64_FORMAT " is not valid", val);
    return NULL;
  }

  id = val;

  sctpclientsink = gst_element_factory_make ("sctpclientsink", NULL);
  sinkpad = gst_element_get_static_pad (sctpclientsink, "sink");
  if (sinkpad == NULL) {
    GST_SCTP_BASE_SINK_UNLOCK (self);
    GST_ERROR_OBJECT (sctpclientsink, "Can not get sink pad");
    gst_object_unref (sctpclientsink);
    return NULL;
  }

  g_object_set (sctpclientsink, "stream-id", id, "socket", self->priv->socket,
      NULL);

  gst_bin_add (GST_BIN (element), sctpclientsink);
  gst_element_sync_state_with_parent (sctpclientsink);

  padname = g_strdup_printf ("sink_%u", id);
  ghostpad = gst_ghost_pad_new_from_template (padname, sinkpad, templ);

  g_object_unref (sinkpad);
  g_free (padname);

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (element) >= GST_STATE_PAUSED)
    gst_pad_set_active (ghostpad, TRUE);

  gst_element_add_pad (element, ghostpad);

  self->priv->streams++;
  GST_SCTP_BASE_SINK_UNLOCK (self);

  return ghostpad;
}
Exemple #20
0
static gboolean
do_toggle_element (GstGConfVideoSink * sink)
{
  GstPad *targetpad;
  gchar *new_gconf_str;
  GstState cur, next;

  new_gconf_str = gst_gconf_get_string (GST_GCONF_VIDEOSINK_KEY);
  if (new_gconf_str != NULL && sink->gconf_str != NULL &&
      (strlen (new_gconf_str) == 0 ||
          strcmp (sink->gconf_str, new_gconf_str) == 0)) {
    g_free (new_gconf_str);
    GST_DEBUG_OBJECT (sink, "GConf key was updated, but it didn't change");
    return TRUE;
  }

  /* Sometime, it would be lovely to allow sink changes even when
   * already running, but this involves sending an appropriate new-segment
   * and possibly prerolling etc */
  GST_OBJECT_LOCK (sink);
  cur = GST_STATE (sink);
  next = GST_STATE_PENDING (sink);
  GST_OBJECT_UNLOCK (sink);

  if (cur > GST_STATE_READY || next == GST_STATE_PAUSED) {
    GST_DEBUG_OBJECT (sink,
        "Auto-sink is already running. Ignoring GConf change");
    g_free (new_gconf_str);
    return TRUE;
  }

  GST_DEBUG_OBJECT (sink, "GConf key changed: '%s' to '%s'",
      GST_STR_NULL (sink->gconf_str), GST_STR_NULL (new_gconf_str));

  g_free (sink->gconf_str);
  sink->gconf_str = new_gconf_str;

  /* kill old element */
  if (sink->kid) {
    GST_DEBUG_OBJECT (sink, "Removing old kid");
    gst_element_set_state (sink->kid, GST_STATE_NULL);
    gst_bin_remove (GST_BIN (sink), sink->kid);
    sink->kid = NULL;
  }

  GST_DEBUG_OBJECT (sink, "Creating new kid");
  if (!(sink->kid = gst_gconf_get_default_video_sink ())) {
    GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
        ("Failed to render video sink from GConf"));
    return FALSE;
  }
  gst_element_set_state (sink->kid, GST_STATE (sink));
  gst_bin_add (GST_BIN (sink), sink->kid);

  /* re-attach ghostpad */
  GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
  targetpad = gst_element_get_static_pad (sink->kid, "sink");
  gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
  gst_object_unref (targetpad);
  GST_DEBUG_OBJECT (sink, "done changing gconf video sink");

  return TRUE;
}
static GstPad *
kms_element_request_new_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  GstPad *ret_pad = NULL;
  gchar *pad_name;
  gboolean added;

  KMS_ELEMENT_LOCK (element);
  if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), "audio_src_%u")) {
    pad_name = g_strdup_printf ("audio_src_%d",
        KMS_ELEMENT (element)->priv->audio_pad_count++);

    ret_pad = kms_element_generate_src_pad (KMS_ELEMENT (element), pad_name,
        KMS_ELEMENT (element)->priv->audio_agnosticbin, templ);
    if (ret_pad == NULL)
      KMS_ELEMENT (element)->priv->audio_pad_count--;

    g_free (pad_name);

  } else if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), "video_src_%u")) {
    pad_name = g_strdup_printf ("video_src_%d",
        KMS_ELEMENT (element)->priv->video_pad_count++);

    ret_pad = kms_element_generate_src_pad (KMS_ELEMENT (element), pad_name,
        KMS_ELEMENT (element)->priv->video_agnosticbin, templ);
    if (ret_pad == NULL)
      KMS_ELEMENT (element)->priv->video_pad_count--;

    g_free (pad_name);

  } else if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), AUDIO_SINK_PAD)) {
    ret_pad =
        kms_element_generate_sink_pad (KMS_ELEMENT (element), AUDIO_SINK_PAD,
        &KMS_ELEMENT (element)->priv->audio_valve, templ);

    gst_pad_add_probe (ret_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
        accept_eos_probe, element, NULL);

    g_signal_connect (G_OBJECT (ret_pad), "unlinked",
        G_CALLBACK (send_flush_on_unlink), NULL);
  } else if (templ ==
      gst_element_class_get_pad_template (GST_ELEMENT_CLASS (G_OBJECT_GET_CLASS
              (element)), VIDEO_SINK_PAD)) {
    ret_pad =
        kms_element_generate_sink_pad (KMS_ELEMENT (element), VIDEO_SINK_PAD,
        &KMS_ELEMENT (element)->priv->video_valve, templ);

    gst_pad_add_probe (ret_pad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
        accept_eos_probe, element, NULL);

    g_signal_connect (G_OBJECT (ret_pad), "unlinked",
        G_CALLBACK (send_flush_on_unlink), NULL);
  }

  if (ret_pad == NULL) {
    KMS_ELEMENT_UNLOCK (element);
    GST_WARNING ("No pad created");
    return NULL;
  }

  if (GST_STATE (element) >= GST_STATE_PAUSED
      || GST_STATE_PENDING (element) >= GST_STATE_PAUSED
      || GST_STATE_TARGET (element) >= GST_STATE_PAUSED)
    gst_pad_set_active (ret_pad, TRUE);

  added = gst_element_add_pad (element, ret_pad);
  KMS_ELEMENT_UNLOCK (element);

  if (added)
    return ret_pad;

  if (gst_pad_get_direction (ret_pad) == GST_PAD_SRC) {
    GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (ret_pad));

    if (target != NULL) {
      GstElement *agnostic = gst_pad_get_parent_element (target);

      gst_element_release_request_pad (agnostic, target);
      g_object_unref (target);
      g_object_unref (agnostic);
    }
  }

  g_object_unref (ret_pad);
  return NULL;
}
static void
gst_decklink_video_sink_start_scheduled_playback (GstElement * element)
{
  GstDecklinkVideoSink *self = GST_DECKLINK_VIDEO_SINK_CAST (element);
  GstClockTime start_time;
  HRESULT res;
  bool active;

  if (self->output->video_enabled && (!self->output->audiosink
          || self->output->audio_enabled)
      && (GST_STATE (self) == GST_STATE_PLAYING
          || GST_STATE_PENDING (self) == GST_STATE_PLAYING)) {
    GstClock *clock = NULL;

    clock = gst_element_get_clock (element);
    if (!clock) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED, (NULL),
          ("Scheduled playback supposed to start but we have no clock"));
      return;
    }
    // Need to unlock to get the clock time
    g_mutex_unlock (&self->output->lock);

    // FIXME: start time is the same for the complete pipeline,
    // but what we need here is the start time of this element!
    start_time = gst_element_get_base_time (element);
    if (start_time != GST_CLOCK_TIME_NONE)
      start_time = gst_clock_get_time (clock) - start_time;

    // FIXME: This will probably not work
    if (start_time == GST_CLOCK_TIME_NONE)
      start_time = 0;

    // Current times of internal and external clock when we go to
    // playing. We need this to convert the pipeline running time
    // to the running time of the hardware
    //
    // We can't use the normal base time for the external clock
    // because we might go to PLAYING later than the pipeline
    self->internal_base_time =
        gst_clock_get_internal_time (self->output->clock);
    self->external_base_time = gst_clock_get_internal_time (clock);

    convert_to_internal_clock (self, &start_time, NULL);

    g_mutex_lock (&self->output->lock);
    // Check if someone else started in the meantime
    if (self->output->started) {
      gst_object_unref (clock);
      return;
    }

    active = false;
    self->output->output->IsScheduledPlaybackRunning (&active);
    if (active) {
      GST_DEBUG_OBJECT (self, "Stopping scheduled playback");

      self->output->started = FALSE;

      res = self->output->output->StopScheduledPlayback (0, 0, 0);
      if (res != S_OK) {
        GST_ELEMENT_ERROR (self, STREAM, FAILED,
            (NULL), ("Failed to stop scheduled playback: 0x%08x", res));
        gst_object_unref (clock);
        return;
      }
    }

    GST_DEBUG_OBJECT (self,
        "Starting scheduled playback at %" GST_TIME_FORMAT,
        GST_TIME_ARGS (start_time));

    res =
        self->output->output->StartScheduledPlayback (start_time,
        GST_SECOND, 1.0);
    if (res != S_OK) {
      GST_ELEMENT_ERROR (self, STREAM, FAILED,
          (NULL), ("Failed to start scheduled playback: 0x%08x", res));
      gst_object_unref (clock);
      return;
    }

    self->output->started = TRUE;
    self->output->clock_restart = TRUE;

    // Need to unlock to get the clock time
    g_mutex_unlock (&self->output->lock);

    // Sample the clocks again to get the most accurate values
    // after we started scheduled playback
    self->internal_base_time =
        gst_clock_get_internal_time (self->output->clock);
    self->external_base_time = gst_clock_get_internal_time (clock);
    g_mutex_lock (&self->output->lock);
    gst_object_unref (clock);
  } else {
    GST_DEBUG_OBJECT (self, "Not starting scheduled playback yet");
  }
}