From 0592bcc3c90125f8a9a68ee8e8940176b9c8cc97 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 19 Jun 2013 20:39:54 +0200 Subject: [PATCH] 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 --- gst/mpegtsdemux/mpegtspacketizer.c | 48 +++++++++++++++++++++++++++--- gst/mpegtsdemux/mpegtspacketizer.h | 2 +- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 3871945b83..11d6e8269a 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -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; diff --git a/gst/mpegtsdemux/mpegtspacketizer.h b/gst/mpegtsdemux/mpegtspacketizer.h index 78a4008912..b6e1aafa44 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.h +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -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 {