cat.c | cat.c | |||
---|---|---|---|---|
/************************************************************************** *** | /************************************************************************** *** | |||
* cat.c: CAT decoder/generator | * cat.c: CAT decoder/generator | |||
*------------------------------------------------------------------------- --- | *------------------------------------------------------------------------- --- | |||
* Copyright (C) 2001-2010 VideoLAN | * Copyright (C) 2001-2011 VideoLAN | |||
* $Id$ | * $Id$ | |||
* | * | |||
* Authors: Johann Hanne | * Authors: Johann Hanne | |||
* heavily based on pmt.c which was written by | * heavily based on pmt.c which was written by | |||
* Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> | * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> | |||
* Jean-Paul Saman <jpsaman@videolan.org> | ||||
* | * | |||
* This library is free software; you can redistribute it and/or | * This library is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | * modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | * License as published by the Free Software Foundation; either | |||
* version 2.1 of the License, or (at your option) any later version. | * version 2.1 of the License, or (at your option) any later version. | |||
* | * | |||
* This library is distributed in the hope that it will be useful, | * This library is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | * Lesser General Public License for more details. | |||
skipping to change at line 33 | skipping to change at line 34 | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130 1 USA | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130 1 USA | |||
* | * | |||
*------------------------------------------------------------------------- --- | *------------------------------------------------------------------------- --- | |||
* | * | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
#include "config.h" | #include "config.h" | |||
#include <stdio.h> | #include <stdio.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <stdbool.h> | ||||
#include <string.h> | #include <string.h> | |||
#if defined(HAVE_INTTYPES_H) | #if defined(HAVE_INTTYPES_H) | |||
#include <inttypes.h> | #include <inttypes.h> | |||
#elif defined(HAVE_STDINT_H) | #elif defined(HAVE_STDINT_H) | |||
#include <stdint.h> | #include <stdint.h> | |||
#endif | #endif | |||
#include <assert.h> | ||||
#include "../dvbpsi.h" | #include "../dvbpsi.h" | |||
#include "../dvbpsi_private.h" | #include "../dvbpsi_private.h" | |||
#include "../psi.h" | #include "../psi.h" | |||
#include "../descriptor.h" | #include "../descriptor.h" | |||
#include "cat.h" | #include "cat.h" | |||
#include "cat_private.h" | #include "cat_private.h" | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_AttachCAT | * dvbpsi_cat_attach | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Initialize a CAT decoder and return a handle on it. | * Initialize a CAT decoder and return a handle on it. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_handle dvbpsi_AttachCAT(dvbpsi_cat_callback pf_callback, | bool dvbpsi_cat_attach(dvbpsi_t *p_dvbpsi, dvbpsi_cat_callback pf_callback, | |||
void* p_cb_data) | void* p_cb_data) | |||
{ | { | |||
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_ | assert(p_dvbpsi); | |||
t)); | assert(p_dvbpsi->p_decoder == NULL); | |||
dvbpsi_cat_decoder_t* p_cat_decoder; | ||||
if(h_dvbpsi == NULL) | ||||
return NULL; | ||||
p_cat_decoder = (dvbpsi_cat_decoder_t*)malloc(sizeof(dvbpsi_cat_decoder_t | dvbpsi_cat_decoder_t* p_cat_decoder; | |||
)); | p_cat_decoder = (dvbpsi_cat_decoder_t*) dvbpsi_decoder_new(&dvbpsi_cat_ | |||
sections_gather, | ||||
if(p_cat_decoder == NULL) | 1024, true, sizeof(dvbpsi_c | |||
{ | at_decoder_t)); | |||
free(h_dvbpsi); | if (p_cat_decoder == NULL) | |||
return NULL; | return false; | |||
} | ||||
/* CAT decoder configuration */ | ||||
/* PSI decoder configuration */ | p_cat_decoder->pf_cat_callback = pf_callback; | |||
h_dvbpsi->pf_callback = &dvbpsi_GatherCATSections; | p_cat_decoder->p_cb_data = p_cb_data; | |||
h_dvbpsi->p_private_decoder = p_cat_decoder; | p_cat_decoder->p_building_cat = NULL; | |||
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(unsigned int i = 0; i <= 255; i++) | ||||
p_cat_decoder->ap_sections[i] = NULL; | ||||
return h_dvbpsi; | p_dvbpsi->p_decoder = DVBPSI_DECODER(p_cat_decoder); | |||
return true; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_DetachCAT | * dvbpsi_cat_detach | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Close a CAT decoder. The handle isn't valid any more. | * Close a CAT decoder. The handle isn't valid any more. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_DetachCAT(dvbpsi_handle h_dvbpsi) | void dvbpsi_cat_detach(dvbpsi_t *p_dvbpsi) | |||
{ | { | |||
dvbpsi_cat_decoder_t* p_cat_decoder | assert(p_dvbpsi); | |||
= (dvbpsi_cat_decoder_t*)h_dvbpsi->p_private_decode | assert(p_dvbpsi->p_decoder); | |||
r; | ||||
free(p_cat_decoder->p_building_cat); | ||||
for(unsigned int i = 0; i <= 255; i++) | dvbpsi_cat_decoder_t* p_cat_decoder | |||
{ | = (dvbpsi_cat_decoder_t*)p_dvbpsi->p_decoder; | |||
if(p_cat_decoder->ap_sections[i]) | if (p_cat_decoder->p_building_cat) | |||
free(p_cat_decoder->ap_sections[i]); | dvbpsi_cat_delete(p_cat_decoder->p_building_cat); | |||
} | p_cat_decoder->p_building_cat = NULL; | |||
free(h_dvbpsi->p_private_decoder); | dvbpsi_decoder_delete(p_dvbpsi->p_decoder); | |||
if(h_dvbpsi->p_current_section) | p_dvbpsi->p_decoder = NULL; | |||
dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); | ||||
free(h_dvbpsi); | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_InitCAT | * dvbpsi_cat_init | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Initialize a pre-allocated dvbpsi_cat_t structure. | * Initialize a pre-allocated dvbpsi_cat_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_InitCAT(dvbpsi_cat_t* p_cat, | void dvbpsi_cat_init(dvbpsi_cat_t* p_cat, uint8_t i_version, bool b_current | |||
uint8_t i_version, int b_current_next) | _next) | |||
{ | ||||
assert(p_cat); | ||||
p_cat->i_version = i_version; | ||||
p_cat->b_current_next = b_current_next; | ||||
p_cat->p_first_descriptor = NULL; | ||||
} | ||||
/************************************************************************** | ||||
*** | ||||
* dvbpsi_cat_new | ||||
************************************************************************** | ||||
*** | ||||
* Allocate and Initialize a dvbpsi_cat_t structure. | ||||
************************************************************************** | ||||
***/ | ||||
dvbpsi_cat_t *dvbpsi_cat_new(uint8_t i_version, bool b_current_next) | ||||
{ | { | |||
p_cat->i_version = i_version; | dvbpsi_cat_t *p_cat = (dvbpsi_cat_t*)malloc(sizeof(dvbpsi_cat_t)); | |||
p_cat->b_current_next = b_current_next; | if (p_cat != NULL) | |||
p_cat->p_first_descriptor = NULL; | dvbpsi_cat_init(p_cat, i_version, b_current_next); | |||
return p_cat; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_EmptyCAT | * dvbpsi_cat_empty | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Clean a dvbpsi_cat_t structure. | * Clean a dvbpsi_cat_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_EmptyCAT(dvbpsi_cat_t* p_cat) | void dvbpsi_cat_empty(dvbpsi_cat_t* p_cat) | |||
{ | { | |||
dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor); | dvbpsi_DeleteDescriptors(p_cat->p_first_descriptor); | |||
p_cat->p_first_descriptor = NULL; | ||||
} | ||||
p_cat->p_first_descriptor = NULL; | /************************************************************************** | |||
*** | ||||
* dvbpsi_cat_delete | ||||
************************************************************************** | ||||
*** | ||||
* Clean a dvbpsi_cat_t structure. | ||||
************************************************************************** | ||||
***/ | ||||
void dvbpsi_cat_delete(dvbpsi_cat_t *p_cat) | ||||
{ | ||||
if (p_cat) | ||||
dvbpsi_cat_empty(p_cat); | ||||
free(p_cat); | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_CATAddDescriptor | * dvbpsi_cat_descriptor_add | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Add a descriptor in the CAT. | * Add a descriptor in the CAT. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_descriptor_t* dvbpsi_CATAddDescriptor(dvbpsi_cat_t* p_cat, | dvbpsi_descriptor_t* dvbpsi_cat_descriptor_add(dvbpsi_cat_t* p_cat, | |||
uint8_t i_tag, uint8_t i_lengt h, | uint8_t i_tag, uint8_t i_lengt h, | |||
uint8_t* p_data) | uint8_t* p_data) | |||
{ | { | |||
dvbpsi_descriptor_t* p_descriptor | dvbpsi_descriptor_t* p_descriptor | |||
= dvbpsi_NewDescriptor(i_tag, i_length, p_data); | = dvbpsi_NewDescriptor(i_tag, i_length, p_data); | |||
if (p_descriptor == NULL) | ||||
return NULL; | ||||
p_cat->p_first_descriptor = dvbpsi_AddDescriptor(p_cat->p_first_descrip | ||||
tor, | ||||
p_descriptor); | ||||
assert(p_cat->p_first_descriptor); | ||||
if (p_cat->p_first_descriptor == NULL) | ||||
return NULL; | ||||
return p_descriptor; | ||||
} | ||||
/* */ | ||||
static void dvbpsi_ReInitCAT(dvbpsi_cat_decoder_t* p_decoder, const bool b_ | ||||
force) | ||||
{ | ||||
assert(p_decoder); | ||||
if(p_descriptor) | dvbpsi_decoder_reset(DVBPSI_DECODER(p_decoder), b_force); | |||
{ | ||||
if(p_cat->p_first_descriptor == NULL) | /* Force redecoding */ | |||
if (b_force) | ||||
{ | { | |||
p_cat->p_first_descriptor = p_descriptor; | /* Free structures */ | |||
if (p_decoder->p_building_cat) | ||||
dvbpsi_cat_delete(p_decoder->p_building_cat); | ||||
} | ||||
p_decoder->p_building_cat = NULL; | ||||
} | ||||
static bool dvbpsi_CheckCAT(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_sec | ||||
tion) | ||||
{ | ||||
bool b_reinit = false; | ||||
assert(p_dvbpsi->p_decoder); | ||||
dvbpsi_cat_decoder_t* p_cat_decoder; | ||||
p_cat_decoder = (dvbpsi_cat_decoder_t *)p_dvbpsi->p_decoder; | ||||
/* Perform a few sanity checks */ | ||||
#if 0 | ||||
if (p_pat_decoder->p_building_pat->i_ts_id != p_section->i_extension) | ||||
{ | ||||
/* transport_stream_id */ | ||||
dvbpsi_error(p_dvbpsi, "PAT decoder", | ||||
"'transport_stream_id' differs" | ||||
" whereas no TS discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | } | |||
else | else | |||
#endif | ||||
if (p_cat_decoder->p_building_cat->i_version != p_section->i_version) | ||||
{ | ||||
/* version_number */ | ||||
dvbpsi_error(p_dvbpsi, "CAT decoder", | ||||
"'version_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
else if (p_cat_decoder->i_last_section_number != p_section->i_last_numb | ||||
er) | ||||
{ | ||||
/* last_section_number */ | ||||
dvbpsi_error(p_dvbpsi, "CAT decoder", | ||||
"'last_section_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
return b_reinit; | ||||
} | ||||
static bool dvbpsi_AddSectionCAT(dvbpsi_t *p_dvbpsi, dvbpsi_cat_decoder_t * | ||||
p_decoder, | ||||
dvbpsi_psi_section_t* p_section) | ||||
{ | ||||
assert(p_dvbpsi); | ||||
assert(p_decoder); | ||||
assert(p_section); | ||||
/* Initialize the structures if it's the first section received */ | ||||
if (p_decoder->p_building_cat == NULL) | ||||
{ | { | |||
dvbpsi_descriptor_t* p_last_descriptor = p_cat->p_first_descriptor; | p_decoder->p_building_cat = dvbpsi_cat_new(p_section->i_version, | |||
while(p_last_descriptor->p_next != NULL) | p_section->b_current_nex | |||
p_last_descriptor = p_last_descriptor->p_next; | t); | |||
p_last_descriptor->p_next = p_descriptor; | if (p_decoder->p_building_cat == NULL) | |||
return false; | ||||
p_decoder->i_last_section_number = p_section->i_last_number; | ||||
} | } | |||
} | ||||
return p_descriptor; | /* Add to linked list of sections */ | |||
if (dvbpsi_decoder_psi_section_add(DVBPSI_DECODER(p_decoder), p_section | ||||
)) | ||||
dvbpsi_debug(p_dvbpsi, "CAT decoder", "overwrite section number %d" | ||||
, | ||||
p_section->i_number); | ||||
return true; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_GatherCATSections | * dvbpsi_cat_sections_gather | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Callback for the PSI decoder. | * Callback for the PSI decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_GatherCATSections(dvbpsi_decoder_t* p_decoder, | void dvbpsi_cat_sections_gather(dvbpsi_t *p_dvbpsi, | |||
dvbpsi_psi_section_t* p_section) | dvbpsi_psi_section_t* p_section) | |||
{ | { | |||
dvbpsi_cat_decoder_t* p_cat_decoder | assert(p_dvbpsi); | |||
= (dvbpsi_cat_decoder_t*)p_decoder->p_private_decod | assert(p_dvbpsi->p_decoder); | |||
er; | ||||
int b_append = 1; | if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0x01, "CAT decoder")) | |||
int b_reinit = 0; | { | |||
dvbpsi_DeletePSISections(p_section); | ||||
DVBPSI_DEBUG_ARG("CAT decoder", | return; | |||
"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, | dvbpsi_cat_decoder_t* p_cat_decoder | |||
p_section->b_current_next); | = (dvbpsi_cat_decoder_t*)p_dvbpsi->p_decoder; | |||
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 */ | /* TS discontinuity check */ | |||
if(p_decoder->b_discontinuity) | if (p_cat_decoder->b_discontinuity) | |||
{ | { | |||
b_reinit = 1; | dvbpsi_ReInitCAT(p_cat_decoder, true); | |||
p_decoder->b_discontinuity = 0; | p_cat_decoder->b_discontinuity = false; | |||
} | } | |||
else | else | |||
{ | { | |||
/* Perform some few sanity checks */ | /* Perform some few sanity checks */ | |||
if(p_cat_decoder->p_building_cat) | 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 */ | if (dvbpsi_CheckCAT(p_dvbpsi, p_section)) | |||
DVBPSI_ERROR("CAT decoder", | dvbpsi_ReInitCAT(p_cat_decoder, true); | |||
"'last_section_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = 1; | ||||
} | } | |||
} | else | |||
else | ||||
{ | ||||
if( (p_cat_decoder->b_current_valid) | ||||
&& (p_cat_decoder->current_cat.i_version == p_section->i_versio | ||||
n) | ||||
&& (p_cat_decoder->current_cat.b_current_next == | ||||
p_section->b_current_next)) | ||||
{ | { | |||
/* Don't decode since this version is already decoded */ | if ( (p_cat_decoder->b_current_valid) | |||
b_append = 0; | && (p_cat_decoder->current_cat.i_version == p_section->i_v | |||
ersion) | ||||
&& (p_cat_decoder->current_cat.b_current_next == | ||||
p_section->b_current_nex | ||||
t)) | ||||
{ | ||||
/* Don't decode since this version is already decoded */ | ||||
dvbpsi_debug(p_dvbpsi, "CAT decoder", | ||||
"ignoring already decoded section %d", | ||||
p_section->i_number); | ||||
dvbpsi_DeletePSISections(p_section); | ||||
return; | ||||
} | ||||
} | } | |||
} | ||||
} | ||||
} | ||||
/* 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(unsigned int 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 */ | /* Add section to CAT */ | |||
if(p_cat_decoder->ap_sections[p_section->i_number] != NULL) | if (!dvbpsi_AddSectionCAT(p_dvbpsi, p_cat_decoder, p_section)) | |||
{ | { | |||
DVBPSI_DEBUG_ARG("CAT decoder", "overwrite section number %d", | dvbpsi_error(p_dvbpsi, "CAT decoder", "failed decoding section %d", | |||
p_section->i_number); | p_section->i_number); | |||
dvbpsi_DeletePSISections(p_cat_decoder->ap_sections[p_section->i_numb | dvbpsi_DeletePSISections(p_section); | |||
er]); | return; | |||
} | } | |||
p_cat_decoder->ap_sections[p_section->i_number] = p_section; | ||||
/* Check if we have all the sections */ | /* Check if we have all the sections */ | |||
b_complete = 0; | if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_cat_decoder) | |||
for(unsigned int i = 0; i <= p_cat_decoder->i_last_section_number; i++) | )) | |||
{ | { | |||
if(!p_cat_decoder->ap_sections[i]) | assert(p_cat_decoder->pf_cat_callback); | |||
break; | ||||
if(i == p_cat_decoder->i_last_section_number) | /* Save the current information */ | |||
b_complete = 1; | p_cat_decoder->current_cat = *p_cat_decoder->p_building_cat; | |||
p_cat_decoder->b_current_valid = true; | ||||
/* Decode the sections */ | ||||
dvbpsi_cat_sections_decode(p_cat_decoder->p_building_cat, | ||||
p_cat_decoder->p_sections); | ||||
/* Delete the sections */ | ||||
dvbpsi_DeletePSISections(p_cat_decoder->p_sections); | ||||
p_cat_decoder->p_sections = NULL; | ||||
/* signal the new CAT */ | ||||
p_cat_decoder->pf_cat_callback(p_cat_decoder->p_cb_data, | ||||
p_cat_decoder->p_building_cat); | ||||
/* Reinitialize the structures */ | ||||
dvbpsi_ReInitCAT(p_cat_decoder, false); | ||||
} | } | |||
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(unsigned int i = 0; (int)i <= p_cat_decoder->i_last_section_num | ||||
ber - 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(unsigned int 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 | * dvbpsi_cat_sections_decode | |||
************************************************************************** *** | ************************************************************************** *** | |||
* CAT decoder. | * CAT decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_DecodeCATSections(dvbpsi_cat_t* p_cat, | void dvbpsi_cat_sections_decode(dvbpsi_cat_t* p_cat, dvbpsi_psi_section_t* | |||
dvbpsi_psi_section_t* p_section) | p_section) | |||
{ | { | |||
uint8_t* p_byte; | uint8_t* p_byte; | |||
while(p_section) | 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]; | /* CAT descriptors */ | |||
uint8_t i_length = p_byte[1]; | p_byte = p_section->p_payload_start; | |||
if(i_length + 2 <= p_section->p_payload_end - p_byte) | while (p_byte + 5 <= p_section->p_payload_end) | |||
dvbpsi_CATAddDescriptor(p_cat, i_tag, i_length, p_byte + 2); | { | |||
p_byte += 2 + i_length; | 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_cat_descriptor_add(p_cat, i_tag, i_length, p_byte + | ||||
2); | ||||
p_byte += 2 + i_length; | ||||
} | ||||
p_section = p_section->p_next; | ||||
} | } | |||
p_section = p_section->p_next; | ||||
} | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_GenCATSections | * dvbpsi_cat_sections_generate | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Generate CAT sections based on the dvbpsi_cat_t structure. | * 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* dvbpsi_cat_sections_generate(dvbpsi_t* p_dvbpsi, dvbp si_cat_t* p_cat) | |||
{ | { | |||
dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); | dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024); | |||
dvbpsi_psi_section_t* p_current = p_result; | dvbpsi_psi_section_t* p_current = p_result; | |||
dvbpsi_psi_section_t* p_prev; | dvbpsi_psi_section_t* p_prev; | |||
dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor; | dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor; | |||
p_current->i_table_id = 0x01; | p_current->i_table_id = 0x01; | |||
p_current->b_syntax_indicator = 1; | p_current->b_syntax_indicator = true; | |||
p_current->b_private_indicator = 0; | p_current->b_private_indicator = false; | |||
p_current->i_length = 9; /* header + CRC_32 */ | p_current->i_length = 9; /* header + CRC_32 */ | |||
p_current->i_extension = 0; /* Not used in the CAT */ | p_current->i_extension = 0; /* Not used in the CAT */ | |||
p_current->i_version = p_cat->i_version; | p_current->i_version = p_cat->i_version; | |||
p_current->b_current_next = p_cat->b_current_next; | p_current->b_current_next = p_cat->b_current_next; | |||
p_current->i_number = 0; | p_current->i_number = 0; | |||
p_current->p_payload_end += 8; /* just after the header */ | p_current->p_payload_end += 8; /* just after the header | |||
p_current->p_payload_start = p_current->p_data + 8; | */ | |||
p_current->p_payload_start = p_current->p_data + 8; | ||||
/* CAT descriptors */ | ||||
while(p_descriptor != NULL) | /* 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; | /* New section if needed */ | |||
p_current = dvbpsi_NewPSISection(1024); | /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_leng | |||
p_prev->p_next = p_current; | th */ | |||
if( (p_current->p_payload_end - p_current->p_data) | ||||
p_current->i_table_id = 0x01; | + p_descriptor->i_length > 1018) | |||
p_current->b_syntax_indicator = 1; | { | |||
p_current->b_private_indicator = 0; | p_prev = p_current; | |||
p_current->i_length = 9; /* header + CRC_32 */ | p_current = dvbpsi_NewPSISection(1024); | |||
p_current->i_extension = 0; /* Not used in the CAT */ | p_prev->p_next = p_current; | |||
p_current->i_version = p_cat->i_version; | ||||
p_current->b_current_next = p_cat->b_current_next; | p_current->i_table_id = 0x01; | |||
p_current->i_number = p_prev->i_number + 1; | p_current->b_syntax_indicator = true; | |||
p_current->p_payload_end += 8; /* just after the header */ | p_current->b_private_indicator = false; | |||
p_current->p_payload_start = p_current->p_data + 8; | p_current->i_length = 9; /* header + CRC_32 */ | |||
} | p_current->i_extension = 0; /* Not used in the CA | |||
T */ | ||||
/* p_payload_end is where the descriptor begins */ | p_current->i_version = p_cat->i_version; | |||
p_current->p_payload_end[0] = p_descriptor->i_tag; | p_current->b_current_next = p_cat->b_current_next; | |||
p_current->p_payload_end[1] = p_descriptor->i_length; | p_current->i_number = p_prev->i_number + 1; | |||
memcpy(p_current->p_payload_end + 2, | p_current->p_payload_end += 8; /* just after the hea | |||
p_descriptor->p_data, | der */ | |||
p_descriptor->i_length); | p_current->p_payload_start = p_current->p_data + 8; | |||
} | ||||
/* Increase length by descriptor_length + 2 */ | ||||
p_current->p_payload_end += p_descriptor->i_length + 2; | /* p_payload_end is where the descriptor begins */ | |||
p_current->i_length += p_descriptor->i_length + 2; | p_current->p_payload_end[0] = p_descriptor->i_tag; | |||
p_current->p_payload_end[1] = p_descriptor->i_length; | ||||
p_descriptor = p_descriptor->p_next; | memcpy(p_current->p_payload_end + 2, | |||
} | p_descriptor->p_data, p_descriptor->i_length); | |||
/* Finalization */ | /* Increase length by descriptor_length + 2 */ | |||
p_prev = p_result; | p_current->p_payload_end += p_descriptor->i_length + 2; | |||
while(p_prev != NULL) | p_current->i_length += p_descriptor->i_length + 2; | |||
{ | ||||
p_prev->i_last_number = p_current->i_number; | ||||
dvbpsi_BuildPSISection(p_prev); | ||||
p_prev = p_prev->p_next; | ||||
} | ||||
return p_result; | 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_dvbpsi, p_prev); | ||||
p_prev = p_prev->p_next; | ||||
} | ||||
return p_result; | ||||
} | } | |||
End of changes. 60 change blocks. | ||||
311 lines changed or deleted | 316 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |