📄 pmt.c
字号:
/***************************************************************************** * pmt.c: PMT decoder/generator *---------------------------------------------------------------------------- * (c)2001-2002 VideoLAN * $Id: pmt.c 108 2005-04-19 12:33:21Z gbazin $ * * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * *---------------------------------------------------------------------------- * *****************************************************************************/#include "config.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#if defined(HAVE_INTTYPES_H)#include <inttypes.h>#elif defined(HAVE_STDINT_H)#include <stdint.h>#endif#include "dvbpsi.h"#include "../dvbpsi_private.h"#include "psi.h"#include "descriptor.h"#include "pmt.h"#include "pmt_private.h"#include "objects.h"/***************************************************************************** * dvbpsi_AttachPMT ***************************************************************************** * Initialize a PMT decoder and return a handle on it. *****************************************************************************/dvbpsi_handle dvbpsi_AttachPMT(uint16_t i_program_number, dvbpsi_pmt_callback pf_callback, void* p_cb_data){ dvbpsi_handle h_dvbpsi = (dvbpsi_decoder_t*)malloc(sizeof(dvbpsi_decoder_t)); dvbpsi_pmt_decoder_t* p_pmt_decoder; unsigned int i; 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; h_dvbpsi->p_free_sections = 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(i = 0; i <= 255; i++) p_pmt_decoder->ap_sections[i] = NULL; return h_dvbpsi;}/***************************************************************************** * dvbpsi_DetachPMT ***************************************************************************** * Close a PMT decoder. The handle isn't valid any more. *****************************************************************************/void dvbpsi_DetachPMT(dvbpsi_handle h_dvbpsi){ dvbpsi_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t*)h_dvbpsi->p_private_decoder; unsigned int i; if (p_pmt_decoder->p_building_pmt) { ObjectRefDec(p_pmt_decoder->p_building_pmt); } for(i = 0; i <= 255; i++) { if(p_pmt_decoder->ap_sections[i]) free(p_pmt_decoder->ap_sections[i]); } free(h_dvbpsi->p_private_decoder); if(h_dvbpsi->p_current_section) dvbpsi_DeletePSISections(h_dvbpsi->p_current_section); if(h_dvbpsi->p_free_sections) dvbpsi_DeletePSISections(h_dvbpsi->p_free_sections); free(h_dvbpsi);}/***************************************************************************** * dvbpsi_InitPMT ***************************************************************************** * Initialize a pre-allocated dvbpsi_pmt_t structure. *****************************************************************************/void dvbpsi_InitPMT(dvbpsi_pmt_t* p_pmt, uint16_t i_program_number, uint8_t i_version, int b_current_next, uint16_t i_pcr_pid){ p_pmt->i_program_number = i_program_number; p_pmt->i_version = i_version; p_pmt->b_current_next = b_current_next; p_pmt->i_pcr_pid = i_pcr_pid; p_pmt->p_first_descriptor = NULL; p_pmt->p_first_es = NULL;}/***************************************************************************** * dvbpsi_EmptyPMT ***************************************************************************** * Clean a dvbpsi_pmt_t structure. *****************************************************************************/void dvbpsi_EmptyPMT(dvbpsi_pmt_t* p_pmt){ dvbpsi_pmt_es_t* p_es = p_pmt->p_first_es; dvbpsi_DeleteDescriptors(p_pmt->p_first_descriptor); while(p_es != NULL) { dvbpsi_pmt_es_t* p_tmp = p_es->p_next; dvbpsi_DeleteDescriptors(p_es->p_first_descriptor); free(p_es); p_es = p_tmp; } p_pmt->p_first_descriptor = NULL; p_pmt->p_first_es = NULL;} /***************************************************************************** * dvbpsi_PMTAddDescriptor ***************************************************************************** * Add a descriptor in the PMT. *****************************************************************************/dvbpsi_descriptor_t* dvbpsi_PMTAddDescriptor(dvbpsi_pmt_t* p_pmt, uint8_t i_tag, uint8_t i_length, uint8_t* p_data){ dvbpsi_descriptor_t* p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); if(p_descriptor) { if(p_pmt->p_first_descriptor == NULL) { p_pmt->p_first_descriptor = p_descriptor; } else { 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;}/***************************************************************************** * dvbpsi_PMTAddES ***************************************************************************** * Add an ES in the PMT. *****************************************************************************/dvbpsi_pmt_es_t* dvbpsi_PMTAddES(dvbpsi_pmt_t* p_pmt, uint8_t i_type, uint16_t i_pid){ dvbpsi_pmt_es_t* p_es = (dvbpsi_pmt_es_t*)malloc(sizeof(dvbpsi_pmt_es_t)); if(p_es) { p_es->i_type = i_type; p_es->i_pid = i_pid; p_es->p_first_descriptor = NULL; p_es->p_next = NULL; if(p_pmt->p_first_es == NULL) { p_pmt->p_first_es = p_es; } else { dvbpsi_pmt_es_t* p_last_es = p_pmt->p_first_es; while(p_last_es->p_next != NULL) p_last_es = p_last_es->p_next; p_last_es->p_next = p_es; } } return p_es;}/***************************************************************************** * dvbpsi_PMTESAddDescriptor ***************************************************************************** * Add a descriptor in the PMT ES. *****************************************************************************/dvbpsi_descriptor_t* dvbpsi_PMTESAddDescriptor(dvbpsi_pmt_es_t* p_es, uint8_t i_tag, uint8_t i_length, uint8_t* p_data){ dvbpsi_descriptor_t* p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data); if(p_descriptor) { if(p_es->p_first_descriptor == NULL) { p_es->p_first_descriptor = p_descriptor; } else { 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; } } return p_descriptor;}/***************************************************************************** * dvbpsi_GatherPMTSections ***************************************************************************** * Callback for the PSI decoder. *****************************************************************************/void dvbpsi_GatherPMTSections(dvbpsi_decoder_t* p_decoder, dvbpsi_psi_section_t* p_section){ dvbpsi_pmt_decoder_t* p_pmt_decoder = (dvbpsi_pmt_decoder_t*)p_decoder->p_private_decoder; int b_append = 1; int b_reinit = 0; unsigned int i; DVBPSI_DEBUG_ARG("PMT decoder", "Table version %2d, " "i_extension %5d, " "section %3d up to %3d, " "current %1d", p_section->i_version, p_section->i_extension, p_section->i_number, p_section->i_last_number, p_section->b_current_next); if(p_section->i_table_id != 0x02) { /* Invalid table_id value */ DVBPSI_ERROR_ARG("PMT 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("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 */ if(p_decoder->b_discontinuity) { b_reinit = 1; p_decoder->b_discontinuity = 0; } else { /* Perform some few sanity checks */ if(p_pmt_decoder->p_building_pmt) { if(p_pmt_decoder->p_building_pmt->i_version != p_section->i_version) { /* version_number */ DVBPSI_ERROR("PMT decoder", "'version_number' differs" " whereas no discontinuity has occured"); b_reinit = 1; } else if(p_pmt_decoder->i_last_section_number != p_section->i_last_number) { /* last_section_number */ DVBPSI_ERROR("PMT decoder", "'last_section_number' differs" " whereas no discontinuity has occured"); b_reinit = 1; } } else { if( (p_pmt_decoder->b_current_valid) && (p_pmt_decoder->current_pmt.i_version == p_section->i_version)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -