mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 10:11:08 +00:00
multipart: port to 0.11
This commit is contained in:
parent
caf1760694
commit
8926a8f753
3 changed files with 80 additions and 114 deletions
|
@ -126,23 +126,8 @@ static void gst_multipart_get_property (GObject * object, guint prop_id,
|
||||||
|
|
||||||
static void gst_multipart_demux_finalize (GObject * object);
|
static void gst_multipart_demux_finalize (GObject * object);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstMultipartDemux, gst_multipart_demux, GstElement,
|
#define gst_multipart_demux_parent_class parent_class
|
||||||
GST_TYPE_ELEMENT);
|
G_DEFINE_TYPE (GstMultipartDemux, gst_multipart_demux, 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>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_multipart_demux_class_init (GstMultipartDemuxClass * klass)
|
gst_multipart_demux_class_init (GstMultipartDemuxClass * klass)
|
||||||
|
@ -189,11 +174,19 @@ gst_multipart_demux_class_init (GstMultipartDemuxClass * klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
gstelement_class->change_state = gst_multipart_demux_change_state;
|
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
|
static void
|
||||||
gst_multipart_demux_init (GstMultipartDemux * multipart,
|
gst_multipart_demux_init (GstMultipartDemux * multipart)
|
||||||
GstMultipartDemuxClass * g_class)
|
|
||||||
{
|
{
|
||||||
/* create the sink pad */
|
/* create the sink pad */
|
||||||
multipart->sinkpad =
|
multipart->sinkpad =
|
||||||
|
@ -392,7 +385,7 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
guint8 *end, *next;
|
guint8 *end, *next;
|
||||||
|
|
||||||
datalen = gst_adapter_available (multipart->adapter);
|
datalen = gst_adapter_available (multipart->adapter);
|
||||||
data = gst_adapter_peek (multipart->adapter, datalen);
|
data = gst_adapter_map (multipart->adapter, datalen);
|
||||||
dataend = data + datalen;
|
dataend = data + datalen;
|
||||||
|
|
||||||
/* Skip leading whitespace, pos endposition should at least leave space for
|
/* Skip leading whitespace, pos endposition should at least leave space for
|
||||||
|
@ -400,9 +393,8 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
for (pos = (guint8 *) data; pos < dataend - 4 && g_ascii_isspace (*pos);
|
for (pos = (guint8 *) data; pos < dataend - 4 && g_ascii_isspace (*pos);
|
||||||
pos++);
|
pos++);
|
||||||
|
|
||||||
if (pos >= dataend - 4) {
|
if (pos >= dataend - 4)
|
||||||
return MULTIPART_NEED_MORE_DATA;
|
goto need_more_data;
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (pos[0] != '-' || pos[1] != '-')) {
|
if (G_UNLIKELY (pos[0] != '-' || pos[1] != '-')) {
|
||||||
GST_DEBUG_OBJECT (multipart, "No boundary available");
|
GST_DEBUG_OBJECT (multipart, "No boundary available");
|
||||||
|
@ -411,7 +403,7 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
|
|
||||||
/* First the boundary */
|
/* First the boundary */
|
||||||
if (!get_line_end (pos, dataend, &end, &next))
|
if (!get_line_end (pos, dataend, &end, &next))
|
||||||
return MULTIPART_NEED_MORE_DATA;
|
goto need_more_data;
|
||||||
|
|
||||||
/* Ignore the leading -- */
|
/* Ignore the leading -- */
|
||||||
boundary_len = end - pos - 2;
|
boundary_len = end - pos - 2;
|
||||||
|
@ -430,9 +422,9 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
* invalid */
|
* invalid */
|
||||||
if (G_UNLIKELY (boundary_len == multipart->boundary_len + 2 &&
|
if (G_UNLIKELY (boundary_len == multipart->boundary_len + 2 &&
|
||||||
!strncmp (boundary, multipart->boundary, multipart->boundary_len) &&
|
!strncmp (boundary, multipart->boundary, multipart->boundary_len) &&
|
||||||
!strncmp (boundary + multipart->boundary_len, "--", 2))) {
|
!strncmp (boundary + multipart->boundary_len, "--", 2)))
|
||||||
return MULTIPART_DATA_EOS;
|
goto eos;
|
||||||
}
|
|
||||||
GST_DEBUG_OBJECT (multipart,
|
GST_DEBUG_OBJECT (multipart,
|
||||||
"Boundary length doesn't match detected boundary (%d <> %d",
|
"Boundary length doesn't match detected boundary (%d <> %d",
|
||||||
boundary_len, multipart->boundary_len);
|
boundary_len, multipart->boundary_len);
|
||||||
|
@ -442,7 +434,6 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
goto wrong_header;
|
goto wrong_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pos = next;
|
pos = next;
|
||||||
while (get_line_end (pos, dataend, &end, &next)) {
|
while (get_line_end (pos, dataend, &end, &next)) {
|
||||||
guint len = end - pos;
|
guint len = end - pos;
|
||||||
|
@ -452,6 +443,7 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
GST_DEBUG_OBJECT (multipart,
|
GST_DEBUG_OBJECT (multipart,
|
||||||
"Parsed the header - boundary: %s, mime-type: %s, content-length: %d",
|
"Parsed the header - boundary: %s, mime-type: %s, content-length: %d",
|
||||||
multipart->boundary, multipart->mime_type, multipart->content_length);
|
multipart->boundary, multipart->mime_type, multipart->content_length);
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
return next - data;
|
return next - data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -471,15 +463,26 @@ multipart_parse_header (GstMultipartDemux * multipart)
|
||||||
}
|
}
|
||||||
pos = next;
|
pos = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
need_more_data:
|
||||||
GST_DEBUG_OBJECT (multipart, "Need more data for the header");
|
GST_DEBUG_OBJECT (multipart, "Need more data for the header");
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
|
|
||||||
return MULTIPART_NEED_MORE_DATA;
|
return MULTIPART_NEED_MORE_DATA;
|
||||||
|
|
||||||
wrong_header:
|
wrong_header:
|
||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (multipart, STREAM, DEMUX, (NULL),
|
GST_ELEMENT_ERROR (multipart, STREAM, DEMUX, (NULL),
|
||||||
("Boundary not found in the multipart header"));
|
("Boundary not found in the multipart header"));
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
return MULTIPART_DATA_ERROR;
|
return MULTIPART_DATA_ERROR;
|
||||||
}
|
}
|
||||||
|
eos:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (multipart, "we are EOS");
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
|
return MULTIPART_DATA_EOS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
|
@ -495,13 +498,15 @@ multipart_find_boundary (GstMultipartDemux * multipart, gint * datalen)
|
||||||
len = multipart->content_length;
|
len = multipart->content_length;
|
||||||
if (gst_adapter_available (multipart->adapter) >= len + 2) {
|
if (gst_adapter_available (multipart->adapter) >= len + 2) {
|
||||||
*datalen = len;
|
*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] contains \r then assume a newline is \r\n */
|
||||||
if (data[len] == '\r')
|
if (data[len] == '\r')
|
||||||
len += 2;
|
len += 2;
|
||||||
else if (data[len] == '\n')
|
else if (data[len] == '\n')
|
||||||
len += 1;
|
len += 1;
|
||||||
|
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
/* Don't check if boundary is actually there, but let the header parsing
|
/* Don't check if boundary is actually there, but let the header parsing
|
||||||
* bail out if it isn't */
|
* bail out if it isn't */
|
||||||
return len;
|
return len;
|
||||||
|
@ -514,7 +519,7 @@ multipart_find_boundary (GstMultipartDemux * multipart, gint * datalen)
|
||||||
len = gst_adapter_available (multipart->adapter);
|
len = gst_adapter_available (multipart->adapter);
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return MULTIPART_NEED_MORE_DATA;
|
return MULTIPART_NEED_MORE_DATA;
|
||||||
data = gst_adapter_peek (multipart->adapter, len);
|
data = gst_adapter_map (multipart->adapter, len);
|
||||||
dataend = data + len;
|
dataend = data + len;
|
||||||
|
|
||||||
for (pos = data + multipart->scanpos;
|
for (pos = data + multipart->scanpos;
|
||||||
|
@ -530,10 +535,12 @@ multipart_find_boundary (GstMultipartDemux * multipart, gint * datalen)
|
||||||
len -= 1;
|
len -= 1;
|
||||||
*datalen = len;
|
*datalen = len;
|
||||||
|
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
multipart->scanpos = 0;
|
multipart->scanpos = 0;
|
||||||
return pos - data;
|
return pos - data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
gst_adapter_unmap (multipart->adapter, 0);
|
||||||
multipart->scanpos = pos - data;
|
multipart->scanpos = pos - data;
|
||||||
return MULTIPART_NEED_MORE_DATA;
|
return MULTIPART_NEED_MORE_DATA;
|
||||||
}
|
}
|
||||||
|
@ -591,13 +598,14 @@ gst_multipart_demux_chain (GstPad * pad, GstBuffer * buf)
|
||||||
outbuf = gst_adapter_take_buffer (adapter, datalen);
|
outbuf = gst_adapter_take_buffer (adapter, datalen);
|
||||||
gst_adapter_flush (adapter, size - datalen);
|
gst_adapter_flush (adapter, size - datalen);
|
||||||
|
|
||||||
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (srcpad->pad));
|
|
||||||
if (created) {
|
if (created) {
|
||||||
GstTagList *tags;
|
GstTagList *tags;
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
/* Push new segment, first buffer has 0 timestamp */
|
/* Push new segment, first buffer has 0 timestamp */
|
||||||
gst_pad_push_event (srcpad->pad,
|
gst_pad_push_event (srcpad->pad, gst_event_new_segment (&segment));
|
||||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
|
|
||||||
|
|
||||||
tags =
|
tags =
|
||||||
gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "Multipart", NULL);
|
gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "Multipart", NULL);
|
||||||
|
@ -610,8 +618,6 @@ gst_multipart_demux_chain (GstPad * pad, GstBuffer * buf)
|
||||||
GST_DEBUG_OBJECT (multipart,
|
GST_DEBUG_OBJECT (multipart,
|
||||||
"pushing buffer with timestamp %" GST_TIME_FORMAT,
|
"pushing buffer with timestamp %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
|
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_pad_push (srcpad->pad, outbuf);
|
||||||
res = gst_multipart_combine_flows (multipart, srcpad, res);
|
res = gst_multipart_combine_flows (multipart, srcpad, res);
|
||||||
if (res != GST_FLOW_OK)
|
if (res != GST_FLOW_OK)
|
||||||
|
|
|
@ -75,16 +75,12 @@ static const MimeTypeMap mimetypes[] = {
|
||||||
{NULL, NULL}
|
{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 void gst_multipart_mux_finalize (GObject * object);
|
||||||
|
|
||||||
static gboolean gst_multipart_mux_handle_src_event (GstPad * pad,
|
static gboolean gst_multipart_mux_handle_src_event (GstPad * pad,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static GstPad *gst_multipart_mux_request_new_pad (GstElement * element,
|
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 *
|
static GstStateChangeReturn gst_multipart_mux_change_state (GstElement *
|
||||||
element, GstStateChange transition);
|
element, GstStateChange transition);
|
||||||
|
|
||||||
|
@ -96,46 +92,8 @@ static void gst_multipart_mux_set_property (GObject * object, guint prop_id,
|
||||||
static void gst_multipart_mux_get_property (GObject * object, guint prop_id,
|
static void gst_multipart_mux_get_property (GObject * object, guint prop_id,
|
||||||
GValue * value, GParamSpec * pspec);
|
GValue * value, GParamSpec * pspec);
|
||||||
|
|
||||||
static GstElementClass *parent_class = NULL;
|
#define gst_multipart_mux_parent_class parent_class
|
||||||
|
G_DEFINE_TYPE (GstMultipartMux, gst_multipart_mux, GST_TYPE_ELEMENT);
|
||||||
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>");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_multipart_mux_class_init (GstMultipartMuxClass * klass)
|
gst_multipart_mux_class_init (GstMultipartMuxClass * klass)
|
||||||
|
@ -160,6 +118,14 @@ gst_multipart_mux_class_init (GstMultipartMuxClass * klass)
|
||||||
gstelement_class->request_new_pad = gst_multipart_mux_request_new_pad;
|
gstelement_class->request_new_pad = gst_multipart_mux_request_new_pad;
|
||||||
gstelement_class->change_state = gst_multipart_mux_change_state;
|
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 */
|
/* populate mime types */
|
||||||
klass->mimetypes = g_hash_table_new (g_str_hash, g_str_equal);
|
klass->mimetypes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
for (i = 0; mimetypes[i].key; i++) {
|
for (i = 0; mimetypes[i].key; i++) {
|
||||||
|
@ -205,7 +171,7 @@ gst_multipart_mux_finalize (GObject * object)
|
||||||
|
|
||||||
static GstPad *
|
static GstPad *
|
||||||
gst_multipart_mux_request_new_pad (GstElement * element,
|
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;
|
GstMultipartMux *multipart_mux;
|
||||||
GstPad *newpad;
|
GstPad *newpad;
|
||||||
|
@ -232,6 +198,7 @@ gst_multipart_mux_request_new_pad (GstElement * element,
|
||||||
sizeof (GstMultipartPadData));
|
sizeof (GstMultipartPadData));
|
||||||
|
|
||||||
/* save a pointer to our data in the pad */
|
/* save a pointer to our data in the pad */
|
||||||
|
multipartpad->pad = newpad;
|
||||||
gst_pad_set_element_private (newpad, multipartpad);
|
gst_pad_set_element_private (newpad, multipartpad);
|
||||||
multipart_mux->numpads++;
|
multipart_mux->numpads++;
|
||||||
}
|
}
|
||||||
|
@ -430,6 +397,7 @@ gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
|
||||||
GstBuffer *footerbuf = NULL;
|
GstBuffer *footerbuf = NULL;
|
||||||
GstBuffer *databuf = NULL;
|
GstBuffer *databuf = NULL;
|
||||||
GstStructure *structure = NULL;
|
GstStructure *structure = NULL;
|
||||||
|
GstCaps *caps;
|
||||||
const gchar *mime;
|
const gchar *mime;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mux, "all pads are collected");
|
GST_DEBUG_OBJECT (mux, "all pads are collected");
|
||||||
|
@ -460,8 +428,8 @@ gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
|
||||||
|
|
||||||
/* see if we need to push a segment */
|
/* see if we need to push a segment */
|
||||||
if (mux->need_segment) {
|
if (mux->need_segment) {
|
||||||
GstEvent *event;
|
|
||||||
GstClockTime time;
|
GstClockTime time;
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
if (best->timestamp != -1)
|
if (best->timestamp != -1)
|
||||||
time = best->timestamp;
|
time = best->timestamp;
|
||||||
|
@ -470,32 +438,35 @@ gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
|
||||||
|
|
||||||
/* for the segment, we take the first timestamp we see, we don't know the
|
/* for the segment, we take the first timestamp we see, we don't know the
|
||||||
* length and the position is 0 */
|
* length and the position is 0 */
|
||||||
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
time, -1, 0);
|
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;
|
mux->need_segment = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
structure = gst_caps_get_structure (GST_BUFFER_CAPS (best->buffer), 0);
|
caps = gst_pad_get_current_caps (best->pad);
|
||||||
if (!structure)
|
if (caps == NULL)
|
||||||
goto no_caps;
|
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 */
|
/* get the mime type for the structure */
|
||||||
mime = gst_multipart_mux_get_mime (mux, structure);
|
mime = gst_multipart_mux_get_mime (mux, structure);
|
||||||
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
header = g_strdup_printf ("--%s\r\nContent-Type: %s\r\n"
|
header = g_strdup_printf ("--%s\r\nContent-Type: %s\r\n"
|
||||||
"Content-Length: %u\r\n\r\n",
|
"Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n",
|
||||||
mux->boundary, mime, GST_BUFFER_SIZE (best->buffer));
|
mux->boundary, mime, gst_buffer_get_size (best->buffer));
|
||||||
headerlen = strlen (header);
|
headerlen = strlen (header);
|
||||||
|
|
||||||
ret = gst_pad_alloc_buffer_and_set_caps (mux->srcpad, GST_BUFFER_OFFSET_NONE,
|
headerbuf = gst_buffer_new_allocate (NULL, headerlen, 1);
|
||||||
headerlen, GST_PAD_CAPS (mux->srcpad), &headerbuf);
|
gst_buffer_fill (headerbuf, 0, header, headerlen);
|
||||||
if (ret != GST_FLOW_OK)
|
|
||||||
goto alloc_failed;
|
|
||||||
|
|
||||||
memcpy (GST_BUFFER_DATA (headerbuf), header, headerlen);
|
|
||||||
g_free (header);
|
g_free (header);
|
||||||
|
|
||||||
/* the header has the same timestamp as the data buffer (which we will push
|
/* the header has the same timestamp as the data buffer (which we will push
|
||||||
|
@ -516,31 +487,26 @@ gst_multipart_mux_collected (GstCollectPads * pads, GstMultipartMux * mux)
|
||||||
|
|
||||||
/* take best->buffer, we don't need to unref it later as we will push it
|
/* take best->buffer, we don't need to unref it later as we will push it
|
||||||
* now. */
|
* now. */
|
||||||
databuf = gst_buffer_make_metadata_writable (best->buffer);
|
databuf = gst_buffer_make_writable (best->buffer);
|
||||||
best->buffer = NULL;
|
best->buffer = NULL;
|
||||||
|
|
||||||
gst_buffer_set_caps (databuf, GST_PAD_CAPS (mux->srcpad));
|
|
||||||
/* we need to updated the timestamp to match the running_time */
|
/* we need to updated the timestamp to match the running_time */
|
||||||
GST_BUFFER_TIMESTAMP (databuf) = best->timestamp;
|
GST_BUFFER_TIMESTAMP (databuf) = best->timestamp;
|
||||||
GST_BUFFER_OFFSET (databuf) = mux->offset;
|
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_OFFSET_END (databuf) = mux->offset;
|
||||||
GST_BUFFER_FLAG_SET (databuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
GST_BUFFER_FLAG_SET (databuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mux, "pushing %u bytes data buffer",
|
GST_DEBUG_OBJECT (mux, "pushing %" G_GSIZE_FORMAT " bytes data buffer",
|
||||||
GST_BUFFER_SIZE (databuf));
|
gst_buffer_get_size (databuf));
|
||||||
ret = gst_pad_push (mux->srcpad, databuf);
|
ret = gst_pad_push (mux->srcpad, databuf);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
/* push always takes ownership of the buffer, even after an error, so we
|
/* push always takes ownership of the buffer, even after an error, so we
|
||||||
* don't need to unref headerbuf here. */
|
* don't need to unref headerbuf here. */
|
||||||
goto beach;
|
goto beach;
|
||||||
|
|
||||||
ret = gst_pad_alloc_buffer_and_set_caps (mux->srcpad, GST_BUFFER_OFFSET_NONE,
|
footerbuf = gst_buffer_new_allocate (NULL, 2, 1);
|
||||||
2, GST_PAD_CAPS (mux->srcpad), &footerbuf);
|
gst_buffer_fill (footerbuf, 0, "\r\n", 2);
|
||||||
if (ret != GST_FLOW_OK)
|
|
||||||
goto alloc_failed;
|
|
||||||
|
|
||||||
memcpy (GST_BUFFER_DATA (footerbuf), "\r\n", 2);
|
|
||||||
|
|
||||||
/* the footer has the same timestamp as the data buffer and has a
|
/* the footer has the same timestamp as the data buffer and has a
|
||||||
* duration of 0 */
|
* duration of 0 */
|
||||||
|
@ -590,13 +556,6 @@ no_caps:
|
||||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
ret = GST_FLOW_NOT_NEGOTIATED;
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
alloc_failed:
|
|
||||||
{
|
|
||||||
GST_WARNING_OBJECT (mux,
|
|
||||||
"failed allocating a %" G_GSIZE_FORMAT " bytes buffer", headerlen);
|
|
||||||
g_free (header);
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -47,6 +47,7 @@ typedef struct
|
||||||
GstBuffer *buffer; /* the queued buffer for this pad */
|
GstBuffer *buffer; /* the queued buffer for this pad */
|
||||||
GstClockTime timestamp; /* its timestamp, converted to running_time so that we can
|
GstClockTime timestamp; /* its timestamp, converted to running_time so that we can
|
||||||
correctly sort over multiple segments. */
|
correctly sort over multiple segments. */
|
||||||
|
GstPad *pad;
|
||||||
}
|
}
|
||||||
GstMultipartPadData;
|
GstMultipartPadData;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue