static GstStateChangeReturn
gst_multipart_demux_change_state (GstElement * element,
    GstStateChange transition)
{
  GstMultipartDemux *multipart;
  GstStateChangeReturn ret;

  multipart = GST_MULTIPART_DEMUX (element);

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

  switch (transition) {
    case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
      break;
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      multipart->header_completed = FALSE;
      g_free (multipart->boundary);
      multipart->boundary = NULL;
      g_free (multipart->mime_type);
      multipart->mime_type = NULL;
      gst_adapter_clear (multipart->adapter);
      multipart->content_length = -1;
      multipart->scanpos = 0;
      gst_multipart_demux_remove_src_pads (multipart);
      multipart->have_group_id = FALSE;
      multipart->group_id = G_MAXUINT;
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      break;
    default:
      break;
  }

  return ret;
}
Exemplo n.º 2
0
static void
gst_multipart_get_property (GObject * object, guint prop_id,
                            GValue * value, GParamSpec * pspec)
{
    GstMultipartDemux *filter;

    g_return_if_fail (GST_IS_MULTIPART_DEMUX (object));
    filter = GST_MULTIPART_DEMUX (object);

    switch (prop_id) {
    case PROP_BOUNDARY:
        g_value_set_string (value, filter->boundary);
        break;
    case PROP_AUTOSCAN:
        g_value_set_boolean (value, filter->autoscan);
        break;
    case PROP_SINGLE_STREAM:
        g_value_set_boolean (value, filter->singleStream);
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}
Exemplo n.º 3
0
static GstFlowReturn
gst_multipart_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
{
  GstMultipartDemux *multipart;
  GstAdapter *adapter;
  gint size = 1;
  GstFlowReturn res;

  multipart = GST_MULTIPART_DEMUX (parent);
  adapter = multipart->adapter;

  res = GST_FLOW_OK;

  if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
    GSList *l;

    for (l = multipart->srcpads; l != NULL; l = l->next) {
      GstMultipartPad *srcpad = l->data;

      srcpad->discont = TRUE;
    }
    gst_adapter_clear (adapter);
  }
  gst_adapter_push (adapter, buf);

  while (gst_adapter_available (adapter) > 0) {
    GstMultipartPad *srcpad;
    GstBuffer *outbuf;
    gboolean created;
    gint datalen;

    if (G_UNLIKELY (!multipart->header_completed)) {
      if ((size = multipart_parse_header (multipart)) < 0) {
        goto nodata;
      } else {
        gst_adapter_flush (adapter, size);
        multipart->header_completed = TRUE;
      }
    }
    if ((size = multipart_find_boundary (multipart, &datalen)) < 0) {
      goto nodata;
    }

    /* Invalidate header info */
    multipart->header_completed = FALSE;
    multipart->content_length = -1;

    if (G_UNLIKELY (datalen <= 0)) {
      GST_DEBUG_OBJECT (multipart, "skipping empty content.");
      gst_adapter_flush (adapter, size - datalen);
    } else {
      GstClockTime ts;

      srcpad =
          gst_multipart_find_pad_by_mime (multipart,
          multipart->mime_type, &created);

      ts = gst_adapter_prev_pts (adapter, NULL);
      outbuf = gst_adapter_take_buffer (adapter, datalen);
      gst_adapter_flush (adapter, size - datalen);

      if (created) {
        GstTagList *tags;
        GstSegment segment;

        gst_segment_init (&segment, GST_FORMAT_TIME);

        /* Push new segment, first buffer has 0 timestamp */
        gst_pad_push_event (srcpad->pad, gst_event_new_segment (&segment));

        tags = gst_tag_list_new (GST_TAG_CONTAINER_FORMAT, "Multipart", NULL);
        gst_tag_list_set_scope (tags, GST_TAG_SCOPE_GLOBAL);
        gst_pad_push_event (srcpad->pad, gst_event_new_tag (tags));
      }

      outbuf = gst_buffer_make_writable (outbuf);
      if (srcpad->last_ts == GST_CLOCK_TIME_NONE || srcpad->last_ts != ts) {
        GST_BUFFER_TIMESTAMP (outbuf) = ts;
        srcpad->last_ts = ts;
      } else {
        GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
      }

      if (srcpad->discont) {
        GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
        srcpad->discont = FALSE;
      } else {
        GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DISCONT);
      }

      GST_DEBUG_OBJECT (multipart,
          "pushing buffer with timestamp %" GST_TIME_FORMAT,
          GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
      res = gst_pad_push (srcpad->pad, outbuf);
      res = gst_multipart_combine_flows (multipart, srcpad, res);
      if (res != GST_FLOW_OK)
        break;
    }
  }

nodata:
  if (G_UNLIKELY (size == MULTIPART_DATA_ERROR))
    return GST_FLOW_ERROR;
  if (G_UNLIKELY (size == MULTIPART_DATA_EOS))
    return GST_FLOW_EOS;

  return res;
}
Exemplo n.º 4
0
static GstFlowReturn
gst_multipart_demux_chain (GstPad * pad, GstBuffer * buf)
{
    GstMultipartDemux *multipart;
    GstAdapter *adapter;
    GstClockTime timestamp;
    gint size = 1;
    GstFlowReturn res;

    multipart = GST_MULTIPART_DEMUX (gst_pad_get_parent (pad));
    adapter = multipart->adapter;

    res = GST_FLOW_OK;

    timestamp = GST_BUFFER_TIMESTAMP (buf);

    if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
        gst_adapter_clear (adapter);
    }
    gst_adapter_push (adapter, buf);

    while (gst_adapter_available (adapter) > 0) {
        GstMultipartPad *srcpad;
        GstBuffer *outbuf;
        gboolean created;
        gint datalen;

        if (G_UNLIKELY (!multipart->header_completed)) {
            if ((size = multipart_parse_header (multipart)) < 0) {
                goto nodata;
            } else {
                gst_adapter_flush (adapter, size);
                multipart->header_completed = TRUE;
            }
        }
        if ((size = multipart_find_boundary (multipart, &datalen)) < 0) {
            goto nodata;
        }

        /* Invalidate header info */
        multipart->header_completed = FALSE;
        multipart->content_length = -1;

        if (G_UNLIKELY (datalen <= 0)) {
            GST_DEBUG_OBJECT (multipart, "skipping empty content.");
            gst_adapter_flush (adapter, size - datalen);
        } else {
            srcpad =
                gst_multipart_find_pad_by_mime (multipart,
                                                multipart->mime_type, &created);
            outbuf = gst_adapter_take_buffer (adapter, datalen);
            gst_adapter_flush (adapter, size - datalen);

            gst_buffer_set_caps (outbuf, GST_PAD_CAPS (srcpad->pad));
            if (created) {
                GstTagList *tags;

                /* Push new segment, first buffer has 0 timestamp */
                gst_pad_push_event (srcpad->pad,
                                    gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));

                tags =
                    gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "Multipart", NULL);
                gst_pad_push_event (srcpad->pad, gst_event_new_tag (tags));

                GST_BUFFER_TIMESTAMP (outbuf) = 0;
            } else {
                GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
            }
            GST_DEBUG_OBJECT (multipart,
                              "pushing buffer with timestamp %" GST_TIME_FORMAT,
                              GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
            GST_DEBUG_OBJECT (multipart, "buffer has caps %" GST_PTR_FORMAT,
                              GST_BUFFER_CAPS (outbuf));
            res = gst_pad_push (srcpad->pad, outbuf);
            res = gst_multipart_combine_flows (multipart, srcpad, res);
            if (res != GST_FLOW_OK)
                break;
        }
    }

nodata:
    gst_object_unref (multipart);

    if (G_UNLIKELY (size == MULTIPART_DATA_ERROR))
        return GST_FLOW_ERROR;
    if (G_UNLIKELY (size == MULTIPART_DATA_EOS))
        return GST_FLOW_UNEXPECTED;

    return res;
}