Esempio n. 1
0
static void
udpsink_test (gboolean use_buffer_lists)
{
  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_function (udpsink);

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

  gst_element_set_state (udpsink, GST_STATE_PLAYING);

  gst_pad_push_event (srcpad, gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
          GST_FORMAT_TIME, 0, -1, 0));

  gst_pad_push_list (srcpad, list);

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

  if (use_buffer_lists)
    fail_if (data_size != render_list_bytes_received);
}
Esempio n. 2
0
/**
 * gst_event_new_new_segment:
 * @update: is this segment an update to a previous one
 * @rate: a new rate for playback
 * @format: The format of the segment values
 * @start: the start value of the segment
 * @stop: the stop value of the segment
 * @position: stream position
 *
 * Allocate a new newsegment event with the given format/values tripplets
 *
 * This method calls gst_event_new_new_segment_full() passing a default
 * value of 1.0 for applied_rate
 *
 * Returns: (transfer full): a new newsegment event.
 */
GstEvent *
gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
    gint64 start, gint64 stop, gint64 position)
{
  return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
      stop, position);
}
Esempio n. 3
0
static HRESULT WINAPI Gstreamer_transform_NewSegment(TransformFilter *iface, REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) {
    GstTfImpl *This = (GstTfImpl*)iface;
    TRACE("%p\n", This);

    gst_pad_push_event(This->my_src, gst_event_new_new_segment_full(1,
                       1.0, dRate, GST_FORMAT_TIME, 0, tStop <= tStart ? -1 : tStop * 100, tStart*100));
    return S_OK;
}
Esempio n. 4
0
static GstFlowReturn
gst_real_audio_demux_parse_data (GstRealAudioDemux * demux)
{
  GstFlowReturn ret = GST_FLOW_OK;
  guint avail, unit_size;

  avail = gst_adapter_available (demux->adapter);

  if (demux->packet_size > 0)
    unit_size = demux->packet_size;
  else
    unit_size = avail & 0xfffffff0;     /* round down to next multiple of 16 */

  GST_LOG_OBJECT (demux, "available = %u, unit_size = %u", avail, unit_size);

  while (ret == GST_FLOW_OK && unit_size > 0 && avail >= unit_size) {
    GstClockTime ts;
    const guint8 *data;
    GstBuffer *buf = NULL;

    buf = gst_buffer_new_and_alloc (unit_size);
    gst_buffer_set_caps (buf, GST_PAD_CAPS (demux->srcpad));

    data = gst_adapter_peek (demux->adapter, unit_size);
    memcpy (GST_BUFFER_DATA (buf), data, unit_size);
    gst_adapter_flush (demux->adapter, unit_size);
    avail -= unit_size;

    if (demux->need_newsegment) {
      gst_pad_push_event (demux->srcpad,
          gst_event_new_new_segment_full (FALSE, demux->segment.rate,
              demux->segment.applied_rate, GST_FORMAT_TIME,
              demux->segment.start, demux->segment.stop, demux->segment.time));
      demux->need_newsegment = FALSE;
    }

    if (demux->pending_tags) {
      gst_element_found_tags_for_pad (GST_ELEMENT (demux), demux->srcpad,
          demux->pending_tags);
      demux->pending_tags = NULL;
    }

    if (demux->fourcc == GST_RM_AUD_DNET) {
      buf = gst_rm_utils_descramble_dnet_buffer (buf);
    }

    ts = gst_real_demux_get_timestamp_from_offset (demux, demux->offset);
    GST_BUFFER_TIMESTAMP (buf) = ts;

    gst_segment_set_last_stop (&demux->segment, GST_FORMAT_TIME, ts);

    ret = gst_pad_push (demux->srcpad, buf);
  }

  return ret;
}
static GstFlowReturn
gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
{
  RsnStreamSelector *sel;
  GstFlowReturn res;
  GstPad *active_sinkpad;
  RsnSelectorPad *selpad;
  GstClockTime timestamp;
  GstSegment *seg;

  sel = RSN_STREAM_SELECTOR (gst_pad_get_parent (pad));
  selpad = GST_SELECTOR_PAD_CAST (pad);
  seg = &selpad->segment;

  active_sinkpad = rsn_stream_selector_get_active (sel, pad);

  timestamp = GST_BUFFER_TIMESTAMP (buf);
  if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
    GST_DEBUG_OBJECT (sel, "received timestamp %" GST_TIME_FORMAT,
        GST_TIME_ARGS (timestamp));
    gst_segment_set_last_stop (seg, seg->format, timestamp);
  }

  /* Ignore buffers from pads except the selected one */
  if (pad != active_sinkpad)
    goto ignore;

  /* if we have a pending segment, push it out now */
  if (selpad->segment_pending) {
    gst_pad_push_event (sel->srcpad, gst_event_new_new_segment_full (FALSE,
            seg->rate, seg->applied_rate, seg->format, seg->start, seg->stop,
            seg->time));

    selpad->segment_pending = FALSE;
  }

  /* forward */
  GST_DEBUG_OBJECT (sel, "Forwarding buffer %p from pad %s:%s", buf,
      GST_DEBUG_PAD_NAME (pad));
  res = gst_pad_push (sel->srcpad, buf);
done:
  gst_object_unref (sel);
  return res;
  /* dropped buffers */
ignore:
  {
    GST_DEBUG_OBJECT (sel, "Ignoring buffer %p from pad %s:%s",
        buf, GST_DEBUG_PAD_NAME (pad));
    gst_buffer_unref (buf);
    res = GST_FLOW_NOT_LINKED;
    goto done;
  }
}
static void
distribute_running_time (GstElement * element, const GstSegment * segment)
{
    GstEvent *event;
    GstPad *pad;

    pad = gst_element_get_static_pad (element, "sink");

    if (segment->accum) {
        event = gst_event_new_new_segment_full (FALSE, segment->rate,
                                                segment->applied_rate, segment->format, 0, segment->accum, 0);
        gst_pad_push_event (pad, event);
    }

    event = gst_event_new_new_segment_full (FALSE, segment->rate,
                                            segment->applied_rate, segment->format,
                                            segment->start, segment->stop, segment->time);
    gst_pad_push_event (pad, event);

    gst_object_unref (pad);
}
Esempio n. 7
0
static GstEvent *
gst_timidity_get_new_segment_event (GstTimidity * timidity, GstFormat format,
    gboolean update)
{
  GstSegment *segment;
  GstEvent *event;

  segment = gst_timidity_get_segment (timidity, format, update);

  event = gst_event_new_new_segment_full (update,
      segment->rate, segment->applied_rate, segment->format,
      segment->start, segment->stop, segment->time);

  gst_segment_free (segment);

  return event;
}
Esempio n. 8
0
static VALUE
newsegment_initialize(VALUE self, VALUE update, VALUE rate, VALUE applied_rate,
                      VALUE format, VALUE start, VALUE stop, VALUE position)
{
    GstEvent *event;

    event = gst_event_new_new_segment_full(RVAL2CBOOL(update),
                                           NUM2DBL(rate),
                                           NUM2DBL(applied_rate),
                                           RVAL2GST_FORMAT(format),
                                           NUM2LL(start),
                                           NUM2LL(stop),
                                           NUM2LL(position));

    G_INITIALIZE(self, event);
    return Qnil;
}
Esempio n. 9
0
static GstEvent *
create_segment_event (GstRDTDepay * depay, gboolean update,
    GstClockTime position)
{
  GstEvent *event;
  GstClockTime stop;

  if (depay->npt_stop != -1)
    stop = depay->npt_stop - depay->npt_start;
  else
    stop = -1;

  event = gst_event_new_new_segment_full (update, depay->play_speed,
      depay->play_scale, GST_FORMAT_TIME, position, stop,
      position + depay->npt_start);

  return event;
}
static GstEvent *
create_segment_event (GstBaseRTPDepayload * filter, gboolean update,
    GstClockTime position)
{
  GstEvent *event;
  GstClockTime stop;
  GstBaseRTPDepayloadPrivate *priv;

  priv = filter->priv;

  if (priv->npt_stop != -1)
    stop = priv->npt_stop - priv->npt_start;
  else
    stop = -1;

  event = gst_event_new_new_segment_full (update, priv->play_speed,
      priv->play_scale, GST_FORMAT_TIME, position, stop,
      position + priv->npt_start);

  return event;
}
Esempio n. 11
0
static gboolean
gst_vcd_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstVcdParse *vcd = GST_VCD_PARSE (gst_pad_get_parent (pad));
  gboolean res;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NEWSEGMENT:{
      GstFormat format;
      gboolean update;
      gdouble rate, applied_rate;
      gint64 start, stop, position;

      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
          &format, &start, &stop, &position);

      if (format == GST_FORMAT_BYTES) {
        gst_event_unref (event);
        event = gst_event_new_new_segment_full (update, rate, applied_rate,
            GST_FORMAT_BYTES, gst_vcd_parse_get_out_offset (start),
            gst_vcd_parse_get_out_offset (stop), position);
      } else {
        GST_WARNING_OBJECT (vcd, "newsegment event in non-byte format");
      }
      res = gst_pad_event_default (pad, event);
      break;
    }
    case GST_EVENT_FLUSH_START:
      gst_adapter_clear (vcd->adapter);
      /* fall through */
    default:
      res = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (vcd);
  return res;
}
Esempio n. 12
0
static GstEvent *
gst_wildmidi_get_new_segment_event (GstWildmidi * wildmidi, GstFormat format)
{
  gint64 start, stop, time;
  GstSegment *segment;
  GstEvent *event;
  GstFormat src_format;

  segment = wildmidi->o_segment;
  src_format = segment->format;

  /* convert the segment values to the target format */
  gst_wildmidi_src_convert (wildmidi, src_format, segment->start, &format,
      &start);
  gst_wildmidi_src_convert (wildmidi, src_format, segment->stop, &format,
      &stop);
  gst_wildmidi_src_convert (wildmidi, src_format, segment->time, &format,
      &time);

  event = gst_event_new_new_segment_full (FALSE,
      segment->rate, segment->applied_rate, format, start, stop, time);

  return event;
}
Esempio n. 13
0
static GstFlowReturn
fs_funnel_chain (GstPad * pad, GstBuffer * buffer)
{
  GstFlowReturn res;
  FsFunnel *funnel = FS_FUNNEL (gst_pad_get_parent (pad));
  FsFunnelPadPrivate *priv = gst_pad_get_element_private (pad);
  GstEvent *event = NULL;
  GstClockTime newts;
  GstCaps *padcaps;

  GST_DEBUG_OBJECT (funnel, "received buffer %p", buffer);

  GST_OBJECT_LOCK (funnel);
  if (priv->segment.format == GST_FORMAT_UNDEFINED) {
    GST_WARNING_OBJECT (funnel, "Got buffer without segment,"
        " setting segment [0,inf[");
     gst_segment_set_newsegment_full (&priv->segment, FALSE, 1.0, 1.0,
         GST_FORMAT_TIME, 0, -1, 0);
  }

  if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer)))
    gst_segment_set_last_stop (&priv->segment, priv->segment.format,
        GST_BUFFER_TIMESTAMP (buffer));

  newts = gst_segment_to_running_time (&priv->segment,
      priv->segment.format, GST_BUFFER_TIMESTAMP (buffer));
  if (newts != GST_BUFFER_TIMESTAMP (buffer)) {
    buffer = gst_buffer_make_metadata_writable (buffer);
    GST_BUFFER_TIMESTAMP (buffer) = newts;
  }

  if (!funnel->has_segment)
  {
    event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
        0, -1, 0);
    funnel->has_segment = TRUE;
  }
  GST_OBJECT_UNLOCK (funnel);

  if (event) {
    if (!gst_pad_push_event (funnel->srcpad, event))
      GST_WARNING_OBJECT (funnel, "Could not push out newsegment event");
  }


  GST_OBJECT_LOCK (pad);
  padcaps = GST_PAD_CAPS (funnel->srcpad);
  GST_OBJECT_UNLOCK (pad);

  if (GST_BUFFER_CAPS (buffer) && GST_BUFFER_CAPS (buffer) != padcaps) {
    if (!gst_pad_set_caps (funnel->srcpad, GST_BUFFER_CAPS (buffer))) {
      res = GST_FLOW_NOT_NEGOTIATED;
      goto out;
    }
  }

  res = gst_pad_push (funnel->srcpad, buffer);

  GST_LOG_OBJECT (funnel, "handled buffer %s", gst_flow_get_name (res));

 out:
  gst_object_unref (funnel);

  return res;
}
Esempio n. 14
0
static GstFlowReturn
gst_selector_pad_chain (GstPad * pad, GstBuffer * buf)
{
  GstInputSelector *sel;
  GstFlowReturn res;
  GstPad *active_sinkpad;
  GstPad *prev_active_sinkpad;
  GstSelectorPad *selpad;
  GstClockTime start_time;
  GstSegment *seg;
  GstEvent *close_event = NULL, *start_event = NULL;
  GstCaps *caps;

  sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad));
  selpad = GST_SELECTOR_PAD_CAST (pad);
  seg = &selpad->segment;

  GST_INPUT_SELECTOR_LOCK (sel);
  /* wait or check for flushing */
  if (gst_input_selector_wait (sel, pad))
    goto flushing;

  GST_LOG_OBJECT (pad, "getting active pad");

  prev_active_sinkpad = sel->active_sinkpad;
  active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad);

  /* update the segment on the srcpad */
  start_time = GST_BUFFER_TIMESTAMP (buf);
  if (GST_CLOCK_TIME_IS_VALID (start_time)) {
    GST_LOG_OBJECT (pad, "received start time %" GST_TIME_FORMAT,
        GST_TIME_ARGS (start_time));
    if (GST_BUFFER_DURATION_IS_VALID (buf))
      GST_LOG_OBJECT (pad, "received end time %" GST_TIME_FORMAT,
          GST_TIME_ARGS (start_time + GST_BUFFER_DURATION (buf)));

    GST_OBJECT_LOCK (pad);
    gst_segment_set_last_stop (seg, seg->format, start_time);
    GST_OBJECT_UNLOCK (pad);
  }

  /* Ignore buffers from pads except the selected one */
  if (pad != active_sinkpad)
    goto ignore;

  if (G_UNLIKELY (sel->pending_close)) {
    GstSegment *cseg = &sel->segment;

    GST_DEBUG_OBJECT (sel,
        "pushing close NEWSEGMENT update %d, rate %lf, applied rate %lf, "
        "format %d, "
        "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
        G_GINT64_FORMAT, TRUE, cseg->rate, cseg->applied_rate, cseg->format,
        cseg->start, cseg->stop, cseg->time);

    /* create update segment */
    close_event = gst_event_new_new_segment_full (TRUE, cseg->rate,
        cseg->applied_rate, cseg->format, cseg->start, cseg->stop, cseg->time);

    sel->pending_close = FALSE;
  }
  /* if we have a pending segment, push it out now */
  if (G_UNLIKELY (selpad->segment_pending)) {
    GST_DEBUG_OBJECT (pad,
        "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, "
        "format %d, "
        "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %"
        G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format,
        seg->start, seg->stop, seg->time);

    start_event = gst_event_new_new_segment_full (FALSE, seg->rate,
        seg->applied_rate, seg->format, seg->start, seg->stop, seg->time);

    selpad->segment_pending = FALSE;
  }
  GST_INPUT_SELECTOR_UNLOCK (sel);

  if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad)
    g_object_notify (G_OBJECT (sel), "active-pad");

  if (close_event)
    gst_pad_push_event (sel->srcpad, close_event);

  if (start_event)
    gst_pad_push_event (sel->srcpad, start_event);

  if (selpad->discont) {
    buf = gst_buffer_make_metadata_writable (buf);

    GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf);
    GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
    selpad->discont = FALSE;
  }

  /* forward */
  GST_LOG_OBJECT (pad, "Forwarding buffer %p", buf);

  if ((caps = GST_BUFFER_CAPS (buf))) {
    if (GST_PAD_CAPS (sel->srcpad) != caps)
      gst_pad_set_caps (sel->srcpad, caps);
  }

  res = gst_pad_push (sel->srcpad, buf);

