mpegtsdemux: Revert to 0.10 state as this is unmergeable, also put it into the non-ported plugins again

This commit is contained in:
Sebastian Dröge 2012-03-29 17:55:09 +02:00
parent 88b833a925
commit a1c291ebb6
7 changed files with 330 additions and 455 deletions

View file

@ -321,7 +321,7 @@ GST_PLUGINS_NONPORTED=" aiff asfmux \
apexsink cdaudio cog curl dc1394 dirac directfb resindvd \ apexsink cdaudio cog curl dc1394 dirac directfb resindvd \
gsettings jp2k ladspa mimic \ gsettings jp2k ladspa mimic \
musepack musicbrainz nas neon ofa openal opencv rsvg sdl sndfile soundtouch spandsp spc timidity \ musepack musicbrainz nas neon ofa openal opencv rsvg sdl sndfile soundtouch spandsp spc timidity \
wildmidi xvid lv2 teletextdec dvb" wildmidi xvid lv2 teletextdec dvb mpegtsdemux"
AC_SUBST(GST_PLUGINS_NONPORTED) AC_SUBST(GST_PLUGINS_NONPORTED)
dnl these are all the gst plug-ins, compilable without additional libs dnl these are all the gst plug-ins, compilable without additional libs

View file

@ -81,35 +81,22 @@ static void mpegts_base_dispose (GObject * object);
static void mpegts_base_finalize (GObject * object); static void mpegts_base_finalize (GObject * object);
static void mpegts_base_free_program (MpegTSBaseProgram * program); static void mpegts_base_free_program (MpegTSBaseProgram * program);
static void mpegts_base_free_stream (MpegTSBaseStream * ptream); static void mpegts_base_free_stream (MpegTSBaseStream * ptream);
static gboolean mpegts_base_sink_activate (GstPad * pad, GstObject * parent); static gboolean mpegts_base_sink_activate (GstPad * pad);
static gboolean mpegts_base_sink_activate_mode (GstPad * pad, static gboolean mpegts_base_sink_activate_pull (GstPad * pad, gboolean active);
GstObject * parent, GstPadMode mode, gboolean active); static gboolean mpegts_base_sink_activate_push (GstPad * pad, gboolean active);
static GstFlowReturn mpegts_base_chain (GstPad * pad, GstObject * parent, static GstFlowReturn mpegts_base_chain (GstPad * pad, GstBuffer * buf);
GstBuffer * buf); static gboolean mpegts_base_sink_event (GstPad * pad, GstEvent * event);
static gboolean mpegts_base_sink_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static GstStateChangeReturn mpegts_base_change_state (GstElement * element, static GstStateChangeReturn mpegts_base_change_state (GstElement * element,
GstStateChange transition); GstStateChange transition);
static void _extra_init (GType type);
static void mpegts_base_get_tags_from_sdt (MpegTSBase * base, static void mpegts_base_get_tags_from_sdt (MpegTSBase * base,
GstStructure * sdt_info); GstStructure * sdt_info);
static void mpegts_base_get_tags_from_eit (MpegTSBase * base, static void mpegts_base_get_tags_from_eit (MpegTSBase * base,
GstStructure * eit_info); GstStructure * eit_info);
static void GST_BOILERPLATE_FULL (MpegTSBase, mpegts_base, GstElement, GST_TYPE_ELEMENT,
_extra_init (void) _extra_init);
{
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] = { static const guint32 crc_tab[256] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
@ -170,6 +157,25 @@ mpegts_base_calc_crc32 (guint8 * data, guint datalen)
return crc; 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_static_pad_template (element_class, &sink_template);
}
static void static void
mpegts_base_class_init (MpegTSBaseClass * klass) mpegts_base_class_init (MpegTSBaseClass * klass)
{ {
@ -179,14 +185,12 @@ mpegts_base_class_init (MpegTSBaseClass * klass)
element_class = GST_ELEMENT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass);
element_class->change_state = mpegts_base_change_state; 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 = G_OBJECT_CLASS (klass);
gobject_class->set_property = mpegts_base_set_property; gobject_class->set_property = mpegts_base_set_property;
gobject_class->get_property = mpegts_base_get_property; gobject_class->get_property = mpegts_base_get_property;
gobject_class->dispose = mpegts_base_dispose; gobject_class->dispose = mpegts_base_dispose;
gobject_class->finalize = mpegts_base_finalize; gobject_class->finalize = mpegts_base_finalize;
} }
static void static void
@ -222,20 +226,19 @@ mpegts_base_reset (MpegTSBase * base)
base->upstream_live = FALSE; base->upstream_live = FALSE;
base->queried_latency = FALSE; base->queried_latency = FALSE;
base->upstream_live = FALSE;
base->query_latency = FALSE;
if (klass->reset) if (klass->reset)
klass->reset (base); klass->reset (base);
} }
static void static void
mpegts_base_init (MpegTSBase * base) mpegts_base_init (MpegTSBase * base, MpegTSBaseClass * klass)
{ {
base->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); 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_activate_function (base->sinkpad, mpegts_base_sink_activate);
gst_pad_set_activatemode_function (base->sinkpad, gst_pad_set_activatepull_function (base->sinkpad,
mpegts_base_sink_activate_mode); mpegts_base_sink_activate_pull);
gst_pad_set_activatepush_function (base->sinkpad,
mpegts_base_sink_activate_push);
gst_pad_set_chain_function (base->sinkpad, mpegts_base_chain); gst_pad_set_chain_function (base->sinkpad, mpegts_base_chain);
gst_pad_set_event_function (base->sinkpad, mpegts_base_sink_event); gst_pad_set_event_function (base->sinkpad, mpegts_base_sink_event);
gst_element_add_pad (GST_ELEMENT (base), base->sinkpad); gst_element_add_pad (GST_ELEMENT (base), base->sinkpad);
@ -486,30 +489,21 @@ mpegts_base_free_program (MpegTSBaseProgram * program)
/* FIXME : This is being called by tsdemux::find_timestamps() /* FIXME : This is being called by tsdemux::find_timestamps()
* We need to avoid re-entrant code like that */ * 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 void
mpegts_base_remove_program (MpegTSBase * base, gint program_number) mpegts_base_remove_program (MpegTSBase * base, gint program_number)
{ {
MpegTSBaseProgram *program; MpegTSBaseProgram *program;
MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base);
program = GST_DEBUG_OBJECT (base, "program_number : %d", program_number);
(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)); g_hash_table_remove (base->programs, GINT_TO_POINTER (program_number));
} }
@ -1056,15 +1050,11 @@ mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section)
/* table ids 0x70 - 0x73 do not have a crc */ /* table ids 0x70 - 0x73 do not have a crc */
if (G_LIKELY (section->table_id < 0x70 || section->table_id > 0x73)) { if (G_LIKELY (section->table_id < 0x70 || section->table_id > 0x73)) {
GstMapInfo map; if (G_UNLIKELY (mpegts_base_calc_crc32 (GST_BUFFER_DATA (section->buffer),
GST_BUFFER_SIZE (section->buffer)) != 0)) {
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); GST_WARNING_OBJECT (base, "bad crc in psi pid 0x%x", section->pid);
return FALSE; return FALSE;
} }
gst_buffer_unmap (section->buffer, &map);
} }
switch (section->table_id) { switch (section->table_id) {
@ -1199,7 +1189,7 @@ mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info)
program = mpegts_base_get_program (base, program_number); program = mpegts_base_get_program (base, program_number);
if (program && !program->tags) { if (program && !program->tags) {
program->tags = gst_tag_list_new (GST_TAG_ARTIST, program->tags = gst_tag_list_new_full (GST_TAG_ARTIST,
gst_structure_get_string (service, "name"), NULL); gst_structure_get_string (service, "name"), NULL);
} }
} }
@ -1240,33 +1230,27 @@ mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info)
gst_structure_get_uint (event, "duration", &duration); gst_structure_get_uint (event, "duration", &duration);
program->event_id = event_id; program->event_id = event_id;
program->tags = gst_tag_list_new (GST_TAG_TITLE, program->tags = gst_tag_list_new_full (GST_TAG_TITLE,
title, GST_TAG_DURATION, duration * GST_SECOND, NULL); title, GST_TAG_DURATION, duration * GST_SECOND, NULL);
} }
} }
} }
} }
static gboolean static void
remove_each_program (gpointer key, MpegTSBaseProgram * program, remove_each_program (gpointer key, MpegTSBaseProgram * program,
MpegTSBase * base) MpegTSBase * base)
{ {
/* First deactivate it */ /* First deactivate it */
mpegts_base_deactivate_program (base, program); mpegts_base_deactivate_program (base, program);
/* Then remove it */
/* Then stop it */ mpegts_base_remove_program (base, program->program_number);
mpegts_base_stop_program (base, program);
/* And tell _foreach_remove() to remove it */
return TRUE;
} }
static gboolean static gboolean
gst_mpegts_base_handle_eos (MpegTSBase * base) gst_mpegts_base_handle_eos (MpegTSBase * base)
{ {
g_hash_table_foreach_remove (base->programs, (GHRFunc) remove_each_program, g_hash_table_foreach (base->programs, (GHFunc) remove_each_program, base);
base);
/* finally remove */ /* finally remove */
return TRUE; return TRUE;
} }
@ -1284,27 +1268,37 @@ mpegts_base_flush (MpegTSBase * base)
} }
static gboolean static gboolean
mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) mpegts_base_sink_event (GstPad * pad, GstEvent * event)
{ {
gboolean res = TRUE; gboolean res = TRUE;
MpegTSBase *base = GST_MPEGTS_BASE (parent); MpegTSBase *base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad)));
GST_WARNING_OBJECT (base, "Got event %s", GST_WARNING_OBJECT (base, "Got event %s",
gst_event_type_get_name (GST_EVENT_TYPE (event))); gst_event_type_get_name (GST_EVENT_TYPE (event)));
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEGMENT: case GST_EVENT_NEWSEGMENT:
gst_event_copy_segment (event, &base->segment); {
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);
gst_event_unref (event); gst_event_unref (event);
}
break; break;
case GST_EVENT_EOS: case GST_EVENT_EOS:
res = gst_mpegts_base_handle_eos (base); res = gst_mpegts_base_handle_eos (base);
gst_event_unref (event);
break;
case GST_EVENT_CAPS:
/* FIXME, do something */
gst_event_unref (event);
break; break;
case GST_EVENT_FLUSH_START: case GST_EVENT_FLUSH_START:
mpegts_packetizer_flush (base->packetizer); mpegts_packetizer_flush (base->packetizer);
@ -1321,7 +1315,7 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
gst_event_unref (event); gst_event_unref (event);
} }
GST_DEBUG ("Returning %d", res); gst_object_unref (base);
return res; return res;
} }
@ -1357,7 +1351,7 @@ mpegts_base_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
} }
static GstFlowReturn static GstFlowReturn
mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) mpegts_base_chain (GstPad * pad, GstBuffer * buf)
{ {
GstFlowReturn res = GST_FLOW_OK; GstFlowReturn res = GST_FLOW_OK;
MpegTSBase *base; MpegTSBase *base;
@ -1366,7 +1360,7 @@ mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
MpegTSPacketizer2 *packetizer; MpegTSPacketizer2 *packetizer;
MpegTSPacketizerPacket packet; MpegTSPacketizerPacket packet;
base = GST_MPEGTS_BASE (parent); base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad)));
packetizer = base->packetizer; packetizer = base->packetizer;
if (G_UNLIKELY (base->queried_latency == FALSE)) { if (G_UNLIKELY (base->queried_latency == FALSE)) {
@ -1374,26 +1368,16 @@ mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
} }
mpegts_packetizer_push (base->packetizer, buf); mpegts_packetizer_push (base->packetizer, buf);
while (((pret = mpegts_packetizer_next_packet (base->packetizer,
while (res == GST_FLOW_OK) { &packet)) != PACKET_NEED_MORE) && 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;
/* bad header, skip the packet */
if (G_UNLIKELY (pret == PACKET_BAD)) if (G_UNLIKELY (pret == PACKET_BAD))
/* bad header, skip the packet */
goto next; goto next;
GST_DEBUG ("Got packet (buffer:%p)", packet.buffer);
/* base PSI data */ /* base PSI data */
if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) { if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) {
MpegTSPacketizerSection section; MpegTSPacketizerSection section;
based = mpegts_packetizer_push_section (packetizer, &packet, &section); based = mpegts_packetizer_push_section (packetizer, &packet, &section);
if (G_UNLIKELY (!based)) if (G_UNLIKELY (!based))
/* bad section data */ /* bad section data */
goto next; goto next;
@ -1401,28 +1385,26 @@ mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
if (G_LIKELY (section.complete)) { if (G_LIKELY (section.complete)) {
/* section complete */ /* section complete */
based = mpegts_base_handle_psi (base, &section); based = mpegts_base_handle_psi (base, &section);
GST_DEBUG ("Unreffing section buffer %p", section.buffer);
gst_buffer_unref (section.buffer); gst_buffer_unref (section.buffer);
if (G_UNLIKELY (!based)) if (G_UNLIKELY (!based))
/* bad PSI table */ /* bad PSI table */
goto next; goto next;
} }
/* we need to push section packet downstream */ /* we need to push section packet downstream */
res = mpegts_base_push (base, &packet, &section); res = mpegts_base_push (base, &packet, &section);
} else if (MPEGTS_BIT_IS_SET (base->is_pes, packet.pid)) { } else if (MPEGTS_BIT_IS_SET (base->is_pes, packet.pid)) {
/* push the packet downstream */ /* push the packet downstream */
res = mpegts_base_push (base, &packet, NULL); res = mpegts_base_push (base, &packet, NULL);
} else { } else
gst_buffer_unref (packet.buffer); gst_buffer_unref (packet.buffer);
}
next: next:
mpegts_packetizer_clear_packet (base->packetizer, &packet); mpegts_packetizer_clear_packet (base->packetizer, &packet);
} }
gst_object_unref (base);
return res; return res;
} }
@ -1519,7 +1501,6 @@ mpegts_base_scan (MpegTSBase * base)
} }
beach: beach:
GST_DEBUG ("Returning %s", gst_flow_get_name (ret));
mpegts_packetizer_clear (base->packetizer); mpegts_packetizer_clear (base->packetizer);
return ret; return ret;
@ -1535,7 +1516,6 @@ static void
mpegts_base_loop (MpegTSBase * base) mpegts_base_loop (MpegTSBase * base)
{ {
GstFlowReturn ret = GST_FLOW_ERROR; GstFlowReturn ret = GST_FLOW_ERROR;
switch (base->mode) { switch (base->mode) {
case BASE_MODE_SCANNING: case BASE_MODE_SCANNING:
/* Find first sync point */ /* Find first sync point */
@ -1551,7 +1531,7 @@ mpegts_base_loop (MpegTSBase * base)
break; break;
case BASE_MODE_STREAMING: case BASE_MODE_STREAMING:
{ {
GstBuffer *buf = NULL; GstBuffer *buf;
GST_DEBUG ("Pulling data from %" G_GUINT64_FORMAT, base->seek_offset); GST_DEBUG ("Pulling data from %" G_GUINT64_FORMAT, base->seek_offset);
@ -1559,8 +1539,8 @@ mpegts_base_loop (MpegTSBase * base)
100 * base->packetsize, &buf); 100 * base->packetsize, &buf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) if (G_UNLIKELY (ret != GST_FLOW_OK))
goto error; goto error;
base->seek_offset += gst_buffer_get_size (buf); base->seek_offset += GST_BUFFER_SIZE (buf);
ret = mpegts_base_chain (base->sinkpad, GST_OBJECT_CAST (base), buf); ret = mpegts_base_chain (base->sinkpad, buf);
if (G_UNLIKELY (ret != GST_FLOW_OK)) if (G_UNLIKELY (ret != GST_FLOW_OK))
goto error; goto error;
} }
@ -1575,9 +1555,8 @@ mpegts_base_loop (MpegTSBase * base)
error: error:
{ {
const gchar *reason = gst_flow_get_name (ret); const gchar *reason = gst_flow_get_name (ret);
GST_DEBUG_OBJECT (base, "Pausing task, reason %s", reason); GST_DEBUG_OBJECT (base, "Pausing task, reason %s", reason);
if (ret == GST_FLOW_EOS) { if (ret == GST_FLOW_UNEXPECTED) {
/* Push EOS downstream */ /* Push EOS downstream */
if (!GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, if (!GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base,
gst_event_new_eos ())) { gst_event_new_eos ())) {
@ -1586,7 +1565,7 @@ error:
("got eos but no streams (yet)")); ("got eos but no streams (yet)"));
} }
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) {
GST_ELEMENT_ERROR (base, STREAM, FAILED, GST_ELEMENT_ERROR (base, STREAM, FAILED,
(_("Internal data stream error.")), (_("Internal data stream error.")),
("stream stopped, reason %s", reason)); ("stream stopped, reason %s", reason));
@ -1652,7 +1631,7 @@ mpegts_base_handle_seek_event (MpegTSBase * base, GstPad * pad,
if (flush) { if (flush) {
/* send a FLUSH_STOP for the sinkpad, since we need data for seeking */ /* send a FLUSH_STOP for the sinkpad, since we need data for seeking */
GST_DEBUG_OBJECT (base, "sending flush stop"); GST_DEBUG_OBJECT (base, "sending flush stop");
gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop (TRUE)); gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop ());
/* And actually flush our pending data */ /* And actually flush our pending data */
mpegts_base_flush (base); mpegts_base_flush (base);
mpegts_packetizer_flush (base->packetizer); mpegts_packetizer_flush (base->packetizer);
@ -1681,7 +1660,7 @@ mpegts_base_handle_seek_event (MpegTSBase * base, GstPad * pad,
GST_DEBUG_OBJECT (base, "sending flush stop"); 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 ());
GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base,
gst_event_new_flush_stop (TRUE)); gst_event_new_flush_stop ());
} }
//else //else
done: done:
@ -1693,63 +1672,39 @@ push_mode:
static gboolean static gboolean
mpegts_base_sink_activate (GstPad * sinkpad, GstObject * parent) mpegts_base_sink_activate (GstPad * pad)
{ {
GstQuery *query; if (gst_pad_check_pull_range (pad)) {
gboolean pull_mode; GST_DEBUG_OBJECT (pad, "activating pull");
return gst_pad_activate_pull (pad, TRUE);
query = gst_query_new_scheduling (); } else {
GST_DEBUG_OBJECT (pad, "activating push");
if (!gst_pad_peer_query (sinkpad, query)) { return gst_pad_activate_push (pad, TRUE);
gst_query_unref (query);
goto activate_push;
}
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 static gboolean
mpegts_base_sink_activate_mode (GstPad * pad, GstObject * parent, mpegts_base_sink_activate_pull (GstPad * pad, gboolean active)
GstPadMode mode, gboolean active)
{ {
gboolean res; MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad));
MpegTSBase *base = GST_MPEGTS_BASE (parent); if (active) {
base->mode = BASE_MODE_SCANNING;
switch (mode) { base->packetizer->calculate_offset = TRUE;
case GST_PAD_MODE_PUSH: return gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, base);
base->mode = BASE_MODE_PUSHING; } else
base->packetizer->calculate_skew = TRUE; return gst_pad_stop_task (pad);
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 gboolean
mpegts_base_sink_activate_push (GstPad * pad, gboolean active)
{
MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad));
base->mode = BASE_MODE_PUSHING;
base->packetizer->calculate_skew = TRUE;
return TRUE;
}
static GstStateChangeReturn static GstStateChangeReturn
mpegts_base_change_state (GstElement * element, GstStateChange transition) mpegts_base_change_state (GstElement * element, GstStateChange transition)
{ {

View file

@ -136,11 +136,6 @@ struct _MpegTSBase {
/* Whether we queried the upstream latency or not */ /* Whether we queried the upstream latency or not */
gboolean queried_latency; gboolean queried_latency;
/* Whether upstream is live or not */
gboolean upstream_live;
/* Whether we queried the upstream latency or not */
gboolean query_latency;
/* Upstream segment */ /* Upstream segment */
GstSegment segment; GstSegment segment;
}; };

View file

@ -357,8 +357,6 @@ mpegts_packetizer_parse_packet (MpegTSPacketizer2 * packetizer,
packet->data = data; packet->data = data;
gst_buffer_unmap (packet->buffer, &packet->bufmap);
if (packet->adaptation_field_control & 0x02) if (packet->adaptation_field_control & 0x02)
if (!mpegts_packetizer_parse_adaptation_field_control (packetizer, packet)) if (!mpegts_packetizer_parse_adaptation_field_control (packetizer, packet))
return FALSE; return FALSE;
@ -375,19 +373,16 @@ static gboolean
mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerStream * stream, MpegTSPacketizerSection * section) MpegTSPacketizerStream * stream, MpegTSPacketizerSection * section)
{ {
GstMapInfo map;
guint8 tmp; guint8 tmp;
guint8 *data, *crc_data; guint8 *data, *crc_data;
MpegTSPacketizerStreamSubtable *subtable; MpegTSPacketizerStreamSubtable *subtable;
GSList *subtable_list = NULL; GSList *subtable_list = NULL;
section->complete = TRUE; section->complete = TRUE;
/* get the section buffer, pass the ownership to the caller */ /* get the section buffer, pass the ownership to the caller */
section->buffer = gst_adapter_take_buffer (stream->section_adapter, section->buffer = gst_adapter_take_buffer (stream->section_adapter,
3 + stream->section_length); 3 + stream->section_length);
gst_buffer_map (section->buffer, &map, GST_MAP_READ); data = GST_BUFFER_DATA (section->buffer);
data = map.data;
GST_BUFFER_OFFSET (section->buffer) = stream->offset; GST_BUFFER_OFFSET (section->buffer) = stream->offset;
section->table_id = *data++; section->table_id = *data++;
@ -423,7 +418,8 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
goto not_applicable; goto not_applicable;
/* CRC is at the end of the section */ /* CRC is at the end of the section */
crc_data = map.data + map.size - 4; crc_data =
GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer) - 4;
section->crc = GST_READ_UINT32_BE (crc_data); section->crc = GST_READ_UINT32_BE (crc_data);
if (section->version_number == subtable->version_number && if (section->version_number == subtable->version_number &&
@ -434,8 +430,6 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
subtable->crc = section->crc; subtable->crc = section->crc;
stream->section_table_id = section->table_id; stream->section_table_id = section->table_id;
gst_buffer_unmap (section->buffer, &map);
return TRUE; return TRUE;
not_applicable: not_applicable:
@ -444,7 +438,6 @@ not_applicable:
section->pid, section->table_id, section->subtable_extension, section->pid, section->table_id, section->subtable_extension,
section->current_next_indicator, section->version_number, section->crc); section->current_next_indicator, section->version_number, section->crc);
section->complete = FALSE; section->complete = FALSE;
gst_buffer_unmap (section->buffer, &map);
gst_buffer_unref (section->buffer); gst_buffer_unref (section->buffer);
return TRUE; return TRUE;
} }
@ -498,7 +491,6 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerSection * section) MpegTSPacketizerSection * section)
{ {
GstStructure *pat_info = NULL; GstStructure *pat_info = NULL;
GstMapInfo map;
guint8 *data, *end; guint8 *data, *end;
guint transport_stream_id; guint transport_stream_id;
guint8 tmp; guint8 tmp;
@ -509,8 +501,7 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
GstStructure *entry = NULL; GstStructure *entry = NULL;
gchar *struct_name; gchar *struct_name;
gst_buffer_map (section->buffer, &map, GST_MAP_READ); data = GST_BUFFER_DATA (section->buffer);
data = map.data;
section->table_id = *data++; section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
@ -526,13 +517,11 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
/* skip section_number and last_section_number */ /* skip section_number and last_section_number */
data += 2; data += 2;
pat_info = gst_structure_new_id (QUARK_PAT, pat_info = gst_structure_id_new (QUARK_PAT,
QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, NULL); QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, NULL);
g_value_init (&entries, GST_TYPE_LIST); g_value_init (&entries, GST_TYPE_LIST);
/* stop at the CRC */ /* stop at the CRC */
end = map.data + map.size; end = GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer);
while (data < end - 4) { while (data < end - 4) {
program_number = GST_READ_UINT16_BE (data); program_number = GST_READ_UINT16_BE (data);
data += 2; data += 2;
@ -541,7 +530,7 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
data += 2; data += 2;
struct_name = g_strdup_printf ("program-%d", program_number); struct_name = g_strdup_printf ("program-%d", program_number);
entry = gst_structure_new_empty (struct_name); entry = gst_structure_new (struct_name, NULL);
g_free (struct_name); g_free (struct_name);
gst_structure_id_set (entry, QUARK_PROGRAM_NUMBER, G_TYPE_UINT, gst_structure_id_set (entry, QUARK_PROGRAM_NUMBER, G_TYPE_UINT,
program_number, QUARK_PID, G_TYPE_UINT, pmt_pid, NULL); program_number, QUARK_PID, G_TYPE_UINT, pmt_pid, NULL);
@ -555,8 +544,6 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
gst_structure_id_set_value (pat_info, QUARK_PROGRAMS, &entries); gst_structure_id_set_value (pat_info, QUARK_PROGRAMS, &entries);
g_value_unset (&entries); g_value_unset (&entries);
gst_buffer_unmap (section->buffer, &map);
if (data != end - 4) { if (data != end - 4) {
/* FIXME: check the CRC before parsing the packet */ /* FIXME: check the CRC before parsing the packet */
GST_ERROR ("at the end of PAT data != end - 4"); GST_ERROR ("at the end of PAT data != end - 4");
@ -573,7 +560,6 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerSection * section) MpegTSPacketizerSection * section)
{ {
GstStructure *pmt = NULL; GstStructure *pmt = NULL;
GstMapInfo map;
guint8 *data, *end; guint8 *data, *end;
guint16 program_number; guint16 program_number;
guint8 tmp; guint8 tmp;
@ -588,17 +574,15 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
GstStructure *stream_info = NULL; GstStructure *stream_info = NULL;
gchar *struct_name; gchar *struct_name;
gst_buffer_map (section->buffer, &map, GST_MAP_READ);
data = map.data;
/* fixed header + CRC == 16 */ /* fixed header + CRC == 16 */
if (map.size < 16) { if (GST_BUFFER_SIZE (section->buffer) < 16) {
GST_WARNING ("PID %d invalid PMT size %d", GST_WARNING ("PID %d invalid PMT size %d",
section->pid, section->section_length); section->pid, section->section_length);
goto error; goto error;
} }
end = map.data + map.size; data = GST_BUFFER_DATA (section->buffer);
end = data + GST_BUFFER_SIZE (section->buffer);
section->table_id = *data++; section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
@ -622,7 +606,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
program_info_length = GST_READ_UINT16_BE (data) & 0x0FFF; program_info_length = GST_READ_UINT16_BE (data) & 0x0FFF;
data += 2; data += 2;
pmt = gst_structure_new_id (QUARK_PMT, pmt = gst_structure_id_new (QUARK_PMT,
QUARK_PROGRAM_NUMBER, G_TYPE_UINT, program_number, QUARK_PROGRAM_NUMBER, G_TYPE_UINT, program_number,
QUARK_PCR_PID, G_TYPE_UINT, pcr_pid, QUARK_PCR_PID, G_TYPE_UINT, pcr_pid,
QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, NULL); QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, NULL);
@ -669,7 +653,7 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
} }
struct_name = g_strdup_printf ("pid-%d", pid); struct_name = g_strdup_printf ("pid-%d", pid);
stream_info = gst_structure_new_empty (struct_name); stream_info = gst_structure_new (struct_name, NULL);
g_free (struct_name); g_free (struct_name);
gst_structure_id_set (stream_info, gst_structure_id_set (stream_info,
QUARK_PID, G_TYPE_UINT, pid, QUARK_STREAM_TYPE, G_TYPE_UINT, QUARK_PID, G_TYPE_UINT, pid, QUARK_STREAM_TYPE, G_TYPE_UINT,
@ -771,8 +755,6 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
gst_structure_id_set_value (pmt, QUARK_STREAMS, &programs); gst_structure_id_set_value (pmt, QUARK_STREAMS, &programs);
g_value_unset (&programs); g_value_unset (&programs);
gst_buffer_unmap (section->buffer, &map);
g_assert (data == end - 4); g_assert (data == end - 4);
return pmt; return pmt;
@ -780,7 +762,6 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer,
error: error:
if (pmt) if (pmt)
gst_structure_free (pmt); gst_structure_free (pmt);
gst_buffer_unmap (section->buffer, &map);
return NULL; return NULL;
} }
@ -790,7 +771,6 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerSection * section) MpegTSPacketizerSection * section)
{ {
GstStructure *nit = NULL, *transport = NULL, *delivery_structure = NULL; GstStructure *nit = NULL, *transport = NULL, *delivery_structure = NULL;
GstMapInfo map;
guint8 *data, *end, *entry_begin; guint8 *data, *end, *entry_begin;
guint16 network_id, transport_stream_id, original_network_id; guint16 network_id, transport_stream_id, original_network_id;
guint tmp; guint tmp;
@ -800,18 +780,15 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
GValueArray *descriptors = NULL; GValueArray *descriptors = NULL;
GST_DEBUG ("NIT"); GST_DEBUG ("NIT");
gst_buffer_map (section->buffer, &map, GST_MAP_READ);
data = map.data;
/* fixed header + CRC == 16 */ /* fixed header + CRC == 16 */
if (map.size < 23) { if (GST_BUFFER_SIZE (section->buffer) < 23) {
GST_WARNING ("PID %d invalid NIT size %d", GST_WARNING ("PID %d invalid NIT size %d",
section->pid, section->section_length); section->pid, section->section_length);
goto error; goto error;
} }
end = map.data + map.size; data = GST_BUFFER_DATA (section->buffer);
end = data + GST_BUFFER_SIZE (section->buffer);
section->table_id = *data++; section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
@ -836,7 +813,7 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF;
data += 2; data += 2;
nit = gst_structure_new_id (QUARK_NIT, nit = gst_structure_id_new (QUARK_NIT,
QUARK_NETWORK_ID, G_TYPE_UINT, network_id, QUARK_NETWORK_ID, G_TYPE_UINT, network_id,
QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number,
QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT,
@ -914,7 +891,7 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
data += 2; data += 2;
transport_name = g_strdup_printf ("transport-%d", transport_stream_id); transport_name = g_strdup_printf ("transport-%d", transport_stream_id);
transport = gst_structure_new_empty (transport_name); transport = gst_structure_new (transport_name, NULL);
g_free (transport_name); g_free (transport_name);
gst_structure_id_set (transport, gst_structure_id_set (transport,
QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id,
@ -1399,16 +1376,15 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
} }
if (data != end - 4) { if (data != end - 4) {
GST_WARNING ("PID %d invalid NIT parsed %d length %" G_GSIZE_FORMAT, GST_WARNING ("PID %d invalid NIT parsed %d length %d",
section->pid, (gint) (data - map.data), map.size); section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)),
GST_BUFFER_SIZE (section->buffer));
goto error; goto error;
} }
gst_structure_id_set_value (nit, QUARK_TRANSPORTS, &transports); gst_structure_id_set_value (nit, QUARK_TRANSPORTS, &transports);
g_value_unset (&transports); g_value_unset (&transports);
gst_buffer_unmap (section->buffer, &map);
GST_DEBUG ("NIT %" GST_PTR_FORMAT, nit); GST_DEBUG ("NIT %" GST_PTR_FORMAT, nit);
return nit; return nit;
@ -1417,8 +1393,6 @@ error:
if (nit) if (nit)
gst_structure_free (nit); gst_structure_free (nit);
gst_buffer_unmap (section->buffer, &map);
if (GST_VALUE_HOLDS_LIST (&transports)) if (GST_VALUE_HOLDS_LIST (&transports))
g_value_unset (&transports); g_value_unset (&transports);
@ -1429,7 +1403,6 @@ GstStructure *
mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerSection * section) MpegTSPacketizerSection * section)
{ {
GstMapInfo map;
GstStructure *sdt = NULL, *service = NULL; GstStructure *sdt = NULL, *service = NULL;
guint8 *data, *end, *entry_begin; guint8 *data, *end, *entry_begin;
guint16 transport_stream_id, original_network_id, service_id; guint16 transport_stream_id, original_network_id, service_id;
@ -1443,18 +1416,15 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
GValue service_value = { 0 }; GValue service_value = { 0 };
GST_DEBUG ("SDT"); GST_DEBUG ("SDT");
gst_buffer_map (section->buffer, &map, GST_MAP_READ);
data = map.data;
/* fixed header + CRC == 16 */ /* fixed header + CRC == 16 */
if (map.size < 14) { if (GST_BUFFER_SIZE (section->buffer) < 14) {
GST_WARNING ("PID %d invalid SDT size %d", GST_WARNING ("PID %d invalid SDT size %d",
section->pid, section->section_length); section->pid, section->section_length);
goto error; goto error;
} }
end = map.data + map.size; data = GST_BUFFER_DATA (section->buffer);
end = data + GST_BUFFER_SIZE (section->buffer);
section->table_id = *data++; section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
@ -1482,7 +1452,7 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
/* skip reserved byte */ /* skip reserved byte */
data += 1; data += 1;
sdt = gst_structure_new_id (QUARK_SDT, sdt = gst_structure_id_new (QUARK_SDT,
QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id,
QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number,
QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT,
@ -1521,7 +1491,7 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
/* TODO send tag event down relevant pad for channel name and provider */ /* TODO send tag event down relevant pad for channel name and provider */
service_name = g_strdup_printf ("service-%d", service_id); service_name = g_strdup_printf ("service-%d", service_id);
service = gst_structure_new_empty (service_name); service = gst_structure_new (service_name, NULL);
g_free (service_name); g_free (service_name);
if (descriptors_loop_length) { if (descriptors_loop_length) {
@ -1611,24 +1581,21 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
} }
if (data != end - 4) { if (data != end - 4) {
GST_WARNING ("PID %d invalid SDT parsed %d length %" G_GSIZE_FORMAT, GST_WARNING ("PID %d invalid SDT parsed %d length %d",
section->pid, (gint) (data - map.data), map.size); section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)),
GST_BUFFER_SIZE (section->buffer));
goto error; goto error;
} }
gst_structure_id_set_value (sdt, QUARK_SERVICES, &services); gst_structure_id_set_value (sdt, QUARK_SERVICES, &services);
g_value_unset (&services); g_value_unset (&services);
gst_buffer_unmap (section->buffer, &map);
return sdt; return sdt;
error: error:
if (sdt) if (sdt)
gst_structure_free (sdt); gst_structure_free (sdt);
gst_buffer_unmap (section->buffer, &map);
if (GST_VALUE_HOLDS_LIST (&services)) if (GST_VALUE_HOLDS_LIST (&services))
g_value_unset (&services); g_value_unset (&services);
@ -1647,7 +1614,6 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
guint16 mjd; guint16 mjd;
guint year, month, day, hour, minute, second; guint year, month, day, hour, minute, second;
guint duration; guint duration;
GstMapInfo map;
guint8 *data, *end, *duration_ptr, *utc_ptr; guint8 *data, *end, *duration_ptr, *utc_ptr;
guint16 descriptors_loop_length; guint16 descriptors_loop_length;
GValue events = { 0 }; GValue events = { 0 };
@ -1656,17 +1622,15 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
gchar *event_name; gchar *event_name;
guint tmp; guint tmp;
gst_buffer_map (section->buffer, &map, GST_MAP_READ);
data = map.data;
/* fixed header + CRC == 16 */ /* fixed header + CRC == 16 */
if (map.size < 18) { if (GST_BUFFER_SIZE (section->buffer) < 18) {
GST_WARNING ("PID %d invalid EIT size %d", GST_WARNING ("PID %d invalid EIT size %d",
section->pid, section->section_length); section->pid, section->section_length);
goto error; goto error;
} }
end = map.data + map.size; data = GST_BUFFER_DATA (section->buffer);
end = data + GST_BUFFER_SIZE (section->buffer);
section->table_id = *data++; section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
@ -1697,7 +1661,7 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
last_table_id = *data; last_table_id = *data;
data += 1; data += 1;
eit = gst_structure_new_id (QUARK_EIT, eit = gst_structure_id_new (QUARK_EIT,
QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number,
QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT,
section->current_next_indicator, QUARK_SERVICE_ID, G_TYPE_UINT, section->current_next_indicator, QUARK_SERVICE_ID, G_TYPE_UINT,
@ -2076,16 +2040,15 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
} }
if (data != end - 4) { if (data != end - 4) {
GST_WARNING ("PID %d invalid EIT parsed %d length %" G_GSIZE_FORMAT, GST_WARNING ("PID %d invalid EIT parsed %d length %d",
section->pid, (gint) (data - map.data), map.size); section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)),
GST_BUFFER_SIZE (section->buffer));
goto error; goto error;
} }
gst_structure_id_set_value (eit, QUARK_EVENTS, &events); gst_structure_id_set_value (eit, QUARK_EVENTS, &events);
g_value_unset (&events); g_value_unset (&events);
gst_buffer_unmap (section->buffer, &map);
GST_DEBUG ("EIT %" GST_PTR_FORMAT, eit); GST_DEBUG ("EIT %" GST_PTR_FORMAT, eit);
return eit; return eit;
@ -2094,8 +2057,6 @@ error:
if (eit) if (eit)
gst_structure_free (eit); gst_structure_free (eit);
gst_buffer_unmap (section->buffer, &map);
if (GST_VALUE_HOLDS_LIST (&events)) if (GST_VALUE_HOLDS_LIST (&events))
g_value_unset (&events); g_value_unset (&events);
@ -2109,22 +2070,18 @@ mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer,
GstStructure *tdt = NULL; GstStructure *tdt = NULL;
guint16 mjd; guint16 mjd;
guint year, month, day, hour, minute, second; guint year, month, day, hour, minute, second;
GstMapInfo map;
guint8 *data, *end, *utc_ptr; guint8 *data, *end, *utc_ptr;
GST_DEBUG ("TDT"); GST_DEBUG ("TDT");
gst_buffer_map (section->buffer, &map, GST_MAP_READ);
data = map.data;
/* length always 8 */ /* length always 8 */
if (G_UNLIKELY (map.size != 8)) { if (G_UNLIKELY (GST_BUFFER_SIZE (section->buffer) != 8)) {
GST_WARNING ("PID %d invalid TDT size %d", GST_WARNING ("PID %d invalid TDT size %d",
section->pid, section->section_length); section->pid, section->section_length);
goto error; goto error;
} }
end = map.data + map.size; data = GST_BUFFER_DATA (section->buffer);
end = data + GST_BUFFER_SIZE (section->buffer);
section->table_id = *data++; section->table_id = *data++;
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
@ -2165,16 +2122,12 @@ mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer,
"hour", G_TYPE_UINT, hour, "hour", G_TYPE_UINT, hour,
"minute", G_TYPE_UINT, minute, "second", G_TYPE_UINT, second, NULL); "minute", G_TYPE_UINT, minute, "second", G_TYPE_UINT, second, NULL);
gst_buffer_unmap (section->buffer, &map);
return tdt; return tdt;
error: error:
if (tdt) if (tdt)
gst_structure_free (tdt); gst_structure_free (tdt);
gst_buffer_unmap (section->buffer, &map);
return NULL; return NULL;
} }
@ -2252,8 +2205,8 @@ mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer)
packetizer->offset = GST_BUFFER_OFFSET (buffer); packetizer->offset = GST_BUFFER_OFFSET (buffer);
} }
GST_DEBUG ("Pushing %" G_GSIZE_FORMAT " byte from offset %" G_GUINT64_FORMAT, GST_DEBUG ("Pushing %u byte from offset %" G_GUINT64_FORMAT,
gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer)); GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
gst_adapter_push (packetizer->adapter, buffer); gst_adapter_push (packetizer->adapter, buffer);
} }
@ -2348,82 +2301,74 @@ mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer,
packet->buffer = NULL; packet->buffer = NULL;
/* Resync if needed */
if (G_UNLIKELY (!packetizer->know_packet_size)) { if (G_UNLIKELY (!packetizer->know_packet_size)) {
if (!mpegts_try_discover_packet_size (packetizer)) if (!mpegts_try_discover_packet_size (packetizer))
return PACKET_NEED_MORE; return PACKET_NEED_MORE;
} }
while ((avail = packetizer->adapter->size) >= packetizer->packet_size) { while ((avail = packetizer->adapter->size) >= packetizer->packet_size) {
guint i;
GstBuffer *tmpbuf;
guint8 *bufdata;
packet->buffer = gst_adapter_take_buffer (packetizer->adapter, packet->buffer = gst_adapter_take_buffer (packetizer->adapter,
packetizer->packet_size); 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 */ /* M2TS packets don't start with the sync byte, all other variants do */
if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) {
packet->data_start += 4; packet->data_start = GST_BUFFER_DATA (packet->buffer) + 4;
} else {
packet->data_start = GST_BUFFER_DATA (packet->buffer);
}
/* ALL mpeg-ts variants contain 188 bytes of data. Those with bigger packet /* ALL mpeg-ts variants contain 188 bytes of data. Those with bigger packet
* sizes contain either extra data (timesync, FEC, ..) either before or after * sizes contain either extra data (timesync, FEC, ..) either before or after
* the data */ * the data */
packet->data_end = packet->data_start + 188; packet->data_end = packet->data_start + 188;
GST_BUFFER_OFFSET (packet->buffer) = packet->offset = packetizer->offset; GST_BUFFER_OFFSET (packet->buffer) = packet->offset = packetizer->offset;
GST_DEBUG ("offset %" G_GUINT64_FORMAT, packet->offset); GST_DEBUG ("offset %" G_GUINT64_FORMAT, packet->offset);
packetizer->offset += packetizer->packet_size; packetizer->offset += packetizer->packet_size;
GST_MEMDUMP ("buffer", bufdata, 16); GST_MEMDUMP ("buffer", GST_BUFFER_DATA (packet->buffer), 16);
GST_MEMDUMP ("data_start", packet->data_start, 16); GST_MEMDUMP ("data_start", packet->data_start, 16);
GST_BUFFER_TIMESTAMP (packet->buffer) = GST_BUFFER_TIMESTAMP (packet->buffer) =
gst_adapter_prev_timestamp (packetizer->adapter, NULL); gst_adapter_prev_timestamp (packetizer->adapter, NULL);
/* Check sync byte */ /* Check sync byte */
if (G_LIKELY (packet->data_start[0] == 0x47)) if (G_UNLIKELY (packet->data_start[0] != 0x47)) {
goto got_valid_packet; guint i;
GstBuffer *tmpbuf;
GST_LOG ("Lost sync %d", packetizer->packet_size); 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;
}
/* Find the 0x47 in the buffer */ if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) {
for (i = 0; i < packetizer->packet_size; i++) if (i >= 4)
if (bufdata[i] == 0x47) i -= 4;
break; else
i += 188;
}
if (G_UNLIKELY (i == packetizer->packet_size)) { /* Pop out the remaining data... */
GST_ERROR ("REALLY lost the sync"); GST_BUFFER_DATA (packet->buffer) += i;
gst_buffer_unmap (packet->buffer, &packet->bufmap); GST_BUFFER_SIZE (packet->buffer) -= i;
gst_buffer_unref (packet->buffer); GST_BUFFER_OFFSET (packet->buffer) += i;
goto done; 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 (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) { return mpegts_packetizer_parse_packet (packetizer, packet);
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: done:
return PACKET_NEED_MORE; return PACKET_NEED_MORE;
got_valid_packet:
return mpegts_packetizer_parse_packet (packetizer, packet);
} }
MpegTSPacketizerPacketReturn MpegTSPacketizerPacketReturn
@ -2438,8 +2383,6 @@ void
mpegts_packetizer_clear_packet (MpegTSPacketizer2 * packetizer, mpegts_packetizer_clear_packet (MpegTSPacketizer2 * packetizer,
MpegTSPacketizerPacket * packet) MpegTSPacketizerPacket * packet)
{ {
GST_DEBUG ("packet:%p, buffer:%p", packet, packet->buffer);
memset (packet, 0, sizeof (MpegTSPacketizerPacket)); memset (packet, 0, sizeof (MpegTSPacketizerPacket));
} }
@ -2474,15 +2417,14 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer,
if (packet->pid == 0x14) { if (packet->pid == 0x14) {
table_id = data[0]; table_id = data[0];
section->section_length = GST_READ_UINT24_BE (data) & 0x000FFF; section->section_length = GST_READ_UINT24_BE (data) & 0x000FFF;
if (data - packet->bufmap.data + section->section_length + 3 > if (data - GST_BUFFER_DATA (packet->buffer) + section->section_length + 3 >
packet->bufmap.size) { GST_BUFFER_SIZE (packet->buffer)) {
GST_WARNING ("PID %dd PSI section length extends past the end " GST_WARNING ("PID %dd PSI section length extends past the end "
"of the buffer", packet->pid); "of the buffer", packet->pid);
goto out; goto out;
} }
section->buffer = section->buffer = gst_buffer_create_sub (packet->buffer,
gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL, data - GST_BUFFER_DATA (packet->buffer), section->section_length + 3);
data - packet->bufmap.data, section->section_length + 3);
section->table_id = table_id; section->table_id = table_id;
section->complete = TRUE; section->complete = TRUE;
res = TRUE; res = TRUE;
@ -2493,8 +2435,8 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer,
/* create a sub buffer from the start of the section (table_id and /* create a sub buffer from the start of the section (table_id and
* section_length included) to the end */ * section_length included) to the end */
sub_buf = gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL, sub_buf = gst_buffer_create_sub (packet->buffer,
data - packet->bufmap.data, packet->data_end - data); data - GST_BUFFER_DATA (packet->buffer), packet->data_end - data);
stream = packetizer->streams[packet->pid]; stream = packetizer->streams[packet->pid];
if (stream == NULL) { if (stream == NULL) {
@ -2518,11 +2460,10 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer,
if (stream->continuity_counter != CONTINUITY_UNSET) { if (stream->continuity_counter != CONTINUITY_UNSET) {
GST_DEBUG GST_DEBUG
("PID %d table_id %d sub_table_extension %d payload_unit_start_indicator set but section " ("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 %" "not complete (last_continuity: %d continuity: %d sec len %d buffer %d avail %d",
G_GSIZE_FORMAT " avail %" G_GSIZE_FORMAT, packet->pid, table_id, packet->pid, table_id, subtable_extension, stream->continuity_counter,
subtable_extension, stream->continuity_counter, packet->continuity_counter, section_length, GST_BUFFER_SIZE (sub_buf),
packet->continuity_counter, section_length, stream->section_adapter->size);
gst_buffer_get_size (sub_buf), stream->section_adapter->size);
mpegts_packetizer_clear_section (packetizer, stream); mpegts_packetizer_clear_section (packetizer, stream);
} else { } else {
GST_DEBUG GST_DEBUG

View file

@ -124,12 +124,9 @@ typedef struct
guint8 continuity_counter; guint8 continuity_counter;
guint8 *payload; guint8 *payload;
/* gst_buffer_map */ guint8 *data_start;
GstMapInfo bufmap;
guint8 *data_start; /* Location of 0x47 marker byte */
guint8 *data_end; guint8 *data_end;
guint8 *data; /* Location of post-TS-header data */ guint8 *data;
guint8 afc_flags; guint8 afc_flags;
guint64 pcr; guint64 pcr;
@ -179,7 +176,7 @@ MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *p
MpegTSPacketizerPacketReturn MpegTSPacketizerPacketReturn
mpegts_packetizer_process_next_packet(MpegTSPacketizer2 * packetizer); mpegts_packetizer_process_next_packet(MpegTSPacketizer2 * packetizer);
void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetizer, void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetizer,
MpegTSPacketizerPacket *packet); MpegTSPacketizerPacket *packet);
void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer, void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer,
gint16 pid); gint16 pid);

View file

@ -70,13 +70,13 @@ struct _MpegTSParsePad
}; };
static GstStaticPadTemplate src_template = static GstStaticPadTemplate src_template =
GST_STATIC_PAD_TEMPLATE ("src_%u", GST_PAD_SRC, GST_STATIC_PAD_TEMPLATE ("src%d", GST_PAD_SRC,
GST_PAD_REQUEST, GST_PAD_REQUEST,
GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
); );
static GstStaticPadTemplate program_template = static GstStaticPadTemplate program_template =
GST_STATIC_PAD_TEMPLATE ("program_%u", GST_PAD_SRC, GST_STATIC_PAD_TEMPLATE ("program_%d", GST_PAD_SRC,
GST_PAD_SOMETIMES, GST_PAD_SOMETIMES,
GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ")
); );
@ -113,14 +113,27 @@ static void mpegts_parse_reset_selected_programs (MpegTSParse2 * parse,
static void mpegts_parse_pad_removed (GstElement * element, GstPad * pad); static void mpegts_parse_pad_removed (GstElement * element, GstPad * pad);
static GstPad *mpegts_parse_request_new_pad (GstElement * element, static GstPad *mpegts_parse_request_new_pad (GstElement * element,
GstPadTemplate * templ, const gchar * name, const GstCaps * caps); GstPadTemplate * templ, const gchar * name);
static void mpegts_parse_release_pad (GstElement * element, GstPad * pad); static void mpegts_parse_release_pad (GstElement * element, GstPad * pad);
static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstObject * parent, static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query);
GstQuery * query);
static gboolean push_event (MpegTSBase * base, GstEvent * event); static gboolean push_event (MpegTSBase * base, GstEvent * event);
#define mpegts_parse_parent_class parent_class GST_BOILERPLATE (MpegTSParse2, mpegts_parse, MpegTSBase, GST_TYPE_MPEGTS_BASE);
G_DEFINE_TYPE (MpegTSParse2, mpegts_parse, 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>");
}
static void static void
mpegts_parse_class_init (MpegTSParse2Class * klass) mpegts_parse_class_init (MpegTSParse2Class * klass)
@ -134,17 +147,6 @@ mpegts_parse_class_init (MpegTSParse2Class * klass)
element_class->request_new_pad = mpegts_parse_request_new_pad; element_class->request_new_pad = mpegts_parse_request_new_pad;
element_class->release_pad = mpegts_parse_release_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 = G_OBJECT_CLASS (klass);
gobject_class->set_property = mpegts_parse_set_property; gobject_class->set_property = mpegts_parse_set_property;
gobject_class->get_property = mpegts_parse_get_property; gobject_class->get_property = mpegts_parse_get_property;
@ -164,7 +166,7 @@ mpegts_parse_class_init (MpegTSParse2Class * klass)
} }
static void static void
mpegts_parse_init (MpegTSParse2 * parse) mpegts_parse_init (MpegTSParse2 * parse, MpegTSParse2Class * klass)
{ {
parse->need_sync_program_pads = FALSE; parse->need_sync_program_pads = FALSE;
parse->program_numbers = g_strdup (""); parse->program_numbers = g_strdup ("");
@ -222,7 +224,7 @@ mpegts_parse_activate_program (MpegTSParse2 * parse,
gchar *pad_name; gchar *pad_name;
pad_name = pad_name =
g_strdup_printf ("program_%u", g_strdup_printf ("program_%d",
((MpegTSBaseProgram *) program)->program_number); ((MpegTSBaseProgram *) program)->program_number);
tspad = mpegts_parse_create_tspad (parse, pad_name); tspad = mpegts_parse_create_tspad (parse, pad_name);
@ -425,7 +427,7 @@ mpegts_parse_pad_removed (GstElement * element, GstPad * pad)
static GstPad * static GstPad *
mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template, mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template,
const gchar * unused, const GstCaps * caps) const gchar * unused)
{ {
MpegTSParse2 *parse; MpegTSParse2 *parse;
gchar *name; gchar *name;
@ -437,7 +439,7 @@ mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template,
parse = GST_MPEGTS_PARSE (element); parse = GST_MPEGTS_PARSE (element);
GST_OBJECT_LOCK (element); GST_OBJECT_LOCK (element);
name = g_strdup_printf ("src_%u", parse->req_pads++); name = g_strdup_printf ("src%d", parse->req_pads++);
GST_OBJECT_UNLOCK (element); GST_OBJECT_UNLOCK (element);
pad = mpegts_parse_create_tspad (parse, name)->pad; pad = mpegts_parse_create_tspad (parse, name)->pad;
@ -507,7 +509,8 @@ mpegts_parse_tspad_push (MpegTSParse2 * parse, MpegTSParsePad * tspad,
MpegTSBaseProgram *bp = (MpegTSBaseProgram *) tspad->program; MpegTSBaseProgram *bp = (MpegTSBaseProgram *) tspad->program;
pad_pids = bp->streams; pad_pids = bp->streams;
if (bp->tags) { if (bp->tags) {
gst_pad_push_event (tspad->pad, gst_event_new_tag (bp->tags)); gst_element_found_tags_for_pad (GST_ELEMENT_CAST (parse), tspad->pad,
bp->tags);
bp->tags = NULL; bp->tags = NULL;
} }
} else { } else {
@ -559,15 +562,9 @@ mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
mpegts_parse_sync_program_pads (parse); mpegts_parse_sync_program_pads (parse);
pid = packet->pid; pid = packet->pid;
#if 0
buffer = gst_buffer_make_metadata_writable (packet->buffer); buffer = gst_buffer_make_metadata_writable (packet->buffer);
/* we have the same caps on all the src pads */ /* we have the same caps on all the src pads */
gst_buffer_set_caps (buffer, base->packetizer->caps); gst_buffer_set_caps (buffer, base->packetizer->caps);
#else
buffer = packet->buffer;
#endif
GST_OBJECT_LOCK (parse); GST_OBJECT_LOCK (parse);
/* clear tspad->pushed on pads */ /* clear tspad->pushed on pads */
@ -675,9 +672,9 @@ mpegts_parse_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program)
} }
static gboolean static gboolean
mpegts_parse_src_pad_query (GstPad * pad, GstObject * parent, GstQuery * query) mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query)
{ {
MpegTSParse2 *parse = GST_MPEGTS_PARSE (parent); MpegTSParse2 *parse = GST_MPEGTS_PARSE (gst_pad_get_parent (pad));
gboolean res; gboolean res;
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
@ -700,8 +697,9 @@ mpegts_parse_src_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
break; break;
} }
default: default:
res = gst_pad_query_default (pad, parent, query); res = gst_pad_query_default (pad, query);
} }
gst_object_unref (parse);
return res; return res;
} }

