示例#1
0
文件: util.c 项目: rodrimc/libmicromb
gboolean
set_video_bin(GstElement *bin, MbMedia *media, GstPad *decoder_src_pad)
{
  GstElement *sink_element = NULL;
  GstCaps *caps = NULL;
  GstPad *sink_pad = NULL, *ghost_pad = NULL, *output_sink_pad = NULL;
  GstPadLinkReturn ret;
  gchar *uri = NULL;
  gboolean is_image = FALSE;
  int return_code = TRUE;

  g_assert (media->video_scaler);
  g_assert (media->video_filter);

  gst_element_set_state(media->video_scaler, GST_STATE_PAUSED);
  gst_element_set_state(media->video_filter, GST_STATE_PAUSED);

  caps = gst_caps_new_simple ("video/x-raw",
      "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
      "width", G_TYPE_INT, media->width,
      "height", G_TYPE_INT, media->height,
      NULL);

  g_object_set (G_OBJECT (media->video_scaler), "add-borders", 0, NULL);
  g_object_set (G_OBJECT (media->video_filter), "caps", caps, NULL);

  gst_bin_add_many(GST_BIN (bin), media->video_scaler, media->video_filter,
      NULL);
  if (!gst_element_link (media->video_scaler, media->video_filter))
  {
    g_debug ("Could not link elements together.\n");
    gst_object_unref (media->video_scaler);
    gst_object_unref (media->video_filter);
    return FALSE;
  }

  sink_element = media->video_scaler;

  g_object_get (G_OBJECT(media->decoder), "uri", &uri, NULL);
  is_image = has_image_extension(uri);

  g_free (uri);

  if (is_image)
  {
    media->image_freezer = gst_element_factory_make("imagefreeze", NULL);
    g_assert (media->image_freezer);

    gst_bin_add (GST_BIN(bin), media->image_freezer);

    if (!gst_element_link (media->image_freezer, media->video_scaler))
    {
      g_debug("Could not link image element.\n");
      gst_object_unref(media->image_freezer);
      return FALSE;
    }

    gst_element_set_state(media->image_freezer, GST_STATE_PAUSED);
    sink_element = media->image_freezer;
  }

  sink_pad = gst_element_get_static_pad (sink_element, "sink");
  g_assert(sink_pad);
  ret = gst_pad_link (decoder_src_pad, sink_pad);

  if (GST_PAD_LINK_FAILED(ret))
    g_debug (" Link failed.\n");
  else
    g_debug (" Link succeeded.\n");

  ghost_pad = gst_ghost_pad_new (
      "v_src", gst_element_get_static_pad (media->video_filter, "src"));

  gst_pad_set_active (ghost_pad, TRUE);
  gst_element_add_pad (bin, ghost_pad);

  output_sink_pad = gst_element_get_request_pad(_mb_global_data.video_mixer,
      "sink_%u");
  g_assert (output_sink_pad);

  media->video_pad_name = gst_pad_get_name (output_sink_pad);
  g_debug ("videomixer: new pad requested (%s)\n", media->video_pad_name);

  ret = gst_pad_link (ghost_pad, output_sink_pad);
  if (GST_PAD_LINK_FAILED(ret))
  {
    return_code = FALSE;
    g_debug (" Could not link %s and videomixer together\n", media->name);
  }
  else
  {
    g_object_set (output_sink_pad, "xpos", media->x_pos, NULL);
    g_object_set (output_sink_pad, "ypos", media->y_pos, NULL);
    g_object_set (output_sink_pad, "zorder", media->z_index, NULL);
    g_object_set (output_sink_pad, "alpha", media->alpha, NULL);

    g_debug (" Link succeeded between %s and videomixer.\n", media->name);
  }

  if (is_image)
    gst_element_set_state(media->image_freezer, GST_STATE_PLAYING);

  gst_element_set_state (media->video_scaler, GST_STATE_PLAYING);
  gst_element_set_state (media->video_filter, GST_STATE_PLAYING);

  gst_caps_unref(caps);
  gst_object_unref (output_sink_pad);
  gst_object_unref(sink_pad);

  return return_code;
}
示例#2
0
static GstFlowReturn
gst_cc_extractor_handle_meta (GstCCExtractor * filter, GstBuffer * buf,
    GstVideoCaptionMeta * meta)
{
  GstBuffer *outbuf = NULL;
  GstEvent *event;
  gchar *captionid;
  GstFlowReturn flow;

  GST_DEBUG_OBJECT (filter, "Handling meta");

  /* Check if the meta type matches the configured one */
  if (filter->captionpad != NULL && meta->caption_type != filter->caption_type) {
    GST_ERROR_OBJECT (filter,
        "GstVideoCaptionMeta type changed, Not handled currently");
    flow = GST_FLOW_NOT_NEGOTIATED;
    goto out;
  }

  if (filter->captionpad == NULL) {
    GstCaps *caption_caps = NULL;
    GstEvent *stream_event;

    GST_DEBUG_OBJECT (filter, "Creating new caption pad");
    switch (meta->caption_type) {
      case GST_VIDEO_CAPTION_TYPE_CEA608_RAW:
        caption_caps =
            gst_caps_from_string ("closedcaption/x-cea-608,format=(string)raw");
        break;
      case GST_VIDEO_CAPTION_TYPE_CEA608_IN_CEA708_RAW:
        caption_caps =
            gst_caps_from_string
            ("closedcaption/x-cea-608,format=(string)cc_data");
        break;
      case GST_VIDEO_CAPTION_TYPE_CEA708_RAW:
        caption_caps =
            gst_caps_from_string
            ("closedcaption/x-cea-708,format=(string)cc_data");
        break;
      case GST_VIDEO_CAPTION_TYPE_CEA708_CDP:
        caption_caps =
            gst_caps_from_string ("closedcaption/x-cea-708,format=(string)cdp");
        break;
      default:
        break;
    }
    if (caption_caps == NULL) {
      GST_ERROR_OBJECT (filter, "Unknown/invalid caption type");
      return GST_FLOW_NOT_NEGOTIATED;
    }

    /* Create the caption pad and set the caps */
    filter->captionpad =
        gst_pad_new_from_static_template (&captiontemplate, "caption");
    gst_pad_set_iterate_internal_links_function (filter->sinkpad,
        GST_DEBUG_FUNCPTR (gst_cc_extractor_iterate_internal_links));
    gst_pad_set_active (filter->captionpad, TRUE);
    gst_element_add_pad (GST_ELEMENT (filter), filter->captionpad);
    gst_flow_combiner_add_pad (filter->combiner, filter->captionpad);

    captionid =
        gst_pad_create_stream_id (filter->captionpad, (GstElement *) filter,
        "caption");
    stream_event = gst_event_new_stream_start (captionid);
    g_free (captionid);

    /* FIXME : Create a proper stream-id */
    if ((event =
            gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_STREAM_START,
                0))) {
      guint group_id;
      if (gst_event_parse_group_id (event, &group_id))
        gst_event_set_group_id (stream_event, group_id);
      gst_event_unref (event);
    }
    gst_pad_push_event (filter->captionpad, stream_event);
    gst_pad_set_caps (filter->captionpad, caption_caps);
    gst_caps_unref (caption_caps);

    /* Carry over sticky events */
    if ((event =
            gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_SEGMENT, 0)))
      gst_pad_push_event (filter->captionpad, event);
    if ((event = gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_TAG, 0)))
      gst_pad_push_event (filter->captionpad, event);


    filter->caption_type = meta->caption_type;
  }

  GST_DEBUG_OBJECT (filter,
      "Creating new buffer of size %" G_GSIZE_FORMAT " bytes", meta->size);
  /* Extract caption data into new buffer with identical buffer timestamps */
  outbuf = gst_buffer_new_allocate (NULL, meta->size, NULL);
  gst_buffer_fill (outbuf, 0, meta->data, meta->size);
  GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf);
  GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buf);
  GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);

  /* We don't really care about the flow return */
  flow = gst_pad_push (filter->captionpad, outbuf);

out:
  /* Set flow return on pad and return combined value */
  return gst_flow_combiner_update_pad_flow (filter->combiner,
      filter->captionpad, flow);
}
示例#3
0
/**
 * gst_collect_pads_remove_pad:
 * @pads: the collectspads to use
 * @pad: the pad to remove
 *
 * Remove a pad from the collection of collect pads. This function will also
 * free the #GstCollectData and all the resources that were allocated with 
 * gst_collect_pads_add_pad().
 *
 * The pad will be deactivated automatically when @pads is stopped.
 *
 * Returns: %TRUE if the pad could be removed.
 *
 * MT safe.
 */
gboolean
gst_collect_pads_remove_pad (GstCollectPads * pads, GstPad * pad)
{
  GstCollectData *data;
  GSList *list;

  g_return_val_if_fail (pads != NULL, FALSE);
  g_return_val_if_fail (GST_IS_COLLECT_PADS (pads), FALSE);
  g_return_val_if_fail (pad != NULL, FALSE);
  g_return_val_if_fail (GST_IS_PAD (pad), FALSE);

  GST_DEBUG ("removing pad %s:%s", GST_DEBUG_PAD_NAME (pad));

  GST_COLLECT_PADS_PAD_LOCK (pads);
  list =
      g_slist_find_custom (pads->abidata.ABI.pad_list, pad,
      (GCompareFunc) find_pad);
  if (!list)
    goto unknown_pad;

  data = (GstCollectData *) list->data;

  GST_DEBUG ("found pad %s:%s at %p", GST_DEBUG_PAD_NAME (pad), data);

  /* clear the stuff we configured */
  gst_pad_set_chain_function (pad, NULL);
  gst_pad_set_event_function (pad, NULL);
  GST_OBJECT_LOCK (pad);
  gst_pad_set_element_private (pad, NULL);
  GST_OBJECT_UNLOCK (pad);

  /* backward compat, also remove from data if stopped, note that this function
   * can only be called when we are stopped because we don't take the LOCK to
   * protect the pads->data list. */
  if (!pads->started) {
    GSList *dlist;

    dlist = g_slist_find_custom (pads->data, pad, (GCompareFunc) find_pad);
    if (dlist) {
      GstCollectData *pdata = dlist->data;

      pads->data = g_slist_delete_link (pads->data, dlist);
      unref_data (pdata);
    }
  }
  /* remove from the pad list */
  pads->abidata.ABI.pad_list =
      g_slist_delete_link (pads->abidata.ABI.pad_list, list);
  pads->abidata.ABI.pad_cookie++;

  /* signal waiters because something changed */
  GST_COLLECT_PADS_BROADCAST (pads);

  /* deactivate the pad when needed */
  if (!pads->started)
    gst_pad_set_active (pad, FALSE);

  /* clean and free the collect data */
  unref_data (data);

  GST_COLLECT_PADS_PAD_UNLOCK (pads);

  return TRUE;

unknown_pad:
  {
    GST_WARNING ("cannot remove unknown pad %s:%s", GST_DEBUG_PAD_NAME (pad));
    GST_COLLECT_PADS_PAD_UNLOCK (pads);
    return FALSE;
  }
}
示例#4
0
static GstFlowReturn
gst_rtp_pt_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstRtpPtDemux *rtpdemux;
  guint8 pt;
  GstPad *srcpad;
  GstCaps *caps;
  GstRTPBuffer rtp = { NULL };

  rtpdemux = GST_RTP_PT_DEMUX (parent);

  if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp))
    goto invalid_buffer;

  pt = gst_rtp_buffer_get_payload_type (&rtp);
  gst_rtp_buffer_unmap (&rtp);

  GST_DEBUG_OBJECT (rtpdemux, "received buffer for pt %d", pt);

  srcpad = find_pad_for_pt (rtpdemux, pt);
  if (srcpad == NULL) {
    /* new PT, create a src pad */
    GstRtpPtDemuxPad *rtpdemuxpad;
    GstElementClass *klass;
    GstPadTemplate *templ;
    gchar *padname;

    caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt);
    if (!caps)
      goto no_caps;

    klass = GST_ELEMENT_GET_CLASS (rtpdemux);
    templ = gst_element_class_get_pad_template (klass, "src_%u");
    padname = g_strdup_printf ("src_%u", pt);
    srcpad = gst_pad_new_from_template (templ, padname);
    gst_pad_use_fixed_caps (srcpad);
    g_free (padname);
    gst_pad_set_event_function (srcpad, gst_rtp_pt_demux_src_event);

    GST_DEBUG ("Adding pt=%d to the list.", pt);
    rtpdemuxpad = g_slice_new0 (GstRtpPtDemuxPad);
    rtpdemuxpad->pt = pt;
    rtpdemuxpad->newcaps = FALSE;
    rtpdemuxpad->pad = srcpad;
    gst_object_ref (srcpad);
    GST_OBJECT_LOCK (rtpdemux);
    rtpdemux->srcpads = g_slist_append (rtpdemux->srcpads, rtpdemuxpad);
    GST_OBJECT_UNLOCK (rtpdemux);

    gst_pad_set_active (srcpad, TRUE);


    /* First push the stream-start event, it must always come first */
    gst_pad_push_event (srcpad,
        gst_pad_get_sticky_event (rtpdemux->sink, GST_EVENT_STREAM_START, 0));

    /* Then caps event is sent */
    caps = gst_caps_make_writable (caps);
    gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
    gst_pad_set_caps (srcpad, caps);
    gst_caps_unref (caps);

    /* First sticky events on sink pad are forwarded to the new src pad */
    gst_pad_sticky_events_foreach (rtpdemux->sink, forward_sticky_events,
        srcpad);

    gst_element_add_pad (GST_ELEMENT_CAST (rtpdemux), srcpad);

    GST_DEBUG ("emitting new-payload-type for pt %d", pt);
    g_signal_emit (G_OBJECT (rtpdemux),
        gst_rtp_pt_demux_signals[SIGNAL_NEW_PAYLOAD_TYPE], 0, pt, srcpad);
  }

  if (pt != rtpdemux->last_pt) {
    gint emit_pt = pt;

    /* our own signal with an extra flag that this is the only pad */
    rtpdemux->last_pt = pt;
    GST_DEBUG ("emitting payload-type-changed for pt %d", emit_pt);
    g_signal_emit (G_OBJECT (rtpdemux),
        gst_rtp_pt_demux_signals[SIGNAL_PAYLOAD_TYPE_CHANGE], 0, emit_pt);
  }

  while (need_caps_for_pt (rtpdemux, pt)) {
    GST_DEBUG ("need new caps for %d", pt);
    caps = gst_rtp_pt_demux_get_caps (rtpdemux, pt);
    if (!caps)
      goto no_caps;

    clear_newcaps_for_pt (rtpdemux, pt);

    caps = gst_caps_make_writable (caps);
    gst_caps_set_simple (caps, "payload", G_TYPE_INT, pt, NULL);
    gst_pad_set_caps (srcpad, caps);
    gst_caps_unref (caps);
  }

  /* push to srcpad */
  ret = gst_pad_push (srcpad, buf);

  gst_object_unref (srcpad);

  return ret;

  /* ERRORS */
