Esempio n. 1
0
static GstBin *
kms_agnostic_bin2_create_dec_bin (KmsAgnosticBin2 * self,
    const GstCaps * raw_caps)
{
  KmsDecTreeBin *dec_bin;
  GstElement *output_tee, *input_element;
  GstCaps *caps = self->priv->input_bin_src_caps;

  if (caps == NULL || raw_caps == NULL) {
    return NULL;
  }

  dec_bin = kms_dec_tree_bin_new (caps, raw_caps);
  if (dec_bin == NULL) {
    return NULL;
  }

  gst_bin_add (GST_BIN (self), GST_ELEMENT (dec_bin));
  gst_element_sync_state_with_parent (GST_ELEMENT (dec_bin));

  output_tee =
      kms_tree_bin_get_output_tee (KMS_TREE_BIN (self->priv->input_bin));
  input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (dec_bin));
  link_element_to_tee (output_tee, input_element);

  return GST_BIN (dec_bin);
}
Esempio n. 2
0
static GstBin *
kms_agnostic_bin2_create_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps)
{
  GstBin *dec_bin;
  KmsEncTreeBin *enc_bin;
  GstElement *input_element, *output_tee;

  dec_bin = kms_agnostic_bin2_get_or_create_dec_bin (self, caps);
  if (dec_bin == NULL) {
    return NULL;
  }

  if (is_raw_caps (caps)) {
    return dec_bin;
  }

  enc_bin = kms_enc_tree_bin_new (caps, self->priv->default_bitrate);
  if (enc_bin == NULL) {
    return NULL;
  }

  gst_bin_add (GST_BIN (self), GST_ELEMENT (enc_bin));
  gst_element_sync_state_with_parent (GST_ELEMENT (enc_bin));

  output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (dec_bin));
  input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (enc_bin));
  link_element_to_tee (output_tee, input_element);

  kms_agnostic_bin2_insert_bin (self, GST_BIN (enc_bin));

  return GST_BIN (enc_bin);
}
Esempio n. 3
0
static GstBin *
kms_agnostic_bin2_find_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps)
{
  GList *bins, *l;
  GstBin *bin = NULL;

  if (gst_caps_is_any (caps) || gst_caps_is_empty (caps)) {
    return self->priv->input_bin;
  }

  if (check_bin (KMS_TREE_BIN (self->priv->input_bin), caps)) {
    bin = self->priv->input_bin;
  }

  bins = g_hash_table_get_values (self->priv->bins);
  for (l = bins; l != NULL && bin == NULL; l = l->next) {
    KmsTreeBin *tree_bin = KMS_TREE_BIN (l->data);

    if (check_bin (tree_bin, caps)) {
      bin = GST_BIN_CAST (tree_bin);
    }
  }
  g_list_free (bins);

  return bin;
}
Esempio n. 4
0
static GstBin *
kms_agnostic_bin2_create_rtp_pay_bin (KmsAgnosticBin2 * self, GstCaps * caps)
{
  KmsRtpPayTreeBin *bin;
  GstBin *enc_bin;
  GstElement *output_tee, *input_element;
  GstCaps *input_caps;
  GstPad *sink;

  bin = kms_rtp_pay_tree_bin_new (caps);

  if (bin == NULL) {
    return NULL;
  }

  gst_bin_add (GST_BIN (self), GST_ELEMENT (bin));
  gst_element_sync_state_with_parent (GST_ELEMENT (bin));

  input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (bin));
  sink = gst_element_get_static_pad (input_element, "sink");
  input_caps = gst_pad_query_caps (sink, NULL);
  g_object_unref (sink);

  enc_bin = kms_agnostic_bin2_find_or_create_bin_for_caps (self, input_caps);
  kms_agnostic_bin2_insert_bin (self, GST_BIN (bin));
  gst_caps_unref (input_caps);

  output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (enc_bin));
  gst_element_link (output_tee, input_element);

  return GST_BIN (bin);
}
Esempio n. 5
0
/**
 * Link a pad internally
 *
 * @self: The #KmsAgnosticBin2 owner of the pad
 * @pad: (transfer full): The pad to be linked
 * @peer: (transfer full): The peer pad
 */
static void
kms_agnostic_bin2_link_pad (KmsAgnosticBin2 * self, GstPad * pad, GstPad * peer)
{
  GstCaps *caps;
  GstBin *bin;

  GST_INFO_OBJECT (self, "Linking: %" GST_PTR_FORMAT, pad);

  caps = gst_pad_query_caps (peer, NULL);

  if (caps == NULL) {
    goto end;
  }

  GST_DEBUG ("Query caps are: %" GST_PTR_FORMAT, caps);
  bin = kms_agnostic_bin2_find_bin_for_caps (self, caps);

  if (bin == NULL) {
    bin = kms_agnostic_bin2_create_bin_for_caps (self, caps);
    GST_DEBUG_OBJECT (self, "Created bin: %" GST_PTR_FORMAT, bin);
  }

  if (bin != NULL) {
    GstElement *tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (bin));

    kms_utils_drop_until_keyframe (pad, TRUE);
    kms_agnostic_bin2_link_to_tee (self, pad, tee, caps);
  }

  gst_caps_unref (caps);

end:
  g_object_unref (peer);
}
Esempio n. 6
0
static gboolean
kms_rtp_pay_tree_bin_configure (KmsRtpPayTreeBin * self, const GstCaps * caps)
{
  KmsTreeBin *tree_bin = KMS_TREE_BIN (self);
  GstElement *pay, *output_tee;
  GstPad *pad;

  pay = create_payloader_for_caps (caps);
  if (pay == NULL) {
    GST_WARNING_OBJECT (self, "Cannot find payloader for caps %" GST_PTR_FORMAT,
        caps);
    return FALSE;
  }
  GST_DEBUG_OBJECT (self, "Payloader found: %" GST_PTR_FORMAT, pay);

  pad = gst_element_get_static_pad (pay, "sink");
  kms_utils_drop_until_keyframe (pad, TRUE);
  gst_object_unref (pad);

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

  kms_tree_bin_set_input_element (tree_bin, pay);
  output_tee = kms_tree_bin_get_output_tee (tree_bin);
  gst_element_link (pay, output_tee);

  return TRUE;
}
Esempio n. 7
0
static GstBin *
kms_agnostic_bin2_create_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps)
{
  GstBin *dec_bin;
  KmsEncTreeBin *enc_bin;
  GstElement *input_element, *output_tee;

  if (kms_utils_caps_are_rtp (caps)) {
    return kms_agnostic_bin2_create_rtp_pay_bin (self, caps);
  }

  dec_bin = kms_agnostic_bin2_get_or_create_dec_bin (self, caps);
  if (dec_bin == NULL) {
    return NULL;
  }

  if (kms_utils_caps_are_raw (caps)) {
    return dec_bin;
  }

  enc_bin =
      kms_enc_tree_bin_new (caps, TARGET_BITRATE_DEFAULT,
      self->priv->min_bitrate, self->priv->max_bitrate,
      self->priv->codec_config);
  if (enc_bin == NULL) {
    return NULL;
  }

  gst_bin_add (GST_BIN (self), GST_ELEMENT (enc_bin));
  gst_element_sync_state_with_parent (GST_ELEMENT (enc_bin));

  output_tee = kms_tree_bin_get_output_tee (KMS_TREE_BIN (dec_bin));
  input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (enc_bin));
  gst_element_link (output_tee, input_element);

  kms_agnostic_bin2_insert_bin (self, GST_BIN (enc_bin));

  return GST_BIN (enc_bin);
}
Esempio n. 8
0
static void
kms_agnostic_bin2_configure_input (KmsAgnosticBin2 * self, const GstCaps * caps)
{
  KmsParseTreeBin *parse_bin;
  GstElement *parser;
  GstPad *parser_src;
  GstElement *input_element;

  KMS_AGNOSTIC_BIN2_LOCK (self);

  if (self->priv->input_bin != NULL) {
    kms_tree_bin_unlink_input_element_from_tee (KMS_TREE_BIN (self->
            priv->input_bin));
  }

  parse_bin = kms_parse_tree_bin_new (caps);
  self->priv->input_bin = GST_BIN (parse_bin);

  parser = kms_parse_tree_bin_get_parser (KMS_PARSE_TREE_BIN (parse_bin));
  parser_src = gst_element_get_static_pad (parser, "src");
  gst_pad_add_probe (parser_src, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
      input_bin_src_caps_probe, g_object_ref (parse_bin), g_object_unref);
  g_object_unref (parser_src);

  gst_bin_add (GST_BIN (self), GST_ELEMENT (parse_bin));
  gst_element_sync_state_with_parent (GST_ELEMENT (parse_bin));

  input_element = kms_tree_bin_get_input_element (KMS_TREE_BIN (parse_bin));
  link_element_to_tee (self->priv->input_tee, input_element);

  self->priv->started = FALSE;

  GST_DEBUG ("Removing old treebins");
  g_hash_table_foreach (self->priv->bins, remove_bin, self);
  g_hash_table_remove_all (self->priv->bins);

  KMS_AGNOSTIC_BIN2_UNLOCK (self);
}
Esempio n. 9
0
static gboolean
tee_query_function (GstPad * pad, GstObject * parent, GstQuery * query)
{
  if (GST_QUERY_TYPE (query) == GST_QUERY_ACCEPT_CAPS) {
    GstCaps *caps;
    KmsTreeBin *self = KMS_TREE_BIN (GST_OBJECT_PARENT (parent));

    gst_query_parse_accept_caps (query, &caps);

    kms_tree_bin_set_input_caps (self, caps);
  }

  return gst_pad_query_default (pad, parent, query);
}
Esempio n. 10
0
static void
kms_parse_tree_bin_configure (KmsParseTreeBin * self, const GstCaps * caps)
{
  KmsTreeBin *tree_bin = KMS_TREE_BIN (self);
  GstElement *output_tee;

  self->priv->parser = create_parser_for_caps (caps);

  gst_bin_add (GST_BIN (self), self->priv->parser);
  gst_element_sync_state_with_parent (self->priv->parser);

  kms_tree_bin_set_input_element (tree_bin, self->priv->parser);
  output_tee = kms_tree_bin_get_output_tee (tree_bin);
  gst_element_link_many (self->priv->parser, output_tee, NULL);
}
Esempio n. 11
0
static gboolean
tee_event_function (GstPad * pad, GstObject * parent, GstEvent * event)
{
  if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) {
    GstCaps *caps;
    KmsTreeBin *self = KMS_TREE_BIN (GST_OBJECT_PARENT (parent));

    gst_event_parse_caps (event, &caps);

    kms_tree_bin_set_input_caps (self, caps);
  }

  gst_event_unref (event);

  /* Return TRUE so that next handler chained can manage this stuff too */
  return TRUE;
}
Esempio n. 12
0
static GstBin *
kms_agnostic_bin2_find_bin_for_caps (KmsAgnosticBin2 * self, GstCaps * caps)
{
  GList *bins, *l;
  GstBin *bin = NULL;

  if (gst_caps_is_any (caps)) {
    return self->priv->input_bin;
  }

  bins = g_hash_table_get_values (self->priv->bins);
  for (l = bins; l != NULL && bin == NULL; l = l->next) {
    GstElement *output_tee =
        kms_tree_bin_get_output_tee (KMS_TREE_BIN (l->data));
    GstPad *tee_sink = gst_element_get_static_pad (output_tee, "sink");
    GstCaps *current_caps = gst_pad_get_current_caps (tee_sink);

    if (current_caps == NULL) {
      current_caps = gst_pad_get_allowed_caps (tee_sink);
      GST_TRACE_OBJECT (l->data, "Allowed caps are: %" GST_PTR_FORMAT,
          current_caps);
    } else {
      GST_TRACE_OBJECT (l->data, "Current caps are: %" GST_PTR_FORMAT,
          current_caps);
    }

    if (current_caps != NULL) {
      if (gst_caps_can_intersect (caps, current_caps))
        bin = l->data;
      gst_caps_unref (current_caps);
    }

    g_object_unref (tee_sink);
  }
  g_list_free (bins);

  return bin;
}
Esempio n. 13
0
static gboolean
kms_enc_tree_bin_configure (KmsEncTreeBin * self, const GstCaps * caps,
    gint target_bitrate)
{
  KmsTreeBin *tree_bin = KMS_TREE_BIN (self);
  GstElement *rate, *convert, *mediator, *output_tee, *capsfilter = NULL;

  self->priv->current_bitrate = target_bitrate;

  kms_enc_tree_bin_create_encoder_for_caps (self, caps, target_bitrate);

  if (self->priv->enc == NULL) {
    GST_WARNING_OBJECT (self, "Invalid encoder for caps: %" GST_PTR_FORMAT,
        caps);
    return FALSE;
  }

  GST_DEBUG_OBJECT (self, "Encoder found: %" GST_PTR_FORMAT, self->priv->enc);

  self->priv->enc_sink = gst_element_get_static_pad (self->priv->enc, "sink");
  self->priv->remb_manager =
      kms_utils_remb_event_manager_create (self->priv->enc_sink);
  kms_utils_remb_event_manager_set_callback (self->priv->remb_manager,
      bitrate_callback, self, NULL);
  gst_pad_add_probe (self->priv->enc_sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
      tag_event_probe, self, NULL);

  rate = kms_utils_create_rate_for_caps (caps);
  convert = kms_utils_create_convert_for_caps (caps);
  mediator = kms_utils_create_mediator_element (caps);

  gst_bin_add_many (GST_BIN (self), rate, convert, mediator, self->priv->enc,
      NULL);
  gst_element_sync_state_with_parent (self->priv->enc);
  gst_element_sync_state_with_parent (mediator);
  gst_element_sync_state_with_parent (convert);
  gst_element_sync_state_with_parent (rate);
  // FIXME: This is a hack to avoid an error on x264enc that does not work
  // properly with some raw formats, this should be fixed in gstreamer
  // but until this is done this hack makes it work
  if (self->priv->enc_type == X264) {
    GstCaps *filter_caps = gst_caps_from_string ("video/x-raw,format=I420");
    GstPad *sink;

    capsfilter = gst_element_factory_make ("capsfilter", NULL);
    sink = gst_element_get_static_pad (capsfilter, "sink");
    gst_pad_add_probe (sink, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
        check_caps_probe, NULL, NULL);
    g_object_unref (sink);

    g_object_set (capsfilter, "caps", filter_caps, NULL);
    gst_caps_unref (filter_caps);

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

  kms_tree_bin_set_input_element (tree_bin, rate);
  output_tee = kms_tree_bin_get_output_tee (tree_bin);
  if (self->priv->enc_type == X264) {
    gst_element_link_many (rate, convert, mediator, capsfilter, self->priv->enc,
        output_tee, NULL);
  } else {
    gst_element_link_many (rate, convert, mediator, self->priv->enc, output_tee,
        NULL);
  }

  return TRUE;
}