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