invalid_buffer:
  {
    /* this is fatal and should be filtered earlier */
    GST_ELEMENT_ERROR (rtpdemux, STREAM, DECODE, (NULL),
        ("Dropping invalid RTP payload"));
    gst_buffer_unref (buf);
    return GST_FLOW_ERROR;
  }
no_caps:
  {
    GST_ELEMENT_ERROR (rtpdemux, STREAM, DECODE, (NULL),
        ("Could not get caps for payload"));
    gst_buffer_unref (buf);
    if (srcpad)
      gst_object_unref (srcpad);
    return GST_FLOW_ERROR;
  }
}
示例#5
0
static GstElement *
gst_auto_convert_add_element (GstAutoConvert * autoconvert,
    GstElementFactory * factory)
{
  GstElement *element = NULL;
  GstPad *internal_sinkpad = NULL;
  GstPad *internal_srcpad = NULL;
  GstPad *sinkpad;
  GstPad *srcpad;
  GstPadLinkReturn padlinkret;

  GST_DEBUG_OBJECT (autoconvert, "Adding element %s to the autoconvert bin",
      gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));

  element = gst_element_factory_create (factory, NULL);
  if (!element)
    return NULL;

  if (!gst_bin_add (GST_BIN (autoconvert), element)) {
    GST_ERROR_OBJECT (autoconvert, "Could not add element %s to the bin",
        GST_OBJECT_NAME (element));
    gst_object_unref (element);
    return NULL;
  }

  srcpad = get_pad_by_direction (element, GST_PAD_SRC);
  if (!srcpad) {
    GST_ERROR_OBJECT (autoconvert, "Could not find source in %s",
        GST_OBJECT_NAME (element));
    goto error;
  }

  sinkpad = get_pad_by_direction (element, GST_PAD_SINK);
  if (!sinkpad) {
    GST_ERROR_OBJECT (autoconvert, "Could not find sink in %s",
        GST_OBJECT_NAME (element));
    goto error;
  }

  internal_sinkpad =
      gst_pad_new_from_static_template (&sink_internal_template,
      "sink_internal");
  internal_srcpad =
      gst_pad_new_from_static_template (&src_internal_template, "src_internal");

  if (!internal_sinkpad || !internal_srcpad) {
    GST_ERROR_OBJECT (autoconvert, "Could not create internal pads");
    goto error;
  }

  g_object_weak_ref (G_OBJECT (element), (GWeakNotify) gst_object_unref,
      internal_sinkpad);
  g_object_weak_ref (G_OBJECT (element), (GWeakNotify) gst_object_unref,
      internal_srcpad);

  gst_pad_set_active (internal_sinkpad, TRUE);
  gst_pad_set_active (internal_srcpad, TRUE);

  g_object_set_qdata (G_OBJECT (internal_srcpad), parent_quark, autoconvert);
  g_object_set_qdata (G_OBJECT (internal_sinkpad), parent_quark, autoconvert);

  gst_pad_set_chain_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_chain));
  gst_pad_set_event_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_event));
  gst_pad_set_query_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_query));
  gst_pad_set_query_type_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_query_type));
  gst_pad_set_getcaps_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_getcaps));
  gst_pad_set_bufferalloc_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_buffer_alloc));
  gst_pad_set_fixatecaps_function (internal_sinkpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_sink_fixatecaps));

  gst_pad_set_event_function (internal_srcpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_src_event));
  gst_pad_set_query_function (internal_srcpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_src_query));
  gst_pad_set_query_type_function (internal_srcpad,
      GST_DEBUG_FUNCPTR (gst_auto_convert_internal_src_query_type));

  padlinkret = gst_pad_link (internal_srcpad, sinkpad);
  if (GST_PAD_LINK_FAILED (padlinkret)) {
    GST_WARNING_OBJECT (autoconvert, "Could not links pad %s:%s to %s:%s"
        " for reason %d",
        GST_DEBUG_PAD_NAME (internal_srcpad),
        GST_DEBUG_PAD_NAME (sinkpad), padlinkret);
    goto error;
  }

  padlinkret = gst_pad_link (srcpad, internal_sinkpad);
  if (GST_PAD_LINK_FAILED (padlinkret)) {
    GST_WARNING_OBJECT (autoconvert, "Could not links pad %s:%s to %s:%s"
        " for reason %d",
        GST_DEBUG_PAD_NAME (internal_srcpad),
        GST_DEBUG_PAD_NAME (sinkpad), padlinkret);
    goto error;
  }

  g_object_set_qdata (G_OBJECT (element),
      internal_srcpad_quark, internal_srcpad);
  g_object_set_qdata (G_OBJECT (element),
      internal_sinkpad_quark, internal_sinkpad);

  /* Iffy */
  gst_element_sync_state_with_parent (element);

  /* Increment the reference count we will return to the caller */
  gst_object_ref (element);

  return element;

error:
  gst_bin_remove (GST_BIN (autoconvert), element);

  return NULL;
}
示例#6
0
gboolean
fs_rtp_sub_stream_add_output_ghostpad_unlock (FsRtpSubStream *substream,
    GError **error)
{
  GstPad *valve_srcpad;
  gchar *padname = NULL;
  GstPad *ghostpad = NULL;
  FsCodec *codec = NULL;

  if (substream->priv->adding_output_ghostpad)
  {
    FS_RTP_SESSION_UNLOCK (substream->priv->session);
    return TRUE;
  }

  g_assert (substream->priv->output_ghostpad == NULL);

  substream->priv->adding_output_ghostpad = TRUE;

  padname = g_strdup_printf ("src_%u_%u_%d", substream->priv->session->id,
      substream->ssrc,
      substream->pt);

  FS_RTP_SESSION_UNLOCK (substream->priv->session);

  valve_srcpad = gst_element_get_static_pad (substream->priv->output_valve,
      "src");
  g_assert (valve_srcpad);

  ghostpad = gst_ghost_pad_new_from_template (padname, valve_srcpad,
      gst_element_class_get_pad_template (
          GST_ELEMENT_GET_CLASS (substream->priv->conference),
          "src_%d_%d_%d"));

  gst_object_unref (valve_srcpad);
  g_free (padname);

  if (!ghostpad)
  {
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
        "Could not build ghostpad src_%u_%u_%d", substream->priv->session->id,
        substream->ssrc, substream->pt);
    substream->priv->adding_output_ghostpad = FALSE;
    return FALSE;
  }

  if (!gst_pad_set_active (ghostpad, TRUE))
  {
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
        "Could not activate the src_%u_%u_%d", substream->priv->session->id,
        substream->ssrc, substream->pt);
    gst_object_unref (ghostpad);
    substream->priv->adding_output_ghostpad = FALSE;
    return FALSE;
  }

  if (!gst_element_add_pad (GST_ELEMENT (substream->priv->conference),
          ghostpad))
  {
    g_set_error (error, FS_ERROR, FS_ERROR_CONSTRUCTION,
        "Could add build ghostpad src_%u_%u_%d to the conference",
        substream->priv->session->id, substream->ssrc, substream->pt);
    gst_object_unref (ghostpad);
    substream->priv->adding_output_ghostpad = FALSE;
    return FALSE;
  }

  FS_RTP_SESSION_LOCK (substream->priv->session);
  substream->priv->output_ghostpad = ghostpad;

  GST_DEBUG ("Src pad added on substream for ssrc:%X pt:%u " FS_CODEC_FORMAT,
      substream->ssrc, substream->pt,
      FS_CODEC_ARGS (substream->codec));

  codec = fs_codec_copy (substream->codec);

  FS_RTP_SESSION_UNLOCK (substream->priv->session);

  g_signal_emit (substream, signals[SRC_PAD_ADDED], 0,
                 ghostpad, codec);
  g_signal_emit (substream, signals[CODEC_CHANGED], 0);

  fs_codec_destroy (codec);

  g_object_set (substream->priv->output_valve, "drop", FALSE, NULL);

  fs_rtp_sub_stream_try_stop (substream);

  return TRUE;
}
示例#7
0
gboolean
gst_uri_downloader_stream_uri (GstUriDownloader * downloader,
    const gchar * uri, gint64 range_start, gint64 range_end,
    GstUriDownloaderChainFunction chain_func, gpointer user_data)
{
  GstStateChangeReturn ret;

  GST_INFO_OBJECT (downloader, "fetching URI %s", uri);

  g_mutex_lock (&downloader->download_lock);
  downloader->chain = chain_func;
  downloader->priv = user_data;
  downloader->eos = FALSE;

  gst_pad_set_active (downloader->pad, TRUE);

  GST_OBJECT_LOCK (downloader);
  if (downloader->cancelled)
    goto quit;

  if (!gst_uri_downloader_set_uri (downloader, uri)) {
    GST_ERROR_OBJECT (downloader, "failed to set URI");
    goto quit;
  }

  gst_bus_set_flushing (downloader->bus, FALSE);
  GST_OBJECT_UNLOCK (downloader);

  /* set to ready state first to allow setting range */
  ret = gst_element_set_state (downloader->urisrc, GST_STATE_READY);

  GST_OBJECT_LOCK (downloader);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    GST_ERROR_OBJECT (downloader, "failed to set src to READY");
    goto quit;
  }

  if (downloader->cancelled)
    goto quit;

  if (!gst_uri_downloader_set_range (downloader, range_start, range_end)) {
    GST_ERROR_OBJECT (downloader, "failed to set range");
    goto quit;
  }

  GST_OBJECT_UNLOCK (downloader);

  ret = gst_element_set_state (downloader->urisrc, GST_STATE_PLAYING);

  GST_OBJECT_LOCK (downloader);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    GST_ERROR_OBJECT (downloader, "failed to set src to PLAYING");
    goto quit;
  }

  if (downloader->cancelled)
    goto quit;

  if (!downloader->eos) {
    /* wait until:
     *   - the download succeed (EOS in the src pad)
     *   - the download failed (Error message on the fetcher bus)
     *   - the download was canceled
     */
    GST_DEBUG_OBJECT (downloader, "waiting to fetch the URI %s", uri);
    g_cond_wait (&downloader->cond, GST_OBJECT_GET_LOCK (downloader));
  }

quit:
  {
    gboolean ret = FALSE;

    if (downloader->cancelled) {
      GST_DEBUG_OBJECT (downloader, "download interrupted");
    } else if (downloader->eos) {
      GST_DEBUG_OBJECT (downloader, "URI fetched successfully");
      ret = TRUE;
    }

    downloader->cancelled = FALSE;
    gst_uri_downloader_stop (downloader);
    GST_OBJECT_UNLOCK (downloader);
    g_mutex_unlock (&downloader->download_lock);

    return ret;
  }
}
示例#8
0
static gboolean
gst_wavpack_parse_create_src_pad (GstWavpackParse * wvparse, GstBuffer * buf,
    WavpackHeader * header)
{
  GstWavpackMetadata meta;
  GstCaps *caps = NULL;
  guchar *bufptr;

  g_assert (wvparse->srcpad == NULL);

  bufptr = GST_BUFFER_DATA (buf) + sizeof (WavpackHeader);

  while (gst_wavpack_read_metadata (&meta, GST_BUFFER_DATA (buf), &bufptr)) {
    switch (meta.id) {
      case ID_WVC_BITSTREAM:{
        caps = gst_caps_new_simple ("audio/x-wavpack-correction",
            "framed", G_TYPE_BOOLEAN, TRUE, NULL);
        wvparse->srcpad =
            gst_pad_new_from_template (gst_element_class_get_pad_template
            (GST_ELEMENT_GET_CLASS (wvparse), "wvcsrc"), "wvcsrc");
        break;
      }
      case ID_WV_BITSTREAM:
      case ID_WVX_BITSTREAM:{
        WavpackStreamReader *stream_reader = gst_wavpack_stream_reader_new ();

        WavpackContext *wpc;

        gchar error_msg[80];

        read_id rid;

        gint channel_mask;

        rid.buffer = GST_BUFFER_DATA (buf);
        rid.length = GST_BUFFER_SIZE (buf);
        rid.position = 0;

        wpc =
            WavpackOpenFileInputEx (stream_reader, &rid, NULL, error_msg, 0, 0);

        if (!wpc)
          return FALSE;

        wvparse->samplerate = WavpackGetSampleRate (wpc);
        wvparse->channels = WavpackGetNumChannels (wpc);
        wvparse->total_samples =
            (header->total_samples ==
            0xffffffff) ? G_GINT64_CONSTANT (-1) : header->total_samples;

        caps = gst_caps_new_simple ("audio/x-wavpack",
            "width", G_TYPE_INT, WavpackGetBitsPerSample (wpc),
            "channels", G_TYPE_INT, wvparse->channels,
            "rate", G_TYPE_INT, wvparse->samplerate,
            "framed", G_TYPE_BOOLEAN, TRUE, NULL);
#ifdef WAVPACK_OLD_API
        channel_mask = wpc->config.channel_mask;
#else
        channel_mask = WavpackGetChannelMask (wpc);
#endif
        if (channel_mask == 0)
          channel_mask =
              gst_wavpack_get_default_channel_mask (wvparse->channels);

        if (channel_mask != 0) {
          if (!gst_wavpack_set_channel_layout (caps, channel_mask)) {
            GST_WARNING_OBJECT (wvparse, "Failed to set channel layout");
            gst_caps_unref (caps);
            caps = NULL;
            WavpackCloseFile (wpc);
            g_free (stream_reader);
            break;
          }
        }

        wvparse->srcpad =
            gst_pad_new_from_template (gst_element_class_get_pad_template
            (GST_ELEMENT_GET_CLASS (wvparse), "src"), "src");
        WavpackCloseFile (wpc);
        g_free (stream_reader);
        break;
      }
      default:{
        GST_LOG_OBJECT (wvparse, "unhandled ID: 0x%02x", meta.id);
        break;
      }
    }
    if (caps != NULL)
      break;
  }

  if (caps == NULL || wvparse->srcpad == NULL)
    return FALSE;

  GST_DEBUG_OBJECT (wvparse, "Added src pad with caps %" GST_PTR_FORMAT, caps);

  gst_pad_set_query_function (wvparse->srcpad,
      GST_DEBUG_FUNCPTR (gst_wavpack_parse_src_query));
  gst_pad_set_query_type_function (wvparse->srcpad,
      GST_DEBUG_FUNCPTR (gst_wavpack_parse_get_src_query_types));
  gst_pad_set_event_function (wvparse->srcpad,
      GST_DEBUG_FUNCPTR (gst_wavpack_parse_src_event));

  gst_pad_set_caps (wvparse->srcpad, caps);
  gst_caps_unref (caps);
  gst_pad_use_fixed_caps (wvparse->srcpad);

  gst_object_ref (wvparse->srcpad);
  gst_pad_set_active (wvparse->srcpad, TRUE);
  gst_element_add_pad (GST_ELEMENT (wvparse), wvparse->srcpad);
  gst_element_no_more_pads (GST_ELEMENT (wvparse));

  return TRUE;
}
示例#9
0
GstElement *
purple_media_manager_get_element(PurpleMediaManager *manager,
		PurpleMediaSessionType type, PurpleMedia *media,
		const gchar *session_id, const gchar *participant)
{
#ifdef USE_VV
	GstElement *ret = NULL;
	PurpleMediaElementInfo *info = NULL;
	PurpleMediaElementType element_type;

	if (type & PURPLE_MEDIA_SEND_AUDIO)
		info = manager->priv->audio_src;
	else if (type & PURPLE_MEDIA_RECV_AUDIO)
		info = manager->priv->audio_sink;
	else if (type & PURPLE_MEDIA_SEND_VIDEO)
		info = manager->priv->video_src;
	else if (type & PURPLE_MEDIA_RECV_VIDEO)
		info = manager->priv->video_sink;

	if (info == NULL)
		return NULL;

	element_type = purple_media_element_info_get_element_type(info);

	if (element_type & PURPLE_MEDIA_ELEMENT_UNIQUE &&
			element_type & PURPLE_MEDIA_ELEMENT_SRC) {
		GstElement *tee;
		GstPad *pad;
		GstPad *ghost;
		gchar *id = purple_media_element_info_get_id(info);

		ret = gst_bin_get_by_name(GST_BIN(
				purple_media_manager_get_pipeline(
				manager)), id);

		if (ret == NULL) {
			GstElement *bin, *fakesink;
			ret = purple_media_element_info_call_create(info,
					media, session_id, participant);
			bin = gst_bin_new(id);
			tee = gst_element_factory_make("tee", "tee");
			gst_bin_add_many(GST_BIN(bin), ret, tee, NULL);
			gst_element_link(ret, tee);

			/*
			 * This shouldn't be necessary, but it stops it from
			 * giving a not-linked error upon destruction
			 */
			fakesink = gst_element_factory_make("fakesink", NULL);
			g_object_set(fakesink, "sync", FALSE, NULL);
			gst_bin_add(GST_BIN(bin), fakesink);
			gst_element_link(tee, fakesink);

			ret = bin;
			gst_object_ref(ret);
			gst_bin_add(GST_BIN(purple_media_manager_get_pipeline(
					manager)), ret);
		}
		g_free(id);

		tee = gst_bin_get_by_name(GST_BIN(ret), "tee");
		pad = gst_element_get_request_pad(tee, "src%d");
		gst_object_unref(tee);
		ghost = gst_ghost_pad_new(NULL, pad);
		gst_object_unref(pad);
		g_signal_connect(GST_PAD(ghost), "unlinked",
				G_CALLBACK(request_pad_unlinked_cb), NULL);
		gst_pad_set_active(ghost, TRUE);
		gst_element_add_pad(ret, ghost);
	} else {
		ret = purple_media_element_info_call_create(info,
				media, session_id, participant);
	}

	if (ret == NULL)
		purple_debug_error("media", "Error creating source or sink\n");

	return ret;
#else
	return NULL;
#endif
}
示例#10
0
static GstFlowReturn
gst_real_audio_demux_parse_header (GstRealAudioDemux * demux)
{
  const guint8 *data;
  gchar *codec_name = NULL;
  GstCaps *caps = NULL;
  GstEvent *event;
  gchar *stream_id;
  guint avail;

  g_assert (demux->ra_version == 4 || demux->ra_version == 3);

  avail = gst_adapter_available (demux->adapter);
  if (avail < 16)
    return GST_FLOW_OK;

  if (!gst_real_audio_demux_get_data_offset_from_header (demux))
    return GST_FLOW_ERROR;      /* shouldn't happen */

  GST_DEBUG_OBJECT (demux, "data_offset  = %u", demux->data_offset);

  if (avail + 6 < demux->data_offset) {
    GST_DEBUG_OBJECT (demux, "Need %u bytes, but only %u available now",
        demux->data_offset - 6, avail);
    return GST_FLOW_OK;
  }

  data = gst_adapter_map (demux->adapter, demux->data_offset - 6);
  g_assert (data);

  switch (demux->ra_version) {
    case 3:
      demux->fourcc = GST_RM_AUD_14_4;
      demux->packet_size = 20;
      demux->sample_rate = 8000;
      demux->channels = 1;
      demux->sample_width = 16;
      demux->flavour = 1;
      demux->leaf_size = 0;
      demux->height = 0;
      break;
    case 4:
      demux->flavour = GST_READ_UINT16_BE (data + 16);
      /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */
      demux->leaf_size = GST_READ_UINT16_BE (data + 38);
      demux->height = GST_READ_UINT16_BE (data + 34);
      demux->packet_size = GST_READ_UINT32_BE (data + 18);
      demux->sample_rate = GST_READ_UINT16_BE (data + 42);
      demux->sample_width = GST_READ_UINT16_BE (data + 46);
      demux->channels = GST_READ_UINT16_BE (data + 48);
      demux->fourcc = GST_READ_UINT32_LE (data + 56);
      demux->pending_tags = gst_rm_utils_read_tags (data + 63,
          demux->data_offset - 63, gst_rm_utils_read_string8);
      if (demux->pending_tags)
        gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL);
      break;
    default:
      g_assert_not_reached ();
#if 0
    case 5:
      demux->flavour = GST_READ_UINT16_BE (data + 16);
      /* demux->frame_size = GST_READ_UINT32_BE (data + 36); */
      demux->leaf_size = GST_READ_UINT16_BE (data + 38);
      demux->height = GST_READ_UINT16_BE (data + 34);

      demux->sample_rate = GST_READ_UINT16_BE (data + 48);
      demux->sample_width = GST_READ_UINT16_BE (data + 52);
      demux->n_channels = GST_READ_UINT16_BE (data + 54);
      demux->fourcc = RMDEMUX_FOURCC_GET (data + 60);
      break;
#endif
  }

  GST_INFO_OBJECT (demux, "packet_size  = %u", demux->packet_size);
  GST_INFO_OBJECT (demux, "sample_rate  = %u", demux->sample_rate);
  GST_INFO_OBJECT (demux, "sample_width = %u", demux->sample_width);
  GST_INFO_OBJECT (demux, "channels     = %u", demux->channels);
  GST_INFO_OBJECT (demux, "fourcc       = '%" GST_FOURCC_FORMAT "' (%08X)",
      GST_FOURCC_ARGS (demux->fourcc), demux->fourcc);

  switch (demux->fourcc) {
    case GST_RM_AUD_14_4:
      caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion",
          G_TYPE_INT, 1, NULL);
      demux->byterate_num = 1000;
      demux->byterate_denom = 1;
      break;

    case GST_RM_AUD_28_8:
      /* FIXME: needs descrambling */
      caps = gst_caps_new_simple ("audio/x-pn-realaudio", "raversion",
          G_TYPE_INT, 2, NULL);
      break;

    case GST_RM_AUD_DNET:
      caps = gst_caps_new_simple ("audio/x-ac3", "rate", G_TYPE_INT,
          demux->sample_rate, NULL);
      if (demux->packet_size == 0 || demux->sample_rate == 0)
        goto broken_file;
      demux->byterate_num = demux->packet_size * demux->sample_rate;
      demux->byterate_denom = 1536;
      break;

      /* Sipro/ACELP.NET Voice Codec (MIME unknown) */
    case GST_RM_AUD_SIPR:
      caps = gst_caps_new_empty_simple ("audio/x-sipro");
      break;

    default:
      GST_WARNING_OBJECT (demux, "unknown fourcc %08X", demux->fourcc);
      break;
  }

  if (caps == NULL)
    goto unknown_fourcc;

  gst_caps_set_simple (caps,
      "flavor", G_TYPE_INT, demux->flavour,
      "rate", G_TYPE_INT, demux->sample_rate,
      "channels", G_TYPE_INT, demux->channels,
      "width", G_TYPE_INT, demux->sample_width,
      "leaf_size", G_TYPE_INT, demux->leaf_size,
      "packet_size", G_TYPE_INT, demux->packet_size,
      "height", G_TYPE_INT, demux->height, NULL);

  GST_INFO_OBJECT (demux, "Adding source pad, caps %" GST_PTR_FORMAT, caps);
  demux->srcpad = gst_pad_new_from_static_template (&src_template, "src");
  gst_pad_set_event_function (demux->srcpad,
      GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_event));
  gst_pad_set_query_function (demux->srcpad,
      GST_DEBUG_FUNCPTR (gst_real_audio_demux_src_query));
  gst_pad_set_active (demux->srcpad, TRUE);
  gst_pad_use_fixed_caps (demux->srcpad);

  stream_id =
      gst_pad_create_stream_id (demux->srcpad, GST_ELEMENT_CAST (demux), NULL);

  event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
  if (event) {
    if (gst_event_parse_group_id (event, &demux->group_id))
      demux->have_group_id = TRUE;
    else
      demux->have_group_id = FALSE;
    gst_event_unref (event);
  } else if (!demux->have_group_id) {
    demux->have_group_id = TRUE;
    demux->group_id = gst_util_group_id_next ();
  }

  event = gst_event_new_stream_start (stream_id);
  if (demux->have_group_id)
    gst_event_set_group_id (event, demux->group_id);

  gst_pad_push_event (demux->srcpad, event);
  g_free (stream_id);

  gst_pad_set_caps (demux->srcpad, caps);
  codec_name = gst_pb_utils_get_codec_description (caps);
  gst_caps_unref (caps);

  gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad);

  if (demux->byterate_num > 0 && demux->byterate_denom > 0) {
    GstFormat bformat = GST_FORMAT_BYTES;
    gint64 size_bytes = 0;

    GST_INFO_OBJECT (demux, "byte rate = %u/%u = %u bytes/sec",
        demux->byterate_num, demux->byterate_denom,
        demux->byterate_num / demux->byterate_denom);

    if (gst_pad_peer_query_duration (demux->sinkpad, bformat, &size_bytes)) {
      demux->duration =
          gst_real_demux_get_timestamp_from_offset (demux, size_bytes);
      demux->upstream_size = size_bytes;
      GST_INFO_OBJECT (demux, "upstream_size = %" G_GUINT64_FORMAT,
          demux->upstream_size);
      GST_INFO_OBJECT (demux, "duration      = %" GST_TIME_FORMAT,
          GST_TIME_ARGS (demux->duration));
    }
  }

  demux->need_newsegment = TRUE;

  if (codec_name) {
    if (demux->pending_tags == NULL) {
      demux->pending_tags = gst_tag_list_new_empty ();
      gst_tag_list_set_scope (demux->pending_tags, GST_TAG_SCOPE_GLOBAL);
    }

    gst_tag_list_add (demux->pending_tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_AUDIO_CODEC, codec_name, NULL);
    g_free (codec_name);
  }

  gst_adapter_unmap (demux->adapter);
  gst_adapter_flush (demux->adapter, demux->data_offset - 6);

  demux->state = REAL_AUDIO_DEMUX_STATE_DATA;
  demux->need_newsegment = TRUE;

  return GST_FLOW_OK;

/* ERRORS */
unknown_fourcc:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL),
        ("Unknown fourcc '0x%" G_GINT32_MODIFIER "x'", demux->fourcc));
    return GST_FLOW_ERROR;
  }
broken_file:
  {
    GST_ELEMENT_ERROR (GST_ELEMENT (demux), STREAM, DECODE, (NULL),
        ("Broken file - invalid sample_rate or other header value"));
    return GST_FLOW_ERROR;
  }

}
示例#11
0
static GstPad *
find_or_create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
    PadType padtype)
{
  GstPad *rtp_pad, *rtcp_pad;
  GstElementClass *klass;
  GstPadTemplate *templ;
  gchar *padname;
  GstRtpSsrcDemuxPad *demuxpad;
  GstPad *retpad;
  gulong rtp_block, rtcp_block;

  GST_PAD_LOCK (demux);

  demuxpad = find_demux_pad_for_ssrc (demux, ssrc);
  if (demuxpad != NULL) {
    gboolean forward = FALSE;

    switch (padtype) {
      case RTP_PAD:
        retpad = gst_object_ref (demuxpad->rtp_pad);
        if (!demuxpad->pushed_initial_rtp_events) {
          forward = TRUE;
          demuxpad->pushed_initial_rtp_events = TRUE;
        }
        break;
      case RTCP_PAD:
        retpad = gst_object_ref (demuxpad->rtcp_pad);
        if (!demuxpad->pushed_initial_rtcp_events) {
          forward = TRUE;
          demuxpad->pushed_initial_rtcp_events = TRUE;
        }
        break;
      default:
        retpad = NULL;
        g_assert_not_reached ();
    }

    GST_PAD_UNLOCK (demux);

    if (forward)
      forward_initial_events (demux, ssrc, retpad, padtype);
    return retpad;
  }

  GST_DEBUG_OBJECT (demux, "creating new pad for SSRC %08x", ssrc);

  klass = GST_ELEMENT_GET_CLASS (demux);
  templ = gst_element_class_get_pad_template (klass, "src_%u");
  padname = g_strdup_printf ("src_%u", ssrc);
  rtp_pad = gst_pad_new_from_template (templ, padname);
  g_free (padname);

  templ = gst_element_class_get_pad_template (klass, "rtcp_src_%u");
  padname = g_strdup_printf ("rtcp_src_%u", ssrc);
  rtcp_pad = gst_pad_new_from_template (templ, padname);
  g_free (padname);

  /* wrap in structure and add to list */
  demuxpad = g_new0 (GstRtpSsrcDemuxPad, 1);
  demuxpad->ssrc = ssrc;
  demuxpad->rtp_pad = rtp_pad;
  demuxpad->rtcp_pad = rtcp_pad;

  gst_pad_set_element_private (rtp_pad, demuxpad);
  gst_pad_set_element_private (rtcp_pad, demuxpad);

  demux->srcpads = g_slist_prepend (demux->srcpads, demuxpad);

  gst_pad_set_query_function (rtp_pad, gst_rtp_ssrc_demux_src_query);
  gst_pad_set_iterate_internal_links_function (rtp_pad,
      gst_rtp_ssrc_demux_iterate_internal_links_src);
  gst_pad_set_event_function (rtp_pad, gst_rtp_ssrc_demux_src_event);
  gst_pad_use_fixed_caps (rtp_pad);
  gst_pad_set_active (rtp_pad, TRUE);

  gst_pad_set_event_function (rtcp_pad, gst_rtp_ssrc_demux_src_event);
  gst_pad_set_iterate_internal_links_function (rtcp_pad,
      gst_rtp_ssrc_demux_iterate_internal_links_src);
  gst_pad_use_fixed_caps (rtcp_pad);
  gst_pad_set_active (rtcp_pad, TRUE);

  if (padtype == RTP_PAD) {
    demuxpad->pushed_initial_rtp_events = TRUE;
    forward_initial_events (demux, ssrc, rtp_pad, padtype);
  } else if (padtype == RTCP_PAD) {
    demuxpad->pushed_initial_rtcp_events = TRUE;
    forward_initial_events (demux, ssrc, rtcp_pad, padtype);
  } else {
    g_assert_not_reached ();
  }

  gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad);
  gst_element_add_pad (GST_ELEMENT_CAST (demux), rtcp_pad);

  switch (padtype) {
    case RTP_PAD:
      retpad = gst_object_ref (demuxpad->rtp_pad);
      break;
    case RTCP_PAD:
      retpad = gst_object_ref (demuxpad->rtcp_pad);
      break;
    default:
      retpad = NULL;
      g_assert_not_reached ();
  }

  gst_object_ref (rtp_pad);
  gst_object_ref (rtcp_pad);

  rtp_block = gst_pad_add_probe (rtp_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
      NULL, NULL, NULL);
  rtcp_block = gst_pad_add_probe (rtcp_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
      NULL, NULL, NULL);

  GST_PAD_UNLOCK (demux);

  g_signal_emit (G_OBJECT (demux),
      gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, rtp_pad);

  gst_pad_remove_probe (rtp_pad, rtp_block);
  gst_pad_remove_probe (rtcp_pad, rtcp_block);

  gst_object_unref (rtp_pad);
  gst_object_unref (rtcp_pad);

  return retpad;
}
static void
test_videoframe_audiolevel_generic (void)
{
  GstElement *alevel;
  GstPad *asink, *vsink, *asrc, *vsrc, *aoutput_sink, *voutput_sink;
  GThread *athread, *vthread;
  GstBus *bus;
  guint i;

  got_eos = FALSE;
  audio_buffer_count = 0;
  video_buffer_count = 0;
  num_msgs = 0;

  g_queue_init (&v_timestamp_q);
  g_queue_init (&msg_timestamp_q);

  alevel = gst_element_factory_make ("videoframe-audiolevel", NULL);
  fail_unless (alevel != NULL);

  bus = gst_bus_new ();
  gst_element_set_bus (alevel, bus);
  gst_bus_set_sync_handler (bus, on_message, NULL, NULL);

  asink = gst_element_get_static_pad (alevel, "asink");
  fail_unless (asink != NULL);

  vsink = gst_element_get_static_pad (alevel, "vsink");
  fail_unless (vsink != NULL);

  asrc = gst_element_get_static_pad (alevel, "asrc");
  aoutput_sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_unless (aoutput_sink != NULL);
  fail_unless (gst_pad_link (asrc, aoutput_sink) == GST_PAD_LINK_OK);

  vsrc = gst_element_get_static_pad (alevel, "vsrc");
  voutput_sink = gst_pad_new ("sink", GST_PAD_SINK);
  fail_unless (voutput_sink != NULL);
  fail_unless (gst_pad_link (vsrc, voutput_sink) == GST_PAD_LINK_OK);

  gst_pad_set_chain_function (aoutput_sink, output_achain);
  gst_pad_set_event_function (aoutput_sink, output_aevent);

  gst_pad_set_chain_function (voutput_sink, output_vchain);
  gst_pad_set_event_function (voutput_sink, output_vevent);

  gst_pad_set_active (aoutput_sink, TRUE);
  gst_pad_set_active (voutput_sink, TRUE);
  fail_unless (gst_element_set_state (alevel,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);

  athread = g_thread_new ("athread", (GThreadFunc) push_abuffers, asink);
  vthread = g_thread_new ("vthread", (GThreadFunc) push_vbuffers, vsink);

  g_thread_join (vthread);
  g_thread_join (athread);

  fail_unless (got_eos);
  fail_unless_equals_int (audio_buffer_count, n_abuffers);
  fail_unless_equals_int (video_buffer_count, n_vbuffers);
  if (!long_video)
    fail_unless_equals_int (num_msgs, n_vbuffers);

  fail_unless_equals_int (g_queue_get_length (&v_timestamp_q), n_vbuffers);
  /* num_msgs is equal to n_vbuffers except in the case of long_video */
  fail_unless_equals_int (g_queue_get_length (&msg_timestamp_q), num_msgs);

  for (i = 0; i < g_queue_get_length (&msg_timestamp_q); i++) {
    GstClockTime *vt = g_queue_pop_head (&v_timestamp_q);
    GstClockTime *mt = g_queue_pop_head (&msg_timestamp_q);
    fail_unless (vt != NULL);
    fail_unless (mt != NULL);
    if (!video_gaps && !video_overlaps && !early_video)
      fail_unless_equals_uint64 (*vt, *mt);
    g_free (vt);
    g_free (mt);
  }

  /* teardown */
  gst_element_set_state (alevel, GST_STATE_NULL);
  gst_bus_set_flushing (bus, TRUE);
  gst_object_unref (bus);
  g_queue_foreach (&v_timestamp_q, (GFunc) g_free, NULL);
  g_queue_foreach (&msg_timestamp_q, (GFunc) g_free, NULL);
  g_queue_clear (&v_timestamp_q);
  g_queue_clear (&msg_timestamp_q);
  gst_pad_unlink (asrc, aoutput_sink);
  gst_object_unref (asrc);
  gst_pad_unlink (vsrc, voutput_sink);
  gst_object_unref (vsrc);
  gst_object_unref (asink);
  gst_object_unref (vsink);
  gst_pad_set_active (aoutput_sink, FALSE);
  gst_object_unref (aoutput_sink);
  gst_pad_set_active (voutput_sink, FALSE);
  gst_object_unref (voutput_sink);
  gst_object_unref (alevel);
}
示例#13
0
文件: util.c 项目: rodrimc/libmicromb
gboolean
set_audio_bin(GstElement *bin, MbMedia *media, GstPad *decoder_src_pad)
{
  GstPad *sink_pad = NULL, *ghost_pad = NULL, *output_sink_pad = NULL;
  GstCaps *caps = NULL;
  GstPadLinkReturn ret;
  int return_code = TRUE;

  media->audio_volume = gst_element_factory_make ("volume", NULL);
  g_assert (media->audio_volume);

  media->audio_converter = gst_element_factory_make ("audioconvert", NULL);
  g_assert (media->audio_converter);

  media->audio_resampler = gst_element_factory_make ("audioresample", NULL);
  g_assert (media->audio_resampler);

  media->audio_filter = gst_element_factory_make ("capsfilter", NULL);
  g_assert (media->audio_filter);

  gst_element_set_state (media->audio_volume, GST_STATE_PAUSED);
  gst_element_set_state (media->audio_converter, GST_STATE_PAUSED);
  gst_element_set_state (media->audio_resampler, GST_STATE_PAUSED);
  gst_element_set_state (media->audio_filter, GST_STATE_PAUSED);

  caps = gst_caps_from_string (audio_caps);
  g_assert (caps);

  g_object_set (media->audio_filter, "caps", caps, NULL);
  gst_caps_unref(caps);

  gst_bin_add_many (GST_BIN(bin), media->audio_volume, media->audio_converter,
      media->audio_resampler, media->audio_filter, NULL);

  if (!gst_element_link_many (media->audio_volume, media->audio_converter,
        media->audio_resampler, media->audio_filter, NULL))
  {
    g_debug ("Could not link audio_converter and audio_volume together\n.");
    return_code = FALSE;
  }
  else
  {
    sink_pad = gst_element_get_static_pad (media->audio_volume, "sink");
    g_assert (sink_pad);

    ret = gst_pad_link (decoder_src_pad, sink_pad);
    if (GST_PAD_LINK_FAILED(ret))
    {
      return_code = FALSE;
      g_debug (" Link failed.\n");
    }
    else
    {
      g_debug (" Link succeeded.\n");

      g_object_set (G_OBJECT(media->audio_volume), "volume", media->volume,
          NULL);

      gst_element_set_state (media->audio_volume, GST_STATE_PLAYING);
      gst_element_set_state (media->audio_converter, GST_STATE_PLAYING);
      gst_element_set_state (media->audio_resampler, GST_STATE_PLAYING);
      gst_element_set_state (media->audio_filter, GST_STATE_PLAYING);

      ghost_pad = gst_ghost_pad_new (
          "a_src", gst_element_get_static_pad (media->audio_filter,
            "src"));
      gst_pad_set_active (ghost_pad, TRUE);
      gst_element_add_pad (bin, ghost_pad);

      output_sink_pad = gst_element_get_request_pad (_mb_global_data.audio_mixer,
          "sink_%u");
      g_assert(output_sink_pad);

      media->audio_pad_name = gst_pad_get_name(output_sink_pad);
      g_debug ("audiomixer: new pad requested (%s)\n", media->audio_pad_name);

      ret = gst_pad_link (ghost_pad, output_sink_pad);
      if (GST_PAD_LINK_FAILED(ret))
      {
        return_code = FALSE;
        g_debug (" Could not link %s and audiomixer together.\n", media->name);
      }

      gst_object_unref (output_sink_pad);
      gst_object_unref (sink_pad);
    }
  }
  return return_code;
}
示例#14
0
static void
_setup_test (gboolean link_h264, gboolean link_yuy2, gboolean link_nv12,
    gboolean link_jpg)
{
  GstCaps *caps;
  GstPad *sinkpad, *h264pad, *yuy2pad, *nv12pad, *jpgpad;
  GstBus *bus;

  bus = gst_bus_new ();

  have_h264_eos = have_yuy2_eos = have_nv12_eos = have_jpg_eos = FALSE;
  buffer_h264 = buffer_yuy2 = buffer_nv12 = buffer_jpg = NULL;

  demux = gst_element_factory_make ("uvch264mjpgdemux", NULL);
  fail_unless (demux != NULL);

  gst_element_set_bus (demux, bus);
  gst_bus_set_sync_handler (bus, _bus_sync_handler, NULL, NULL);

  mjpg_pad = gst_pad_new_from_static_template (&mjpg_template, "src");
  fail_unless (mjpg_pad != NULL);
  sinkpad = gst_element_get_static_pad (demux, "sink");
  fail_unless (sinkpad != NULL);
  fail_unless (gst_pad_link (mjpg_pad, sinkpad) == GST_PAD_LINK_OK);
  gst_object_unref (sinkpad);

  gst_pad_set_active (mjpg_pad, TRUE);

  if (link_h264) {
    h264pad = gst_element_get_static_pad (demux, "h264");
    fail_unless (h264pad != NULL);

    h264_pad = gst_pad_new_from_static_template (&sink_template, "h264");
    fail_unless (h264_pad != NULL);
    gst_pad_set_chain_function (h264_pad, _sink_h264_chain);
    gst_pad_set_event_function (h264_pad, _sink_h264_event);

    fail_unless (gst_pad_link (h264pad, h264_pad) == GST_PAD_LINK_OK);
    gst_object_unref (h264pad);

    gst_pad_set_active (h264_pad, TRUE);
  }
  if (link_yuy2) {
    yuy2pad = gst_element_get_static_pad (demux, "yuy2");
    fail_unless (yuy2pad != NULL);

    yuy2_pad = gst_pad_new_from_static_template (&sink_template, "yuy2");
    fail_unless (yuy2_pad != NULL);
    gst_pad_set_chain_function (yuy2_pad, _sink_yuy2_chain);
    gst_pad_set_event_function (yuy2_pad, _sink_yuy2_event);

    fail_unless (gst_pad_link (yuy2pad, yuy2_pad) == GST_PAD_LINK_OK);
    gst_object_unref (yuy2pad);

    gst_pad_set_active (yuy2_pad, TRUE);
  }
  if (link_nv12) {
    nv12pad = gst_element_get_static_pad (demux, "nv12");
    fail_unless (nv12pad != NULL);

    nv12_pad = gst_pad_new_from_static_template (&sink_template, "nv12");
    fail_unless (nv12_pad != NULL);
    gst_pad_set_chain_function (nv12_pad, _sink_nv12_chain);
    gst_pad_set_event_function (nv12_pad, _sink_nv12_event);

    fail_unless (gst_pad_link (nv12pad, nv12_pad) == GST_PAD_LINK_OK);
    gst_object_unref (nv12pad);
    gst_pad_set_active (nv12_pad, TRUE);
  }
  if (link_jpg) {
    jpgpad = gst_element_get_static_pad (demux, "jpeg");
    fail_unless (jpgpad != NULL);

    jpg_pad = gst_pad_new_from_static_template (&sink_template, "jpeg");
    fail_unless (jpg_pad != NULL);
    gst_pad_set_chain_function (jpg_pad, _sink_jpg_chain);
    gst_pad_set_event_function (jpg_pad, _sink_jpg_event);

    fail_unless (gst_pad_link (jpgpad, jpg_pad) == GST_PAD_LINK_OK);
    gst_object_unref (jpgpad);

    gst_pad_set_active (jpg_pad, TRUE);
  }

  gst_element_set_state (demux, GST_STATE_PLAYING);

  caps = gst_static_pad_template_get_caps (&mjpg_template);
  gst_check_setup_events_with_stream_id (mjpg_pad, demux, caps,
      GST_FORMAT_TIME, "uvch264demux-test");
  gst_caps_unref (caps);
}
示例#15
0
static gboolean
activate_session (GstRDTManager * rdtmanager, GstRDTManagerSession * session,
    guint32 ssrc, guint8 pt)
{
  GstPadTemplate *templ;
  GstElementClass *klass;
  gchar *name;
  GstCaps *caps;
  GValue ret = { 0 };
  GValue args[3] = { {0}
  , {0}
  , {0}
  };

  GST_DEBUG_OBJECT (rdtmanager, "creating stream");

  session->ssrc = ssrc;
  session->pt = pt;

  /* get pt map */
  g_value_init (&args[0], GST_TYPE_ELEMENT);
  g_value_set_object (&args[0], rdtmanager);
  g_value_init (&args[1], G_TYPE_UINT);
  g_value_set_uint (&args[1], session->id);
  g_value_init (&args[2], G_TYPE_UINT);
  g_value_set_uint (&args[2], pt);

  g_value_init (&ret, GST_TYPE_CAPS);
  g_value_set_boxed (&ret, NULL);

  g_signal_emitv (args, gst_rdt_manager_signals[SIGNAL_REQUEST_PT_MAP], 0,
      &ret);

  g_value_unset (&args[0]);
  g_value_unset (&args[1]);
  g_value_unset (&args[2]);
  caps = (GstCaps *) g_value_dup_boxed (&ret);
  g_value_unset (&ret);

  if (caps)
    gst_rdt_manager_parse_caps (rdtmanager, session, caps);

  name = g_strdup_printf ("recv_rtp_src_%d_%u_%d", session->id, ssrc, pt);
  klass = GST_ELEMENT_GET_CLASS (rdtmanager);
  templ = gst_element_class_get_pad_template (klass, "recv_rtp_src_%d_%d_%d");
  session->recv_rtp_src = gst_pad_new_from_template (templ, name);
  g_free (name);

  gst_pad_set_caps (session->recv_rtp_src, caps);
  gst_caps_unref (caps);

  gst_pad_set_element_private (session->recv_rtp_src, session);
  gst_pad_set_query_function (session->recv_rtp_src, gst_rdt_manager_query_src);
  gst_pad_set_activatepush_function (session->recv_rtp_src,
      gst_rdt_manager_src_activate_push);

  gst_pad_set_active (session->recv_rtp_src, TRUE);
  gst_element_add_pad (GST_ELEMENT_CAST (rdtmanager), session->recv_rtp_src);

  return TRUE;
}
/****************************************************
 *              GstElement vmetods                  *
 ****************************************************/
static GstPad *
_request_new_pad (GstElement * element, GstPadTemplate * templ,
    const gchar * name, const GstCaps * caps)
{
  GstPad *audioresample_srcpad, *audioconvert_sinkpad, *tmpghost;
  GstPad *ghost;
  GstElement *audioconvert, *audioresample;
  PadInfos *infos = g_slice_new0 (PadInfos);
  GESSmartAdder *self = GES_SMART_ADDER (element);

  infos->adder_pad = gst_element_request_pad (self->adder,
      gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (self->adder),
          "sink_%u"), NULL, caps);

  if (infos->adder_pad == NULL) {
    GST_WARNING_OBJECT (element, "Could not get any pad from GstAdder");
    g_slice_free (PadInfos, infos);

    return NULL;
  }

  infos->self = self;

  infos->bin = gst_bin_new (NULL);
  audioconvert = gst_element_factory_make ("audioconvert", NULL);
  audioresample = gst_element_factory_make ("audioresample", NULL);

  gst_bin_add_many (GST_BIN (infos->bin), audioconvert, audioresample, NULL);
  gst_element_link_many (audioconvert, audioresample, NULL);

  audioconvert_sinkpad = gst_element_get_static_pad (audioconvert, "sink");
  tmpghost = GST_PAD (gst_ghost_pad_new (NULL, audioconvert_sinkpad));
  gst_object_unref (audioconvert_sinkpad);
  gst_pad_set_active (tmpghost, TRUE);
  gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);

  gst_bin_add (GST_BIN (self), infos->bin);
  ghost = gst_ghost_pad_new (NULL, tmpghost);
  gst_pad_set_active (ghost, TRUE);
  if (!gst_element_add_pad (GST_ELEMENT (self), ghost))
    goto could_not_add;

  audioresample_srcpad = gst_element_get_static_pad (audioresample, "src");
  tmpghost = GST_PAD (gst_ghost_pad_new (NULL, audioresample_srcpad));
  gst_object_unref (audioresample_srcpad);
  gst_pad_set_active (tmpghost, TRUE);
  gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);
  gst_pad_link (tmpghost, infos->adder_pad);

  LOCK (self);
  g_hash_table_insert (self->pads_infos, ghost, infos);
  UNLOCK (self);

  GST_DEBUG_OBJECT (self, "Returning new pad %" GST_PTR_FORMAT, ghost);
  return ghost;

could_not_add:
  {
    GST_ERROR_OBJECT (self, "could not add pad");
    destroy_pad (infos);
    return NULL;
  }
}
示例#17
0
GstElement *
ges_source_create_topbin (const gchar * bin_name, GstElement * sub_element, ...)
{
  va_list argp;

  GstElement *element;
  GstElement *prev = NULL;
  GstElement *first = NULL;
  GstElement *bin;
  GstPad *sub_srcpad;

  va_start (argp, sub_element);
  bin = gst_bin_new (bin_name);
  gst_bin_add (GST_BIN (bin), sub_element);

  while ((element = va_arg (argp, GstElement *)) != NULL) {
    gst_bin_add (GST_BIN (bin), element);
    if (prev)
      gst_element_link (prev, element);
    prev = element;
    if (first == NULL)
      first = element;
  }

  va_end (argp);

  sub_srcpad = gst_element_get_static_pad (sub_element, "src");

  if (prev != NULL) {
    GstPad *srcpad, *sinkpad, *ghost;

    srcpad = gst_element_get_static_pad (prev, "src");
    ghost = gst_ghost_pad_new ("src", srcpad);
    gst_pad_set_active (ghost, TRUE);
    gst_element_add_pad (bin, ghost);

    sinkpad = gst_element_get_static_pad (first, "sink");
    if (sub_srcpad)
      gst_pad_link (sub_srcpad, sinkpad);
    else
      g_signal_connect (sub_element, "pad-added", G_CALLBACK (_pad_added_cb),
          sinkpad);

    gst_object_unref (srcpad);
    gst_object_unref (sinkpad);

  } else if (sub_srcpad) {
    GstPad *ghost;

    ghost = gst_ghost_pad_new ("src", sub_srcpad);
    gst_pad_set_active (ghost, TRUE);
    gst_element_add_pad (bin, ghost);
  } else {
    g_signal_connect (sub_element, "pad-added",
        G_CALLBACK (_ghost_pad_added_cb), bin);
  }

  if (sub_srcpad)
    gst_object_unref (sub_srcpad);

  return bin;
}
/*
 * create_post_tee_bin
 *
 * The following chain is created after the tee for each output from the
 * source:
 *
 *    +-------+   +---------------------+   +-------+
 * ---+ queue +---+ conversion elements +---+ queue +---
 *    +-------+   +---------------------+   +-------+
 */
static GstElement *create_post_tee_bin(OwrMediaSource *media_source, GstElement *source_bin,
    GstCaps *caps, GstPad *ghostpad, guint source_id)
{
    OwrMediaType media_type;
    GstElement *post_tee_bin, *queue_pre, *queue_post, *capsfilter;
    GstPad *bin_pad, *queue_pre_pad, *srcpad;
    GSList *list = NULL;
    gchar *bin_name;

    bin_name = g_strdup_printf("source-post-tee-bin-%u", source_id);
    post_tee_bin = gst_bin_new(bin_name);
    if (!gst_bin_add(GST_BIN(source_bin), post_tee_bin)) {
        GST_ERROR("Failed to add %s to source bin", bin_name);
        g_free(bin_name);
        g_object_unref(post_tee_bin);
        post_tee_bin = NULL;
        goto done;
    }
    g_free(bin_name);
    gst_element_sync_state_with_parent(post_tee_bin);

    CREATE_ELEMENT_WITH_ID(queue_pre, "queue", "source-post-tee-queue", source_id);
    CREATE_ELEMENT_WITH_ID(capsfilter, "capsfilter", "source-output-capsfilter", source_id);
    list = g_slist_append(list, capsfilter);
    CREATE_ELEMENT_WITH_ID(queue_post, "queue", "source-output-queue", source_id);
    list = g_slist_append(list, queue_post);

    g_object_get(media_source, "media-type", &media_type, NULL);
    switch (media_type) {
    case OWR_MEDIA_TYPE_AUDIO:
        {
        GstElement *audioresample, *audioconvert;

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

        CREATE_ELEMENT_WITH_ID(audioresample, "audioresample", "source-audio-resample", source_id);
        list = g_slist_prepend(list, audioresample);
        CREATE_ELEMENT_WITH_ID(audioconvert, "audioconvert", "source-audio-convert", source_id);
        list = g_slist_prepend(list, audioconvert);
        list = g_slist_prepend(list, queue_pre);

        gst_bin_add_many(GST_BIN(post_tee_bin),
            queue_pre, audioconvert, audioresample, capsfilter, queue_post, NULL);
        LINK_ELEMENTS(capsfilter, queue_post);
        LINK_ELEMENTS(audioresample, capsfilter);
        LINK_ELEMENTS(audioconvert, audioresample);
        LINK_ELEMENTS(queue_pre, audioconvert);

        break;
        }
    case OWR_MEDIA_TYPE_VIDEO:
        {
        GstElement *videorate, *videoscale, *videoconvert;
        GstCaps *source_caps;
        GstStructure *source_structure;
        gint fps_n = 0, fps_d = 1;

        source_caps = gst_caps_copy(caps);
        source_structure = gst_caps_get_structure(source_caps, 0);
        if (gst_structure_get_fraction(source_structure, "framerate", &fps_n, &fps_d))
            gst_structure_remove_field(source_structure, "framerate");
        g_object_set(capsfilter, "caps", source_caps, NULL);
        gst_caps_unref(source_caps);

        CREATE_ELEMENT_WITH_ID(videoconvert, VIDEO_CONVERT, "source-video-convert", source_id);
        list = g_slist_prepend(list, videoconvert);
        CREATE_ELEMENT_WITH_ID(videoscale, "videoscale", "source-video-scale", source_id);
        list = g_slist_prepend(list, videoscale);
        CREATE_ELEMENT_WITH_ID(videorate, "videorate", "source-video-rate", source_id);
        g_object_set(videorate, "drop-only", TRUE, "max-rate", fps_n / fps_d, NULL);
        list = g_slist_prepend(list, videorate);
        list = g_slist_prepend(list, queue_pre);

        gst_bin_add_many(GST_BIN(post_tee_bin),
            queue_pre, videorate, videoscale, videoconvert, capsfilter, queue_post, NULL);
        LINK_ELEMENTS(capsfilter, queue_post);
        LINK_ELEMENTS(videoconvert, capsfilter);
        LINK_ELEMENTS(videoscale, videoconvert);
        LINK_ELEMENTS(videorate, videoscale);
        LINK_ELEMENTS(queue_pre, videorate);

        break;
        }
    case OWR_MEDIA_TYPE_UNKNOWN:
    default:
        g_assert_not_reached();
        goto done;
    }

    srcpad = gst_element_get_static_pad(queue_post, "src");
    g_assert(srcpad);

    bin_pad = gst_ghost_pad_new("src", srcpad);
    gst_pad_set_active(bin_pad, TRUE);
    gst_element_add_pad(post_tee_bin, bin_pad);
    gst_object_unref(srcpad);

    gst_ghost_pad_set_target(GST_GHOST_PAD(ghostpad), bin_pad);
    gst_pad_set_active(ghostpad, TRUE);
    gst_element_add_pad(source_bin, ghostpad);

    g_slist_foreach(list, sync_to_parent, NULL);

    queue_pre_pad = gst_element_get_static_pad(queue_pre, "sink");
    g_assert(queue_pre_pad);

    bin_pad = gst_ghost_pad_new("sink", queue_pre_pad);
    gst_pad_set_active(bin_pad, TRUE);
    gst_element_add_pad(post_tee_bin, bin_pad);
    gst_object_unref(queue_pre_pad);

done:
    g_slist_free(list);
    list = NULL;

    return post_tee_bin;
}
/**
 * gst_wrapper_camera_bin_src_construct_pipeline:
 * @bcamsrc: camerasrc object
 *
 * This function creates and links the elements of the camerasrc bin
 * videosrc ! cspconv ! srcfilter ! cspconv ! capsfilter ! crop ! scale ! \
 * capsfilter ! tee name=t
 *    t. ! ... (viewfinder pad)
 *    t. ! output-selector name=outsel
 *        outsel. ! (image pad)
 *        outsel. ! (video pad)
 *
 * Returns: TRUE, if elements were successfully created, FALSE otherwise
 */
