示例#1
0
static void
gst_au_parse_dispose (GObject * object)
{
  GstAuParse *au = GST_AU_PARSE (object);

  if (au->adapter != NULL) {
    g_object_unref (au->adapter);
    au->adapter = NULL;
  }
  G_OBJECT_CLASS (parent_class)->dispose (object);
}
示例#2
0
static gboolean
gst_au_parse_sink_event (GstPad * pad, GstEvent * event)
{
  GstAuParse *auparse;
  gboolean ret;

  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));

  switch (GST_EVENT_TYPE (event)) {
    default:
      ret = gst_pad_event_default (pad, event);
      break;
  }

  gst_object_unref (auparse);
  return ret;
}
示例#3
0
static GstStateChangeReturn
gst_au_parse_change_state (GstElement * element, GstStateChange transition)
{
  GstAuParse *auparse = GST_AU_PARSE (element);
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  ret = parent_class->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_au_parse_reset (auparse);
    default:
      break;
  }

  return ret;
}
示例#4
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;
}
示例#5
0
static gboolean
gst_au_parse_src_query (GstPad * pad, GstQuery * query)
{
  GstAuParse *auparse;
  gboolean ret = FALSE;

  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));

  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_DURATION:{
      GstFormat bformat = GST_FORMAT_BYTES;
      GstFormat format;
      gint64 len, val;

      gst_query_parse_duration (query, &format, NULL);
      if (!gst_pad_query_peer_duration (auparse->sinkpad, &bformat, &len)) {
        GST_DEBUG_OBJECT (auparse, "failed to query upstream length");
        break;
      }
      GST_OBJECT_LOCK (auparse);
      len -= auparse->offset;
      GST_OBJECT_UNLOCK (auparse);

      ret = gst_au_parse_src_convert (auparse, bformat, len, format, &val);

      if (ret) {
        gst_query_set_duration (query, format, val);
      }
      break;
    }
    case GST_QUERY_POSITION:{
      GstFormat bformat = GST_FORMAT_BYTES;
      GstFormat format;
      gint64 pos, val;

      gst_query_parse_position (query, &format, NULL);
      if (!gst_pad_query_peer_position (auparse->sinkpad, &bformat, &pos)) {
        GST_DEBUG_OBJECT (auparse, "failed to query upstream position");
        break;
      }
      GST_OBJECT_LOCK (auparse);
      pos -= auparse->offset;
      GST_OBJECT_UNLOCK (auparse);

      ret = gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos,
          format, &val);

      if (ret) {
        gst_query_set_position (query, format, val);
      }
      break;
    }
    case GST_QUERY_SEEKING:{
      GstFormat format;

      gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
      /* FIXME: query duration in 'format'
         gst_query_set_seeking (query, format, TRUE, 0, duration);
       */
      gst_query_set_seeking (query, format, TRUE, 0, GST_CLOCK_TIME_NONE);
      ret = TRUE;
      break;
    }
    default:
      ret = gst_pad_query_default (pad, query);
      break;
  }

  gst_object_unref (auparse);
  return ret;
}
示例#6
0
static GstFlowReturn
gst_au_parse_chain (GstPad * pad, GstBuffer * buf)
{
  GstFlowReturn ret = GST_FLOW_OK;
  GstAuParse *auparse;
  gint avail, sendnow = 0;
  gint64 timestamp;
  gint64 duration;
  gint64 offset;

  auparse = GST_AU_PARSE (gst_pad_get_parent (pad));

  GST_LOG_OBJECT (auparse, "got buffer of size %u", GST_BUFFER_SIZE (buf));

  gst_adapter_push (auparse->adapter, buf);
  buf = NULL;

  /* if we haven't seen any data yet... */
  if (auparse->srcpad == NULL) {
    if (gst_adapter_available (auparse->adapter) < AU_HEADER_SIZE) {
      GST_DEBUG_OBJECT (auparse, "need more data to parse header");
      ret = GST_FLOW_OK;
      goto out;
    }

    ret = gst_au_parse_parse_header (auparse);
    if (ret != GST_FLOW_OK)
      goto out;

    gst_pad_push_event (auparse->srcpad,
        gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
            0, GST_CLOCK_TIME_NONE, 0));
  }

  avail = gst_adapter_available (auparse->adapter);

  if (auparse->sample_size > 0) {
    /* Ensure we push a buffer that's a multiple of the frame size downstream */
    sendnow = avail - (avail % auparse->sample_size);
  } else {
    /* It's something non-trivial (such as ADPCM), we don't understand it, so
     * just push downstream and assume it will know what to do with it */
    sendnow = avail;
  }

  if (sendnow > 0) {
    GstBuffer *outbuf;
    const guint8 *data;
    gint64 pos;

    ret = gst_pad_alloc_buffer_and_set_caps (auparse->srcpad,
        auparse->buffer_offset, sendnow, GST_PAD_CAPS (auparse->srcpad),
        &outbuf);

    if (ret != GST_FLOW_OK) {
      GST_DEBUG_OBJECT (auparse, "pad alloc flow: %s", gst_flow_get_name (ret));
      goto out;
    }

    data = gst_adapter_peek (auparse->adapter, sendnow);
    memcpy (GST_BUFFER_DATA (outbuf), data, sendnow);
    gst_adapter_flush (auparse->adapter, sendnow);

    pos = auparse->buffer_offset - auparse->offset;
    pos = MAX (pos, 0);

    if (auparse->sample_size > 0 && auparse->samplerate > 0) {
      gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos,
          GST_FORMAT_DEFAULT, &offset);
      gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES, pos,
          GST_FORMAT_TIME, &timestamp);
      gst_au_parse_src_convert (auparse, GST_FORMAT_BYTES,
          sendnow, GST_FORMAT_TIME, &duration);

      GST_BUFFER_OFFSET (outbuf) = offset;
      GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
      GST_BUFFER_DURATION (outbuf) = duration;
    }

    auparse->buffer_offset += sendnow;

    ret = gst_pad_push (auparse->srcpad, outbuf);
  }

out:

  gst_object_unref (auparse);
  return ret;
}