done:
  gst_object_unref (sel);
  return res;

  /* dropped buffers */
ignore:
  {
    GST_DEBUG_OBJECT (pad, "Pad not active, discard buffer %p", buf);
    /* when we drop a buffer, we're creating a discont on this pad */
    selpad->discont = TRUE;
    GST_INPUT_SELECTOR_UNLOCK (sel);
    gst_buffer_unref (buf);

    /* figure out what to return upstream */
    GST_OBJECT_LOCK (selpad);
    if (selpad->always_ok)
      res = GST_FLOW_OK;
    else
      res = GST_FLOW_NOT_LINKED;
    GST_OBJECT_UNLOCK (selpad);

    goto done;
  }
flushing:
  {
    GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf);
    GST_INPUT_SELECTOR_UNLOCK (sel);
    gst_buffer_unref (buf);
    res = GST_FLOW_WRONG_STATE;
    goto done;
  }
}
Esempio n. 15
0
static GstFlowReturn
theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet)
{
  GstCaps *caps;
  gint par_num, par_den;
  GstFlowReturn ret = GST_FLOW_OK;
  gboolean eret;
  GstEvent *event;
  guint32 bitstream_version;

  GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d",
      dec->info.fps_numerator, dec->info.fps_denominator,
      dec->info.aspect_numerator, dec->info.aspect_denominator);

  /* calculate par
   * the info.aspect_* values reflect PAR;
   * 0:0 is allowed and can be interpreted as 1:1, so correct for it.
   * x:0 for other x isn't technically allowed, but it's seen in the wild and
   * is reasonable to treat the same. 
   */
  par_num = dec->info.aspect_numerator;
  par_den = dec->info.aspect_denominator;
  if (par_den == 0) {
    par_num = par_den = 1;
  }
  /* theora has:
   *
   *  width/height : dimension of the encoded frame 
   *  frame_width/frame_height : dimension of the visible part
   *  offset_x/offset_y : offset in encoded frame where visible part starts
   */
  GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.width,
      dec->info.height, par_num, par_den);
  GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d",
      dec->info.frame_width, dec->info.frame_height,
      dec->info.offset_x, dec->info.offset_y);
  if (dec->info.pixelformat != OC_PF_420) {
    GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE,
        (NULL), ("pixel formats other than 4:2:0 not yet supported"));

    return GST_FLOW_ERROR;
  }

  if (dec->crop) {
    /* add black borders to make width/height/offsets even. we need this because
     * we cannot express an offset to the peer plugin. */
    dec->width =
        GST_ROUND_UP_2 (dec->info.frame_width + (dec->info.offset_x & 1));
    dec->height =
        GST_ROUND_UP_2 (dec->info.frame_height + (dec->info.offset_y & 1));
    dec->offset_x = dec->info.offset_x & ~1;
    dec->offset_y = dec->info.offset_y & ~1;
  } else {
    /* no cropping, use the encoded dimensions */
    dec->width = dec->info.width;
    dec->height = dec->info.height;
    dec->offset_x = 0;
    dec->offset_y = 0;
  }

  dec->granule_shift = _theora_ilog (dec->info.keyframe_frequency_force - 1);

  /* With libtheora-1.0beta1 the granulepos scheme was changed:
   * where earlier the granulepos refered to the index/beginning
   * of a frame, it now refers to the end, which matches the use
   * in vorbis/speex. We check the bitstream version from the header so
   * we know which way to interpret the incoming granuepos
   */
  bitstream_version = (dec->info.version_major << 16) |
      (dec->info.version_minor << 8) | dec->info.version_subminor;
  dec->is_old_bitstream = (bitstream_version <= 0x00030200);

  GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d",
      dec->width, dec->height, dec->offset_x, dec->offset_y);

  /* done */
  theora_decode_init (&dec->state, &dec->info);

  caps = gst_caps_new_simple ("video/x-raw-yuv",
      "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
      "framerate", GST_TYPE_FRACTION,
      dec->info.fps_numerator, dec->info.fps_denominator,
      "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den,
      "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
  gst_pad_set_caps (dec->srcpad, caps);
  gst_caps_unref (caps);

  dec->have_header = TRUE;
  if (!dec->sent_newsegment) {
    GST_DEBUG_OBJECT (dec, "Sending newsegment event");

    event = gst_event_new_new_segment_full (FALSE,
        dec->segment.rate, dec->segment.applied_rate,
        dec->segment.format, dec->segment.start, dec->segment.stop,
        dec->segment.time);
    eret = gst_pad_push_event (dec->srcpad, event);
    dec->sent_newsegment = TRUE;
  }

  if (dec->tags) {
    gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec), dec->srcpad,
        dec->tags);
    dec->tags = NULL;
  }

  return ret;
}
Esempio n. 16
0
static gboolean
gst_au_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstAuParse *auparse;
  gboolean ret = TRUE;

  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_NEWSEGMENT:
    {
      GstFormat format;
      gdouble rate, arate;
      gint64 start, stop, time, offset = 0;
      gboolean update;
      GstSegment segment;
      GstEvent *new_event = NULL;

      gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
          &start, &stop, &time);
      gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
          start, stop, time);

      if (auparse->sample_size > 0) {
        if (start > 0) {
          offset = start;
          start -= auparse->offset;
          start = MAX (start, 0);
        }
        if (stop > 0) {
          stop -= auparse->offset;
          stop = MAX (stop, 0);
        }
        gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, start,
            GST_FORMAT_TIME, &start);
        gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, stop,
            GST_FORMAT_TIME, &stop);
      }

      if (auparse->srcpad) {
        GST_INFO_OBJECT (auparse,
            "new segment: %" GST_TIME_FORMAT " ... %" GST_TIME_FORMAT,
            GST_TIME_ARGS (start), GST_TIME_ARGS (stop));

        new_event = gst_event_new_new_segment_full (update, rate, arate,
            GST_FORMAT_TIME, start, stop, start);

        ret = gst_pad_push_event (auparse->srcpad, new_event);
      }

      auparse->buffer_offset = offset;

      gst_event_unref (event);
      break;
    }
    case GST_EVENT_EOS:
      if (!auparse->srcpad) {
        GST_ELEMENT_ERROR (auparse, STREAM, WRONG_TYPE,
            ("No valid input found before end of stream"), (NULL));
      }
      /* fall-through */
    default:
      ret = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (auparse);
  return ret;
}
Esempio n. 17
0
static gboolean
gst_real_audio_demux_handle_seek (GstRealAudioDemux * demux, GstEvent * event)
{
  GstFormat format;
  GstSeekFlags flags;
  GstSeekType cur_type, stop_type;
  gboolean flush, update;
  gdouble rate;
  guint64 seek_pos;
  gint64 cur, stop;

  if (!demux->seekable)
    goto not_seekable;

  if (demux->byterate_num == 0 || demux->byterate_denom == 0)
    goto no_bitrate;

  gst_event_parse_seek (event, &rate, &format, &flags,
      &cur_type, &cur, &stop_type, &stop);

  if (format != GST_FORMAT_TIME)
    goto only_time_format_supported;

  if (rate <= 0.0)
    goto cannot_do_backwards_playback;

  flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);

  GST_DEBUG_OBJECT (demux, "flush=%d, rate=%g", flush, rate);

  /* unlock streaming thread and make streaming stop */
  if (flush) {
    gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
    gst_pad_push_event (demux->srcpad, gst_event_new_flush_start ());
  } else {
    gst_pad_pause_task (demux->sinkpad);
  }

  GST_PAD_STREAM_LOCK (demux->sinkpad);

  if (demux->segment_running && !flush) {
    GstEvent *newseg;

    newseg = gst_event_new_new_segment_full (TRUE, demux->segment.rate,
        demux->segment.applied_rate, GST_FORMAT_TIME, demux->segment.start,
        demux->segment.last_stop, demux->segment.time);

    GST_DEBUG_OBJECT (demux, "sending NEWSEGMENT event to close the current "
        "segment: %" GST_PTR_FORMAT, newseg);

    gst_pad_push_event (demux->srcpad, newseg);
  }

  gst_segment_set_seek (&demux->segment, rate, format, flags,
      cur_type, cur, stop_type, stop, &update);

  GST_DEBUG_OBJECT (demux, "segment: %" GST_SEGMENT_FORMAT, &demux->segment);

  seek_pos = gst_util_uint64_scale (demux->segment.start,
      demux->byterate_num, demux->byterate_denom * GST_SECOND);
  if (demux->packet_size > 0) {
    seek_pos -= seek_pos % demux->packet_size;
  }
  seek_pos += demux->data_offset;

  GST_DEBUG_OBJECT (demux, "seek_pos = %" G_GUINT64_FORMAT, seek_pos);

  /* stop flushing */
  gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
  gst_pad_push_event (demux->srcpad, gst_event_new_flush_stop ());

  demux->offset = seek_pos;
  demux->need_newsegment = TRUE;

  /* notify start of new segment */
  if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
    gst_element_post_message (GST_ELEMENT (demux),
        gst_message_new_segment_start (GST_OBJECT (demux),
            GST_FORMAT_TIME, demux->segment.last_stop));
  }

  demux->segment_running = TRUE;
  /* restart our task since it might have been stopped when we did the flush */
  gst_pad_start_task (demux->sinkpad,
      (GstTaskFunction) gst_real_audio_demux_loop, demux);

  /* streaming can continue now */
  GST_PAD_STREAM_UNLOCK (demux->sinkpad);

  return TRUE;

/* ERRORS */
not_seekable:
  {
    GST_DEBUG_OBJECT (demux, "seek failed: cannot seek in streaming mode");
    return FALSE;
  }
no_bitrate:
  {
    GST_DEBUG_OBJECT (demux, "seek failed: bitrate unknown");
    return FALSE;
  }
only_time_format_supported:
  {
    GST_DEBUG_OBJECT (demux, "can only seek in TIME format");
    return FALSE;
  }
cannot_do_backwards_playback:
  {
    GST_DEBUG_OBJECT (demux, "can only seek with positive rate, not %lf", rate);
    return FALSE;
  }
}
Esempio n. 18
0
static GstFlowReturn
gst_interleave_collected (GstCollectPads * pads, GstInterleave * self)
{
  guint size;

  GstBuffer *outbuf;

  GstFlowReturn ret = GST_FLOW_OK;

  GSList *collected;

  guint nsamples;

  guint ncollected = 0;

  gboolean empty = TRUE;

  gint width = self->width / 8;

  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);

  size = gst_collect_pads_available (pads);

  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;

  ret =
      gst_pad_alloc_buffer (self->src, GST_BUFFER_OFFSET_NONE,
      size * self->channels, GST_PAD_CAPS (self->src), &outbuf);

  if (ret != GST_FLOW_OK) {
    return ret;
  } else if (outbuf == NULL || GST_BUFFER_SIZE (outbuf) < size * self->channels) {
    gst_buffer_unref (outbuf);
    return GST_FLOW_NOT_NEGOTIATED;
  } else if (!gst_caps_is_equal (GST_BUFFER_CAPS (outbuf),
          GST_PAD_CAPS (self->src))) {
    gst_buffer_unref (outbuf);
    return GST_FLOW_NOT_NEGOTIATED;
  }

  memset (GST_BUFFER_DATA (outbuf), 0, size * self->channels);

  for (collected = pads->data; collected != NULL; collected = collected->next) {
    GstCollectData *cdata;

    GstBuffer *inbuf;

    guint8 *outdata;

    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++;

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

    empty = FALSE;
    outdata =
        GST_BUFFER_DATA (outbuf) +
        width * GST_INTERLEAVE_PAD_CAST (cdata->pad)->channel;

    self->func (outdata, GST_BUFFER_DATA (inbuf), self->channels, nsamples);

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

  if (ncollected == 0)
    goto eos;

  if (self->segment_pending) {
    GstEvent *event;

    event = gst_event_new_new_segment_full (FALSE, self->segment_rate,
        1.0, GST_FORMAT_TIME, self->timestamp, -1, self->segment_position);

    gst_pad_push_event (self->src, event);
    self->segment_pending = FALSE;
    self->segment_position = 0;
  }

  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_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");
    gst_buffer_unref (outbuf);
    gst_pad_push_event (self->src, gst_event_new_eos ());
    return GST_FLOW_UNEXPECTED;
  }
}
Esempio n. 19
0
static gboolean
gst_raw_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
  gboolean ret;

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_EOS:
    case GST_EVENT_FLUSH_STOP:
      /* Only happens in push mode */
      gst_raw_parse_reset (rp);
      ret = gst_pad_push_event (rp->srcpad, event);
      break;
    case GST_EVENT_NEWSEGMENT:
    {
      GstClockTimeDiff start, stop, time;
      gdouble rate, arate;
      gboolean update;
      GstFormat format;

      /* Only happens in push mode */

      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
          &start, &stop, &time);

      if (format == GST_FORMAT_TIME) {
        gst_segment_set_newsegment_full (&rp->segment, update, rate, arate,
            GST_FORMAT_TIME, start, stop, time);
        ret = gst_pad_push_event (rp->srcpad, event);
      } else {

        gst_event_unref (event);

        ret =
            gst_raw_parse_convert (rp, format, start, GST_FORMAT_TIME, &start);
        ret &= gst_raw_parse_convert (rp, format, time, GST_FORMAT_TIME, &time);
        ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_TIME, &stop);
        if (!ret) {
          GST_ERROR_OBJECT (rp,
              "Failed converting to GST_FORMAT_TIME format (%d)", format);
          break;
        }

        gst_segment_set_newsegment_full (&rp->segment, update, rate, arate,
            GST_FORMAT_TIME, start, stop, time);

        /* create new segment with the fields converted to time */
        event = gst_event_new_new_segment_full (update, rate, arate,
            GST_FORMAT_TIME, start, stop, time);

        ret = gst_pad_push_event (rp->srcpad, event);
      }
      break;
    }
    default:
      ret = gst_pad_event_default (rp->sinkpad, event);
      break;
  }

  gst_object_unref (rp);

  return ret;
}
Esempio n. 20
0
static void
gst_live_adder_loop (gpointer data)
{
    GstLiveAdder *adder = GST_LIVE_ADDER (data);
    GstClockTime buffer_timestamp = 0;
    GstClockTime sync_time = 0;
    GstClock *clock = NULL;
    GstClockID id = NULL;
    GstClockReturn ret;
    GstBuffer *buffer = NULL;
    GstFlowReturn result;
    GstEvent *newseg_event = NULL;

    GST_OBJECT_LOCK (adder);

again:

    for (;;) {
        if (adder->srcresult != GST_FLOW_OK)
            goto flushing;
        if (!g_queue_is_empty (adder->buffers))
            break;
        if (check_eos_locked (adder))
            goto eos;
        g_cond_wait (adder->not_empty_cond, GST_OBJECT_GET_LOCK (adder));
    }

    buffer_timestamp = GST_BUFFER_TIMESTAMP (g_queue_peek_head (adder->buffers));

    clock = GST_ELEMENT_CLOCK (adder);

    /* If we have no clock, then we can't do anything.. error */
    if (!clock) {
        if (adder->playing)
            goto no_clock;
        else
            goto push_buffer;
    }

    GST_DEBUG_OBJECT (adder, "sync to timestamp %" GST_TIME_FORMAT,
                      GST_TIME_ARGS (buffer_timestamp));

    sync_time = buffer_timestamp + GST_ELEMENT_CAST (adder)->base_time;
    /* add latency, this includes our own latency and the peer latency. */
    sync_time += adder->latency_ms * GST_MSECOND;
    sync_time += adder->peer_latency;

    /* create an entry for the clock */
    id = adder->clock_id = gst_clock_new_single_shot_id (clock, sync_time);
    GST_OBJECT_UNLOCK (adder);

    ret = gst_clock_id_wait (id, NULL);

    GST_OBJECT_LOCK (adder);

    /* and free the entry */
    gst_clock_id_unref (id);
    adder->clock_id = NULL;

    /* at this point, the clock could have been unlocked by a timeout, a new
     * head element was added to the queue or because we are shutting down. Check
     * for shutdown first. */

    if (adder->srcresult != GST_FLOW_OK)
        goto flushing;

    if (ret == GST_CLOCK_UNSCHEDULED) {
        GST_DEBUG_OBJECT (adder,
                          "Wait got unscheduled, will retry to push with new buffer");
        goto again;
    }

    if (ret != GST_CLOCK_OK && ret != GST_CLOCK_EARLY)
        goto clock_error;

push_buffer:

    buffer = g_queue_pop_head (adder->buffers);

    if (!buffer)
        goto again;

    /*
     * We make sure the timestamps are exactly contiguous
     * If its only small skew (due to rounding errors), we correct it
     * silently. Otherwise we put the discont flag
     */
    if (GST_CLOCK_TIME_IS_VALID (adder->next_timestamp) &&
            GST_BUFFER_TIMESTAMP (buffer) != adder->next_timestamp) {
        GstClockTimeDiff diff = GST_CLOCK_DIFF (GST_BUFFER_TIMESTAMP (buffer),
                                                adder->next_timestamp);
        if (diff < 0)
            diff = -diff;

        if (diff < GST_SECOND / adder->rate) {
            GST_BUFFER_TIMESTAMP (buffer) = adder->next_timestamp;
            GST_DEBUG_OBJECT (adder, "Correcting slight skew");
            GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT);
        } else {
            GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
            GST_DEBUG_OBJECT (adder, "Expected buffer at %" GST_TIME_FORMAT
                              ", but is at %" GST_TIME_FORMAT ", setting discont",
                              GST_TIME_ARGS (adder->next_timestamp),
                              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
        }
    } else {
        GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT);
    }

    GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE;
    GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE;

    if (GST_BUFFER_DURATION_IS_VALID (buffer))
        adder->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) +
                                GST_BUFFER_DURATION (buffer);
    else
        adder->next_timestamp = GST_CLOCK_TIME_NONE;

    if (adder->segment_pending) {
        /*
         * We set the start at 0, because we re-timestamps to the running time
         */
        newseg_event = gst_event_new_new_segment_full (FALSE, 1.0, 1.0,
                       GST_FORMAT_TIME, 0, -1, 0);

        adder->segment_pending = FALSE;
    }

    GST_OBJECT_UNLOCK (adder);

    if (newseg_event)
        gst_pad_push_event (adder->srcpad, newseg_event);

    GST_LOG_OBJECT (adder, "About to push buffer time:%" GST_TIME_FORMAT
                    " duration:%" GST_TIME_FORMAT,
                    GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
                    GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));

    result = gst_pad_push (adder->srcpad, buffer);
    if (result != GST_FLOW_OK)
        goto pause;

    return;

flushing:
    {
        GST_DEBUG_OBJECT (adder, "we are flushing");
        gst_pad_pause_task (adder->srcpad);
        GST_OBJECT_UNLOCK (adder);
        return;
    }

clock_error:
    {
        gst_pad_pause_task (adder->srcpad);
        GST_OBJECT_UNLOCK (adder);
        GST_ELEMENT_ERROR (adder, STREAM, MUX, ("Error with the clock"),
                           ("Error with the clock: %d", ret));
        GST_ERROR_OBJECT (adder, "Error with the clock: %d", ret);
        return;
    }

no_clock:
    {
        gst_pad_pause_task (adder->srcpad);
        GST_OBJECT_UNLOCK (adder);
        GST_ELEMENT_ERROR (adder, STREAM, MUX, ("No available clock"),
                           ("No available clock"));
        GST_ERROR_OBJECT (adder, "No available clock");
        return;
    }

pause:
    {
        GST_DEBUG_OBJECT (adder, "pausing task, reason %s",
                          gst_flow_get_name (result));

        GST_OBJECT_LOCK (adder);

        /* store result */
        adder->srcresult = result;
        /* we don't post errors or anything because upstream will do that for us
         * when we pass the return value upstream. */
        gst_pad_pause_task (adder->srcpad);
        GST_OBJECT_UNLOCK (adder);
        return;
    }

