mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
mpegtsdemux: port to 0.11
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=674397
This commit is contained in:
parent
5bd76c7c97
commit
fcd8155d87
7 changed files with 430 additions and 398 deletions
|
@ -314,7 +314,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 mpegtsdemux"
|
wildmidi xvid lv2 teletextdec dvb"
|
||||||
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
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
plugin_LTLIBRARIES = libgstmpegtsdemux.la
|
plugin_LTLIBRARIES = libgstmpegtsdemux.la
|
||||||
|
|
||||||
|
# FIXME 0.11: ignore GValueArray warnings for now until this is sorted
|
||||||
|
ERROR_CFLAGS=
|
||||||
|
|
||||||
libgstmpegtsdemux_la_SOURCES = \
|
libgstmpegtsdemux_la_SOURCES = \
|
||||||
gsttsdemux.c \
|
gsttsdemux.c \
|
||||||
gstmpegdesc.c \
|
gstmpegdesc.c \
|
||||||
|
|
|
@ -81,14 +81,15 @@ 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);
|
static gboolean mpegts_base_sink_activate (GstPad * pad, GstObject * parent);
|
||||||
static gboolean mpegts_base_sink_activate_pull (GstPad * pad, gboolean active);
|
static gboolean mpegts_base_sink_activate_mode (GstPad * pad,
|
||||||
static gboolean mpegts_base_sink_activate_push (GstPad * pad, gboolean active);
|
GstObject * parent, GstPadMode mode, gboolean active);
|
||||||
static GstFlowReturn mpegts_base_chain (GstPad * pad, GstBuffer * buf);
|
static GstFlowReturn mpegts_base_chain (GstPad * pad, GstObject * parent,
|
||||||
static gboolean mpegts_base_sink_event (GstPad * pad, GstEvent * event);
|
GstBuffer * buf);
|
||||||
|
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,
|
||||||
|
@ -97,9 +98,20 @@ static gboolean
|
||||||
remove_each_program (gpointer key, MpegTSBaseProgram * program,
|
remove_each_program (gpointer key, MpegTSBaseProgram * program,
|
||||||
MpegTSBase * base);
|
MpegTSBase * base);
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (MpegTSBase, mpegts_base, GstElement, GST_TYPE_ELEMENT,
|
static void
|
||||||
_extra_init);
|
_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] = {
|
static const guint32 crc_tab[256] = {
|
||||||
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
|
||||||
|
@ -160,25 +172,6 @@ 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)
|
||||||
{
|
{
|
||||||
|
@ -188,6 +181,9 @@ 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;
|
||||||
|
@ -237,14 +233,12 @@ mpegts_base_reset (MpegTSBase * base)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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");
|
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_activatepull_function (base->sinkpad,
|
gst_pad_set_activatemode_function (base->sinkpad,
|
||||||
mpegts_base_sink_activate_pull);
|
mpegts_base_sink_activate_mode);
|
||||||
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);
|
||||||
|
@ -495,21 +489,31 @@ 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);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (base, "program_number : %d", program_number);
|
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));
|
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 */
|
/* 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)) {
|
||||||
if (G_UNLIKELY (mpegts_base_calc_crc32 (GST_BUFFER_DATA (section->buffer),
|
GstMapInfo map;
|
||||||
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) {
|
||||||
|
@ -1195,7 +1203,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_full (GST_TAG_ARTIST,
|
program->tags = gst_tag_list_new (GST_TAG_ARTIST,
|
||||||
gst_structure_get_string (service, "name"), NULL);
|
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);
|
gst_structure_get_uint (event, "duration", &duration);
|
||||||
|
|
||||||
program->event_id = event_id;
|
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);
|
title, GST_TAG_DURATION, duration * GST_SECOND, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1280,39 +1288,30 @@ mpegts_base_flush (MpegTSBase * base)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
mpegts_base_sink_event (GstPad * pad, GstEvent * event)
|
mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
||||||
{
|
{
|
||||||
gboolean res = TRUE;
|
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_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_NEWSEGMENT:
|
case GST_EVENT_SEGMENT:
|
||||||
{
|
gst_event_copy_segment (event, &base->segment);
|
||||||
gboolean update;
|
gst_event_unref (event);
|
||||||
gdouble rate, applied_rate;
|
break;
|
||||||
GstFormat format;
|
case GST_EVENT_STREAM_START:
|
||||||
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);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_CAPS:
|
||||||
|
/* FIXME, do something */
|
||||||
|
gst_event_unref (event);
|
||||||
|
break;
|
||||||
case GST_EVENT_FLUSH_START:
|
case GST_EVENT_FLUSH_START:
|
||||||
mpegts_packetizer_flush (base->packetizer);
|
mpegts_packetizer_flush (base->packetizer);
|
||||||
mpegts_base_flush (base);
|
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);
|
res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (base);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1362,7 +1360,7 @@ mpegts_base_push (MpegTSBase * base, MpegTSPacketizerPacket * packet,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
mpegts_base_chain (GstPad * pad, GstBuffer * buf)
|
mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstFlowReturn res = GST_FLOW_OK;
|
GstFlowReturn res = GST_FLOW_OK;
|
||||||
MpegTSBase *base;
|
MpegTSBase *base;
|
||||||
|
@ -1371,7 +1369,7 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf)
|
||||||
MpegTSPacketizer2 *packetizer;
|
MpegTSPacketizer2 *packetizer;
|
||||||
MpegTSPacketizerPacket packet;
|
MpegTSPacketizerPacket packet;
|
||||||
|
|
||||||
base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad)));
|
base = GST_MPEGTS_BASE (parent);
|
||||||
packetizer = base->packetizer;
|
packetizer = base->packetizer;
|
||||||
|
|
||||||
if (G_UNLIKELY (base->queried_latency == FALSE)) {
|
if (G_UNLIKELY (base->queried_latency == FALSE)) {
|
||||||
|
@ -1379,8 +1377,14 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
mpegts_packetizer_push (base->packetizer, 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))
|
if (G_UNLIKELY (pret == PACKET_BAD))
|
||||||
/* bad header, skip the packet */
|
/* bad header, skip the packet */
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -1417,7 +1421,6 @@ mpegts_base_chain (GstPad * pad, GstBuffer * buf)
|
||||||
mpegts_packetizer_clear_packet (base->packetizer, &packet);
|
mpegts_packetizer_clear_packet (base->packetizer, &packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (base);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1480,7 +1483,7 @@ mpegts_base_scan (MpegTSBase * base)
|
||||||
|
|
||||||
/* Get the size of upstream */
|
/* Get the size of upstream */
|
||||||
format = GST_FORMAT_BYTES;
|
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;
|
goto beach;
|
||||||
upstream_size = tmpval;
|
upstream_size = tmpval;
|
||||||
done = FALSE;
|
done = FALSE;
|
||||||
|
@ -1554,8 +1557,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_SIZE (buf);
|
base->seek_offset += gst_buffer_get_size (buf);
|
||||||
ret = mpegts_base_chain (base->sinkpad, buf);
|
ret = mpegts_base_chain (base->sinkpad, GST_OBJECT_CAST (base), buf);
|
||||||
if (G_UNLIKELY (ret != GST_FLOW_OK))
|
if (G_UNLIKELY (ret != GST_FLOW_OK))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -1571,16 +1574,9 @@ 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_UNEXPECTED) {
|
if (ret == GST_FLOW_EOS) {
|
||||||
/* Push EOS downstream */
|
GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, gst_event_new_eos ());
|
||||||
if (!GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base,
|
} else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
|
||||||
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) {
|
|
||||||
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));
|
||||||
|
@ -1646,7 +1642,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 ());
|
gst_pad_push_event (base->sinkpad, gst_event_new_flush_stop (TRUE));
|
||||||
/* 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);
|
||||||
|
@ -1675,7 +1671,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 ());
|
gst_event_new_flush_stop (TRUE));
|
||||||
}
|
}
|
||||||
//else
|
//else
|
||||||
done:
|
done:
|
||||||
|
@ -1687,39 +1683,63 @@ push_mode:
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
mpegts_base_sink_activate (GstPad * pad)
|
mpegts_base_sink_activate (GstPad * sinkpad, GstObject * parent)
|
||||||
{
|
{
|
||||||
if (gst_pad_check_pull_range (pad)) {
|
GstQuery *query;
|
||||||
GST_DEBUG_OBJECT (pad, "activating pull");
|
gboolean pull_mode;
|
||||||
return gst_pad_activate_pull (pad, TRUE);
|
|
||||||
} else {
|
query = gst_query_new_scheduling ();
|
||||||
GST_DEBUG_OBJECT (pad, "activating push");
|
|
||||||
return gst_pad_activate_push (pad, TRUE);
|
if (!gst_pad_peer_query (sinkpad, query)) {
|
||||||
|
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_pull (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));
|
gboolean res;
|
||||||
if (active) {
|
MpegTSBase *base = GST_MPEGTS_BASE (parent);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
switch (mode) {
|
||||||
mpegts_base_sink_activate_push (GstPad * pad, gboolean active)
|
case GST_PAD_MODE_PUSH:
|
||||||
{
|
base->mode = BASE_MODE_PUSHING;
|
||||||
MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad));
|
base->packetizer->calculate_skew = TRUE;
|
||||||
base->mode = BASE_MODE_PUSHING;
|
res = TRUE;
|
||||||
base->packetizer->calculate_skew = TRUE;
|
break;
|
||||||
return TRUE;
|
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
|
static GstStateChangeReturn
|
||||||
mpegts_base_change_state (GstElement * element, GstStateChange transition)
|
mpegts_base_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
|
|
@ -357,6 +357,8 @@ 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;
|
||||||
|
@ -373,6 +375,7 @@ 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;
|
||||||
|
@ -382,7 +385,8 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
|
||||||
/* 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);
|
||||||
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;
|
GST_BUFFER_OFFSET (section->buffer) = stream->offset;
|
||||||
|
|
||||||
section->table_id = *data++;
|
section->table_id = *data++;
|
||||||
|
@ -418,8 +422,7 @@ 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 =
|
crc_data = map.data + map.size - 4;
|
||||||
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 &&
|
||||||
|
@ -430,6 +433,8 @@ 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:
|
||||||
|
@ -438,6 +443,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -491,6 +497,7 @@ 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;
|
||||||
|
@ -501,7 +508,8 @@ mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer,
|
||||||
GstStructure *entry = NULL;
|
GstStructure *entry = NULL;
|
||||||
gchar *struct_name;
|
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->table_id = *data++;
|
||||||
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
|
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 */
|
/* skip section_number and last_section_number */
|
||||||
data += 2;
|
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);
|
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 = GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer);
|
end = map.data + map.size;
|
||||||
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;
|
||||||
|
@ -530,7 +538,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 (struct_name, NULL);
|
entry = gst_structure_new_empty (struct_name);
|
||||||
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);
|
||||||
|
@ -544,6 +552,8 @@ 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");
|
||||||
|
@ -560,6 +570,7 @@ 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;
|
||||||
|
@ -574,15 +585,17 @@ 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 (GST_BUFFER_SIZE (section->buffer) < 16) {
|
if (map.size < 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (section->buffer);
|
end = map.data + map.size;
|
||||||
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;
|
||||||
|
@ -606,7 +619,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_id_new (QUARK_PMT,
|
pmt = gst_structure_new_id (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);
|
||||||
|
@ -653,7 +666,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 (struct_name, NULL);
|
stream_info = gst_structure_new_empty (struct_name);
|
||||||
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,
|
||||||
|
@ -755,6 +768,8 @@ 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;
|
||||||
|
@ -762,6 +777,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -771,6 +787,7 @@ 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;
|
||||||
|
@ -780,15 +797,18 @@ 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 (GST_BUFFER_SIZE (section->buffer) < 23) {
|
if (map.size < 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (section->buffer);
|
end = map.data + map.size;
|
||||||
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;
|
||||||
|
@ -813,7 +833,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_id_new (QUARK_NIT,
|
nit = gst_structure_new_id (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,
|
||||||
|
@ -891,7 +911,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 (transport_name, NULL);
|
transport = gst_structure_new_empty (transport_name);
|
||||||
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,
|
||||||
|
@ -1376,15 +1396,16 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data != end - 4) {
|
if (data != end - 4) {
|
||||||
GST_WARNING ("PID %d invalid NIT parsed %d length %d",
|
GST_WARNING ("PID %d invalid NIT parsed %d length %" G_GSIZE_FORMAT,
|
||||||
section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)),
|
section->pid, (gint) (data - map.data), map.size);
|
||||||
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;
|
||||||
|
@ -1393,6 +1414,8 @@ 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);
|
||||||
|
|
||||||
|
@ -1403,6 +1426,7 @@ 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;
|
||||||
|
@ -1416,15 +1440,18 @@ 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 (GST_BUFFER_SIZE (section->buffer) < 14) {
|
if (map.size < 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (section->buffer);
|
end = map.data + map.size;
|
||||||
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;
|
||||||
|
@ -1452,7 +1479,7 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
|
||||||
/* skip reserved byte */
|
/* skip reserved byte */
|
||||||
data += 1;
|
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_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,
|
||||||
|
@ -1491,7 +1518,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 (service_name, NULL);
|
service = gst_structure_new_empty (service_name);
|
||||||
g_free (service_name);
|
g_free (service_name);
|
||||||
|
|
||||||
if (descriptors_loop_length) {
|
if (descriptors_loop_length) {
|
||||||
|
@ -1581,21 +1608,24 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data != end - 4) {
|
if (data != end - 4) {
|
||||||
GST_WARNING ("PID %d invalid SDT parsed %d length %d",
|
GST_WARNING ("PID %d invalid SDT parsed %d length %" G_GSIZE_FORMAT,
|
||||||
section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)),
|
section->pid, (gint) (data - map.data), map.size);
|
||||||
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);
|
||||||
|
|
||||||
|
@ -1614,6 +1644,7 @@ 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 };
|
||||||
|
@ -1622,15 +1653,17 @@ 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 (GST_BUFFER_SIZE (section->buffer) < 18) {
|
if (map.size < 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (section->buffer);
|
end = map.data + map.size;
|
||||||
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;
|
||||||
|
@ -1661,7 +1694,7 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
|
||||||
last_table_id = *data;
|
last_table_id = *data;
|
||||||
data += 1;
|
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_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,
|
||||||
|
@ -2040,15 +2073,16 @@ mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data != end - 4) {
|
if (data != end - 4) {
|
||||||
GST_WARNING ("PID %d invalid EIT parsed %d length %d",
|
GST_WARNING ("PID %d invalid EIT parsed %d length %" G_GSIZE_FORMAT,
|
||||||
section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)),
|
section->pid, (gint) (data - map.data), map.size);
|
||||||
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;
|
||||||
|
@ -2057,6 +2091,8 @@ 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);
|
||||||
|
|
||||||
|
@ -2070,18 +2106,22 @@ 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 (GST_BUFFER_SIZE (section->buffer) != 8)) {
|
if (G_UNLIKELY (map.size != 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (section->buffer);
|
end = map.data + map.size;
|
||||||
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;
|
||||||
|
@ -2122,12 +2162,16 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2205,8 +2249,8 @@ mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer)
|
||||||
packetizer->offset = GST_BUFFER_OFFSET (buffer);
|
packetizer->offset = GST_BUFFER_OFFSET (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG ("Pushing %u byte from offset %" G_GUINT64_FORMAT,
|
GST_DEBUG ("Pushing %" G_GSIZE_FORMAT " byte from offset %" G_GUINT64_FORMAT,
|
||||||
GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
|
gst_buffer_get_size (buffer), GST_BUFFER_OFFSET (buffer));
|
||||||
gst_adapter_push (packetizer->adapter, buffer);
|
gst_adapter_push (packetizer->adapter, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2307,15 +2351,21 @@ mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
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 = GST_BUFFER_DATA (packet->buffer) + 4;
|
packet->data_start += 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 */
|
||||||
|
@ -2323,52 +2373,51 @@ mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer,
|
||||||
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", GST_BUFFER_DATA (packet->buffer), 16);
|
GST_MEMDUMP ("buffer", bufdata, 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_UNLIKELY (packet->data_start[0] != 0x47)) {
|
if (G_LIKELY (packet->data_start[0] == 0x47))
|
||||||
guint i;
|
goto got_valid_packet;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) {
|
/* Find the 0x47 in the buffer */
|
||||||
if (i >= 4)
|
for (i = 0; i < packetizer->packet_size; i++)
|
||||||
i -= 4;
|
if (bufdata[i] == 0x47)
|
||||||
else
|
break;
|
||||||
i += 188;
|
gst_buffer_unmap (packet->buffer, &packet->bufmap);
|
||||||
}
|
if (G_UNLIKELY (i == packetizer->packet_size)) {
|
||||||
|
GST_ERROR ("REALLY lost the sync");
|
||||||
/* Pop out the remaining data... */
|
gst_buffer_unref (packet->buffer);
|
||||||
GST_BUFFER_DATA (packet->buffer) += i;
|
goto done;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
done:
|
||||||
return PACKET_NEED_MORE;
|
return PACKET_NEED_MORE;
|
||||||
|
|
||||||
|
got_valid_packet:
|
||||||
|
return mpegts_packetizer_parse_packet (packetizer, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
MpegTSPacketizerPacketReturn
|
MpegTSPacketizerPacketReturn
|
||||||
|
@ -2422,14 +2471,15 @@ 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 - GST_BUFFER_DATA (packet->buffer) + section->section_length + 3 >
|
if (data - packet->bufmap.data + section->section_length + 3 >
|
||||||
GST_BUFFER_SIZE (packet->buffer)) {
|
packet->bufmap.size) {
|
||||||
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 = gst_buffer_create_sub (packet->buffer,
|
section->buffer =
|
||||||
data - GST_BUFFER_DATA (packet->buffer), section->section_length + 3);
|
gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL,
|
||||||
|
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;
|
||||||
|
@ -2440,8 +2490,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_create_sub (packet->buffer,
|
sub_buf = gst_buffer_copy_region (packet->buffer, GST_BUFFER_COPY_ALL,
|
||||||
data - GST_BUFFER_DATA (packet->buffer), packet->data_end - data);
|
data - packet->bufmap.data, packet->data_end - data);
|
||||||
|
|
||||||
stream = packetizer->streams[packet->pid];
|
stream = packetizer->streams[packet->pid];
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
|
@ -2465,10 +2515,11 @@ 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 %d avail %d",
|
"not complete (last_continuity: %d continuity: %d sec len %d buffer %"
|
||||||
packet->pid, table_id, subtable_extension, stream->continuity_counter,
|
G_GSIZE_FORMAT " avail %" G_GSIZE_FORMAT, packet->pid, table_id,
|
||||||
packet->continuity_counter, section_length, GST_BUFFER_SIZE (sub_buf),
|
subtable_extension, stream->continuity_counter,
|
||||||
stream->section_adapter->size);
|
packet->continuity_counter, section_length,
|
||||||
|
gst_buffer_get_size (sub_buf), stream->section_adapter->size);
|
||||||
mpegts_packetizer_clear_section (packetizer, stream);
|
mpegts_packetizer_clear_section (packetizer, stream);
|
||||||
} else {
|
} else {
|
||||||
GST_DEBUG
|
GST_DEBUG
|
||||||
|
|
|
@ -124,6 +124,8 @@ typedef struct
|
||||||
guint8 continuity_counter;
|
guint8 continuity_counter;
|
||||||
guint8 *payload;
|
guint8 *payload;
|
||||||
|
|
||||||
|
GstMapInfo bufmap;
|
||||||
|
|
||||||
guint8 *data_start;
|
guint8 *data_start;
|
||||||
guint8 *data_end;
|
guint8 *data_end;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
|
@ -176,7 +178,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);
|
||||||
|
|
||||||
|
|
|
@ -70,13 +70,13 @@ struct _MpegTSParsePad
|
||||||
};
|
};
|
||||||
|
|
||||||
static GstStaticPadTemplate src_template =
|
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_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_%d", GST_PAD_SRC,
|
GST_STATIC_PAD_TEMPLATE ("program_%u", 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,27 +113,14 @@ 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);
|
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||||
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, GstQuery * query);
|
static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstObject * parent,
|
||||||
|
GstQuery * query);
|
||||||
static gboolean push_event (MpegTSBase * base, GstEvent * event);
|
static gboolean push_event (MpegTSBase * base, GstEvent * event);
|
||||||
|
|
||||||
GST_BOILERPLATE (MpegTSParse2, mpegts_parse, MpegTSBase, GST_TYPE_MPEGTS_BASE);
|
#define mpegts_parse_parent_class parent_class
|
||||||
|
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)
|
||||||
|
@ -147,6 +134,17 @@ 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;
|
||||||
|
@ -166,7 +164,7 @@ mpegts_parse_class_init (MpegTSParse2Class * klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mpegts_parse_init (MpegTSParse2 * parse, MpegTSParse2Class * klass)
|
mpegts_parse_init (MpegTSParse2 * parse)
|
||||||
{
|
{
|
||||||
parse->need_sync_program_pads = FALSE;
|
parse->need_sync_program_pads = FALSE;
|
||||||
parse->program_numbers = g_strdup ("");
|
parse->program_numbers = g_strdup ("");
|
||||||
|
@ -224,7 +222,7 @@ mpegts_parse_activate_program (MpegTSParse2 * parse,
|
||||||
gchar *pad_name;
|
gchar *pad_name;
|
||||||
|
|
||||||
pad_name =
|
pad_name =
|
||||||
g_strdup_printf ("program_%d",
|
g_strdup_printf ("program_%u",
|
||||||
((MpegTSBaseProgram *) program)->program_number);
|
((MpegTSBaseProgram *) program)->program_number);
|
||||||
|
|
||||||
tspad = mpegts_parse_create_tspad (parse, pad_name);
|
tspad = mpegts_parse_create_tspad (parse, pad_name);
|
||||||
|
@ -430,7 +428,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 gchar * unused, const GstCaps * caps)
|
||||||
{
|
{
|
||||||
MpegTSParse2 *parse;
|
MpegTSParse2 *parse;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
|
@ -442,11 +440,12 @@ 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%d", parse->req_pads++);
|
name = g_strdup_printf ("src_%u", 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;
|
||||||
gst_pad_set_active (pad, TRUE);
|
gst_pad_set_active (pad, TRUE);
|
||||||
|
gst_pad_push_event (pad, gst_event_new_stream_start ());
|
||||||
gst_element_add_pad (element, pad);
|
gst_element_add_pad (element, pad);
|
||||||
g_free (name);
|
g_free (name);
|
||||||
|
|
||||||
|
@ -512,8 +511,7 @@ 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_element_found_tags_for_pad (GST_ELEMENT_CAST (parse), tspad->pad,
|
gst_pad_push_event (tspad->pad, gst_event_new_tag (bp->tags));
|
||||||
bp->tags);
|
|
||||||
bp->tags = NULL;
|
bp->tags = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -565,9 +563,7 @@ 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;
|
||||||
buffer = gst_buffer_make_metadata_writable (packet->buffer);
|
buffer = packet->buffer;
|
||||||
/* we have the same caps on all the src pads */
|
|
||||||
gst_buffer_set_caps (buffer, base->packetizer->caps);
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (parse);
|
GST_OBJECT_LOCK (parse);
|
||||||
/* clear tspad->pushed on pads */
|
/* clear tspad->pushed on pads */
|
||||||
|
@ -675,9 +671,9 @@ mpegts_parse_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program)
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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;
|
gboolean res;
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
@ -700,9 +696,8 @@ mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
res = gst_pad_query_default (pad, query);
|
res = gst_pad_query_default (pad, parent, query);
|
||||||
}
|
}
|
||||||
gst_object_unref (parse);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,13 +73,13 @@
|
||||||
|
|
||||||
#define SEGMENT_FORMAT "[format:%s, rate:%f, start:%" \
|
#define SEGMENT_FORMAT "[format:%s, rate:%f, start:%" \
|
||||||
GST_TIME_FORMAT", stop:%"GST_TIME_FORMAT", time:%"GST_TIME_FORMAT \
|
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"]"
|
", duration:%"GST_TIME_FORMAT"]"
|
||||||
|
|
||||||
#define SEGMENT_ARGS(a) gst_format_get_name((a).format), (a).rate, \
|
#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).start), GST_TIME_ARGS((a).stop), \
|
||||||
GST_TIME_ARGS((a).time), GST_TIME_ARGS((a).accum), \
|
GST_TIME_ARGS((a).time), GST_TIME_ARGS((a).base), \
|
||||||
GST_TIME_ARGS((a).last_stop), GST_TIME_ARGS((a).duration)
|
GST_TIME_ARGS((a).position), GST_TIME_ARGS((a).duration)
|
||||||
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (ts_demux_debug);
|
GST_DEBUG_CATEGORY_STATIC (ts_demux_debug);
|
||||||
|
@ -134,8 +134,6 @@ 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 */
|
||||||
|
@ -165,7 +163,7 @@ struct _TSDemuxStream
|
||||||
"video/x-dirac;" \
|
"video/x-dirac;" \
|
||||||
"video/x-wmv," \
|
"video/x-wmv," \
|
||||||
"wmvversion = (int) 3, " \
|
"wmvversion = (int) 3, " \
|
||||||
"format = (fourcc) WVC1" \
|
"format = (string) WVC1" \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define AUDIO_CAPS \
|
#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 void gst_ts_demux_stream_flush (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 (GType type)
|
_extra_init (void)
|
||||||
{
|
{
|
||||||
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");
|
||||||
|
@ -269,29 +263,15 @@ _extra_init (GType type)
|
||||||
QUARK_OFFSET = g_quark_from_string ("offset");
|
QUARK_OFFSET = g_quark_from_string ("offset");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
#define gst_ts_demux_parent_class parent_class
|
||||||
gst_ts_demux_base_init (gpointer klass)
|
G_DEFINE_TYPE_WITH_CODE (GstTSDemux, gst_ts_demux, GST_TYPE_MPEGTS_BASE,
|
||||||
{
|
_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);
|
||||||
|
@ -308,6 +288,22 @@ 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);
|
||||||
|
@ -341,7 +337,7 @@ gst_ts_demux_reset (MpegTSBase * base)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_ts_demux_init (GstTSDemux * demux, GstTSDemuxClass * klass)
|
gst_ts_demux_init (GstTSDemux * demux)
|
||||||
{
|
{
|
||||||
GST_MPEGTS_BASE (demux)->stream_size = sizeof (TSDemuxStream);
|
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
|
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;
|
gboolean res = TRUE;
|
||||||
GstFormat format;
|
GstFormat format;
|
||||||
GstTSDemux *demux;
|
GstTSDemux *demux;
|
||||||
MpegTSBase *base;
|
MpegTSBase *base;
|
||||||
|
|
||||||
demux = GST_TS_DEMUX (gst_pad_get_parent (pad));
|
demux = GST_TS_DEMUX (parent);
|
||||||
base = GST_MPEGTS_BASE (demux);
|
base = GST_MPEGTS_BASE (demux);
|
||||||
|
|
||||||
switch (GST_QUERY_TYPE (query)) {
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
@ -421,7 +404,7 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query)
|
||||||
gint64 val;
|
gint64 val;
|
||||||
|
|
||||||
format = GST_FORMAT_BYTES;
|
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;
|
res = FALSE;
|
||||||
else {
|
else {
|
||||||
GstClockTime dur =
|
GstClockTime dur =
|
||||||
|
@ -485,10 +468,9 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
res = gst_pad_query_default (pad, query);
|
res = gst_pad_query_default (pad, parent, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (demux);
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -535,7 +517,7 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event)
|
||||||
GST_DEBUG ("seeksegment before set_seek " SEGMENT_FORMAT,
|
GST_DEBUG ("seeksegment before set_seek " SEGMENT_FORMAT,
|
||||||
SEGMENT_ARGS (seeksegment));
|
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);
|
stop_type, stop, &update);
|
||||||
|
|
||||||
GST_DEBUG ("seeksegment after set_seek " SEGMENT_FORMAT,
|
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) {
|
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.last_stop));
|
demux->segment.format, demux->segment.stop));
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -569,10 +551,10 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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;
|
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_DEBUG_OBJECT (pad, "Got event %s",
|
||||||
gst_event_type_get_name (GST_EVENT_TYPE (event)));
|
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);
|
gst_event_unref (event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, parent, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_object_unref (demux);
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,7 +672,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_simple ("audio/x-ac3", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-ac3");
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -702,7 +683,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_simple ("audio/x-eac3", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +693,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_simple ("private/teletext", NULL);
|
caps = gst_caps_new_empty_simple ("private/teletext");
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +704,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_simple ("subpicture/x-dvb", NULL);
|
caps = gst_caps_new_empty_simple ("subpicture/x-dvb");
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -739,7 +720,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_simple ("audio/x-dts", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-dts");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
|
@ -816,7 +797,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_simple ("video/x-dirac", NULL);
|
caps = gst_caps_new_empty_simple ("video/x-dirac");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
|
@ -836,8 +817,7 @@ 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", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
|
"format", G_TYPE_STRING, "WVC1", NULL);
|
||||||
NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
|
@ -860,13 +840,13 @@ 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_simple ("audio/x-ac3", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-ac3");
|
||||||
|
|
||||||
g_free (ac3_desc);
|
g_free (ac3_desc);
|
||||||
} else {
|
} else {
|
||||||
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_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) {
|
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_simple ("audio/x-eac3", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
||||||
g_free (desc);
|
g_free (desc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -900,38 +880,38 @@ 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_simple ("audio/x-ac3", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-ac3");
|
||||||
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_simple ("audio/x-eac3", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-eac3");
|
||||||
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_simple ("audio/x-dts", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-dts");
|
||||||
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_simple ("audio/x-lpcm", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-lpcm");
|
||||||
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_simple ("audio/x-private-ts-lpcm", NULL);
|
caps = gst_caps_new_empty_simple ("audio/x-private-ts-lpcm");
|
||||||
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_simple ("video/x-dvd-subpicture", NULL);
|
caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture");
|
||||||
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_simple ("subpicture/x-pgs", NULL);
|
caps = gst_caps_new_empty_simple ("subpicture/x-pgs");
|
||||||
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",
|
||||||
|
@ -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_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_push_event (pad, gst_event_new_stream_start ());
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -1014,7 +995,6 @@ 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");
|
||||||
|
@ -1037,16 +1017,6 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream)
|
||||||
memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS);
|
memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS);
|
||||||
stream->nbpending = 0;
|
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) {
|
if (stream->currentlist) {
|
||||||
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);
|
||||||
|
@ -1055,7 +1025,6 @@ gst_ts_demux_stream_flush (TSDemuxStream * stream)
|
||||||
|
|
||||||
stream->expected_size = 0;
|
stream->expected_size = 0;
|
||||||
stream->current_size = 0;
|
stream->current_size = 0;
|
||||||
stream->current = NULL;
|
|
||||||
stream->need_newsegment = TRUE;
|
stream->need_newsegment = TRUE;
|
||||||
stream->pts = GST_CLOCK_TIME_NONE;
|
stream->pts = GST_CLOCK_TIME_NONE;
|
||||||
stream->dts = 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 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) {
|
if (program->initial_program && base->segment.format == GST_FORMAT_TIME) {
|
||||||
demux->segment = base->segment;
|
demux->segment = base->segment;
|
||||||
demux->segment_event =
|
demux->segment_event = gst_event_new_segment (&demux->segment);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME : When do we emit no_more_pads ? */
|
/* 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)) {
|
if (G_UNLIKELY (demux->emit_statistics)) {
|
||||||
GstStructure *st;
|
GstStructure *st;
|
||||||
st = gst_structure_id_empty_new (QUARK_TSDEMUX);
|
st = gst_structure_new_id_empty (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,
|
||||||
|
@ -1150,7 +1115,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_id_empty_new (QUARK_TSDEMUX);
|
st = gst_structure_new_id_empty (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,
|
||||||
|
@ -1196,7 +1161,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_id_empty_new (QUARK_TSDEMUX);
|
st = gst_structure_new_id_empty (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,
|
||||||
|
@ -1241,7 +1206,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_id_empty_new (QUARK_TSDEMUX);
|
st = gst_structure_new_id_empty (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,
|
||||||
|
@ -1256,20 +1221,22 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
{
|
{
|
||||||
MpegTSBase *base = (MpegTSBase *) demux;
|
MpegTSBase *base = (MpegTSBase *) demux;
|
||||||
PESHeader header;
|
PESHeader header;
|
||||||
|
GstBuffer *buf;
|
||||||
GstFlowReturn res = GST_FLOW_OK;
|
GstFlowReturn res = GST_FLOW_OK;
|
||||||
gint offset = 0;
|
gint offset = 0;
|
||||||
guint8 *data;
|
GstMapInfo map;
|
||||||
guint32 length;
|
|
||||||
guint64 bufferoffset;
|
guint64 bufferoffset;
|
||||||
PESParsingResult parseres;
|
PESParsingResult parseres;
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (stream->pendingbuffers[0]);
|
buf = stream->pendingbuffers[0] =
|
||||||
length = GST_BUFFER_SIZE (stream->pendingbuffers[0]);
|
gst_buffer_make_writable (stream->pendingbuffers[0]);
|
||||||
bufferoffset = GST_BUFFER_OFFSET (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))
|
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)) {
|
||||||
|
@ -1292,34 +1259,27 @@ gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
{
|
{
|
||||||
MpegTSPacketizer2 *packetizer = base->packetizer;
|
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);
|
mpegts_packetizer_pts_to_ts (packetizer, stream->pts);
|
||||||
}
|
}
|
||||||
GST_DEBUG ("buf %" GST_TIME_FORMAT,
|
GST_DEBUG ("buf %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_PTS (buf)));
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0])));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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, map.size);
|
||||||
GST_BUFFER_SIZE (stream->pendingbuffers[0]));
|
|
||||||
stream->expected_size = header.packet_length;
|
stream->expected_size = header.packet_length;
|
||||||
GST_BUFFER_DATA (stream->pendingbuffers[0]) += header.header_size;
|
gst_buffer_resize (buf, header.header_size, map.size - 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->current == NULL)) {
|
if (G_UNLIKELY (stream->currentlist == 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 =
|
||||||
|
@ -1350,10 +1310,12 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
|
||||||
GST_DEBUG ("state:%d", stream->state);
|
GST_DEBUG ("state:%d", stream->state);
|
||||||
|
|
||||||
buf = packet->buffer;
|
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_DEBUG ("Resizing buffer to %d (size:%d) (Was %" G_GSIZE_FORMAT
|
||||||
GST_BUFFER_DATA (buf) = packet->payload;
|
" bytes long)", (int) (packet->payload - packet->bufmap.data),
|
||||||
GST_BUFFER_SIZE (buf) = packet->data_end - packet->payload;
|
(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 (stream->state == PENDING_PACKET_EMPTY) {
|
||||||
if (G_UNLIKELY (!packet->payload_unit_start_indicator)) {
|
if (G_UNLIKELY (!packet->payload_unit_start_indicator)) {
|
||||||
|
@ -1362,10 +1324,6 @@ 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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,7 +1333,7 @@ gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream,
|
||||||
GST_LOG ("HEADER: appending data to array");
|
GST_LOG ("HEADER: appending data to array");
|
||||||
/* Append to the array */
|
/* Append to the array */
|
||||||
stream->pendingbuffers[stream->nbpending++] = buf;
|
stream->pendingbuffers[stream->nbpending++] = buf;
|
||||||
stream->current_size += GST_BUFFER_SIZE (buf);
|
stream->current_size += packet->bufmap.size;
|
||||||
|
|
||||||
/* parse the header */
|
/* parse the header */
|
||||||
gst_ts_demux_parse_pes_header (demux, stream);
|
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");
|
GST_LOG ("BUFFER: appending data to bufferlist");
|
||||||
stream->currentlist = g_list_prepend (stream->currentlist, buf);
|
stream->currentlist = g_list_prepend (stream->currentlist, buf);
|
||||||
stream->current_size += GST_BUFFER_SIZE (buf);
|
stream->current_size += packet->bufmap.size;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PENDING_PACKET_DISCONT:
|
case PENDING_PACKET_DISCONT:
|
||||||
|
@ -1442,39 +1400,30 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
|
||||||
GST_DEBUG ("Calculating update segment");
|
GST_DEBUG ("Calculating update segment");
|
||||||
/* If we have a valid segment, create an update of that */
|
/* If we have a valid segment, create an update of that */
|
||||||
if (demux->segment.format == GST_FORMAT_TIME) {
|
if (demux->segment.format == GST_FORMAT_TIME) {
|
||||||
|
GstSegment update_segment;
|
||||||
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_segment_copy_into (&demux->segment, &update_segment);
|
||||||
gst_event_new_new_segment_full (TRUE, demux->segment.rate,
|
update_segment.stop = firstts;
|
||||||
demux->segment.applied_rate, GST_FORMAT_TIME, demux->segment.start,
|
demux->update_segment = gst_event_new_segment (&update_segment);
|
||||||
firstts, demux->segment.time);
|
|
||||||
GST_EVENT_SRC (demux->update_segment) = gst_object_ref (demux);
|
|
||||||
}
|
}
|
||||||
demux->calculate_update_segment = FALSE;
|
demux->calculate_update_segment = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!demux->segment_event) {
|
if (!demux->segment_event) {
|
||||||
gint64 start, stop, time;
|
GstSegment new_segment;
|
||||||
|
|
||||||
GST_DEBUG ("Calculating actual segment");
|
GST_DEBUG ("Calculating actual segment");
|
||||||
|
|
||||||
if (demux->segment.format == GST_FORMAT_TIME) {
|
gst_segment_copy_into (&demux->segment, &new_segment);
|
||||||
/* if we have a TIME segment, set NS.start to the target ts so downstream
|
if (new_segment.format != GST_FORMAT_TIME) {
|
||||||
* can clip
|
/* Start from the first ts/pts */
|
||||||
*/
|
new_segment.start = firstts;
|
||||||
start = demux->segment.start;
|
new_segment.stop = GST_CLOCK_TIME_NONE;
|
||||||
stop = demux->segment.stop;
|
new_segment.position = firstts;
|
||||||
time = demux->segment.time;
|
|
||||||
} else {
|
|
||||||
/* ...else start from the first ts/pts */
|
|
||||||
start = firstts;
|
|
||||||
stop = GST_CLOCK_TIME_NONE;
|
|
||||||
time = firstts;
|
|
||||||
}
|
}
|
||||||
demux->segment_event =
|
|
||||||
gst_event_new_new_segment_full (FALSE, demux->segment.rate,
|
demux->segment_event = gst_event_new_segment (&new_segment);
|
||||||
demux->segment.applied_rate, GST_FORMAT_TIME, start, stop, time);
|
|
||||||
GST_EVENT_SRC (demux->segment_event) = gst_object_ref (demux);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
push_new_segment:
|
push_new_segment:
|
||||||
|
@ -1497,16 +1446,17 @@ 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; */
|
|
||||||
GstBuffer *firstbuffer = NULL;
|
|
||||||
MpegTSPacketizer2 *packetizer = MPEG_TS_BASE_PACKETIZER (demux);
|
MpegTSPacketizer2 *packetizer = MPEG_TS_BASE_PACKETIZER (demux);
|
||||||
|
GstBuffer *buf;
|
||||||
|
GstClockTime ts;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (stream->pad,
|
GST_DEBUG_OBJECT (stream->pad,
|
||||||
"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->current == NULL)) {
|
if (G_UNLIKELY (stream->currentlist == NULL)) {
|
||||||
GST_LOG ("stream->current == NULL");
|
GST_LOG ("stream->current == NULL");
|
||||||
goto beach;
|
goto beach;
|
||||||
}
|
}
|
||||||
|
@ -1527,8 +1477,7 @@ 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);
|
||||||
gst_buffer_list_iterator_free (stream->currentit);
|
stream->currentlist = NULL;
|
||||||
gst_buffer_list_unref (stream->current);
|
|
||||||
goto beach;
|
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 */
|
/* We have a confirmed buffer, let's push it out */
|
||||||
GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList");
|
GST_LOG_OBJECT (stream->pad, "Putting pending data into GstBufferList");
|
||||||
stream->currentlist = g_list_reverse (stream->currentlist);
|
stream->currentlist = g_list_reverse (stream->currentlist);
|
||||||
gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist);
|
buf = gst_buffer_make_writable ((GstBuffer *) stream->currentlist->data);
|
||||||
stream->currentlist = NULL;
|
|
||||||
gst_buffer_list_iterator_free (stream->currentit);
|
|
||||||
|
|
||||||
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_DEBUG_OBJECT (stream->pad, "stream->pts %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (stream->pts));
|
GST_TIME_ARGS (stream->pts));
|
||||||
if (GST_CLOCK_TIME_IS_VALID (stream->pts)
|
if (GST_CLOCK_TIME_IS_VALID (stream->pts)
|
||||||
&& !GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (firstbuffer)))
|
&& !GST_CLOCK_TIME_IS_VALID (ts))
|
||||||
GST_BUFFER_TIMESTAMP (firstbuffer) =
|
ts = mpegts_packetizer_pts_to_ts (packetizer, stream->pts);
|
||||||
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,
|
GST_DEBUG_OBJECT (stream->pad,
|
||||||
"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_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));
|
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));
|
||||||
|
@ -1566,11 +1523,13 @@ beach:
|
||||||
stream->state = PENDING_PACKET_EMPTY;
|
stream->state = PENDING_PACKET_EMPTY;
|
||||||
memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS);
|
memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS);
|
||||||
stream->nbpending = 0;
|
stream->nbpending = 0;
|
||||||
stream->current = NULL;
|
|
||||||
stream->currentit = NULL;
|
|
||||||
stream->currentlist = NULL;
|
|
||||||
stream->expected_size = 0;
|
stream->expected_size = 0;
|
||||||
stream->current_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;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -1581,8 +1540,10 @@ 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,
|
||||||
|
@ -1590,8 +1551,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 %d",
|
GST_DEBUG ("section complete:%d, buffer size %" G_GSIZE_FORMAT,
|
||||||
section->complete, GST_BUFFER_SIZE (section->buffer));
|
section->complete, gst_buffer_get_size (section->buffer));
|
||||||
gst_buffer_unref (packet->buffer);
|
gst_buffer_unref (packet->buffer);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue