gst/mpegtsparse/mpegtspacketizer.*: Hash streams by pid again. Add a linked list inside each stream with a list of su...

Original commit message from CVS:
* gst/mpegtsparse/mpegtspacketizer.c:
* gst/mpegtsparse/mpegtspacketizer.h:
Hash streams by pid again. Add a linked list inside each
stream with a list of sub_tables. Fix multiple sections
as it was borked with my last commit.
This commit is contained in:
Zaheer Abbas Merali 2007-12-14 17:51:49 +00:00
parent 57889d4b0a
commit 91bb79004f
3 changed files with 118 additions and 48 deletions

View file

@ -1,3 +1,11 @@
2007-12-14 Zaheer Abbas Merali <zaheerabbas at merali dot org>
* gst/mpegtsparse/mpegtspacketizer.c:
* gst/mpegtsparse/mpegtspacketizer.h:
Hash streams by pid again. Add a linked list inside each
stream with a list of sub_tables. Fix multiple sections
as it was borked with my last commit.
2007-12-14 Christian Schaller <christian.schaller@collabora.co.uk> 2007-12-14 Christian Schaller <christian.schaller@collabora.co.uk>
* sys/glsink/Makefile.am: add glvideo.h * sys/glsink/Makefile.am: add glvideo.h

View file

