ts.c

来自「VLC媒体播放程序」· C语言 代码 · 共 1,679 行 · 第 1/5 页

C
1,679
字号
/***************************************************************************** * mpeg_ts.c : Transport Stream input module for vlc ***************************************************************************** * Copyright (C) 2000-2004 VideoLAN * $Id: ts.c,v 1.46 2004/01/25 20:05:28 hartman Exp $ * * Authors: Henri Fallon <henri@via.ecp.fr> *          Johan Bilien <jobi@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, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/input.h>#include "iso_lang.h"#if defined MODULE_NAME_IS_ts_dvbpsi#   ifdef HAVE_DVBPSI_DR_H#       include <dvbpsi/dvbpsi.h>#       include <dvbpsi/descriptor.h>#       include <dvbpsi/pat.h>#       include <dvbpsi/pmt.h>#       include <dvbpsi/dr.h>#   else#       include "dvbpsi.h"#       include "descriptor.h"#       include "tables/pat.h"#       include "tables/pmt.h"#       include "descriptors/dr.h"#   endif#endif#include "system.h"#include "codecs.h"/***************************************************************************** * Constants *****************************************************************************/#define TS_READ_ONCE 200/***************************************************************************** * Private structure *****************************************************************************/struct demux_sys_t{    module_t *   p_module;    mpeg_demux_t mpeg;};#define local_iso639_getlang(p1, p2)                                         \{                                                                           \    const iso639_lang_t * p_iso;                                            \    p_iso = GetLang_2T((char*)(p1));                                        \    if( p_iso && strcmp(p_iso->psz_native_name,"Unknown"))                  \    {                                                                       \        if( p_iso->psz_native_name[0] )                                     \            strncpy( (p2), p_iso->psz_native_name, 20 );                    \        else                                                                \            strncpy( (p2), p_iso->psz_eng_name, 20 );                       \    }                                                                       \    else                                                                    \    {                                                                       \        p_iso = GetLang_2B((char*)(p1));                                    \        if ( p_iso )                                                        \        {                                                                   \            if( p_iso->psz_native_name[0] )                                 \                strncpy( (p2), p_iso->psz_native_name, 20 );                \            else                                                            \                strncpy( (p2), p_iso->psz_eng_name, 20 );                   \        }                                                                   \        else                                                                \        {                                                                   \            strncpy( (p2), p1, 3 );                                         \        }                                                                   \    }                                                                       \}/***************************************************************************** * Local prototypes *****************************************************************************/static int  Activate   ( vlc_object_t * );static void Deactivate ( vlc_object_t * );static int  Demux      ( input_thread_t * );#if defined MODULE_NAME_IS_tsstatic void TSDemuxPSI ( input_thread_t *, data_packet_t *,                          es_descriptor_t *, vlc_bool_t );static void TSDecodePAT( input_thread_t *, es_descriptor_t *);static void TSDecodePMT( input_thread_t *, es_descriptor_t *);#define PSI_CALLBACK TSDemuxPSI#elif defined MODULE_NAME_IS_ts_dvbpsistatic void TS_DVBPSI_DemuxPSI  ( input_thread_t *, data_packet_t *,                                  es_descriptor_t *, vlc_bool_t );static void TS_DVBPSI_HandlePAT ( input_thread_t *, dvbpsi_pat_t * );static void TS_DVBPSI_HandlePMT ( input_thread_t *, dvbpsi_pmt_t * );#define PSI_CALLBACK TS_DVBPSI_DemuxPSI#endif/***************************************************************************** * Module descriptor *****************************************************************************/#define VLS_BACKWARDS_COMPAT_TEXT N_("Compatibility with pre-0.4 VLS")#define VLS_BACKWARDS_COMPAT_LONGTEXT N_( \    "The protocol for transmitting A/52 audio streams changed between VLC " \    "0.3.x and 0.4. By default VLC assumes you have the latest VLS. In case " \    "you're using an old version, select this option.")#define BUGGY_PSI_TEXT N_("Buggy PSI")#define BUGGY_PSI_LONGTEXT N_( \    "If you have a stream whose PSI packets do not feature incremented " \    "continuity counters, select this option.")vlc_module_begin();#if defined MODULE_NAME_IS_ts    set_description( _("ISO 13818-1 MPEG Transport Stream input") );    set_capability( "demux", 160 );    add_shortcut( "ts" );#elif defined MODULE_NAME_IS_ts_dvbpsi    set_description( _("ISO 13818-1 MPEG Transport Stream input (libdvbpsi)") );    set_capability( "demux", 170 );    add_shortcut( "ts_dvbpsi" );#endif    add_bool( "vls-backwards-compat", 0, NULL,              VLS_BACKWARDS_COMPAT_TEXT, VLS_BACKWARDS_COMPAT_LONGTEXT, VLC_TRUE );    add_bool( "buggy-psi", 0, NULL, BUGGY_PSI_TEXT, BUGGY_PSI_LONGTEXT, VLC_TRUE );    set_callbacks( Activate, Deactivate );vlc_module_end();/***************************************************************************** * Activate: initialize TS structures *****************************************************************************/static int Activate( vlc_object_t * p_this ){    input_thread_t *    p_input = (input_thread_t *)p_this;    demux_sys_t *       p_demux;    es_descriptor_t *   p_pat_es;    es_ts_data_t *      p_demux_data;    stream_ts_data_t *  p_stream_data;    byte_t *            p_peek;    vlc_bool_t          b_force = VLC_FALSE;    int                 i_sync_pos;    /* Set the demux function */    p_input->pf_demux = Demux;    p_input->pf_demux_control = demux_vaControlDefault;    /* Have a peep at the show */    if( input_Peek( p_input, &p_peek, TS_PACKET_SIZE ) < TS_PACKET_SIZE )    {        msg_Err( p_input, "cannot peek()" );        return VLC_EGENERIC;    }    if( *p_input->psz_demux && ( !strncmp( p_input->psz_demux, "ts", 3 )         || !strncmp( p_input->psz_demux, "ts_dvbpsi", 10 ) ) )        b_force = VLC_TRUE;    /* In a TS_PACKET_SIZE buffer we should find a sync byte */    for( i_sync_pos = 0; i_sync_pos < TS_PACKET_SIZE &&         p_peek[i_sync_pos] != TS_SYNC_CODE; i_sync_pos++ );    if( i_sync_pos >= TS_PACKET_SIZE )    {        if( b_force )        {            /* User forced */            msg_Err( p_input, "this does not look like a TS stream, "                     "continuing anyway" );        }        else        {            msg_Warn( p_input, "TS module discarded (no sync)" );            return VLC_EGENERIC;        }    }    /* Now that we have the first TS_SYNC_CODE, check the following     * TS_SYNC_CODEs are where they are supposed to be (one byte sync code     * is not enough to ensure the sync). */    if( !b_force )    {        if( input_Peek( p_input, &p_peek, TS_PACKET_SIZE * TS_SYNC_CODES_MIN )            < TS_PACKET_SIZE * TS_SYNC_CODES_MIN )        {            msg_Err( p_input, "cannot peek()" );            return VLC_EGENERIC;        }        for( ; i_sync_pos < TS_PACKET_SIZE * TS_SYNC_CODES_MIN;             i_sync_pos += TS_PACKET_SIZE )        {            if( p_peek[i_sync_pos] != TS_SYNC_CODE )            {                msg_Warn( p_input, "TS module discarded (lost sync)" );                return VLC_EGENERIC;            }        }    }    /* Adapt the bufsize for our only use. */    if( p_input->i_mtu != 0 )    {        /* Have minimum granularity to avoid bottlenecks at the input level. */        p_input->i_bufsize = (p_input->i_mtu / TS_PACKET_SIZE) * TS_PACKET_SIZE;    }    p_demux = p_input->p_demux_data = malloc( sizeof(demux_sys_t ) );    if( p_demux == NULL )    {        return -1;    }    p_input->p_private = (void*)&p_demux->mpeg;    p_demux->p_module = module_Need( p_input, "mpeg-system", NULL );    if( p_demux->p_module == NULL )    {        free( p_input->p_demux_data );        return -1;    }    vlc_mutex_lock( &p_input->stream.stream_lock );    if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )    {        module_Unneed( p_input, p_demux->p_module );        free( p_input->p_demux_data );        return -1;    }    p_stream_data = (stream_ts_data_t *)p_input->stream.p_demux_data;    p_stream_data->i_pat_version = PAT_UNINITIALIZED ;    p_stream_data->b_buggy_psi = config_GetInt( p_input, "buggy-psi" );#ifdef MODULE_NAME_IS_ts_dvbpsi    p_stream_data->p_pat_handle = (dvbpsi_handle *)      dvbpsi_AttachPAT( (dvbpsi_pat_callback) &TS_DVBPSI_HandlePAT, p_input );    if( p_stream_data->p_pat_handle == NULL )    {        msg_Err( p_input, "could not create PAT decoder" );        module_Unneed( p_input, p_demux->p_module );        free( p_input->p_demux_data );        return -1;    }#endif    /* We'll have to catch the PAT in order to continue     * Then the input will catch the PMT and then the others ES     * The PAT es is indepedent of any program. */    p_pat_es = input_AddES( p_input, NULL, 0x00,                            UNKNOWN_ES, NULL, sizeof( es_ts_data_t ) );    p_pat_es->i_fourcc = VLC_FOURCC( 'p', 'a', 't', ' ' );    p_demux_data = (es_ts_data_t *)p_pat_es->p_demux_data;    p_demux_data->b_psi = 1;    p_demux_data->i_psi_type = PSI_IS_PAT;    p_demux_data->p_psi_section = malloc(sizeof(psi_section_t));    p_demux_data->p_psi_section->b_is_complete = 1;    p_demux_data->i_continuity_counter = 0xFF;    vlc_mutex_unlock( &p_input->stream.stream_lock );    return 0;}/***************************************************************************** * Deactivate: deinitialize TS structures *****************************************************************************/static void Deactivate( vlc_object_t * p_this ){    input_thread_t *    p_input = (input_thread_t *)p_this;    module_Unneed( p_input, p_input->p_demux_data->p_module );    free( p_input->p_demux_data );}/***************************************************************************** * Demux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, otherwise the number of * packets. *****************************************************************************/static int Demux( input_thread_t * p_input ){    demux_sys_t *   p_demux = p_input->p_demux_data;    int             i_read_once = (p_input->i_mtu ?                                   p_input->i_bufsize / TS_PACKET_SIZE :                                   TS_READ_ONCE);    int             i;    for( i = 0; i < i_read_once; i++ )    {        data_packet_t *     p_data;        ssize_t             i_result;        i_result = p_demux->mpeg.pf_read_ts( p_input, &p_data );        if( i_result <= 0 )        {            return i_result;        }        p_demux->mpeg.pf_demux_ts( p_input, p_data,                                   (psi_callback_t) &PSI_CALLBACK );    }    return i_read_once;}#if defined MODULE_NAME_IS_ts/* * PSI demultiplexing and decoding without libdvbpsi *//***************************************************************************** * DemuxPSI : makes up complete PSI data *****************************************************************************/

⌨️ 快捷键说明

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