diff -uNr libdvbpsi-trunk/src/Makefile.am libdvbpsi-trunk+nit/src/Makefile.am
--- libdvbpsi-trunk/src/Makefile.am	2008-04-23 18:45:32.000000000 +0200
+++ libdvbpsi-trunk+nit/src/Makefile.am	2008-04-24 18:01:07.000000000 +0200
@@ -15,7 +15,7 @@
 
 pkginclude_HEADERS = dvbpsi.h psi.h descriptor.h demux.h \
                      tables/pat.h tables/pmt.h tables/sdt.h tables/eit.h \
-                     tables/cat.h \
+                     tables/cat.h tables/nit.h \
                      descriptors/dr_02.h \
                      descriptors/dr_03.h \
                      descriptors/dr_04.h \
@@ -73,5 +73,6 @@
              tables/pmt.c tables/pmt_private.h \
              tables/sdt.c tables/sdt_private.h \
              tables/eit.c tables/eit_private.h \
-             tables/cat.c tables/cat_private.h
+             tables/cat.c tables/cat_private.h \
+             tables/nit.c tables/nit_private.h
 
diff -uNr libdvbpsi-trunk/src/tables/nit.c libdvbpsi-trunk+nit/src/tables/nit.c
--- libdvbpsi-trunk/src/tables/nit.c	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi-trunk+nit/src/tables/nit.c	2008-04-24 18:00:00.000000000 +0200
@@ -0,0 +1,751 @@
+/*****************************************************************************
+ * nit.c: NIT decoder/generator
+ *----------------------------------------------------------------------------
+ * (c)2001-2008 VideoLAN
+ * $Id: $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.c which was written by
+ *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *----------------------------------------------------------------------------
+ *
+ *****************************************************************************/
+
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#elif defined(HAVE_STDINT_H)
+#include <stdint.h>
+#endif
+
+#include "../dvbpsi.h"
+#include "../dvbpsi_private.h"
+#include "../psi.h"
+#include "../descriptor.h"
+#include "../demux.h"
+#include "nit.h"
+#include "nit_private.h"
+
+
+/*****************************************************************************
+ * dvbpsi_AttachNIT
+ *****************************************************************************
+ * Initialize a NIT subtable decoder.
+ *****************************************************************************/
+int dvbpsi_AttachNIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
+                     uint16_t i_extension, dvbpsi_nit_callback pf_callback,
+                     void* p_cb_data)
+{
+  dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_decoder;
+  dvbpsi_demux_subdec_t* p_subdec;
+  dvbpsi_nit_decoder_t*  p_nit_decoder;
+  unsigned int i;
+
+  if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
+  {
+    DVBPSI_ERROR_ARG("NIT decoder",
+                     "Already a decoder for (table_id == 0x%02x,"
+                     "extension == 0x%02x)",
+                     i_table_id, i_extension);
+
+    return 1;
+  }
+
+  p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
+  if(p_subdec == NULL)
+  {
+    return 1;
+  }
+
+  p_nit_decoder = (dvbpsi_nit_decoder_t*)malloc(sizeof(dvbpsi_nit_decoder_t));
+
+  if(p_nit_decoder == NULL)
+  {
+    free(p_subdec);
+    return 1;
+  }
+
+  /* subtable decoder configuration */
+  p_subdec->pf_callback = &dvbpsi_GatherNITSections;
+  p_subdec->p_cb_data = p_nit_decoder;
+  p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension;
+  p_subdec->pf_detach = dvbpsi_DetachNIT;
+
+  /* Attach the subtable decoder to the demux */
+  p_subdec->p_next = p_demux->p_first_subdec;
+  p_demux->p_first_subdec = p_subdec;
+
+  /* NIT decoder information */
+  p_nit_decoder->i_network_id = i_extension;
+  p_nit_decoder->pf_callback = pf_callback;
+  p_nit_decoder->p_cb_data = p_cb_data;
+  /* NIT decoder initial state */
+  p_nit_decoder->b_current_valid = 0;
+  p_nit_decoder->p_building_nit = NULL;
+  for(i = 0; i <= 255; i++)
+    p_nit_decoder->ap_sections[i] = NULL;
+
+  return 0;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_DetachNIT
+ *****************************************************************************
+ * Close a NIT decoder.
+ *****************************************************************************/
+void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
+                      uint16_t i_extension)
+{
+  dvbpsi_demux_subdec_t* p_subdec;
+  dvbpsi_demux_subdec_t** pp_prev_subdec;
+  dvbpsi_nit_decoder_t* p_nit_decoder;
+
+  unsigned int i;
+
+  p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
+
+  if(p_demux == NULL)
+  {
+    DVBPSI_ERROR_ARG("NIT Decoder",
+                     "No such NIT decoder (table_id == 0x%02x,"
+                     "extension == 0x%02x)",
+                     i_table_id, i_extension);
+    return;
+  }
+
+  p_nit_decoder = (dvbpsi_nit_decoder_t*)p_subdec->p_cb_data;
+
+  free(p_nit_decoder->p_building_nit);
+
+  for(i = 0; i <= 255; i++)
+  {
+    if(p_nit_decoder->ap_sections[i])
+      dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[i]);
+  }
+
+  free(p_subdec->p_cb_data);
+
+  pp_prev_subdec = &p_demux->p_first_subdec;
+  while(*pp_prev_subdec != p_subdec)
+    pp_prev_subdec = &(*pp_prev_subdec)->p_next;
+
+  *pp_prev_subdec = p_subdec->p_next;
+  free(p_subdec);
+}
+
+
+/*****************************************************************************
+ * dvbpsi_InitNIT
+ *****************************************************************************
+ * Initialize a pre-allocated dvbpsi_nit_t structure.
+ *****************************************************************************/
+void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id,
+                    uint8_t i_version, int b_current_next)
+{
+  p_nit->i_network_id = i_network_id;
+  p_nit->i_version = i_version;
+  p_nit->b_current_next = b_current_next;
+  p_nit->p_first_descriptor = NULL;
+  p_nit->p_first_ts = NULL;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_EmptyNIT
+ *****************************************************************************
+ * Clean a dvbpsi_nit_t structure.
+ *****************************************************************************/
+void dvbpsi_EmptyNIT(dvbpsi_nit_t* p_nit)
+{
+  dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
+
+  dvbpsi_DeleteDescriptors(p_nit->p_first_descriptor);
+
+  while(p_ts != NULL)
+  {
+    dvbpsi_nit_ts_t* p_tmp = p_ts->p_next;
+    dvbpsi_DeleteDescriptors(p_ts->p_first_descriptor);
+    free(p_ts);
+    p_ts = p_tmp;
+  }
+
+  p_nit->p_first_descriptor = NULL;
+  p_nit->p_first_ts = NULL;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_NITAddDescriptor
+ *****************************************************************************
+ * Add a descriptor in the NIT.
+ *****************************************************************************/
+dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
+                                             uint8_t i_tag, uint8_t i_length,
+                                             uint8_t* p_data)
+{
+  dvbpsi_descriptor_t* p_descriptor
+                        = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
+
+  if(p_descriptor)
+  {
+    if(p_nit->p_first_descriptor == NULL)
+    {
+      p_nit->p_first_descriptor = p_descriptor;
+    }
+    else
+    {
+      dvbpsi_descriptor_t* p_last_descriptor = p_nit->p_first_descriptor;
+      while(p_last_descriptor->p_next != NULL)
+        p_last_descriptor = p_last_descriptor->p_next;
+      p_last_descriptor->p_next = p_descriptor;
+    }
+  }
+
+  return p_descriptor;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_NITAddTS
+ *****************************************************************************
+ * Add an TS in the NIT.
+ *****************************************************************************/
+dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit,
+                                 uint16_t i_ts_id, uint16_t i_orig_network_id)
+{
+  dvbpsi_nit_ts_t* p_ts = (dvbpsi_nit_ts_t*)malloc(sizeof(dvbpsi_nit_ts_t));
+
+  if(p_ts)
+  {
+    p_ts->i_ts_id = i_ts_id;
+    p_ts->i_orig_network_id = i_orig_network_id;
+    p_ts->p_first_descriptor = NULL;
+    p_ts->p_next = NULL;
+
+    if(p_nit->p_first_ts == NULL)
+    {
+      p_nit->p_first_ts = p_ts;
+    }
+    else
+    {
+      dvbpsi_nit_ts_t* p_last_ts = p_nit->p_first_ts;
+      while(p_last_ts->p_next != NULL)
+        p_last_ts = p_last_ts->p_next;
+      p_last_ts->p_next = p_ts;
+    }
+  }
+
+  return p_ts;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_NITTSAddDescriptor
+ *****************************************************************************
+ * Add a descriptor in the NIT TS.
+ *****************************************************************************/
+dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts,
+                                               uint8_t i_tag, uint8_t i_length,
+                                               uint8_t* p_data)
+{
+  dvbpsi_descriptor_t* p_descriptor
+                        = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
+
+  if(p_descriptor)
+  {
+    if(p_ts->p_first_descriptor == NULL)
+    {
+      p_ts->p_first_descriptor = p_descriptor;
+    }
+    else
+    {
+      dvbpsi_descriptor_t* p_last_descriptor = p_ts->p_first_descriptor;
+      while(p_last_descriptor->p_next != NULL)
+        p_last_descriptor = p_last_descriptor->p_next;
+      p_last_descriptor->p_next = p_descriptor;
+    }
+  }
+
+  return p_descriptor;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_GatherNITSections
+ *****************************************************************************
+ * Callback for the PSI decoder.
+ *****************************************************************************/
+void dvbpsi_GatherNITSections(dvbpsi_decoder_t * p_decoder,
+                              void * p_private_decoder,
+                              dvbpsi_psi_section_t * p_section)
+{
+  dvbpsi_nit_decoder_t* p_nit_decoder
+                        = (dvbpsi_nit_decoder_t*)p_private_decoder;
+  int b_append = 1;
+  int b_reinit = 0;
+  unsigned int i;
+
+  DVBPSI_DEBUG_ARG("NIT decoder",
+                   "Table version %2d, " "i_extension %5d, "
+                   "section %3d up to %3d, " "current %1d",
+                   p_section->i_version, p_section->i_extension,
+                   p_section->i_number, p_section->i_last_number,
+                   p_section->b_current_next);
+
+  if(p_section->i_table_id != 0x40 && p_section->i_table_id != 0x41)
+  {
+    /* Invalid table_id value */
+    DVBPSI_ERROR_ARG("NIT decoder",
+                     "invalid section (table_id == 0x%02x)",
+                     p_section->i_table_id);
+    b_append = 0;
+  }
+
+  if(b_append && !p_section->b_syntax_indicator)
+  {
+    /* Invalid section_syntax_indicator */
+    DVBPSI_ERROR("NIT decoder",
+                 "invalid section (section_syntax_indicator == 0)");
+    b_append = 0;
+  }
+
+  /* Now if b_append is true then we have a valid NIT section */
+  if(b_append && (p_nit_decoder->i_network_id != p_section->i_extension))
+  {
+    /* Invalid program_number */
+#if 0
+    DVBPSI_ERROR("NIT decoder", "'network_id' don't match");
+#endif
+    b_append = 0;
+  }
+
+  if(b_append)
+  {
+    /* TS discontinuity check */
+    if(p_decoder->b_discontinuity)
+    {
+      b_reinit = 1;
+      p_decoder->b_discontinuity = 0;
+    }
+    else
+    {
+      /* Perform some few sanity checks */
+      if(p_nit_decoder->p_building_nit)
+      {
+        if(p_nit_decoder->p_building_nit->i_version != p_section->i_version)
+        {
+          /* version_number */
+          DVBPSI_ERROR("NIT decoder",
+                       "'version_number' differs"
+                       " whereas no discontinuity has occured");
+          b_reinit = 1;
+        }
+        else if(p_nit_decoder->i_last_section_number
+                                                != p_section->i_last_number)
+        {
+          /* last_section_number */
+          DVBPSI_ERROR("NIT decoder",
+                       "'last_section_number' differs"
+                       " whereas no discontinuity has occured");
+          b_reinit = 1;
+        }
+      }
+      else
+      {
+        if(    (p_nit_decoder->b_current_valid)
+            && (p_nit_decoder->current_nit.i_version == p_section->i_version))
+        {
+          /* Signal a new NIT if the previous one wasn't active */
+          if(    (!p_nit_decoder->current_nit.b_current_next)
+              && (p_section->b_current_next))
+          {
+            dvbpsi_nit_t* p_nit = (dvbpsi_nit_t*)malloc(sizeof(dvbpsi_nit_t));
+
+            p_nit_decoder->current_nit.b_current_next = 1;
+            *p_nit = p_nit_decoder->current_nit;
+            p_nit_decoder->pf_callback(p_nit_decoder->p_cb_data, p_nit);
+          }
+
+          /* Don't decode since this version is already decoded */
+          b_append = 0;
+        }
+      }
+    }
+  }
+
+  /* Reinit the decoder if wanted */
+  if(b_reinit)
+  {
+    /* Force redecoding */
+    p_nit_decoder->b_current_valid = 0;
+    /* Free structures */
+    if(p_nit_decoder->p_building_nit)
+    {
+      free(p_nit_decoder->p_building_nit);
+      p_nit_decoder->p_building_nit = NULL;
+    }
+    /* Clear the section array */
+    for(i = 0; i <= 255; i++)
+    {
+      if(p_nit_decoder->ap_sections[i] != NULL)
+      {
+        dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[i]);
+        p_nit_decoder->ap_sections[i] = NULL;
+      }
+    }
+  }
+
+  /* Append the section to the list if wanted */
+  if(b_append)
+  {
+    int b_complete;
+
+    /* Initialize the structures if it's the first section received */
+    if(!p_nit_decoder->p_building_nit)
+    {
+      p_nit_decoder->p_building_nit =
+                                (dvbpsi_nit_t*)malloc(sizeof(dvbpsi_nit_t));
+      dvbpsi_InitNIT(p_nit_decoder->p_building_nit,
+                     p_nit_decoder->i_network_id,
+                     p_section->i_version,
+                     p_section->b_current_next);
+      p_nit_decoder->i_last_section_number = p_section->i_last_number;
+    }
+
+    /* Fill the section array */
+    if(p_nit_decoder->ap_sections[p_section->i_number] != NULL)
+    {
+      DVBPSI_DEBUG_ARG("NIT decoder", "overwrite section number %d",
+                       p_section->i_number);
+      dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[p_section->i_number]);
+    }
+    p_nit_decoder->ap_sections[p_section->i_number] = p_section;
+
+    /* Check if we have all the sections */
+    b_complete = 0;
+    for(i = 0; i <= p_nit_decoder->i_last_section_number; i++)
+    {
+      if(!p_nit_decoder->ap_sections[i])
+        break;
+
+      if(i == p_nit_decoder->i_last_section_number)
+        b_complete = 1;
+    }
+
+    if(b_complete)
+    {
+      /* Save the current information */
+      p_nit_decoder->current_nit = *p_nit_decoder->p_building_nit;
+      p_nit_decoder->b_current_valid = 1;
+      /* Chain the sections */
+      if(p_nit_decoder->i_last_section_number)
+      {
+        for(i = 0; i <= p_nit_decoder->i_last_section_number - 1; i++)
+          p_nit_decoder->ap_sections[i]->p_next =
+                                        p_nit_decoder->ap_sections[i + 1];
+      }
+      /* Decode the sections */
+      dvbpsi_DecodeNITSections(p_nit_decoder->p_building_nit,
+                               p_nit_decoder->ap_sections[0]);
+      /* Delete the sections */
+      dvbpsi_DeletePSISections(p_nit_decoder->ap_sections[0]);
+      /* signal the new NIT */
+      p_nit_decoder->pf_callback(p_nit_decoder->p_cb_data,
+                                 p_nit_decoder->p_building_nit);
+      /* Reinitialize the structures */
+      p_nit_decoder->p_building_nit = NULL;
+      for(i = 0; i <= p_nit_decoder->i_last_section_number; i++)
+        p_nit_decoder->ap_sections[i] = NULL;
+    }
+  }
+  else
+  {
+    dvbpsi_DeletePSISections(p_section);
+  }
+}
+
+
+/*****************************************************************************
+ * dvbpsi_DecodeNITSections
+ *****************************************************************************
+ * NIT decoder.
+ *****************************************************************************/
+void dvbpsi_DecodeNITSections(dvbpsi_nit_t* p_nit,
+                              dvbpsi_psi_section_t* p_section)
+{
+  uint8_t* p_byte, * p_end, * p_end2;
+
+  while(p_section)
+  {
+    /* - NIT descriptors */
+    p_byte = p_section->p_payload_start + 2;
+    p_end = p_byte + (   ((uint16_t)(p_section->p_payload_start[0] & 0x0f) << 8)
+                       | p_section->p_payload_start[1]);
+
+    while(p_byte + 2 <= p_end)
+    {
+      uint8_t i_tag = p_byte[0];
+      uint8_t i_length = p_byte[1];
+      if(i_length + 2 <= p_end - p_byte)
+        dvbpsi_NITAddDescriptor(p_nit, i_tag, i_length, p_byte + 2);
+      p_byte += 2 + i_length;
+    }
+
+    p_end = p_byte + (   ((uint16_t)(p_byte[0] & 0x0f) << 8)
+                       | p_byte[1]);
+    if(p_end > p_section->p_payload_end)
+    {
+        p_end = p_section->p_payload_end;
+    }
+    p_byte += 2;
+
+    /* - TSs */
+    for(; p_byte + 6 <= p_end;)
+    {
+      uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1];
+      uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3];
+      uint16_t i_length = ((uint16_t)(p_byte[4] & 0x0f) << 8) | p_byte[5];
+      dvbpsi_nit_ts_t* p_ts = dvbpsi_NITAddTS(p_nit, i_ts_id, i_orig_network_id);
+      /* - TS descriptors */
+      p_byte += 6;
+      p_end2 = p_byte + i_length;
+      if( p_end2 > p_section->p_payload_end )
+      {
+            p_end2 = p_section->p_payload_end;
+      }
+      while(p_byte + 2 <= p_end2)
+      {
+        uint8_t i_tag = p_byte[0];
+        uint8_t i_length = p_byte[1];
+        if(i_length + 2 <= p_end2 - p_byte)
+          dvbpsi_NITTSAddDescriptor(p_ts, i_tag, i_length, p_byte + 2);
+        p_byte += 2 + i_length;
+      }
+    }
+
+    p_section = p_section->p_next;
+  }
+}
+
+
+/*****************************************************************************
+ * dvbpsi_GenNITSections
+ *****************************************************************************
+ * Generate NIT sections based on the dvbpsi_nit_t structure.
+ *****************************************************************************/
+dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit,
+                                            uint8_t i_table_id)
+{
+  dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
+  dvbpsi_psi_section_t* p_current = p_result;
+  dvbpsi_psi_section_t* p_prev;
+  dvbpsi_descriptor_t* p_descriptor = p_nit->p_first_descriptor;
+  dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
+  uint16_t i_network_descriptors_length, i_transport_stream_loop_length;
+  uint8_t * p_transport_stream_loop_length;
+
+  p_current->i_table_id = i_table_id;
+  p_current->b_syntax_indicator = 1;
+  p_current->b_private_indicator = 0;
+  p_current->i_length = 13;                     /* including CRC_32 */
+  p_current->i_extension = p_nit->i_network_id;
+  p_current->i_version = p_nit->i_version;
+  p_current->b_current_next = p_nit->b_current_next;
+  p_current->i_number = 0;
+  p_current->p_payload_end += 10;
+  p_current->p_payload_start = p_current->p_data + 8;
+
+  /* NIT descriptors */
+  while(p_descriptor != NULL)
+  {
+    /* New section if needed */
+    /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
+    if(   (p_current->p_payload_end - p_current->p_data)
+                                + p_descriptor->i_length > 1018)
+    {
+      /* network_descriptors_length */
+      i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
+      p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0;
+      p_current->p_data[9] = i_network_descriptors_length;
+
+      /* transport_stream_loop_length */
+      p_current->p_payload_end[0] = 0;
+      p_current->p_payload_end[1] = 0;
+      p_current->p_payload_end += 2;
+
+      p_prev = p_current;
+      p_current = dvbpsi_NewPSISection(1024);
+      p_prev->p_next = p_current;
+
+      p_current->i_table_id = i_table_id;
+      p_current->b_syntax_indicator = 1;
+      p_current->b_private_indicator = 0;
+      p_current->i_length = 13;                 /* including CRC_32 */
+      p_current->i_extension = p_nit->i_network_id;
+      p_current->i_version = p_nit->i_version;
+      p_current->b_current_next = p_nit->b_current_next;
+      p_current->i_number = p_prev->i_number + 1;
+      p_current->p_payload_end += 10;
+      p_current->p_payload_start = p_current->p_data + 8;
+    }
+
+    /* p_payload_end is where the descriptor begins */
+    p_current->p_payload_end[0] = p_descriptor->i_tag;
+    p_current->p_payload_end[1] = p_descriptor->i_length;
+    memcpy(p_current->p_payload_end + 2,
+           p_descriptor->p_data,
+           p_descriptor->i_length);
+
+    /* Increase length by descriptor_length + 2 */
+    p_current->p_payload_end += p_descriptor->i_length + 2;
+    p_current->i_length += p_descriptor->i_length + 2;
+
+    p_descriptor = p_descriptor->p_next;
+  }
+
+  /* network_descriptors_length */
+  i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
+  p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0;
+  p_current->p_data[9] = i_network_descriptors_length;
+
+  /* Store the position of the transport_stream_loop_length field
+     and reserve two bytes for it */
+  p_transport_stream_loop_length = p_current->p_payload_end;
+  p_current->p_payload_end += 2;
+
+  /* NIT TSs */
+  while(p_ts != NULL)
+  {
+    uint8_t* p_ts_start = p_current->p_payload_end;
+    uint16_t i_ts_length = 5;
+
+    /* Can the current section carry all the descriptors ? */
+    p_descriptor = p_ts->p_first_descriptor;
+    while(    (p_descriptor != NULL)
+           && ((p_ts_start - p_current->p_data) + i_ts_length <= 1020))
+    {
+      i_ts_length += p_descriptor->i_length + 2;
+      p_descriptor = p_descriptor->p_next;
+    }
+
+    /* If _no_ and the current section isn't empty and an empty section
+       may carry one more descriptor
+       then create a new section */
+    if(    (p_descriptor != NULL)
+        && (p_ts_start - p_current->p_data != 12)
+        && (i_ts_length <= 1008))
+    {
+      /* transport_stream_loop_length */
+      i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
+      p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
+      p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
+
+      /* will put more descriptors in an empty section */
+      DVBPSI_DEBUG("NIT generator",
+                   "create a new section to carry more TS descriptors");
+      p_prev = p_current;
+      p_current = dvbpsi_NewPSISection(1024);
+      p_prev->p_next = p_current;
+
+      p_current->i_table_id = i_table_id;
+      p_current->b_syntax_indicator = 1;
+      p_current->b_private_indicator = 0;
+      p_current->i_length = 13;                 /* including CRC_32 */
+      p_current->i_extension = p_nit->i_network_id;
+      p_current->i_version = p_nit->i_version;
+      p_current->b_current_next = p_nit->b_current_next;
+      p_current->i_number = p_prev->i_number + 1;
+      p_current->p_payload_end += 10;
+      p_current->p_payload_start = p_current->p_data + 8;
+
+      /* network_descriptors_length = 0 */
+      p_current->p_data[8] = 0xf0;
+      p_current->p_data[9] = 0x00;
+
+      /* Store the position of the transport_stream_loop_length field
+         and reserve two bytes for it */
+      p_transport_stream_loop_length = p_current->p_payload_end;
+      p_current->p_payload_end += 2;
+
+      p_ts_start = p_current->p_payload_end;
+    }
+
+    /* p_ts_start is where the TS begins */
+    p_ts_start[0] = p_ts->i_ts_id >> 8;
+    p_ts_start[1] = p_ts->i_ts_id & 0xff;
+    p_ts_start[2] = p_ts->i_orig_network_id >> 8;
+    p_ts_start[3] = p_ts->i_orig_network_id & 0xff;
+
+    /* Increase the length by 6 */
+    p_current->p_payload_end += 6;
+    p_current->i_length += 6;
+
+    /* TS descriptors */
+    p_descriptor = p_ts->p_first_descriptor;
+    while(    (p_descriptor != NULL)
+           && (   (p_current->p_payload_end - p_current->p_data)
+                + p_descriptor->i_length <= 1018))
+    {
+      /* p_payload_end is where the descriptor begins */
+      p_current->p_payload_end[0] = p_descriptor->i_tag;
+      p_current->p_payload_end[1] = p_descriptor->i_length;
+      memcpy(p_current->p_payload_end + 2,
+             p_descriptor->p_data,
+             p_descriptor->i_length);
+
+      /* Increase length by descriptor_length + 2 */
+      p_current->p_payload_end += p_descriptor->i_length + 2;
+      p_current->i_length += p_descriptor->i_length + 2;
+
+      p_descriptor = p_descriptor->p_next;
+    }
+
+    if(p_descriptor != NULL)
+      DVBPSI_ERROR("NIT generator", "unable to carry all the TS descriptors");
+
+    /* TS_info_length */
+    i_ts_length = p_current->p_payload_end - p_ts_start - 5;
+    p_ts_start[4] = (i_ts_length >> 8) | 0xf0;
+    p_ts_start[5] = i_ts_length;
+
+    p_ts = p_ts->p_next;
+  }
+
+  /* transport_stream_loop_length */
+  i_transport_stream_loop_length = (p_current->p_payload_end - p_transport_stream_loop_length) - 2;
+  p_transport_stream_loop_length[0] = (i_transport_stream_loop_length >> 8) | 0xf0;
+  p_transport_stream_loop_length[1] = i_transport_stream_loop_length;
+
+  /* Finalization */
+  p_prev = p_result;
+  while(p_prev != NULL)
+  {
+    p_prev->i_last_number = p_current->i_number;
+    dvbpsi_BuildPSISection(p_prev);
+    p_prev = p_prev->p_next;
+  }
+
+  return p_result;
+}
diff -uNr libdvbpsi-trunk/src/tables/nit.h libdvbpsi-trunk+nit/src/tables/nit.h
--- libdvbpsi-trunk/src/tables/nit.h	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi-trunk+nit/src/tables/nit.h	2008-04-24 18:00:00.000000000 +0200
@@ -0,0 +1,287 @@
+/*****************************************************************************
+ * nit.h
+ * (c)2001-2008 VideoLAN
+ * $Id: $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.c which was written by
+ *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *****************************************************************************/
+
+/*!
+ * \file <nit.h>
+ * \author Johann Hanne
+ * \brief Application interface for the NIT decoder and the NIT generator.
+ *
+ * Application interface for the NIT decoder and the NIT generator. New
+ * decoded NIT tables are sent by callback to the application. If a table
+ * wasn't active (b_current_next == 0) and the next is the same but active
+ * (b_current_next == 1) then the two lists are empty and should be
+ * caught from the previous structure.
+ */
+
+#ifndef _DVBPSI_NIT_H_
+#define _DVBPSI_NIT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*****************************************************************************
+ * dvbpsi_nit_ts_t
+ *****************************************************************************/
+/*!
+ * \struct dvbpsi_nit_ts_s
+ * \brief NIT TS structure.
+ *
+ * This structure is used to store a decoded TS description.
+ * (ETSI EN 300 468 section 5.2.1).
+ */
+/*!
+ * \typedef struct dvbpsi_nit_ts_s dvbpsi_nit_ts_t
+ * \brief dvbpsi_nit_ts_t type definition.
+ */
+typedef struct dvbpsi_nit_ts_s
+{
+  uint16_t                      i_ts_id;                /*!< transport stream id */
+  uint16_t                      i_orig_network_id;      /*!< original network id */
+
+  dvbpsi_descriptor_t *         p_first_descriptor;     /*!< descriptor list */
+
+  struct dvbpsi_nit_ts_s *      p_next;                 /*!< next element of
+                                                             the list */
+
+} dvbpsi_nit_ts_t;
+
+
+/*****************************************************************************
+ * dvbpsi_nit_t
+ *****************************************************************************/
+/*!
+ * \struct dvbpsi_nit_s
+ * \brief NIT structure.
+ *
+ * This structure is used to store a decoded NIT.
+ * (ETSI EN 300 468 section 5.2.1).
+ */
+/*!
+ * \typedef struct dvbpsi_nit_s dvbpsi_nit_t
+ * \brief dvbpsi_nit_t type definition.
+ */
+typedef struct dvbpsi_nit_s
+{
+  uint16_t                  i_network_id;       /*!< network_id */
+  uint8_t                   i_version;          /*!< version_number */
+  int                       b_current_next;     /*!< current_next_indicator */
+
+  dvbpsi_descriptor_t *     p_first_descriptor; /*!< descriptor list */
+
+  dvbpsi_nit_ts_t *         p_first_ts;         /*!< TS list */
+
+} dvbpsi_nit_t;
+
+
+/*****************************************************************************
+ * dvbpsi_nit_callback
+ *****************************************************************************/
+/*!
+ * \typedef void (* dvbpsi_nit_callback)(void* p_cb_data,
+                                         dvbpsi_nit_t* p_new_nit)
+ * \brief Callback type definition.
+ */
+typedef void (* dvbpsi_nit_callback)(void* p_cb_data, dvbpsi_nit_t* p_new_nit);
+
+
+/*****************************************************************************
+ * dvbpsi_AttachNIT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_AttachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
+                             uint16_t i_extension, dvbpsi_nit_callback pf_callback,
+                             void* p_cb_data)
+ * \brief Creation and initialization of a NIT decoder.
+ * \param p_demux Subtable demultiplexor to which the decoder is attached.
+ * \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
+ * \param i_extension Table ID extension, here service ID.
+ * \param pf_callback function to call back on new NIT.
+ * \param p_cb_data private data given in argument to the callback.
+ * \return 0 if everything went ok.
+ */
+int dvbpsi_AttachNIT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
+                     uint16_t i_extension, dvbpsi_nit_callback pf_callback,
+                     void* p_cb_data);
+
+
+/*****************************************************************************
+ * dvbpsi_DetachNIT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
+                             uint16_t i_extension)
+ * \brief Destroy a NIT decoder.
+ * \param p_demux Subtable demultiplexor to which the decoder is attached.
+ * \param i_table_id Table ID, 0x4E, 0x4F, or 0x50-0x6F.
+ * \param i_extension Table ID extension, here service ID.
+ * \return nothing.
+ */
+void dvbpsi_DetachNIT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
+                      uint16_t i_extension);
+
+
+/*****************************************************************************
+ * dvbpsi_InitNIT/dvbpsi_NewNIT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id,
+                           uint8_t i_version, int b_current_next)
+ * \brief Initialize a user-allocated dvbpsi_nit_t structure.
+ * \param p_nit pointer to the NIT structure
+ * \param i_network_id network id
+ * \param i_version NIT version
+ * \param b_current_next current next indicator
+ * \return nothing.
+ */
+void dvbpsi_InitNIT(dvbpsi_nit_t* p_nit, uint16_t i_network_id,
+                    uint8_t i_version, int b_current_next);
+
+/*!
+ * \def dvbpsi_NewNIT(p_nit, i_network_id,
+                      i_version, b_current_next)
+ * \brief Allocate and initialize a new dvbpsi_nit_t structure.
+ * \param p_nit pointer to the NIT structure
+ * \param i_network_id network id
+ * \param i_version NIT version
+ * \param b_current_next current next indicator
+ * \param i_pcr_pid PCR_PID
+ * \return nothing.
+ */
+#define dvbpsi_NewNIT(p_nit, i_network_id,                              \
+                      i_version, b_current_next)                        \
+do {                                                                    \
+  p_nit = (dvbpsi_nit_t*)malloc(sizeof(dvbpsi_nit_t));                  \
+  if(p_nit != NULL)                                                     \
+    dvbpsi_InitNIT(p_nit, i_network_id, i_version, b_current_next);     \
+} while(0);
+
+
+/*****************************************************************************
+ * dvbpsi_EmptyNIT/dvbpsi_DeleteNIT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_EmptyNIT(dvbpsi_nit_t* p_nit)
+ * \brief Clean a dvbpsi_nit_t structure.
+ * \param p_nit pointer to the NIT structure
+ * \return nothing.
+ */
+void dvbpsi_EmptyNIT(dvbpsi_nit_t* p_nit);
+
+/*!
+ * \def dvbpsi_DeleteNIT(p_nit)
+ * \brief Clean and free a dvbpsi_nit_t structure.
+ * \param p_nit pointer to the NIT structure
+ * \return nothing.
+ */
+#define dvbpsi_DeleteNIT(p_nit)                                         \
+do {                                                                    \
+  dvbpsi_EmptyNIT(p_nit);                                               \
+  free(p_nit);                                                          \
+} while(0);
+
+
+/*****************************************************************************
+ * dvbpsi_NITAddDescriptor
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
+                                                    uint8_t i_tag,
+                                                    uint8_t i_length,
+                                                    uint8_t* p_data)
+ * \brief Add a descriptor in the NIT.
+ * \param p_nit pointer to the NIT structure
+ * \param i_tag descriptor's tag
+ * \param i_length descriptor's length
+ * \param p_data descriptor's data
+ * \return a pointer to the added descriptor.
+ */
+dvbpsi_descriptor_t* dvbpsi_NITAddDescriptor(dvbpsi_nit_t* p_nit,
+                                             uint8_t i_tag, uint8_t i_length,
+                                             uint8_t* p_data);
+
+
+/*****************************************************************************
+ * dvbpsi_NITAddTS
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit,
+                                        uint8_t i_type, uint16_t i_pid)
+ * \brief Add an TS in the NIT.
+ * \param p_nit pointer to the NIT structure
+ * \param i_type type of TS
+ * \param i_pid PID of the TS
+ * \return a pointer to the added TS.
+ */
+dvbpsi_nit_ts_t* dvbpsi_NITAddTS(dvbpsi_nit_t* p_nit,
+                                 uint16_t i_ts_id, uint16_t i_orig_network_id);
+
+
+/*****************************************************************************
+ * dvbpsi_NITTSAddDescriptor
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts,
+                                                      uint8_t i_tag,
+                                                      uint8_t i_length,
+                                                      uint8_t* p_data)
+ * \brief Add a descriptor in the NIT TS.
+ * \param p_ts pointer to the TS structure
+ * \param i_tag descriptor's tag
+ * \param i_length descriptor's length
+ * \param p_data descriptor's data
+ * \return a pointer to the added descriptor.
+ */
+dvbpsi_descriptor_t* dvbpsi_NITTSAddDescriptor(dvbpsi_nit_ts_t* p_ts,
+                                               uint8_t i_tag, uint8_t i_length,
+                                               uint8_t* p_data);
+
+
+/*****************************************************************************
+ * dvbpsi_GenNITSections
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit,
+                                                   uint8_t i_table_id)
+ * \brief NIT generator
+ * \param p_nit NIT structure
+ * \param i_table_id table id, 0x40 = actual network / 0x41 = other network
+ * \return a pointer to the list of generated PSI sections.
+ *
+ * Generate NIT sections based on the dvbpsi_nit_t structure.
+ */
+dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit,
+                                            uint8_t i_table_id);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#else
+#error "Multiple inclusions of nit.h"
+#endif
+
diff -uNr libdvbpsi-trunk/src/tables/nit_private.h libdvbpsi-trunk+nit/src/tables/nit_private.h
--- libdvbpsi-trunk/src/tables/nit_private.h	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi-trunk+nit/src/tables/nit_private.h	2008-04-24 18:02:34.000000000 +0200
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * nit_private.h: private NIT structures
+ *----------------------------------------------------------------------------
+ * (c)2001-2002 VideoLAN
+ * $Id: $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.c which was written by
+ *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ *----------------------------------------------------------------------------
+ *
+ *****************************************************************************/
+
+#ifndef _DVBPSI_NIT_PRIVATE_H_
+#define _DVBPSI_NIT_PRIVATE_H_
+
+/*****************************************************************************
+ * dvbpsi_nit_decoder_t
+ *****************************************************************************
+ * NIT decoder.
+ *****************************************************************************/
+typedef struct dvbpsi_nit_decoder_s
+{
+  uint16_t                      i_network_id;
+
+  dvbpsi_nit_callback           pf_callback;
+  void *                        p_cb_data;
+
+  dvbpsi_nit_t                  current_nit;
+  dvbpsi_nit_t *                p_building_nit;
+
+  int                           b_current_valid;
+
+  uint8_t                       i_last_section_number;
+  dvbpsi_psi_section_t *        ap_sections [256];
+
+} dvbpsi_nit_decoder_t;
+
+
+/*****************************************************************************
+ * dvbpsi_GatherNITSections
+ *****************************************************************************
+ * Callback for the PSI decoder.
+ *****************************************************************************/
+void dvbpsi_GatherNITSections(dvbpsi_decoder_t* p_psi_decoder,
+                              void* p_private_decoder,
+                              dvbpsi_psi_section_t* p_section);
+
+
+/*****************************************************************************
+ * dvbpsi_DecodeNITSections
+ *****************************************************************************
+ * NIT decoder.
+ *****************************************************************************/
+void dvbpsi_DecodeNITSections(dvbpsi_nit_t* p_nit,
+                              dvbpsi_psi_section_t* p_section);
+
+
+#else
+#error "Multiple inclusions of nit_private.h"
+#endif
+