static gboolean
gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc)
{
  GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc);
  GstBin *cbin = GST_BIN (bcamsrc);
  GstElement *tee;
  GstElement *filter_csp;
  GstElement *src_csp;
  GstElement *capsfilter;
  gboolean ret = FALSE;
  GstPad *vf_pad;
  GstPad *tee_capture_pad;
  GstPad *src_caps_src_pad;

  if (!self->elements_created) {

    GST_DEBUG_OBJECT (self, "constructing pipeline");

    /* Add application set or default video src element */
    if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin,
                self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC,
                "camerasrc-real-src"))) {
      self->src_vid_src = NULL;
      goto done;
    } else {
      if (!gst_camerabin_add_element (cbin, self->src_vid_src)) {
        goto done;
      }
    }
    /* we lost the reference */
    self->app_vid_src = NULL;

    /* we listen for changes to max-zoom in the video src so that
     * we can proxy them to the basecamerasrc property */
    if (g_object_class_find_property (G_OBJECT_GET_CLASS (bcamsrc), "max-zoom")) {
      g_signal_connect (G_OBJECT (self->src_vid_src), "notify::max-zoom",
          (GCallback) gst_wrapper_camera_bin_src_max_zoom_cb, bcamsrc);
    }

    /* add a buffer probe to the src elemento to drop EOS from READY->NULL */
    {
      GstPad *pad;
      pad = gst_element_get_static_pad (self->src_vid_src, "src");

      self->src_event_probe_id = gst_pad_add_event_probe (pad,
          (GCallback) gst_wrapper_camera_src_src_event_probe, self);
      gst_object_unref (pad);
    }

    if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace",
            "src-colorspace"))
      goto done;

    if (!(self->src_filter =
            gst_camerabin_create_and_add_element (cbin, "capsfilter",
                "src-capsfilter")))
      goto done;

    /* attach to notify::caps on the first capsfilter and use a callback
     * to recalculate the zoom properties when these caps change and to
     * propagate the caps to the second capsfilter */
    src_caps_src_pad = gst_element_get_static_pad (self->src_filter, "src");
    g_signal_connect (src_caps_src_pad, "notify::caps",
        G_CALLBACK (gst_wrapper_camera_bin_src_caps_cb), self);
    gst_object_unref (src_caps_src_pad);

    if (!(self->src_zoom_crop =
            gst_camerabin_create_and_add_element (cbin, "videocrop",
                "zoom-crop")))
      goto done;
    if (!(self->src_zoom_scale =
            gst_camerabin_create_and_add_element (cbin, "videoscale",
                "zoom-scale")))
      goto done;
    if (!(self->src_zoom_filter =
            gst_camerabin_create_and_add_element (cbin, "capsfilter",
                "zoom-capsfilter")))
      goto done;

    if (!(tee =
            gst_camerabin_create_and_add_element (cbin, "tee",
                "camerasrc-tee")))
      goto done;

    /* viewfinder pad */
    vf_pad = gst_element_get_request_pad (tee, "src%d");
    g_object_set (tee, "alloc-pad", vf_pad, NULL);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad);
    gst_object_unref (vf_pad);

    /* image/video pad from tee */
    tee_capture_pad = gst_element_get_request_pad (tee, "src%d");

    self->output_selector =
        gst_element_factory_make ("output-selector", "outsel");
    g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL);
    gst_bin_add (GST_BIN (self), self->output_selector);
    {
      GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink");

      /* check return TODO */
      gst_pad_link (tee_capture_pad, pad);
      gst_object_unref (pad);
    }
    gst_object_unref (tee_capture_pad);

    /* Create the 2 output pads for video and image */
    self->outsel_vidpad =
        gst_element_get_request_pad (self->output_selector, "src%d");
    self->outsel_imgpad =
        gst_element_get_request_pad (self->output_selector, "src%d");

    g_assert (self->outsel_vidpad != NULL);
    g_assert (self->outsel_imgpad != NULL);

    gst_pad_add_buffer_probe (self->outsel_imgpad,
        G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self);
    gst_pad_add_buffer_probe (self->outsel_vidpad,
        G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc),
        self->outsel_imgpad);
    gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc),
        self->outsel_vidpad);

    if (bcamsrc->mode == MODE_IMAGE) {
      g_object_set (self->output_selector, "active-pad", self->outsel_imgpad,
          NULL);
    } else {
      g_object_set (self->output_selector, "active-pad", self->outsel_vidpad,
          NULL);
    }



    gst_pad_set_active (self->vfsrc, TRUE);
    gst_pad_set_active (self->imgsrc, TRUE);    /* XXX ??? */
    gst_pad_set_active (self->vidsrc, TRUE);    /* XXX ??? */
  }

  /* Do this even if pipeline is constructed */

  if (self->video_filter) {
    /* check if we need to replace the current one */
    if (self->video_filter != self->app_vid_filter) {
      gst_bin_remove (cbin, self->video_filter);
      gst_object_unref (self->video_filter);
      self->video_filter = NULL;
      filter_csp = gst_bin_get_by_name (cbin, "filter-colorspace");
      gst_bin_remove (cbin, filter_csp);
      gst_object_unref (filter_csp);
      filter_csp = NULL;
    }
  }

  if (!self->video_filter) {
    if (self->app_vid_filter) {
      self->video_filter = gst_object_ref (self->app_vid_filter);
      filter_csp = gst_element_factory_make ("ffmpegcolorspace",
          "filter-colorspace");
      gst_bin_add_many (cbin, self->video_filter, filter_csp, NULL);
      src_csp = gst_bin_get_by_name (cbin, "src-colorspace");
      capsfilter = gst_bin_get_by_name (cbin, "src-capsfilter");
      if (gst_pad_is_linked (gst_element_get_static_pad (src_csp, "src")))
        gst_element_unlink (src_csp, capsfilter);
      if (!gst_element_link_many (src_csp, self->video_filter, filter_csp,
              capsfilter, NULL))
        goto done;
    }
  }
  ret = TRUE;
  self->elements_created = TRUE;
done:
  return ret;
}
示例#20
0
static GstMultipartPad *
gst_multipart_find_pad_by_mime (GstMultipartDemux * demux, gchar * mime,
    gboolean * created)
{
  GSList *walk;

  walk = demux->srcpads;
  while (walk) {
    GstMultipartPad *pad = (GstMultipartPad *) walk->data;

    if (!strcmp (pad->mime, mime)) {
      if (created) {
        *created = FALSE;
      }
      return pad;
    }

    walk = walk->next;
  }
  /* pad not found, create it */
  {
    GstPad *pad;
    GstMultipartPad *mppad;
    gchar *name;
    const gchar *capsname;
    GstCaps *caps;

    mppad = g_new0 (GstMultipartPad, 1);

    GST_DEBUG_OBJECT (demux, "creating pad with mime: %s", mime);

    name = g_strdup_printf ("src_%d", demux->numpads);
    pad =
        gst_pad_new_from_static_template (&multipart_demux_src_template_factory,
        name);
    g_free (name);

    /* take the mime type, convert it to the caps name */
    capsname = gst_multipart_demux_get_gstname (demux, mime);
    caps = gst_caps_from_string (capsname);
    GST_DEBUG_OBJECT (demux, "caps for pad: %s", capsname);
    gst_pad_use_fixed_caps (pad);
    gst_pad_set_caps (pad, caps);
    gst_caps_unref (caps);

    mppad->pad = pad;
    mppad->mime = g_strdup (mime);
    mppad->last_ret = GST_FLOW_OK;

    demux->srcpads = g_slist_prepend (demux->srcpads, mppad);
    demux->numpads++;

    gst_pad_set_active (pad, TRUE);
    gst_element_add_pad (GST_ELEMENT_CAST (demux), pad);

    if (created) {
      *created = TRUE;
    }

    return mppad;
  }
}
示例#21
0
static void
gst_nle_source_pad_added_cb (GstElement * element, GstPad * pad,
    GstNleSource * nlesrc)
{
  GstCaps *caps;
  const GstStructure *s;
  const gchar *mime;
  GstElement *appsink = NULL;
  GstPad *sink_pad;
  GstAppSinkCallbacks appsink_cbs;
  GstNleSrcItem *item;

  item = (GstNleSrcItem *) g_list_nth_data (nlesrc->queue, nlesrc->index);

  caps = gst_pad_get_caps_reffed (pad);
  s = gst_caps_get_structure (caps, 0);
  mime = gst_structure_get_name (s);
  GST_DEBUG_OBJECT (nlesrc, "Found mime type: %s", mime);

  if (g_strrstr (mime, "video") && !nlesrc->video_linked) {
    appsink = gst_element_factory_make ("appsink", NULL);
    memset (&appsink_cbs, 0, sizeof (appsink_cbs));
    appsink_cbs.eos = gst_nle_source_on_video_eos;
    appsink_cbs.new_preroll = gst_nle_source_on_preroll_buffer;
    appsink_cbs.new_buffer = gst_nle_source_on_video_buffer;
    nlesrc->video_linked = TRUE;
    if (!nlesrc->video_srcpad_added) {
      gst_pad_set_active (nlesrc->video_srcpad, TRUE);
      gst_element_add_pad (GST_ELEMENT (nlesrc),
          gst_object_ref (nlesrc->video_srcpad));
      nlesrc->video_srcpad_added = TRUE;
    }
    gst_pad_add_event_probe (GST_BASE_SINK_PAD (GST_BASE_SINK (appsink)),
        (GCallback) gst_nle_source_video_pad_probe_cb, nlesrc);
    nlesrc->video_eos = FALSE;
  } else if (g_strrstr (mime, "audio") && nlesrc->with_audio
      && !nlesrc->audio_linked && (item ? item->rate == 1.0 : TRUE)) {
    appsink = gst_element_factory_make ("appsink", NULL);
    memset (&appsink_cbs, 0, sizeof (appsink_cbs));
    appsink_cbs.eos = gst_nle_source_on_audio_eos;
    appsink_cbs.new_preroll = gst_nle_source_on_preroll_buffer;
    appsink_cbs.new_buffer = gst_nle_source_on_audio_buffer;
    nlesrc->audio_linked = TRUE;
    if (!nlesrc->audio_srcpad_added) {
      gst_pad_set_active (nlesrc->audio_srcpad, TRUE);
      gst_element_add_pad (GST_ELEMENT (nlesrc),
          gst_object_ref (nlesrc->audio_srcpad));
      nlesrc->audio_srcpad_added = TRUE;
    }
    gst_pad_add_event_probe (GST_BASE_SINK_PAD (GST_BASE_SINK (appsink)),
        (GCallback) gst_nle_source_audio_pad_probe_cb, nlesrc);
    nlesrc->audio_eos = FALSE;
  }
  if (appsink != NULL) {
    g_object_set (appsink, "sync", FALSE, NULL);
    gst_app_sink_set_callbacks (GST_APP_SINK (appsink), &appsink_cbs, nlesrc,
        NULL);
    gst_bin_add (GST_BIN (nlesrc->decoder), appsink);
    sink_pad = gst_element_get_static_pad (appsink, "sink");
    gst_pad_link (pad, sink_pad);
    gst_element_sync_state_with_parent (appsink);
    gst_object_unref (sink_pad);
  }
}
示例#22
0
static gboolean
create_elements (RsnDvdBin * dvdbin)
{
  GstPadTemplate *src_templ = NULL;
  GstPad *src = NULL;
  GstPad *sink = NULL;
  RsnDvdBinPadBlockCtx *bctx = NULL;

  if (!try_create_piece (dvdbin, DVD_ELEM_SOURCE, NULL,
          RESIN_TYPE_DVDSRC, "dvdsrc", "DVD source")) {
    return FALSE;
  }

  /* FIXME: Locking */
  if (dvdbin->device) {
    g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SOURCE]),
        "device", dvdbin->device, NULL);
  }

  /* FIXME: Import and use local copy of mpeg PS demuxer */
  if (!try_create_piece (dvdbin, DVD_ELEM_DEMUX,
          NULL, GST_TYPE_FLUPS_DEMUX, "dvddemux", "DVD demuxer"))
    return FALSE;

  if (gst_element_link (dvdbin->pieces[DVD_ELEM_SOURCE],
          dvdbin->pieces[DVD_ELEM_DEMUX]) == FALSE)
    goto failed_connect;

  /* Listen for new pads from the demuxer */
  g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "pad-added",
      G_CALLBACK (demux_pad_added), dvdbin);

  g_signal_connect (G_OBJECT (dvdbin->pieces[DVD_ELEM_DEMUX]), "no-more-pads",
      G_CALLBACK (demux_no_more_pads), dvdbin);

  if (!try_create_piece (dvdbin, DVD_ELEM_MQUEUE, "multiqueue", 0, "rsnmq",
          "multiqueue"))
    return FALSE;

  g_object_set (dvdbin->pieces[DVD_ELEM_MQUEUE],
      "max-size-time", (7 * GST_SECOND / 10), "max-size-bytes", 0,
      "max-size-buffers", 0, NULL);

  if (!try_create_piece (dvdbin, DVD_ELEM_VIDPARSE, "mpegvideoparse", 0,
          "rsnvidparse", "video parser"))
    return FALSE;

  /* Decodebin will throw a missing element message to find an MPEG decoder */
  if (!try_create_piece (dvdbin, DVD_ELEM_VIDDEC, NULL, RSN_TYPE_VIDEODEC,
          "rsnviddec", "video decoder"))
    return FALSE;

  /* FIXME: Replace identity */
  if (!try_create_piece (dvdbin, DVD_ELEM_PARSET, NULL, RSN_TYPE_RSNPARSETTER,
          "rsnparsetter", "Aspect ratio adjustment"))
    return FALSE;

  if (!try_link_pieces (dvdbin->pieces[DVD_ELEM_VIDPARSE], "src",
          dvdbin->pieces[DVD_ELEM_VIDDEC], "sink"))
    goto failed_vidparse_connect;

  src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_VIDDEC], "src");
  sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "sink");
  if (src == NULL || sink == NULL)
    goto failed_viddec_connect;
  if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink)))
    goto failed_viddec_connect;
  gst_object_unref (src);
  gst_object_unref (sink);
  src = sink = NULL;

  src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_PARSET], "src");
  if (src == NULL)
    goto failed_video_ghost;
  src_templ = gst_static_pad_template_get (&video_src_template);
  dvdbin->video_pad = gst_ghost_pad_new_from_template ("video", src, src_templ);
  gst_object_unref (src_templ);
  if (dvdbin->video_pad == NULL)
    goto failed_video_ghost;
  gst_pad_set_active (dvdbin->video_pad, TRUE);
  bctx = g_slice_new (RsnDvdBinPadBlockCtx);
  bctx->dvdbin = gst_object_ref (dvdbin);
  bctx->pad = gst_object_ref (dvdbin->video_pad);
  bctx->pad_block_id =
      gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
      (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify)
      _pad_block_destroy_notify);
  gst_object_unref (src);
  src = NULL;

