コード例 #1
0
ファイル: multipartdemux.c プロジェクト: PeterXu/gst-mobile
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;
}
コード例 #2
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;
}