From 6abe2134bf64855e9c7b31ef7afef83a276f83e8 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 12 Oct 2011 18:05:07 +0200 Subject: [PATCH] tsdemux/tsparse: Port to 0.11 This is a naive port that somewhat works but is inefficient. I need to rethink how to make the best out of GstMemory/GstBuffer --- configure.ac | 2 +- gst/mpegtsdemux/mpegtsbase.c | 115 ++++++++-------- gst/mpegtsdemux/mpegtspacketizer.c | 205 ++++++++++++++++++----------- gst/mpegtsdemux/mpegtspacketizer.h | 10 +- gst/mpegtsdemux/mpegtsparse.c | 43 +++--- gst/mpegtsdemux/tsdemux.c | 171 ++++++++++++------------ gst/mpegtsdemux/tsdemux.h | 1 + 7 files changed, 309 insertions(+), 238 deletions(-) diff --git a/configure.ac b/configure.ac index 0e1d608cd9..a08a7e8b32 100644 --- a/configure.ac +++ b/configure.ac @@ -298,7 +298,7 @@ GST_PLUGINS_NONPORTED=" adpcmdec adpcmenc aiff asfmux \ dccp debugutils dtmf faceoverlay festival \ fieldanalysis freeze frei0r gaudieffects geometrictransform h264parse \ hdvparse hls id3tag inter interlace ivfparse jpegformat jp2kdecimator \ - liveadder legacyresample librfb mpegdemux mpegtsdemux mpegtsmux \ + liveadder legacyresample librfb mpegdemux mpegtsmux \ mpegpsmux mpegvideoparse mve mxf nsf nuvdemux \ patchdetect pcapparse pnm rawparse real removesilence rtpmux rtpvp8 scaletempo \ sdi segmentclip siren speed subenc stereo tta videofilters \ diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 437af9d785..1976ee5c1e 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -84,15 +84,26 @@ static GstFlowReturn mpegts_base_chain (GstPad * pad, GstBuffer * buf); static gboolean mpegts_base_sink_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn mpegts_base_change_state (GstElement * element, GstStateChange transition); -static void _extra_init (GType type); + static void mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info); static void mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info); -GST_BOILERPLATE_FULL (MpegTSBase, mpegts_base, GstElement, GST_TYPE_ELEMENT, - _extra_init); +static void +_extra_init (void) +{ + QUARK_PROGRAMS = g_quark_from_string ("programs"); + QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number"); + QUARK_PID = g_quark_from_string ("pid"); + QUARK_PCR_PID = g_quark_from_string ("pcr-pid"); + QUARK_STREAMS = g_quark_from_string ("streams"); + QUARK_STREAM_TYPE = g_quark_from_string ("stream-type"); +} +#define mpegts_base_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (MpegTSBase, mpegts_base, GST_TYPE_ELEMENT, + _extra_init ()); static const guint32 crc_tab[256] = { 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, @@ -153,26 +164,6 @@ mpegts_base_calc_crc32 (guint8 * data, guint datalen) return crc; } -static void -_extra_init (GType type) -{ - QUARK_PROGRAMS = g_quark_from_string ("programs"); - QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number"); - QUARK_PID = g_quark_from_string ("pid"); - QUARK_PCR_PID = g_quark_from_string ("pcr-pid"); - QUARK_STREAMS = g_quark_from_string ("streams"); - QUARK_STREAM_TYPE = g_quark_from_string ("stream-type"); -} - -static void -mpegts_base_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); -} - static void mpegts_base_class_init (MpegTSBaseClass * klass) { @@ -181,13 +172,14 @@ mpegts_base_class_init (MpegTSBaseClass * klass) element_class = GST_ELEMENT_CLASS (klass); element_class->change_state = mpegts_base_change_state; + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = mpegts_base_set_property; gobject_class->get_property = mpegts_base_get_property; gobject_class->dispose = mpegts_base_dispose; gobject_class->finalize = mpegts_base_finalize; - } static void @@ -227,7 +219,7 @@ mpegts_base_reset (MpegTSBase * base) } static void -mpegts_base_init (MpegTSBase * base, MpegTSBaseClass * klass) +mpegts_base_init (MpegTSBase * base) { base->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); gst_pad_set_activate_function (base->sinkpad, mpegts_base_sink_activate); @@ -956,11 +948,16 @@ mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section) /* table ids 0x70 - 0x73 do not have a crc */ if (G_LIKELY (section->table_id < 0x70 || section->table_id > 0x73)) { - if (G_UNLIKELY (mpegts_base_calc_crc32 (GST_BUFFER_DATA (section->buffer), - GST_BUFFER_SIZE (section->buffer)) != 0)) { + gpointer data; + gsize size; + + data = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); + if (G_UNLIKELY (mpegts_base_calc_crc32 (data, size) != 0)) { + gst_buffer_unmap (section->buffer, data, size); GST_WARNING_OBJECT (base, "bad crc in psi pid 0x%x", section->pid); return FALSE; } + gst_buffer_unmap (section->buffer, data, size); } switch (section->table_id) { @@ -1180,24 +1177,12 @@ mpegts_base_sink_event (GstPad * pad, GstEvent * event) gst_event_type_get_name (GST_EVENT_TYPE (event))); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: { - gboolean update; - gdouble rate, applied_rate; - GstFormat format; - gint64 start, stop, position; + gst_event_copy_segment (event, &base->segment); - gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, - &format, &start, &stop, &position); - GST_DEBUG_OBJECT (base, - "Segment update:%d, rate:%f, applied_rate:%f, format:%s", update, - rate, applied_rate, gst_format_get_name (format)); - GST_DEBUG_OBJECT (base, - " start:%" G_GINT64_FORMAT ", stop:%" G_GINT64_FORMAT - ", position:%" G_GINT64_FORMAT, start, stop, position); - gst_segment_set_newsegment_full (&base->segment, update, rate, - applied_rate, format, start, stop, position); gst_event_unref (event); + base->in_gap = GST_CLOCK_TIME_NONE; base->first_buf_ts = GST_CLOCK_TIME_NONE; } @@ -1268,10 +1253,14 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) /* bad header, skip the packet */ goto next; + GST_DEBUG ("Got packet (buffer:%p)", packet.buffer); + /* base PSI data */ if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) { MpegTSPacketizerSection section; + based = mpegts_packetizer_push_section (packetizer, &packet, §ion); + if (G_UNLIKELY (!based)) /* bad section data */ goto next; @@ -1279,6 +1268,8 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) if (G_LIKELY (section.complete)) { /* section complete */ based = mpegts_base_handle_psi (base, §ion); + + GST_DEBUG ("Unreffing section buffer %p", section.buffer); gst_buffer_unref (section.buffer); if (G_UNLIKELY (!based)) @@ -1287,7 +1278,6 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) } /* we need to push section packet downstream */ res = mpegts_base_push (base, &packet, §ion); - } else if (MPEGTS_BIT_IS_SET (base->is_pes, packet.pid)) { /* push the packet downstream */ res = mpegts_base_push (base, &packet, NULL); @@ -1349,6 +1339,7 @@ mpegts_base_scan (MpegTSBase * base) ret = GST_FLOW_ERROR; beach: + GST_DEBUG ("Returning %s", gst_flow_get_name (ret)); mpegts_packetizer_clear (base->packetizer); return ret; @@ -1382,7 +1373,7 @@ mpegts_base_loop (MpegTSBase * base) 100 * base->packetsize, &buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto error; - base->seek_offset += GST_BUFFER_SIZE (buf); + base->seek_offset += gst_buffer_get_size (buf); ret = mpegts_base_chain (base->sinkpad, buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto error; @@ -1398,6 +1389,7 @@ mpegts_base_loop (MpegTSBase * base) error: { const gchar *reason = gst_flow_get_name (ret); + GST_DEBUG_OBJECT (base, "Pausing task, reason %s", reason); if (ret == GST_FLOW_UNEXPECTED) GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, gst_event_new_eos ()); @@ -1477,7 +1469,7 @@ mpegts_base_handle_seek_event (MpegTSBase * base, GstPad * pad, if (flush) { /* send a FLUSH_STOP for the sinkpad, since we need data for seeking */ GST_DEBUG_OBJECT (base, "sending flush stop"); - gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop ()); + gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop (TRUE)); } if (flags & (GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_SKIP)) { @@ -1505,7 +1497,7 @@ mpegts_base_handle_seek_event (MpegTSBase * base, GstPad * pad, GST_DEBUG_OBJECT (base, "sending flush stop"); //gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop ()); GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, - gst_event_new_flush_stop ()); + gst_event_new_flush_stop (TRUE)); } //else done: @@ -1517,14 +1509,31 @@ push_mode: static gboolean -mpegts_base_sink_activate (GstPad * pad) +mpegts_base_sink_activate (GstPad * sinkpad) { - if (gst_pad_check_pull_range (pad)) { - GST_DEBUG_OBJECT (pad, "activating pull"); - return gst_pad_activate_pull (pad, TRUE); - } else { - GST_DEBUG_OBJECT (pad, "activating push"); - return gst_pad_activate_push (pad, TRUE); + GstQuery *query; + gboolean pull_mode; + + query = gst_query_new_scheduling (); + + if (!gst_pad_peer_query (sinkpad, query)) { + gst_query_unref (query); + goto activate_push; + } + + gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL); + gst_query_unref (query); + + if (!pull_mode) + goto activate_push; + + GST_DEBUG_OBJECT (sinkpad, "activating pull"); + return gst_pad_activate_pull (sinkpad, TRUE); + +activate_push: + { + GST_DEBUG_OBJECT (sinkpad, "activating push"); + return gst_pad_activate_push (sinkpad, TRUE); } } diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 25d75cfa84..c005328411 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -287,6 +287,8 @@ mpegts_packetizer_parse_packet (MpegTSPacketizer2 * packetizer, packet->data = data; + gst_buffer_unmap (packet->buffer, packet->bufdata, packet->bufsize); + if (packet->adaptation_field_control & 0x02) if (!mpegts_packetizer_parse_adaptation_field_control (packetizer, packet)) return FALSE; @@ -304,15 +306,17 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, MpegTSPacketizerStream * stream, MpegTSPacketizerSection * section) { guint8 tmp; - guint8 *data, *crc_data; + guint8 *bufdata, *data, *crc_data; + gsize size; MpegTSPacketizerStreamSubtable *subtable; GSList *subtable_list = NULL; section->complete = TRUE; + /* get the section buffer, pass the ownership to the caller */ section->buffer = gst_adapter_take_buffer (stream->section_adapter, 3 + stream->section_length); - data = GST_BUFFER_DATA (section->buffer); + bufdata = data = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); GST_BUFFER_OFFSET (section->buffer) = stream->offset; section->table_id = *data++; @@ -348,8 +352,7 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, goto not_applicable; /* CRC is at the end of the section */ - crc_data = - GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer) - 4; + crc_data = bufdata + size - 4; section->crc = GST_READ_UINT32_BE (crc_data); if (section->version_number == subtable->version_number && @@ -360,6 +363,8 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, subtable->crc = section->crc; stream->section_table_id = section->table_id; + gst_buffer_unmap (section->buffer, bufdata, size); + return TRUE; not_applicable: @@ -368,6 +373,7 @@ not_applicable: section->pid, section->table_id, section->subtable_extension, section->current_next_indicator, section->version_number, section->crc); section->complete = FALSE; + gst_buffer_unmap (section->buffer, bufdata, size); gst_buffer_unref (section->buffer); return TRUE; } @@ -421,7 +427,8 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *pat_info = NULL; - guint8 *data, *end; + guint8 *bufdata, *data, *end; + gsize size; guint transport_stream_id; guint8 tmp; guint program_number; @@ -431,7 +438,7 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, GstStructure *entry = NULL; gchar *struct_name; - data = GST_BUFFER_DATA (section->buffer); + bufdata = data = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -450,8 +457,10 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, pat_info = gst_structure_id_new (QUARK_PAT, QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, NULL); g_value_init (&entries, GST_TYPE_LIST); + /* stop at the CRC */ - end = GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer); + end = bufdata + size; + while (data < end - 4) { program_number = GST_READ_UINT16_BE (data); data += 2; @@ -474,6 +483,8 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, gst_structure_id_set_value (pat_info, QUARK_PROGRAMS, &entries); g_value_unset (&entries); + gst_buffer_unmap (section->buffer, bufdata, size); + if (data != end - 4) { /* FIXME: check the CRC before parsing the packet */ GST_ERROR ("at the end of PAT data != end - 4"); @@ -490,7 +501,8 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *pmt = NULL; - guint8 *data, *end; + guint8 *bufdata, *data, *end; + gsize size; guint16 program_number; guint8 tmp; guint pcr_pid; @@ -504,15 +516,16 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, GstStructure *stream_info = NULL; gchar *struct_name; + data = bufdata = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 16) { + if (size < 16) { GST_WARNING ("PID %d invalid PMT size %d", section->pid, section->section_length); goto error; } - data = GST_BUFFER_DATA (section->buffer); - end = data + GST_BUFFER_SIZE (section->buffer); + end = data + size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -682,6 +695,8 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, gst_structure_id_set_value (pmt, QUARK_STREAMS, &programs); g_value_unset (&programs); + gst_buffer_unmap (section->buffer, bufdata, size); + g_assert (data == end - 4); return pmt; @@ -689,6 +704,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, error: if (pmt) gst_structure_free (pmt); + gst_buffer_unmap (section->buffer, bufdata, size); return NULL; } @@ -698,7 +714,8 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *nit = NULL, *transport = NULL, *delivery_structure = NULL; - guint8 *data, *end, *entry_begin; + guint8 *bufdata, *data, *end, *entry_begin; + gsize size; guint16 network_id, transport_stream_id, original_network_id; guint tmp; guint16 descriptors_loop_length, transport_stream_loop_length; @@ -707,15 +724,17 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, GValueArray *descriptors = NULL; GST_DEBUG ("NIT"); + + data = bufdata = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 23) { + if (size < 23) { GST_WARNING ("PID %d invalid NIT size %d", section->pid, section->section_length); goto error; } - data = GST_BUFFER_DATA (section->buffer); - end = data + GST_BUFFER_SIZE (section->buffer); + end = data + size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -1304,14 +1323,15 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, if (data != end - 4) { GST_WARNING ("PID %d invalid NIT parsed %d length %d", - section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)), - GST_BUFFER_SIZE (section->buffer)); + section->pid, (gint) (data - bufdata), size); goto error; } gst_structure_id_set_value (nit, QUARK_TRANSPORTS, &transports); g_value_unset (&transports); + gst_buffer_unmap (section->buffer, bufdata, size); + GST_DEBUG ("NIT %" GST_PTR_FORMAT, nit); return nit; @@ -1320,6 +1340,8 @@ error: if (nit) gst_structure_free (nit); + gst_buffer_unmap (section->buffer, bufdata, size); + if (GST_VALUE_HOLDS_LIST (&transports)) g_value_unset (&transports); @@ -1331,7 +1353,8 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *sdt = NULL, *service = NULL; - guint8 *data, *end, *entry_begin; + guint8 *data, *bufdata, *end, *entry_begin; + gsize size; guint16 transport_stream_id, original_network_id, service_id; guint tmp; guint sdt_info_length; @@ -1343,15 +1366,17 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, GValue service_value = { 0 }; GST_DEBUG ("SDT"); + + data = bufdata = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 14) { + if (size < 14) { GST_WARNING ("PID %d invalid SDT size %d", section->pid, section->section_length); goto error; } - data = GST_BUFFER_DATA (section->buffer); - end = data + GST_BUFFER_SIZE (section->buffer); + end = data + size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -1509,20 +1534,23 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, if (data != end - 4) { GST_WARNING ("PID %d invalid SDT parsed %d length %d", - section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)), - GST_BUFFER_SIZE (section->buffer)); + section->pid, (gint) (data - bufdata), size); goto error; } gst_structure_id_set_value (sdt, QUARK_SERVICES, &services); g_value_unset (&services); + gst_buffer_unmap (section->buffer, bufdata, size); + return sdt; error: if (sdt) gst_structure_free (sdt); + gst_buffer_unmap (section->buffer, bufdata, size); + if (GST_VALUE_HOLDS_LIST (&services)) g_value_unset (&services); @@ -1541,7 +1569,8 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, guint16 mjd; guint year, month, day, hour, minute, second; guint duration; - guint8 *data, *end, *duration_ptr, *utc_ptr; + guint8 *data, *bufdata, *end, *duration_ptr, *utc_ptr; + gsize size; guint16 descriptors_loop_length; GValue events = { 0 }; GValue event_value = { 0 }; @@ -1549,15 +1578,16 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, gchar *event_name; guint tmp; + data = bufdata = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 18) { + if (size < 18) { GST_WARNING ("PID %d invalid EIT size %d", section->pid, section->section_length); goto error; } - data = GST_BUFFER_DATA (section->buffer); - end = data + GST_BUFFER_SIZE (section->buffer); + end = data + size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -1968,14 +1998,15 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, if (data != end - 4) { GST_WARNING ("PID %d invalid EIT parsed %d length %d", - section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)), - GST_BUFFER_SIZE (section->buffer)); + section->pid, (gint) (data - bufdata), size); goto error; } gst_structure_id_set_value (eit, QUARK_EVENTS, &events); g_value_unset (&events); + gst_buffer_unmap (section->buffer, bufdata, size); + GST_DEBUG ("EIT %" GST_PTR_FORMAT, eit); return eit; @@ -1984,6 +2015,8 @@ error: if (eit) gst_structure_free (eit); + gst_buffer_unmap (section->buffer, bufdata, size); + if (GST_VALUE_HOLDS_LIST (&events)) g_value_unset (&events); @@ -1997,18 +2030,21 @@ mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer, GstStructure *tdt = NULL; guint16 mjd; guint year, month, day, hour, minute, second; - guint8 *data, *end, *utc_ptr; + guint8 *data, *bufdata, *end, *utc_ptr; + gsize size; GST_DEBUG ("TDT"); + + data = bufdata = gst_buffer_map (section->buffer, &size, 0, GST_MAP_READ); + /* length always 8 */ - if (G_UNLIKELY (GST_BUFFER_SIZE (section->buffer) != 8)) { + if (G_UNLIKELY (size != 8)) { GST_WARNING ("PID %d invalid TDT size %d", section->pid, section->section_length); goto error; } - data = GST_BUFFER_DATA (section->buffer); - end = data + GST_BUFFER_SIZE (section->buffer); + end = data + size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -2049,12 +2085,16 @@ mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer, "hour", G_TYPE_UINT, hour, "minute", G_TYPE_UINT, minute, "second", G_TYPE_UINT, second, NULL); + gst_buffer_unmap (section->buffer, bufdata, size); + return tdt; error: if (tdt) gst_structure_free (tdt); + gst_buffer_unmap (section->buffer, bufdata, size); + return NULL; } @@ -2133,7 +2173,7 @@ mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer) } GST_DEBUG ("Pushing %u byte from offset %" G_GUINT64_FORMAT, - GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); + gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer)); gst_adapter_push (packetizer->adapter, buffer); } @@ -2227,77 +2267,87 @@ mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer, packet->buffer = NULL; + /* Resync if needed */ if (G_UNLIKELY (!packetizer->know_packet_size)) { if (!mpegts_try_discover_packet_size (packetizer)) return PACKET_NEED_MORE; } while ((avail = packetizer->adapter->size) >= packetizer->packet_size) { + guint i; + GstBuffer *tmpbuf; + guint8 *bufdata; + packet->buffer = gst_adapter_take_buffer (packetizer->adapter, packetizer->packet_size); + + bufdata = packet->bufdata = packet->data_start = + gst_buffer_map (packet->buffer, &packet->bufsize, 0, GST_MAP_READ); + /* M2TS packets don't start with the sync byte, all other variants do */ - if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) { - packet->data_start = GST_BUFFER_DATA (packet->buffer) + 4; - } else { - packet->data_start = GST_BUFFER_DATA (packet->buffer); - } + if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) + packet->data_start += 4; + /* ALL mpeg-ts variants contain 188 bytes of data. Those with bigger packet * sizes contain either extra data (timesync, FEC, ..) either before or after * the data */ packet->data_end = packet->data_start + 188; GST_BUFFER_OFFSET (packet->buffer) = packet->offset = packetizer->offset; GST_DEBUG ("offset %" G_GUINT64_FORMAT, packet->offset); + packetizer->offset += packetizer->packet_size; - GST_MEMDUMP ("buffer", GST_BUFFER_DATA (packet->buffer), 16); + GST_MEMDUMP ("buffer", bufdata, 16); GST_MEMDUMP ("data_start", packet->data_start, 16); /* Check sync byte */ - if (G_UNLIKELY (packet->data_start[0] != 0x47)) { - guint i; - GstBuffer *tmpbuf; + if (G_LIKELY (packet->data_start[0] == 0x47)) + goto got_valid_packet; - GST_LOG ("Lost sync %d", packetizer->packet_size); - /* Find the 0x47 in the buffer */ - for (i = 0; i < packetizer->packet_size; i++) - if (GST_BUFFER_DATA (packet->buffer)[i] == 0x47) - break; - if (G_UNLIKELY (i == packetizer->packet_size)) { - GST_ERROR ("REALLY lost the sync"); - gst_buffer_unref (packet->buffer); - goto done; - } + GST_LOG ("Lost sync %d", packetizer->packet_size); - if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) { - if (i >= 4) - i -= 4; - else - i += 188; - } + /* Find the 0x47 in the buffer */ + for (i = 0; i < packetizer->packet_size; i++) + if (bufdata[i] == 0x47) + break; - /* Pop out the remaining data... */ - GST_BUFFER_DATA (packet->buffer) += i; - GST_BUFFER_SIZE (packet->buffer) -= i; - GST_BUFFER_OFFSET (packet->buffer) += i; - tmpbuf = - gst_adapter_take_buffer (packetizer->adapter, - packetizer->adapter->size); - /* ... and push everything back in */ - gst_adapter_push (packetizer->adapter, packet->buffer); - gst_adapter_push (packetizer->adapter, tmpbuf); - continue; + if (G_UNLIKELY (i == packetizer->packet_size)) { + GST_ERROR ("REALLY lost the sync"); + gst_buffer_unmap (packet->buffer, bufdata, packet->bufsize); + gst_buffer_unref (packet->buffer); + goto done; } - return mpegts_packetizer_parse_packet (packetizer, packet); + if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) { + if (i >= 4) + i -= 4; + else + i += 188; + } + + /* Pop out the remaining data... */ + gst_buffer_resize (packet->buffer, i, packet->bufsize - i); + GST_BUFFER_OFFSET (packet->buffer) += i; + tmpbuf = + gst_adapter_take_buffer (packetizer->adapter, + packetizer->adapter->size); + /* ... and push everything back in */ + gst_adapter_push (packetizer->adapter, packet->buffer); + gst_adapter_push (packetizer->adapter, tmpbuf); } done: return PACKET_NEED_MORE; + +got_valid_packet: + return mpegts_packetizer_parse_packet (packetizer, packet); } void mpegts_packetizer_clear_packet (MpegTSPacketizer2 * packetizer, MpegTSPacketizerPacket * packet) { + GST_DEBUG ("packet:%p, buffer:%p", packet, packet->buffer); + memset (packet, 0, sizeof (MpegTSPacketizerPacket)); } @@ -2332,8 +2382,9 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, if (packet->pid == 0x14) { table_id = data[0]; section->section_length = GST_READ_UINT24_BE (data) & 0x000FFF; - section->buffer = gst_buffer_create_sub (packet->buffer, - data - GST_BUFFER_DATA (packet->buffer), section->section_length + 3); + section->buffer = + gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL, + data - packet->bufdata, section->section_length + 3); section->table_id = table_id; section->complete = TRUE; res = TRUE; @@ -2344,8 +2395,8 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, /* create a sub buffer from the start of the section (table_id and * section_length included) to the end */ - sub_buf = gst_buffer_create_sub (packet->buffer, - data - GST_BUFFER_DATA (packet->buffer), packet->data_end - data); + sub_buf = gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL, + data - packet->bufdata, packet->data_end - data); stream = packetizer->streams[packet->pid]; @@ -2372,8 +2423,8 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, ("PID %d table_id %d sub_table_extension %d payload_unit_start_indicator set but section " "not complete (last_continuity: %d continuity: %d sec len %d buffer %d avail %d", packet->pid, table_id, subtable_extension, stream->continuity_counter, - packet->continuity_counter, section_length, GST_BUFFER_SIZE (sub_buf), - stream->section_adapter->size); + packet->continuity_counter, section_length, + gst_buffer_get_size (sub_buf), stream->section_adapter->size); mpegts_packetizer_clear_section (packetizer, stream); } else { GST_DEBUG diff --git a/gst/mpegtsdemux/mpegtspacketizer.h b/gst/mpegtsdemux/mpegtspacketizer.h index 832862577d..d70a101047 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.h +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -94,9 +94,13 @@ typedef struct guint8 continuity_counter; guint8 *payload; - guint8 *data_start; + /* temporary copies of gst_buffer_map */ + guint8 *bufdata; + gsize bufsize; + + guint8 *data_start; /* Location of 0x47 marker byte */ guint8 *data_end; - guint8 *data; + guint8 *data; /* Location of post-TS-header data */ guint8 afc_flags; guint64 pcr; @@ -144,7 +148,7 @@ gboolean mpegts_packetizer_has_packets (MpegTSPacketizer2 *packetizer); MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *packetizer, MpegTSPacketizerPacket *packet); void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetizer, - MpegTSPacketizerPacket *packet); + MpegTSPacketizerPacket *packet); void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer, gint16 pid); diff --git a/gst/mpegtsdemux/mpegtsparse.c b/gst/mpegtsdemux/mpegtsparse.c index ede74ae827..7bd9d5cdaf 100644 --- a/gst/mpegtsdemux/mpegtsparse.c +++ b/gst/mpegtsdemux/mpegtsparse.c @@ -113,29 +113,13 @@ static void mpegts_parse_reset_selected_programs (MpegTSParse2 * parse, static void mpegts_parse_pad_removed (GstElement * element, GstPad * pad); static GstPad *mpegts_parse_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name); + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); static void mpegts_parse_release_pad (GstElement * element, GstPad * pad); static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query); static gboolean push_event (MpegTSBase * base, GstEvent * event); -GST_BOILERPLATE (MpegTSParse2, mpegts_parse, MpegTSBase, GST_TYPE_MPEGTS_BASE); - -static void -mpegts_parse_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&program_template)); - - gst_element_class_set_details_simple (element_class, - "MPEG transport stream parser", "Codec/Parser", - "Parses MPEG2 transport streams", - "Alessandro Decina , " - "Zaheer Abbas Merali "); -} +#define mpegts_parse_parent_class parent_class +G_DEFINE_TYPE (MpegTSParse2, mpegts_parse, GST_TYPE_MPEGTS_BASE); static void mpegts_parse_class_init (MpegTSParse2Class * klass) @@ -149,6 +133,17 @@ mpegts_parse_class_init (MpegTSParse2Class * klass) element_class->request_new_pad = mpegts_parse_request_new_pad; element_class->release_pad = mpegts_parse_release_pad; + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&program_template)); + + gst_element_class_set_details_simple (element_class, + "MPEG transport stream parser", "Codec/Parser", + "Parses MPEG2 transport streams", + "Alessandro Decina , " + "Zaheer Abbas Merali "); + gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = mpegts_parse_set_property; gobject_class->get_property = mpegts_parse_get_property; @@ -168,7 +163,7 @@ mpegts_parse_class_init (MpegTSParse2Class * klass) } static void -mpegts_parse_init (MpegTSParse2 * parse, MpegTSParse2Class * klass) +mpegts_parse_init (MpegTSParse2 * parse) { parse->need_sync_program_pads = FALSE; parse->program_numbers = g_strdup (""); @@ -429,7 +424,7 @@ mpegts_parse_pad_removed (GstElement * element, GstPad * pad) static GstPad * mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template, - const gchar * unused) + const gchar * unused, const GstCaps * caps) { MpegTSParse2 *parse; gchar *name; @@ -564,9 +559,15 @@ mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, mpegts_parse_sync_program_pads (parse); pid = packet->pid; + +#if 0 buffer = gst_buffer_make_metadata_writable (packet->buffer); + /* we have the same caps on all the src pads */ gst_buffer_set_caps (buffer, base->packetizer->caps); +#else + buffer = packet->buffer; +#endif GST_OBJECT_LOCK (parse); /* clear tspad->pushed on pads */ diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index 3facd64073..00f0a24005 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -109,7 +109,6 @@ struct _TSDemuxStream /* Current data to be pushed out */ GstBufferList *current; - GstBufferListIterator *currentit; GList *currentlist; /* Current PTS for this stream */ @@ -126,7 +125,7 @@ struct _TSDemuxStream "video/x-dirac;" \ "video/x-wmv," \ "wmvversion = (int) 3, " \ - "format = (fourcc) WVC1" \ + "format = (string) WVC1" \ ) #define AUDIO_CAPS \ @@ -217,13 +216,9 @@ static GstFlowReturn gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream); static gboolean push_event (MpegTSBase * base, GstEvent * event); -static void _extra_init (GType type); - -GST_BOILERPLATE_FULL (GstTSDemux, gst_ts_demux, MpegTSBase, - GST_TYPE_MPEGTS_BASE, _extra_init); static void -_extra_init (GType type) +_extra_init (void) { QUARK_TSDEMUX = g_quark_from_string ("tsdemux"); QUARK_PID = g_quark_from_string ("pid"); @@ -234,32 +229,15 @@ _extra_init (GType type) QUARK_OFFSET = g_quark_from_string ("offset"); } -static void -gst_ts_demux_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&video_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&audio_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&subpicture_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&private_template)); - - gst_element_class_set_details_simple (element_class, - "MPEG transport stream demuxer", - "Codec/Demuxer", - "Demuxes MPEG2 transport streams", - "Zaheer Abbas Merali \n" - "Edward Hervey "); -} +#define gst_ts_demux_parent_class parent_class +G_DEFINE_TYPE_WITH_CODE (GstTSDemux, gst_ts_demux, GST_TYPE_MPEGTS_BASE, + _extra_init ()); static void gst_ts_demux_class_init (GstTSDemuxClass * klass) { GObjectClass *gobject_class; + GstElementClass *element_class; MpegTSBaseClass *ts_class; gobject_class = G_OBJECT_CLASS (klass); @@ -277,6 +255,22 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass) "Emit messages for every pcr/opcr/pts/dts", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + element_class = GST_ELEMENT_CLASS (klass); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&video_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&audio_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&subpicture_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&private_template)); + + gst_element_class_set_details_simple (element_class, + "MPEG transport stream demuxer", + "Codec/Demuxer", + "Demuxes MPEG2 transport streams", + "Zaheer Abbas Merali \n" + "Edward Hervey "); ts_class = GST_MPEGTS_BASE_CLASS (klass); ts_class->reset = GST_DEBUG_FUNCPTR (gst_ts_demux_reset); @@ -291,7 +285,7 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass) } static void -gst_ts_demux_init (GstTSDemux * demux, GstTSDemuxClass * klass) +gst_ts_demux_init (GstTSDemux * demux) { demux->need_newsegment = TRUE; demux->program_number = -1; @@ -615,8 +609,7 @@ gst_ts_demux_perform_seek (MpegTSBase * base, GstSegment * segment, guint16 pid) max_loop_cnt = (segment->flags & GST_SEEK_FLAG_ACCURATE) ? 25 : 10; seektime = - MAX (0, - segment->last_stop - SEEK_TIMESTAMP_OFFSET) + demux->first_pcr.gsttime; + MAX (0, segment->stop - SEEK_TIMESTAMP_OFFSET) + demux->first_pcr.gsttime; seekpcroffset.gsttime = seektime; GST_DEBUG ("seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (seektime)); @@ -789,7 +782,9 @@ gst_ts_demux_perform_seek (MpegTSBase * base, GstSegment * segment, guint16 pid) seektime -= demux->first_pcr.gsttime; +#if 0 segment->last_stop = seektime; +#endif segment->time = seektime; /* we stop at the end */ @@ -838,24 +833,21 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event, guint16 pid) /* copy segment, we need this because we still need the old * segment when we close the current segment. */ memcpy (&seeksegment, &demux->segment, sizeof (GstSegment)); + /* configure the segment with the seek variables */ GST_DEBUG_OBJECT (demux, "configuring seek"); GST_DEBUG ("seeksegment: start: %" GST_TIME_FORMAT " stop: %" - GST_TIME_FORMAT " time: %" GST_TIME_FORMAT " accum: %" GST_TIME_FORMAT - " last_stop: %" GST_TIME_FORMAT " duration: %" GST_TIME_FORMAT, + GST_TIME_FORMAT " time: %" GST_TIME_FORMAT + " duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (seeksegment.stop), - GST_TIME_ARGS (seeksegment.time), GST_TIME_ARGS (seeksegment.accum), - GST_TIME_ARGS (seeksegment.last_stop), - GST_TIME_ARGS (seeksegment.duration)); - gst_segment_set_seek (&seeksegment, rate, format, flags, start_type, start, + GST_TIME_ARGS (seeksegment.time), GST_TIME_ARGS (seeksegment.duration)); + gst_segment_do_seek (&seeksegment, rate, format, flags, start_type, start, stop_type, stop, &update); GST_DEBUG ("seeksegment: start: %" GST_TIME_FORMAT " stop: %" - GST_TIME_FORMAT " time: %" GST_TIME_FORMAT " accum: %" GST_TIME_FORMAT - " last_stop: %" GST_TIME_FORMAT " duration: %" GST_TIME_FORMAT, + GST_TIME_FORMAT " time: %" GST_TIME_FORMAT + " duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (seeksegment.stop), - GST_TIME_ARGS (seeksegment.time), GST_TIME_ARGS (seeksegment.accum), - GST_TIME_ARGS (seeksegment.last_stop), - GST_TIME_ARGS (seeksegment.duration)); + GST_TIME_ARGS (seeksegment.time), GST_TIME_ARGS (seeksegment.duration)); res = gst_ts_demux_perform_seek (base, &seeksegment, pid); if (G_UNLIKELY (res != GST_FLOW_OK)) { @@ -869,7 +861,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event, guint16 pid) if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) { gst_element_post_message (GST_ELEMENT_CAST (demux), gst_message_new_segment_start (GST_OBJECT_CAST (demux), - demux->segment.format, demux->segment.last_stop)); + demux->segment.format, demux->segment.stop)); } done: @@ -1113,8 +1105,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, name = g_strdup_printf ("video_%04x", bstream->pid); caps = gst_caps_new_simple ("video/x-wmv", "wmvversion", G_TYPE_INT, 3, - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'), - NULL); + "format", G_TYPE_STRING, "WVC1", NULL); } } g_free (desc); @@ -1375,6 +1366,7 @@ process_section (MpegTSBase * base) next: mpegts_packetizer_clear_packet (base->packetizer, &packet); } + return done; } @@ -1553,7 +1545,6 @@ find_timestamps (MpegTSBase * base, guint64 initoff, guint64 * offset) GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf; gboolean done = FALSE; - GstFormat format = GST_FORMAT_BYTES; gint64 total_bytes; guint64 scan_offset; guint i = 0; @@ -1600,8 +1591,8 @@ find_timestamps (MpegTSBase * base, guint64 initoff, guint64 * offset) demux->program = NULL; /* Find end position */ - if (G_UNLIKELY (!gst_pad_query_peer_duration (base->sinkpad, &format, - &total_bytes) || format != GST_FORMAT_BYTES)) { + if (G_UNLIKELY (!gst_pad_query_peer_duration (base->sinkpad, GST_FORMAT_BYTES, + &total_bytes))) { GST_WARNING_OBJECT (base, "Couldn't get upstream size in bytes"); ret = GST_FLOW_ERROR; mpegts_packetizer_clear (base->packetizer); @@ -1641,9 +1632,8 @@ find_timestamps (MpegTSBase * base, guint64 initoff, guint64 * offset) verify_timestamps (base, &initial, &final); - gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME, - demux->last_pcr.gsttime - demux->first_pcr.gsttime); - demux->duration = demux->last_pcr.gsttime - demux->first_pcr.gsttime; + demux->duration = demux->segment.duration = + demux->last_pcr.gsttime - demux->first_pcr.gsttime; GST_DEBUG ("Done, duration:%" GST_TIME_FORMAT, GST_TIME_ARGS (demux->duration)); @@ -1699,7 +1689,9 @@ process_pcr (MpegTSBase * base, guint64 initoff, TSPcrOffset * pcroffset, pcrpattern = 0x47000020 | ((program->pcr_pid & 0x1fff) << 8); for (i = 0; (i < 20) && (nbpcr < numpcr); i++) { - guint offset, size; + guint offset; + gsize size, bufsize; + gpointer data; ret = gst_pad_pull_range (base->sinkpad, @@ -1708,17 +1700,21 @@ process_pcr (MpegTSBase * base, guint64 initoff, TSPcrOffset * pcroffset, if (G_UNLIKELY (ret != GST_FLOW_OK)) goto beach; - gst_byte_reader_init_from_buffer (&br, buf); + data = gst_buffer_map (buf, &bufsize, 0, GST_MAP_READ); + size = bufsize; + + gst_byte_reader_init (&br, data, size); offset = 0; - size = GST_BUFFER_SIZE (buf); resync: offset = gst_byte_reader_masked_scan_uint32 (&br, 0xff000000, 0x47000000, 0, base->packetsize); - if (offset == -1) + if (offset == -1) { + gst_buffer_unmap (buf, data, bufsize); continue; + } while ((nbpcr < numpcr) && (size >= base->packetsize)) { @@ -1767,6 +1763,7 @@ process_pcr (MpegTSBase * base, guint64 initoff, TSPcrOffset * pcroffset, size -= base->packetsize; offset += base->packetsize; } + gst_buffer_unmap (buf, data, bufsize); } beach: @@ -1930,21 +1927,22 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) { MpegTSBase *base = (MpegTSBase *) demux; PESHeader header; + GstBuffer *buf = stream->pendingbuffers[0]; GstFlowReturn res = GST_FLOW_OK; gint offset = 0; guint8 *data; - guint32 length; + gsize length; guint64 bufferoffset; GstClockTime time; PESParsingResult parseres; - data = GST_BUFFER_DATA (stream->pendingbuffers[0]); - length = GST_BUFFER_SIZE (stream->pendingbuffers[0]); - bufferoffset = GST_BUFFER_OFFSET (stream->pendingbuffers[0]); + data = gst_buffer_map (buf, &length, 0, GST_MAP_READ); + bufferoffset = GST_BUFFER_OFFSET (buf); GST_MEMDUMP ("Header buffer", data, MIN (length, 32)); parseres = mpegts_parse_pes_header (data, length, &header, &offset); + if (G_UNLIKELY (parseres == PES_PARSING_NEED_MORE)) goto discont; if (G_UNLIKELY (parseres == PES_PARSING_BAD)) { @@ -2008,16 +2006,17 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) if (!GST_CLOCK_TIME_IS_VALID (base->in_gap)) base->in_gap = 0; - GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = time + base->in_gap; + GST_BUFFER_TIMESTAMP (buf) = time + base->in_gap; } if (header.DTS != -1) gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset); + gst_buffer_unmap (buf, data, length); + /* Remove PES headers */ GST_DEBUG ("Moving data forward by %d bytes", header.header_size); - GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size; - GST_BUFFER_SIZE (stream->pendingbuffers[0]) -= header.header_size; + gst_buffer_resize (buf, header.header_size, length - header.header_size); /* FIXME : responsible for switching to PENDING_PACKET_BUFFER and * creating the bufferlist */ @@ -2028,9 +2027,7 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) /* Create a new bufferlist */ stream->current = gst_buffer_list_new (); - stream->currentit = gst_buffer_list_iterate (stream->current); stream->currentlist = NULL; - gst_buffer_list_iterator_add_group (stream->currentit); /* Push pending buffers into the list */ for (i = stream->nbpending; i; i--) @@ -2058,14 +2055,20 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, MpegTSPacketizerPacket * packet) { GstBuffer *buf; + guint8 *data; + gsize size; GST_DEBUG ("state:%d", stream->state); buf = packet->buffer; - /* HACK : Instead of creating a new buffer, we just modify the data/size - * of the buffer to point to the payload */ - GST_BUFFER_DATA (buf) = packet->payload; - GST_BUFFER_SIZE (buf) = packet->data_end - packet->payload; + data = gst_buffer_map (buf, &size, 0, GST_MAP_READ); + + GST_DEBUG ("Resizing buffer to %d (size:%d) (Was %d bytes long)", + packet->payload - data, packet->data_end - packet->payload, size); + gst_buffer_unmap (buf, data, size); + + gst_buffer_resize (buf, packet->payload - data, + packet->data_end - packet->payload); if (stream->state == PENDING_PACKET_EMPTY) { if (G_UNLIKELY (!packet->payload_unit_start_indicator)) { @@ -2074,10 +2077,6 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, } else { GST_LOG ("EMPTY=>HEADER"); stream->state = PENDING_PACKET_HEADER; - if (stream->pad) { - GST_DEBUG ("Setting pad caps on buffer %p", buf); - gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); - } } } @@ -2170,9 +2169,7 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream) GST_DEBUG ("new segment: start: %" GST_TIME_FORMAT " stop: %" GST_TIME_FORMAT " time: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (position)); - newsegmentevent = - gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, start, stop, - position); + newsegmentevent = gst_event_new_segment (&demux->segment); push_event ((MpegTSBase *) demux, newsegmentevent); @@ -2183,7 +2180,9 @@ static GstFlowReturn gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) { GstFlowReturn res = GST_FLOW_OK; + GList *tmp; MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + GstBuffer *buf; GST_DEBUG ("stream:%p, pid:0x%04x stream_type:%d state:%d pad:%s:%s", stream, bs->pid, bs->stream_type, stream->state, @@ -2205,7 +2204,6 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) if (G_UNLIKELY (stream->pad == NULL)) { g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL); g_list_free (stream->currentlist); - gst_buffer_list_iterator_free (stream->currentit); gst_buffer_list_unref (stream->current); goto beach; } @@ -2215,16 +2213,19 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) /* We have a confirmed buffer, let's push it out */ GST_LOG ("Putting pending data into GstBufferList"); + stream->currentlist = g_list_reverse (stream->currentlist); - gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist); - gst_buffer_list_iterator_free (stream->currentit); + buf = (GstBuffer *) stream->currentlist->data; + + for (tmp = stream->currentlist->next; tmp; tmp = tmp->next) { + buf = gst_buffer_merge (buf, (GstBuffer *) tmp->data); + } GST_DEBUG_OBJECT (stream->pad, - "Pushing buffer list with timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (gst_buffer_list_get - (stream->current, 0, 0)))); + "Pushing buffer with timestamp: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); - res = gst_pad_push_list (stream->pad, stream->current); + res = gst_pad_push (stream->pad, buf); GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res)); res = tsdemux_combine_flows (demux, stream, res); GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res)); @@ -2246,8 +2247,10 @@ gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream, { GstFlowReturn res = GST_FLOW_OK; +#if 0 GST_DEBUG ("buffer:%p, data:%p", GST_BUFFER_DATA (packet->buffer), packet->data); +#endif GST_LOG ("pid 0x%04x pusi:%d, afc:%d, cont:%d, payload:%p", packet->pid, packet->payload_unit_start_indicator, @@ -2256,7 +2259,7 @@ gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream, if (section) { GST_DEBUG ("section complete:%d, buffer size %d", - section->complete, GST_BUFFER_SIZE (section->buffer)); + section->complete, gst_buffer_get_size (section->buffer)); gst_buffer_unref (packet->buffer); return res; } @@ -2299,6 +2302,8 @@ gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, TSDemuxStream *stream = NULL; GstFlowReturn res = GST_FLOW_OK; + GST_DEBUG ("packet->buffer %p", packet->buffer); + if (G_LIKELY (demux->program)) { stream = (TSDemuxStream *) demux->program->streams[packet->pid]; diff --git a/gst/mpegtsdemux/tsdemux.h b/gst/mpegtsdemux/tsdemux.h index 395cf3e134..c74d4970db 100644 --- a/gst/mpegtsdemux/tsdemux.h +++ b/gst/mpegtsdemux/tsdemux.h @@ -70,6 +70,7 @@ struct _GstTSDemux MpegTSBaseProgram *program; /* Current program */ guint current_program_number; gboolean need_newsegment; + /* Downstream segment */ GstSegment segment; GstClockTime duration; /* Total duration */