@ -33,7 +33,7 @@ static void mpegts_packetizer_finalize (GObject * object);
#define CONTINUITY_UNSET 255 #define CONTINUITY_UNSET 255
#define MAX_CONTINUITY 15 #define MAX_CONTINUITY 15
#define SECTION_VERSION_NUMBER_NOTSET 255 #define VERSION_NUMBER_NOTSET 255
typedef struct typedef struct
{ {
@ -41,24 +41,54 @@ typedef struct
/* the spec says sub_table_extension is the fourth and fifth byte of a /* the spec says sub_table_extension is the fourth and fifth byte of a
* section when the section_syntax_indicator is set to a value of "1". If * section when the section_syntax_indicator is set to a value of "1". If
* section_syntax_indicator is 0, sub_table_extension will be set to 0 */ * section_syntax_indicator is 0, sub_table_extension will be set to 0 */
guint16 sub_table_extension; guint16 subtable_extension;
guint8 version_number;
} MpegTSPacketizerStreamSubtable;
typedef struct
{
guint continuity_counter; guint continuity_counter;
GstAdapter *section_adapter; GstAdapter *section_adapter;
guint section_length; guint section_length;
guint8 section_version_number; GSList *subtables;
} MpegTSPacketizerStream; } MpegTSPacketizerStream;
static gint
mpegts_packetizer_stream_subtable_compare (gconstpointer a, gconstpointer b)
{
MpegTSPacketizerStreamSubtable *asub, *bsub;
asub = (MpegTSPacketizerStreamSubtable *) a;
bsub = (MpegTSPacketizerStreamSubtable *) b;
if (asub->table_id == bsub->table_id &&
asub->subtable_extension == bsub->subtable_extension)
return 0;
return -1;
}
static MpegTSPacketizerStreamSubtable *
mpegts_packetizer_stream_subtable_new (guint8 table_id,
guint16 subtable_extension)
{
MpegTSPacketizerStreamSubtable *subtable;
subtable = g_new0 (MpegTSPacketizerStreamSubtable, 1);
subtable->version_number = VERSION_NUMBER_NOTSET;
subtable->table_id = table_id;
subtable->subtable_extension = subtable_extension;
return subtable;
}
static MpegTSPacketizerStream * static MpegTSPacketizerStream *
mpegts_packetizer_stream_new (guint8 table_id, guint16 sub_table_extension) mpegts_packetizer_stream_new ()
{ {
MpegTSPacketizerStream *stream; MpegTSPacketizerStream *stream;
stream = (MpegTSPacketizerStream *) g_new0 (MpegTSPacketizerStream, 1); stream = (MpegTSPacketizerStream *) g_new0 (MpegTSPacketizerStream, 1);
stream->section_adapter = gst_adapter_new (); stream->section_adapter = gst_adapter_new ();
stream->table_id = table_id;
stream->sub_table_extension = sub_table_extension;
stream->continuity_counter = CONTINUITY_UNSET; stream->continuity_counter = CONTINUITY_UNSET;
stream->section_version_number = SECTION_VERSION_NUMBER_NOTSET; stream->subtables = NULL;
return stream; return stream;
} }
@ -67,6 +97,8 @@ mpegts_packetizer_stream_free (MpegTSPacketizerStream * stream)
{ {
gst_adapter_clear (stream->section_adapter); gst_adapter_clear (stream->section_adapter);
g_object_unref (stream->section_adapter); g_object_unref (stream->section_adapter);
g_slist_foreach (stream->subtables, (GFunc) g_free, NULL);
g_slist_free (stream->subtables);
g_free (stream); g_free (stream);
} }
@ -94,7 +126,7 @@ static void
mpegts_packetizer_init (MpegTSPacketizer * packetizer) mpegts_packetizer_init (MpegTSPacketizer * packetizer)
{ {
packetizer->adapter = gst_adapter_new (); packetizer->adapter = gst_adapter_new ();
packetizer->streams = g_hash_table_new (g_str_hash, g_str_equal); packetizer->streams = g_hash_table_new (g_direct_hash, g_direct_equal);
} }
static void static void
@ -207,6 +239,8 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer * packetizer,
{ {
guint8 tmp; guint8 tmp;
guint8 *data; guint8 *data;
MpegTSPacketizerStreamSubtable *subtable;
GSList *subtable_list = NULL;
section->complete = TRUE; section->complete = TRUE;
/* get the section buffer, pass the ownership to the caller */ /* get the section buffer, pass the ownership to the caller */
@ -215,6 +249,23 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer * packetizer,
data = GST_BUFFER_DATA (section->buffer); data = GST_BUFFER_DATA (section->buffer);
section->table_id = *data++; section->table_id = *data++;
if ((data[0] & 0x80) == 0)
section->subtable_extension = 0;
else
section->subtable_extension = GST_READ_UINT16_BE (data + 2);
subtable = mpegts_packetizer_stream_subtable_new (section->table_id,
section->subtable_extension);
subtable_list = g_slist_find_custom (stream->subtables, subtable,
mpegts_packetizer_stream_subtable_compare);
if (subtable_list) {
g_free (subtable);
subtable = (MpegTSPacketizerStreamSubtable *) (subtable_list->data);
} else {
stream->subtables = g_slist_prepend (stream->subtables, subtable);
}
section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
data += 2; data += 2;
@ -224,18 +275,20 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer * packetizer,
tmp = *data++; tmp = *data++;
section->version_number = (tmp >> 1) & 0x1F; section->version_number = (tmp >> 1) & 0x1F;
section->current_next_indicator = tmp & 0x01; section->current_next_indicator = tmp & 0x01;
if (!section->current_next_indicator) if (!section->current_next_indicator)
goto not_applicable; goto not_applicable;
if (section->version_number == stream->section_version_number) if (section->version_number == subtable->version_number)
goto not_applicable; goto not_applicable;
subtable->version_number = section->version_number;
stream->section_version_number = section->version_number;
return TRUE; return TRUE;
not_applicable: not_applicable:
GST_LOG
("not applicable pid %d table_id %d subtable_extension %d, current_next %d version %d",
section->pid, section->table_id, section->subtable_extension,
section->current_next_indicator, section->version_number);
section->complete = FALSE; section->complete = FALSE;
gst_buffer_unref (section->buffer); gst_buffer_unref (section->buffer);
return TRUE; return TRUE;
@ -504,6 +557,7 @@ mpegts_packetizer_parse_nit (MpegTSPacketizer * packetizer,
GValueArray *descriptors = NULL; GValueArray *descriptors = NULL;
gchar *dbg_str; gchar *dbg_str;
GST_DEBUG ("NIT");
/* fixed header + CRC == 16 */ /* fixed header + CRC == 16 */
if (GST_BUFFER_SIZE (section->buffer) < 23) { if (GST_BUFFER_SIZE (section->buffer) < 23) {
GST_WARNING ("PID %d invalid NIT size %d", GST_WARNING ("PID %d invalid NIT size %d",
@ -670,6 +724,7 @@ mpegts_packetizer_parse_sdt (MpegTSPacketizer * packetizer,
GValue service_value = { 0 }; GValue service_value = { 0 };
gchar *dbg_str; gchar *dbg_str;
GST_DEBUG ("SDT");
/* fixed header + CRC == 16 */ /* fixed header + CRC == 16 */
if (GST_BUFFER_SIZE (section->buffer) < 14) { if (GST_BUFFER_SIZE (section->buffer) < 14) {
GST_WARNING ("PID %d invalid SDT size %d", GST_WARNING ("PID %d invalid SDT size %d",
@ -1058,11 +1113,10 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
gboolean res = FALSE; gboolean res = FALSE;
MpegTSPacketizerStream *stream; MpegTSPacketizerStream *stream;
guint8 pointer, table_id; guint8 pointer, table_id;
guint16 sub_table_extension; guint16 subtable_extension;
guint section_length; guint section_length;
GstBuffer *sub_buf; GstBuffer *sub_buf;
guint8 *data; guint8 *data;
gchar *sub_table_identifier;
g_return_val_if_fail (GST_IS_MPEGTS_PACKETIZER (packetizer), FALSE); g_return_val_if_fail (GST_IS_MPEGTS_PACKETIZER (packetizer), FALSE);
g_return_val_if_fail (packet != NULL, FALSE); g_return_val_if_fail (packet != NULL, FALSE);
@ -1081,59 +1135,65 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
data += pointer; data += pointer;
} }
table_id = *data++;
/* sub_table_extension should be read from 4th and 5th bytes only if
* section_syntax_indicator is 1 */
if ((data[0] & 0x80) == 0)
sub_table_extension = 0;
else
sub_table_extension = GST_READ_UINT16_BE (data + 2);
sub_table_identifier =
g_strdup_printf ("%d,%d", table_id, sub_table_extension);
GST_DEBUG ("sub table identifier is: %s", sub_table_identifier);
stream = (MpegTSPacketizerStream *) g_hash_table_lookup (packetizer->streams,
sub_table_identifier);
if (stream == NULL) {
stream = mpegts_packetizer_stream_new (table_id, sub_table_extension);
g_hash_table_insert (packetizer->streams, sub_table_identifier, stream);
} else {
g_free (sub_table_identifier);
}
section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
data += 2;
/* 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_create_sub (packet->buffer,
data - 3 - GST_BUFFER_DATA (packet->buffer), packet->data_end - data + 3); data - GST_BUFFER_DATA (packet->buffer), packet->data_end - data);
stream = (MpegTSPacketizerStream *) g_hash_table_lookup (packetizer->streams,
GINT_TO_POINTER ((gint) packet->pid));
if (stream == NULL) {
stream = mpegts_packetizer_stream_new ();
g_hash_table_insert (packetizer->streams,
GINT_TO_POINTER ((gint) packet->pid), stream);
}
if (packet->payload_unit_start_indicator) { if (packet->payload_unit_start_indicator) {
table_id = *data++;
/* subtable_extension should be read from 4th and 5th bytes only if
* section_syntax_indicator is 1 */
if ((data[0] & 0x80) == 0)
subtable_extension = 0;
else
subtable_extension = GST_READ_UINT16_BE (data + 2);
GST_DEBUG ("pid: %d table_id %d sub_table_extension %d",
packet->pid, table_id, subtable_extension);
section_length = GST_READ_UINT16_BE (data) & 0x0FFF;
if (stream->continuity_counter != CONTINUITY_UNSET) { if (stream->continuity_counter != CONTINUITY_UNSET) {
GST_WARNING ("PID %d payload_unit_start_indicator set but section " GST_DEBUG
("PID %d table_id %d sub_table_extension %d payload_unit_start_indicator set but section "
"not complete (last_continuity: %d continuity: %d sec len %d buffer %d avail %d", "not complete (last_continuity: %d continuity: %d sec len %d buffer %d avail %d",
packet->pid, stream->continuity_counter, packet->continuity_counter, packet->pid, table_id, subtable_extension, stream->continuity_counter,
section_length, GST_BUFFER_SIZE (sub_buf), packet->continuity_counter, section_length, GST_BUFFER_SIZE (sub_buf),
gst_adapter_available (stream->section_adapter)); gst_adapter_available (stream->section_adapter));
mpegts_packetizer_clear_section (packetizer, stream); mpegts_packetizer_clear_section (packetizer, stream);
} else {
GST_DEBUG
("pusi set and new stream section is %d long and data we have is: %d",
section_length, packet->data_end - packet->data);
} }
stream->continuity_counter = packet->continuity_counter; stream->continuity_counter = packet->continuity_counter;
stream->section_length = section_length; stream->section_length = section_length;
gst_adapter_push (stream->section_adapter, sub_buf); gst_adapter_push (stream->section_adapter, sub_buf);
res = TRUE; res = TRUE;
} else if (packet->continuity_counter == stream->continuity_counter + 1 || } else if (stream->continuity_counter != CONTINUITY_UNSET &&
(stream->continuity_counter == MAX_CONTINUITY && (packet->continuity_counter == stream->continuity_counter + 1 ||
packet->continuity_counter == 0)) { (stream->continuity_counter == MAX_CONTINUITY &&
packet->continuity_counter == 0))) {
stream->continuity_counter = packet->continuity_counter; stream->continuity_counter = packet->continuity_counter;
gst_adapter_push (stream->section_adapter, sub_buf); gst_adapter_push (stream->section_adapter, sub_buf);
res = TRUE; res = TRUE;
} else { } else {
GST_WARNING ("PID %d section discontinuity " if (stream->continuity_counter == CONTINUITY_UNSET)
"(last_continuity: %d continuity: %d", packet->pid, GST_DEBUG ("PID %d waiting for pusi", packet->pid);
stream->continuity_counter, packet->continuity_counter); else
GST_DEBUG ("PID %d section discontinuity "
"(last_continuity: %d continuity: %d", packet->pid,
stream->continuity_counter, packet->continuity_counter);
mpegts_packetizer_clear_section (packetizer, stream); mpegts_packetizer_clear_section (packetizer, stream);
gst_buffer_unref (sub_buf); gst_buffer_unref (sub_buf);
} }
@ -1146,7 +1206,6 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
* section_length */ * section_length */
if (gst_adapter_available (stream->section_adapter) >= if (gst_adapter_available (stream->section_adapter) >=
stream->section_length + 3) { stream->section_length + 3) {
res = mpegts_packetizer_parse_section_header (packetizer, res = mpegts_packetizer_parse_section_header (packetizer,
stream, section); stream, section);
@ -1157,6 +1216,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer * packetizer,
section->complete = FALSE; section->complete = FALSE;
} }
} else { } else {
GST_WARNING ("section not complete");
section->complete = FALSE; section->complete = FALSE;
} }

View file

@ -49,6 +49,7 @@ struct _MpegTSPacketizer {
GObject object; GObject object;
GstAdapter *adapter; GstAdapter *adapter;
/* streams hashed by pid */
GHashTable *streams; GHashTable *streams;
gboolean disposed; gboolean disposed;
}; };
@ -78,6 +79,7 @@ typedef struct
GstBuffer *buffer; GstBuffer *buffer;
gint16 pid; gint16 pid;
guint8 table_id; guint8 table_id;
guint16 subtable_extension;
guint section_length; guint section_length;
guint8 version_number; guint8 version_number;
guint8 current_next_indicator; guint8 current_next_indicator;