View file

@ -134,6 +134,8 @@ struct _TSDemuxStream
guint current_size; guint current_size;
/* Current data to be pushed out */ /* Current data to be pushed out */
GstBufferList *current;
GstBufferListIterator *currentit;
GList *currentlist; GList *currentlist;
/* Current PTS/DTS for this stream */ /* Current PTS/DTS for this stream */
@ -163,7 +165,7 @@ struct _TSDemuxStream
"video/x-dirac;" \ "video/x-dirac;" \
"video/x-wmv," \ "video/x-wmv," \
"wmvversion = (int) 3, " \ "wmvversion = (int) 3, " \
"format = (string) WVC1" \ "format = (fourcc) WVC1" \
) )
#define AUDIO_CAPS \ #define AUDIO_CAPS \
@ -225,6 +227,7 @@ enum
/* Pad functions */ /* Pad functions */
/* mpegtsbase methods */ /* mpegtsbase methods */
static void static void
gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program); gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program);
@ -248,9 +251,13 @@ static GstFlowReturn
gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream); gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream);
static gboolean push_event (MpegTSBase * base, GstEvent * event); 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 static void
_extra_init (void) _extra_init (GType type)
{ {
QUARK_TSDEMUX = g_quark_from_string ("tsdemux"); QUARK_TSDEMUX = g_quark_from_string ("tsdemux");
QUARK_PID = g_quark_from_string ("pid"); QUARK_PID = g_quark_from_string ("pid");
@ -261,15 +268,29 @@ _extra_init (void)
QUARK_OFFSET = g_quark_from_string ("offset"); QUARK_OFFSET = g_quark_from_string ("offset");
} }
#define gst_ts_demux_parent_class parent_class static void
G_DEFINE_TYPE_WITH_CODE (GstTSDemux, gst_ts_demux, GST_TYPE_MPEGTS_BASE, gst_ts_demux_base_init (gpointer klass)
_extra_init ()); {
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>");
}
static void static void
gst_ts_demux_class_init (GstTSDemuxClass * klass) gst_ts_demux_class_init (GstTSDemuxClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *element_class;
MpegTSBaseClass *ts_class; MpegTSBaseClass *ts_class;
gobject_class = G_OBJECT_CLASS (klass); gobject_class = G_OBJECT_CLASS (klass);
@ -286,22 +307,6 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass)
"Emit messages for every pcr/opcr/pts/dts", FALSE, "Emit messages for every pcr/opcr/pts/dts", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 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 = GST_MPEGTS_BASE_CLASS (klass);
ts_class->reset = GST_DEBUG_FUNCPTR (gst_ts_demux_reset); ts_class->reset = GST_DEBUG_FUNCPTR (gst_ts_demux_reset);
@ -395,14 +400,14 @@ gst_ts_demux_srcpad_query_types (GstPad * pad)
} }
static gboolean static gboolean
gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query) gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstFormat format; GstFormat format;
GstTSDemux *demux; GstTSDemux *demux;
MpegTSBase *base; MpegTSBase *base;
demux = GST_TS_DEMUX (parent); demux = GST_TS_DEMUX (gst_pad_get_parent (pad));
base = GST_MPEGTS_BASE (demux); base = GST_MPEGTS_BASE (demux);
switch (GST_QUERY_TYPE (query)) { switch (GST_QUERY_TYPE (query)) {
@ -479,9 +484,10 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query)
break; break;
} }
default: default:
res = gst_pad_query_default (pad, parent, query); res = gst_pad_query_default (pad, query);
} }
gst_object_unref (demux);
return res; return res;
} }
@ -554,7 +560,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event)
if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) { if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
gst_element_post_message (GST_ELEMENT_CAST (demux), gst_element_post_message (GST_ELEMENT_CAST (demux),
gst_message_new_segment_start (GST_OBJECT_CAST (demux), gst_message_new_segment_start (GST_OBJECT_CAST (demux),
demux->segment.format, demux->segment.stop)); demux->segment.format, demux->segment.last_stop));
} }
done: done:
@ -562,10 +568,10 @@ done:
} }
static gboolean static gboolean
gst_ts_demux_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event) gst_ts_demux_srcpad_event (GstPad * pad, GstEvent * event)
{ {
gboolean res = TRUE; gboolean res = TRUE;
GstTSDemux *demux = GST_TS_DEMUX (parent); GstTSDemux *demux = GST_TS_DEMUX (gst_pad_get_parent (pad));
GST_DEBUG_OBJECT (pad, "Got event %s", GST_DEBUG_OBJECT (pad, "Got event %s",
gst_event_type_get_name (GST_EVENT_TYPE (event))); gst_event_type_get_name (GST_EVENT_TYPE (event)));
@ -578,9 +584,10 @@ gst_ts_demux_srcpad_event (GstPad * pad, GstObject * parent, GstEvent * event)
gst_event_unref (event); gst_event_unref (event);
break; break;
default: default:
res = gst_pad_event_default (pad, parent, event); res = gst_pad_event_default (pad, event);
} }
gst_object_unref (demux);
return res; return res;
} }
@ -601,8 +608,6 @@ push_event (MpegTSBase * base, GstEvent * event)
} }
} }
gst_event_unref (event);
return TRUE; return TRUE;
} }
@ -681,7 +686,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
GST_LOG ("ac3 audio"); GST_LOG ("ac3 audio");
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-ac3"); caps = gst_caps_new_simple ("audio/x-ac3", NULL);
g_free (desc); g_free (desc);
break; break;
} }
@ -692,7 +697,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
GST_LOG ("ac3 audio"); GST_LOG ("ac3 audio");
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-eac3"); caps = gst_caps_new_simple ("audio/x-eac3", NULL);
g_free (desc); g_free (desc);
break; break;
} }
@ -702,7 +707,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
GST_LOG ("teletext"); GST_LOG ("teletext");
template = gst_static_pad_template_get (&private_template); template = gst_static_pad_template_get (&private_template);
name = g_strdup_printf ("private_%04x", bstream->pid); name = g_strdup_printf ("private_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("private/teletext"); caps = gst_caps_new_simple ("private/teletext", NULL);
g_free (desc); g_free (desc);
break; break;
} }
@ -713,7 +718,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
GST_LOG ("subtitling"); GST_LOG ("subtitling");
template = gst_static_pad_template_get (&private_template); template = gst_static_pad_template_get (&private_template);
name = g_strdup_printf ("private_%04x", bstream->pid); name = g_strdup_printf ("private_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("subpicture/x-dvb"); caps = gst_caps_new_simple ("subpicture/x-dvb", NULL);
g_free (desc); g_free (desc);
break; break;
} }
@ -806,7 +811,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
/* dirac in hex */ /* dirac in hex */
template = gst_static_pad_template_get (&video_template); template = gst_static_pad_template_get (&video_template);
name = g_strdup_printf ("video_%04x", bstream->pid); name = g_strdup_printf ("video_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("video/x-dirac"); caps = gst_caps_new_simple ("video/x-dirac", NULL);
} }
} }
g_free (desc); g_free (desc);
@ -826,7 +831,8 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
name = g_strdup_printf ("video_%04x", bstream->pid); name = g_strdup_printf ("video_%04x", bstream->pid);
caps = gst_caps_new_simple ("video/x-wmv", caps = gst_caps_new_simple ("video/x-wmv",
"wmvversion", G_TYPE_INT, 3, "wmvversion", G_TYPE_INT, 3,
"format", G_TYPE_STRING, "WVC1", NULL); "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
NULL);
} }
} }
g_free (desc); g_free (desc);
@ -857,6 +863,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_simple ("audio/x-eac3", NULL); caps = gst_caps_new_simple ("audio/x-eac3", NULL);
} }
} }
g_free (desc); g_free (desc);
@ -871,7 +878,7 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
if (desc) { if (desc) {
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-eac3"); caps = gst_caps_new_simple ("audio/x-eac3", NULL);
g_free (desc); g_free (desc);
break; break;
} }
@ -888,60 +895,58 @@ create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
g_free (desc); g_free (desc);
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-ac3"); caps = gst_caps_new_simple ("audio/x-ac3", NULL);
break; break;
} }
case ST_BD_AUDIO_EAC3: case ST_BD_AUDIO_EAC3:
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-eac3"); caps = gst_caps_new_simple ("audio/x-eac3", NULL);
break; break;
case ST_PS_AUDIO_DTS: case ST_PS_AUDIO_DTS:
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-dts"); caps = gst_caps_new_simple ("audio/x-dts", NULL);
break; break;
case ST_PS_AUDIO_LPCM: case ST_PS_AUDIO_LPCM:
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-lpcm"); caps = gst_caps_new_simple ("audio/x-lpcm", NULL);
break; break;
case ST_BD_AUDIO_LPCM: case ST_BD_AUDIO_LPCM:
template = gst_static_pad_template_get (&audio_template); template = gst_static_pad_template_get (&audio_template);
name = g_strdup_printf ("audio_%04x", bstream->pid); name = g_strdup_printf ("audio_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("audio/x-private-ts-lpcm"); caps = gst_caps_new_simple ("audio/x-private-ts-lpcm", NULL);
break; break;
case ST_PS_DVD_SUBPICTURE: case ST_PS_DVD_SUBPICTURE:
template = gst_static_pad_template_get (&subpicture_template); template = gst_static_pad_template_get (&subpicture_template);
name = g_strdup_printf ("subpicture_%04x", bstream->pid); name = g_strdup_printf ("subpicture_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture"); caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
break; break;
case ST_BD_PGS_SUBPICTURE: case ST_BD_PGS_SUBPICTURE:
template = gst_static_pad_template_get (&subpicture_template); template = gst_static_pad_template_get (&subpicture_template);
name = g_strdup_printf ("subpicture_%04x", bstream->pid); name = g_strdup_printf ("subpicture_%04x", bstream->pid);
caps = gst_caps_new_empty_simple ("subpicture/x-pgs"); caps = gst_caps_new_simple ("subpicture/x-pgs", NULL);
break; break;
default: default:
GST_WARNING ("Non-media stream (stream_type:0x%x). Not creating pad", GST_WARNING ("Non-media stream (stream_type:0x%x). Not creating pad",
bstream->stream_type); bstream->stream_type);
break; break;
} }
if (template && name && caps) { if (template && name && caps) {
GST_LOG ("stream:%p creating pad with name %s and caps %s", stream, name, GST_LOG ("stream:%p creating pad with name %s and caps %s", stream, name,
gst_caps_to_string (caps)); gst_caps_to_string (caps));
pad = gst_pad_new_from_template (template, name); pad = gst_pad_new_from_template (template, name);
gst_pad_set_active (pad, TRUE);
gst_pad_use_fixed_caps (pad); gst_pad_use_fixed_caps (pad);
gst_pad_set_caps (pad, caps); 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_query_function (pad, gst_ts_demux_srcpad_query);
gst_pad_set_event_function (pad, gst_ts_demux_srcpad_event); gst_pad_set_event_function (pad, gst_ts_demux_srcpad_event);
} }
if (name) if (name)
g_free (name); g_free (name);
if (template)
gst_object_unref (template);
if (caps) if (caps)
gst_caps_unref (caps); gst_caps_unref (caps);
@ -1002,6 +1007,7 @@ activate_pad_for_stream (GstTSDemux * tsdemux, TSDemuxStream * stream)
if (stream->pad) { if (stream->pad) {
GST_DEBUG_OBJECT (tsdemux, "Activating pad %s:%s for stream %p", GST_DEBUG_OBJECT (tsdemux, "Activating pad %s:%s for stream %p",
GST_DEBUG_PAD_NAME (stream->pad), stream); GST_DEBUG_PAD_NAME (stream->pad), stream);
gst_pad_set_active (stream->pad, TRUE);
gst_element_add_pad ((GstElement *) tsdemux, stream->pad); gst_element_add_pad ((GstElement *) tsdemux, stream->pad);
stream->active = TRUE; stream->active = TRUE;
GST_DEBUG_OBJECT (stream->pad, "done adding pad"); GST_DEBUG_OBJECT (stream->pad, "done adding pad");
@ -1097,7 +1103,7 @@ gst_ts_demux_record_pcr (GstTSDemux * demux, TSDemuxStream * stream,
if (G_UNLIKELY (demux->emit_statistics)) { if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st; GstStructure *st;
st = gst_structure_new_id_empty (QUARK_TSDEMUX); st = gst_structure_id_empty_new (QUARK_TSDEMUX);
gst_structure_id_set (st, gst_structure_id_set (st,
QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_PID, G_TYPE_UINT, bs->pid,
QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PCR, G_TYPE_UINT64, pcr, QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PCR, G_TYPE_UINT64, pcr,
@ -1121,7 +1127,7 @@ gst_ts_demux_record_opcr (GstTSDemux * demux, TSDemuxStream * stream,
if (G_UNLIKELY (demux->emit_statistics)) { if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st; GstStructure *st;
st = gst_structure_new_id_empty (QUARK_TSDEMUX); st = gst_structure_id_empty_new (QUARK_TSDEMUX);
gst_structure_id_set (st, gst_structure_id_set (st,
QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_PID, G_TYPE_UINT, bs->pid,
QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_OFFSET, G_TYPE_UINT64, offset,
@ -1167,7 +1173,7 @@ gst_ts_demux_record_pts (GstTSDemux * demux, TSDemuxStream * stream,
if (G_UNLIKELY (demux->emit_statistics)) { if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st; GstStructure *st;
st = gst_structure_new_id_empty (QUARK_TSDEMUX); st = gst_structure_id_empty_new (QUARK_TSDEMUX);
gst_structure_id_set (st, gst_structure_id_set (st,
QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_PID, G_TYPE_UINT, bs->pid,
QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PTS, G_TYPE_UINT64, pts, QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PTS, G_TYPE_UINT64, pts,
@ -1212,7 +1218,7 @@ gst_ts_demux_record_dts (GstTSDemux * demux, TSDemuxStream * stream,
if (G_UNLIKELY (demux->emit_statistics)) { if (G_UNLIKELY (demux->emit_statistics)) {
GstStructure *st; GstStructure *st;
st = gst_structure_new_id_empty (QUARK_TSDEMUX); st = gst_structure_id_empty_new (QUARK_TSDEMUX);
gst_structure_id_set (st, gst_structure_id_set (st,
QUARK_PID, G_TYPE_UINT, bs->pid, QUARK_PID, G_TYPE_UINT, bs->pid,
QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_DTS, G_TYPE_UINT64, dts, QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_DTS, G_TYPE_UINT64, dts,
@ -1227,22 +1233,20 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
{ {
MpegTSBase *base = (MpegTSBase *) demux; MpegTSBase *base = (MpegTSBase *) demux;
PESHeader header; PESHeader header;
GstBuffer *buf = stream->pendingbuffers[0];
GstFlowReturn res = GST_FLOW_OK; GstFlowReturn res = GST_FLOW_OK;
gint offset = 0; gint offset = 0;
GstMapInfo map; guint8 *data;
guint32 length;
guint64 bufferoffset; guint64 bufferoffset;
PESParsingResult parseres; PESParsingResult parseres;
GstClockTime origts;
gst_buffer_map (buf, &map, GST_MAP_READ); data = GST_BUFFER_DATA (stream->pendingbuffers[0]);
bufferoffset = GST_BUFFER_OFFSET (buf); length = GST_BUFFER_SIZE (stream->pendingbuffers[0]);
origts = GST_BUFFER_TIMESTAMP (buf); bufferoffset = GST_BUFFER_OFFSET (stream->pendingbuffers[0]);
GST_MEMDUMP ("Header buffer", map.data, MIN (map.size, 32)); GST_MEMDUMP ("Header buffer", data, MIN (length, 32));
parseres = mpegts_parse_pes_header (map.data, map.size, &header, &offset);
parseres = mpegts_parse_pes_header (data, length, &header, &offset);
if (G_UNLIKELY (parseres == PES_PARSING_NEED_MORE)) if (G_UNLIKELY (parseres == PES_PARSING_NEED_MORE))
goto discont; goto discont;
if (G_UNLIKELY (parseres == PES_PARSING_BAD)) { if (G_UNLIKELY (parseres == PES_PARSING_BAD)) {
@ -1272,25 +1276,27 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]))); GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0])));
} }
if (header.DTS != -1)
gst_ts_demux_record_dts (demux, stream, header.DTS, bufferoffset);
gst_buffer_unmap (buf, &map);
/* Remove PES headers */ /* Remove PES headers */
GST_DEBUG ("Moving data forward by %d bytes (packet_size:%d, have:%d)", GST_DEBUG ("Moving data forward by %d bytes (packet_size:%d, have:%d)",
header.header_size, header.packet_length, header.header_size, header.packet_length,
GST_BUFFER_SIZE (stream->pendingbuffers[0])); GST_BUFFER_SIZE (stream->pendingbuffers[0]));
stream->expected_size = header.packet_length; stream->expected_size = header.packet_length;
gst_buffer_resize (buf, header.header_size, map.size - header.header_size); GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size;
GST_BUFFER_SIZE (stream->pendingbuffers[0]) -= header.header_size;
/* FIXME : responsible for switching to PENDING_PACKET_BUFFER and /* FIXME : responsible for switching to PENDING_PACKET_BUFFER and
* creating the bufferlist */ * creating the bufferlist */
if (1) { if (1) {
/* Append to the buffer list */ /* Append to the buffer list */
if (G_UNLIKELY (stream->currentlist == NULL)) { if (G_UNLIKELY (stream->current == NULL)) {
guint8 i; 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 */ /* Push pending buffers into the list */
for (i = stream->nbpending; i; i--) for (i = stream->nbpending; i; i--)
stream->currentlist = stream->currentlist =
@ -1317,19 +1323,14 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
MpegTSPacketizerPacket * packet) MpegTSPacketizerPacket * packet)
{ {
GstBuffer *buf; GstBuffer *buf;
GstMapInfo map;
GST_DEBUG ("state:%d", stream->state); GST_DEBUG ("state:%d", stream->state);
buf = packet->buffer; buf = packet->buffer;
gst_buffer_map (buf, &map, GST_MAP_READ); /* HACK : Instead of creating a new buffer, we just modify the data/size
* of the buffer to point to the payload */
GST_DEBUG ("Resizing buffer to %d (size:%d) (Was %" G_GSIZE_FORMAT GST_BUFFER_DATA (buf) = packet->payload;
" bytes long)", (int) (packet->payload - map.data), GST_BUFFER_SIZE (buf) = packet->data_end - packet->payload;
(int) (packet->data_end - packet->payload), map.size);
gst_buffer_resize (buf, packet->payload - map.data,
packet->data_end - packet->payload);
gst_buffer_unmap (buf, &map);
if (stream->state == PENDING_PACKET_EMPTY) { if (stream->state == PENDING_PACKET_EMPTY) {
if (G_UNLIKELY (!packet->payload_unit_start_indicator)) { if (G_UNLIKELY (!packet->payload_unit_start_indicator)) {
@ -1338,6 +1339,10 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
} else { } else {
GST_LOG ("EMPTY=>HEADER"); GST_LOG ("EMPTY=>HEADER");
stream->state = PENDING_PACKET_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));
}
} }
} }
@ -1391,7 +1396,6 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
lowest_pts = pstream->dts; lowest_pts = pstream->dts;
} }
} }
if (GST_CLOCK_TIME_IS_VALID (lowest_pts)) if (GST_CLOCK_TIME_IS_VALID (lowest_pts))
firstts = mpegts_packetizer_pts_to_ts (base->packetizer, lowest_pts); firstts = mpegts_packetizer_pts_to_ts (base->packetizer, lowest_pts);
GST_DEBUG ("lowest_pts %" G_GUINT64_FORMAT " => clocktime %" GST_TIME_FORMAT, GST_DEBUG ("lowest_pts %" G_GUINT64_FORMAT " => clocktime %" GST_TIME_FORMAT,
@ -1403,7 +1407,10 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
if (demux->segment.format == GST_FORMAT_TIME) { if (demux->segment.format == GST_FORMAT_TIME) {
GST_DEBUG ("Re-using segment " SEGMENT_FORMAT, GST_DEBUG ("Re-using segment " SEGMENT_FORMAT,
SEGMENT_ARGS (demux->segment)); SEGMENT_ARGS (demux->segment));
demux->update_segment = gst_event_new_segment (&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_EVENT_SRC (demux->update_segment) = gst_object_ref (demux);
} }
demux->calculate_update_segment = FALSE; demux->calculate_update_segment = FALSE;
@ -1412,7 +1419,9 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
if (!demux->segment_event) { if (!demux->segment_event) {
GST_DEBUG ("Calculating actual segment"); GST_DEBUG ("Calculating actual segment");
/* FIXME : Set proper values */ /* FIXME : Set proper values */
demux->segment_event = gst_event_new_segment (&demux->segment); demux->segment_event =
gst_event_new_new_segment_full (FALSE, 1.0, 1.0, GST_FORMAT_TIME,
firstts, GST_CLOCK_TIME_NONE, firstts);
GST_EVENT_SRC (demux->segment_event) = gst_object_ref (demux); GST_EVENT_SRC (demux->segment_event) = gst_object_ref (demux);
} }
@ -1436,7 +1445,6 @@ static GstFlowReturn
gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
{ {
GstFlowReturn res = GST_FLOW_OK; GstFlowReturn res = GST_FLOW_OK;
GList *tmp;
MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; MpegTSBaseStream *bs = (MpegTSBaseStream *) stream;
/* MpegTSBase *base = (MpegTSBase*) demux; */ /* MpegTSBase *base = (MpegTSBase*) demux; */
GstBuffer *firstbuffer = NULL; GstBuffer *firstbuffer = NULL;
@ -1446,7 +1454,7 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
"stream:%p, pid:0x%04x stream_type:%d state:%d", stream, bs->pid, "stream:%p, pid:0x%04x stream_type:%d state:%d", stream, bs->pid,
bs->stream_type, stream->state); bs->stream_type, stream->state);
if (G_UNLIKELY (stream->currentlist == NULL)) { if (G_UNLIKELY (stream->current == NULL)) {
GST_LOG ("stream->current == NULL"); GST_LOG ("stream->current == NULL");
goto beach; goto beach;
} }
@ -1465,7 +1473,8 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
if (G_UNLIKELY (stream->pad == NULL)) { if (G_UNLIKELY (stream->pad == NULL)) {
g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL); g_list_foreach (stream->currentlist, (GFunc) gst_buffer_unref, NULL);
g_list_free (stream->currentlist); g_list_free (stream->currentlist);
stream->currentlist = NULL; gst_buffer_list_iterator_free (stream->currentit);
gst_buffer_list_unref (stream->current);
goto beach; goto beach;
} }
@ -1473,26 +1482,10 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
calculate_and_push_newsegment (demux, stream); calculate_and_push_newsegment (demux, stream);
/* We have a confirmed buffer, let's push it out */ /* We have a confirmed buffer, let's push it out */
GST_LOG_OBJECT (stream->pad, "Putting pending data into buffer list"); GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList");
stream->currentlist = g_list_reverse (stream->currentlist); stream->currentlist = g_list_reverse (stream->currentlist);
buf = (GstBuffer *) stream->currentlist->data; gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist);
gst_buffer_list_iterator_free (stream->currentit);
ts = GST_BUFFER_TIMESTAMP (buf);
GST_DEBUG_OBJECT (stream->pad,
"ts %" GST_TIME_FORMAT " delta %" GST_TIME_FORMAT " stream->pts %"
GST_TIME_FORMAT, GST_TIME_ARGS (ts), GST_TIME_ARGS (demux->pts_delta),
GST_TIME_ARGS (stream->pts));
if (GST_CLOCK_TIME_IS_VALID (demux->pts_delta)
&& GST_CLOCK_TIME_IS_VALID (stream->pts)
&& !GST_CLOCK_TIME_IS_VALID (ts)) {
ts = stream->pts - demux->pts_delta;
}
for (tmp = stream->currentlist->next; tmp; tmp = tmp->next) {
buf = gst_buffer_append (buf, (GstBuffer *) tmp->data);
}
firstbuffer = gst_buffer_list_get (stream->current, 0, 0); firstbuffer = gst_buffer_list_get (stream->current, 0, 0);
@ -1507,7 +1500,7 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
"Pushing buffer list with timestamp: %" GST_TIME_FORMAT, "Pushing buffer list with timestamp: %" GST_TIME_FORMAT,
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (firstbuffer))); GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (firstbuffer)));
res = gst_pad_push (stream->pad, buf); res = gst_pad_push_list (stream->pad, stream->current);
GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res)); GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res));
res = tsdemux_combine_flows (demux, stream, res); res = tsdemux_combine_flows (demux, stream, res);
GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res)); GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res));
@ -1531,10 +1524,8 @@ gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream,
{ {
GstFlowReturn res = GST_FLOW_OK; GstFlowReturn res = GST_FLOW_OK;
#if 0
GST_DEBUG ("buffer:%p, data:%p", GST_BUFFER_DATA (packet->buffer), GST_DEBUG ("buffer:%p, data:%p", GST_BUFFER_DATA (packet->buffer),
packet->data); packet->data);
#endif
GST_LOG ("pid 0x%04x pusi:%d, afc:%d, cont:%d, payload:%p", GST_LOG ("pid 0x%04x pusi:%d, afc:%d, cont:%d, payload:%p",
packet->pid, packet->pid,
packet->payload_unit_start_indicator, packet->payload_unit_start_indicator,
@ -1542,8 +1533,8 @@ gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream,
packet->continuity_counter, packet->payload); packet->continuity_counter, packet->payload);
if (section) { if (section) {
GST_DEBUG ("section complete:%d, buffer size %" G_GSIZE_FORMAT, GST_DEBUG ("section complete:%d, buffer size %d",
section->complete, gst_buffer_get_size (section->buffer)); section->complete, GST_BUFFER_SIZE (section->buffer));
gst_buffer_unref (packet->buffer); gst_buffer_unref (packet->buffer);
return res; return res;
} }
@ -1590,8 +1581,6 @@ gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
TSDemuxStream *stream = NULL; TSDemuxStream *stream = NULL;
GstFlowReturn res = GST_FLOW_OK; GstFlowReturn res = GST_FLOW_OK;
GST_DEBUG ("packet->buffer %p", packet->buffer);
if (G_LIKELY (demux->program)) { if (G_LIKELY (demux->program)) {
stream = (TSDemuxStream *) demux->program->streams[packet->pid]; stream = (TSDemuxStream *) demux->program->streams[packet->pid];