Esempio n. 1
0
static KmsAlphaBlendingData *
kms_alpha_blending_port_data_create (KmsAlphaBlending * mixer, gint id)
{
  KmsAlphaBlendingData *data;
  gchar *padname;

  data = kms_create_alpha_blending_data ();
  data->id = id;
  data->mixer = mixer;
  data->videoconvert = gst_element_factory_make ("videoconvert", NULL);

  gst_bin_add_many (GST_BIN (mixer), data->videoconvert, NULL);

  gst_element_sync_state_with_parent (data->videoconvert);

  /*link basemixer -> video_agnostic */
  kms_base_hub_link_video_sink (KMS_BASE_HUB (mixer), id, data->videoconvert,
      "sink", FALSE);

  padname = g_strdup_printf (AUDIO_SINK_PAD, id);
  kms_base_hub_link_audio_sink (KMS_BASE_HUB (mixer), id,
      mixer->priv->audiomixer, padname, FALSE);
  g_free (padname);

  data->videoconvert_sink_pad = gst_element_get_static_pad (data->videoconvert,
      "sink");

  data->link_probe_id = gst_pad_add_probe (data->videoconvert_sink_pad,
      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BLOCK,
      (GstPadProbeCallback) link_to_videomixer,
      KMS_ALPHA_BLENDING_REF (data), (GDestroyNotify) kms_ref_struct_unref);

  return data;
}
static KmsSelectableMixerPortData *
kms_selectable_mixer_port_data_create (KmsSelectableMixer * self, gint id)
{
  KmsSelectableMixerPortData *data = g_slice_new0 (KmsSelectableMixerPortData);

  data->mixer = self;
  data->audiomixer = gst_element_factory_make ("audiomixerbin", NULL);
  data->audio_agnostic = gst_element_factory_make ("agnosticbin", NULL);
  data->video_agnostic = gst_element_factory_make ("agnosticbin", NULL);
  data->id = id;

  gst_bin_add_many (GST_BIN (self), g_object_ref (data->audio_agnostic),
      g_object_ref (data->video_agnostic), data->audiomixer, NULL);

  gst_element_sync_state_with_parent (data->audio_agnostic);
  gst_element_sync_state_with_parent (data->video_agnostic);
  gst_element_sync_state_with_parent (data->audiomixer);

  kms_base_hub_link_video_sink (KMS_BASE_HUB (self), id, data->video_agnostic,
      "sink", FALSE);
  kms_base_hub_link_audio_sink (KMS_BASE_HUB (self), id, data->audio_agnostic,
      "sink", FALSE);
  kms_base_hub_link_audio_src (KMS_BASE_HUB (self), id, data->audiomixer,
      "src", FALSE);

  return data;
}
Esempio n. 3
0
static KmsCompositeMixerData *
kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id)
{
  KmsCompositeMixerData *data;
  gchar *padname;
  GstCaps *filtercaps;

  data = kms_create_composite_mixer_data ();
  data->mixer = mixer;
  data->id = id;
  data->input = FALSE;
  data->removing = FALSE;
  data->eos_managed = FALSE;

  data->videoconvert = gst_element_factory_make ("videoconvert", NULL);
  data->input_capsfilter = gst_element_factory_make ("capsfilter", NULL);

  filtercaps =
      gst_caps_new_simple ("video/x-raw", "format", G_TYPE_STRING, "AYUV",
      "width", G_TYPE_INT, mixer->priv->output_width,
      "height", G_TYPE_INT, mixer->priv->output_height,
      "framerate", GST_TYPE_FRACTION, 15, 1, NULL);
  g_object_set (G_OBJECT (data->input_capsfilter), "caps", filtercaps, NULL);
  gst_caps_unref (filtercaps);

  gst_bin_add_many (GST_BIN (mixer), data->input_capsfilter, data->videoconvert,
      NULL);

  gst_element_sync_state_with_parent (data->videoconvert);
  gst_element_sync_state_with_parent (data->input_capsfilter);

  /*link basemixer -> video_agnostic */
  kms_base_hub_link_video_sink (KMS_BASE_HUB (mixer), data->id,
      data->input_capsfilter, "sink", FALSE);

  gst_element_link (data->input_capsfilter, data->videoconvert);

  padname = g_strdup_printf (AUDIO_SINK_PAD, id);
  kms_base_hub_link_audio_sink (KMS_BASE_HUB (mixer), id,
      mixer->priv->audiomixer, padname, FALSE);
  g_free (padname);

  data->videoconvert_sink_pad = gst_element_get_static_pad (data->videoconvert,
      "sink");

  data->link_probe_id = gst_pad_add_probe (data->videoconvert_sink_pad,
      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BLOCK,
      (GstPadProbeCallback) link_to_videomixer,
      KMS_COMPOSITE_MIXER_REF (data), (GDestroyNotify) kms_ref_struct_unref);

  return data;
}
Esempio n. 4
0
static gint
kms_alpha_blending_handle_port (KmsBaseHub * mixer,
    GstElement * mixer_end_point)
{
  KmsAlphaBlending *self = KMS_ALPHA_BLENDING (mixer);
  KmsAlphaBlendingData *port_data;
  gint port_id;

  port_id = KMS_BASE_HUB_CLASS (G_OBJECT_CLASS
      (kms_alpha_blending_parent_class))->handle_port (mixer, mixer_end_point);

  if (port_id < 0) {
    return port_id;
  }

  KMS_ALPHA_BLENDING_LOCK (self);

  if (self->priv->videomixer == NULL) {
    GstElement *videorate_mixer;

    videorate_mixer = gst_element_factory_make ("videorate", NULL);
    self->priv->videomixer = gst_element_factory_make ("compositor", NULL);
    g_object_set (G_OBJECT (self->priv->videomixer), "background", 1, NULL);
    self->priv->mixer_video_agnostic =
        gst_element_factory_make ("agnosticbin", NULL);

    gst_bin_add_many (GST_BIN (mixer), self->priv->videomixer, videorate_mixer,
        self->priv->mixer_video_agnostic, NULL);

    gst_element_sync_state_with_parent (self->priv->videomixer);
    gst_element_sync_state_with_parent (videorate_mixer);
    gst_element_sync_state_with_parent (self->priv->mixer_video_agnostic);

    gst_element_link_many (self->priv->videomixer, videorate_mixer,
        self->priv->mixer_video_agnostic, NULL);
  }

  if (self->priv->audiomixer == NULL) {
    self->priv->audiomixer = gst_element_factory_make ("kmsaudiomixer", NULL);

    gst_bin_add (GST_BIN (mixer), self->priv->audiomixer);

    gst_element_sync_state_with_parent (self->priv->audiomixer);
    g_signal_connect (self->priv->audiomixer, "pad-added",
        G_CALLBACK (pad_added_cb), self);
    g_signal_connect (self->priv->audiomixer, "pad-removed",
        G_CALLBACK (pad_removed_cb), self);
  }

  kms_base_hub_link_video_src (KMS_BASE_HUB (self), port_id,
      self->priv->mixer_video_agnostic, "src_%u", TRUE);

  port_data = kms_alpha_blending_port_data_create (self, port_id);

  g_hash_table_insert (self->priv->ports, GINT_TO_POINTER (port_id), port_data);

  KMS_ALPHA_BLENDING_UNLOCK (self);

  return port_id;
}
static gboolean
kms_selectable_mixer_connect_video (KmsSelectableMixer * self, guint source,
    guint sink)
{
  KmsSelectableMixerPortData *source_port, *sink_port;
  gboolean connected = FALSE;

  KMS_SELECTABLE_MIXER_LOCK (self);

  source_port = g_hash_table_lookup (self->priv->ports, &source);
  if (source_port == NULL) {
    GST_ERROR_OBJECT (self, "No source port %u found", source);
    goto end;
  }

  sink_port = g_hash_table_lookup (self->priv->ports, &sink);
  if (sink_port == NULL) {
    GST_ERROR_OBJECT (self, "No sink port %u found", source);
    goto end;
  }

  if (!(connected =
          kms_base_hub_link_video_src (KMS_BASE_HUB (self), sink_port->id,
              source_port->video_agnostic, "src_%u", TRUE))) {
    GST_ERROR_OBJECT (self, "Can not connect video port");
  }

end:

  KMS_SELECTABLE_MIXER_UNLOCK (self);
  return connected;
}
Esempio n. 6
0
static gboolean
remove_elements_from_pipeline (KmsAlphaBlendingData * port_data)
{
  KmsAlphaBlending *self = port_data->mixer;
  GstElement *videoconvert, *videoscale, *videorate, *capsfilter, *queue,
      *videobox;

  KMS_ALPHA_BLENDING_LOCK (self);

  videobox = port_data->videobox;
  gst_element_unlink (videobox, self->priv->videomixer);

  if (port_data->video_mixer_pad != NULL) {
    gst_element_release_request_pad (self->priv->videomixer,
        port_data->video_mixer_pad);
    g_object_unref (port_data->video_mixer_pad);
    port_data->video_mixer_pad = NULL;
  }

  videoconvert = g_object_ref (port_data->videoconvert);
  videorate = g_object_ref (port_data->videorate);
  queue = g_object_ref (port_data->queue);
  videoscale = g_object_ref (port_data->videoscale);
  capsfilter = g_object_ref (port_data->capsfilter);
  g_object_ref (videobox);

  g_object_unref (port_data->videoconvert_sink_pad);

  port_data->videoconvert_sink_pad = NULL;
  port_data->videoconvert = NULL;
  port_data->videorate = NULL;
  port_data->queue = NULL;
  port_data->videoscale = NULL;
  port_data->capsfilter = NULL;
  port_data->videobox = NULL;

  gst_bin_remove_many (GST_BIN (self), videoconvert, videoscale, capsfilter,
      videorate, queue, videobox, NULL);

  kms_base_hub_unlink_video_src (KMS_BASE_HUB (self), port_data->id);

  KMS_ALPHA_BLENDING_UNLOCK (self);

  gst_element_set_state (videoconvert, GST_STATE_NULL);
  gst_element_set_state (videoscale, GST_STATE_NULL);
  gst_element_set_state (videorate, GST_STATE_NULL);
  gst_element_set_state (capsfilter, GST_STATE_NULL);
  gst_element_set_state (queue, GST_STATE_NULL);
  gst_element_set_state (videobox, GST_STATE_NULL);

  g_object_unref (videoconvert);
  g_object_unref (videoscale);
  g_object_unref (videorate);
  g_object_unref (capsfilter);
  g_object_unref (queue);
  g_object_unref (videobox);

  return G_SOURCE_REMOVE;
}
Esempio n. 7
0
static gboolean
remove_elements_from_pipeline (KmsCompositeMixerData * port_data)
{
  KmsCompositeMixer *self = port_data->mixer;

  KMS_COMPOSITE_MIXER_LOCK (self);

  gst_element_unlink (port_data->capsfilter, self->priv->videomixer);

  if (port_data->video_mixer_pad != NULL) {
    gst_element_release_request_pad (self->priv->videomixer,
        port_data->video_mixer_pad);
    g_object_unref (port_data->video_mixer_pad);
    port_data->video_mixer_pad = NULL;
  }

  g_object_unref (port_data->videoconvert_sink_pad);

  gst_bin_remove_many (GST_BIN (self),
      g_object_ref (port_data->input_capsfilter),
      g_object_ref (port_data->videoconvert),
      g_object_ref (port_data->videoscale),
      g_object_ref (port_data->capsfilter), g_object_ref (port_data->videorate),
      g_object_ref (port_data->queue), NULL);

  kms_base_hub_unlink_video_src (KMS_BASE_HUB (self), port_data->id);

  KMS_COMPOSITE_MIXER_UNLOCK (self);

  gst_element_set_state (port_data->input_capsfilter, GST_STATE_NULL);
  gst_element_set_state (port_data->videoconvert, GST_STATE_NULL);
  gst_element_set_state (port_data->videoscale, GST_STATE_NULL);
  gst_element_set_state (port_data->videorate, GST_STATE_NULL);
  gst_element_set_state (port_data->capsfilter, GST_STATE_NULL);
  gst_element_set_state (port_data->queue, GST_STATE_NULL);

  g_object_unref (port_data->input_capsfilter);
  g_object_unref (port_data->videoconvert);
  g_object_unref (port_data->videoscale);
  g_object_unref (port_data->videorate);
  g_object_unref (port_data->capsfilter);
  g_object_unref (port_data->queue);

  port_data->videoconvert_sink_pad = NULL;
  port_data->input_capsfilter = NULL;
  port_data->videoconvert = NULL;
  port_data->videoscale = NULL;
  port_data->capsfilter = NULL;
  port_data->videorate = NULL;
  port_data->queue = NULL;

  return G_SOURCE_REMOVE;
}
Esempio n. 8
0
static gboolean
kms_dispatcher_connect (KmsDispatcher * self, guint source, guint sink)
{
  KmsDispatcherPortData *source_port, *sink_port;
  gboolean connected = FALSE;

  KMS_DISPATCHER_LOCK (self);

  source_port = g_hash_table_lookup (self->priv->ports, &source);
  if (source_port == NULL) {
    GST_ERROR_OBJECT (self, "No source port %u found", source);
    goto end;
  }

  sink_port = g_hash_table_lookup (self->priv->ports, &sink);
  if (sink_port == NULL) {
    GST_ERROR_OBJECT (self, "No sink port %u found", source);
    goto end;
  }

  if (!kms_base_hub_link_audio_src (KMS_BASE_HUB (self), sink_port->id,
          source_port->audio_agnostic, "src_%u", TRUE)) {
    GST_ERROR_OBJECT (self, "Can not connect audio port");
    goto end;
  }

  if (!kms_base_hub_link_video_src (KMS_BASE_HUB (self), sink_port->id,
          source_port->video_agnostic, "src_%u", TRUE)) {
    GST_ERROR_OBJECT (self, "Can not connect video port");
    kms_base_hub_unlink_audio_src (KMS_BASE_HUB (self), sink_port->id);
    goto end;
  }

  connected = TRUE;

end:

  KMS_DISPATCHER_UNLOCK (self);
  return connected;
}
Esempio n. 9
0
static void
kms_base_hub_dispose (GObject * object)
{
  KmsBaseHub *self = KMS_BASE_HUB (object);

  GST_DEBUG_OBJECT (self, "dispose");

  KMS_BASE_HUB_LOCK (self);
  g_hash_table_remove_all (self->priv->ports);
  KMS_BASE_HUB_UNLOCK (self);

  G_OBJECT_CLASS (kms_base_hub_parent_class)->dispose (object);
}
Esempio n. 10
0
static void
kms_base_hub_finalize (GObject * object)
{
  KmsBaseHub *self = KMS_BASE_HUB (object);

  GST_DEBUG_OBJECT (self, "finalize");

  g_rec_mutex_clear (&self->priv->mutex);

  if (self->priv->ports != NULL) {
    g_hash_table_unref (self->priv->ports);
    self->priv->ports = NULL;
  }

  G_OBJECT_CLASS (kms_base_hub_parent_class)->finalize (object);
}
Esempio n. 11
0
static gboolean
remove_elements_from_pipeline (KmsCompositeMixerData * port_data)
{
  KmsCompositeMixer *self = port_data->mixer;

  KMS_COMPOSITE_MIXER_LOCK (self);

  gst_element_unlink (port_data->capsfilter, self->priv->videomixer);

  if (port_data->latency_probe_id > 0) {
    gst_pad_remove_probe (port_data->video_mixer_pad,
        port_data->latency_probe_id);
    port_data->latency_probe_id = 0;
  }

  if (port_data->video_mixer_pad != NULL) {
    gst_element_release_request_pad (self->priv->videomixer,
        port_data->video_mixer_pad);
    g_object_unref (port_data->video_mixer_pad);
    port_data->video_mixer_pad = NULL;
  }

  gst_bin_remove_many (GST_BIN (self),
      g_object_ref (port_data->capsfilter),
      g_object_ref (port_data->tee), g_object_ref (port_data->fakesink), NULL);

  kms_base_hub_unlink_video_src (KMS_BASE_HUB (self), port_data->id);

  KMS_COMPOSITE_MIXER_UNLOCK (self);

  gst_element_set_state (port_data->capsfilter, GST_STATE_NULL);
  gst_element_set_state (port_data->tee, GST_STATE_NULL);
  gst_element_set_state (port_data->fakesink, GST_STATE_NULL);

  g_object_unref (port_data->capsfilter);
  g_object_unref (port_data->tee);
  g_object_unref (port_data->fakesink);
  g_object_unref (port_data->tee_sink_pad);

  port_data->tee_sink_pad = NULL;
  port_data->capsfilter = NULL;
  port_data->tee = NULL;
  port_data->fakesink = NULL;

  return G_SOURCE_REMOVE;
}
Esempio n. 12
0
static void
pad_added_cb (GstElement * element, GstPad * pad, gpointer data)
{
  gint id;
  KmsAlphaBlending *self = KMS_ALPHA_BLENDING (data);

  if (gst_pad_get_direction (pad) != GST_PAD_SRC)
    return;

  id = get_stream_id_from_padname (GST_OBJECT_NAME (pad));

  if (id < 0) {
    GST_ERROR_OBJECT (self, "Invalid HubPort for %" GST_PTR_FORMAT, pad);
    return;
  }

  kms_base_hub_link_audio_src (KMS_BASE_HUB (self), id,
      self->priv->audiomixer, GST_OBJECT_NAME (pad), TRUE);
}
Esempio n. 13
0
static void
kms_alpha_blending_port_data_destroy (KmsAlphaBlendingData * port_data)
{
  KmsAlphaBlending *self = port_data->mixer;
  GstPad *audiosink;
  gchar *padname;

  KMS_ALPHA_BLENDING_LOCK (self);

  port_data->removing = TRUE;

  kms_base_hub_unlink_video_sink (KMS_BASE_HUB (self), port_data->id);
  kms_base_hub_unlink_audio_sink (KMS_BASE_HUB (self), port_data->id);

  if (port_data->input) {
    GstEvent *event;
    gboolean result;
    GstPad *pad;

    if (port_data->videorate == NULL) {
      KMS_ALPHA_BLENDING_UNLOCK (self);
      return;
    }

    pad = gst_element_get_static_pad (port_data->videorate, "sink");

    if (pad == NULL) {
      KMS_ALPHA_BLENDING_UNLOCK (self);
      return;
    }

    if (!GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS)) {

      event = gst_event_new_eos ();
      result = gst_pad_send_event (pad, event);

      if (port_data->input && self->priv->n_elems > 0) {
        port_data->input = FALSE;
        self->priv->n_elems--;
      }

      if (!result) {
        GST_WARNING ("EOS event did not send");
      }

      gst_element_unlink (port_data->videoconvert, port_data->videorate);
      g_object_unref (pad);

      KMS_ALPHA_BLENDING_UNLOCK (self);
    } else {
      gboolean remove = FALSE;

      /* EOS callback was triggered before we could remove the port data */
      /* so we have to remove elements to avoid memory leaks. */
      remove = port_data->eos_managed;

      gst_element_unlink (port_data->videoconvert, port_data->videorate);
      g_object_unref (pad);

      KMS_ALPHA_BLENDING_UNLOCK (self);

      if (remove) {
        /* Remove pipeline without helding the mutex */
        kms_loop_idle_add_full (self->priv->loop, G_PRIORITY_DEFAULT,
            (GSourceFunc) remove_elements_from_pipeline,
            KMS_ALPHA_BLENDING_REF (port_data),
            (GDestroyNotify) kms_ref_struct_unref);
      }
    }
  } else {
    GstElement *videoconvert;

    videoconvert = g_object_ref (port_data->videoconvert);
    port_data->videoconvert = NULL;

    if (port_data->probe_id > 0) {
      gst_pad_remove_probe (port_data->video_mixer_pad, port_data->probe_id);
    }

    if (port_data->link_probe_id > 0) {
      gst_pad_remove_probe (port_data->videoconvert_sink_pad,
          port_data->link_probe_id);
    }
    KMS_ALPHA_BLENDING_UNLOCK (self);

    gst_bin_remove (GST_BIN (self), videoconvert);
    gst_element_set_state (videoconvert, GST_STATE_NULL);
    g_object_unref (videoconvert);
  }

  padname = g_strdup_printf (AUDIO_SINK_PAD, port_data->id);
  audiosink = gst_element_get_static_pad (self->priv->audiomixer, padname);

  gst_element_release_request_pad (self->priv->audiomixer, audiosink);

  gst_object_unref (audiosink);
  g_free (padname);

  KMS_ALPHA_BLENDING_UNREF (port_data);
}
Esempio n. 14
0
static gint
kms_composite_mixer_handle_port (KmsBaseHub * mixer,
    GstElement * mixer_end_point)
{
  KmsCompositeMixer *self = KMS_COMPOSITE_MIXER (mixer);
  KmsCompositeMixerData *port_data;
  gint port_id;

  GST_DEBUG ("handle new port");
  port_id = KMS_BASE_HUB_CLASS (G_OBJECT_CLASS
      (kms_composite_mixer_parent_class))->handle_port (mixer, mixer_end_point);

  if (port_id < 0) {
    return port_id;
  }

  KMS_COMPOSITE_MIXER_LOCK (self);

  if (self->priv->videomixer == NULL) {
    self->priv->videomixer = gst_element_factory_make ("compositor", NULL);
    g_object_set (G_OBJECT (self->priv->videomixer), "background",
        1 /*black */ , "start-time-selection", 1 /*first */ ,
        "latency", LATENCY * GST_MSECOND, NULL);
    self->priv->mixer_video_agnostic =
        gst_element_factory_make ("agnosticbin", NULL);

    gst_bin_add_many (GST_BIN (mixer), self->priv->videomixer,
        self->priv->mixer_video_agnostic, NULL);

    if (self->priv->videotestsrc == NULL) {
      GstElement *capsfilter;
      GstCaps *filtercaps;
      GstPad *pad;
      GstPadTemplate *sink_pad_template;

      sink_pad_template =
          gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS
          (self->priv->videomixer), "sink_%u");

      if (G_UNLIKELY (sink_pad_template == NULL)) {
        GST_ERROR_OBJECT (self, "Error taking a new pad from videomixer");
      }

      self->priv->videotestsrc =
          gst_element_factory_make ("videotestsrc", NULL);
      capsfilter = gst_element_factory_make ("capsfilter", NULL);
      g_object_set (G_OBJECT (capsfilter), "caps-change-mode", 1, NULL);

      g_object_set (self->priv->videotestsrc, "is-live", TRUE, "pattern",
          /*black */ 2, NULL);

      filtercaps =
          gst_caps_new_simple ("video/x-raw",
          "width", G_TYPE_INT, self->priv->output_width,
          "height", G_TYPE_INT, self->priv->output_height,
          "framerate", GST_TYPE_FRACTION, 15, 1, NULL);
      g_object_set (G_OBJECT (capsfilter), "caps", filtercaps, NULL);
      gst_caps_unref (filtercaps);

      gst_bin_add_many (GST_BIN (self), self->priv->videotestsrc,
          capsfilter, NULL);

      gst_element_link (self->priv->videotestsrc, capsfilter);

      /*link capsfilter -> videomixer */
      pad = gst_element_request_pad (self->priv->videomixer, sink_pad_template,
          NULL, NULL);

      gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_QUERY_UPSTREAM,
          (GstPadProbeCallback) cb_latency, NULL, NULL);

      gst_element_link_pads (capsfilter, NULL,
          self->priv->videomixer, GST_OBJECT_NAME (pad));
      g_object_set (pad, "xpos", 0, "ypos", 0, "alpha", 0.0, NULL);
      g_object_unref (pad);

      gst_element_sync_state_with_parent (capsfilter);
      gst_element_sync_state_with_parent (self->priv->videotestsrc);
    }
    gst_element_sync_state_with_parent (self->priv->videomixer);
    gst_element_sync_state_with_parent (self->priv->mixer_video_agnostic);

    gst_element_link (self->priv->videomixer, self->priv->mixer_video_agnostic);
  }

  if (self->priv->audiomixer == NULL) {
    self->priv->audiomixer = gst_element_factory_make ("kmsaudiomixer", NULL);

    gst_bin_add (GST_BIN (mixer), self->priv->audiomixer);

    gst_element_sync_state_with_parent (self->priv->audiomixer);
    g_signal_connect (self->priv->audiomixer, "pad-added",
        G_CALLBACK (pad_added_cb), self);
    g_signal_connect (self->priv->audiomixer, "pad-removed",
        G_CALLBACK (pad_removed_cb), self);
  }
  kms_base_hub_link_video_src (KMS_BASE_HUB (self), port_id,
      self->priv->mixer_video_agnostic, "src_%u", TRUE);

  port_data = kms_composite_mixer_port_data_create (self, port_id);
  g_hash_table_insert (self->priv->ports, create_gint (port_id), port_data);

  KMS_COMPOSITE_MIXER_UNLOCK (self);

  return port_id;
}
Esempio n. 15
0
static KmsCompositeMixerData *
kms_composite_mixer_port_data_create (KmsCompositeMixer * mixer, gint id)
{
  KmsCompositeMixerData *data;
  gchar *padname;
  GstPad *tee_src;
  GstCaps *filtercaps;

  data = kms_create_composite_mixer_data ();
  data->mixer = mixer;
  data->id = id;
  data->input = FALSE;
  data->removing = FALSE;
  data->eos_managed = FALSE;

  data->tee = gst_element_factory_make ("tee", NULL);
  data->fakesink = gst_element_factory_make ("fakesink", NULL);
  data->capsfilter = gst_element_factory_make ("capsfilter", NULL);

  g_object_set (G_OBJECT (data->capsfilter), "caps-change-mode",
      1 /*delayed */ , NULL);

  g_object_set (G_OBJECT (data->fakesink), "async", FALSE, "sync", FALSE, NULL);

  gst_bin_add_many (GST_BIN (mixer), data->capsfilter, data->tee,
      data->fakesink, NULL);

  gst_element_sync_state_with_parent (data->capsfilter);
  gst_element_sync_state_with_parent (data->tee);
  gst_element_sync_state_with_parent (data->fakesink);

  filtercaps =
      gst_caps_new_simple ("video/x-raw",
      "width", G_TYPE_INT, mixer->priv->output_width,
      "height", G_TYPE_INT, mixer->priv->output_height,
      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
  g_object_set (data->capsfilter, "caps", filtercaps, NULL);
  gst_caps_unref (filtercaps);

  /*link basemixer -> video_agnostic */
  kms_base_hub_link_video_sink (KMS_BASE_HUB (mixer), data->id,
      data->capsfilter, "sink", FALSE);

  data->tee_sink_pad = gst_element_get_static_pad (data->tee, "sink");
  gst_element_link_pads (data->capsfilter, NULL, data->tee,
      GST_OBJECT_NAME (data->tee_sink_pad));

  tee_src = gst_element_get_request_pad (data->tee, "src_%u");
  gst_element_link_pads (data->tee, GST_OBJECT_NAME (tee_src), data->fakesink,
      "sink");
  g_object_unref (tee_src);

  padname = g_strdup_printf (AUDIO_SINK_PAD, id);
  kms_base_hub_link_audio_sink (KMS_BASE_HUB (mixer), id,
      mixer->priv->audiomixer, padname, FALSE);
  g_free (padname);

  data->link_probe_id = gst_pad_add_probe (data->tee_sink_pad,
      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BLOCK,
      (GstPadProbeCallback) link_to_videomixer,
      KMS_COMPOSITE_MIXER_REF (data), (GDestroyNotify) kms_ref_struct_unref);

  return data;
}
Esempio n. 16
0
static void
kms_composite_mixer_port_data_destroy (gpointer data)
{
  KmsCompositeMixerData *port_data = (KmsCompositeMixerData *) data;
  KmsCompositeMixer *self = port_data->mixer;
  GstPad *audiosink;
  gchar *padname;

  KMS_COMPOSITE_MIXER_LOCK (self);

  port_data->removing = TRUE;

  kms_base_hub_unlink_video_sink (KMS_BASE_HUB (self), port_data->id);
  kms_base_hub_unlink_audio_sink (KMS_BASE_HUB (self), port_data->id);

  if (port_data->input) {
    GstEvent *event;
    gboolean result;
    GstPad *pad;

    if (port_data->capsfilter == NULL) {
      KMS_COMPOSITE_MIXER_UNLOCK (self);
      return;
    }

    pad = gst_element_get_static_pad (port_data->capsfilter, "sink");

    if (pad == NULL) {
      KMS_COMPOSITE_MIXER_UNLOCK (self);
      return;
    }

    if (!GST_OBJECT_FLAG_IS_SET (pad, GST_PAD_FLAG_EOS)) {

      if (GST_PAD_IS_FLUSHING (pad)) {
        gst_pad_send_event (pad, gst_event_new_flush_stop (FALSE));
      }

      event = gst_event_new_eos ();
      result = gst_pad_send_event (pad, event);

      if (port_data->input && self->priv->n_elems > 0) {
        port_data->input = FALSE;
        self->priv->n_elems--;
        kms_composite_mixer_recalculate_sizes (self);
      }
      KMS_COMPOSITE_MIXER_UNLOCK (self);

      if (!result) {
        GST_WARNING ("EOS event did not send");
      }
    } else {
      gboolean remove = FALSE;

      /* EOS callback was triggered before we could remove the port data */
      /* so we have to remove elements to avoid memory leaks. */
      remove = port_data->eos_managed;
      KMS_COMPOSITE_MIXER_UNLOCK (self);

      if (remove) {
        /* Remove pipeline without helding the mutex */
        kms_loop_idle_add_full (self->priv->loop, G_PRIORITY_DEFAULT,
            (GSourceFunc) remove_elements_from_pipeline,
            KMS_COMPOSITE_MIXER_REF (port_data),
            (GDestroyNotify) kms_ref_struct_unref);
      }
    }
    gst_element_unlink (port_data->capsfilter, port_data->tee);
    g_object_unref (pad);
  } else {
    if (port_data->probe_id > 0) {
      gst_pad_remove_probe (port_data->video_mixer_pad, port_data->probe_id);
    }

    if (port_data->latency_probe_id > 0) {
      gst_pad_remove_probe (port_data->video_mixer_pad,
          port_data->latency_probe_id);
    }

    if (port_data->link_probe_id > 0) {
      gst_pad_remove_probe (port_data->tee_sink_pad, port_data->link_probe_id);
    }
    KMS_COMPOSITE_MIXER_UNLOCK (self);

    gst_element_unlink (port_data->capsfilter, port_data->tee);
    gst_element_unlink (port_data->tee, port_data->fakesink);

    gst_bin_remove (GST_BIN (self), g_object_ref (port_data->capsfilter));
    gst_element_set_state (port_data->capsfilter, GST_STATE_NULL);
    g_object_unref (port_data->capsfilter);
    port_data->capsfilter = NULL;

    gst_bin_remove (GST_BIN (self), g_object_ref (port_data->tee));
    gst_element_set_state (port_data->tee, GST_STATE_NULL);
    g_object_unref (port_data->tee);
    port_data->tee = NULL;

    gst_bin_remove (GST_BIN (self), g_object_ref (port_data->fakesink));
    gst_element_set_state (port_data->fakesink, GST_STATE_NULL);
    g_object_unref (port_data->fakesink);
    port_data->fakesink = NULL;
  }

  padname = g_strdup_printf (AUDIO_SINK_PAD, port_data->id);
  audiosink = gst_element_get_static_pad (self->priv->audiomixer, padname);
  gst_element_release_request_pad (self->priv->audiomixer, audiosink);
  gst_object_unref (audiosink);
  g_free (padname);
}