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);
}
/* convert the PacketLost event from a jitterbuffer to a GAP event.
 * subclasses can override this.  */
static gboolean
gst_rtp_base_depayload_packet_lost (GstRTPBaseDepayload * filter,
    GstEvent * event)
{
  GstClockTime timestamp, duration;
  GstEvent *sevent;
  const GstStructure *s;

  s = gst_event_get_structure (event);

  /* first start by parsing the timestamp and duration */
  timestamp = -1;
  duration = -1;

  if (!gst_structure_get_clock_time (s, "timestamp", &timestamp) ||
      !gst_structure_get_clock_time (s, "duration", &duration)) {
    GST_ERROR_OBJECT (filter,
        "Packet loss event without timestamp or duration");
    return FALSE;
  }

  sevent = gst_pad_get_sticky_event (filter->srcpad, GST_EVENT_SEGMENT, 0);
  if (G_UNLIKELY (!sevent)) {
    /* Typically happens if lost event arrives before first buffer */
    GST_DEBUG_OBJECT (filter, "Ignore packet loss because segment event missing");
    return FALSE;
  }
  gst_event_unref (sevent);

  /* send GAP event */
  sevent = gst_event_new_gap (timestamp, duration);

  return gst_pad_push_event (filter->srcpad, sevent);
}
Example #3
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;
}
void InbandTextTrackPrivateGStreamer::notifyTrackOfStreamChanged()
{
    GRefPtr<GstEvent> event = adoptGRef(gst_pad_get_sticky_event(m_pad.get(),
        GST_EVENT_STREAM_START, 0));
    if (!event)
        return;

    const gchar* streamId;
    gst_event_parse_stream_start(event.get(), &streamId);
    INFO_MEDIA_MESSAGE("Track %d got stream start for stream %s.", m_index, streamId);
    m_streamId = streamId;
}
static void
input_selector_check_eos (gint present)
{
  GstEvent *eos;

  eos = gst_pad_get_sticky_event (output_pad, GST_EVENT_EOS, 0);
  if (present) {
    fail_unless (eos != NULL);
    gst_event_unref (eos);
  } else {
    fail_unless (eos == NULL);
  }
}
static void
gst_type_find_element_have_type (GstTypeFindElement * typefind,
    guint probability, GstCaps * caps)
{
  GstEvent *event;

  g_assert (caps != NULL);

  GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
      caps, probability);

  /* Do nothing if downstream is pulling from us */
  if (GST_PAD_MODE (typefind->src) == GST_PAD_MODE_PULL)
    return;

  GST_OBJECT_LOCK (typefind);

  /* Now actually send the CAPS event downstream.
   *
   * Try to directly send the CAPS event downstream that we created in
   * gst_type_find_element_emit_have_type() if it is still there, instead
   * of creating a new one. No need to create an equivalent one, replacing
   * it in the sticky event list and possibly causing renegotiation
   */
  event = gst_pad_get_sticky_event (typefind->src, GST_EVENT_CAPS, 0);
  if (event) {
    GstCaps *event_caps;

    gst_event_parse_caps (event, &event_caps);
    if (caps != event_caps) {
      gst_event_unref (event);
      event = gst_event_new_caps (caps);
    }
  } else {
    event = gst_event_new_caps (caps);
  }

  GST_OBJECT_UNLOCK (typefind);

  gst_pad_push_event (typefind->src, event);
}
void InbandTextTrackPrivateGStreamer::notifyTrackOfTagsChanged()
{
    m_tagTimerHandler = 0;
    if (!m_pad)
        return;

    String label;
    String language;
    GRefPtr<GstEvent> event;
    for (guint i = 0; (event = adoptGRef(gst_pad_get_sticky_event(m_pad.get(), GST_EVENT_TAG, i))); ++i) {
        GstTagList* tags = 0;
        gst_event_parse_tag(event.get(), &tags);
        ASSERT(tags);

        gchar* tagValue;
        if (gst_tag_list_get_string(tags, GST_TAG_TITLE, &tagValue)) {
            INFO_MEDIA_MESSAGE("Text track %d got title %s.", m_index, tagValue);
            label = tagValue;
            g_free(tagValue);
        }

        if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &tagValue)) {
            INFO_MEDIA_MESSAGE("Text track %d got language %s.", m_index, tagValue);
            language = tagValue;
            g_free(tagValue);
        }
    }

    if (m_label != label) {
        m_label = label;
        client()->labelChanged(this, m_label);
    }

    if (m_language != language) {
        m_language = language;
        client()->languageChanged(this, m_language);
    }
}
Example #8
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;
  }
}
Example #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 '%" GST_FOURCC_FORMAT "'",
            GST_FOURCC_ARGS (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;
  }

}
Example #11
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 ();
}
Example #12
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;
  }
}
Example #13
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);
}