eos:
    {
        /* store result, we are flushing now */
        GST_DEBUG_OBJECT (adder, "We are EOS, pushing EOS downstream");
        adder->srcresult = GST_FLOW_UNEXPECTED;
        gst_pad_pause_task (adder->srcpad);
        GST_OBJECT_UNLOCK (adder);
        gst_pad_push_event (adder->srcpad, gst_event_new_eos ());
        return;
    }
}
Esempio n. 21
0
static gboolean
gst_raw_parse_handle_seek_pull (GstRawParse * rp, GstEvent * event)
{
  gdouble rate;
  GstFormat format;
  GstSeekFlags flags;
  GstSeekType start_type, stop_type;
  gint64 start, stop;
  gint64 last_stop;
  gboolean ret = FALSE;
  gboolean flush;
  GstSegment seeksegment;

  if (event) {
    gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
        &stop_type, &stop);

    /* convert input offsets to time */
    ret = gst_raw_parse_convert (rp, format, start, GST_FORMAT_TIME, &start);
    ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_TIME, &stop);
    if (!ret)
      goto convert_failed;

    GST_DEBUG_OBJECT (rp, "converted start - stop to time");

    format = GST_FORMAT_TIME;

    gst_event_unref (event);
  } else {
    format = GST_FORMAT_TIME;
    flags = 0;
  }

  flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);

  /* start flushing up and downstream so that the loop function pauses and we
   * can acquire the STREAM_LOCK. */
  if (flush) {
    GST_LOG_OBJECT (rp, "flushing");
    gst_pad_push_event (rp->sinkpad, gst_event_new_flush_start ());
    gst_pad_push_event (rp->srcpad, gst_event_new_flush_start ());
  } else {
    GST_LOG_OBJECT (rp, "pause task");
    gst_pad_pause_task (rp->sinkpad);
  }

  GST_PAD_STREAM_LOCK (rp->sinkpad);

  memcpy (&seeksegment, &rp->segment, sizeof (GstSegment));

  if (event) {
    /* configure the seek values */
    gst_segment_set_seek (&seeksegment, rate, format, flags,
        start_type, start, stop_type, stop, NULL);
  }

  /* get the desired position */
  last_stop = seeksegment.last_stop;

  GST_LOG_OBJECT (rp, "seeking to %" GST_TIME_FORMAT,
      GST_TIME_ARGS (last_stop));

  /* convert the desired position to bytes */
  ret =
      gst_raw_parse_convert (rp, format, last_stop, GST_FORMAT_BYTES,
      &last_stop);

  /* prepare for streaming */
  if (flush) {
    GST_LOG_OBJECT (rp, "stop flush");
    gst_pad_push_event (rp->sinkpad, gst_event_new_flush_stop ());
    gst_pad_push_event (rp->srcpad, gst_event_new_flush_stop ());
  } else if (ret && rp->running) {
    /* we are running the current segment and doing a non-flushing seek, 
     * close the segment first based on the last_stop. */
    GST_DEBUG_OBJECT (rp, "prepare close segment %" G_GINT64_FORMAT
        " to %" G_GINT64_FORMAT, rp->segment.start, rp->segment.last_stop);

    /* queue the segment for sending in the stream thread */
    if (rp->close_segment)
      gst_event_unref (rp->close_segment);
    rp->close_segment =
        gst_event_new_new_segment_full (TRUE,
        rp->segment.rate, rp->segment.applied_rate, rp->segment.format,
        rp->segment.start, rp->segment.last_stop, rp->segment.time);
  }

  if (ret) {
    /* seek done */

    /* Seek on a frame boundary */
    last_stop -= last_stop % rp->framesize;

    rp->offset = last_stop;
    rp->n_frames = last_stop / rp->framesize;

    GST_LOG_OBJECT (rp, "seeking to bytes %" G_GINT64_FORMAT, last_stop);

    memcpy (&rp->segment, &seeksegment, sizeof (GstSegment));

    if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) {
      gst_element_post_message (GST_ELEMENT_CAST (rp),
          gst_message_new_segment_start (GST_OBJECT_CAST (rp),
              rp->segment.format, rp->segment.last_stop));
    }

    /* for deriving a stop position for the playback segment from the seek
     * segment, we must take the duration when the stop is not set */
    if ((stop = rp->segment.stop) == -1)
      stop = rp->segment.duration;

    GST_DEBUG_OBJECT (rp, "preparing newsegment from %" G_GINT64_FORMAT
        " to %" G_GINT64_FORMAT, rp->segment.start, stop);

    /* now replace the old segment so that we send it in the stream thread the
     * next time it is scheduled. */
    if (rp->start_segment)
      gst_event_unref (rp->start_segment);

    if (rp->segment.rate >= 0.0) {
      /* forward, we send data from last_stop to stop */
      rp->start_segment =
          gst_event_new_new_segment_full (FALSE,
          rp->segment.rate, rp->segment.applied_rate, rp->segment.format,
          rp->segment.last_stop, stop, rp->segment.time);
    } else {
      /* reverse, we send data from last_stop to start */
      rp->start_segment =
          gst_event_new_new_segment_full (FALSE,
          rp->segment.rate, rp->segment.applied_rate, rp->segment.format,
          rp->segment.start, rp->segment.last_stop, rp->segment.time);
    }
  }
  rp->discont = TRUE;

  GST_LOG_OBJECT (rp, "start streaming");
  rp->running = TRUE;
  gst_pad_start_task (rp->sinkpad, (GstTaskFunction) gst_raw_parse_loop, rp);

  GST_PAD_STREAM_UNLOCK (rp->sinkpad);

  return ret;

  /* ERRORS */
convert_failed:
  {
    GST_DEBUG_OBJECT (rp, "Seek failed: couldn't convert to byte positions");
    return FALSE;
  }
}