#if DEBUG_TIMING
  gst_pad_add_probe (dvdbin->video_pad,
      GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM | GST_PAD_PROBE_TYPE_BUFFER |
      GST_PAD_PROBE_TYPE_EVENT_FLUSH,
      (GstPadProbeCallback) dvdbin_dump_timing_info, NULL, NULL);
#endif

  /* FIXME: Merge stream-selection logic to core and switch back */
  if (!try_create_piece (dvdbin, DVD_ELEM_SPU_SELECT, NULL,
          RSN_TYPE_INPUT_SELECTOR, "subpselect", "Subpicture stream selector"))
    return FALSE;

  g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_SPU_SELECT]),
      "sync-streams", FALSE, NULL);

  /* Add a single standalone queue to hold a single buffer of SPU data */
  if (!try_create_piece (dvdbin, DVD_ELEM_SPUQ, "queue", 0, "spu_q",
          "subpicture decoder buffer"))
    return FALSE;
  /* Allow a lot more while pre-rolling */
  g_object_set (dvdbin->pieces[DVD_ELEM_SPUQ],
      "max-size-time", G_GUINT64_CONSTANT (0), "max-size-bytes", 0,
      "max-size-buffers", 100, NULL);

  src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPU_SELECT], "src");
  sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "sink");
  if (src == NULL || sink == NULL)
    goto failed_spuq_connect;
  if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink)))
    goto failed_spuq_connect;
  gst_object_unref (src);
  gst_object_unref (sink);
  src = sink = NULL;

  src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_SPUQ], "src");
  if (src == NULL)
    goto failed_spu_ghost;
  src_templ = gst_static_pad_template_get (&subpicture_src_template);
  dvdbin->subpicture_pad =
      gst_ghost_pad_new_from_template ("subpicture", src, src_templ);
  gst_object_unref (src_templ);
  if (dvdbin->subpicture_pad == NULL)
    goto failed_spu_ghost;
  gst_pad_set_active (dvdbin->subpicture_pad, TRUE);
  bctx = g_slice_new (RsnDvdBinPadBlockCtx);
  bctx->dvdbin = gst_object_ref (dvdbin);
  bctx->pad = gst_object_ref (dvdbin->subpicture_pad);
  bctx->pad_block_id =
      gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
      (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify)
      _pad_block_destroy_notify);
  gst_object_unref (src);
  src = NULL;

  if (!try_create_piece (dvdbin, DVD_ELEM_AUD_SELECT, NULL,
          RSN_TYPE_INPUT_SELECTOR, "audioselect", "Audio stream selector"))
    return FALSE;
  g_object_set (G_OBJECT (dvdbin->pieces[DVD_ELEM_AUD_SELECT]),
      "sync-streams", FALSE, NULL);

  if (!try_create_piece (dvdbin, DVD_ELEM_AUDDEC, NULL,
          RSN_TYPE_AUDIODEC, "auddec", "audio decoder"))
    return FALSE;

  src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUD_SELECT], "src");
  sink = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "sink");
  if (src == NULL || sink == NULL)
    goto failed_aud_connect;
  if (GST_PAD_LINK_FAILED (gst_pad_link (src, sink)))
    goto failed_aud_connect;
  gst_object_unref (sink);
  gst_object_unref (src);
  src = sink = NULL;

  /* ghost audio munge output pad onto bin */
  src = gst_element_get_static_pad (dvdbin->pieces[DVD_ELEM_AUDDEC], "src");
  if (src == NULL)
    goto failed_aud_ghost;
  src_templ = gst_static_pad_template_get (&audio_src_template);
  dvdbin->audio_pad = gst_ghost_pad_new_from_template ("audio", src, src_templ);
  gst_object_unref (src_templ);
  if (dvdbin->audio_pad == NULL)
    goto failed_aud_ghost;
  gst_pad_set_active (dvdbin->audio_pad, TRUE);
  bctx = g_slice_new (RsnDvdBinPadBlockCtx);
  bctx->dvdbin = gst_object_ref (dvdbin);
  bctx->pad = gst_object_ref (dvdbin->audio_pad);
  bctx->pad_block_id =
      gst_pad_add_probe (src, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
      (GstPadProbeCallback) dvdbin_pad_blocked_cb, bctx, (GDestroyNotify)
      _pad_block_destroy_notify);
  gst_object_unref (src);
  src = NULL;

  if (dvdbin->video_added && (dvdbin->audio_added || dvdbin->audio_broken)
      && dvdbin->subpicture_added) {
    rsn_dvdbin_no_more_pads (dvdbin);
  }

  return TRUE;

failed_connect:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not connect DVD source and demuxer elements"));
  goto error_out;
failed_vidparse_connect:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not connect DVD video parser and video decoder"));
  goto error_out;
failed_viddec_connect:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not connect DVD video decoder and aspect ratio adjuster"));
  goto error_out;
failed_video_ghost:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not ghost video output pad"));
  goto error_out;
failed_spuq_connect:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not connect DVD subpicture selector and buffer elements"));
  goto error_out;
failed_spu_ghost:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not ghost SPU output pad"));
  goto error_out;
failed_aud_connect:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not connect DVD audio decoder"));
  goto error_out;
failed_aud_ghost:
  GST_ELEMENT_ERROR (dvdbin, CORE, FAILED, (NULL),
      ("Could not ghost audio output pad"));
  goto error_out;
