/*
 * Sets the caps on deinterlace sinkpad and validates the
 * caps that is set on the srcpad
 */
static void
deinterlace_set_caps_and_check (GstCaps * input, gboolean must_deinterlace)
{
  GstCaps *othercaps = NULL;
  GstSegment segment;

  gst_pad_send_event (sinkpad, gst_event_new_stream_start ("test"));
  fail_unless (gst_pad_set_caps (sinkpad, input));
  gst_segment_init (&segment, GST_FORMAT_TIME);
  gst_pad_send_event (sinkpad, gst_event_new_segment (&segment));

  g_object_get (srcpad, "caps", &othercaps, NULL);

  if (must_deinterlace) {
    fail_if (gst_caps_is_interlaced (othercaps));
  } else {
    GstStructure *s;

    fail_unless (gst_caps_is_interlaced (input) ==
        gst_caps_is_interlaced (othercaps));

    othercaps = gst_caps_make_writable (othercaps);
    s = gst_caps_get_structure (othercaps, 0);
    gst_structure_remove_field (s, "interlace-mode");

    input = gst_caps_make_writable (input);
    s = gst_caps_get_structure (input, 0);
    gst_structure_remove_field (s, "interlace-mode");

    fail_unless (gst_caps_is_equal (input, othercaps));
  }
  gst_caps_unref (input);
  gst_caps_unref (othercaps);
}
Пример #2
0
static gboolean
prepare_src_pad (MpegTSBase * base, MpegTSParse2 * parse)
{
  GstEvent *event;
  gchar *stream_id;
  GstCaps *caps;

  if (!parse->first)
    return TRUE;

  /* If there's no packet_size yet, we can't set caps yet */
  if (G_UNLIKELY (base->packetizer->packet_size == 0))
    return FALSE;

  stream_id =
      gst_pad_create_stream_id (parse->srcpad, GST_ELEMENT_CAST (base),
      "multi-program");

  event =
      gst_pad_get_sticky_event (parse->parent.sinkpad, GST_EVENT_STREAM_START,
      0);
  if (event) {
    if (gst_event_parse_group_id (event, &parse->group_id))
      parse->have_group_id = TRUE;
    else
      parse->have_group_id = FALSE;
    gst_event_unref (event);
  } else if (!parse->have_group_id) {
    parse->have_group_id = TRUE;
    parse->group_id = gst_util_group_id_next ();
  }
  event = gst_event_new_stream_start (stream_id);
  if (parse->have_group_id)
    gst_event_set_group_id (event, parse->group_id);

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

  caps = gst_caps_new_simple ("video/mpegts",
      "systemstream", G_TYPE_BOOLEAN, TRUE,
      "packetsize", G_TYPE_INT, base->packetizer->packet_size, NULL);

  gst_pad_set_caps (parse->srcpad, caps);
  gst_caps_unref (caps);

  /* If setting output timestamps, ensure that the output segment is TIME */
  if (parse->set_timestamps == FALSE || base->segment.format == GST_FORMAT_TIME)
    gst_pad_push_event (parse->srcpad, gst_event_new_segment (&base->segment));
  else {
    GstSegment seg;
    gst_segment_init (&seg, GST_FORMAT_TIME);
    GST_DEBUG_OBJECT (parse,
        "Generating time output segment %" GST_SEGMENT_FORMAT, &seg);
    gst_pad_push_event (parse->srcpad, gst_event_new_segment (&seg));
  }

  parse->first = FALSE;

  return TRUE;
}
Пример #3
0
static void
switch_pads (GstHLSDemux * demux, GstCaps * newcaps)
{
  GstPad *oldpad = demux->srcpad;

  GST_DEBUG ("Switching pads (oldpad:%p) with caps: %" GST_PTR_FORMAT, oldpad,
      newcaps);

  /* First create and activate new pad */
  demux->srcpad = gst_pad_new_from_static_template (&srctemplate, NULL);
  gst_pad_set_event_function (demux->srcpad,
      GST_DEBUG_FUNCPTR (gst_hls_demux_src_event));
  gst_pad_set_query_function (demux->srcpad,
      GST_DEBUG_FUNCPTR (gst_hls_demux_src_query));
  gst_pad_set_element_private (demux->srcpad, demux);
  gst_pad_set_active (demux->srcpad, TRUE);
  gst_pad_push_event (demux->srcpad, gst_event_new_stream_start ());
  gst_pad_set_caps (demux->srcpad, newcaps);
  gst_element_add_pad (GST_ELEMENT (demux), demux->srcpad);

  gst_element_no_more_pads (GST_ELEMENT (demux));

  if (oldpad) {
    /* Push out EOS */
    gst_pad_push_event (oldpad, gst_event_new_eos ());
    gst_pad_set_active (oldpad, FALSE);
    gst_element_remove_pad (GST_ELEMENT (demux), oldpad);
  }
}
static void
udpsink_test (gboolean use_buffer_lists)
{
  GstSegment segment;
  GstElement *udpsink;
  GstPad *srcpad;
  GstBufferList *list;
  guint data_size;

  list = create_buffer_list (&data_size);

  udpsink = gst_check_setup_element ("udpsink");
  if (use_buffer_lists)
    set_render_list_function (udpsink);

  srcpad = gst_check_setup_src_pad_by_name (udpsink, &srctemplate, "sink");

  gst_element_set_state (udpsink, GST_STATE_PLAYING);
  gst_pad_set_active (srcpad, TRUE);

  gst_pad_push_event (srcpad, gst_event_new_stream_start ("hey there!"));

  gst_segment_init (&segment, GST_FORMAT_TIME);
  gst_pad_push_event (srcpad, gst_event_new_segment (&segment));

  fail_unless_equals_int (gst_pad_push_list (srcpad, list), GST_FLOW_OK);

  gst_check_teardown_pad_by_name (udpsink, "sink");
  gst_check_teardown_element (udpsink);

  if (use_buffer_lists)
    fail_unless_equals_int (data_size, render_list_bytes_received);
}
Пример #5
0
static GstFlowReturn
gst_dtls_enc_push (GstDtlsEnc * self, GstBuffer * buffer)
{
  GstDtlsBase *base = GST_DTLS_BASE (self);
  GstEvent *segment_event, *caps_event;
  gchar *stream_id;

  stream_id = gst_pad_get_stream_id (base->srcpad);

  if (stream_id == NULL) {
    stream_id = gst_pad_get_stream_id (base->sinkpad);

    if (stream_id == NULL) {
      stream_id = gst_pad_create_stream_id (base->srcpad,
          GST_ELEMENT (base), NULL);
    }

    gst_pad_push_event (base->srcpad, gst_event_new_stream_start (stream_id));
  }

  g_free (stream_id);

  caps_event = gst_pad_get_sticky_event (base->srcpad, GST_EVENT_CAPS, 0);

  if (caps_event == NULL) {
    GstCaps *caps = gst_caps_from_string ("application/x-dtls");

    caps_event = gst_event_new_caps (caps);
    gst_caps_unref (caps);

    gst_pad_push_event (base->srcpad, caps_event);
  } else {
    gst_event_unref (caps_event);
  }

  segment_event = gst_pad_get_sticky_event (base->srcpad, GST_EVENT_SEGMENT, 0);

  if (segment_event == NULL) {
    GstSegment *segment = gst_segment_new ();

    gst_segment_init (segment, GST_FORMAT_BYTES);
    segment_event = gst_event_new_segment (segment);
    gst_segment_free (segment);

    gst_pad_push_event (base->srcpad, segment_event);
  } else {
    gst_event_unref (segment_event);
  }

  GST_OBJECT_LOCK (self);
  if (self->src_buffer && self->running_thread == g_thread_self ()) {
    g_assert (gst_buffer_get_size (buffer) != 181);
    gst_buffer_copy_into (buffer, self->src_buffer, GST_BUFFER_COPY_METADATA, 0,
        -1);
  }
  GST_OBJECT_UNLOCK (self);

  return gst_pad_push (base->srcpad, buffer);
}
Пример #6
0
static gboolean
gst_droidcamsrc_mode_negotiate_pad (GstDroidCamSrcMode * mode, GstPad * pad,
    gboolean force)
{
  GstDroidCamSrcPad *data = gst_pad_get_element_private (pad);
  /* take pad lock */
  g_mutex_lock (&data->lock);

  if (!force) {
    if (!gst_pad_check_reconfigure (data->pad)) {
      g_mutex_unlock (&data->lock);
      return TRUE;
    }
  }

  /*
   * stream start
   * we must send it before we send our CAPS event
   */
  if (G_UNLIKELY (data->open_stream)) {
    gchar *stream_id;
    GstEvent *event;

    stream_id =
        gst_pad_create_stream_id (data->pad, GST_ELEMENT_CAST (mode->src),
        GST_PAD_NAME (data->pad));

    GST_DEBUG_OBJECT (pad, "Pushing STREAM_START for pad");
    event = gst_event_new_stream_start (stream_id);
    gst_event_set_group_id (event, gst_util_group_id_next ());
    if (!gst_pad_push_event (data->pad, event)) {
      GST_ERROR_OBJECT (mode->src,
          "failed to push STREAM_START event for pad %s",
          GST_PAD_NAME (data->pad));
    }

    g_free (stream_id);
    data->open_stream = FALSE;
  }

  /* negotiate */
  if (!data->negotiate (data)) {
    GST_ELEMENT_ERROR (mode->src, STREAM, FORMAT, (NULL),
        ("failed to negotiate %s.", GST_PAD_NAME (data->pad)));

    g_mutex_unlock (&data->lock);
    return FALSE;
  }

  /* toss pad queue */
  g_queue_foreach (data->queue, (GFunc) gst_buffer_unref, NULL);
  g_queue_clear (data->queue);

  /* unlock */
  g_mutex_unlock (&data->lock);

  return TRUE;
}
static GstEvent *
create_new_stream_start_event (GstHarness * h, gpointer data)
{
  guint *counter = data;
  gchar *stream_id = g_strdup_printf ("streamid/%d", *counter);
  GstEvent *event = gst_event_new_stream_start (stream_id);
  g_free (stream_id);
  (*counter)++;
  return event;
}
Пример #8
0
static void
gst_decklink_src_send_initial_events (GstDecklinkSrc * src)
{
  GstSegment segment;
  GstEvent *event;
  guint group_id;
  guint32 audio_id, video_id;
  gchar stream_id[9];

  /* stream-start */
  audio_id = g_random_int ();
  video_id = g_random_int ();
  while (video_id == audio_id)
    video_id = g_random_int ();

  group_id = gst_util_group_id_next ();
  g_snprintf (stream_id, sizeof (stream_id), "%08x", audio_id);
  event = gst_event_new_stream_start (stream_id);
  gst_event_set_group_id (event, group_id);
  gst_pad_push_event (src->audiosrcpad, event);

  g_snprintf (stream_id, sizeof (stream_id), "%08x", video_id);
  event = gst_event_new_stream_start (stream_id);
  gst_event_set_group_id (event, group_id);
  gst_pad_push_event (src->videosrcpad, event);

  /* segment */
  gst_segment_init (&segment, GST_FORMAT_TIME);
  event = gst_event_new_segment (&segment);
  gst_pad_push_event (src->videosrcpad, gst_event_ref (event));
  gst_pad_push_event (src->audiosrcpad, event);

  /* caps */
  gst_pad_push_event (src->audiosrcpad,
      gst_event_new_caps (gst_caps_new_simple ("audio/x-raw",
          "format", G_TYPE_STRING, "S16LE", "channels", G_TYPE_INT, 2,
          "rate", G_TYPE_INT, 48000, "layout", G_TYPE_STRING, "interleaved",
          NULL)));

  gst_pad_push_event (src->videosrcpad,
      gst_event_new_caps (gst_decklink_mode_get_caps (src->mode)));
}
Пример #9
0
static inline void
_push_mandatory_events (GstAggregator * self)
{
  GstAggregatorPrivate *priv = self->priv;

  if (g_atomic_int_get (&self->priv->send_stream_start)) {
    gchar s_id[32];

    GST_INFO_OBJECT (self, "pushing stream start");
    /* stream-start (FIXME: create id based on input ids) */
    g_snprintf (s_id, sizeof (s_id), "agg-%08x", g_random_int ());
    if (!gst_pad_push_event (self->srcpad, gst_event_new_stream_start (s_id))) {
      GST_WARNING_OBJECT (self->srcpad, "Sending stream start event failed");
    }
    g_atomic_int_set (&self->priv->send_stream_start, FALSE);
  }

  if (self->priv->srccaps) {

    GST_INFO_OBJECT (self, "pushing caps: %" GST_PTR_FORMAT,
        self->priv->srccaps);
    if (!gst_pad_push_event (self->srcpad,
            gst_event_new_caps (self->priv->srccaps))) {
      GST_WARNING_OBJECT (self->srcpad, "Sending caps event failed");
    }
    gst_caps_unref (self->priv->srccaps);
    self->priv->srccaps = NULL;
  }

  if (g_atomic_int_get (&self->priv->send_segment)) {
    if (!g_atomic_int_get (&self->priv->flush_seeking)) {
      GstEvent *segev = gst_event_new_segment (&self->segment);

      if (!self->priv->seqnum)
        self->priv->seqnum = gst_event_get_seqnum (segev);
      else
        gst_event_set_seqnum (segev, self->priv->seqnum);

      GST_DEBUG_OBJECT (self, "pushing segment %" GST_PTR_FORMAT, segev);
      gst_pad_push_event (self->srcpad, segev);
      g_atomic_int_set (&self->priv->send_segment, FALSE);
    }
  }

  if (priv->tags && priv->tags_changed) {
    gst_pad_push_event (self->srcpad,
        gst_event_new_tag (gst_tag_list_ref (priv->tags)));
    priv->tags_changed = FALSE;
  }
}
Пример #10
0
static void
gst_check_setup_events_textoverlay (GstPad * srcpad, GstElement * element,
    GstCaps * caps, GstFormat format, const gchar * stream_id)
{
  GstSegment segment;

  gst_segment_init (&segment, format);

  fail_unless (gst_pad_push_event (srcpad,
          gst_event_new_stream_start (stream_id)));
  if (caps)
    fail_unless (gst_pad_push_event (srcpad, gst_event_new_caps (caps)));
  fail_unless (gst_pad_push_event (srcpad, gst_event_new_segment (&segment)));
}
Пример #11
0
static void
send_startup_events (void)
{
  GstCaps *caps;

  fail_unless (gst_pad_push_event (mysrcpad,
          gst_event_new_stream_start ("randomvalue")));

  /* push caps */
  caps =
      gst_caps_new_simple ("audio/x-test-custom", "channels", G_TYPE_INT, 2,
      "rate", G_TYPE_INT, 44100, NULL);
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps)));

}
static GstFlowReturn
gst_agregator_collected (GstCollectPads * pads, gpointer user_data)
{
  GstAggregator *aggregator = GST_AGGREGATOR (user_data);
  GstBuffer *inbuf;
  GstCollectData *collect_data = NULL;
  guint outsize = 0;
  GSList *walk;

  walk = pads->data;
  for (walk = pads->data; walk; walk = walk->next) {
    GstCollectData *tmp = (GstCollectData *) walk->data;
    if (tmp->buffer) {
      collect_data = tmp;
      break;
    }
  }

  /* can only happen when no pads to collect or all EOS */
  if (collect_data == NULL)
    goto eos;

  outsize = gst_buffer_get_size (collect_data->buffer);
  inbuf = gst_collect_pads_take_buffer (pads, collect_data, outsize);
  if (!inbuf)
    goto eos;

  if (aggregator->first) {
    GstSegment segment;

    gst_segment_init (&segment, GST_FORMAT_BYTES);
    gst_pad_push_event (aggregator->srcpad,
        gst_event_new_stream_start ("test"));
    gst_pad_push_event (aggregator->srcpad, gst_event_new_segment (&segment));
    aggregator->first = FALSE;
  }

  /* just forward the first buffer */
  GST_DEBUG_OBJECT (aggregator, "forward buffer %p", inbuf);
  return gst_pad_push (aggregator->srcpad, inbuf);
  /* ERRORS */
eos:
  {
    GST_DEBUG_OBJECT (aggregator, "no data available, must be EOS");
    gst_pad_push_event (aggregator->srcpad, gst_event_new_eos ());
    return GST_FLOW_EOS;
  }
}
Пример #13
0
static void
send_startup_events (void)
{
  GstCaps *caps;

  fail_unless (gst_pad_push_event (mysrcpad,
          gst_event_new_stream_start ("randomvalue")));

  /* push caps */
  caps =
      gst_caps_new_simple ("audio/x-raw", "rate", G_TYPE_INT,
      TEST_AUDIO_RATE, "channels", G_TYPE_INT, TEST_AUDIO_CHANNELS, "format",
      G_TYPE_STRING, "S16LE", "layout", G_TYPE_STRING, "interleaved", NULL);
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps)));
  gst_caps_unref (caps);
}
static void
send_startup_events (void)
{
  GstCaps *caps;

  fail_unless (gst_pad_push_event (mysrcpad,
          gst_event_new_stream_start ("randomvalue")));

  /* push caps */
  caps =
      gst_caps_new_simple ("video/x-test-custom", "width", G_TYPE_INT,
      TEST_VIDEO_WIDTH, "height", G_TYPE_INT, TEST_VIDEO_HEIGHT, "framerate",
      GST_TYPE_FRACTION, TEST_VIDEO_FPS_N, TEST_VIDEO_FPS_D, NULL);
  fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_caps (caps)));
  gst_caps_unref (caps);
}
Пример #15
0
static gboolean
gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
{
  GstStructure *structure;
  gboolean ret = FALSE;
  GstRTPMuxPadPrivate *padpriv;

  structure = gst_caps_get_structure (caps, 0);

  if (!structure)
    return FALSE;

  GST_OBJECT_LOCK (rtp_mux);
  padpriv = gst_pad_get_element_private (pad);
  if (padpriv &&
      gst_structure_get_uint (structure, "timestamp-offset",
          &padpriv->timestamp_offset)) {
    padpriv->have_timestamp_offset = TRUE;
  }
  GST_OBJECT_UNLOCK (rtp_mux);

  caps = gst_caps_copy (caps);

  gst_caps_set_simple (caps,
      "timestamp-offset", G_TYPE_UINT, rtp_mux->ts_base,
      "seqnum-offset", G_TYPE_UINT, rtp_mux->seqnum_base, NULL);

  if (rtp_mux->send_stream_start) {
    gchar s_id[32];

    /* stream-start (FIXME: create id based on input ids) */
    g_snprintf (s_id, sizeof (s_id), "interleave-%08x", g_random_int ());
    gst_pad_push_event (rtp_mux->srcpad, gst_event_new_stream_start (s_id));

    rtp_mux->send_stream_start = FALSE;
  }

  GST_DEBUG_OBJECT (rtp_mux,
      "setting caps %" GST_PTR_FORMAT " on src pad..", caps);
  ret = gst_pad_set_caps (rtp_mux->srcpad, caps);

  gst_structure_get_uint (structure, "ssrc", &rtp_mux->current_ssrc);

  gst_caps_unref (caps);

  return ret;
}
Пример #16
0
static void
gst_interleave_send_stream_start (GstInterleave * self)
{
  GST_OBJECT_LOCK (self);
  if (self->send_stream_start) {
    gchar s_id[32];

    self->send_stream_start = FALSE;
    GST_OBJECT_UNLOCK (self);

    /* stream-start (FIXME: create id based on input ids) */
    g_snprintf (s_id, sizeof (s_id), "interleave-%08x", g_random_int ());
    gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
  } else {
    GST_OBJECT_UNLOCK (self);
  }
}
Пример #17
0
static gpointer
push_buffer (gpointer user_data)
{
  GstFlowReturn flow;
  GstCaps *caps;
  TestData *test_data = (TestData *) user_data;

  gst_pad_push_event (test_data->pad, gst_event_new_stream_start ("test"));

  caps = gst_caps_new_empty_simple ("foo/x-bar");
  gst_pad_push_event (test_data->pad, gst_event_new_caps (caps));
  gst_caps_unref (caps);

  flow = gst_pad_push (test_data->pad, test_data->buffer);
  fail_unless (flow == GST_FLOW_OK, "got flow %s instead of OK",
      gst_flow_get_name (flow));

  return NULL;
}
Пример #18
0
static gpointer
push_vbuffers (gpointer data)
{
  GstSegment segment;
  GstPad *pad = data;
  gint i;
  GstClockTime timestamp = 0;

  if (videodelay)
    g_usleep (2000);

  if (late_video)
    timestamp = 50 * GST_MSECOND;

  gst_pad_send_event (pad, gst_event_new_stream_start ("test"));
  gst_segment_init (&segment, GST_FORMAT_TIME);
  gst_pad_send_event (pad, gst_event_new_segment (&segment));

  for (i = 0; i < n_vbuffers; i++) {
    GstBuffer *buf = gst_buffer_new_and_alloc (1000);
    GstClockTime *rtime = g_new (GstClockTime, 1);

    gst_buffer_memset (buf, 0, i, 1);

    GST_BUFFER_TIMESTAMP (buf) = timestamp;
    timestamp += 25 * GST_MSECOND;
    GST_BUFFER_DURATION (buf) = timestamp - GST_BUFFER_TIMESTAMP (buf);
    *rtime = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, timestamp);
    g_queue_push_tail (&v_timestamp_q, rtime);

    if (i == 4) {
      if (video_gaps)
        timestamp += 10 * GST_MSECOND;
      else if (video_overlaps)
        timestamp -= 10 * GST_MSECOND;
    }

    fail_unless (gst_pad_chain (pad, buf) == GST_FLOW_OK);
  }
  gst_pad_send_event (pad, gst_event_new_eos ());

  return NULL;
}
static GstElement *
setup_wavpackenc (void)
{
  GstElement *wavpackenc;

  GST_DEBUG ("setup_wavpackenc");
  wavpackenc = gst_check_setup_element ("wavpackenc");
  mysrcpad = gst_check_setup_src_pad (wavpackenc, &srctemplate);
  mysinkpad = gst_check_setup_sink_pad (wavpackenc, &sinktemplate);
  gst_pad_set_active (mysrcpad, TRUE);
  gst_pad_set_active (mysinkpad, TRUE);

  fail_unless (gst_element_set_state (wavpackenc,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
      "could not set to playing");
  bus = gst_bus_new ();

  gst_pad_push_event (mysrcpad, gst_event_new_stream_start ("test-silence"));

  return wavpackenc;
}
Пример #20
0
/* prepare the source pad for output */
static gboolean
mpegpsdemux_prepare_srcpad (MpegPsMux * mux)
{
  GstSegment segment;
  GValue val = { 0, };
  GList *headers, *l;
  GstCaps *caps;
  gchar s_id[32];

  /* stream-start (FIXME: create id based on input ids) */
  g_snprintf (s_id, sizeof (s_id), "mpegpsmux-%08x", g_random_int ());
  gst_pad_push_event (mux->srcpad, gst_event_new_stream_start (s_id));

  caps = gst_caps_new_simple ("video/mpeg",
      "mpegversion", G_TYPE_INT, 2, "systemstream", G_TYPE_BOOLEAN, TRUE, NULL);

  headers = psmux_get_stream_headers (mux->psmux);
  g_value_init (&val, GST_TYPE_ARRAY);
  for (l = headers; l != NULL; l = l->next) {
    GValue buf_val = { 0, };

    g_value_init (&buf_val, GST_TYPE_BUFFER);
    gst_value_take_buffer (&buf_val, GST_BUFFER (l->data));
    l->data = NULL;
    gst_value_array_append_value (&val, &buf_val);
    g_value_unset (&buf_val);
  }
  gst_caps_set_value (caps, "streamheader", &val);
  g_value_unset (&val);
  g_list_free (headers);

  /* Set caps on src pad and push new segment */
  gst_pad_push_event (mux->srcpad, gst_event_new_caps (caps));
  gst_caps_unref (caps);

  gst_segment_init (&segment, GST_FORMAT_BYTES);
  gst_pad_push_event (mux->srcpad, gst_event_new_segment (&segment));

  return TRUE;
}
Пример #21
0
static void
push_newsegment_events (GList * input_pads)
{
  GstSegment seg;
  GList *l;

  seg.flags = GST_SEGMENT_FLAG_NONE;
  seg.rate = seg.applied_rate = 1.0;
  seg.format = GST_FORMAT_BYTES;
  seg.base = 0;
  seg.start = 0;
  seg.stop = -1;
  seg.time = 0;
  seg.position = 0;
  seg.duration = -1;

  for (l = input_pads; l; l = l->next) {
    GstPad *pad = l->data;

    gst_pad_push_event (pad, gst_event_new_stream_start ("test"));
    gst_pad_push_event (pad, gst_event_new_segment (&seg));
  }
}
Пример #22
0
static gboolean
gst_musepack_stream_init (GstMusepackDec * musepackdec)
{
  mpc_streaminfo i;
  GstTagList *tags;
  GstCaps *caps;
  gchar *stream_id;

  /* set up reading */
  gst_musepack_init_reader (musepackdec->r, musepackdec);

  musepackdec->d = mpc_demux_init (musepackdec->r);
  if (!musepackdec->d) {
    GST_ELEMENT_ERROR (musepackdec, STREAM, WRONG_TYPE, (NULL), (NULL));
    return FALSE;
  }

  mpc_demux_get_info (musepackdec->d, &i);

  stream_id = gst_pad_create_stream_id (musepackdec->srcpad,
      GST_ELEMENT_CAST (musepackdec), NULL);
  gst_pad_push_event (musepackdec->srcpad,
      gst_event_new_stream_start (stream_id));
  g_free (stream_id);

  /* capsnego */
  caps = gst_caps_new_simple ("audio/x-raw",
      "format", G_TYPE_STRING, GST_MPC_FORMAT,
      "layout", G_TYPE_STRING, "interleaved",
      "channels", G_TYPE_INT, i.channels,
      "rate", G_TYPE_INT, i.sample_freq, NULL);
  gst_pad_use_fixed_caps (musepackdec->srcpad);
  if (!gst_pad_set_caps (musepackdec->srcpad, caps)) {
    GST_ELEMENT_ERROR (musepackdec, CORE, NEGOTIATION, (NULL), (NULL));
    return FALSE;
  }

  g_atomic_int_set (&musepackdec->bps, 4 * i.channels);
  g_atomic_int_set (&musepackdec->rate, i.sample_freq);

  musepackdec->segment.position = 0;
  musepackdec->segment.duration = mpc_streaminfo_get_length_samples (&i);

  /* send basic tags */
  tags = gst_tag_list_new_empty ();
  gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
      GST_TAG_AUDIO_CODEC, "Musepack", NULL);

  if (i.encoder[0] != '\0' && i.encoder_version > 0) {
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_ENCODER, i.encoder,
        GST_TAG_ENCODER_VERSION, i.encoder_version, NULL);
  }

  if (i.bitrate > 0) {
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_BITRATE, i.bitrate, NULL);
  } else if (i.average_bitrate > 0.0) {
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_BITRATE, (guint) i.average_bitrate, NULL);
  }

  if (i.gain_title != 0 || i.gain_album != 0) {
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_GAIN, (gdouble) i.gain_title / 100.0,
        GST_TAG_ALBUM_GAIN, (gdouble) i.gain_album / 100.0, NULL);
  }

  if (i.peak_title != 0 && i.peak_title != 32767 &&
      i.peak_album != 0 && i.peak_album != 32767) {
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_TRACK_PEAK, (gdouble) i.peak_title / 32767.0,
        GST_TAG_ALBUM_PEAK, (gdouble) i.peak_album / 32767.0, NULL);
  }

  GST_LOG_OBJECT (musepackdec, "Posting tags: %" GST_PTR_FORMAT, tags);
  gst_pad_push_event (musepackdec->srcpad, gst_event_new_tag (tags));


  return TRUE;
}
Пример #23
0
static void
test_basic (const gchar * elem_name, const gchar * sink2, int count,
    check_cb cb)
{
  GstElement *rtpmux = NULL;
  GstPad *reqpad1 = NULL;
  GstPad *reqpad2 = NULL;
  GstPad *src1 = NULL;
  GstPad *src2 = NULL;
  GstPad *sink = NULL;
  GstBuffer *inbuf = NULL;
  GstCaps *src1caps = NULL;
  GstCaps *src2caps = NULL;
  GstCaps *sinkcaps = NULL;
  GstCaps *caps;
  GstSegment segment;
  int i;

  rtpmux = gst_check_setup_element (elem_name);

  reqpad1 = gst_element_get_request_pad (rtpmux, "sink_1");
  fail_unless (reqpad1 != NULL);
  reqpad2 = gst_element_get_request_pad (rtpmux, sink2);
  fail_unless (reqpad2 != NULL);
  sink = gst_check_setup_sink_pad_by_name (rtpmux, &sinktemplate, "src");

  src1 = gst_pad_new_from_static_template (&srctemplate, "src");
  src2 = gst_pad_new_from_static_template (&srctemplate, "src");
  fail_unless (gst_pad_link (src1, reqpad1) == GST_PAD_LINK_OK);
  fail_unless (gst_pad_link (src2, reqpad2) == GST_PAD_LINK_OK);
  gst_pad_set_query_function (src1, query_func);
  gst_pad_set_query_function (src2, query_func);
  gst_pad_set_query_function (sink, query_func);
  gst_pad_set_event_function (sink, event_func);
  g_object_set_data (G_OBJECT (src1), "caps", &src1caps);
  g_object_set_data (G_OBJECT (src2), "caps", &src2caps);
  g_object_set_data (G_OBJECT (sink), "caps", &sinkcaps);

  src1caps = gst_caps_new_simple ("application/x-rtp",
      "clock-rate", G_TYPE_INT, 1, "ssrc", G_TYPE_UINT, 11, NULL);
  src2caps = gst_caps_new_simple ("application/x-rtp",
      "clock-rate", G_TYPE_INT, 2, "ssrc", G_TYPE_UINT, 12, NULL);
  sinkcaps = gst_caps_new_simple ("application/x-rtp",
      "clock-rate", G_TYPE_INT, 3, "ssrc", G_TYPE_UINT, 13, NULL);

  caps = gst_pad_peer_query_caps (src1, NULL);
  fail_unless (gst_caps_is_empty (caps));
  gst_caps_unref (caps);

  gst_caps_set_simple (src2caps, "clock-rate", G_TYPE_INT, 3, NULL);
  caps = gst_pad_peer_query_caps (src1, NULL);
  gst_caps_unref (caps);

  g_object_set (rtpmux, "seqnum-offset", 100, "timestamp-offset", 1000,
      "ssrc", 55, NULL);

  fail_unless (gst_element_set_state (rtpmux,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS);
  gst_pad_set_active (sink, TRUE);
  gst_pad_set_active (src1, TRUE);
  gst_pad_set_active (src2, TRUE);

  fail_unless (gst_pad_push_event (src1,
          gst_event_new_stream_start ("stream1")));
  fail_unless (gst_pad_push_event (src2,
          gst_event_new_stream_start ("stream2")));

  gst_caps_set_simple (sinkcaps,
      "payload", G_TYPE_INT, 98, "seqnum-offset", G_TYPE_UINT, 100,
      "timestamp-offset", G_TYPE_UINT, 1000, "ssrc", G_TYPE_UINT, 66, NULL);
  caps = gst_caps_new_simple ("application/x-rtp",
      "payload", G_TYPE_INT, 98, "clock-rate", G_TYPE_INT, 3,
      "seqnum-offset", G_TYPE_UINT, 56, "timestamp-offset", G_TYPE_UINT, 57,
      "ssrc", G_TYPE_UINT, 66, NULL);
  fail_unless (gst_pad_set_caps (src1, caps));
  gst_caps_unref (caps);

  caps = gst_pad_peer_query_caps (sink, NULL);
  fail_if (gst_caps_is_empty (caps));

  gst_segment_init (&segment, GST_FORMAT_TIME);
  segment.start = 100000;
  fail_unless (gst_pad_push_event (src1, gst_event_new_segment (&segment)));
  segment.start = 0;
  fail_unless (gst_pad_push_event (src2, gst_event_new_segment (&segment)));


  for (i = 0; i < count; i++) {
    GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT;

    inbuf = gst_rtp_buffer_new_allocate (10, 0, 0);
    GST_BUFFER_PTS (inbuf) = i * 1000 + 100000;
    GST_BUFFER_DURATION (inbuf) = 1000;

    gst_rtp_buffer_map (inbuf, GST_MAP_WRITE, &rtpbuffer);

    gst_rtp_buffer_set_version (&rtpbuffer, 2);
    gst_rtp_buffer_set_payload_type (&rtpbuffer, 98);
    gst_rtp_buffer_set_ssrc (&rtpbuffer, 44);
    gst_rtp_buffer_set_timestamp (&rtpbuffer, 200 + i);
    gst_rtp_buffer_set_seq (&rtpbuffer, 2000 + i);
    gst_rtp_buffer_unmap (&rtpbuffer);
    fail_unless (gst_pad_push (src1, inbuf) == GST_FLOW_OK);

    if (buffers)
      fail_unless (GST_BUFFER_PTS (buffers->data) == i * 1000, "%lld",
          GST_BUFFER_PTS (buffers->data));

    cb (src2, i);

    g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL);
    g_list_free (buffers);
    buffers = NULL;
  }


  gst_pad_set_active (sink, FALSE);
  gst_pad_set_active (src1, FALSE);
  gst_pad_set_active (src2, FALSE);
  fail_unless (gst_element_set_state (rtpmux,
          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
  gst_check_teardown_pad_by_name (rtpmux, "src");
  gst_object_unref (reqpad1);
  gst_object_unref (reqpad2);
  gst_check_teardown_pad_by_name (rtpmux, "sink_1");
  gst_check_teardown_pad_by_name (rtpmux, sink2);
  gst_element_release_request_pad (rtpmux, reqpad1);
  gst_element_release_request_pad (rtpmux, reqpad2);

  gst_caps_unref (caps);
  gst_caps_replace (&src1caps, NULL);
  gst_caps_replace (&src2caps, NULL);
  gst_caps_replace (&sinkcaps, NULL);

  gst_check_teardown_element (rtpmux);
}
static void
gst_type_find_element_loop (GstPad * pad)
{
  GstTypeFindElement *typefind;
  GstFlowReturn ret = GST_FLOW_OK;

  typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));

  if (typefind->need_stream_start) {
    gchar *stream_id;
    GstEvent *event;

    stream_id = gst_pad_create_stream_id (typefind->src,
        GST_ELEMENT_CAST (typefind), NULL);

    GST_DEBUG_OBJECT (typefind, "Pushing STREAM_START");
    event = gst_event_new_stream_start (stream_id);
    gst_event_set_group_id (event, gst_util_group_id_next ());
    gst_pad_push_event (typefind->src, event);

    typefind->need_stream_start = FALSE;
    g_free (stream_id);
  }

  if (typefind->mode == MODE_TYPEFIND) {
    GstPad *peer = NULL;
    GstCaps *found_caps = NULL;
    GstTypeFindProbability probability = GST_TYPE_FIND_NONE;

    GST_DEBUG_OBJECT (typefind, "find type in pull mode");

    GST_OBJECT_LOCK (typefind);
    if (typefind->force_caps) {
      found_caps = gst_caps_ref (typefind->force_caps);
      probability = GST_TYPE_FIND_MAXIMUM;
    }
    GST_OBJECT_UNLOCK (typefind);

    if (!found_caps) {
      peer = gst_pad_get_peer (pad);
      if (peer) {
        gint64 size;
        gchar *ext;

        if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) {
          GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
          gst_object_unref (peer);

          ret = GST_FLOW_ERROR;
          goto pause;
        }

        /* the size if 0, we cannot continue */
        if (size == 0) {
          /* keep message in sync with message in sink event handler */
          GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
              (_("Stream contains no data.")), ("Can't typefind empty stream"));
          gst_object_unref (peer);
          ret = GST_FLOW_ERROR;
          goto pause;
        }
        ext = gst_type_find_get_extension (typefind, pad);

        found_caps =
            gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
            GST_OBJECT_PARENT (peer),
            (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
            (guint64) size, ext, &probability);
        g_free (ext);

        GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);

        gst_object_unref (peer);
      }
    }

    if (!found_caps || probability < typefind->min_probability) {
      GST_DEBUG ("Trying to guess using extension");
      gst_caps_replace (&found_caps, NULL);
      found_caps =
          gst_type_find_guess_by_extension (typefind, pad, &probability);
    }

    if (!found_caps || probability < typefind->min_probability) {
      GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
      gst_caps_replace (&found_caps, NULL);
      ret = GST_FLOW_ERROR;
      goto pause;
    }

    GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
    gst_type_find_element_emit_have_type (typefind, probability, found_caps);
    typefind->mode = MODE_NORMAL;
    gst_caps_unref (found_caps);
  } else if (typefind->mode == MODE_NORMAL) {
    GstBuffer *outbuf = NULL;

    if (typefind->need_segment) {
      typefind->need_segment = FALSE;
      gst_pad_push_event (typefind->src,
          gst_event_new_segment (&typefind->segment));
    }

    /* Pull 4k blocks and send downstream */
    ret = gst_pad_pull_range (typefind->sink, typefind->offset, 4096, &outbuf);
    if (ret != GST_FLOW_OK)
      goto pause;

    typefind->offset += gst_buffer_get_size (outbuf);

    ret = gst_pad_push (typefind->src, outbuf);
    if (ret != GST_FLOW_OK)
      goto pause;
  } else {
    /* Error out */
    ret = GST_FLOW_ERROR;
    goto pause;
  }

  return;

