pmt.c | pmt.c | |||
---|---|---|---|---|
/************************************************************************** *** | /************************************************************************** *** | |||
* pmt.c: PMT decoder/generator | * pmt.c: PMT decoder/generator | |||
*------------------------------------------------------------------------- --- | *------------------------------------------------------------------------- --- | |||
* Copyright (C) 2001-2010 VideoLAN | * Copyright (C) 2001-2011 VideoLAN | |||
* $Id$ | * $Id$ | |||
* | * | |||
* Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> | * Authors: 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 31 | skipping to change at line 32 | |||
* 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 "pmt.h" | #include "pmt.h" | |||
#include "pmt_private.h" | #include "pmt_private.h" | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_AttachPMT | * dvbpsi_pmt_attach | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Initialize a PMT decoder and return a handle on it. | * Initialize a PMT decoder and return a handle on it. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_handle dvbpsi_AttachPMT(uint16_t i_program_number, | bool dvbpsi_pmt_attach(dvbpsi_t *p_dvbpsi, uint16_t i_program_number, | |||
dvbpsi_pmt_callback pf_callback, | dvbpsi_pmt_callback pf_callback, void* p_cb_data) | |||
void* p_cb_data) | { | |||
{ | assert(p_dvbpsi); | |||
dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_ | assert(p_dvbpsi->p_decoder == NULL); | |||
t)); | ||||
dvbpsi_pmt_decoder_t* p_pmt_decoder; | ||||
if(h_dvbpsi == NULL) | ||||
return NULL; | ||||
p_pmt_decoder = (dvbpsi_pmt_decoder_t*)malloc(sizeof(dvbpsi_pmt_decoder_t | ||||
)); | ||||
if(p_pmt_decoder == NULL) | ||||
{ | ||||
free(h_dvbpsi); | ||||
return NULL; | ||||
} | ||||
/* PSI decoder configuration */ | ||||
h_dvbpsi->pf_callback = &dvbpsi_GatherPMTSections; | ||||
h_dvbpsi->p_private_decoder = p_pmt_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; | ||||
/* PMT decoder configuration */ | ||||
p_pmt_decoder->i_program_number = i_program_number; | ||||
p_pmt_decoder->pf_callback = pf_callback; | ||||
p_pmt_decoder->p_cb_data = p_cb_data; | ||||
/* PMT decoder initial state */ | ||||
p_pmt_decoder->b_current_valid = 0; | ||||
p_pmt_decoder->p_building_pmt = NULL; | ||||
for(unsigned int i = 0; i <= 255; i++) | ||||
p_pmt_decoder->ap_sections[i] = NULL; | ||||
return h_dvbpsi; | dvbpsi_pmt_decoder_t* p_pmt_decoder; | |||
p_pmt_decoder = (dvbpsi_pmt_decoder_t*) dvbpsi_decoder_new(&dvbpsi_pmt_ | ||||
sections_gather, | ||||
1024, true, sizeof(dvbpsi_pmt_d | ||||
ecoder_t)); | ||||
if (p_pmt_decoder == NULL) | ||||
return false; | ||||
p_dvbpsi->p_decoder = DVBPSI_DECODER(p_pmt_decoder); | ||||
/* PMT decoder configuration */ | ||||
p_pmt_decoder->i_program_number = i_program_number; | ||||
p_pmt_decoder->pf_pmt_callback = pf_callback; | ||||
p_pmt_decoder->p_cb_data = p_cb_data; | ||||
p_pmt_decoder->p_building_pmt = NULL; | ||||
return true; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_DetachPMT | * dvbpsi_pmt_detach | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Close a PMT decoder. The handle isn't valid any more. | * Close a PMT decoder. The handle isn't valid any more. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi) | void dvbpsi_pmt_detach(dvbpsi_t *p_dvbpsi) | |||
{ | { | |||
dvbpsi_pmt_decoder_t* p_pmt_decoder | assert(p_dvbpsi); | |||
= (dvbpsi_pmt_decoder_t*)h_dvbpsi->p_private_decode | assert(p_dvbpsi->p_decoder); | |||
r; | ||||
free(p_pmt_decoder->p_building_pmt); | ||||
for(unsigned int i = 0; i <= 255; i++) | dvbpsi_pmt_decoder_t* p_pmt_decoder; | |||
{ | p_pmt_decoder = (dvbpsi_pmt_decoder_t*)p_dvbpsi->p_decoder; | |||
if(p_pmt_decoder->ap_sections[i]) | if (p_pmt_decoder->p_building_pmt) | |||
free(p_pmt_decoder->ap_sections[i]); | dvbpsi_pmt_delete(p_pmt_decoder->p_building_pmt); | |||
} | p_pmt_decoder->p_building_pmt = 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_InitPMT | * dvbpsi_pmt_init | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Initialize a pre-allocated dvbpsi_pmt_t structure. | * Initialize a pre-allocated dvbpsi_pmt_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_InitPMT(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number, | void dvbpsi_pmt_init(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number, | |||
uint8_t i_version, int b_current_next, uint16_t i_pcr_p | uint8_t i_version, bool b_current_next, uint16_t i_pcr_ | |||
id) | pid) | |||
{ | { | |||
p_pmt->i_program_number = i_program_number; | assert(p_pmt); | |||
p_pmt->i_version = i_version; | ||||
p_pmt->b_current_next = b_current_next; | p_pmt->i_program_number = i_program_number; | |||
p_pmt->i_pcr_pid = i_pcr_pid; | p_pmt->i_version = i_version; | |||
p_pmt->p_first_descriptor = NULL; | p_pmt->b_current_next = b_current_next; | |||
p_pmt->p_first_es = NULL; | p_pmt->i_pcr_pid = i_pcr_pid; | |||
p_pmt->p_first_descriptor = NULL; | ||||
p_pmt->p_first_es = NULL; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_EmptyPMT | * dvbpsi_pmt_new | |||
************************************************************************** | ||||
*** | ||||
* Allocate and Initialize a new dvbpsi_pmt_t structure. | ||||
************************************************************************** | ||||
***/ | ||||
dvbpsi_pmt_t* dvbpsi_pmt_new(uint16_t i_program_number, uint8_t i_version, | ||||
bool b_current_next, uint16_t i_pcr_pid) | ||||
{ | ||||
dvbpsi_pmt_t *p_pmt = (dvbpsi_pmt_t*)malloc(sizeof(dvbpsi_pmt_t)); | ||||
if(p_pmt != NULL) | ||||
dvbpsi_pmt_init(p_pmt, i_program_number, i_version, | ||||
b_current_next, i_pcr_pid); | ||||
return p_pmt; | ||||
} | ||||
/************************************************************************** | ||||
*** | ||||
* dvbpsi_pmt_empty | ||||
************************************************************************** *** | ************************************************************************** *** | |||
* Clean a dvbpsi_pmt_t structure. | * Clean a dvbpsi_pmt_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_EmptyPMT(dvbpsi_pmt_t* p_pmt) | void dvbpsi_pmt_empty(dvbpsi_pmt_t* p_pmt) | |||
{ | { | |||
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; | dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; | |||
dvbpsi_DeleteDescriptors(p_pmt->p_first_descriptor); | dvbpsi_DeleteDescriptors(p_pmt->p_first_descriptor); | |||
while(p_es != NULL) | while(p_es != NULL) | |||
{ | { | |||
dvbpsi_pmt_es_t* p_tmp = p_es->p_next; | dvbpsi_pmt_es_t* p_tmp = p_es->p_next; | |||
dvbpsi_DeleteDescriptors(p_es->p_first_descriptor); | dvbpsi_DeleteDescriptors(p_es->p_first_descriptor); | |||
free(p_es); | free(p_es); | |||
p_es = p_tmp; | p_es = p_tmp; | |||
} | } | |||
p_pmt->p_first_descriptor = NULL; | p_pmt->p_first_descriptor = NULL; | |||
p_pmt->p_first_es = NULL; | p_pmt->p_first_es = NULL; | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_PMTAddDescriptor | * dvbpsi_pmt_delete | |||
************************************************************************** | ||||
*** | ||||
* Clean a dvbpsi_pmt_t structure. | ||||
************************************************************************** | ||||
***/ | ||||
void dvbpsi_pmt_delete(dvbpsi_pmt_t* p_pmt) | ||||
{ | ||||
if (p_pmt) | ||||
dvbpsi_pmt_empty(p_pmt); | ||||
free(p_pmt); | ||||
} | ||||
/************************************************************************** | ||||
*** | ||||
* dvbpsi_pmt_descriptor_add | ||||
************************************************************************** *** | ************************************************************************** *** | |||
* Add a descriptor in the PMT. | * Add a descriptor in the PMT. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt, | dvbpsi_descriptor_t* dvbpsi_pmt_descriptor_add(dvbpsi_pmt_t* p_pmt, | |||
uint8_t i_tag, uint8_t i_lengt | uint8_t i_tag, uint8_t i_len | |||
h, | gth, | |||
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); | p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); | |||
if (p_descriptor == NULL) | ||||
if(p_descriptor) | return NULL; | |||
{ | ||||
if(p_pmt->p_first_descriptor == NULL) | p_pmt->p_first_descriptor = dvbpsi_AddDescriptor(p_pmt->p_first_descrip | |||
{ | tor, | |||
p_pmt->p_first_descriptor = p_descriptor; | p_descriptor); | |||
} | assert(p_pmt->p_first_descriptor); | |||
else | if (p_pmt->p_first_descriptor == NULL) | |||
{ | return NULL; | |||
dvbpsi_descriptor_t* p_last_descriptor = p_pmt->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; | return p_descriptor; | |||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_PMTAddES | * dvbpsi_pmt_es_add | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Add an ES in the PMT. | * Add an ES in the PMT. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_pmt_es_t* dvbpsi_PMTAddES(dvbpsi_pmt_t* p_pmt, | dvbpsi_pmt_es_t* dvbpsi_pmt_es_add(dvbpsi_pmt_t* p_pmt, | |||
uint8_t i_type, uint16_t i_pid) | uint8_t i_type, uint16_t i_pid) | |||
{ | { | |||
dvbpsi_pmt_es_t* p_es = (dvbpsi_pmt_es_t*)malloc(sizeof(dvbpsi_pmt_es_t)) | dvbpsi_pmt_es_t* p_es = (dvbpsi_pmt_es_t*)malloc(sizeof(dvbpsi_pmt_es_t | |||
; | )); | |||
if (p_es == NULL) | ||||
return NULL; | ||||
if(p_es) | ||||
{ | ||||
p_es->i_type = i_type; | p_es->i_type = i_type; | |||
p_es->i_pid = i_pid; | p_es->i_pid = i_pid; | |||
p_es->p_first_descriptor = NULL; | p_es->p_first_descriptor = NULL; | |||
p_es->p_next = NULL; | p_es->p_next = NULL; | |||
if(p_pmt->p_first_es == NULL) | if (p_pmt->p_first_es == NULL) | |||
{ | p_pmt->p_first_es = p_es; | |||
p_pmt->p_first_es = p_es; | ||||
} | ||||
else | else | |||
{ | { | |||
dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es; | dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es; | |||
while(p_last_es->p_next != NULL) | while (p_last_es->p_next != NULL) | |||
p_last_es = p_last_es->p_next; | p_last_es = p_last_es->p_next; | |||
p_last_es->p_next = p_es; | p_last_es->p_next = p_es; | |||
} | } | |||
} | return p_es; | |||
return p_es; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_PMTESAddDescriptor | * dvbpsi_pmt_es_descriptor_add | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Add a descriptor in the PMT ES. | * Add a descriptor in the PMT ES. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_descriptor_t* dvbpsi_PMTESAddDescriptor(dvbpsi_pmt_es_t* p_es, | dvbpsi_descriptor_t* dvbpsi_pmt_es_descriptor_add(dvbpsi_pmt_es_t* p_es, | |||
uint8_t i_tag, uint8_t i_len gth, | uint8_t i_tag, uint8_t i_len gth, | |||
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); | p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); | |||
if (p_descriptor == NULL) | ||||
return NULL; | ||||
if(p_descriptor) | if (p_es->p_first_descriptor == NULL) | |||
{ | p_es->p_first_descriptor = p_descriptor; | |||
if(p_es->p_first_descriptor == NULL) | else | |||
{ | { | |||
p_es->p_first_descriptor = p_descriptor; | dvbpsi_descriptor_t* p_last_descriptor = p_es->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; | ||||
} | } | |||
else | return p_descriptor; | |||
} | ||||
/* */ | ||||
static void dvbpsi_ReInitPMT(dvbpsi_pmt_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) | ||||
{ | ||||
/* Free structures */ | ||||
if (p_decoder->p_building_pmt) | ||||
dvbpsi_pmt_delete(p_decoder->p_building_pmt); | ||||
} | ||||
p_decoder->p_building_pmt = NULL; | ||||
} | ||||
static bool dvbpsi_CheckPMT(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t *p_sec | ||||
tion) | ||||
{ | ||||
bool b_reinit = false; | ||||
assert(p_dvbpsi->p_decoder); | ||||
dvbpsi_pmt_decoder_t* p_pmt_decoder; | ||||
p_pmt_decoder = (dvbpsi_pmt_decoder_t *)p_dvbpsi->p_decoder; | ||||
if (p_pmt_decoder->p_building_pmt->i_version != p_section->i_version) | ||||
{ | ||||
/* version_number */ | ||||
dvbpsi_error(p_dvbpsi, "PMT decoder", | ||||
"'version_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = true; | ||||
} | ||||
else if (p_pmt_decoder->i_last_section_number != p_section->i_last_numb | ||||
er) | ||||
{ | { | |||
dvbpsi_descriptor_t* p_last_descriptor = p_es->p_first_descriptor; | /* last_section_number */ | |||
while(p_last_descriptor->p_next != NULL) | dvbpsi_error(p_dvbpsi, "PMT decoder", | |||
p_last_descriptor = p_last_descriptor->p_next; | "'last_section_number' differs" | |||
p_last_descriptor->p_next = p_descriptor; | " whereas no discontinuity has occured"); | |||
b_reinit = true; | ||||
} | } | |||
} | ||||
return p_descriptor; | return b_reinit; | |||
} | ||||
static bool dvbpsi_AddSectionPMT(dvbpsi_t *p_dvbpsi, dvbpsi_pmt_decoder_t * | ||||
p_pmt_decoder, | ||||
dvbpsi_psi_section_t* p_section) | ||||
{ | ||||
assert(p_dvbpsi); | ||||
assert(p_pmt_decoder); | ||||
assert(p_section); | ||||
/* Initialize the structures if it's the first section received */ | ||||
if (p_pmt_decoder->p_building_pmt == NULL) | ||||
{ | ||||
p_pmt_decoder->p_building_pmt = dvbpsi_pmt_new(p_pmt_decoder->i_pro | ||||
gram_number, | ||||
p_section->i_version, p_section->b_current_ne | ||||
xt, | ||||
((uint16_t)(p_section->p_payload_start[0] & 0 | ||||
x1f) << 8) | ||||
| p_section->p_payload_start[1]); | ||||
if (p_pmt_decoder->p_building_pmt == NULL) | ||||
return false; | ||||
p_pmt_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_pmt_decoder), p_sec | ||||
tion)) | ||||
dvbpsi_debug(p_dvbpsi, "PMT decoder", "overwrite section number %d" | ||||
, | ||||
p_section->i_number); | ||||
return true; | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_GatherPMTSections | * dvbpsi_GatherPMTSections | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Callback for the PSI decoder. | * Callback for the PSI decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, | void dvbpsi_pmt_sections_gather(dvbpsi_t *p_dvbpsi, dvbpsi_psi_section_t* p | |||
dvbpsi_psi_section_t* p_section) | _section) | |||
{ | { | |||
dvbpsi_pmt_decoder_t* p_pmt_decoder | assert(p_dvbpsi); | |||
= (dvbpsi_pmt_decoder_t*)p_decoder->p_private_decod | assert(p_dvbpsi->p_decoder); | |||
er; | ||||
int b_append = 1; | if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0x02, "PMT decoder")) | |||
int b_reinit = 0; | { | |||
dvbpsi_DeletePSISections(p_section); | ||||
DVBPSI_DEBUG_ARG("PMT 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_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t*)p_dvbpsi-> | |||
p_section->b_current_next); | p_decoder; | |||
assert(p_pmt_decoder); | ||||
if(p_section->i_table_id != 0x02) | ||||
{ | /* We have a valid PMT section */ | |||
/* Invalid table_id value */ | if (p_pmt_decoder->i_program_number != p_section->i_extension) | |||
DVBPSI_ERROR_ARG("PMT decoder", | { | |||
"invalid section (table_id == 0x%02x)", | /* Invalid program_number */ | |||
p_section->i_table_id); | dvbpsi_error(p_dvbpsi, "PMT decoder", "'program_number' don't match | |||
b_append = 0; | "); | |||
} | dvbpsi_DeletePSISections(p_section); | |||
return; | ||||
if(b_append && !p_section->b_syntax_indicator) | } | |||
{ | ||||
/* Invalid section_syntax_indicator */ | ||||
DVBPSI_ERROR("PMT decoder", | ||||
"invalid section (section_syntax_indicator == 0)"); | ||||
b_append = 0; | ||||
} | ||||
/* Now if b_append is true then we have a valid PMT section */ | ||||
if(b_append && (p_pmt_decoder->i_program_number != p_section->i_extension | ||||
)) | ||||
{ | ||||
/* Invalid program_number */ | ||||
#if 0 | ||||
DVBPSI_ERROR("PMT decoder", \ | ||||
"'program_number' don't match"); | ||||
#endif | ||||
b_append = 0; | ||||
} | ||||
if(b_append) | ||||
{ | ||||
/* TS discontinuity check */ | /* TS discontinuity check */ | |||
if(p_decoder->b_discontinuity) | if (p_pmt_decoder->b_discontinuity) | |||
{ | { | |||
b_reinit = 1; | dvbpsi_ReInitPMT(p_pmt_decoder, true); | |||
p_decoder->b_discontinuity = 0; | p_pmt_decoder->b_discontinuity = false; | |||
} | } | |||
else | else | |||
{ | { | |||
/* Perform some few sanity checks */ | /* Perform some few sanity checks */ | |||
if(p_pmt_decoder->p_building_pmt) | if (p_pmt_decoder->p_building_pmt) | |||
{ | ||||
if(p_pmt_decoder->p_building_pmt->i_version != p_section->i_version | ||||
) | ||||
{ | { | |||
/* version_number */ | if (dvbpsi_CheckPMT(p_dvbpsi, p_section)) | |||
DVBPSI_ERROR("PMT decoder", | dvbpsi_ReInitPMT(p_pmt_decoder, true); | |||
"'version_number' differs" | ||||
" whereas no discontinuity has occured"); | ||||
b_reinit = 1; | ||||
} | } | |||
else if(p_pmt_decoder->i_last_section_number | else | |||
!= p_section->i_last_number | ||||
) | ||||
{ | { | |||
/* last_section_number */ | if( (p_pmt_decoder->b_current_valid) | |||
DVBPSI_ERROR("PMT decoder", | && (p_pmt_decoder->current_pmt.i_version == p_section->i_ve | |||
"'last_section_number' differs" | rsion) | |||
" whereas no discontinuity has occured"); | && (p_pmt_decoder->current_pmt.b_current_next == | |||
b_reinit = 1; | p_section->b_current_next)) | |||
{ | ||||
/* Don't decode since this version is already decoded */ | ||||
dvbpsi_debug(p_dvbpsi, "PMT decoder", | ||||
"ignoring already decoded section %d", | ||||
p_section->i_number); | ||||
dvbpsi_DeletePSISections(p_section); | ||||
return; | ||||
} | ||||
} | } | |||
} | ||||
else | ||||
{ | ||||
if( (p_pmt_decoder->b_current_valid) | ||||
&& (p_pmt_decoder->current_pmt.i_version == p_section->i_versio | ||||
n) | ||||
&& (p_pmt_decoder->current_pmt.b_current_next == | ||||
p_section->b_current_next)) | ||||
{ | ||||
/* Don't decode since this version is already decoded */ | ||||
b_append = 0; | ||||
} | ||||
} | ||||
} | } | |||
} | ||||
/* Reinit the decoder if wanted */ | ||||
if(b_reinit) | ||||
{ | ||||
/* Force redecoding */ | ||||
p_pmt_decoder->b_current_valid = 0; | ||||
/* Free structures */ | ||||
if(p_pmt_decoder->p_building_pmt) | ||||
{ | ||||
free(p_pmt_decoder->p_building_pmt); | ||||
p_pmt_decoder->p_building_pmt = NULL; | ||||
} | ||||
/* Clear the section array */ | ||||
for(unsigned int i = 0; i <= 255; i++) | ||||
{ | ||||
if(p_pmt_decoder->ap_sections[i] != NULL) | ||||
{ | ||||
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[i]); | ||||
p_pmt_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 */ | /* Add section to PMT */ | |||
if(!p_pmt_decoder->p_building_pmt) | if (!dvbpsi_AddSectionPMT(p_dvbpsi, p_pmt_decoder, p_section)) | |||
{ | { | |||
p_pmt_decoder->p_building_pmt = | dvbpsi_error(p_dvbpsi, "PMT decoder", "failed decoding section %d", | |||
(dvbpsi_pmt_t*)malloc(sizeof(dvbpsi_pmt_t)) | p_section->i_number); | |||
; | dvbpsi_DeletePSISections(p_section); | |||
dvbpsi_InitPMT(p_pmt_decoder->p_building_pmt, | return; | |||
p_pmt_decoder->i_program_number, | } | |||
p_section->i_version, | ||||
p_section->b_current_next, | if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_pmt_decoder) | |||
((uint16_t)(p_section->p_payload_start[0] & 0x1f) << | )) | |||
8) | { | |||
| p_section->p_payload_start[1]); | assert(p_pmt_decoder->pf_pmt_callback); | |||
p_pmt_decoder->i_last_section_number = p_section->i_last_number; | ||||
} | /* Save the current information */ | |||
p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt; | ||||
/* Fill the section array */ | p_pmt_decoder->b_current_valid = true; | |||
if(p_pmt_decoder->ap_sections[p_section->i_number] != NULL) | /* Decode the sections */ | |||
{ | dvbpsi_pmt_sections_decode(p_pmt_decoder->p_building_pmt, | |||
DVBPSI_DEBUG_ARG("PMT decoder", "overwrite section number %d", | p_pmt_decoder->p_sections); | |||
p_section->i_number); | /* Delete the sections */ | |||
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[p_section->i_numb | dvbpsi_DeletePSISections(p_pmt_decoder->p_sections); | |||
er]); | p_pmt_decoder->p_sections = NULL; | |||
} | /* signal the new PMT */ | |||
p_pmt_decoder->ap_sections[p_section->i_number] = p_section; | p_pmt_decoder->pf_pmt_callback(p_pmt_decoder->p_cb_data, | |||
p_pmt_decoder->p_building_pmt); | ||||
/* Check if we have all the sections */ | /* Reinitialize the structures */ | |||
b_complete = 0; | dvbpsi_ReInitPMT(p_pmt_decoder, false); | |||
for(unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i++) | } | |||
{ | ||||
if(!p_pmt_decoder->ap_sections[i]) | ||||
break; | ||||
if(i == p_pmt_decoder->i_last_section_number) | ||||
b_complete = 1; | ||||
} | ||||
if(b_complete) | ||||
{ | ||||
/* Save the current information */ | ||||
p_pmt_decoder->current_pmt = *p_pmt_decoder->p_building_pmt; | ||||
p_pmt_decoder->b_current_valid = 1; | ||||
/* Chain the sections */ | ||||
if(p_pmt_decoder->i_last_section_number) | ||||
{ | ||||
for(unsigned int i = 0; (int)i <= p_pmt_decoder->i_last_section_num | ||||
ber - 1; i++) | ||||
p_pmt_decoder->ap_sections[i]->p_next = | ||||
p_pmt_decoder->ap_sections[i + 1]; | ||||
} | ||||
/* Decode the sections */ | ||||
dvbpsi_DecodePMTSections(p_pmt_decoder->p_building_pmt, | ||||
p_pmt_decoder->ap_sections[0]); | ||||
/* Delete the sections */ | ||||
dvbpsi_DeletePSISections(p_pmt_decoder->ap_sections[0]); | ||||
/* signal the new PMT */ | ||||
p_pmt_decoder->pf_callback(p_pmt_decoder->p_cb_data, | ||||
p_pmt_decoder->p_building_pmt); | ||||
/* Reinitialize the structures */ | ||||
p_pmt_decoder->p_building_pmt = NULL; | ||||
for(unsigned int i = 0; i <= p_pmt_decoder->i_last_section_number; i+ | ||||
+) | ||||
p_pmt_decoder->ap_sections[i] = NULL; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
dvbpsi_DeletePSISections(p_section); | ||||
} | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_DecodePMTSections | * dvbpsi_pmt_sections_decode | |||
************************************************************************** *** | ************************************************************************** *** | |||
* PMT decoder. | * PMT decoder. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
void dvbpsi_DecodePMTSections(dvbpsi_pmt_t* p_pmt, | void dvbpsi_pmt_sections_decode(dvbpsi_pmt_t* p_pmt, | |||
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) | |||
{ | { | |||
/* - PMT descriptors */ | /* - PMT descriptors */ | |||
p_byte = p_section->p_payload_start + 4; | p_byte = p_section->p_payload_start + 4; | |||
p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[2] & 0x0f) | p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[2] & 0x | |||
<< 8) | 0f) << 8) | |||
| p_section->p_payload_start[3]); | | p_section->p_payload_start[3]); | |||
while(p_byte + 2 <= p_end) | while (p_byte + 2 <= p_end) | |||
{ | { | |||
uint8_t i_tag = p_byte[0]; | uint8_t i_tag = p_byte[0]; | |||
uint8_t i_length = p_byte[1]; | uint8_t i_length = p_byte[1]; | |||
if(i_length + 2 <= p_end - p_byte) | if (i_length + 2 <= p_end - p_byte) | |||
dvbpsi_PMTAddDescriptor(p_pmt, i_tag, i_length, p_byte + 2); | dvbpsi_pmt_descriptor_add(p_pmt, i_tag, i_length, p_byte + | |||
p_byte += 2 + i_length; | 2); | |||
} | p_byte += 2 + i_length; | |||
} | ||||
/* - ESs */ | ||||
for(p_byte = p_end; p_byte + 5 <= p_section->p_payload_end;) | ||||
{ | ||||
uint8_t i_type = p_byte[0]; | ||||
uint16_t i_pid = ((uint16_t)(p_byte[1] & 0x1f) << 8) | p_byte[2]; | ||||
uint16_t i_es_length = ((uint16_t)(p_byte[3] & 0x0f) << 8) | p_byte[4 | ||||
]; | ||||
dvbpsi_pmt_es_t* p_es = dvbpsi_PMTAddES(p_pmt, i_type, i_pid); | ||||
/* - ES descriptors */ | ||||
p_byte += 5; | ||||
p_end = p_byte + i_es_length; | ||||
if( p_end > p_section->p_payload_end ) | ||||
{ | ||||
p_end = p_section->p_payload_end; | ||||
} | ||||
while(p_byte + 2 <= p_end) | ||||
{ | ||||
uint8_t i_tag = p_byte[0]; | ||||
uint8_t i_length = p_byte[1]; | ||||
if(i_length + 2 <= p_end - p_byte) | ||||
dvbpsi_PMTESAddDescriptor(p_es, i_tag, i_length, p_byte + 2); | ||||
p_byte += 2 + i_length; | ||||
} | ||||
} | ||||
p_section = p_section->p_next; | /* - ESs */ | |||
} | for (p_byte = p_end; p_byte + 5 <= p_section->p_payload_end;) | |||
{ | ||||
uint8_t i_type = p_byte[0]; | ||||
uint16_t i_pid = ((uint16_t)(p_byte[1] & 0x1f) << 8) | p_byte[2 | ||||
]; | ||||
uint16_t i_es_length = ((uint16_t)(p_byte[3] & 0x0f) << 8) | p_ | ||||
byte[4]; | ||||
dvbpsi_pmt_es_t* p_es = dvbpsi_pmt_es_add(p_pmt, i_type, i_pid) | ||||
; | ||||
/* - ES descriptors */ | ||||
p_byte += 5; | ||||
p_end = p_byte + i_es_length; | ||||
if (p_end > p_section->p_payload_end) | ||||
{ | ||||
p_end = p_section->p_payload_end; | ||||
} | ||||
while (p_byte + 2 <= p_end) | ||||
{ | ||||
uint8_t i_tag = p_byte[0]; | ||||
uint8_t i_length = p_byte[1]; | ||||
if (i_length + 2 <= p_end - p_byte) | ||||
dvbpsi_pmt_es_descriptor_add(p_es, i_tag, i_length, p_b | ||||
yte + 2); | ||||
p_byte += 2 + i_length; | ||||
} | ||||
} | ||||
p_section = p_section->p_next; | ||||
} | ||||
} | } | |||
/************************************************************************** *** | /************************************************************************** *** | |||
* dvbpsi_GenPMTSections | * dvbpsi_pmt_sections_generate | |||
************************************************************************** *** | ************************************************************************** *** | |||
* Generate PMT sections based on the dvbpsi_pmt_t structure. | * Generate PMT sections based on the dvbpsi_pmt_t structure. | |||
************************************************************************** ***/ | ************************************************************************** ***/ | |||
dvbpsi_psi_section_t* dvbpsi_GenPMTSections(dvbpsi_pmt_t* p_pmt) | dvbpsi_psi_section_t* dvbpsi_pmt_sections_generate(dvbpsi_t *p_dvbpsi, dvbp si_pmt_t* p_pmt) | |||
{ | { | |||
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_pmt->p_first_descriptor; | dvbpsi_descriptor_t* p_descriptor = p_pmt->p_first_descriptor; | |||
dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; | dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; | |||
uint16_t i_info_length; | uint16_t i_info_length; | |||
p_current->i_table_id = 0x02; | p_current->i_table_id = 0x02; | |||
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 = 13; /* header + CRC_32 */ | p_current->i_length = 13; /* header + CRC_32 */ | |||
p_current->i_extension = p_pmt->i_program_number; | p_current->i_extension = p_pmt->i_program_number; | |||
p_current->i_version = p_pmt->i_version; | p_current->i_version = p_pmt->i_version; | |||
p_current->b_current_next = p_pmt->b_current_next; | p_current->b_current_next = p_pmt->b_current_next; | |||
p_current->i_number = 0; | p_current->i_number = 0; | |||
p_current->p_payload_end += 12; /* just after the header */ | p_current->p_payload_end += 12; /* just after the header | |||
p_current->p_payload_start = p_current->p_data + 8; | */ | |||
p_current->p_payload_start = p_current->p_data + 8; | ||||
/* PCR_PID */ | ||||
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; | /* PCR_PID */ | |||
p_current->p_data[9] = p_pmt->i_pcr_pid; | p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; | |||
p_current->p_data[9] = p_pmt->i_pcr_pid; | ||||
/* PMT descriptors */ | ||||
while(p_descriptor != NULL) | /* PMT descriptors */ | |||
{ | while (p_descriptor != NULL) | |||
/* New section if needed */ | { | |||
/* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length * | /* New section if needed */ | |||
/ | /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_leng | |||
if( (p_current->p_payload_end - p_current->p_data) | th */ | |||
+ p_descriptor->i_length > 1018) | if ((p_current->p_payload_end - p_current->p_data) | |||
{ | + p_descriptor->i_length > 1018) | |||
/* program_info_length */ | { | |||
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12; | /* program_info_length */ | |||
p_current->p_data[10] = (i_info_length >> 8) | 0xf0; | i_info_length = (p_current->p_payload_end - p_current->p_data) | |||
p_current->p_data[11] = i_info_length; | - 12; | |||
p_current->p_data[10] = (i_info_length >> 8) | 0xf0; | ||||
p_prev = p_current; | p_current->p_data[11] = i_info_length; | |||
p_current = dvbpsi_NewPSISection(1024); | ||||
p_prev->p_next = p_current; | p_prev = p_current; | |||
p_current = dvbpsi_NewPSISection(1024); | ||||
p_current->i_table_id = 0x02; | p_prev->p_next = p_current; | |||
p_current->b_syntax_indicator = 1; | ||||
p_current->b_private_indicator = 0; | p_current->i_table_id = 0x02; | |||
p_current->i_length = 13; /* header + CRC_32 */ | p_current->b_syntax_indicator = true; | |||
p_current->i_extension = p_pmt->i_program_number; | p_current->b_private_indicator = false; | |||
p_current->i_version = p_pmt->i_version; | p_current->i_length = 13; /* header + CRC_32 */ | |||
p_current->b_current_next = p_pmt->b_current_next; | p_current->i_extension = p_pmt->i_program_number; | |||
p_current->i_number = p_prev->i_number + 1; | p_current->i_version = p_pmt->i_version; | |||
p_current->p_payload_end += 12; /* just after the header */ | p_current->b_current_next = p_pmt->b_current_next; | |||
p_current->p_payload_start = p_current->p_data + 8; | p_current->i_number = p_prev->i_number + 1; | |||
p_current->p_payload_end += 12; /* just after the hea | ||||
/* PCR_PID */ | der */ | |||
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; | p_current->p_payload_start = p_current->p_data + 8; | |||
p_current->p_data[9] = p_pmt->i_pcr_pid; | ||||
} | /* PCR_PID */ | |||
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; | ||||
/* p_payload_end is where the descriptor begins */ | p_current->p_data[9] = p_pmt->i_pcr_pid; | |||
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_payload_end is where the descriptor begins */ | |||
p_descriptor->p_data, | p_current->p_payload_end[0] = p_descriptor->i_tag; | |||
p_descriptor->i_length); | p_current->p_payload_end[1] = p_descriptor->i_length; | |||
memcpy(p_current->p_payload_end + 2, | ||||
/* Increase length by descriptor_length + 2 */ | p_descriptor->p_data, | |||
p_current->p_payload_end += p_descriptor->i_length + 2; | p_descriptor->i_length); | |||
p_current->i_length += p_descriptor->i_length + 2; | ||||
/* Increase length by descriptor_length + 2 */ | ||||
p_descriptor = p_descriptor->p_next; | p_current->p_payload_end += p_descriptor->i_length + 2; | |||
} | p_current->i_length += p_descriptor->i_length + 2; | |||
/* program_info_length */ | p_descriptor = p_descriptor->p_next; | |||
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12; | } | |||
p_current->p_data[10] = (i_info_length >> 8) | 0xf0; | ||||
p_current->p_data[11] = i_info_length; | /* program_info_length */ | |||
i_info_length = (p_current->p_payload_end - p_current->p_data) - 12; | ||||
/* PMT ESs */ | p_current->p_data[10] = (i_info_length >> 8) | 0xf0; | |||
while(p_es != NULL) | p_current->p_data[11] = i_info_length; | |||
{ | ||||
uint8_t* p_es_start = p_current->p_payload_end; | /* PMT ESs */ | |||
uint16_t i_es_length = 5; | while (p_es != NULL) | |||
{ | ||||
/* Can the current section carry all the descriptors ? */ | uint8_t* p_es_start = p_current->p_payload_end; | |||
p_descriptor = p_es->p_first_descriptor; | uint16_t i_es_length = 5; | |||
while( (p_descriptor != NULL) | ||||
&& ((p_es_start - p_current->p_data) + i_es_length <= 1020)) | /* Can the current section carry all the descriptors ? */ | |||
{ | p_descriptor = p_es->p_first_descriptor; | |||
i_es_length += p_descriptor->i_length + 2; | while( (p_descriptor != NULL) | |||
p_descriptor = p_descriptor->p_next; | && ((p_es_start - p_current->p_data) + i_es_length <= 1020)) | |||
} | { | |||
i_es_length += p_descriptor->i_length + 2; | ||||
/* If _no_ and the current section isn't empty and an empty section | p_descriptor = p_descriptor->p_next; | |||
may carry one more descriptor | } | |||
then create a new section */ | ||||
if( (p_descriptor != NULL) | /* If _no_ and the current section isn't empty and an empty section | |||
&& (p_es_start - p_current->p_data != 12) | may carry one more descriptor | |||
&& (i_es_length <= 1008)) | then create a new section */ | |||
{ | if( (p_descriptor != NULL) | |||
/* will put more descriptors in an empty section */ | && (p_es_start - p_current->p_data != 12) | |||
DVBPSI_DEBUG("PMT generator", | && (i_es_length <= 1008)) | |||
"create a new section to carry more ES descriptors"); | { | |||
p_prev = p_current; | /* will put more descriptors in an empty section */ | |||
p_current = dvbpsi_NewPSISection(1024); | dvbpsi_debug(p_dvbpsi, "PMT generator", | |||
p_prev->p_next = p_current; | "create a new section to carry more ES descriptors | |||
"); | ||||
p_current->i_table_id = 0x02; | ||||
p_current->b_syntax_indicator = 1; | p_prev = p_current; | |||
p_current->b_private_indicator = 0; | p_current = dvbpsi_NewPSISection(1024); | |||
p_current->i_length = 13; /* header + CRC_32 */ | p_prev->p_next = p_current; | |||
p_current->i_extension = p_pmt->i_program_number; | ||||
p_current->i_version = p_pmt->i_version; | p_current->i_table_id = 0x02; | |||
p_current->b_current_next = p_pmt->b_current_next; | p_current->b_syntax_indicator = true; | |||
p_current->i_number = p_prev->i_number + 1; | p_current->b_private_indicator = false; | |||
p_current->p_payload_end += 12; /* just after the header */ | p_current->i_length = 13; /* header + CRC_32 */ | |||
p_current->p_payload_start = p_current->p_data + 8; | p_current->i_extension = p_pmt->i_program_number; | |||
p_current->i_version = p_pmt->i_version; | ||||
/* PCR_PID */ | p_current->b_current_next = p_pmt->b_current_next; | |||
p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; | p_current->i_number = p_prev->i_number + 1; | |||
p_current->p_data[9] = p_pmt->i_pcr_pid; | p_current->p_payload_end += 12; /* just after the hea | |||
der */ | ||||
/* program_info_length */ | p_current->p_payload_start = p_current->p_data + 8; | |||
i_info_length = 0; | ||||
p_current->p_data[10] = 0xf0; | /* PCR_PID */ | |||
p_current->p_data[11] = 0x00; | p_current->p_data[8] = (p_pmt->i_pcr_pid >> 8) | 0xe0; | |||
p_current->p_data[9] = p_pmt->i_pcr_pid; | ||||
p_es_start = p_current->p_payload_end; | ||||
} | /* program_info_length */ | |||
i_info_length = 0; | ||||
/* p_es_start is where the ES begins */ | p_current->p_data[10] = 0xf0; | |||
p_es_start[0] = p_es->i_type; | p_current->p_data[11] = 0x00; | |||
p_es_start[1] = (p_es->i_pid >> 8) | 0xe0; | ||||
p_es_start[2] = p_es->i_pid; | p_es_start = p_current->p_payload_end; | |||
} | ||||
/* Increase the length by 5 */ | ||||
p_current->p_payload_end += 5; | /* p_es_start is where the ES begins */ | |||
p_current->i_length += 5; | p_es_start[0] = p_es->i_type; | |||
p_es_start[1] = (p_es->i_pid >> 8) | 0xe0; | ||||
/* ES descriptors */ | p_es_start[2] = p_es->i_pid; | |||
p_descriptor = p_es->p_first_descriptor; | ||||
while( (p_descriptor != NULL) | /* Increase the length by 5 */ | |||
&& ( (p_current->p_payload_end - p_current->p_data) | p_current->p_payload_end += 5; | |||
+ p_descriptor->i_length <= 1018)) | p_current->i_length += 5; | |||
{ | ||||
/* p_payload_end is where the descriptor begins */ | /* ES descriptors */ | |||
p_current->p_payload_end[0] = p_descriptor->i_tag; | p_descriptor = p_es->p_first_descriptor; | |||
p_current->p_payload_end[1] = p_descriptor->i_length; | while( (p_descriptor != NULL) | |||
memcpy(p_current->p_payload_end + 2, | && ( (p_current->p_payload_end - p_current->p_data) | |||
p_descriptor->p_data, | + p_descriptor->i_length <= 1018)) | |||
p_descriptor->i_length); | { | |||
/* p_payload_end is where the descriptor begins */ | ||||
/* Increase length by descriptor_length + 2 */ | p_current->p_payload_end[0] = p_descriptor->i_tag; | |||
p_current->p_payload_end += p_descriptor->i_length + 2; | p_current->p_payload_end[1] = p_descriptor->i_length; | |||
p_current->i_length += p_descriptor->i_length + 2; | memcpy(p_current->p_payload_end + 2, | |||
p_descriptor->p_data, | ||||
p_descriptor = p_descriptor->p_next; | p_descriptor->i_length); | |||
} | ||||
/* Increase length by descriptor_length + 2 */ | ||||
if(p_descriptor != NULL) | p_current->p_payload_end += p_descriptor->i_length + 2; | |||
DVBPSI_ERROR("PMT generator", "unable to carry all the ES descriptors | p_current->i_length += p_descriptor->i_length + 2; | |||
"); | ||||
p_descriptor = p_descriptor->p_next; | ||||
/* ES_info_length */ | } | |||
i_es_length = p_current->p_payload_end - p_es_start - 5; | ||||
p_es_start[3] = (i_es_length >> 8) | 0xf0; | if (p_descriptor != NULL) | |||
p_es_start[4] = i_es_length; | dvbpsi_error(p_dvbpsi, "PMT generator", "unable to carry all th | |||
e ES descriptors"); | ||||
p_es = p_es->p_next; | ||||
} | /* ES_info_length */ | |||
i_es_length = p_current->p_payload_end - p_es_start - 5; | ||||
/* Finalization */ | p_es_start[3] = (i_es_length >> 8) | 0xf0; | |||
p_prev = p_result; | p_es_start[4] = i_es_length; | |||
while(p_prev != NULL) | ||||
{ | p_es = p_es->p_next; | |||
p_prev->i_last_number = p_current->i_number; | } | |||
dvbpsi_BuildPSISection(p_prev); | ||||
p_prev = p_prev->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; | return p_result; | |||
} | } | |||
End of changes. 62 change blocks. | ||||
537 lines changed or deleted | 530 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/ |