⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 input_psi.c

📁 vlc stand 0.1.99 ist sehr einfach
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************** * psi.c: PSI management * Manages structures containing PSI information, and affiliated decoders. * TODO: Fonctions d'init des structures ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * * Authors: * * 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, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "defs.h"#include <sys/types.h>                        /* on BSD, uio.h needs types.h */#include <sys/uio.h>                                            /* "input.h" */#include <stdlib.h>                                     /* free(), realloc() */#include <string.h>                                               /* bzero() */#include <netinet/in.h>                                           /* ntohs() */#include "config.h"#include "common.h"#include "threads.h"#include "mtime.h"#include "intf_msg.h"#include "debug.h"#include "input.h"#include "input_ctrl.h"#include "input_psi.h"#include "main.h"/* * Precalculated 32-bits CRC table, shared by all instances of the PSI decoder */boolean_t b_crc_initialised = 0;u32 i_crc_32_table[256];/* * Global configuration variable, need by AUTO_SPAWN to determine * the option (audio and video) passed to the VideoLAN client. */#ifdef AUTO_SPAWN//XXX?? extern program_data_t *p_main;#endif/* * Locale type definitions */#define PSI_VIDEO_STREAM_DESCRIPTOR                 0x02#define PSI_AUDIO_STREAM_DESCRIPTOR                 0x03#define PSI_TARGET_BACKGROUND_GRID_DESCRIPTOR       0x07#define PSI_VIDEO_WINDOW_DESCRIPTOR                 0x08#ifdef DVB_EXTENSIONS#define PSI_SERVICE_DESCRIPTOR                      0x48#endif/* That info must be stored in the version field since it contains   unused bits */#define PSI_UNINITIALISED                           0xFF/* * Local prototypes */static int input_AddPsiPID( input_thread_t *p_input, int i_pid );static int input_DelPsiPID( input_thread_t *p_input, int i_pid );static void DecodePgrmAssocSection( byte_t* p_pas, input_thread_t *p_input );static void DecodePgrmMapSection( byte_t* p_pms, input_thread_t *p_input );static void DecodeSrvDescrSection( byte_t* p_sdt, input_thread_t *p_input );static void DecodePgrmDescriptor( byte_t* p_descr, pgrm_descriptor_t* p_pgrm );static void DecodeESDescriptor( byte_t* p_descriptor, es_descriptor_t* p_es );static stream_descriptor_t* AddStreamDescr( input_thread_t* p_input,                                            u16 i_stream_id );static void DestroyStreamDescr( input_thread_t* p_input, u16 i_stream_id );static pgrm_descriptor_t* AddPgrmDescr( stream_descriptor_t* p_stream,                                       u16 i_pgrm_id );static void DestroyPgrmDescr( input_thread_t* p_input,                              stream_descriptor_t* p_stream, u16 i_pgrm_id );static es_descriptor_t* AddESDescr( input_thread_t* p_input,                                    pgrm_descriptor_t* p_pgrm, u16 i_es_pid );static void DestroyESDescr( input_thread_t* p_input, pgrm_descriptor_t* p_pgrm,                            u16 i_es_pid);static void BuildCrc32Table();static int CheckCRC32( u8* p_pms, int i_size);static boolean_t Is_known( byte_t* a_known_section, u8 i_section );static void Set_known( byte_t* a_known_section, u8 i_section );static void Unset_known( byte_t* a_known_section, u8 i_section );/***************************************************************************** * input_PsiInit: Initialize PSI decoder ***************************************************************************** * Init the structures in which the PSI decoder will put the informations it * got from PSI tables and request for the reception of the PAT. *****************************************************************************/int input_PsiInit( input_thread_t *p_input ){  ASSERT(p_input);  /* Precalculate the 32-bit CRC table if not already done ?     FIXME: Put a lock or do that at pgrm init ?? */  if( !b_crc_initialised )  {    BuildCrc32Table();    b_crc_initialised = 1;  }  /* Init the structure that describes the stream we are receiving */  AddStreamDescr( p_input, PSI_UNINITIALISED );  /* Request for reception of the program association table */  input_AddPsiPID( p_input, 0 );#ifdef DVB_EXTENSIONS  /* Request for reception of the service description table */  input_AddPsiPID( p_input, 17 );#endif  return( 0 );}/***************************************************************************** * input_PsiClean: Clean PSI structures before dying *****************************************************************************/int input_PsiEnd( input_thread_t *p_input ){  ASSERT(p_input);  /* Stop to receive all the PSI tables associated with that program */  /* FIXME: Not really useful ??*/  /* Clean also descriptors for programs associated with that stream */  /* FIXME: -> Not really useful and maybe buggy ??*/  /* Destroy the stream description */  DestroyStreamDescr( p_input, p_input->p_stream->i_stream_id );  return( 0 );}/***************************************************************************** * input_PsiRead: Read the table of programs ***************************************************************************** * Ugly debugging function at that time ? XXX?? *****************************************************************************/void input_PsiRead( input_thread_t *p_input /* XXX?? */ ){  int i_index;  int i_index2;  pgrm_descriptor_t* p_pgrm;  ASSERT( p_input );  /* Lock the tables, since this method can be called from any thread */  //vlc_mutex_lock()  /* Check if the table is complete or not */  if( !p_input->p_stream->b_is_PMT_complete )  {    intf_IntfMsg( "Warning: PMT not yet complete\n" );  }  /* Read the table */  for( i_index = 0; i_index < p_input->p_stream->i_pgrm_number; i_index++ )  {    p_pgrm = p_input->p_stream->ap_programs[i_index];    intf_DbgMsg("Printing info for program %d\n", p_pgrm->i_number );    intf_IntfMsg("Printing info for program %d\n", p_pgrm->i_number );    for( i_index2 = 0; i_index2 < p_pgrm->i_es_number; i_index2++ )    {      intf_DbgMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n",                   p_pgrm->ap_es[i_index2]->i_id,                   p_pgrm->ap_es[i_index2]->i_type,                   p_pgrm->ap_es[i_index2]->b_pcr,                   p_pgrm->ap_es[i_index2]->b_psi);      intf_IntfMsg( " ->Pid %d: type %d, PCR: %d, PSI: %d\n",                    p_pgrm->ap_es[i_index2]->i_id,                    p_pgrm->ap_es[i_index2]->i_type,                    p_pgrm->ap_es[i_index2]->b_pcr,                    p_pgrm->ap_es[i_index2]->b_psi);    }  }  /* Unock the tables */  //vlc_mutex_unlock()}/***************************************************************************** * input_PsiDecode: Decode a PSI section ***************************************************************************** * This funtion is essentially a wrapper that will  perform basic checks on * the section and then call the right function according to its type. *****************************************************************************/void input_PsiDecode( input_thread_t *p_input, psi_section_t* p_psi_section ){  ASSERT(p_input);  ASSERT(p_psi_section);  /* Hexa dump of the beginning of the section (for real men) */  //intf_DbgMsg( "Section: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", (u8)p_psi_section->buffer[0], (u8)p_psi_section->buffer[1], (u8)p_psi_section->buffer[2], (u8)p_psi_section->buffer[3], (u8)p_psi_section->buffer[4], (u8)p_psi_section->buffer[5], (u8)p_psi_section->buffer[6], (u8)p_psi_section->buffer[7], (u8)p_psi_section->buffer[8], (u8)p_psi_section->buffer[9], (u8)p_psi_section->buffer[10], (u8)p_psi_section->buffer[11], (u8)p_psi_section->buffer[12], (u8)p_psi_section->buffer[13], (u8)p_psi_section->buffer[14], (u8)p_psi_section->buffer[15], (u8)p_psi_section->buffer[16], (u8)p_psi_section->buffer[17], (u8)p_psi_section->buffer[18], (u8)p_psi_section->buffer[19] );  /* Check the CRC validity if any CRC is carried */#if 0  if( p_psi_section->buffer[1] & 0x80 )  {    if( CheckCRC32 (p_psi_section->buffer, p_psi_section->i_length) )    {      intf_DbgMsg("iSize: %d, CRC: %d\n", p_psi_section->i_length,                  U32_AT(&p_psi_section->buffer[p_psi_section->i_length-4]));      intf_DbgMsg( "Invalid CRC for PSI\n" );      return;    }  }#endif  /* If the section is not immediatly applicable, trash it (DVB drafts disallow     transmission of such sections, so we didn't implement it) */  if( !p_psi_section->buffer[5] & 0x01 )  {    intf_DbgMsg( "PSI not yet applicable: trash it\n" );    return;  }  /* Handle the packet according to it's type given it the table_id  */  switch ( p_psi_section->buffer[0] )  {    case 0x00:      //intf_DbgMsg("Program association section received\n");      DecodePgrmAssocSection(p_psi_section->buffer, p_input);      break;    case 0x01:      //intf_DbgMsg("Conditional access section received\n");      break;    case 0x02:      //intf_DbgMsg("Program map section received\n");      DecodePgrmMapSection(p_psi_section->buffer, p_input);      break;    case 0x42:      //intf_DbgMsg("Service description section received\n");      DecodeSrvDescrSection(p_psi_section->buffer, p_input);      break;    default:      //intf_DbgMsg("Private PSI data received (type %x), ignoring it\n",      //            p_psi_section->buffer[0]);  }}/***************************************************************************** * DecodeAssocSection: Decode a PAS ***************************************************************************** * No check is made to known if the table is currently applicable or not, so * that unapplicable sections must be filtered before calling this function * The Program Association Table can be segmented to occupy multiple sections * so that we have to know which sections we have already received (IsKnown() / * SetKnown() calls) *****************************************************************************/static void DecodePgrmAssocSection(u8* p_pas, input_thread_t *p_input ){    u8 i_stream_id;            /* Id of the stream described in that section */    u8 i_version;             /* Version of the table carried in the section */    u16 i_pgrm_id;                      /* Id of the current described  pgrm */    u16 i_pgrm_map_pid;           /* PID of the associated program map table */    int i_pgrm_number;        /* Number of programs described in the section */    boolean_t b_is_invalid = 0;    u8 i_current_section;    u8 i_last_section;    int i_pgrm_index;    int i_es_index;    ASSERT(p_pas);    ASSERT(p_input);#define p_descr (p_input->p_stream)    /* Read stream id and version number immediately, to be sure they will be       initialised in all cases we will need it */    i_stream_id = U16_AT(&p_pas[3]);    i_version = (p_pas[5] >> 1) & 0x1F;    //intf_DbgMsg("TS Id: %d, version: %d\n", U16_AT(&p_pas[3]),(p_pas[5] >> 1) & 0x1F);    /* Test if the stream has not changed by looking at the stream_id */    if( p_descr->i_stream_id != i_stream_id )    {        /* This can either mean that the PSI decoder has just started or that           the stream has changed */        if( p_descr->i_PAT_version== PSI_UNINITIALISED )            intf_DbgMsg("Building Program Association table\n");        else            intf_ErrMsg( "Stream Id has suddenly changed ! Rebuilding PAT\n" );        /* Whatever it is, ask the PSI decoder to rebuild the table */        b_is_invalid = 1;    }    else    {        /* Stream has not changed, test if the PMT is up to date */        if( p_descr->i_PAT_version != i_version )        {            intf_DbgMsg("PAT has been updated, rebuilding it\n");            /* Ask the PSI decoder to rebuild the table */            b_is_invalid = 1;        }    }    /* Clear the table if needed */    if( b_is_invalid )    {        intf_DbgMsg("Updating PAT table\n");        /* Any program in the stream may have disapeared, or a new one           can have been added. The good way to handle such a case would be           to build a temporary table and to make a diff */        /* Stop the reception of all programs and PSI informations           associated with this stream, excepted the PAT on PID 0 and the SDT           on PID 17 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -