[patch] 2/2: Add TOT/TDT support

Johann Hanne <[email protected]>
Newsgroups gmane.comp.video.videolan.libdvbpsi.devel
Message-ID <200804241822.59676.jhml__28477.2969469943$1209054250$gmane$org@gmx.net>
Hi,

the attached patch adds support for the TOT table. As the TDT table is nearly 
the same (it's a TOT without descriptors and CRC), it can also be used to 
create a TDT. As the TOT includes a CRC32 in it's payload, the patch also 
moves the CRC table to dvbpsi.c, so it can be access from tot.c.

Please apply.

Cheers, Johann

_______________________________________________
libdvbpsi-devel mailing list
[email protected]
http://mailman.videolan.org/listinfo/libdvbpsi-devel
add_tot_support.diff (text/x-diff, 37.7 KB)
diff -uNr libdvbpsi-trunk+nit/src/dvbpsi.c libdvbpsi-trunk+nit+tot/src/dvbpsi.c
--- libdvbpsi-trunk+nit/src/dvbpsi.c	2008-04-23 18:45:32.000000000 +0200
+++ libdvbpsi-trunk+nit+tot/src/dvbpsi.c	2008-04-24 18:05:31.000000000 +0200
@@ -42,6 +42,102 @@
 
 
 /*****************************************************************************
+ * dvbpsi_crc32_table
+ *****************************************************************************
+ * This table is used to compute a PSI CRC byte per byte instead of bit per
+ * bit. It's been generated by 'gen_crc' in the 'misc' directory:
+ * 
+ *   uint32_t table[256];
+ *   uint32_t i, j, k;
+ *
+ *   for(i = 0; i < 256; i++)
+ *   {
+ *     k = 0;
+ *     for (j = (i << 24) | 0x800000; j != 0x80000000; j <<= 1)
+ *       k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
+ *     table[i] = k;
+ *   }
+ *
+ * A CRC is computed like this:
+ *
+ *   initialization
+ *   --------------
+ *   uint32_t i_crc = 0xffffffff;
+ *
+ *   for each data byte do
+ *   ---------------------
+ *   i_crc = (i_crc << 8) ^ dvbpsi_crc32_table[(i_crc >> 24) ^ (data_byte)];
+ *****************************************************************************/
+uint32_t dvbpsi_crc32_table[256] =
+{
+  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+  0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+  0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+  0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+  0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+  0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+  0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+  0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+  0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+  0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+  0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+  0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+  0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+  0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+  0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+  0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+  0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+  0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+  0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+  0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+  0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+  0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+  0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+  0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+  0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+  0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+  0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+  0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+  0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+  0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+  0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+  0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+  0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+  0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+  0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+  0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+  0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+  0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+  0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+  0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+  0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+  0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+  0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+
+/*****************************************************************************
  * dvbpsi_PushPacket
  *****************************************************************************
  * Injection of a TS packet into a PSI decoder.
diff -uNr libdvbpsi-trunk+nit/src/dvbpsi_private.h libdvbpsi-trunk+nit+tot/src/dvbpsi_private.h
--- libdvbpsi-trunk+nit/src/dvbpsi_private.h	2008-04-23 18:45:32.000000000 +0200
+++ libdvbpsi-trunk+nit+tot/src/dvbpsi_private.h	2008-04-24 18:05:45.000000000 +0200
@@ -28,6 +28,9 @@
 #define _DVBPSI_DVBPSI_PRIVATE_H_
 
 
+extern uint32_t dvbpsi_crc32_table[];
+
+
 /*****************************************************************************
  * Error management
  *****************************************************************************/
diff -uNr libdvbpsi-trunk+nit/src/Makefile.am libdvbpsi-trunk+nit+tot/src/Makefile.am
--- libdvbpsi-trunk+nit/src/Makefile.am	2008-04-24 18:01:07.000000000 +0200
+++ libdvbpsi-trunk+nit+tot/src/Makefile.am	2008-04-24 18:09: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/nit.h \
+                     tables/cat.h tables/nit.h tables/tot.h \
                      descriptors/dr_02.h \
                      descriptors/dr_03.h \
                      descriptors/dr_04.h \
@@ -74,5 +74,6 @@
              tables/sdt.c tables/sdt_private.h \
              tables/eit.c tables/eit_private.h \
              tables/cat.c tables/cat_private.h \
-             tables/nit.c tables/nit_private.h
+             tables/nit.c tables/nit_private.h \
+             tables/tot.c tables/tot_private.h
 
diff -uNr libdvbpsi-trunk+nit/src/psi.c libdvbpsi-trunk+nit+tot/src/psi.c
--- libdvbpsi-trunk+nit/src/psi.c	2008-04-23 18:45:32.000000000 +0200
+++ libdvbpsi-trunk+nit+tot/src/psi.c	2008-04-24 18:05:31.000000000 +0200
@@ -42,102 +42,6 @@
 
 
 /*****************************************************************************
- * s_crc32_table
- *****************************************************************************
- * This table is used to compute a PSI CRC byte per byte instead of bit per
- * bit. It's been generated by 'gen_crc' in the 'misc' directory:
- * 
- *   uint32_t table[256];
- *   uint32_t i, j, k;
- *
- *   for(i = 0; i < 256; i++)
- *   {
- *     k = 0;
- *     for (j = (i << 24) | 0x800000; j != 0x80000000; j <<= 1)
- *       k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
- *     table[i] = k;
- *   }
- *
- * A CRC is computed like this:
- *
- *   initialization
- *   --------------
- *   uint32_t i_crc = 0xffffffff;
- *
- *   for each data byte do
- *   ---------------------
- *   i_crc = (i_crc << 8) ^ s_crc32_table[(i_crc >> 24) ^ (data_byte)];
- *****************************************************************************/
-static uint32_t s_crc32_table[256] =
-{
-  0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
-  0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
-  0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
-  0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
-  0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
-  0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
-  0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
-  0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
-  0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
-  0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
-  0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
-  0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
-  0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
-  0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
-  0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
-  0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
-  0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
-  0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
-  0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
-  0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
-  0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
-  0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
-  0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
-  0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
-  0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
-  0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
-  0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
-  0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
-  0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
-  0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
-  0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
-  0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
-  0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
-  0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
-  0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
-  0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
-  0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
-  0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
-  0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
-  0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
-  0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
-  0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
-  0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
-  0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
-  0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
-  0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
-  0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
-  0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
-  0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
-  0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
-  0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
-  0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
-  0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
-  0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
-  0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
-  0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
-  0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
-  0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
-  0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
-  0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
-  0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
-  0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
-  0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
-  0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
-};
-
-
-/*****************************************************************************
  * dvbpsi_NewPSISection
  *****************************************************************************
  * Creation of a new dvbpsi_psi_section_t structure.
@@ -205,7 +109,7 @@
 
     while(p_byte < p_section->p_payload_end + 4)
     {
-      i_crc = (i_crc << 8) ^ s_crc32_table[(i_crc >> 24) ^ (*p_byte)];
+      i_crc = (i_crc << 8) ^ dvbpsi_crc32_table[(i_crc >> 24) ^ (*p_byte)];
       p_byte++;
     }
 
@@ -270,7 +174,7 @@
     while(p_byte < p_section->p_payload_end)
     {
       p_section->i_crc =   (p_section->i_crc << 8)
-                         ^ s_crc32_table[(p_section->i_crc >> 24) ^ (*p_byte)];
+                         ^ dvbpsi_crc32_table[(p_section->i_crc >> 24) ^ (*p_byte)];
       p_byte++;
     }
 
diff -uNr libdvbpsi-trunk+nit/src/tables/tot.c libdvbpsi-trunk+nit+tot/src/tables/tot.c
--- libdvbpsi-trunk+nit/src/tables/tot.c	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi-trunk+nit+tot/src/tables/tot.c	2008-04-24 18:06:08.000000000 +0200
@@ -0,0 +1,461 @@
+/*****************************************************************************
+ * tot.c: TDT/TOT decoder/generator
+ *----------------------------------------------------------------------------
+ * (c)2001-2008 VideoLAN
+ * $Id: $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.c which was written by
+ *          Arnaud de Bossoreille de Ribou <[email protected]>
+ *
+ * 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 "tot.h"
+#include "tot_private.h"
+
+
+/*****************************************************************************
+ * dvbpsi_AttachTOT
+ *****************************************************************************
+ * Initialize a TDT/TOT subtable decoder.
+ *****************************************************************************/
+int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
+                     uint16_t i_extension,
+                     dvbpsi_tot_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_tot_decoder_t*  p_tot_decoder;
+
+  if(dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0))
+  {
+    DVBPSI_ERROR_ARG("TDT/TOT decoder",
+                     "Already a decoder for (table_id == 0x%02x,"
+                     "extension == 0x%02x)",
+                     i_table_id, 0);
+
+    return 1;
+  }
+
+  p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t));
+  if(p_subdec == NULL)
+  {
+    return 1;
+  }
+
+  p_tot_decoder = (dvbpsi_tot_decoder_t*)malloc(sizeof(dvbpsi_tot_decoder_t));
+
+  if(p_tot_decoder == NULL)
+  {
+    free(p_subdec);
+    return 1;
+  }
+
+  /* subtable decoder configuration */
+  p_subdec->pf_callback = &dvbpsi_GatherTOTSections;
+  p_subdec->p_cb_data = p_tot_decoder;
+  p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)0;
+  p_subdec->pf_detach = dvbpsi_DetachTOT;
+
+  /* Attach the subtable decoder to the demux */
+  p_subdec->p_next = p_demux->p_first_subdec;
+  p_demux->p_first_subdec = p_subdec;
+
+  /* TDT/TOT decoder information */
+  p_tot_decoder->pf_callback = pf_callback;
+  p_tot_decoder->p_cb_data = p_cb_data;
+
+  return 0;
+}
+
+/*****************************************************************************
+ * dvbpsi_DetachTOT
+ *****************************************************************************
+ * Close a TDT/TOT decoder.
+ *****************************************************************************/
+void dvbpsi_DetachTOT(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;
+
+  p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, 0);
+
+  if(p_demux == NULL)
+  {
+    DVBPSI_ERROR_ARG("TDT/TOT Decoder",
+                     "No such TDT/TOT decoder (table_id == 0x%02x,"
+                     "extension == 0x%02x)",
+                     i_table_id, 0);
+    return;
+  }
+
+  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_InitTOT
+ *****************************************************************************
+ * Initialize a pre-allocated dvbpsi_tot_t structure.
+ *****************************************************************************/
+void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot, uint64_t i_utc_time)
+{
+  p_tot->i_utc_time = i_utc_time;
+  p_tot->p_first_descriptor = NULL;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_EmptyTOT
+ *****************************************************************************
+ * Clean a dvbpsi_tot_t structure.
+ *****************************************************************************/
+void dvbpsi_EmptyTOT(dvbpsi_tot_t* p_tot)
+{
+  dvbpsi_DeleteDescriptors(p_tot->p_first_descriptor);
+
+  p_tot->p_first_descriptor = NULL;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_TOTAddDescriptor
+ *****************************************************************************
+ * Add a descriptor in the TOT.
+ *****************************************************************************/
+dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
+                                             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_tot->p_first_descriptor == NULL)
+    {
+      p_tot->p_first_descriptor = p_descriptor;
+    }
+    else
+    {
+      dvbpsi_descriptor_t* p_last_descriptor = p_tot->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_GatherTOTSections
+ *****************************************************************************
+ * Callback for the PSI decoder.
+ *****************************************************************************/
+void dvbpsi_GatherTOTSections(dvbpsi_decoder_t* p_decoder,
+                              void * p_private_decoder,
+                              dvbpsi_psi_section_t* p_section)
+{
+  dvbpsi_tot_decoder_t* p_tot_decoder
+                        = (dvbpsi_tot_decoder_t*)p_private_decoder;
+  int b_append = 1;
+  dvbpsi_tot_t* p_building_tot;
+
+  DVBPSI_DEBUG("TDT/TOT decoder", "got a section");
+
+  if(p_section->i_table_id != 0x70 && p_section->i_table_id != 0x73)
+  {
+    /* Invalid table_id value */
+    DVBPSI_ERROR_ARG("TDT/TOT decoder",
+                     "invalid section (table_id == 0x%02x)",
+                     p_section->i_table_id);
+    b_append = 0;
+  }
+
+  if(b_append && p_section->b_syntax_indicator != 0)
+  {
+    /* Invalid section_syntax_indicator */
+    DVBPSI_ERROR("TDT/TOT decoder",
+                 "invalid section (section_syntax_indicator != 0)");
+    b_append = 0;
+  }
+
+  /* Now if b_append is true then we have a valid TDT/TOT section */
+
+  if(b_append)
+  {
+    /* TS discontinuity check */
+    if(p_decoder->b_discontinuity)
+    {
+      /* We don't care about discontinuities with the TDT/TOT as it
+         only consists of one section anyway */
+      p_decoder->b_discontinuity = 0;
+    }
+
+    p_building_tot = (dvbpsi_tot_t*)malloc(sizeof(dvbpsi_tot_t));
+    dvbpsi_InitTOT(p_building_tot,   ((uint64_t)p_section->p_payload_start[0] << 32)
+                                   | ((uint64_t)p_section->p_payload_start[1] << 24)
+                                   | ((uint64_t)p_section->p_payload_start[2] << 16)
+                                   | ((uint64_t)p_section->p_payload_start[3] <<  8)
+                                   |  (uint64_t)p_section->p_payload_start[4]);
+
+    /* Decode the section */
+    dvbpsi_DecodeTOTSections(p_building_tot, p_section);
+    /* Delete the section */
+    dvbpsi_DeletePSISections(p_section);
+    /* signal the new TDT/TOT */
+    p_tot_decoder->pf_callback(p_tot_decoder->p_cb_data, p_building_tot);
+  }
+  else
+  {
+    dvbpsi_DeletePSISections(p_section);
+  }
+}
+
+
+/*****************************************************************************
+ * dvbpsi_ValidTOTSection
+ *****************************************************************************
+ * Check the CRC_32 if the section has b_syntax_indicator set.
+ *****************************************************************************/
+int dvbpsi_ValidTOTSection(dvbpsi_psi_section_t* p_section)
+{
+  if(p_section->i_table_id == 0x73)
+  {
+    /* Check the CRC_32 if it's a TOT */
+    uint32_t i_crc = 0xffffffff;
+    uint8_t* p_byte = p_section->p_data;
+
+    while(p_byte < p_section->p_payload_end)
+    {
+      i_crc = (i_crc << 8) ^ dvbpsi_crc32_table[(i_crc >> 24) ^ (*p_byte)];
+      p_byte++;
+    }
+
+    if(i_crc == 0)
+    {
+      return 1;
+    }
+    else
+    {
+      DVBPSI_ERROR_ARG("TDT/TOT decoder",
+                       "Bad CRC_32 (0x%08x) !!!", i_crc);
+      return 0;
+    }
+  }
+  else
+  {
+    /* A TDT always has a length of 5 bytes (which is only the UTC time) */
+    if(p_section->i_length != 5) {
+      DVBPSI_ERROR_ARG("TDT/TOT decoder",
+                       "TDT has an invalid payload size (%d bytes) !!!",
+                       p_section->i_length);
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_DecodeTOTSections
+ *****************************************************************************
+ * TDT/TOT decoder.
+ *****************************************************************************/
+void dvbpsi_DecodeTOTSections(dvbpsi_tot_t* p_tot,
+                              dvbpsi_psi_section_t* p_section)
+{
+  uint8_t* p_byte;
+
+  if(p_section)
+  {
+
+    if (!dvbpsi_ValidTOTSection(p_section)) {
+      return;
+    }
+
+    p_byte = p_section->p_payload_start;
+
+    if(p_byte + 5 <= p_section->p_payload_end)
+    {
+      p_tot->i_utc_time = ((uint64_t)p_byte[0] << 32) |
+                          ((uint64_t)p_byte[1] << 24) |
+                          ((uint64_t)p_byte[2] << 16) |
+                          ((uint64_t)p_byte[3] << 8) |
+                           (uint64_t)p_byte[4];
+    }
+
+    /* If we have a TOT, extract the descriptors */
+    if (p_section->i_table_id == 0x73)
+    {
+      uint8_t* p_end;
+
+      p_end = p_byte + (   ((uint16_t)(p_section->p_payload_start[5] & 0x0f) << 8)
+                         | p_section->p_payload_start[6]);
+
+      p_byte += 7;
+
+      while(p_byte + 5 <= p_end)
+      {
+        uint8_t i_tag = p_byte[0];
+        uint8_t i_length = p_byte[1];
+        if(i_length + 2 <= p_section->p_payload_end - p_byte)
+          dvbpsi_TOTAddDescriptor(p_tot, i_tag, i_length, p_byte + 2);
+        p_byte += 2 + i_length;
+      }
+
+    }
+  }
+}
+
+
+/*****************************************************************************
+ * dvbpsi_GenTOTSections
+ *****************************************************************************
+ * Generate TDT/TOT sections based on the dvbpsi_tot_t structure.
+ *****************************************************************************/
+dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_tot_t* p_tot)
+{
+  dvbpsi_psi_section_t* p_result;
+
+  dvbpsi_descriptor_t* p_descriptor = p_tot->p_first_descriptor;
+
+  /* If it has descriptors, it must be a TOT, otherwise a TDT */
+  p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8);
+
+  p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70;
+  p_result->b_syntax_indicator = 0;
+  p_result->b_private_indicator = 0;
+  p_result->i_length = 5;
+  p_result->p_payload_start = p_result->p_data + 3;
+  p_result->p_payload_end = p_result->p_data + 8;
+
+  p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff;
+  p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff;
+  p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff;
+  p_result->p_data[6] = (p_tot->i_utc_time >>  8) & 0xff;
+  p_result->p_data[7] =  p_tot->i_utc_time        & 0xff;
+
+  if(p_result->i_table_id == 0x73) {
+    /* Special handling for TOT only (A TDT doesn't have descriptors!) */
+
+    /* Reserve two bytes for descriptors_loop_length */
+    p_result->p_payload_end += 2;
+    p_result->i_length += 2;
+
+    /* TOT descriptors */
+    while(p_descriptor != NULL)
+    {
+      /* A TOT cannot have multiple sections! */
+      if(   (p_result->p_payload_end - p_result->p_data)
+                                  + p_descriptor->i_length > 4090)
+      {
+        DVBPSI_ERROR("TDT/TOT generator",
+                     "TOT does not fit into one section as it ought to be !!!");
+        break;
+      }
+
+      /* p_payload_end is where the descriptor begins */
+      p_result->p_payload_end[0] = p_descriptor->i_tag;
+      p_result->p_payload_end[1] = p_descriptor->i_length;
+      memcpy(p_result->p_payload_end + 2,
+             p_descriptor->p_data,
+             p_descriptor->i_length);
+
+      /* Increase length by descriptor_length + 2 */
+      p_result->p_payload_end += p_descriptor->i_length + 2;
+      p_result->i_length += p_descriptor->i_length + 2;
+
+      p_descriptor = p_descriptor->p_next;
+    }
+
+    /* descriptors_loop_length */
+    p_result->p_payload_start[5] = ((p_result->i_length - 7) << 8) | 0xf0;
+    p_result->p_payload_start[6] =  (p_result->i_length - 7)       & 0xff;
+  }
+
+  if (p_result->i_table_id == 0x73) {
+    /* A TOT has a CRC_32 although it's a private section,
+       but the CRC_32 is part of the payload! */
+    p_result->p_payload_end += 4;
+    p_result->i_length += 4;
+  }
+
+  dvbpsi_BuildPSISection(p_result);
+
+  if (p_result->i_table_id == 0x73) {
+    uint8_t* p_byte = p_result->p_data;
+
+    p_tot->i_crc = 0xffffffff;
+
+    while(p_byte < p_result->p_payload_end - 4)
+    {
+      p_tot->i_crc =   (p_tot->i_crc << 8)
+                     ^ dvbpsi_crc32_table[(p_tot->i_crc >> 24) ^ (*p_byte)];
+      p_byte++;
+    }
+
+    p_byte[0] = (p_tot->i_crc >> 24) & 0xff;
+    p_byte[1] = (p_tot->i_crc >> 16) & 0xff;
+    p_byte[2] = (p_tot->i_crc >> 8) & 0xff;
+    p_byte[3] = p_tot->i_crc & 0xff;
+  }
+
+#ifdef DEBUG
+  if(!dvbpsi_ValidTOTSection(p_result))
+  {
+    DVBPSI_ERROR("TDT/TOT generator", "********************************************");
+    DVBPSI_ERROR("TDT/TOT generator", "*  Generated TDT/TOT section is invalid.   *");
+    DVBPSI_ERROR("TDT/TOT generator", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
+    DVBPSI_ERROR("TDT/TOT generator", "*  ---  [email protected]  ---  *");
+    DVBPSI_ERROR("TDT/TOT generator", "********************************************");
+  }
+#endif
+
+  return p_result;
+}
diff -uNr libdvbpsi-trunk+nit/src/tables/tot.h libdvbpsi-trunk+nit+tot/src/tables/tot.h
--- libdvbpsi-trunk+nit/src/tables/tot.h	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi-trunk+nit+tot/src/tables/tot.h	2008-04-24 18:06:08.000000000 +0200
@@ -0,0 +1,208 @@
+/*****************************************************************************
+ * tot.h
+ * (c)2001-2008 VideoLAN
+ * $Id: $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.c which was written by
+ *          Arnaud de Bossoreille de Ribou <[email protected]>
+ *
+ * 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 <tot.h>
+ * \author Johann Hanne
+ * \brief Application interface for the TDT/TOT decoder and the TDT/TOT generator.
+ *
+ * Application interface for the TDT/TOT decoder and the TDT/TOT generator. New
+ * decoded TDT/TOT 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_TOT_H_
+#define _DVBPSI_TOT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*****************************************************************************
+ * dvbpsi_tot_t
+ *****************************************************************************/
+/*!
+ * \struct dvbpsi_tot_s
+ * \brief TDT/TOT structure.
+ *
+ * This structure is used to store a decoded TDT/TOT.
+ * (ETSI EN 300 468 section 5.2.5/5.2.6).
+ */
+/*!
+ * \typedef struct dvbpsi_tot_s dvbpsi_tot_t
+ * \brief dvbpsi_tot_t type definition.
+ */
+typedef struct dvbpsi_tot_s
+{
+  uint64_t                  i_utc_time;         /*!< UTC_time */
+
+  dvbpsi_descriptor_t *     p_first_descriptor; /*!< descriptor list */
+
+  uint32_t      i_crc;                          /*!< CRC_32 (TOT only) */
+
+} dvbpsi_tot_t;
+
+
+/*****************************************************************************
+ * dvbpsi_tot_callback
+ *****************************************************************************/
+/*!
+ * \typedef void (* dvbpsi_tot_callback)(void* p_cb_data,
+                                         dvbpsi_tot_t* p_new_tot)
+ * \brief Callback type definition.
+ */
+typedef void (* dvbpsi_tot_callback)(void* p_cb_data, dvbpsi_tot_t* p_new_tot);
+
+
+/*****************************************************************************
+ * dvbpsi_AttachTOT
+ *****************************************************************************/
+/*!
+ * \fn int dvbpsi_AttachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
+                            dvbpsi_tot_callback pf_callback, void* p_cb_data)
+ * \brief Creation and initialization of a TDT/TOT decoder.
+ * \param p_demux Subtable demultiplexor to which the decoder is attached.
+ * \param i_table_id Table ID, usually 0x70
+ * \param i_extension Table ID extension, unused in the TDT/TOT
+ * \param pf_callback function to call back on new TDT/TOT.
+ * \param p_cb_data private data given in argument to the callback.
+ * \return 0 if everything went ok.
+ */
+int dvbpsi_AttachTOT(dvbpsi_decoder_t * p_psi_decoder, uint8_t i_table_id,
+                     uint16_t i_extension,
+                     dvbpsi_tot_callback pf_callback, void* p_cb_data);
+
+
+/*****************************************************************************
+ * dvbpsi_DetachTOT
+ *****************************************************************************/
+/*!
+ * \fn int dvbpsi_DetachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id)
+ * \brief Destroy a TDT/TOT decoder.
+ * \param p_demux Subtable demultiplexor to which the decoder is attached.
+ * \param i_table_id Table ID, usually 0x70
+ * \param i_extension Table ID extension, unused in the TDT/TOT
+ * \return nothing.
+ */
+void dvbpsi_DetachTOT(dvbpsi_demux_t * p_demux, uint8_t i_table_id,
+                      uint16_t i_extension);
+
+
+/*****************************************************************************
+ * dvbpsi_InitTOT/dvbpsi_NewTOT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot)
+ * \brief Initialize a user-allocated dvbpsi_tot_t structure.
+ * \param p_tot pointer to the TDT/TOT structure
+ * \param i_utc_time the time in UTC
+ * \return nothing.
+ */
+void dvbpsi_InitTOT(dvbpsi_tot_t* p_tot, uint64_t i_utc_time);
+
+/*!
+ * \def dvbpsi_NewTOT(p_tot)
+ * \brief Allocate and initialize a new dvbpsi_tot_t structure.
+ * \param p_tot pointer to the TDT/TOT structure
+ * \param i_utc_time the time in UTC
+ * \return nothing.
+ */
+#define dvbpsi_NewTOT(p_tot, i_utc_time)                                \
+do {                                                                    \
+  p_tot = (dvbpsi_tot_t*)malloc(sizeof(dvbpsi_tot_t));                  \
+  if(p_tot != NULL)                                                     \
+    dvbpsi_InitTOT(p_tot, i_utc_time);                                  \
+} while(0);
+
+
+/*****************************************************************************
+ * dvbpsi_EmptyTOT/dvbpsi_DeleteTOT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_EmptyTOT(dvbpsi_tot_t* p_tot)
+ * \brief Clean a dvbpsi_tot_t structure.
+ * \param p_tot pointer to the TDT/TOT structure
+ * \return nothing.
+ */
+void dvbpsi_EmptyTOT(dvbpsi_tot_t* p_tot);
+
+/*!
+ * \def dvbpsi_DeleteTOT(p_tot)
+ * \brief Clean and free a dvbpsi_tot_t structure.
+ * \param p_tot pointer to the TDT/TOT structure
+ * \return nothing.
+ */
+#define dvbpsi_DeleteTOT(p_tot)                                         \
+do {                                                                    \
+  dvbpsi_EmptyTOT(p_tot);                                               \
+  free(p_tot);                                                          \
+} while(0);
+
+
+/*****************************************************************************
+ * dvbpsi_TOTAddDescriptor
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_descriptor_t* dvbpsi_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
+                                                    uint8_t i_tag,
+                                                    uint8_t i_length,
+                                                    uint8_t* p_data)
+ * \brief Add a descriptor in the TOT.
+ * \param p_tot pointer to the TOT 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_TOTAddDescriptor(dvbpsi_tot_t* p_tot,
+                                             uint8_t i_tag, uint8_t i_length,
+                                             uint8_t* p_data);
+
+
+/*****************************************************************************
+ * dvbpsi_GenTOTSections
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_Ttot_t* p_tot)
+ * \brief TDT/TOT generator
+ * \param p_tot TDT/TOT structure
+ * \return a pointer to the list of generated PSI sections.
+ *
+ * Generate TDT/TOT sections based on the dvbpsi_tot_t structure.
+ */
+dvbpsi_psi_section_t* dvbpsi_GenTOTSections(dvbpsi_tot_t* p_tot);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#else
+#error "Multiple inclusions of tot.h"
+#endif
+
diff -uNr libdvbpsi-trunk+nit/src/tables/tot_private.h libdvbpsi-trunk+nit+tot/src/tables/tot_private.h
--- libdvbpsi-trunk+nit/src/tables/tot_private.h	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi-trunk+nit+tot/src/tables/tot_private.h	2008-04-24 18:06:08.000000000 +0200
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * tot_private.h: private TDT/TOT structures
+ *----------------------------------------------------------------------------
+ * (c)2001-2008 VideoLAN
+ * $Id: $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.c which was written by
+ *          Arnaud de Bossoreille de Ribou <[email protected]>
+ *
+ * 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_TOT_PRIVATE_H_
+#define _DVBPSI_TOT_PRIVATE_H_
+
+/*****************************************************************************
+ * dvbpsi_tot_decoder_t
+ *****************************************************************************
+ * TDT/TOT decoder.
+ *****************************************************************************/
+typedef struct dvbpsi_tot_decoder_s
+{
+  dvbpsi_tot_callback           pf_callback;
+  void *                        p_cb_data;
+
+} dvbpsi_tot_decoder_t;
+
+
+/*****************************************************************************
+ * dvbpsi_GatherTOTSections
+ *****************************************************************************
+ * Callback for the PSI decoder.
+ *****************************************************************************/
+void dvbpsi_GatherTOTSections(dvbpsi_decoder_t* p_decoder,
+                              void * p_private_decoder,
+                              dvbpsi_psi_section_t* p_section);
+
+
+/*****************************************************************************
+ * dvbpsi_DecodeTOTSections
+ *****************************************************************************
+ * TDT/TOT decoder.
+ *****************************************************************************/
+void dvbpsi_DecodeTOTSections(dvbpsi_tot_t* p_tot,
+                              dvbpsi_psi_section_t* p_section);
+
+
+#else
+#error "Multiple inclusions of tot_private.h"
+#endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.