[patch] Add CAT support

Johann Hanne <[email protected]>
Newsgroups gmane.comp.video.videolan.libdvbpsi.devel
Message-ID <200708241047.57409.jhml__7483.83356626636$1187948868$gmane$org@gmx.net>
Hi all,

the attached patch adds support for decoding and generating the conditional 
access tables in mpeg2 transport streams. It has mostly been copy&paste work 
from the pmt code, so credits go to Arnaud de Bossoreille de Ribou as it was 
mostly his work.

Please apply.

Cheers, Johann

_______________________________________________
libdvbpsi-devel mailing list
[email protected]
http://mailman.videolan.org/listinfo/libdvbpsi-devel
libdvbpsi4-0.1.6pre-svn144-cat.diff (text/x-diff, 27.9 KB)
diff -uNr libdvbpsi4-0.1.6pre-svn144/src/Makefile.am libdvbpsi4-0.1.6pre-svn144-cat/src/Makefile.am
--- libdvbpsi4-0.1.6pre-svn144/src/Makefile.am	2007-08-22 09:47:02.000000000 +0200
+++ libdvbpsi4-0.1.6pre-svn144-cat/src/Makefile.am	2007-08-23 18:24:50.000000000 +0200
@@ -15,6 +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 \
                      descriptors/dr_02.h \
                      descriptors/dr_03.h \
                      descriptors/dr_04.h \
@@ -67,5 +68,6 @@
 tables_src = tables/pat.c tables/pat_private.h \
              tables/pmt.c tables/pmt_private.h \
 	     tables/sdt.c tables/sdt_private.h \
-	     tables/eit.c tables/eit_private.h
+	     tables/eit.c tables/eit_private.h \
+	     tables/cat.c tables/cat_private.h
 
diff -uNr libdvbpsi4-0.1.6pre-svn144/src/tables/cat.c libdvbpsi4-0.1.6pre-svn144-cat/src/tables/cat.c
--- libdvbpsi4-0.1.6pre-svn144/src/tables/cat.c	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi4-0.1.6pre-svn144-cat/src/tables/cat.c	2007-08-23 22:56:42.000000000 +0200
@@ -0,0 +1,462 @@
+/*****************************************************************************
+ * cat.c: CAT decoder/generator
+ *----------------------------------------------------------------------------
+ * (c)2001-2002 VideoLAN
+ * $Id: cat.c 108 2005-04-19 12:33:21Z gbazin $
+ *
+ * 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 "cat.h"
+#include "cat_private.h"
+
+
+/*****************************************************************************
+ * dvbpsi_AttachCAT
+ *****************************************************************************
+ * Initialize a CAT decoder and return a handle on it.
+ *****************************************************************************/
+dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback,
+                               void* p_cb_data)
+{
+  dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t));
+  dvbpsi_cat_decoder_t* p_cat_decoder;
+  unsigned int i;
+
+  if(h_dvbpsi == NULL)
+    return NULL;
+
+  p_cat_decoder = (dvbpsi_cat_decoder_t*)malloc(sizeof(dvbpsi_cat_decoder_t));
+
+  if(p_cat_decoder == NULL)
+  {
+    free(h_dvbpsi);
+    return NULL;
+  }
+
+  /* PSI decoder configuration */
+  h_dvbpsi->pf_callback = &dvbpsi_GatherCATSections;
+  h_dvbpsi->p_private_decoder = p_cat_decoder;
+  h_dvbpsi->i_section_max_size = 1024;
+  /* PSI decoder initial state */
+  h_dvbpsi->i_continuity_counter = 31;
+  h_dvbpsi->b_discontinuity = 1;
+  h_dvbpsi->p_current_section = NULL;
+
+  /* CAT decoder configuration */
+  p_cat_decoder->pf_callback = pf_callback;
+  p_cat_decoder->p_cb_data = p_cb_data;
+  /* CAT decoder initial state */
+  p_cat_decoder->b_current_valid = 0;
+  p_cat_decoder->p_building_cat = NULL;
+  for(i = 0; i <= 255; i++)
+    p_cat_decoder->ap_sections[i] = NULL;
+
+  return h_dvbpsi;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_DetachCAT
+ *****************************************************************************
+ * Close a CAT decoder. The handle isn't valid any more.
+ *****************************************************************************/
+void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi)
+{
+  dvbpsi_cat_decoder_t* p_cat_decoder
+                        = (dvbpsi_cat_decoder_t*)h_dvbpsi->p_private_decoder;
+  unsigned int i;
+
+  free(p_cat_decoder->p_building_cat);
+
+  for(i = 0; i <= 255; i++)              
+  {
+    if(p_cat_decoder->ap_sections[i])
+      free(p_cat_decoder->ap_sections[i]);
+  }
+
+  free(h_dvbpsi->p_private_decoder);
+  if(h_dvbpsi->p_current_section)
+    dvbpsi_DeletePSISections(h_dvbpsi->p_current_section);
+  free(h_dvbpsi);
+}
+
+
+/*****************************************************************************
+ * dvbpsi_InitCAT
+ *****************************************************************************
+ * Initialize a pre-allocated dvbpsi_cat_t structure.
+ *****************************************************************************/
+void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
+                    uint8_t i_version, int b_current_next)
+{
+  p_cat->i_version = i_version;
+  p_cat->b_current_next = b_current_next;
+  p_cat->p_first_descriptor = NULL;
+}
+
+
+/*****************************************************************************
+ * dvbpsi_EmptyCAT
+ *****************************************************************************
+ * Clean a dvbpsi_cat_t structure.
+ *****************************************************************************/
+void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat)
+{
+  dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor);
+
+  p_cat->p_first_descriptor = NULL;
+}
+                        
+
+/*****************************************************************************
+ * dvbpsi_CATAddDescriptor
+ *****************************************************************************
+ * Add a descriptor in the CAT.
+ *****************************************************************************/
+dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat,
+                                             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_cat->p_first_descriptor == NULL)
+    {
+      p_cat->p_first_descriptor = p_descriptor;
+    }
+    else
+    {
+      dvbpsi_descriptor_t* p_last_descriptor = p_cat->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_GatherCATSections
+ *****************************************************************************
+ * Callback for the PSI decoder.
+ *****************************************************************************/
+void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
+                              dvbpsi_psi_section_t* p_section)
+{
+  dvbpsi_cat_decoder_t* p_cat_decoder
+                        = (dvbpsi_cat_decoder_t*)p_decoder->p_private_decoder;
+  int b_append = 1;
+  int b_reinit = 0;
+  unsigned int i;
+
+  DVBPSI_DEBUG_ARG("CAT 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 != 0x01)
+  {
+    /* Invalid table_id value */
+    DVBPSI_ERROR_ARG("CAT 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("CAT decoder",
+                 "invalid section (section_syntax_indicator == 0)");
+    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_cat_decoder->p_building_cat)
+      {
+        if(p_cat_decoder->p_building_cat->i_version != p_section->i_version)
+        {
+          /* version_number */
+          DVBPSI_ERROR("CAT decoder",
+                       "'version_number' differs"
+                       " whereas no discontinuity has occured");
+          b_reinit = 1;
+        }
+        else if(p_cat_decoder->i_last_section_number
+                                                != p_section->i_last_number)
+        {
+          /* last_section_number */
+          DVBPSI_ERROR("CAT decoder",
+                       "'last_section_number' differs"
+                       " whereas no discontinuity has occured");
+          b_reinit = 1;
+        }
+      }
+      else
+      {
+        if(    (p_cat_decoder->b_current_valid)
+            && (p_cat_decoder->current_cat.i_version == p_section->i_version))
+        {
+          /* Signal a new CAT if the previous one wasn't active */
+          if(    (!p_cat_decoder->current_cat.b_current_next)
+              && (p_section->b_current_next))
+          {
+            dvbpsi_cat_t* p_cat = (dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t));
+
+            p_cat_decoder->current_cat.b_current_next = 1;
+            *p_cat = p_cat_decoder->current_cat;
+            p_cat_decoder->pf_callback(p_cat_decoder->p_cb_data, p_cat);
+          }
+
+          /* Don't decode since this version is already decoded */
+          b_append = 0;
+        }
+      }
+    }
+  }
+
+  /* Reinit the decoder if wanted */
+  if(b_reinit)
+  {
+    /* Force redecoding */
+    p_cat_decoder->b_current_valid = 0;
+    /* Free structures */
+    if(p_cat_decoder->p_building_cat)
+    {
+      free(p_cat_decoder->p_building_cat);
+      p_cat_decoder->p_building_cat = NULL;
+    }
+    /* Clear the section array */
+    for(i = 0; i <= 255; i++)
+    {
+      if(p_cat_decoder->ap_sections[i] != NULL)
+      {
+        dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[i]);
+        p_cat_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_cat_decoder->p_building_cat)
+    {
+      p_cat_decoder->p_building_cat =
+                                (dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t));
+      dvbpsi_InitCAT(p_cat_decoder->p_building_cat,
+                     p_section->i_version,
+                     p_section->b_current_next);
+      p_cat_decoder->i_last_section_number = p_section->i_last_number;
+    }
+
+    /* Fill the section array */
+    if(p_cat_decoder->ap_sections[p_section->i_number] != NULL)
+    {
+      DVBPSI_DEBUG_ARG("CAT decoder", "overwrite section number %d",
+                       p_section->i_number);
+      dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[p_section->i_number]);
+    }
+    p_cat_decoder->ap_sections[p_section->i_number] = p_section;
+
+    /* Check if we have all the sections */
+    b_complete = 0;
+    for(i = 0; i <= p_cat_decoder->i_last_section_number; i++)
+    {
+      if(!p_cat_decoder->ap_sections[i])
+        break;
+
+      if(i == p_cat_decoder->i_last_section_number)
+        b_complete = 1;
+    }
+
+    if(b_complete)
+    {
+      /* Save the current information */
+      p_cat_decoder->current_cat = *p_cat_decoder->p_building_cat;
+      p_cat_decoder->b_current_valid = 1;
+      /* Chain the sections */
+      if(p_cat_decoder->i_last_section_number)
+      {
+        for(i = 0; i <= p_cat_decoder->i_last_section_number - 1; i++)
+          p_cat_decoder->ap_sections[i]->p_next =
+                                        p_cat_decoder->ap_sections[i + 1];
+      }
+      /* Decode the sections */
+      dvbpsi_DecodeCATSections(p_cat_decoder->p_building_cat,
+                               p_cat_decoder->ap_sections[0]);
+      /* Delete the sections */
+      dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[0]);
+      /* signal the new CAT */
+      p_cat_decoder->pf_callback(p_cat_decoder->p_cb_data,
+                                 p_cat_decoder->p_building_cat);
+      /* Reinitialize the structures */
+      p_cat_decoder->p_building_cat = NULL;
+      for(i = 0; i <= p_cat_decoder->i_last_section_number; i++)
+        p_cat_decoder->ap_sections[i] = NULL;
+    }
+  }
+  else
+  {
+    dvbpsi_DeletePSISections(p_section);
+  }
+}
+
+
+/*****************************************************************************
+ * dvbpsi_DecodeCATSections
+ *****************************************************************************
+ * CAT decoder.
+ *****************************************************************************/
+void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat,
+                              dvbpsi_psi_section_t* p_section)
+{
+  uint8_t* p_byte, * p_end;
+
+  while(p_section)
+  {
+    /* CAT descriptors */
+    p_byte = p_section->p_payload_start;
+    while(p_byte + 5 <= p_section->p_payload_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_CATAddDescriptor(p_cat, i_tag, i_length, p_byte + 2);
+      p_byte += 2 + i_length;
+    }
+
+    p_section = p_section->p_next;
+  }
+}
+
+
+/*****************************************************************************
+ * dvbpsi_GenCATSections
+ *****************************************************************************
+ * Generate CAT sections based on the dvbpsi_cat_t structure.
+ *****************************************************************************/
+dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat)
+{
+  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_cat->p_first_descriptor;
+
+  p_current->i_table_id = 0x01;
+  p_current->b_syntax_indicator = 1;
+  p_current->b_private_indicator = 0;
+  p_current->i_length = 9;                      /* header + CRC_32 */
+  p_current->i_extension = 0;                   /* Not used in the CAT */
+  p_current->i_version = p_cat->i_version;
+  p_current->b_current_next = p_cat->b_current_next;
+  p_current->i_number = 0;
+  p_current->p_payload_end += 8;                /* just after the header */
+  p_current->p_payload_start = p_current->p_data + 8;
+
+  /* CAT 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)
+    {
+      p_prev = p_current;
+      p_current = dvbpsi_NewPSISection(1024);
+      p_prev->p_next = p_current;
+
+      p_current->i_table_id = 0x01;
+      p_current->b_syntax_indicator = 1;
+      p_current->b_private_indicator = 0;
+      p_current->i_length = 9;                  /* header + CRC_32 */
+      p_current->i_extension = 0;               /* Not used in the CAT */
+      p_current->i_version = p_cat->i_version;
+      p_current->b_current_next = p_cat->b_current_next;
+      p_current->i_number = p_prev->i_number + 1;
+      p_current->p_payload_end += 8;            /* just after the header */
+      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;
+  }
+
+  /* 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 libdvbpsi4-0.1.6pre-svn144/src/tables/cat.h libdvbpsi4-0.1.6pre-svn144-cat/src/tables/cat.h
--- libdvbpsi4-0.1.6pre-svn144/src/tables/cat.h	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi4-0.1.6pre-svn144-cat/src/tables/cat.h	2007-08-23 22:58:56.000000000 +0200
@@ -0,0 +1,208 @@
+/*****************************************************************************
+ * cat.h
+ * (c)2001-2002 VideoLAN
+ * $Id: cat.h 103 2005-01-21 14:34:51Z massiot $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt.h 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 <cat.h>
+ * \author Arnaud de Bossoreille de Ribou <[email protected]>
+ * \brief Application interface for the CAT decoder and the CAT generator.
+ *
+ * Application interface for the CAT decoder and the CAT generator. New
+ * decoded CAT 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_CAT_H_
+#define _DVBPSI_CAT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*****************************************************************************
+ * dvbpsi_cat_t
+ *****************************************************************************/
+/*!
+ * \struct dvbpsi_cat_s
+ * \brief CAT structure.
+ *
+ * This structure is used to store a decoded CAT.
+ * (ISO/IEC 13818-1 section 2.4.4.6).
+ */
+/*!
+ * \typedef struct dvbpsi_cat_s dvbpsi_cat_t
+ * \brief dvbpsi_cat_t type definition.
+ */
+typedef struct dvbpsi_cat_s
+{
+  uint8_t                   i_version;          /*!< version_number */
+  int                       b_current_next;     /*!< current_next_indicator */
+
+  dvbpsi_descriptor_t *     p_first_descriptor; /*!< descriptor list */
+
+} dvbpsi_cat_t;
+
+
+/*****************************************************************************
+ * dvbpsi_cat_callback
+ *****************************************************************************/
+/*!
+ * \typedef void (* dvbpsi_cat_callback)(void* p_cb_data,
+                                         dvbpsi_cat_t* p_new_cat)
+ * \brief Callback type definition.
+ */
+typedef void (* dvbpsi_cat_callback)(void* p_cb_data, dvbpsi_cat_t* p_new_cat);
+
+
+/*****************************************************************************
+ * dvbpsi_AttachCAT
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback,
+                                      void* p_cb_data)
+ * \brief Creation and initialization of a CAT decoder.
+ * \param pf_callback function to call back on new CAT
+ * \param p_cb_data private data given in argument to the callback
+ * \return a pointer to the decoder for future calls.
+ */
+dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback,
+                               void* p_cb_data);
+
+
+/*****************************************************************************
+ * dvbpsi_DetachCAT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi)
+ * \brief Destroy a CAT decoder.
+ * \param h_dvbpsi handle to the decoder
+ * \return nothing.
+ *
+ * The handle isn't valid any more.
+ */
+void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi);
+
+
+/*****************************************************************************
+ * dvbpsi_InitCAT/dvbpsi_NewCAT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
+                           uint8_t i_version, int b_current_next)
+ * \brief Initialize a user-allocated dvbpsi_cat_t structure.
+ * \param p_cat pointer to the CAT structure
+ * \param i_version CAT version
+ * \param b_current_next current next indicator
+ * \return nothing.
+ */
+void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat,
+                    uint8_t i_version, int b_current_next);
+
+/*!
+ * \def dvbpsi_NewCAT(p_cat,
+                      i_version, b_current_next)
+ * \brief Allocate and initialize a new dvbpsi_cat_t structure.
+ * \param p_cat pointer to the CAT structure
+ * \param i_version CAT version
+ * \param b_current_next current next indicator
+ * \return nothing.
+ */
+#define dvbpsi_NewCAT(p_cat,                                            \
+                      i_version, b_current_next)                        \
+do {                                                                    \
+  p_cat = (dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t));                  \
+  if(p_cat != NULL)                                                     \
+    dvbpsi_InitCAT(p_cat, i_version, b_current_next);                   \
+} while(0);
+
+
+/*****************************************************************************
+ * dvbpsi_EmptyCAT/dvbpsi_DeleteCAT
+ *****************************************************************************/
+/*!
+ * \fn void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat)
+ * \brief Clean a dvbpsi_cat_t structure.
+ * \param p_cat pointer to the CAT structure
+ * \return nothing.
+ */
+void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat);
+
+/*!
+ * \def dvbpsi_DeleteCAT(p_cat)
+ * \brief Clean and free a dvbpsi_cat_t structure.
+ * \param p_cat pointer to the CAT structure
+ * \return nothing.
+ */
+#define dvbpsi_DeleteCAT(p_cat)                                         \
+do {                                                                    \
+  dvbpsi_EmptyCAT(p_cat);                                               \
+  free(p_cat);                                                          \
+} while(0);
+
+
+/*****************************************************************************
+ * dvbpsi_CATAddDescriptor
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat,
+                                                    uint8_t i_tag,
+                                                    uint8_t i_length,
+                                                    uint8_t* p_data)
+ * \brief Add a descriptor in the CAT.
+ * \param p_cat pointer to the CAT 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_CATAddDescriptor(dvbpsi_cat_t* p_cat,
+                                             uint8_t i_tag, uint8_t i_length,
+                                             uint8_t* p_data);
+
+
+/*****************************************************************************
+ * dvbpsi_GenCATSections
+ *****************************************************************************/
+/*!
+ * \fn dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat)
+ * \brief CAT generator
+ * \param p_cat CAT structure
+ * \return a pointer to the list of generated PSI sections.
+ *
+ * Generate CAT sections based on the dvbpsi_cat_t structure.
+ */
+dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#else
+#error "Multiple inclusions of cat.h"
+#endif
+
diff -uNr libdvbpsi4-0.1.6pre-svn144/src/tables/cat_private.h libdvbpsi4-0.1.6pre-svn144-cat/src/tables/cat_private.h
--- libdvbpsi4-0.1.6pre-svn144/src/tables/cat_private.h	1970-01-01 01:00:00.000000000 +0100
+++ libdvbpsi4-0.1.6pre-svn144-cat/src/tables/cat_private.h	2007-08-23 18:54:47.000000000 +0200
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * cat_private.h: private CAT structures
+ *----------------------------------------------------------------------------
+ * (c)2001-2002 VideoLAN
+ * $Id: cat_private.h 88 2004-02-24 14:31:18Z sam $
+ *
+ * Authors: Johann Hanne
+ *          heavily based on pmt_private.h 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_CAT_PRIVATE_H_
+#define _DVBPSI_CAT_PRIVATE_H_
+
+/*****************************************************************************
+ * dvbpsi_cat_decoder_t
+ *****************************************************************************
+ * CAT decoder.
+ *****************************************************************************/
+typedef struct dvbpsi_cat_decoder_s
+{
+  dvbpsi_cat_callback           pf_callback;
+  void *                        p_cb_data;
+
+  dvbpsi_cat_t                  current_cat;
+  dvbpsi_cat_t *                p_building_cat;
+
+  int                           b_current_valid;
+
+  uint8_t                       i_last_section_number;
+  dvbpsi_psi_section_t *        ap_sections [256];
+
+} dvbpsi_cat_decoder_t;
+
+
+/*****************************************************************************
+ * dvbpsi_GatherCATSections
+ *****************************************************************************
+ * Callback for the PSI decoder.
+ *****************************************************************************/
+void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder,
+                              dvbpsi_psi_section_t* p_section);
+
+
+/*****************************************************************************
+ * dvbpsi_DecodeCATSections
+ *****************************************************************************
+ * CAT decoder.
+ *****************************************************************************/
+void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat,
+                              dvbpsi_psi_section_t* p_section);
+
+
+#else
+#error "Multiple inclusions of cat_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.