static void gst_multipart_demux_finalize (GObject * object);
-GST_BOILERPLATE (GstMultipartDemux, gst_multipart_demux, GstElement,
- GST_TYPE_ELEMENT);
-
-static void
-gst_multipart_demux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&multipart_demux_sink_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&multipart_demux_src_template_factory));
- gst_element_class_set_details_simple (element_class, "Multipart demuxer",
- "Codec/Demuxer",
- "demux multipart streams",
- "Wim Taymans <wim.taymans@gmail.com>, Sjoerd Simons <sjoerd@luon.net>");
-}
+#define gst_multipart_demux_parent_class parent_class
+G_DEFINE_TYPE (GstMultipartDemux, gst_multipart_demux, GST_TYPE_ELEMENT);
static void
gst_multipart_demux_class_init (GstMultipartDemuxClass * klass)
}
gstelement_class->change_state = gst_multipart_demux_change_state;
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&multipart_demux_sink_template_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&multipart_demux_src_template_factory));
+ gst_element_class_set_details_simple (gstelement_class, "Multipart demuxer",
+ "Codec/Demuxer",
+ "demux multipart streams",
+ "Wim Taymans <wim.taymans@gmail.com>, Sjoerd Simons <sjoerd@luon.net>");
}
static void
-gst_multipart_demux_init (GstMultipartDemux * multipart,
- GstMultipartDemuxClass * g_class)
+gst_multipart_demux_init (GstMultipartDemux * multipart)
{
/* create the sink pad */
multipart->sinkpad =
guint8 *end, *next;
datalen = gst_adapter_available (multipart->adapter);
- data = gst_adapter_peek (multipart->adapter, datalen);
+ data = gst_adapter_map (multipart->adapter, datalen);
dataend = data + datalen;
/* Skip leading whitespace, pos endposition should at least leave space for
for (pos = (guint8 *) data; pos < dataend - 4 && g_ascii_isspace (*pos);
pos++);
- if (pos >= dataend - 4) {
- return MULTIPART_NEED_MORE_DATA;
- }
+ if (pos >= dataend - 4)
+ goto need_more_data;
if (G_UNLIKELY (pos[0] != '-' || pos[1] != '-')) {
GST_DEBUG_OBJECT (multipart, "No boundary available");
/* First the boundary */
if (!get_line_end (pos, dataend, &end, &next))
- return MULTIPART_NEED_MORE_DATA;
+ goto need_more_data;
/* Ignore the leading -- */
boundary_len = end - pos - 2;
* invalid */
if (G_UNLIKELY (boundary_len == multipart->boundary_len + 2 &&
!strncmp (boundary, multipart->boundary, multipart->boundary_len) &&
- !strncmp (boundary + multipart->boundary_len, "--", 2))) {
- return MULTIPART_DATA_EOS;
- }
+ !strncmp (boundary + multipart->boundary_len, "--", 2)))
+ goto eos;
+
GST_DEBUG_OBJECT (multipart,
"Boundary length doesn't match detected boundary (%d <> %d",
boundary_len, multipart->boundary_len);
goto wrong_header;
}
-
pos = next;
while (get_line_end (pos, dataend, &end, &next)) {
guint len = end - pos;
GST_DEBUG_OBJECT (multipart,
"Parsed the header - boundary: %s, mime-type: %s, content-length: %d",
multipart->boundary, multipart->mime_type, multipart->content_length);
+ gst_adapter_unmap (multipart->adapter, 0);
return next - data;
}
}
pos = next;
}
+
+need_more_data:
GST_DEBUG_OBJECT (multipart, "Need more data for the header");
+ gst_adapter_unmap (multipart->adapter, 0);
+
return MULTIPART_NEED_MORE_DATA;
wrong_header:
{
GST_ELEMENT_ERROR (multipart, STREAM, DEMUX, (NULL),
("Boundary not found in the multipart header"));
+ gst_adapter_unmap (multipart->adapter, 0);
return MULTIPART_DATA_ERROR;
}
+eos:
+ {
+ GST_DEBUG_OBJECT (multipart, "we are EOS");
+ gst_adapter_unmap (multipart->adapter, 0);
+ return MULTIPART_DATA_EOS;
+ }
}
static gint
len = multipart->content_length;
if (gst_adapter_available (multipart->adapter) >= len + 2) {
*datalen = len;
- data = gst_adapter_peek (multipart->adapter, len + 1);
+ data = gst_adapter_map (multipart->adapter, len + 1);
/* If data[len] contains \r then assume a newline is \r\n */
if (data[len] == '\r')
len += 2;
else if (data[len] == '\n')
len += 1;
- /* Don't check if boundary is actually there, but let the header parsing
+
+ gst_adapter_unmap (multipart->adapter, 0);
+ /* Don't check if boundary is actually there, but let the header parsing
* bail out if it isn't */
return len;
} else {
len = gst_adapter_available (multipart->adapter);
if (len == 0)
return MULTIPART_NEED_MORE_DATA;
- data = gst_adapter_peek (multipart->adapter, len);
+ data = gst_adapter_map (multipart->adapter, len);
dataend = data + len;
for (pos = data + multipart->scanpos;
len -= 1;
*datalen = len;
+ gst_adapter_unmap (multipart->adapter, 0);
multipart->scanpos = 0;
return pos - data;
}
}
+ gst_adapter_unmap (multipart->adapter, 0);
multipart->scanpos = pos - data;
return MULTIPART_NEED_MORE_DATA;
}
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;
+ 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_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
+ gst_pad_push_event (srcpad->pad, gst_event_new_segment (&segment));
tags =
gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "Multipart", NULL);
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)
{NULL, NULL}
};
-static void gst_multipart_mux_base_init (gpointer g_class);
-static void gst_multipart_mux_class_init (GstMultipartMuxClass * klass);
-static void gst_multipart_mux_init (GstMultipartMux * multipart_mux);
-
static void gst_multipart_mux_finalize (GObject * object);
static gboolean gst_multipart_mux_handle_src_event (GstPad * pad,
GstEvent * event);
static GstPad *gst_multipart_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
+ GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
static GstStateChangeReturn gst_multipart_mux_change_state (GstElement *
element, GstStateChange transition);
static void gst_multipart_mux_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static GstElementClass *parent_class = NULL;
-
-GType
-gst_multipart_mux_get_type (void)
-{
- static GType multipart_mux_type = 0;
-
- if (!multipart_mux_type) {
- static const GTypeInfo multipart_mux_info = {
- sizeof (GstMultipartMuxClass),
- gst_multipart_mux_base_init,
- NULL,
- (GClassInitFunc) gst_multipart_mux_class_init,
- NULL,
- NULL,
- sizeof (GstMultipartMux),
- 0,
- (GInstanceInitFunc) gst_multipart_mux_init,
- };
-
- multipart_mux_type =
- g_type_register_static (GST_TYPE_ELEMENT, "GstMultipartMux",
- &multipart_mux_info, 0);
- }
- return multipart_mux_type;
-}
-
-static void
-gst_multipart_mux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_factory));
-
- gst_element_class_set_details_simple (element_class, "Multipart muxer",
- "Codec/Muxer", "mux multipart streams", "Wim Taymans <wim@fluendo.com>");
-}
+#define gst_multipart_mux_parent_class parent_class
+G_DEFINE_TYPE (GstMultipartMux, gst_multipart_mux, GST_TYPE_ELEMENT);
static void
gst_multipart_mux_class_init (GstMultipartMuxClass * klass)
gstelement_class->request_new_pad = gst_multipart_mux_request_new_pad;
gstelement_class->change_state = gst_multipart_mux_change_state;
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&sink_factory));
+
+ gst_element_class_set_details_simple (gstelement_class, "Multipart muxer",
+ "Codec/Muxer", "mux multipart streams", "Wim Taymans <wim@fluendo.com>");
+
/* populate mime types */
klass->mimetypes = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; mimetypes[i].key; i++) {
static GstPad *
gst_multipart_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * req_name)
+ GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
{
GstMultipartMux *multipart_mux;
GstPad *newpad;
sizeof (GstMultipartPadData));
/* save a pointer to our data in the pad */
+ multipartpad->pad = newpad;
gst_pad_set_element_private (newpad, multipartpad);
multipart_mux->numpads++;
}
GstBuffer *footerbuf = NULL;
GstBuffer *databuf = NULL;
GstStructure *structure = NULL;
+ GstCaps *caps;
const gchar *mime;
GST_DEBUG_OBJECT (mux, "all pads are collected");
/* see if we need to push a segment */
if (mux->need_segment) {
- GstEvent *event;
GstClockTime time;
+ GstSegment segment;
if (best->timestamp != -1)
time = best->timestamp;
/* for the segment, we take the first timestamp we see, we don't know the
* length and the position is 0 */
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
- time, -1, 0);
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+ segment.start = time;
- gst_pad_push_event (mux->srcpad, event);
+ gst_pad_push_event (mux->srcpad, gst_event_new_segment (&segment));
mux->need_segment = FALSE;
}
- structure = gst_caps_get_structure (GST_BUFFER_CAPS (best->buffer), 0);
- if (!structure)
+ caps = gst_pad_get_current_caps (best->pad);
+ if (caps == NULL)
goto no_caps;
+ structure = gst_caps_get_structure (caps, 0);
+ if (!structure) {
+ gst_caps_unref (caps);
+ goto no_caps;
+ }
+
/* get the mime type for the structure */
mime = gst_multipart_mux_get_mime (mux, structure);
+ gst_caps_unref (caps);
header = g_strdup_printf ("--%s\r\nContent-Type: %s\r\n"
- "Content-Length: %u\r\n\r\n",
- mux->boundary, mime, GST_BUFFER_SIZE (best->buffer));
+ "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n",
+ mux->boundary, mime, gst_buffer_get_size (best->buffer));
headerlen = strlen (header);
- ret = gst_pad_alloc_buffer_and_set_caps (mux->srcpad, GST_BUFFER_OFFSET_NONE,
- headerlen, GST_PAD_CAPS (mux->srcpad), &headerbuf);
- if (ret != GST_FLOW_OK)
- goto alloc_failed;
-
- memcpy (GST_BUFFER_DATA (headerbuf), header, headerlen);
+ headerbuf = gst_buffer_new_allocate (NULL, headerlen, 1);
+ gst_buffer_fill (headerbuf, 0, header, headerlen);
g_free (header);
/* the header has the same timestamp as the data buffer (which we will push
/* take best->buffer, we don't need to unref it later as we will push it
* now. */
- databuf = gst_buffer_make_metadata_writable (best->buffer);
+ databuf = gst_buffer_make_writable (best->buffer);
best->buffer = NULL;
- gst_buffer_set_caps (databuf, GST_PAD_CAPS (mux->srcpad));
/* we need to updated the timestamp to match the running_time */
GST_BUFFER_TIMESTAMP (databuf) = best->timestamp;
GST_BUFFER_OFFSET (databuf) = mux->offset;
- mux->offset += GST_BUFFER_SIZE (databuf);
+ mux->offset += gst_buffer_get_size (databuf);
GST_BUFFER_OFFSET_END (databuf) = mux->offset;
GST_BUFFER_FLAG_SET (databuf, GST_BUFFER_FLAG_DELTA_UNIT);
- GST_DEBUG_OBJECT (mux, "pushing %u bytes data buffer",
- GST_BUFFER_SIZE (databuf));
+ GST_DEBUG_OBJECT (mux, "pushing %" G_GSIZE_FORMAT " bytes data buffer",
+ gst_buffer_get_size (databuf));
ret = gst_pad_push (mux->srcpad, databuf);
if (ret != GST_FLOW_OK)
/* push always takes ownership of the buffer, even after an error, so we
* don't need to unref headerbuf here. */
goto beach;
- ret = gst_pad_alloc_buffer_and_set_caps (mux->srcpad, GST_BUFFER_OFFSET_NONE,
- 2, GST_PAD_CAPS (mux->srcpad), &footerbuf);
- if (ret != GST_FLOW_OK)
- goto alloc_failed;
-
- memcpy (GST_BUFFER_DATA (footerbuf), "\r\n", 2);
+ footerbuf = gst_buffer_new_allocate (NULL, 2, 1);
+ gst_buffer_fill (footerbuf, 0, "\r\n", 2);
/* the footer has the same timestamp as the data buffer and has a
* duration of 0 */
ret = GST_FLOW_NOT_NEGOTIATED;
goto beach;
}
-alloc_failed:
- {
- GST_WARNING_OBJECT (mux,
- "failed allocating a %" G_GSIZE_FORMAT " bytes buffer", headerlen);
- g_free (header);
- goto beach;
- }
}
static void