pause:
  {
    const gchar *reason = gst_flow_get_name (ret);
    gboolean push_eos = FALSE;

    GST_LOG_OBJECT (typefind, "pausing task, reason %s", reason);
    gst_pad_pause_task (typefind->sink);

    if (ret == GST_FLOW_EOS) {
      /* perform EOS logic */

      if (typefind->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
        gint64 stop;

        /* for segment playback we need to post when (in stream time)
         * we stopped, this is either stop (when set) or the duration. */
        if ((stop = typefind->segment.stop) == -1)
          stop = typefind->offset;

        GST_LOG_OBJECT (typefind, "Sending segment done, at end of segment");
        gst_element_post_message (GST_ELEMENT (typefind),
            gst_message_new_segment_done (GST_OBJECT (typefind),
                GST_FORMAT_BYTES, stop));
        gst_pad_push_event (typefind->src,
            gst_event_new_segment_done (GST_FORMAT_BYTES, stop));
      } else {
        push_eos = TRUE;
      }
    } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
      /* for fatal errors we post an error message */
      GST_ELEMENT_ERROR (typefind, STREAM, FAILED, (NULL),
          ("stream stopped, reason %s", reason));
      push_eos = TRUE;
    }
    if (push_eos) {
      /* send EOS, and prevent hanging if no streams yet */
      GST_LOG_OBJECT (typefind, "Sending EOS, at end of stream");
      gst_pad_push_event (typefind->src, gst_event_new_eos ());
    }
    return;
  }
}
static gboolean
gst_rtp_mux_setcaps (GstPad * pad, GstRTPMux * rtp_mux, GstCaps * caps)
{
  GstStructure *structure;
  gboolean ret = FALSE;
  GstRTPMuxPadPrivate *padpriv;
  GstCaps *peercaps;

  if (!gst_caps_is_fixed (caps))
    return FALSE;

  peercaps = gst_pad_peer_query_caps (rtp_mux->srcpad, NULL);
  if (peercaps) {
    GstCaps *tcaps, *othercaps;;
    tcaps = gst_pad_get_pad_template_caps (pad);
    othercaps = gst_caps_intersect_full (peercaps, tcaps,
        GST_CAPS_INTERSECT_FIRST);

    if (gst_caps_get_size (othercaps) > 0) {
      structure = gst_caps_get_structure (othercaps, 0);
      GST_OBJECT_LOCK (rtp_mux);
      if (gst_structure_get_uint (structure, "ssrc", &rtp_mux->current_ssrc)) {
        GST_DEBUG_OBJECT (pad, "Use downstream ssrc: %x",
            rtp_mux->current_ssrc);
        rtp_mux->have_ssrc = TRUE;
      }
      GST_OBJECT_UNLOCK (rtp_mux);
    }

    gst_caps_unref (othercaps);

    gst_caps_unref (peercaps);
    gst_caps_unref (tcaps);
  }

  structure = gst_caps_get_structure (caps, 0);

  if (!structure)
    return FALSE;

  GST_OBJECT_LOCK (rtp_mux);
  padpriv = gst_pad_get_element_private (pad);
  if (padpriv &&
      gst_structure_get_uint (structure, "timestamp-offset",
          &padpriv->timestamp_offset)) {
    padpriv->have_timestamp_offset = TRUE;
  }

  caps = gst_caps_copy (caps);

  /* if we don't have a specified ssrc, first try to take one from the caps,
     and if that fails, generate one */
  if (!rtp_mux->have_ssrc) {
    if (rtp_mux->ssrc_random) {
      if (!gst_structure_get_uint (structure, "ssrc", &rtp_mux->current_ssrc))
        rtp_mux->current_ssrc = g_random_int ();
      rtp_mux->have_ssrc = TRUE;
    }
  }

  gst_caps_set_simple (caps,
      "timestamp-offset", G_TYPE_UINT, rtp_mux->ts_base,
      "seqnum-offset", G_TYPE_UINT, rtp_mux->seqnum_base,
      "ssrc", G_TYPE_UINT, rtp_mux->current_ssrc, NULL);

  GST_OBJECT_UNLOCK (rtp_mux);

  if (rtp_mux->send_stream_start) {
    gchar s_id[32];

    /* stream-start (FIXME: create id based on input ids) */
    g_snprintf (s_id, sizeof (s_id), "interleave-%08x", g_random_int ());
    gst_pad_push_event (rtp_mux->srcpad, gst_event_new_stream_start (s_id));

    rtp_mux->send_stream_start = FALSE;
  }

  GST_DEBUG_OBJECT (rtp_mux,
      "setting caps %" GST_PTR_FORMAT " on src pad..", caps);
  ret = gst_pad_set_caps (rtp_mux->srcpad, caps);


  gst_caps_unref (caps);

  return ret;
}
Пример #26
0
static GstFlowReturn
gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
{
  guint size;
  GstBuffer *outbuf = NULL;
  GstFlowReturn ret = GST_FLOW_OK;
  GSList *collected;
  guint nsamples;
  guint ncollected = 0;
  gboolean empty = TRUE;
  gint width = self->width / 8;
  GstMapInfo write_info;
  GstClockTime timestamp = -1;

  /* FIXME: send caps and tags after stream-start */
#if 0
  if (self->send_stream_start) {
    gchar s_id[32];

    /* stream-start (FIXME: create id based on input ids) */
    g_snprintf (s_id, sizeof (s_id), "interleave-%08x", g_random_int ());
    gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
    self->send_stream_start = FALSE;
  }
#endif

  size = gst_collect_pads_available (pads);
  if (size == 0)
    goto eos;

  g_return_val_if_fail (self->func != NULL, GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (self->width > 0, GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (self->channels > 0, GST_FLOW_NOT_NEGOTIATED);
  g_return_val_if_fail (self->rate > 0, GST_FLOW_NOT_NEGOTIATED);

  g_return_val_if_fail (size % width == 0, GST_FLOW_ERROR);

  GST_DEBUG_OBJECT (self, "Starting to collect %u bytes from %d channels", size,
      self->channels);

  nsamples = size / width;

  outbuf = gst_buffer_new_allocate (NULL, size * self->channels, NULL);

  if (outbuf == NULL || gst_buffer_get_size (outbuf) < size * self->channels) {
    gst_buffer_unref (outbuf);
    return GST_FLOW_NOT_NEGOTIATED;
  }

  gst_buffer_map (outbuf, &write_info, GST_MAP_WRITE);
  memset (write_info.data, 0, size * self->channels);

  for (collected = pads->data; collected != NULL; collected = collected->next) {
    GstCollectData *cdata;
    GstBuffer *inbuf;
    guint8 *outdata;
    GstMapInfo input_info;

    cdata = (GstCollectData *) collected->data;

    inbuf = gst_collect_pads_take_buffer (pads, cdata, size);
    if (inbuf == NULL) {
      GST_DEBUG_OBJECT (cdata->pad, "No buffer available");
      goto next;
    }
    ncollected++;
    gst_buffer_map (inbuf, &input_info, GST_MAP_READ);

    if (timestamp == -1)
      timestamp = GST_BUFFER_TIMESTAMP (inbuf);

    if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP))
      goto next;

    empty = FALSE;
    outdata =
        write_info.data + width * GST_INTERLEAVE_PAD_CAST (cdata->pad)->channel;

    self->func (outdata, input_info.data, self->channels, nsamples);
    gst_buffer_unmap (inbuf, &input_info);

  next:
    if (inbuf)
      gst_buffer_unref (inbuf);
  }

  if (ncollected == 0) {
    gst_buffer_unmap (outbuf, &write_info);
    goto eos;
  }

  GST_OBJECT_LOCK (self);
  if (self->pending_segment) {
    GstEvent *event;
    GstSegment segment;

    event = self->pending_segment;
    self->pending_segment = NULL;
    GST_OBJECT_UNLOCK (self);

    /* convert the input segment to time now */
    gst_event_copy_segment (event, &segment);

    if (segment.format != GST_FORMAT_TIME) {
      gst_event_unref (event);

      /* not time, convert */
      switch (segment.format) {
        case GST_FORMAT_BYTES:
          segment.start *= width;
          if (segment.stop != -1)
            segment.stop *= width;
          if (segment.position != -1)
            segment.position *= width;
          /* fallthrough for the samples case */
        case GST_FORMAT_DEFAULT:
          segment.start =
              gst_util_uint64_scale_int (segment.start, GST_SECOND, self->rate);
          if (segment.stop != -1)
            segment.stop =
                gst_util_uint64_scale_int (segment.stop, GST_SECOND,
                self->rate);
          if (segment.position != -1)
            segment.position =
                gst_util_uint64_scale_int (segment.position, GST_SECOND,
                self->rate);
          break;
        default:
          GST_WARNING ("can't convert segment values");
          segment.start = 0;
          segment.stop = -1;
          segment.position = 0;
          break;
      }
      event = gst_event_new_segment (&segment);
    }
    gst_pad_push_event (self->src, event);

    GST_OBJECT_LOCK (self);
  }
  GST_OBJECT_UNLOCK (self);

  if (timestamp != -1) {
    self->offset = gst_util_uint64_scale_int (timestamp, self->rate,
        GST_SECOND);
    self->timestamp = timestamp;
  }

  GST_BUFFER_TIMESTAMP (outbuf) = self->timestamp;
  GST_BUFFER_OFFSET (outbuf) = self->offset;

  self->offset += nsamples;
  self->timestamp = gst_util_uint64_scale_int (self->offset,
      GST_SECOND, self->rate);

  GST_BUFFER_DURATION (outbuf) =
      self->timestamp - GST_BUFFER_TIMESTAMP (outbuf);

  if (empty)
    GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);

  gst_buffer_unmap (outbuf, &write_info);

  GST_LOG_OBJECT (self, "pushing outbuf, timestamp %" GST_TIME_FORMAT,
      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
  ret = gst_pad_push (self->src, outbuf);

  return ret;

eos:
  {
    GST_DEBUG_OBJECT (self, "no data available, must be EOS");
    if (outbuf)
      gst_buffer_unref (outbuf);
    gst_pad_push_event (self->src, gst_event_new_eos ());
    return GST_FLOW_EOS;
  }
}
static void src_task_loop(GstPad *pad)
{
    GstErDtlsEnc *self = GST_ER_DTLS_ENC(GST_PAD_PARENT(pad));
    GstFlowReturn ret;
    GstPad *peer;
    gboolean peer_is_active;

    if (!gst_pad_is_active(pad)) {
        GST_LOG_OBJECT(self, "src task loop entered on inactive pad");
        return;
    }

    GST_TRACE_OBJECT(self, "src loop: acquiring lock");
    g_mutex_lock(&self->queue_lock);
    GST_TRACE_OBJECT(self, "src loop: acquired lock");

    while (!self->queue->len) {
        GST_TRACE_OBJECT(self, "src loop: queue empty, waiting for add");
        g_cond_wait(&self->queue_cond_add, &self->queue_lock);
        GST_TRACE_OBJECT(self, "src loop: add signaled");

        if (!gst_pad_is_active(pad)) {
            GST_LOG_OBJECT(self, "pad inactive, task returning");
            GST_TRACE_OBJECT(self, "src loop: releasing lock");
            g_mutex_unlock(&self->queue_lock);
            return;
        }
    }
    GST_TRACE_OBJECT(self, "src loop: queue has element");

    peer = gst_pad_get_peer(pad);
    peer_is_active = gst_pad_is_active(peer);
    gst_object_unref(peer);

    if (peer_is_active) {
        GstBuffer *buffer;
        gboolean start_connection_timeout = FALSE;

        if (self->send_initial_events) {
          GstSegment segment;
          gchar s_id[32];
          GstCaps *caps;

          g_snprintf (s_id, sizeof (s_id), "erdtlsenc-%08x", g_random_int ());
          gst_pad_push_event (self->src, gst_event_new_stream_start (s_id));
          caps = gst_caps_new_empty_simple ("application/x-dtls");
          gst_pad_push_event (self->src, gst_event_new_caps (caps));
          gst_caps_unref (caps);
          gst_segment_init (&segment, GST_FORMAT_BYTES);
          gst_pad_push_event (self->src, gst_event_new_segment (&segment));
          self->send_initial_events = FALSE;
          start_connection_timeout = TRUE;
        }

        buffer = g_ptr_array_remove_index(self->queue, 0);

        GST_TRACE_OBJECT(self, "src loop: releasing lock");
        g_mutex_unlock(&self->queue_lock);

        ret = gst_pad_push(self->src, buffer);
        if (start_connection_timeout)
          er_dtls_connection_start_timeout (self->connection);

        if (G_UNLIKELY(ret != GST_FLOW_OK)) {
            GST_WARNING_OBJECT(self, "failed to push buffer on src pad: %s", gst_flow_get_name(ret));
        }
    } else {
        g_warn_if_reached();
        GST_TRACE_OBJECT(self, "src loop: releasing lock");
        g_mutex_unlock(&self->queue_lock);
    }
}
Пример #28
0
static void
_create_issues (GstValidateRunner * runner)
{
  GstPad *srcpad1, *srcpad2, *sinkpad, *funnel_sink1, *funnel_sink2;
  GstElement *src1, *src2, *sink, *fakemixer;
  GstSegment segment;

  src1 = create_and_monitor_element ("fakesrc2", "fakesrc1", runner);
  src2 = create_and_monitor_element ("fakesrc2", "fakesrc2", runner);
  fakemixer = create_and_monitor_element ("fakemixer", "fakemixer", runner);
  sink = create_and_monitor_element ("fakesink", "fakesink", runner);

  srcpad1 = gst_element_get_static_pad (src1, "src");
  srcpad2 = gst_element_get_static_pad (src2, "src");
  funnel_sink1 = gst_element_get_request_pad (fakemixer, "sink_%u");
  funnel_sink2 = gst_element_get_request_pad (fakemixer, "sink_%u");
  sinkpad = gst_element_get_static_pad (sink, "sink");

  fail_unless (gst_element_link (fakemixer, sink));
  fail_unless (gst_pad_link (srcpad1, funnel_sink1) == GST_PAD_LINK_OK);
  fail_unless (gst_pad_link (srcpad2, funnel_sink2) == GST_PAD_LINK_OK);

  /* We want to handle the src behaviour ourselves */
  fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, TRUE));
  fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, TRUE));

  /* Setup all needed events */
  gst_segment_init (&segment, GST_FORMAT_TIME);
  segment.start = 0;
  segment.stop = GST_SECOND;

  fail_unless (gst_pad_push_event (srcpad1,
          gst_event_new_stream_start ("the-stream")));
  fail_unless (gst_pad_push_event (srcpad1, gst_event_new_segment (&segment)));

  fail_unless (gst_pad_push_event (srcpad2,
          gst_event_new_stream_start ("the-stream")));
  fail_unless (gst_pad_push_event (srcpad2, gst_event_new_segment (&segment)));

  fail_unless_equals_int (gst_element_set_state (fakemixer, GST_STATE_PLAYING),
      GST_STATE_CHANGE_SUCCESS);
  fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_PLAYING),
      GST_STATE_CHANGE_ASYNC);

  /* Send an unexpected flush stop */
  _gst_check_expecting_log = TRUE;
  fail_unless (gst_pad_push_event (srcpad1, gst_event_new_flush_stop (TRUE)));

  /* Once again but on the other fakemixer sink */
  fail_unless (gst_pad_push_event (srcpad2, gst_event_new_flush_stop (TRUE)));

  /* clean up */
  fail_unless (gst_pad_activate_mode (srcpad1, GST_PAD_MODE_PUSH, FALSE));
  fail_unless (gst_pad_activate_mode (srcpad2, GST_PAD_MODE_PUSH, FALSE));
  fail_unless_equals_int (gst_element_set_state (fakemixer, GST_STATE_NULL),
      GST_STATE_CHANGE_SUCCESS);
  fail_unless_equals_int (gst_element_set_state (sink, GST_STATE_NULL),
      GST_STATE_CHANGE_SUCCESS);

  gst_object_unref (srcpad1);
  gst_object_unref (srcpad2);
  gst_object_unref (sinkpad);
  gst_object_unref (funnel_sink1);
  gst_object_unref (funnel_sink2);
  gst_check_objects_destroyed_on_unref (fakemixer, funnel_sink1, funnel_sink2,
      NULL);
  gst_check_objects_destroyed_on_unref (src1, srcpad1, NULL);
  gst_check_objects_destroyed_on_unref (src2, srcpad2, NULL);
  gst_check_objects_destroyed_on_unref (sink, sinkpad, NULL);
}
Пример #29
0
static void
gst_srtp_dec_push_early_events (GstSrtpDec * filter, GstPad * pad,
    GstPad * otherpad, gboolean is_rtcp)
{
  GstEvent *otherev, *ev;

  ev = gst_pad_get_sticky_event (pad, GST_EVENT_STREAM_START, 0);
  if (ev) {
    gst_event_unref (ev);
  } else {
    gchar *new_stream_id;

    otherev = gst_pad_get_sticky_event (otherpad, GST_EVENT_STREAM_START, 0);

    if (otherev) {
      const gchar *other_stream_id;

      gst_event_parse_stream_start (otherev, &other_stream_id);

      new_stream_id = g_strdup_printf ("%s/%s", other_stream_id,
          is_rtcp ? "rtcp" : "rtp");
      gst_event_unref (otherev);
    } else {
      new_stream_id = gst_pad_create_stream_id (pad, GST_ELEMENT (filter),
          is_rtcp ? "rtcp" : "rtp");
    }

    ev = gst_event_new_stream_start (new_stream_id);
    g_free (new_stream_id);

    gst_pad_push_event (pad, ev);
  }

  ev = gst_pad_get_sticky_event (pad, GST_EVENT_CAPS, 0);
  if (ev) {
    gst_event_unref (ev);
  } else {
    GstCaps *caps;

    if (is_rtcp)
      caps = gst_caps_new_empty_simple ("application/x-rtcp");
    else
      caps = gst_caps_new_empty_simple ("application/x-rtp");

    gst_pad_set_caps (pad, caps);
    gst_caps_unref (caps);
  }

  ev = gst_pad_get_sticky_event (pad, GST_EVENT_SEGMENT, 0);
  if (ev) {
    gst_event_unref (ev);
  } else {
    ev = gst_pad_get_sticky_event (otherpad, GST_EVENT_SEGMENT, 0);

    if (ev)
      gst_pad_push_event (pad, ev);
  }

  if (is_rtcp)
    filter->rtcp_has_segment = TRUE;
  else
    filter->rtp_has_segment = TRUE;

}
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;
    gchar *stream_id;
    GstEvent *event;

    mppad = g_new0 (GstMultipartPad, 1);

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

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

    mppad->pad = pad;
    mppad->mime = g_strdup (mime);
    mppad->last_ret = GST_FLOW_OK;
    mppad->last_ts = GST_CLOCK_TIME_NONE;
    mppad->discont = TRUE;

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

    gst_pad_use_fixed_caps (pad);
    gst_pad_set_active (pad, TRUE);

    /* prepare and send stream-start */
    if (!demux->have_group_id) {
      event = gst_pad_get_sticky_event (demux->sinkpad,
          GST_EVENT_STREAM_START, 0);

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

    stream_id = gst_pad_create_stream_id (pad,
        GST_ELEMENT_CAST (demux), demux->mime_type);

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

    gst_pad_store_sticky_event (pad, event);
    g_free (stream_id);
    gst_event_unref (event);

    /* 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_set_caps (pad, caps);
    gst_element_add_pad (GST_ELEMENT_CAST (demux), pad);
    gst_caps_unref (caps);

    if (created) {
      *created = TRUE;
    }

    if (demux->singleStream) {
      gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
    }

    return mppad;
  }
}