mpegtspacketizer: Better detect already seen section

In some cases (NIT on highly-populated DVB-C operator for example), there
will be more than one section emitted for the same subtable and version
number.

In order not to lose those updates for the same version number, we checked
against the CRC of the previous section we parsed.

The problem is that, while it made sure we didn't lose any information, it
also meant that if the same section came back (same version, same CRC) later
on we would re-process it, re-parse it and re-emit it.

This version improves on that by keeping a list of previously observed CRC
for identical PID/subtable/version-number and will only process sections if
they really were never seen in the past (as opposed to just before).

On a 30s clip, this brings down the number of NIT section parsing from 4541
down to 663.

https://bugzilla.gnome.org/show_bug.cgi?id=614479
This commit is contained in:
Edward Hervey 2013-06-19 20:39:54 +02:00
parent e2b83ff8a0
commit 0592bcc3c9
2 changed files with 45 additions and 5 deletions

View file

@ -320,6 +320,18 @@ mpegts_packetizer_stream_subtable_compare (gconstpointer a, gconstpointer b)
return -1;
}
static gboolean
saw_subtable_crc (GList * list, guint32 crc)
{
GList *tmp;
for (tmp = list; tmp; tmp = tmp->next)
if (GPOINTER_TO_UINT (tmp->data) == crc)
return TRUE;
return FALSE;
}
static MpegTSPacketizerStreamSubtable *
mpegts_packetizer_stream_subtable_new (guint8 table_id,
guint16 subtable_extension)
@ -330,7 +342,7 @@ mpegts_packetizer_stream_subtable_new (guint8 table_id,
subtable->version_number = VERSION_NUMBER_UNSET;
subtable->table_id = table_id;
subtable->subtable_extension = subtable_extension;
subtable->crc = 0;
subtable->crc = NULL;
return subtable;
}
@ -355,13 +367,22 @@ mpegts_packetizer_clear_section (MpegTSPacketizerStream * stream)
stream->section_table_id = TABLE_ID_UNSET;
}
static void
mpegts_packetizer_stream_subtable_free (MpegTSPacketizerStreamSubtable *
subtable)
{
g_list_free (subtable->crc);
g_free (subtable);
}
static void
mpegts_packetizer_stream_free (MpegTSPacketizerStream * stream)
{
mpegts_packetizer_clear_section (stream);
if (stream->section_data)
g_free (stream->section_data);
g_slist_foreach (stream->subtables, (GFunc) g_free, NULL);
g_slist_foreach (stream->subtables,
(GFunc) mpegts_packetizer_stream_subtable_free, NULL);
g_slist_free (stream->subtables);
g_free (stream);
}
@ -626,9 +647,15 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
subtable_list = g_slist_find_custom (stream->subtables, subtable,
mpegts_packetizer_stream_subtable_compare);
if (subtable_list) {
GST_DEBUG ("Found previous subtable_extension:%d",
section->subtable_extension);
g_free (subtable);
subtable = (MpegTSPacketizerStreamSubtable *) (subtable_list->data);
} else {
GST_DEBUG ("Appending new subtable_extension:%d",
section->subtable_extension);
stream->subtables = g_slist_prepend (stream->subtables, subtable);
}
@ -657,12 +684,25 @@ mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer,
crc_data = section->data + section->section_length - 4;
section->crc = GST_READ_UINT32_BE (crc_data);
/* If the section version number hasn't changed and we have
* already seen this exact section before, don't process further
*/
if (section->version_number == subtable->version_number &&
section->crc == subtable->crc)
saw_subtable_crc (subtable->crc, section->crc))
goto no_changes;
/* If the version number changed, reset our observations */
if (section->version_number != subtable->version_number)
g_list_free (subtable->crc);
GST_DEBUG
("section changed. pid 0x%04x table_id 0x%03x subtable_extension %d version number:%d (previous%d) crc 0x%x",
section->pid, section->table_id, section->subtable_extension,
section->version_number, subtable->version_number, section->crc);
subtable->version_number = section->version_number;
subtable->crc = section->crc;
subtable->crc =
g_list_prepend (subtable->crc, GUINT_TO_POINTER (section->crc));
stream->section_table_id = section->table_id;
return TRUE;

View file

@ -154,7 +154,7 @@ typedef struct
* section_syntax_indicator is 0, sub_table_extension will be set to 0 */
guint16 subtable_extension;
guint8 version_number;
guint32 crc;
GList * crc;
} MpegTSPacketizerStreamSubtable;
typedef enum {