diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | gst/mpegtsdemux/Makefile.am | 3 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtsbase.c | 238 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtspacketizer.c | 227 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtspacketizer.h | 4 | ||||
-rw-r--r-- | gst/mpegtsdemux/mpegtsparse.c | 61 | ||||
-rw-r--r-- | gst/mpegtsdemux/tsdemux.c | 293 |
7 files changed, 430 insertions, 398 deletions
diff --git a/configure.ac b/configure.ac index 6d831b9fd..447400ca4 100644 --- a/configure.ac +++ b/configure.ac @@ -314,7 +314,7 @@ GST_PLUGINS_NONPORTED=" aiff asfmux \ apexsink cdaudio cog curl dc1394 dirac directfb resindvd \ gsettings jp2k ladspa mimic \ musepack musicbrainz nas neon ofa openal opencv rsvg sdl sndfile soundtouch spandsp spc timidity \ - wildmidi xvid lv2 teletextdec dvb mpegtsdemux" + wildmidi xvid lv2 teletextdec dvb" AC_SUBST(GST_PLUGINS_NONPORTED) dnl these are all the gst plug-ins, compilable without additional libs diff --git a/gst/mpegtsdemux/Makefile.am b/gst/mpegtsdemux/Makefile.am index e6b727e42..b2cd46896 100644 --- a/gst/mpegtsdemux/Makefile.am +++ b/gst/mpegtsdemux/Makefile.am @@ -1,5 +1,8 @@ plugin_LTLIBRARIES = libgstmpegtsdemux.la +# FIXME 0.11: ignore GValueArray warnings for now until this is sorted +ERROR_CFLAGS= + libgstmpegtsdemux_la_SOURCES = \ gsttsdemux.c \ gstmpegdesc.c \ diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index cf1e26d9c..8a4c7fea2 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -81,14 +81,15 @@ static void mpegts_base_dispose (GObject * object); static void mpegts_base_finalize (GObject * object); static void mpegts_base_free_program (MpegTSBaseProgram * program); static void mpegts_base_free_stream (MpegTSBaseStream * ptream); -static gboolean mpegts_base_sink_activate (GstPad * pad); -static gboolean mpegts_base_sink_activate_pull (GstPad * pad, gboolean active); -static gboolean mpegts_base_sink_activate_push (GstPad * pad, gboolean active); -static GstFlowReturn mpegts_base_chain (GstPad * pad, GstBuffer * buf); -static gboolean mpegts_base_sink_event (GstPad * pad, GstEvent * event); +static gboolean mpegts_base_sink_activate (GstPad * pad, GstObject * parent); +static gboolean mpegts_base_sink_activate_mode (GstPad * pad, + GstObject * parent, GstPadMode mode, gboolean active); +static GstFlowReturn mpegts_base_chain (GstPad * pad, GstObject * parent, + GstBuffer * buf); +static gboolean mpegts_base_sink_event (GstPad * pad, GstObject * parent, + 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, @@ -97,9 +98,20 @@ static gboolean remove_each_program (gpointer key, MpegTSBaseProgram * program, MpegTSBase * base); -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, @@ -161,25 +173,6 @@ mpegts_base_calc_crc32 (guint8 * data, guint datalen) } 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_static_pad_template (element_class, &sink_template); -} - -static void mpegts_base_class_init (MpegTSBaseClass * klass) { GObjectClass *gobject_class; @@ -188,6 +181,9 @@ 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; @@ -237,14 +233,12 @@ 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); - gst_pad_set_activatepull_function (base->sinkpad, - mpegts_base_sink_activate_pull); - gst_pad_set_activatepush_function (base->sinkpad, - mpegts_base_sink_activate_push); + gst_pad_set_activatemode_function (base->sinkpad, + mpegts_base_sink_activate_mode); gst_pad_set_chain_function (base->sinkpad, mpegts_base_chain); gst_pad_set_event_function (base->sinkpad, mpegts_base_sink_event); gst_element_add_pad (GST_ELEMENT (base), base->sinkpad); @@ -495,21 +489,31 @@ mpegts_base_free_program (MpegTSBaseProgram * program) /* FIXME : This is being called by tsdemux::find_timestamps() * We need to avoid re-entrant code like that */ +static gboolean +mpegts_base_stop_program (MpegTSBase * base, MpegTSBaseProgram * program) +{ + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + GST_DEBUG_OBJECT (base, "program_number : %d", program->program_number); + + if (klass->program_stopped) + klass->program_stopped (base, program); + + return TRUE; +} + void mpegts_base_remove_program (MpegTSBase * base, gint program_number) { MpegTSBaseProgram *program; - MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); GST_DEBUG_OBJECT (base, "program_number : %d", program_number); + program = + (MpegTSBaseProgram *) g_hash_table_lookup (base->programs, + GINT_TO_POINTER (program_number)); + if (program) + mpegts_base_stop_program (base, program); - if (klass->program_stopped) { - program = - (MpegTSBaseProgram *) g_hash_table_lookup (base->programs, - GINT_TO_POINTER (program_number)); - if (program) - klass->program_stopped (base, program); - } g_hash_table_remove (base->programs, GINT_TO_POINTER (program_number)); } @@ -1056,11 +1060,15 @@ 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)) { + GstMapInfo map; + + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + if (G_UNLIKELY (mpegts_base_calc_crc32 (map.data, map.size) != 0)) { + gst_buffer_unmap (section->buffer, &map); GST_WARNING_OBJECT (base, "bad crc in psi pid 0x%x", section->pid); return FALSE; } + gst_buffer_unmap (section->buffer, &map); } switch (section->table_id) { @@ -1195,7 +1203,7 @@ mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info) program = mpegts_base_get_program (base, program_number); if (program && !program->tags) { - program->tags = gst_tag_list_new_full (GST_TAG_ARTIST, + program->tags = gst_tag_list_new (GST_TAG_ARTIST, gst_structure_get_string (service, "name"), NULL); } } @@ -1236,7 +1244,7 @@ mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info) gst_structure_get_uint (event, "duration", &duration); program->event_id = event_id; - program->tags = gst_tag_list_new_full (GST_TAG_TITLE, + program->tags = gst_tag_list_new (GST_TAG_TITLE, title, GST_TAG_DURATION, duration * GST_SECOND, NULL); } } @@ -1280,39 +1288,30 @@ mpegts_base_flush (MpegTSBase * base) } static gboolean -mpegts_base_sink_event (GstPad * pad, GstEvent * event) +mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; - MpegTSBase *base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad))); + MpegTSBase *base = GST_MPEGTS_BASE (parent); GST_WARNING_OBJECT (base, "Got event %s", gst_event_type_get_name (GST_EVENT_TYPE (event))); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - gdouble rate, applied_rate; - GstFormat format; - gint64 start, stop, position; - - 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); + case GST_EVENT_SEGMENT: + gst_event_copy_segment (event, &base->segment); + gst_event_unref (event); + break; + case GST_EVENT_STREAM_START: gst_event_unref (event); - } break; case GST_EVENT_EOS: res = gst_mpegts_base_handle_eos (base); gst_event_unref (event); break; + case GST_EVENT_CAPS: + /* FIXME, do something */ + gst_event_unref (event); + break; case GST_EVENT_FLUSH_START: mpegts_packetizer_flush (base->packetizer); mpegts_base_flush (base); @@ -1326,7 +1325,6 @@ mpegts_base_sink_event (GstPad * pad, GstEvent * event) res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); } - gst_object_unref (base); return res; } @@ -1362,7 +1360,7 @@ mpegts_base_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, } static GstFlowReturn -mpegts_base_chain (GstPad * pad, GstBuffer * buf) +mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstFlowReturn res = GST_FLOW_OK; MpegTSBase *base; @@ -1371,7 +1369,7 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) MpegTSPacketizer2 *packetizer; MpegTSPacketizerPacket packet; - base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad))); + base = GST_MPEGTS_BASE (parent); packetizer = base->packetizer; if (G_UNLIKELY (base->queried_latency == FALSE)) { @@ -1379,8 +1377,14 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) } mpegts_packetizer_push (base->packetizer, buf); - while (((pret = mpegts_packetizer_next_packet (base->packetizer, - &packet)) != PACKET_NEED_MORE) && res == GST_FLOW_OK) { + + while (res == GST_FLOW_OK) { + pret = mpegts_packetizer_next_packet (base->packetizer, &packet); + + /* If we don't have enough data, return */ + if (G_UNLIKELY (pret == PACKET_NEED_MORE)) + break; + if (G_UNLIKELY (pret == PACKET_BAD)) /* bad header, skip the packet */ goto next; @@ -1417,7 +1421,6 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf) mpegts_packetizer_clear_packet (base->packetizer, &packet); } - gst_object_unref (base); return res; } @@ -1480,7 +1483,7 @@ mpegts_base_scan (MpegTSBase * base) /* Get the size of upstream */ format = GST_FORMAT_BYTES; - if (!gst_pad_query_peer_duration (base->sinkpad, &format, &tmpval)) + if (!gst_pad_peer_query_duration (base->sinkpad, format, &tmpval)) goto beach; upstream_size = tmpval; done = FALSE; @@ -1554,8 +1557,8 @@ 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); - ret = mpegts_base_chain (base->sinkpad, buf); + base->seek_offset += gst_buffer_get_size (buf); + ret = mpegts_base_chain (base->sinkpad, GST_OBJECT_CAST (base), buf); if (G_UNLIKELY (ret != GST_FLOW_OK)) goto error; } @@ -1571,16 +1574,9 @@ error: { const gchar *reason = gst_flow_get_name (ret); GST_DEBUG_OBJECT (base, "Pausing task, reason %s", reason); - if (ret == GST_FLOW_UNEXPECTED) { - /* Push EOS downstream */ - if (!GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, - gst_event_new_eos ())) { - /* If that failed, emit an error so the pipeline can be stopped */ - GST_ELEMENT_ERROR (base, STREAM, DEMUX, (NULL), - ("got eos but no streams (yet)")); - - } - } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) { + if (ret == GST_FLOW_EOS) { + GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, gst_event_new_eos ()); + } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { GST_ELEMENT_ERROR (base, STREAM, FAILED, (_("Internal data stream error.")), ("stream stopped, reason %s", reason)); @@ -1646,7 +1642,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)); /* And actually flush our pending data */ mpegts_base_flush (base); mpegts_packetizer_flush (base->packetizer); @@ -1675,7 +1671,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: @@ -1687,38 +1683,62 @@ push_mode: static gboolean -mpegts_base_sink_activate (GstPad * pad) +mpegts_base_sink_activate (GstPad * sinkpad, GstObject * parent) { - 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; } -} -static gboolean -mpegts_base_sink_activate_pull (GstPad * pad, gboolean active) -{ - MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad)); - if (active) { - base->mode = BASE_MODE_SCANNING; - base->packetizer->calculate_offset = TRUE; - return gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, base); - } else - return gst_pad_stop_task (pad); + pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL); + gst_query_unref (query); + + if (!pull_mode) + goto activate_push; + + GST_DEBUG_OBJECT (sinkpad, "activating pull"); + return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE); + +activate_push: + { + GST_DEBUG_OBJECT (sinkpad, "activating push"); + return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); + } } static gboolean -mpegts_base_sink_activate_push (GstPad * pad, gboolean active) +mpegts_base_sink_activate_mode (GstPad * pad, GstObject * parent, + GstPadMode mode, gboolean active) { - MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad)); - base->mode = BASE_MODE_PUSHING; - base->packetizer->calculate_skew = TRUE; - return TRUE; -} + gboolean res; + MpegTSBase *base = GST_MPEGTS_BASE (parent); + switch (mode) { + case GST_PAD_MODE_PUSH: + base->mode = BASE_MODE_PUSHING; + base->packetizer->calculate_skew = TRUE; + res = TRUE; + break; + case GST_PAD_MODE_PULL: + if (active) { + base->mode = BASE_MODE_SCANNING; + base->packetizer->calculate_offset = TRUE; + res = + gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, base); + } else + res = gst_pad_stop_task (pad); + break; + default: + res = FALSE; + break; + } + return res; +} static GstStateChangeReturn mpegts_base_change_state (GstElement * element, GstStateChange transition) diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 41ff6dd37..b89492033 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -357,6 +357,8 @@ mpegts_packetizer_parse_packet (MpegTSPacketizer2 * packetizer, packet->data = data; + gst_buffer_unmap (packet->buffer, &packet->bufmap); + if (packet->adaptation_field_control & 0x02) if (!mpegts_packetizer_parse_adaptation_field_control (packetizer, packet)) return FALSE; @@ -373,6 +375,7 @@ static gboolean mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, MpegTSPacketizerStream * stream, MpegTSPacketizerSection * section) { + GstMapInfo map; guint8 tmp; guint8 *data, *crc_data; MpegTSPacketizerStreamSubtable *subtable; @@ -382,7 +385,8 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, /* 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); + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; GST_BUFFER_OFFSET (section->buffer) = stream->offset; section->table_id = *data++; @@ -418,8 +422,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 = map.data + map.size - 4; section->crc = GST_READ_UINT32_BE (crc_data); if (section->version_number == subtable->version_number && @@ -430,6 +433,8 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, subtable->crc = section->crc; stream->section_table_id = section->table_id; + gst_buffer_unmap (section->buffer, &map); + return TRUE; not_applicable: @@ -438,6 +443,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, &map); gst_buffer_unref (section->buffer); return TRUE; } @@ -491,6 +497,7 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *pat_info = NULL; + GstMapInfo map; guint8 *data, *end; guint transport_stream_id; guint8 tmp; @@ -501,7 +508,8 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, GstStructure *entry = NULL; gchar *struct_name; - data = GST_BUFFER_DATA (section->buffer); + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -517,11 +525,11 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, /* skip section_number and last_section_number */ data += 2; - pat_info = gst_structure_id_new (QUARK_PAT, + pat_info = gst_structure_new_id (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 = map.data + map.size; while (data < end - 4) { program_number = GST_READ_UINT16_BE (data); data += 2; @@ -530,7 +538,7 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, data += 2; struct_name = g_strdup_printf ("program-%d", program_number); - entry = gst_structure_new (struct_name, NULL); + entry = gst_structure_new_empty (struct_name); g_free (struct_name); gst_structure_id_set (entry, QUARK_PROGRAM_NUMBER, G_TYPE_UINT, program_number, QUARK_PID, G_TYPE_UINT, pmt_pid, NULL); @@ -544,6 +552,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, &map); + if (data != end - 4) { /* FIXME: check the CRC before parsing the packet */ GST_ERROR ("at the end of PAT data != end - 4"); @@ -560,6 +570,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *pmt = NULL; + GstMapInfo map; guint8 *data, *end; guint16 program_number; guint8 tmp; @@ -574,15 +585,17 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, GstStructure *stream_info = NULL; gchar *struct_name; + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 16) { + if (map.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 = map.data + map.size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -606,7 +619,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, program_info_length = GST_READ_UINT16_BE (data) & 0x0FFF; data += 2; - pmt = gst_structure_id_new (QUARK_PMT, + pmt = gst_structure_new_id (QUARK_PMT, QUARK_PROGRAM_NUMBER, G_TYPE_UINT, program_number, QUARK_PCR_PID, G_TYPE_UINT, pcr_pid, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, NULL); @@ -653,7 +666,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, } struct_name = g_strdup_printf ("pid-%d", pid); - stream_info = gst_structure_new (struct_name, NULL); + stream_info = gst_structure_new_empty (struct_name); g_free (struct_name); gst_structure_id_set (stream_info, QUARK_PID, G_TYPE_UINT, pid, QUARK_STREAM_TYPE, G_TYPE_UINT, @@ -755,6 +768,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, &map); + g_assert (data == end - 4); return pmt; @@ -762,6 +777,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, error: if (pmt) gst_structure_free (pmt); + gst_buffer_unmap (section->buffer, &map); return NULL; } @@ -771,6 +787,7 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { GstStructure *nit = NULL, *transport = NULL, *delivery_structure = NULL; + GstMapInfo map; guint8 *data, *end, *entry_begin; guint16 network_id, transport_stream_id, original_network_id; guint tmp; @@ -780,15 +797,18 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, GValueArray *descriptors = NULL; GST_DEBUG ("NIT"); + + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 23) { + if (map.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 = map.data + map.size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -813,7 +833,7 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; data += 2; - nit = gst_structure_id_new (QUARK_NIT, + nit = gst_structure_new_id (QUARK_NIT, QUARK_NETWORK_ID, G_TYPE_UINT, network_id, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, @@ -891,7 +911,7 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, data += 2; transport_name = g_strdup_printf ("transport-%d", transport_stream_id); - transport = gst_structure_new (transport_name, NULL); + transport = gst_structure_new_empty (transport_name); g_free (transport_name); gst_structure_id_set (transport, QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, @@ -1376,15 +1396,16 @@ 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)); + GST_WARNING ("PID %d invalid NIT parsed %d length %" G_GSIZE_FORMAT, + section->pid, (gint) (data - map.data), map.size); goto error; } gst_structure_id_set_value (nit, QUARK_TRANSPORTS, &transports); g_value_unset (&transports); + gst_buffer_unmap (section->buffer, &map); + GST_DEBUG ("NIT %" GST_PTR_FORMAT, nit); return nit; @@ -1393,6 +1414,8 @@ error: if (nit) gst_structure_free (nit); + gst_buffer_unmap (section->buffer, &map); + if (GST_VALUE_HOLDS_LIST (&transports)) g_value_unset (&transports); @@ -1403,6 +1426,7 @@ GstStructure * mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, MpegTSPacketizerSection * section) { + GstMapInfo map; GstStructure *sdt = NULL, *service = NULL; guint8 *data, *end, *entry_begin; guint16 transport_stream_id, original_network_id, service_id; @@ -1416,15 +1440,18 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, GValue service_value = { 0 }; GST_DEBUG ("SDT"); + + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 14) { + if (map.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 = map.data + map.size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -1452,7 +1479,7 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, /* skip reserved byte */ data += 1; - sdt = gst_structure_id_new (QUARK_SDT, + sdt = gst_structure_new_id (QUARK_SDT, QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, @@ -1491,7 +1518,7 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, /* TODO send tag event down relevant pad for channel name and provider */ service_name = g_strdup_printf ("service-%d", service_id); - service = gst_structure_new (service_name, NULL); + service = gst_structure_new_empty (service_name); g_free (service_name); if (descriptors_loop_length) { @@ -1581,21 +1608,24 @@ 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)); + GST_WARNING ("PID %d invalid SDT parsed %d length %" G_GSIZE_FORMAT, + section->pid, (gint) (data - map.data), map.size); goto error; } gst_structure_id_set_value (sdt, QUARK_SERVICES, &services); g_value_unset (&services); + gst_buffer_unmap (section->buffer, &map); + return sdt; error: if (sdt) gst_structure_free (sdt); + gst_buffer_unmap (section->buffer, &map); + if (GST_VALUE_HOLDS_LIST (&services)) g_value_unset (&services); @@ -1614,6 +1644,7 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, guint16 mjd; guint year, month, day, hour, minute, second; guint duration; + GstMapInfo map; guint8 *data, *end, *duration_ptr, *utc_ptr; guint16 descriptors_loop_length; GValue events = { 0 }; @@ -1622,15 +1653,17 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, gchar *event_name; guint tmp; + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; + /* fixed header + CRC == 16 */ - if (GST_BUFFER_SIZE (section->buffer) < 18) { + if (map.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 = map.data + map.size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -1661,7 +1694,7 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, last_table_id = *data; data += 1; - eit = gst_structure_id_new (QUARK_EIT, + eit = gst_structure_new_id (QUARK_EIT, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, section->current_next_indicator, QUARK_SERVICE_ID, G_TYPE_UINT, @@ -2040,15 +2073,16 @@ 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)); + GST_WARNING ("PID %d invalid EIT parsed %d length %" G_GSIZE_FORMAT, + section->pid, (gint) (data - map.data), map.size); goto error; } gst_structure_id_set_value (eit, QUARK_EVENTS, &events); g_value_unset (&events); + gst_buffer_unmap (section->buffer, &map); + GST_DEBUG ("EIT %" GST_PTR_FORMAT, eit); return eit; @@ -2057,6 +2091,8 @@ error: if (eit) gst_structure_free (eit); + gst_buffer_unmap (section->buffer, &map); + if (GST_VALUE_HOLDS_LIST (&events)) g_value_unset (&events); @@ -2070,18 +2106,22 @@ mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer, GstStructure *tdt = NULL; guint16 mjd; guint year, month, day, hour, minute, second; + GstMapInfo map; guint8 *data, *end, *utc_ptr; GST_DEBUG ("TDT"); + + gst_buffer_map (section->buffer, &map, GST_MAP_READ); + data = map.data; + /* length always 8 */ - if (G_UNLIKELY (GST_BUFFER_SIZE (section->buffer) != 8)) { + if (G_UNLIKELY (map.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 = map.data + map.size; section->table_id = *data++; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; @@ -2122,12 +2162,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, &map); + return tdt; error: if (tdt) gst_structure_free (tdt); + gst_buffer_unmap (section->buffer, &map); + return NULL; } @@ -2205,8 +2249,8 @@ mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer) packetizer->offset = GST_BUFFER_OFFSET (buffer); } - GST_DEBUG ("Pushing %u byte from offset %" G_GUINT64_FORMAT, - GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); + GST_DEBUG ("Pushing %" G_GSIZE_FORMAT " byte from offset %" G_GUINT64_FORMAT, + gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer)); gst_adapter_push (packetizer->adapter, buffer); } @@ -2307,15 +2351,21 @@ mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer, } 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); + gst_buffer_map (packet->buffer, &packet->bufmap, GST_MAP_READ); + + bufdata = packet->data_start = packet->bufmap.data; + /* 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 */ @@ -2323,52 +2373,51 @@ mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer, 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); GST_BUFFER_TIMESTAMP (packet->buffer) = gst_adapter_prev_timestamp (packetizer->adapter, NULL); /* Check sync byte */ - if (G_UNLIKELY (packet->data_start[0] != 0x47)) { - guint i; - GstBuffer *tmpbuf; - - 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; - } + if (G_LIKELY (packet->data_start[0] == 0x47)) + goto got_valid_packet; - if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) { - if (i >= 4) - i -= 4; - else - i += 188; - } + GST_LOG ("Lost sync %d", packetizer->packet_size); - /* 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; + /* Find the 0x47 in the buffer */ + for (i = 0; i < packetizer->packet_size; i++) + if (bufdata[i] == 0x47) + break; + gst_buffer_unmap (packet->buffer, &packet->bufmap); + if (G_UNLIKELY (i == packetizer->packet_size)) { + GST_ERROR ("REALLY lost the sync"); + 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->bufmap.size - 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); } MpegTSPacketizerPacketReturn @@ -2422,14 +2471,15 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, if (packet->pid == 0x14) { table_id = data[0]; section->section_length = GST_READ_UINT24_BE (data) & 0x000FFF; - if (data - GST_BUFFER_DATA (packet->buffer) + section->section_length + 3 > - GST_BUFFER_SIZE (packet->buffer)) { + if (data - packet->bufmap.data + section->section_length + 3 > + packet->bufmap.size) { GST_WARNING ("PID %dd PSI section length extends past the end " "of the buffer", packet->pid); goto out; } - 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->bufmap.data, section->section_length + 3); section->table_id = table_id; section->complete = TRUE; res = TRUE; @@ -2440,8 +2490,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->bufmap.data, packet->data_end - data); stream = packetizer->streams[packet->pid]; if (stream == NULL) { @@ -2465,10 +2515,11 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, if (stream->continuity_counter != CONTINUITY_UNSET) { GST_DEBUG ("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); + "not complete (last_continuity: %d continuity: %d sec len %d buffer %" + G_GSIZE_FORMAT " avail %" G_GSIZE_FORMAT, packet->pid, table_id, + subtable_extension, stream->continuity_counter, + 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 418da0847..f588cd355 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.h +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -124,6 +124,8 @@ typedef struct guint8 continuity_counter; guint8 *payload; + GstMapInfo bufmap; + guint8 *data_start; guint8 *data_end; guint8 *data; @@ -176,7 +178,7 @@ MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *p MpegTSPacketizerPacketReturn mpegts_packetizer_process_next_packet(MpegTSPacketizer2 * packetizer); 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 f15a8bd69..b66efcc0b 100644 --- a/gst/mpegtsdemux/mpegtsparse.c +++ b/gst/mpegtsdemux/mpegtsparse.c @@ -70,13 +70,13 @@ struct _MpegTSParsePad }; static GstStaticPadTemplate src_template = -GST_STATIC_PAD_TEMPLATE ("src%d", GST_PAD_SRC, +GST_STATIC_PAD_TEMPLATE ("src_%u", GST_PAD_SRC, GST_PAD_REQUEST, GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") ); static GstStaticPadTemplate program_template = -GST_STATIC_PAD_TEMPLATE ("program_%d", GST_PAD_SRC, +GST_STATIC_PAD_TEMPLATE ("program_%u", GST_PAD_SRC, GST_PAD_SOMETIMES, GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") ); @@ -113,27 +113,14 @@ 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 mpegts_parse_src_pad_query (GstPad * pad, GstObject * parent, + 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_static_pad_template (element_class, &src_template); - gst_element_class_add_static_pad_template (element_class, &program_template); - - gst_element_class_set_details_simple (element_class, - "MPEG transport stream parser", "Codec/Parser", - "Parses MPEG2 transport streams", - "Alessandro Decina <alessandro@nnva.org>, " - "Zaheer Abbas Merali <zaheerabbas at merali dot org>"); -} +#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) @@ -147,6 +134,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 <alessandro@nnva.org>, " + "Zaheer Abbas Merali <zaheerabbas at merali dot org>"); + gobject_class = G_OBJECT_CLASS (klass); gobject_class->set_property = mpegts_parse_set_property; gobject_class->get_property = mpegts_parse_get_property; @@ -166,7 +164,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 (""); @@ -224,7 +222,7 @@ mpegts_parse_activate_program (MpegTSParse2 * parse, gchar *pad_name; pad_name = - g_strdup_printf ("program_%d", + g_strdup_printf ("program_%u", ((MpegTSBaseProgram *) program)->program_number); tspad = mpegts_parse_create_tspad (parse, pad_name); @@ -430,7 +428,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; @@ -442,11 +440,12 @@ mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template, parse = GST_MPEGTS_PARSE (element); GST_OBJECT_LOCK (element); - name = g_strdup_printf ("src%d", parse->req_pads++); + name = g_strdup_printf ("src_%u", parse->req_pads++); GST_OBJECT_UNLOCK (element); pad = mpegts_parse_create_tspad (parse, name)->pad; gst_pad_set_active (pad, TRUE); + gst_pad_push_event (pad, gst_event_new_stream_start ()); gst_element_add_pad (element, pad); g_free (name); @@ -512,8 +511,7 @@ mpegts_parse_tspad_push (MpegTSParse2 * parse, MpegTSParsePad * tspad, MpegTSBaseProgram *bp = (MpegTSBaseProgram *) tspad->program; pad_pids = bp->streams; if (bp->tags) { - gst_element_found_tags_for_pad (GST_ELEMENT_CAST (parse), tspad->pad, - bp->tags); + gst_pad_push_event (tspad->pad, gst_event_new_tag (bp->tags)); bp->tags = NULL; } } else { @@ -565,9 +563,7 @@ mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, mpegts_parse_sync_program_pads (parse); pid = packet->pid; - 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); + buffer = packet->buffer; GST_OBJECT_LOCK (parse); /* clear tspad->pushed on pads */ @@ -675,9 +671,9 @@ mpegts_parse_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program) } static gboolean -mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query) +mpegts_parse_src_pad_query (GstPad * pad, GstObject * parent, GstQuery * query) { - MpegTSParse2 *parse = GST_MPEGTS_PARSE (gst_pad_get_parent (pad)); + MpegTSParse2 *parse = GST_MPEGTS_PARSE (parent); gboolean res; switch (GST_QUERY_TYPE (query)) { @@ -700,9 +696,8 @@ mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query) break; } default: - res = gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, parent, query); } - gst_object_unref (parse); return res; } diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index 9b69f5b39..f7be0d925 100644 --- a/gst/mpegtsdemux/tsdemux.c +++ b/gst/mpegtsdemux/tsdemux.c @@ -73,13 +73,13 @@ #define SEGMENT_FORMAT "[format:%s, rate:%f, start:%" \ GST_TIME_FORMAT", stop:%"GST_TIME_FORMAT", time:%"GST_TIME_FORMAT \ - ", accum:%"GST_TIME_FORMAT", last_stop:%"GST_TIME_FORMAT \ + ", base:%"GST_TIME_FORMAT", position:%"GST_TIME_FORMAT \ ", duration:%"GST_TIME_FORMAT"]" #define SEGMENT_ARGS(a) gst_format_get_name((a).format), (a).rate, \ GST_TIME_ARGS((a).start), GST_TIME_ARGS((a).stop), \ - GST_TIME_ARGS((a).time), GST_TIME_ARGS((a).accum), \ - GST_TIME_ARGS((a).last_stop), GST_TIME_ARGS((a).duration) + GST_TIME_ARGS((a).time), GST_TIME_ARGS((a).base), \ + GST_TIME_ARGS((a).position), GST_TIME_ARGS((a).duration) GST_DEBUG_CATEGORY_STATIC (ts_demux_debug); @@ -134,8 +134,6 @@ struct _TSDemuxStream guint current_size; /* Current data to be pushed out */ - GstBufferList *current; - GstBufferListIterator *currentit; GList *currentlist; /* Current PTS/DTS for this stream */ @@ -165,7 +163,7 @@ struct _TSDemuxStream "video/x-dirac;" \ "video/x-wmv," \ "wmvversion = (int) 3, " \ - "format = (fourcc) WVC1" \ + "format = (string) WVC1" \ ) #define AUDIO_CAPS \ @@ -252,13 +250,9 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream); static void gst_ts_demux_stream_flush (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"); @@ -269,29 +263,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_static_pad_template (element_class, &video_template); - gst_element_class_add_static_pad_template (element_class, &audio_template); - gst_element_class_add_static_pad_template (element_class, - &subpicture_template); - gst_element_class_add_static_pad_template (element_class, &private_template); - - gst_element_class_set_details_simple (element_class, - "MPEG transport stream demuxer", - "Codec/Demuxer", - "Demuxes MPEG2 transport streams", - "Zaheer Abbas Merali <zaheerabbas at merali dot org>\n" - "Edward Hervey <edward.hervey@collabora.co.uk>"); -} +#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); @@ -308,6 +288,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 <zaheerabbas at merali dot org>\n" + "Edward Hervey <edward.hervey@collabora.co.uk>"); ts_class = GST_MPEGTS_BASE_CLASS (klass); ts_class->reset = GST_DEBUG_FUNCPTR (gst_ts_demux_reset); @@ -341,7 +337,7 @@ gst_ts_demux_reset (MpegTSBase * base) } static void -gst_ts_demux_init (GstTSDemux * demux, GstTSDemuxClass * klass) +gst_ts_demux_init (GstTSDemux * demux) { GST_MPEGTS_BASE (demux)->stream_size = sizeof (TSDemuxStream); @@ -387,28 +383,15 @@ gst_ts_demux_get_property (GObject * object, guint prop_id, } } -static const GstQueryType * -gst_ts_demux_srcpad_query_types (GstPad * pad) -{ - static const GstQueryType query_types[] = { - GST_QUERY_DURATION, - GST_QUERY_SEEKING, - GST_QUERY_LATENCY, - 0 - }; - - return query_types; -} - static gboolean -gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query) +gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query) { gboolean res = TRUE; GstFormat format; GstTSDemux *demux; MpegTSBase *base; - demux = GST_TS_DEMUX (gst_pad_get_parent (pad)); + demux = GST_TS_DEMUX (parent); base = GST_MPEGTS_BASE (demux); switch (GST_QUERY_TYPE (query)) { @@ -421,7 +404,7 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query) gint64 val; format = GST_FORMAT_BYTES; - if (!gst_pad_query_peer_duration (base->sinkpad, &format, &val)) + if (!gst_pad_peer_query_duration (base->sinkpad, format, &val)) res = FALSE; else { GstClockTime dur = @@ -485,10 +468,9 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query) break; } default: - res = gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, parent, query); } - gst_object_unref (demux); return res; } @@ -535,7 +517,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event) GST_DEBUG ("seeksegment before set_seek " SEGMENT_FORMAT, SEGMENT_ARGS (seeksegment)); - gst_segment_set_seek (&seeksegment, rate, format, flags, start_type, start, + gst_segment_do_seek (&seeksegment, rate, format, flags, start_type, start, stop_type, stop, &update); GST_DEBUG ("seeksegment after set_seek " SEGMENT_FORMAT, @@ -561,7 +543,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event) 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: @@ -569,10 +551,10 @@ done: } static gboolean -gst_ts_demux_srcpad_event (GstPad * pad, GstEvent * event) +gst_ts_demux_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event) { gboolean res = TRUE; - GstTSDemux *demux = GST_TS_DEMUX (gst_pad_get_parent (pad)); + GstTSDemux *demux = GST_TS_DEMUX (parent); GST_DEBUG_OBJECT (pad, "Got event %s", gst_event_type_get_name (GST_EVENT_TYPE (event))); @@ -585,10 +567,9 @@ gst_ts_demux_srcpad_event (GstPad * pad, GstEvent * event) gst_event_unref (event); break; default: - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); } - gst_object_unref (demux); return res; } @@ -691,7 +672,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("ac3 audio"); template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-ac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-ac3"); g_free (desc); break; } @@ -702,7 +683,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("ac3 audio"); template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-eac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-eac3"); g_free (desc); break; } @@ -712,7 +693,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("teletext"); template = gst_static_pad_template_get (&private_template); name = g_strdup_printf ("private_%04x", bstream->pid); - caps = gst_caps_new_simple ("private/teletext", NULL); + caps = gst_caps_new_empty_simple ("private/teletext"); g_free (desc); break; } @@ -723,7 +704,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("subtitling"); template = gst_static_pad_template_get (&private_template); name = g_strdup_printf ("private_%04x", bstream->pid); - caps = gst_caps_new_simple ("subpicture/x-dvb", NULL); + caps = gst_caps_new_empty_simple ("subpicture/x-dvb"); g_free (desc); break; } @@ -739,7 +720,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("subtitling"); template = gst_static_pad_template_get (&private_template); name = g_strdup_printf ("private_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-dts", NULL); + caps = gst_caps_new_empty_simple ("audio/x-dts"); break; } g_free (desc); @@ -816,7 +797,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, /* dirac in hex */ template = gst_static_pad_template_get (&video_template); name = g_strdup_printf ("video_%04x", bstream->pid); - caps = gst_caps_new_simple ("video/x-dirac", NULL); + caps = gst_caps_new_empty_simple ("video/x-dirac"); } } g_free (desc); @@ -836,8 +817,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); @@ -860,13 +840,13 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("ac3 audio"); template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-ac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-ac3"); g_free (ac3_desc); } else { template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-eac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-eac3"); } } @@ -883,7 +863,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, if (desc) { template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-eac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-eac3"); g_free (desc); break; } @@ -900,38 +880,38 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, g_free (desc); template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-ac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-ac3"); break; } case ST_BD_AUDIO_EAC3: template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-eac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-eac3"); break; case ST_PS_AUDIO_DTS: template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-dts", NULL); + caps = gst_caps_new_empty_simple ("audio/x-dts"); break; case ST_PS_AUDIO_LPCM: template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-lpcm", NULL); + caps = gst_caps_new_empty_simple ("audio/x-lpcm"); break; case ST_BD_AUDIO_LPCM: template = gst_static_pad_template_get (&audio_template); name = g_strdup_printf ("audio_%04x", bstream->pid); - caps = gst_caps_new_simple ("audio/x-private-ts-lpcm", NULL); + caps = gst_caps_new_empty_simple ("audio/x-private-ts-lpcm"); break; case ST_PS_DVD_SUBPICTURE: template = gst_static_pad_template_get (&subpicture_template); name = g_strdup_printf ("subpicture_%04x", bstream->pid); - caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL); + caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture"); break; case ST_BD_PGS_SUBPICTURE: template = gst_static_pad_template_get (&subpicture_template); name = g_strdup_printf ("subpicture_%04x", bstream->pid); - caps = gst_caps_new_simple ("subpicture/x-pgs", NULL); + caps = gst_caps_new_empty_simple ("subpicture/x-pgs"); break; default: GST_WARNING ("Non-media stream (stream_type:0x%x). Not creating pad", @@ -942,9 +922,10 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream, GST_LOG ("stream:%p creating pad with name %s and caps %s", stream, name, gst_caps_to_string (caps)); pad = gst_pad_new_from_template (template, name); + gst_pad_set_active (pad, TRUE); gst_pad_use_fixed_caps (pad); + gst_pad_push_event (pad, gst_event_new_stream_start ()); gst_pad_set_caps (pad, caps); - gst_pad_set_query_type_function (pad, gst_ts_demux_srcpad_query_types); gst_pad_set_query_function (pad, gst_ts_demux_srcpad_query); gst_pad_set_event_function (pad, gst_ts_demux_srcpad_event); } @@ -1014,7 +995,6 @@ activate_pad_for_stream (GstTSDemux * tsdemux, TSDemuxStream * stream) if (stream->pad) { GST_DEBUG_OBJECT (tsdemux, "Activating pad %s:%s for stream %p", GST_DEBUG_PAD_NAME (stream->pad), stream); - gst_pad_set_active (stream->pad, TRUE); gst_element_add_pad ((GstElement *) tsdemux, stream->pad); stream->active = TRUE; GST_DEBUG_OBJECT (stream->pad, "done adding pad"); @@ -1037,16 +1017,6 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream) memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS); stream->nbpending = 0; - if (stream->current) { - gst_buffer_list_unref (stream->current); - stream->current = NULL; - } - - if (stream->currentit) { - gst_buffer_list_iterator_free (stream->currentit); - stream->currentit = NULL; - } - if (stream->currentlist) { g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL); g_list_free (stream->currentlist); @@ -1055,7 +1025,6 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream) stream->expected_size = 0; stream->current_size = 0; - stream->current = NULL; stream->need_newsegment = TRUE; stream->pts = GST_CLOCK_TIME_NONE; stream->dts = GST_CLOCK_TIME_NONE; @@ -1096,11 +1065,7 @@ gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program) /* If we have an upstream time segment and it's the initial program, just use that */ if (program->initial_program && base->segment.format == GST_FORMAT_TIME) { demux->segment = base->segment; - demux->segment_event = - gst_event_new_new_segment_full (FALSE, base->segment.rate, - base->segment.applied_rate, GST_FORMAT_TIME, base->segment.start, - base->segment.stop, base->segment.time); - GST_EVENT_SRC (demux->segment_event) = gst_object_ref (demux); + demux->segment_event = gst_event_new_segment (&demux->segment); } /* FIXME : When do we emit no_more_pads ? */ @@ -1126,7 +1091,7 @@ gst_ts_demux_record_pcr (GstTSDemux * demux, TSDemuxStream * stream, if (G_UNLIKELY (demux->emit_statistics)) { GstStructure *st; - st = gst_structure_id_empty_new (QUARK_TSDEMUX); + st = gst_structure_new_id_empty (QUARK_TSDEMUX); gst_structure_id_set (st, QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PCR, G_TYPE_UINT64, pcr, @@ -1150,7 +1115,7 @@ gst_ts_demux_record_opcr (GstTSDemux * demux, TSDemuxStream * stream, if (G_UNLIKELY (demux->emit_statistics)) { GstStructure *st; - st = gst_structure_id_empty_new (QUARK_TSDEMUX); + st = gst_structure_new_id_empty (QUARK_TSDEMUX); gst_structure_id_set (st, QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_OFFSET, G_TYPE_UINT64, offset, @@ -1196,7 +1161,7 @@ gst_ts_demux_record_pts (GstTSDemux * demux, TSDemuxStream * stream, if (G_UNLIKELY (demux->emit_statistics)) { GstStructure *st; - st = gst_structure_id_empty_new (QUARK_TSDEMUX); + st = gst_structure_new_id_empty (QUARK_TSDEMUX); gst_structure_id_set (st, QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PTS, G_TYPE_UINT64, pts, @@ -1241,7 +1206,7 @@ gst_ts_demux_record_dts (GstTSDemux * demux, TSDemuxStream * stream, if (G_UNLIKELY (demux->emit_statistics)) { GstStructure *st; - st = gst_structure_id_empty_new (QUARK_TSDEMUX); + st = gst_structure_new_id_empty (QUARK_TSDEMUX); gst_structure_id_set (st, QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_DTS, G_TYPE_UINT64, dts, @@ -1256,20 +1221,22 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) { MpegTSBase *base = (MpegTSBase *) demux; PESHeader header; + GstBuffer *buf; GstFlowReturn res = GST_FLOW_OK; gint offset = 0; - guint8 *data; - guint32 length; + GstMapInfo map; guint64 bufferoffset; PESParsingResult parseres; - data = GST_BUFFER_DATA (stream->pendingbuffers[0]); - length = GST_BUFFER_SIZE (stream->pendingbuffers[0]); - bufferoffset = GST_BUFFER_OFFSET (stream->pendingbuffers[0]); + buf = stream->pendingbuffers[0] = + gst_buffer_make_writable (stream->pendingbuffers[0]); + gst_buffer_map (buf, &map, GST_MAP_READ); + bufferoffset = GST_BUFFER_OFFSET (buf); - GST_MEMDUMP ("Header buffer", data, MIN (length, 32)); + GST_MEMDUMP ("Header buffer", map.data, MIN (map.size, 32)); - parseres = mpegts_parse_pes_header (data, length, &header, &offset); + parseres = mpegts_parse_pes_header (map.data, map.size, &header, &offset); + gst_buffer_unmap (buf, &map); if (G_UNLIKELY (parseres == PES_PARSING_NEED_MORE)) goto discont; if (G_UNLIKELY (parseres == PES_PARSING_BAD)) { @@ -1292,34 +1259,27 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) { MpegTSPacketizer2 *packetizer = base->packetizer; - GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = + GST_BUFFER_DTS (buf) = + mpegts_packetizer_pts_to_ts (packetizer, stream->dts); + GST_BUFFER_PTS (buf) = mpegts_packetizer_pts_to_ts (packetizer, stream->pts); } - GST_DEBUG ("buf %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]))); + GST_DEBUG ("buf %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf))); } /* Remove PES headers */ GST_DEBUG ("Moving data forward by %d bytes (packet_size:%d, have:%d)", - header.header_size, header.packet_length, - GST_BUFFER_SIZE (stream->pendingbuffers[0])); + header.header_size, header.packet_length, map.size); stream->expected_size = header.packet_length; - 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, map.size - header.header_size); /* FIXME : responsible for switching to PENDING_PACKET_BUFFER and * creating the bufferlist */ if (1) { /* Append to the buffer list */ - if (G_UNLIKELY (stream->current == NULL)) { + if (G_UNLIKELY (stream->currentlist == NULL)) { guint8 i; - /* 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--) stream->currentlist = @@ -1350,10 +1310,12 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, 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; + + GST_DEBUG ("Resizing buffer to %d (size:%d) (Was %" G_GSIZE_FORMAT + " bytes long)", (int) (packet->payload - packet->bufmap.data), + (int) (packet->data_end - packet->payload), packet->bufmap.size); + gst_buffer_resize (buf, packet->payload - packet->bufmap.data, + packet->data_end - packet->payload); if (stream->state == PENDING_PACKET_EMPTY) { if (G_UNLIKELY (!packet->payload_unit_start_indicator)) { @@ -1362,10 +1324,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)); - } } } @@ -1375,7 +1333,7 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, GST_LOG ("HEADER: appending data to array"); /* Append to the array */ stream->pendingbuffers[stream->nbpending++] = buf; - stream->current_size += GST_BUFFER_SIZE (buf); + stream->current_size += packet->bufmap.size; /* parse the header */ gst_ts_demux_parse_pes_header (demux, stream); @@ -1385,7 +1343,7 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, { GST_LOG ("BUFFER: appending data to bufferlist"); stream->currentlist = g_list_prepend (stream->currentlist, buf); - stream->current_size += GST_BUFFER_SIZE (buf); + stream->current_size += packet->bufmap.size; break; } case PENDING_PACKET_DISCONT: @@ -1442,39 +1400,30 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream) GST_DEBUG ("Calculating update segment"); /* If we have a valid segment, create an update of that */ if (demux->segment.format == GST_FORMAT_TIME) { + GstSegment update_segment; GST_DEBUG ("Re-using segment " SEGMENT_FORMAT, SEGMENT_ARGS (demux->segment)); - demux->update_segment = - gst_event_new_new_segment_full (TRUE, demux->segment.rate, - demux->segment.applied_rate, GST_FORMAT_TIME, demux->segment.start, - firstts, demux->segment.time); - GST_EVENT_SRC (demux->update_segment) = gst_object_ref (demux); + gst_segment_copy_into (&demux->segment, &update_segment); + update_segment.stop = firstts; + demux->update_segment = gst_event_new_segment (&update_segment); } demux->calculate_update_segment = FALSE; } if (!demux->segment_event) { - gint64 start, stop, time; + GstSegment new_segment; GST_DEBUG ("Calculating actual segment"); - if (demux->segment.format == GST_FORMAT_TIME) { - /* if we have a TIME segment, set NS.start to the target ts so downstream - * can clip - */ - start = demux->segment.start; - stop = demux->segment.stop; - time = demux->segment.time; - } else { - /* ...else start from the first ts/pts */ - start = firstts; - stop = GST_CLOCK_TIME_NONE; - time = firstts; + gst_segment_copy_into (&demux->segment, &new_segment); + if (new_segment.format != GST_FORMAT_TIME) { + /* Start from the first ts/pts */ + new_segment.start = firstts; + new_segment.stop = GST_CLOCK_TIME_NONE; + new_segment.position = firstts; } - demux->segment_event = - gst_event_new_new_segment_full (FALSE, demux->segment.rate, - demux->segment.applied_rate, GST_FORMAT_TIME, start, stop, time); - GST_EVENT_SRC (demux->segment_event) = gst_object_ref (demux); + + demux->segment_event = gst_event_new_segment (&new_segment); } push_new_segment: @@ -1497,16 +1446,17 @@ static GstFlowReturn gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) { GstFlowReturn res = GST_FLOW_OK; + GList *tmp; MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; - /* MpegTSBase *base = (MpegTSBase*) demux; */ - GstBuffer *firstbuffer = NULL; MpegTSPacketizer2 *packetizer = MPEG_TS_BASE_PACKETIZER (demux); + GstBuffer *buf; + GstClockTime ts; GST_DEBUG_OBJECT (stream->pad, "stream:%p, pid:0x%04x stream_type:%d state:%d", stream, bs->pid, bs->stream_type, stream->state); - if (G_UNLIKELY (stream->current == NULL)) { + if (G_UNLIKELY (stream->currentlist == NULL)) { GST_LOG ("stream->current == NULL"); goto beach; } @@ -1527,8 +1477,7 @@ 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); + stream->currentlist = NULL; goto beach; } @@ -1538,24 +1487,32 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) /* We have a confirmed buffer, let's push it out */ GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList"); stream->currentlist = g_list_reverse (stream->currentlist); - gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist); - stream->currentlist = NULL; - gst_buffer_list_iterator_free (stream->currentit); + buf = gst_buffer_make_writable ((GstBuffer *) stream->currentlist->data); - firstbuffer = gst_buffer_list_get (stream->current, 0, 0); + ts = GST_BUFFER_PTS (buf); GST_DEBUG_OBJECT (stream->pad, "stream->pts %" GST_TIME_FORMAT, GST_TIME_ARGS (stream->pts)); if (GST_CLOCK_TIME_IS_VALID (stream->pts) - && !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (firstbuffer))) - GST_BUFFER_TIMESTAMP (firstbuffer) = - mpegts_packetizer_pts_to_ts (packetizer, stream->pts); + && !GST_CLOCK_TIME_IS_VALID (ts)) + ts = mpegts_packetizer_pts_to_ts (packetizer, stream->pts); + + for (tmp = stream->currentlist->next; tmp; tmp = tmp->next) { + gst_buffer_copy_into (buf, (GstBuffer *) tmp->data, GST_BUFFER_COPY_MEMORY, + 0, -1); + gst_buffer_unref ((GstBuffer *) tmp->data); + } + g_list_free (stream->currentlist); + stream->currentlist = NULL; + + GST_BUFFER_PTS (buf) = ts; + GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT); GST_DEBUG_OBJECT (stream->pad, "Pushing buffer list with timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (firstbuffer))); + GST_TIME_ARGS (GST_BUFFER_PTS (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)); @@ -1566,11 +1523,13 @@ beach: stream->state = PENDING_PACKET_EMPTY; memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS); stream->nbpending = 0; - stream->current = NULL; - stream->currentit = NULL; - stream->currentlist = NULL; stream->expected_size = 0; stream->current_size = 0; + if (stream->currentlist) { + g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL); + g_list_free (stream->currentlist); + } + stream->currentlist = NULL; return res; } @@ -1581,8 +1540,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, @@ -1590,8 +1551,8 @@ gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream, packet->continuity_counter, packet->payload); if (section) { - GST_DEBUG ("section complete:%d, buffer size %d", - section->complete, GST_BUFFER_SIZE (section->buffer)); + GST_DEBUG ("section complete:%d, buffer size %" G_GSIZE_FORMAT, + section->complete, gst_buffer_get_size (section->buffer)); gst_buffer_unref (packet->buffer); return res; } |