error_out:
  if (src != NULL)
    gst_object_unref (src);
  if (sink != NULL)
    gst_object_unref (sink);
  return FALSE;
}
示例#23
0
/* with PAD_LOCK */
static GstRtpSsrcDemuxPad *
create_demux_pad_for_ssrc (GstRtpSsrcDemux * demux, guint32 ssrc,
    GstClockTime timestamp)
{
  GstPad *rtp_pad, *rtcp_pad;
  GstElementClass *klass;
  GstPadTemplate *templ;
  gchar *padname;
  GstRtpSsrcDemuxPad *demuxpad;

  GST_DEBUG_OBJECT (demux, "creating pad for SSRC %08x", ssrc);

  klass = GST_ELEMENT_GET_CLASS (demux);
  templ = gst_element_class_get_pad_template (klass, "src_%d");
  padname = g_strdup_printf ("src_%d", ssrc);
  rtp_pad = gst_pad_new_from_template (templ, padname);
  g_free (padname);

  templ = gst_element_class_get_pad_template (klass, "rtcp_src_%d");
  padname = g_strdup_printf ("rtcp_src_%d", ssrc);
  rtcp_pad = gst_pad_new_from_template (templ, padname);
  g_free (padname);

  /* we use the first timestamp received to calculate the difference between
   * timestamps on all streams */
  GST_DEBUG_OBJECT (demux, "SSRC %08x, first timestamp %" GST_TIME_FORMAT,
      ssrc, GST_TIME_ARGS (timestamp));

  /* wrap in structure and add to list */
  demuxpad = g_new0 (GstRtpSsrcDemuxPad, 1);
  demuxpad->ssrc = ssrc;
  demuxpad->rtp_pad = rtp_pad;
  demuxpad->rtcp_pad = rtcp_pad;

  GST_DEBUG_OBJECT (demux, "first timestamp %" GST_TIME_FORMAT,
      GST_TIME_ARGS (timestamp));

  gst_pad_set_element_private (rtp_pad, demuxpad);
  gst_pad_set_element_private (rtcp_pad, demuxpad);

  demux->srcpads = g_slist_prepend (demux->srcpads, demuxpad);

  /* copy caps from input */
  gst_pad_set_caps (rtp_pad, GST_PAD_CAPS (demux->rtp_sink));
  gst_pad_use_fixed_caps (rtp_pad);
  gst_pad_set_caps (rtcp_pad, GST_PAD_CAPS (demux->rtcp_sink));
  gst_pad_use_fixed_caps (rtcp_pad);

  gst_pad_set_event_function (rtp_pad, gst_rtp_ssrc_demux_src_event);
  gst_pad_set_query_function (rtp_pad, gst_rtp_ssrc_demux_src_query);
  gst_pad_set_iterate_internal_links_function (rtp_pad,
      gst_rtp_ssrc_demux_iterate_internal_links);
  gst_pad_set_active (rtp_pad, TRUE);

  gst_pad_set_event_function (rtcp_pad, gst_rtp_ssrc_demux_src_event);
  gst_pad_set_iterate_internal_links_function (rtcp_pad,
      gst_rtp_ssrc_demux_iterate_internal_links);
  gst_pad_set_active (rtcp_pad, TRUE);

  gst_element_add_pad (GST_ELEMENT_CAST (demux), rtp_pad);
  gst_element_add_pad (GST_ELEMENT_CAST (demux), rtcp_pad);

  g_signal_emit (G_OBJECT (demux),
      gst_rtp_ssrc_demux_signals[SIGNAL_NEW_SSRC_PAD], 0, ssrc, rtp_pad);

  return demuxpad;
}
示例#24
0
static GstPad *
gst_live_adder_request_new_pad (GstElement * element, GstPadTemplate * templ,
                                const gchar * unused)
{
    gchar *name;
    GstLiveAdder *adder;
    GstPad *newpad;
    gint padcount;
    GstLiveAdderPadPrivate *padprivate = NULL;

    if (templ->direction != GST_PAD_SINK)
        goto not_sink;

    adder = GST_LIVE_ADDER (element);

    /* increment pad counter */
#if GLIB_CHECK_VERSION(2,29,5)
    padcount = g_atomic_int_add (&adder->padcount, 1);
#else
    padcount = g_atomic_int_exchange_and_add (&adder->padcount, 1);
#endif

    name = g_strdup_printf ("sink%d", padcount);
    newpad = gst_pad_new_from_template (templ, name);
    GST_DEBUG_OBJECT (adder, "request new pad %s", name);
    g_free (name);

    gst_pad_set_getcaps_function (newpad,
                                  GST_DEBUG_FUNCPTR (gst_live_adder_sink_getcaps));
    gst_pad_set_setcaps_function (newpad,
                                  GST_DEBUG_FUNCPTR (gst_live_adder_setcaps));
    gst_pad_set_event_function (newpad,
                                GST_DEBUG_FUNCPTR (gst_live_adder_sink_event));

    padprivate = g_new0 (GstLiveAdderPadPrivate, 1);

    gst_segment_init (&padprivate->segment, GST_FORMAT_UNDEFINED);
    padprivate->eos = FALSE;
    padprivate->expected_timestamp = GST_CLOCK_TIME_NONE;

    gst_pad_set_element_private (newpad, padprivate);

    gst_pad_set_chain_function (newpad, gst_live_live_adder_chain);


    if (!gst_pad_set_active (newpad, TRUE))
        goto could_not_activate;

    /* takes ownership of the pad */
    if (!gst_element_add_pad (GST_ELEMENT (adder), newpad))
        goto could_not_add;

    GST_OBJECT_LOCK (adder);
    adder->sinkpads = g_list_prepend (adder->sinkpads, newpad);
    GST_OBJECT_UNLOCK (adder);

    return newpad;

    /* errors */
not_sink:
    {
        g_warning ("gstadder: request new pad that is not a SINK pad\n");
        return NULL;
    }
could_not_add:
    {
        GST_DEBUG_OBJECT (adder, "could not add pad");
        g_free (padprivate);
        gst_object_unref (newpad);
        return NULL;
    }
could_not_activate:
    {
        GST_DEBUG_OBJECT (adder, "could not activate new pad");
        g_free (padprivate);
        gst_object_unref (newpad);
        return NULL;
    }
}
int main(int argc, char *argv[])
{
  GstElement *pipeline, *bin, *effect_element, *convert, *sink;
  GstPad *pad, *ghost_pad;
  char *pipeline_str;
  GIOChannel *io_stdin = g_io_channel_unix_new(fileno(stdin));
  CustomData data;
  GstStateChangeReturn ret;
  gboolean list_effects = FALSE;
  gchar *effect_name = NULL;
  GError *error = NULL;
  GstPlugin *gaudiplugin;
  gchar *props_str = NULL;
  GOptionContext *context;
  GOptionEntry options[] = {
    { "list-effects", 'l', 0, G_OPTION_ARG_NONE, &list_effects,
      "list available effects and exits", NULL },
    { "effect", 'e', 0, G_OPTION_ARG_STRING, &effect_name,
      "set the desired effect", NULL },
    { "props", 'p', 0, G_OPTION_ARG_STRING, &props_str,
      "for property setting (-p \"silent,bool,true;adjustement,uint,150\")",
      NULL },
    { NULL }
  };

  setlocale(LC_ALL, "fr_FR.utf8");

  gst_init(&argc, &argv);

  gaudiplugin = gst_registry_find_plugin(GET_PLUGIN_REGISTRY, "gaudieffects");
  if (gaudiplugin == NULL) {
    g_print("Pas de plugin “gaudieffects” trouvé !! :(\n");
    return -1;
  }

  context = g_option_context_new("");
  g_option_context_add_main_entries(context, options, "");
  if (!g_option_context_parse(context, &argc, &argv, &error)) {
    g_print("option parsing failed: %s\n", error->message);
    return -1;
  }
  g_option_context_free(context);

  if (list_effects == TRUE)
    return  list_gaudieffects_features();

  if (argc > 1) {
    if (g_str_has_prefix(argv[1], "http://") ||
	g_str_has_prefix(argv[1], "ftp://"))
      pipeline_str = g_strdup_printf("%s uri=\"%s\"", PLAYBIN, argv[1]);
    else if (argv[1][0] == '~')
      pipeline_str = g_strdup_printf("%s uri=\"file://%s%s\"", PLAYBIN,
				     g_get_home_dir(), argv[1]+1);
    else if (g_file_test(argv[1], G_FILE_TEST_IS_REGULAR))
      pipeline_str = g_strdup_printf("playbin uri=\"file://%s\"", argv[1]);
    else
      pipeline_str = g_strdup_printf("%s uri=%s", PLAYBIN, DEFAULT_URI);
  } else
    pipeline_str = g_strdup_printf("%s uri=%s", PLAYBIN, DEFAULT_URI);

  g_io_add_watch(io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);

  pipeline = gst_parse_launch(pipeline_str, NULL);

  if (gst_plugin_is_loaded(gaudiplugin) == FALSE)
    gst_plugin_load(gaudiplugin);

  if (effect_name == NULL)
    effect_name = "solarize";

  effect_element = gst_element_factory_make(effect_name, effect_name);
  convert = gst_element_factory_make("videoconvert", "convert");
  sink = gst_element_factory_make("autovideosink", "video_sink");
  if (!effect_element || !convert || !sink) {
    g_printerr("Not all elements could be created.\n");
    return -1;
  }

  bin = gst_bin_new("video_sink_bin");
  gst_bin_add_many(GST_BIN(bin), effect_element, convert, sink, NULL);
  gst_element_link_many(effect_element, convert, sink, NULL);
  pad = gst_element_get_static_pad(effect_element, "sink");
  ghost_pad = gst_ghost_pad_new("sink", pad);
  gst_pad_set_active(ghost_pad, TRUE);
  gst_element_add_pad(bin, ghost_pad);
  gst_object_unref(pad);

  g_object_set(GST_OBJECT(pipeline), "video-sink", bin, NULL);

  if (props_str != NULL)
    set_props(effect_element, props_str);

  ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
    g_printerr("Unable to set the pipeline to the playing state.\n");
    gst_object_unref(pipeline);
    return -1;
  }

  data.loop = g_main_loop_new(NULL, FALSE);
  g_main_loop_run(data.loop);

  g_io_channel_unref(io_stdin);

  gst_element_set_state(pipeline, GST_STATE_NULL);

  gst_object_unref(pipeline);

  return 0;
}
示例#26
0
static void
_audiodecoder_flush_events (gboolean send_buffers)
{
  GstSegment segment;
  GstBuffer *buffer;
  guint64 i;
  GList *events_iter;
  GstMessage *msg;

  setup_audiodecodertester ();

  gst_pad_set_active (mysrcpad, TRUE);
  gst_element_set_state (dec, GST_STATE_PLAYING);
  gst_pad_set_active (mysinkpad, TRUE);

  send_startup_events ();

  /* push a new segment */
  gst_segment_init (&segment, GST_FORMAT_TIME);
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_segment (&segment)));

  if (send_buffers) {
    /* push buffers, the data is actually a number so we can track them */
    for (i = 0; i < NUM_BUFFERS; i++) {
      if (i % 10 == 0) {
        GstTagList *tags;

        tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, i, NULL);
        fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
      } else {
        buffer = create_test_buffer (i);

        fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK);
      }
    }
  } else {
    /* push sticky event */
    GstTagList *tags;
    tags = gst_tag_list_new (GST_TAG_TRACK_NUMBER, 0, NULL);
    fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_tag (tags)));
  }

  msg =
      gst_message_new_element (GST_OBJECT (mysrcpad),
      gst_structure_new_empty ("test"));
  fail_unless (gst_pad_push_event (mysrcpad,
      gst_event_new_sink_message ("test", msg)));
  gst_message_unref (msg);

  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()));

  events_iter = events;
  /* make sure the usual events have been received */
  {
    GstEvent *sstart = events_iter->data;
    fail_unless (GST_EVENT_TYPE (sstart) == GST_EVENT_STREAM_START);
    events_iter = g_list_next (events_iter);
  }
  if (send_buffers) {
    {
      GstEvent *caps_event = events_iter->data;
      fail_unless (GST_EVENT_TYPE (caps_event) == GST_EVENT_CAPS);
      events_iter = g_list_next (events_iter);
    }
    {
      GstEvent *segment_event = events_iter->data;
      fail_unless (GST_EVENT_TYPE (segment_event) == GST_EVENT_SEGMENT);
      events_iter = g_list_next (events_iter);
    }
    for (int i=0; i< NUM_BUFFERS / 10; i++)
    {
      GstEvent *tag_event = events_iter->data;
      fail_unless (GST_EVENT_TYPE (tag_event) == GST_EVENT_TAG);
      events_iter = g_list_next (events_iter);
    }
  }
  {
    GstEvent *eos_event = events_iter->data;
    fail_unless (GST_EVENT_TYPE (eos_event) == GST_EVENT_EOS);
    events_iter = g_list_next (events_iter);
  }

  /* check that EOS was received */
  fail_unless (GST_PAD_IS_EOS (mysrcpad));
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_start ()));
  fail_unless (GST_PAD_IS_EOS (mysrcpad));

  /* Check that we have tags */
  {
    GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0);

    fail_unless (tags != NULL);
    gst_event_unref (tags);
  }

  /* Check that we still have a segment set */
  {
    GstEvent *segment =
        gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0);

    fail_unless (segment != NULL);
    gst_event_unref (segment);
  }

  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_flush_stop (TRUE)));
  fail_if (GST_PAD_IS_EOS (mysrcpad));

  /* Check that the segment was flushed on FLUSH_STOP */
  {
    GstEvent *segment =
        gst_pad_get_sticky_event (mysrcpad, GST_EVENT_SEGMENT, 0);

    fail_unless (segment == NULL);
  }

  /* Check the tags were not lost on FLUSH_STOP */
  {
    GstEvent *tags = gst_pad_get_sticky_event (mysrcpad, GST_EVENT_TAG, 0);

    fail_unless (tags != NULL);
    gst_event_unref (tags);

  }

  g_list_free_full (buffers, (GDestroyNotify) gst_buffer_unref);
  buffers = NULL;

  gst_element_set_state (dec, GST_STATE_NULL);
  cleanup_audiodecodertest ();
}
示例#27
0
static void
gst_wavpack_enc_set_wp_config (GstWavpackEnc * enc)
{
  enc->wp_config = g_new0 (WavpackConfig, 1);
  /* set general stream informations in the WavpackConfig */
  enc->wp_config->bytes_per_sample = GST_ROUND_UP_8 (enc->depth) / 8;
  enc->wp_config->bits_per_sample = enc->depth;
  enc->wp_config->num_channels = enc->channels;
  enc->wp_config->channel_mask = enc->channel_mask;
  enc->wp_config->sample_rate = enc->samplerate;

  /*
   * Set parameters in WavpackConfig
   */

  /* Encoding mode */
  switch (enc->mode) {
#if 0
    case GST_WAVPACK_ENC_MODE_VERY_FAST:
      enc->wp_config->flags |= CONFIG_VERY_FAST_FLAG;
      enc->wp_config->flags |= CONFIG_FAST_FLAG;
      break;
#endif
    case GST_WAVPACK_ENC_MODE_FAST:
      enc->wp_config->flags |= CONFIG_FAST_FLAG;
      break;
    case GST_WAVPACK_ENC_MODE_DEFAULT:
      break;
    case GST_WAVPACK_ENC_MODE_HIGH:
      enc->wp_config->flags |= CONFIG_HIGH_FLAG;
      break;
#ifndef WAVPACK_OLD_API
    case GST_WAVPACK_ENC_MODE_VERY_HIGH:
      enc->wp_config->flags |= CONFIG_HIGH_FLAG;
      enc->wp_config->flags |= CONFIG_VERY_HIGH_FLAG;
      break;
#endif
  }

  /* Bitrate, enables lossy mode */
  if (enc->bitrate) {
    enc->wp_config->flags |= CONFIG_HYBRID_FLAG;
    enc->wp_config->flags |= CONFIG_BITRATE_KBPS;
    enc->wp_config->bitrate = enc->bitrate / 1000.0;
  } else if (enc->bps) {
    enc->wp_config->flags |= CONFIG_HYBRID_FLAG;
    enc->wp_config->bitrate = enc->bps;
  }

  /* Correction Mode, only in lossy mode */
  if (enc->wp_config->flags & CONFIG_HYBRID_FLAG) {
    if (enc->correction_mode > GST_WAVPACK_CORRECTION_MODE_OFF) {
      GstCaps *caps = gst_caps_new_simple ("audio/x-wavpack-correction",
          "framed", G_TYPE_BOOLEAN, TRUE, NULL);

      enc->wvcsrcpad =
          gst_pad_new_from_static_template (&wvcsrc_factory, "wvcsrc");

      /* try to add correction src pad, don't set correction mode on failure */
      GST_DEBUG_OBJECT (enc, "Adding correction pad with caps %"
          GST_PTR_FORMAT, caps);
      if (!gst_pad_set_caps (enc->wvcsrcpad, caps)) {
        enc->correction_mode = 0;
        GST_WARNING_OBJECT (enc, "setting correction caps failed");
      } else {
        gst_pad_use_fixed_caps (enc->wvcsrcpad);
        gst_pad_set_active (enc->wvcsrcpad, TRUE);
        gst_element_add_pad (GST_ELEMENT (enc), enc->wvcsrcpad);
        enc->wp_config->flags |= CONFIG_CREATE_WVC;
        if (enc->correction_mode == GST_WAVPACK_CORRECTION_MODE_OPTIMIZED) {
          enc->wp_config->flags |= CONFIG_OPTIMIZE_WVC;
        }
      }
      gst_caps_unref (caps);
    }
  } else {
    if (enc->correction_mode > GST_WAVPACK_CORRECTION_MODE_OFF) {
      enc->correction_mode = 0;
      GST_WARNING_OBJECT (enc, "setting correction mode only has "
          "any effect if a bitrate is provided.");
    }
  }
  gst_element_no_more_pads (GST_ELEMENT (enc));

  /* MD5, setup MD5 context */
  if ((enc->md5) && !(enc->md5_context)) {
    enc->wp_config->flags |= CONFIG_MD5_CHECKSUM;
    enc->md5_context = g_new0 (MD5_CTX, 1);
    MD5Init (enc->md5_context);
  }

  /* Extra encode processing */
  if (enc->extra_processing) {
    enc->wp_config->flags |= CONFIG_EXTRA_MODE;
    enc->wp_config->xmode = enc->extra_processing;
  }

  /* Joint stereo mode */
  switch (enc->joint_stereo_mode) {
    case GST_WAVPACK_JS_MODE_AUTO:
      break;
    case GST_WAVPACK_JS_MODE_LEFT_RIGHT:
      enc->wp_config->flags |= CONFIG_JOINT_OVERRIDE;
      enc->wp_config->flags &= ~CONFIG_JOINT_STEREO;
      break;
    case GST_WAVPACK_JS_MODE_MID_SIDE:
      enc->wp_config->flags |= (CONFIG_JOINT_OVERRIDE | CONFIG_JOINT_STEREO);
      break;
  }
}