sis.c | sis.c | |||
---|---|---|---|---|
/************************************************************************** *** | /************************************************************************** *** | |||
* sis.c: SIS decoder/generator | * sis.c: SIS decoder/generator | |||
*------------------------------------------------------------------------- --- | *------------------------------------------------------------------------- --- | |||
* Copyright (C) 2010 VideoLAN | * Copyright (C) 2010-2011 VideoLAN | |||
* $Id:$ | * $Id:$ | |||
* | * | |||
* Authors: Jean-Paul Saman <jpsaman@videolan.org> | * Authors: 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, | |||
skipping to change at line 31 | skipping to change at line 31 | |||
* 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 <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 "../demux.h" | #include "../demux.h" | |||
#include "sis.h" | #include "sis.h" | |||
#include "sis_private.h" | #include "sis_private.h" | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_AttachSIS | * dvbpsi_sis_attach | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Initialize a SIS subtable decoder. | * Initialize a SIS subtable decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
int dvbpsi_AttachSIS(dvbpsi_decoder_t *p_psi_decoder, uint8_t i_table_id, | bool dvbpsi_sis_attach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_e | |||
uint16_t i_extension, dvbpsi_sis_callback pf_callback, | xtension, | |||
void* p_cb_data) | dvbpsi_sis_callback pf_callback, void* p_cb_data) | |||
{ | { | |||
dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_psi_decoder->p_private_dec | assert(p_dvbpsi); | |||
oder; | assert(p_dvbpsi->p_decoder); | |||
dvbpsi_demux_subdec_t* p_subdec; | ||||
dvbpsi_sis_decoder_t* p_sis_decoder; | dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_decoder; | |||
i_extension = 0; | i_extension = 0; | |||
if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) | if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension)) | |||
{ | { | |||
DVBPSI_ERROR_ARG("SIS decoder", | dvbpsi_error(p_dvbpsi, "SIS decoder", | |||
"Already a decoder for (table_id == 0x%02x," | "Already a decoder for (table_id == 0x%02x," | |||
"extension == 0x%02x)", | "extension == 0x%02x)", | |||
i_table_id, i_extension); | i_table_id, i_extension); | |||
return false; | ||||
return 1; | ||||
} | } | |||
p_subdec = (dvbpsi_demux_subdec_t*)malloc(sizeof(dvbpsi_demux_subdec_t) | dvbpsi_sis_decoder_t* p_sis_decoder; | |||
); | p_sis_decoder = (dvbpsi_sis_decoder_t*) dvbpsi_decoder_new(NULL, | |||
if (p_subdec == NULL) | 0, true, sizeof(dvbpsi_sis_dec | |||
{ | oder_t)); | |||
return 1; | ||||
} | ||||
p_sis_decoder = (dvbpsi_sis_decoder_t*)malloc(sizeof(dvbpsi_sis_decoder | ||||
_t)); | ||||
if (p_sis_decoder == NULL) | if (p_sis_decoder == NULL) | |||
{ | return false; | |||
free(p_subdec); | ||||
return 1; | ||||
} | ||||
/* subtable decoder configuration */ | /* subtable decoder configuration */ | |||
p_subdec->pf_callback = &dvbpsi_GatherSISSections; | dvbpsi_demux_subdec_t* p_subdec; | |||
p_subdec->p_cb_data = p_sis_decoder; | p_subdec = dvbpsi_NewDemuxSubDecoder(i_table_id, i_extension, dvbpsi_si | |||
p_subdec->i_id = (uint32_t)i_table_id << 16 | (uint32_t)i_extension; | s_detach, | |||
p_subdec->pf_detach = dvbpsi_DetachSIS; | dvbpsi_sis_sections_gather, DVBPSI | |||
_DECODER(p_sis_decoder)); | ||||
if (p_subdec == NULL) | ||||
{ | ||||
dvbpsi_decoder_delete(DVBPSI_DECODER(p_sis_decoder)); | ||||
return false; | ||||
} | ||||
/* Attach the subtable decoder to the demux */ | /* Attach the subtable decoder to the demux */ | |||
p_subdec->p_next = p_demux->p_first_subdec; | dvbpsi_AttachDemuxSubDecoder(p_demux, p_subdec); | |||
p_demux->p_first_subdec = p_subdec; | ||||
/* SIS decoder information */ | /* SIS decoder information */ | |||
p_sis_decoder->pf_callback = pf_callback; | p_sis_decoder->pf_sis_callback = pf_callback; | |||
p_sis_decoder->p_cb_data = p_cb_data; | p_sis_decoder->p_cb_data = p_cb_data; | |||
p_sis_decoder->p_building_sis = NULL; | ||||
return 0; | return true; | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_DetachSIS | * dvbpsi_sis_detach | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Close a SIS decoder. | * Close a SIS decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_DetachSIS(dvbpsi_demux_t * p_demux, uint8_t i_table_id, | void dvbpsi_sis_detach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_e | |||
uint16_t i_extension) | xtension) | |||
{ | { | |||
dvbpsi_demux_subdec_t* p_subdec; | assert(p_dvbpsi); | |||
dvbpsi_demux_subdec_t** pp_prev_subdec; | assert(p_dvbpsi->p_decoder); | |||
dvbpsi_sis_decoder_t* p_sis_decoder; | ||||
i_extension = 0; | dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder; | |||
i_extension = 0; | ||||
dvbpsi_demux_subdec_t* p_subdec; | ||||
p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension); | p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension); | |||
if (p_demux == NULL) | if (p_demux == NULL) | |||
{ | { | |||
DVBPSI_ERROR_ARG("SIS Decoder", | dvbpsi_error(p_dvbpsi, "SIS Decoder", | |||
"No such SIS decoder (table_id == 0x%02x," | "No such SIS decoder (table_id == 0x%02x," | |||
"extension == 0x%02x)", | "extension == 0x%02x)", | |||
i_table_id, i_extension); | i_table_id, i_extension); | |||
return; | return; | |||
} | } | |||
p_sis_decoder = (dvbpsi_sis_decoder_t*)p_subdec->p_cb_data; | assert(p_subdec->p_decoder); | |||
free(p_subdec->p_cb_data); | ||||
pp_prev_subdec = &p_demux->p_first_subdec; | dvbpsi_sis_decoder_t* p_sis_decoder; | |||
while(*pp_prev_subdec != p_subdec) | p_sis_decoder = (dvbpsi_sis_decoder_t*)p_subdec->p_decoder; | |||
pp_prev_subdec = &(*pp_prev_subdec)->p_next; | if (p_sis_decoder->p_building_sis) | |||
dvbpsi_sis_delete(p_sis_decoder->p_building_sis); | ||||
p_sis_decoder->p_building_sis = NULL; | ||||
*pp_prev_subdec = p_subdec->p_next; | dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec); | |||
free(p_subdec); | dvbpsi_DeleteDemuxSubDecoder(p_subdec); | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_InitSIS | * dvbpsi_sis_init | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Initialize a pre-allocated dvbpsi_sis_t structure. | * Initialize a pre-allocated dvbpsi_sis_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_InitSIS(dvbpsi_sis_t *p_sis, uint8_t i_protocol_version) | void dvbpsi_sis_init(dvbpsi_sis_t *p_sis, uint8_t i_table_id, uint16_t i_ex | |||
tension, | ||||
uint8_t i_version, bool b_current_next, uint8_t i_prot | ||||
ocol_version) | ||||
{ | { | |||
p_sis->i_table_id = i_table_id; | ||||
p_sis->i_extension = i_extension; | ||||
p_sis->i_version = i_version; | ||||
p_sis->b_current_next = b_current_next; | ||||
assert(i_protocol_version == 0); | assert(i_protocol_version == 0); | |||
p_sis->i_protocol_version = 0; /* must be 0 */ | p_sis->i_protocol_version = 0; /* must be 0 */ | |||
/* encryption */ | /* encryption */ | |||
p_sis->b_encrypted_packet = 0; | p_sis->b_encrypted_packet = false; | |||
p_sis->i_encryption_algorithm = 0; | p_sis->i_encryption_algorithm = 0; | |||
p_sis->i_pts_adjustment = (uint64_t)0; | p_sis->i_pts_adjustment = (uint64_t)0; | |||
p_sis->cw_index = 0; | p_sis->cw_index = 0; | |||
/* splice command */ | /* splice command */ | |||
p_sis->i_splice_command_length = 0; | p_sis->i_splice_command_length = 0; | |||
p_sis->i_splice_command_type = 0x00; | p_sis->i_splice_command_type = 0x00; | |||
/* FIXME: splice_info_section comes here */ | /* FIXME: splice_info_section comes here */ | |||
skipping to change at line 174 | skipping to change at line 178 | |||
/* descriptors */ | /* descriptors */ | |||
p_sis->i_descriptors_length = 0; | p_sis->i_descriptors_length = 0; | |||
p_sis->p_first_descriptor = NULL; | p_sis->p_first_descriptor = NULL; | |||
/* FIXME: alignment stuffing */ | /* FIXME: alignment stuffing */ | |||
p_sis->i_ecrc = 0; | p_sis->i_ecrc = 0; | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_EmptySIS | * dvbpsi_sis_new | |||
************************************************************************** | ||||
*** | ||||
* Allocate and Initialize a new dvbpsi_sis_t structure. | ||||
************************************************************************** | ||||
***/ | ||||
dvbpsi_sis_t* dvbpsi_sis_new(uint8_t i_table_id, uint16_t i_extension, uint | ||||
8_t i_version, | ||||
bool b_current_next, uint8_t i_protocol_versio | ||||
n) | ||||
{ | ||||
dvbpsi_sis_t* p_sis = (dvbpsi_sis_t*)malloc(sizeof(dvbpsi_sis_t)); | ||||
if (p_sis != NULL) | ||||
dvbpsi_sis_init(p_sis, i_table_id, i_extension, i_version, | ||||
b_current_next, i_protocol_version); | ||||
return p_sis; | ||||
} | ||||
/************************************************************************** | ||||
*** | ||||
* dvbpsi_sis_empty | ||||
************************************************************************** *** | ************************************************************************** *** | |||
* Clean a dvbpsi_sis_t structure. | * Clean a dvbpsi_sis_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_EmptySIS(dvbpsi_sis_t* p_sis) | void dvbpsi_sis_empty(dvbpsi_sis_t* p_sis) | |||
{ | { | |||
/* FIXME: free splice_command_sections */ | /* FIXME: free splice_command_sections */ | |||
dvbpsi_DeleteDescriptors(p_sis->p_first_descriptor); | dvbpsi_DeleteDescriptors(p_sis->p_first_descriptor); | |||
p_sis->p_first_descriptor = NULL; | p_sis->p_first_descriptor = NULL; | |||
/* FIXME: free alignment stuffing */ | /* FIXME: free alignment stuffing */ | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_SISAddDescriptor | * dvbpsi_sis_delete | |||
************************************************************************** | ||||
*** | ||||
* Clean and Delete a dvbpsi_sis_t structure. | ||||
************************************************************************** | ||||
***/ | ||||
void dvbpsi_sis_delete(dvbpsi_sis_t *p_sis) | ||||
{ | ||||
if (p_sis) | ||||
dvbpsi_sis_empty(p_sis); | ||||
free(p_sis); | ||||
} | ||||
/************************************************************************** | ||||
*** | ||||
* dvbpsi_sis_descriptor_add | ||||
************************************************************************** *** | ************************************************************************** *** | |||
* Add a descriptor in the SIS service description. | * Add a descriptor in the SIS service description. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_descriptor_t *dvbpsi_SISAddDescriptor( dvbpsi_sis_t *p_sis, | dvbpsi_descriptor_t *dvbpsi_sis_descriptor_add(dvbpsi_sis_t *p_sis, | |||
uint8_t i_tag, uint8_t i_leng | uint8_t i_tag, uint8_t i_lengt | |||
th, | h, | |||
uint8_t *p_data) | uint8_t *p_data) | |||
{ | { | |||
dvbpsi_descriptor_t * p_descriptor; | dvbpsi_descriptor_t * p_descriptor; | |||
p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); | p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); | |||
if (p_descriptor) | if (p_descriptor == NULL) | |||
return NULL; | ||||
p_sis->p_first_descriptor = dvbpsi_AddDescriptor(p_sis->p_first_descrip | ||||
tor, | ||||
p_descriptor); | ||||
assert(p_sis->p_first_descriptor); | ||||
if (p_sis->p_first_descriptor == NULL) | ||||
return NULL; | ||||
return p_descriptor; | ||||
} | ||||
/* */ | ||||
static void dvbpsi_ReInitSIS(dvbpsi_sis_decoder_t* p_decoder, const bool b_ | ||||
force) | ||||
{ | ||||
assert(p_decoder); | ||||
dvbpsi_decoder_reset(DVBPSI_DECODER(p_decoder), b_force); | ||||
/* Force redecoding */ | ||||
if (b_force) | ||||
{ | { | |||
if (p_sis->p_first_descriptor == NULL) | /* Free structures */ | |||
{ | if (p_decoder->p_building_sis) | |||
p_sis->p_first_descriptor = p_descriptor; | dvbpsi_sis_delete(p_decoder->p_building_sis); | |||
} | ||||
else | ||||
{ | ||||
dvbpsi_descriptor_t * p_last_descriptor = p_sis->p_first_descri | ||||
ptor; | ||||
while (p_last_descriptor->p_next != NULL) | ||||
p_last_descriptor = p_last_descriptor->p_next; | ||||
p_last_descriptor->p_next = p_descriptor; | ||||
} | ||||
} | } | |||
p_decoder->p_building_sis = NULL; | ||||
} | ||||
return p_descriptor; | static bool dvbpsi_CheckSIS(dvbpsi_t *p_dvbpsi, dvbpsi_sis_decoder_t* p_sis | |||
_decoder, | ||||
dvbpsi_psi_section_t *p_section) | ||||
{ | ||||
bool b_reinit = false; | ||||
assert(p_dvbpsi); | ||||
assert(p_sis_decoder); | ||||
if (p_sis_decoder->p_building_sis->i_protocol_version != 0) | ||||
{ | ||||
dvbpsi_error(p_dvbpsi, "SIS decoder", | ||||
"'protocol_version' differs" | ||||
" while no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
else if (p_sis_decoder->p_building_sis->i_extension != p_section->i_ext | ||||
ension) | ||||
{ | ||||
dvbpsi_error(p_dvbpsi, "SIS decoder", | ||||
"'transport_stream_id' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
else if (p_sis_decoder->p_building_sis->i_version != p_section->i_versi | ||||
on) | ||||
{ | ||||
/* version_number */ | ||||
dvbpsi_error(p_dvbpsi, "SIS decoder", | ||||
"'version_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
else if (p_sis_decoder->i_last_section_number != p_section->i_last_numb | ||||
er) | ||||
{ | ||||
/* last_section_number */ | ||||
dvbpsi_error(p_dvbpsi, "SIS decoder", | ||||
"'last_section_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
return b_reinit; | ||||
} | ||||
static bool dvbpsi_AddSectionSIS(dvbpsi_t *p_dvbpsi, dvbpsi_sis_decoder_t * | ||||
p_sis_decoder, | ||||
dvbpsi_psi_section_t* p_section) | ||||
{ | ||||
assert(p_dvbpsi); | ||||
assert(p_sis_decoder); | ||||
assert(p_section); | ||||
/* Initialize the structures if it's the first section received */ | ||||
if (!p_sis_decoder->p_building_sis) | ||||
{ | ||||
p_sis_decoder->p_building_sis = dvbpsi_sis_new( | ||||
p_section->i_table_id, p_section->i_extension, | ||||
p_section->i_version, p_section->b_current_next | ||||
, 0); | ||||
if (p_sis_decoder->p_building_sis == NULL) | ||||
return false; | ||||
p_sis_decoder->i_last_section_number = p_section->i_last_number; | ||||
} | ||||
/* Add to linked list of sections */ | ||||
if (dvbpsi_decoder_psi_section_add(DVBPSI_DECODER(p_sis_decoder), p_sec | ||||
tion)) | ||||
dvbpsi_debug(p_dvbpsi, "SDT decoder", "overwrite section number %d" | ||||
, | ||||
p_section->i_number); | ||||
return true; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_GatherSISSections | * dvbpsi_sis_sections_gather | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Callback for the subtable demultiplexor. | * Callback for the subtable demultiplexor. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_GatherSISSections(dvbpsi_decoder_t * p_psi_decoder, | void dvbpsi_sis_sections_gather(dvbpsi_t *p_dvbpsi, | |||
void * p_private_decoder, | dvbpsi_decoder_t *p_decoder, | |||
dvbpsi_psi_section_t * p_section) | dvbpsi_psi_section_t * p_section) | |||
{ | { | |||
dvbpsi_sis_decoder_t * p_sis_decoder | assert(p_dvbpsi); | |||
= (dvbpsi_sis_decoder_t*)p_private_decoder; | assert(p_dvbpsi->p_decoder); | |||
int b_append = 1; | ||||
int b_reinit = 0; | ||||
DVBPSI_DEBUG_ARG("SIS decoder", | ||||
"Table version %2d, " "i_table_id %2d, " "i_extension | ||||
%5d, " | ||||
"section %3d up to %3d, " "current %1d", | ||||
p_section->i_version, p_section->i_table_id, | ||||
p_section->i_extension, | ||||
p_section->i_number, p_section->i_last_number, | ||||
p_section->b_current_next); | ||||
if (p_section->i_table_id != 0xFC) | if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0xFC, "SIS decoder")) | |||
{ | { | |||
/* Invalid table_id value */ | dvbpsi_DeletePSISections(p_section); | |||
DVBPSI_ERROR_ARG("SIS decoder", | return; | |||
"invalid section (table_id == 0x%02x)", | ||||
p_section->i_table_id); | ||||
b_append = 0; | ||||
} | } | |||
if (p_section->b_syntax_indicator != 0) | /* */ | |||
{ | dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder; | |||
/* Invalid section_syntax_indicator */ | dvbpsi_sis_decoder_t * p_sis_decoder = (dvbpsi_sis_decoder_t*)p_decoder | |||
DVBPSI_ERROR("SIS decoder", | ; | |||
"invalid section (section_syntax_indicator != 0)"); | ||||
b_append = 0; | ||||
} | ||||
if (p_section->b_private_indicator != 0) | if (p_section->b_private_indicator) | |||
{ | { | |||
/* Invalid private_syntax_indicator */ | /* Invalid private_syntax_indicator */ | |||
DVBPSI_ERROR("SIS decoder", | dvbpsi_error(p_dvbpsi, "SIS decoder", | |||
"invalid private section (private_syntax_indicator != | "invalid private section (private_syntax_indicator != | |||
0)"); | false)"); | |||
b_append = 0; | dvbpsi_DeletePSISections(p_section); | |||
return; | ||||
} | } | |||
/* Now if b_append is true then we have a valid SIS section */ | /* TS discontinuity check */ | |||
if (b_append) | if (p_demux->b_discontinuity) | |||
{ | { | |||
/* TS discontinuity check */ | dvbpsi_ReInitSIS(p_sis_decoder, true); | |||
if (p_psi_decoder->b_discontinuity) | p_sis_decoder->b_discontinuity = false; | |||
p_demux->b_discontinuity = false; | ||||
} | ||||
else | ||||
{ | ||||
/* Perform a few sanity checks */ | ||||
if (p_sis_decoder->p_building_sis) | ||||
{ | { | |||
b_reinit = 1; | if (dvbpsi_CheckSIS(p_dvbpsi, p_sis_decoder, p_section)) | |||
p_psi_decoder->b_discontinuity = 0; | dvbpsi_ReInitSIS(p_sis_decoder, true); | |||
} | } | |||
else | else | |||
{ | { | |||
/* Perform a few sanity checks */ | if( (p_sis_decoder->b_current_valid) | |||
if (p_sis_decoder->p_building_sis) | && (p_sis_decoder->current_sis.i_version == p_section->i_v | |||
{ | ersion) | |||
if (p_sis_decoder->p_building_sis->i_protocol_version != 0) | && (p_sis_decoder->current_sis.b_current_next == p_section | |||
{ | ->b_current_next)) | |||
/* transport_stream_id */ | { | |||
DVBPSI_ERROR("SIS decoder", | /* Don't decode since this version is already decoded */ | |||
"'protocol_version' differs");\ | dvbpsi_debug(p_dvbpsi, "SIT decoder", | |||
b_reinit = 1; | "ignoring already decoded section %d", | |||
} | p_section->i_number); | |||
} | dvbpsi_DeletePSISections(p_section); | |||
else | return; | |||
{ | } | |||
if (p_sis_decoder->b_current_valid) | ||||
{ | ||||
/* Don't decode since this version is already decoded * | ||||
/ | ||||
b_append = 0; | ||||
} | ||||
} | ||||
} | } | |||
} | } | |||
/* Reinit the decoder if wanted */ | /* Add section to SIS */ | |||
if (b_reinit) | if (!dvbpsi_AddSectionSIS(p_dvbpsi, p_sis_decoder, p_section)) | |||
{ | { | |||
/* Force redecoding */ | dvbpsi_error(p_dvbpsi, "SIS decoder", "failed decoding section %d", | |||
p_sis_decoder->b_current_valid = 0; | p_section->i_number); | |||
dvbpsi_DeletePSISections(p_section); | ||||
/* Free structures */ | return; | |||
if (p_sis_decoder->p_building_sis) | ||||
{ | ||||
free(p_sis_decoder->p_building_sis); | ||||
p_sis_decoder->p_building_sis = NULL; | ||||
} | ||||
} | } | |||
/* Append the section to the list if wanted */ | /* Check if we have all the sections */ | |||
if (b_append) | if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_sis_decoder) | |||
{ | )) | |||
/* Initialize the structures if it's the first section received */ | ||||
if (!p_sis_decoder->p_building_sis) | ||||
{ | ||||
p_sis_decoder->p_building_sis = | ||||
(dvbpsi_sis_t*)malloc(sizeof(dvbpsi_sis_t)) | ||||
; | ||||
// FIXME: potiential crash on OUT OF MEMORY | ||||
dvbpsi_InitSIS(p_sis_decoder->p_building_sis, 0); | ||||
} | ||||
} | ||||
else | ||||
{ | { | |||
dvbpsi_DeletePSISections(p_section); | assert(p_sis_decoder->pf_sis_callback); | |||
/* Save the current information */ | ||||
p_sis_decoder->current_sis = *p_sis_decoder->p_building_sis; | ||||
p_sis_decoder->b_current_valid = true; | ||||
/* Decode the sections */ | ||||
dvbpsi_sis_sections_decode(p_dvbpsi, p_sis_decoder->p_building_sis, | ||||
p_sis_decoder->p_sections); | ||||
/* Delete the sections */ | ||||
dvbpsi_DeletePSISections(p_sis_decoder->p_sections); | ||||
p_sis_decoder->p_sections = NULL; | ||||
/* signal the new SDT */ | ||||
p_sis_decoder->pf_sis_callback(p_sis_decoder->p_cb_data, | ||||
p_sis_decoder->p_building_sis); | ||||
/* Reinitialize the structures */ | ||||
dvbpsi_ReInitSIS(p_sis_decoder, false); | ||||
} | } | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_DecodeSISSection | * dvbpsi_sis_sections_decode | |||
************************************************************************** *** | ************************************************************************** *** | |||
* SIS decoder. | * SIS decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_DecodeSISSections(dvbpsi_sis_t* p_sis, | void dvbpsi_sis_sections_decode(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis, | |||
dvbpsi_psi_section_t* p_section) | dvbpsi_psi_section_t* p_section) | |||
{ | { | |||
uint8_t *p_byte, *p_end; | uint8_t *p_byte, *p_end; | |||
while (p_section) | while (p_section) | |||
{ | { | |||
for (p_byte = p_section->p_payload_start + 3; | for (p_byte = p_section->p_payload_start + 3; | |||
p_byte < p_section->p_payload_end; ) | p_byte < p_section->p_payload_end; ) | |||
{ | { | |||
p_sis->i_protocol_version = p_byte[3]; | p_sis->i_protocol_version = p_byte[3]; | |||
p_sis->b_encrypted_packet = ((p_byte[4] & 0x80)>>8); | p_sis->b_encrypted_packet = ((p_byte[4] & 0x80)>>8); | |||
/* NOTE: cannot handle encrypted packet */ | /* NOTE: cannot handle encrypted packet */ | |||
assert(p_sis->b_encrypted_packet == 1); | assert(p_sis->b_encrypted_packet); | |||
p_sis->i_encryption_algorithm = ((p_byte[4] & 0x7E) >> 1); | p_sis->i_encryption_algorithm = ((p_byte[4] & 0x7E) >> 1); | |||
p_sis->i_pts_adjustment = ((((uint64_t)p_byte[4] & 0x01) << 32) | | p_sis->i_pts_adjustment = ((((uint64_t)p_byte[4] & 0x01) << 32) | | |||
((uint64_t)p_byte[5] << 24) | | ((uint64_t)p_byte[5] << 24) | | |||
((uint64_t)p_byte[6] << 16) | | ((uint64_t)p_byte[6] << 16) | | |||
((uint64_t)p_byte[7] << 8) | | ((uint64_t)p_byte[7] << 8) | | |||
(uint64_t)p_byte[8]); | (uint64_t)p_byte[8]); | |||
p_sis->cw_index = p_byte[9]; | p_sis->cw_index = p_byte[9]; | |||
p_sis->i_splice_command_length = ((p_byte[11] & 0x0F) << 8) | p _byte[12]; | p_sis->i_splice_command_length = ((p_byte[11] & 0x0F) << 8) | p _byte[12]; | |||
p_sis->i_splice_command_type = p_byte[13]; | p_sis->i_splice_command_type = p_byte[13]; | |||
uint32_t i_splice_command_length = p_sis->i_splice_command_leng th; | uint32_t i_splice_command_length = p_sis->i_splice_command_leng th; | |||
if (p_sis->i_splice_command_length == 0xfff) | if (p_sis->i_splice_command_length == 0xfff) | |||
{ | { | |||
/* FIXME: size 0xfff of splice_command_section is undefined */ | /* FIXME: size 0xfff of splice_command_section is undefined */ | |||
assert(p_sis->i_splice_command_length != 0xfff); | assert(p_sis->i_splice_command_length != 0xfff); | |||
} | } | |||
/* FIXME: handle splice_command_sections */ | /* FIXME: handle splice_command_sections */ | |||
switch(p_sis->i_splice_command_type) | ||||
{ | ||||
case 0x00: /* splice_null */ | ||||
case 0x04: /* splice_schedule */ | ||||
case 0x05: /* splice_insert */ | ||||
case 0x06: /* time_signal */ | ||||
case 0x07: /* bandwidth_reservation */ | ||||
break; | ||||
default: | ||||
dvbpsi_error(p_dvbpsi, "SIS decoder", "invalid SIS Comm | ||||
and found"); | ||||
break; | ||||
} | ||||
/* Service descriptors */ | /* Service descriptors */ | |||
uint8_t *p_desc = p_byte + 13 + i_splice_command_length; | uint8_t *p_desc = p_byte + 13 + i_splice_command_length; | |||
p_sis->i_descriptors_length = (p_desc[0] << 8) | p_desc[1]; | p_sis->i_descriptors_length = (p_desc[0] << 8) | p_desc[1]; | |||
p_desc += 1; | p_desc += 1; | |||
p_end = p_desc + p_sis->i_descriptors_length; | p_end = p_desc + p_sis->i_descriptors_length; | |||
if (p_end > p_section->p_payload_end) break; | if (p_end > p_section->p_payload_end) break; | |||
while (p_desc + 2 <= p_end) | while (p_desc + 2 <= p_end) | |||
{ | { | |||
uint8_t i_tag = p_desc[0]; | uint8_t i_tag = p_desc[0]; | |||
uint8_t i_length = p_desc[1]; | uint8_t i_length = p_desc[1]; | |||
if ((i_length <= 254) && | if ((i_length <= 254) && | |||
(i_length + 2 <= p_end - p_desc)) | (i_length + 2 <= p_end - p_desc)) | |||
dvbpsi_SISAddDescriptor(p_sis, i_tag, i_length, p_desc + 2); | dvbpsi_sis_descriptor_add(p_sis, i_tag, i_length, p_des c + 2); | |||
p_desc += 2 + i_length; | p_desc += 2 + i_length; | |||
} | } | |||
if (p_sis->b_encrypted_packet == 1) | if (p_sis->b_encrypted_packet) | |||
{ | { | |||
/* FIXME: Currently ignored */ | /* FIXME: Currently ignored */ | |||
/* Calculate crc32 over decoded | /* Calculate crc32 over decoded | |||
* p_sis->i_splice_command_type till p_sis->i_ecrc, | * p_sis->i_splice_command_type till p_sis->i_ecrc, | |||
* the result should be exactly p_sis->i_ecrc and indicates | * the result should be exactly p_sis->i_ecrc and indicates | |||
* a successfull decryption. | * a successfull decryption. | |||
*/ | */ | |||
p_desc += 4; /* E CRC 32 */ | p_desc += 4; /* E CRC 32 */ | |||
} | } | |||
/* point to next section */ | /* point to next section */ | |||
p_byte = p_desc + 4 /* CRC 32 */; | p_byte = p_desc + 4 /* CRC 32 */; | |||
} | } | |||
p_section = p_section->p_next; | p_section = p_section->p_next; | |||
} | } | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_GenSISSections | * dvbpsi_sis_sections_generate | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Generate SIS sections based on the dvbpsi_sis_t structure. | * Generate SIS sections based on the dvbpsi_sis_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_psi_section_t *dvbpsi_GenSISSections(dvbpsi_sis_t* p_sis) | dvbpsi_psi_section_t *dvbpsi_sis_sections_generate(dvbpsi_t *p_dvbpsi, dvbp si_sis_t* p_sis) | |||
{ | { | |||
dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024); | dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024); | |||
p_current->i_table_id = 0xFC; | p_current->i_table_id = 0xFC; | |||
p_current->b_syntax_indicator = 0; | p_current->b_syntax_indicator = false; | |||
p_current->b_private_indicator = 0; | p_current->b_private_indicator = false; | |||
p_current->i_length = 3; /* header + CRC_32 */ | p_current->i_length = 3; /* header + CRC_32 */ | |||
/* FIXME: looks weird */ | /* FIXME: looks weird */ | |||
p_current->p_payload_end += 2; /* just after the header * / | p_current->p_payload_end += 2; /* just after the header * / | |||
p_current->p_payload_start = p_current->p_data + 3; | p_current->p_payload_start = p_current->p_data + 3; | |||
p_current->p_data[3] = p_sis->i_protocol_version; | p_current->p_data[3] = p_sis->i_protocol_version; | |||
p_current->p_data[4] = p_sis->b_encrypted_packet ? 0x80 : 0x0; | p_current->p_data[4] = p_sis->b_encrypted_packet ? 0x80 : 0x0; | |||
/* NOTE: cannot handle encrypted packet */ | /* NOTE: cannot handle encrypted packet */ | |||
assert(p_sis->b_encrypted_packet == 1); | assert(p_sis->b_encrypted_packet); | |||
p_current->p_data[4] |= ((p_sis->i_encryption_algorithm << 1) & 0x7E); | p_current->p_data[4] |= ((p_sis->i_encryption_algorithm << 1) & 0x7E); | |||
p_current->p_data[4] |= ((p_sis->i_pts_adjustment & 0x00800) >> 32); | p_current->p_data[4] |= ((p_sis->i_pts_adjustment & 0x00800) >> 32); | |||
p_current->p_data[5] = (p_sis->i_pts_adjustment >> 24); | p_current->p_data[5] = (p_sis->i_pts_adjustment >> 24); | |||
p_current->p_data[6] = (p_sis->i_pts_adjustment >> 16); | p_current->p_data[6] = (p_sis->i_pts_adjustment >> 16); | |||
p_current->p_data[7] = (p_sis->i_pts_adjustment >> 8); | p_current->p_data[7] = (p_sis->i_pts_adjustment >> 8); | |||
p_current->p_data[8] = p_sis->i_pts_adjustment; | p_current->p_data[8] = p_sis->i_pts_adjustment; | |||
p_current->p_data[9] = p_sis->cw_index; | p_current->p_data[9] = p_sis->cw_index; | |||
p_current->p_data[11] = 0x00; | p_current->p_data[11] = 0x00; | |||
skipping to change at line 476 | skipping to change at line 578 | |||
memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descri ptor->i_length); | memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descri ptor->i_length); | |||
/* Increase length by descriptor_length + 2 */ | /* Increase length by descriptor_length + 2 */ | |||
p_current->p_payload_end += p_descriptor->i_length + 2; | p_current->p_payload_end += p_descriptor->i_length + 2; | |||
p_current->i_length += p_descriptor->i_length + 2; | p_current->i_length += p_descriptor->i_length + 2; | |||
} | } | |||
/* Coding error if this condition is not met */ | /* Coding error if this condition is not met */ | |||
assert( i_desc_length == p_sis->i_descriptors_length); | assert( i_desc_length == p_sis->i_descriptors_length); | |||
/* Finalization */ | /* Finalization */ | |||
dvbpsi_BuildPSISection(p_current); | dvbpsi_BuildPSISection(p_dvbpsi, p_current); | |||
return p_current; | return p_current; | |||
} | } | |||
End of changes. 64 change blocks. | ||||
171 lines changed or deleted | 296 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/ |