ps.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:17k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * ps.c: Program Stream demux module for VLC.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 the VideoLAN team
  5.  * $Id: cee838bda7e8e6dc32ee19d522be270327216226 $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *
  9.  * This program is free software; you can redistribute it and/or modify
  10.  * it under the terms of the GNU General Public License as published by
  11.  * the Free Software Foundation; either version 2 of the License, or
  12.  * (at your option) any later version.
  13.  *
  14.  * This program is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17.  * GNU General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU General Public License
  20.  * along with this program; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #ifdef HAVE_CONFIG_H
  27. # include "config.h"
  28. #endif
  29. #include <vlc_common.h>
  30. #include <vlc_plugin.h>
  31. #include <vlc_demux.h>
  32. #include "ps.h"
  33. /* TODO:
  34.  *  - re-add pre-scanning.
  35.  *  - ...
  36.  */
  37. #define TIME_TEXT N_("Trust MPEG timestamps")
  38. #define TIME_LONGTEXT N_("Normally we use the timestamps of the MPEG files " 
  39.     "to calculate position and duration. However sometimes this might not " 
  40.     "be usable. Disable this option to calculate from the bitrate instead." )
  41. /*****************************************************************************
  42.  * Module descriptor
  43.  *****************************************************************************/
  44. static int  OpenForce( vlc_object_t * );
  45. static int  Open   ( vlc_object_t * );
  46. static void Close  ( vlc_object_t * );
  47. vlc_module_begin ()
  48.     set_description( N_("MPEG-PS demuxer") )
  49.     set_shortname( N_("PS") )
  50.     set_category( CAT_INPUT )
  51.     set_subcategory( SUBCAT_INPUT_DEMUX )
  52.     set_capability( "demux", 1 )
  53.     set_callbacks( OpenForce, Close )
  54.     add_shortcut( "ps" )
  55.     add_bool( "ps-trust-timestamps", true, NULL, TIME_TEXT,
  56.                  TIME_LONGTEXT, true )
  57.         change_safe ()
  58.     add_submodule ()
  59.     set_description( N_("MPEG-PS demuxer") )
  60.     set_capability( "demux", 8 )
  61.     set_callbacks( Open, Close )
  62.     add_shortcut( "ps" )
  63. vlc_module_end ()
  64. /*****************************************************************************
  65.  * Local prototypes
  66.  *****************************************************************************/
  67. struct demux_sys_t
  68. {
  69.     ps_psm_t    psm;
  70.     ps_track_t  tk[PS_TK_COUNT];
  71.     int64_t     i_scr;
  72.     int         i_mux_rate;
  73.     int64_t     i_length;
  74.     int         i_time_track;
  75.     int64_t     i_current_pts;
  76.     bool  b_lost_sync;
  77.     bool  b_have_pack;
  78.     bool  b_seekable;
  79. };
  80. static int Demux  ( demux_t *p_demux );
  81. static int Control( demux_t *p_demux, int i_query, va_list args );
  82. static int      ps_pkt_resynch( stream_t *, uint32_t *pi_code );
  83. static block_t *ps_pkt_read   ( stream_t *, uint32_t i_code );
  84. /*****************************************************************************
  85.  * Open
  86.  *****************************************************************************/
  87. static int OpenCommon( vlc_object_t *p_this, bool b_force )
  88. {
  89.     demux_t     *p_demux = (demux_t*)p_this;
  90.     demux_sys_t *p_sys;
  91.     const uint8_t *p_peek;
  92.     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
  93.     {
  94.         msg_Err( p_demux, "cannot peek" );
  95.         return VLC_EGENERIC;
  96.     }
  97.     if( memcmp( p_peek, "x00x00x01", 3 ) || ( p_peek[3] < 0xb9 ) )
  98.     {
  99.         if( !b_force )
  100.             return VLC_EGENERIC;
  101.         msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
  102.                   "continuing anyway" );
  103.     }
  104.     /* Fill p_demux field */
  105.     p_demux->pf_demux = Demux;
  106.     p_demux->pf_control = Control;
  107.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  108.     if( !p_sys ) return VLC_ENOMEM;
  109.     /* Init p_sys */
  110.     p_sys->i_mux_rate = 0;
  111.     p_sys->i_scr      = -1;
  112.     p_sys->i_length   = -1;
  113.     p_sys->i_current_pts = (mtime_t) 0;
  114.     p_sys->i_time_track = -1;
  115.     p_sys->b_lost_sync = false;
  116.     p_sys->b_have_pack = false;
  117.     p_sys->b_seekable  = false;
  118.     stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );
  119.     ps_psm_init( &p_sys->psm );
  120.     ps_track_init( p_sys->tk );
  121.     /* TODO prescanning of ES */
  122.     return VLC_SUCCESS;
  123. }
  124. static int OpenForce( vlc_object_t *p_this )
  125. {
  126.     return OpenCommon( p_this, true );
  127. }
  128. static int Open( vlc_object_t *p_this )
  129. {
  130.     return OpenCommon( p_this, ((demux_t *)p_this)->b_force );
  131. }
  132. /*****************************************************************************
  133.  * Close
  134.  *****************************************************************************/
  135. static void Close( vlc_object_t *p_this )
  136. {
  137.     demux_t     *p_demux = (demux_t*)p_this;
  138.     demux_sys_t *p_sys = p_demux->p_sys;
  139.     int i;
  140.     for( i = 0; i < PS_TK_COUNT; i++ )
  141.     {
  142.         ps_track_t *tk = &p_sys->tk[i];
  143.         if( tk->b_seen )
  144.         {
  145.             es_format_Clean( &tk->fmt );
  146.             if( tk->es ) es_out_Del( p_demux->out, tk->es );
  147.         }
  148.     }
  149.     ps_psm_destroy( &p_sys->psm );
  150.     free( p_sys );
  151. }
  152. static int Demux2( demux_t *p_demux, bool b_end )
  153. {
  154.     demux_sys_t *p_sys = p_demux->p_sys;
  155.     int i_ret, i_id;
  156.     uint32_t i_code;
  157.     block_t *p_pkt;
  158.     i_ret = ps_pkt_resynch( p_demux->s, &i_code );
  159.     if( i_ret < 0 )
  160.     {
  161.         return 0;
  162.     }
  163.     else if( i_ret == 0 )
  164.     {
  165.         if( !p_sys->b_lost_sync )
  166.             msg_Warn( p_demux, "garbage at input, trying to resync..." );
  167.         p_sys->b_lost_sync = true;
  168.         return 1;
  169.     }
  170.     if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
  171.     p_sys->b_lost_sync = false;
  172.     if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL )
  173.     {
  174.         return 0;
  175.     }
  176.     if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 )
  177.     {
  178.         ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  179.         if( !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
  180.         {
  181.             if( b_end && p_pkt->i_pts > tk->i_last_pts )
  182.             {
  183.                 tk->i_last_pts = p_pkt->i_pts;
  184.             }
  185.             else if ( tk->i_first_pts == -1 )
  186.             {
  187.                 tk->i_first_pts = p_pkt->i_pts;
  188.             }
  189.         }
  190.     }
  191.     block_Release( p_pkt );
  192.     return 1;
  193. }
  194. static void FindLength( demux_t *p_demux )
  195. {
  196.     demux_sys_t *p_sys = p_demux->p_sys;
  197.     int64_t i_current_pos = -1, i_size = 0, i_end = 0;
  198.     int i;
  199.     if( !var_CreateGetInteger( p_demux, "ps-trust-timestamps" ) )
  200.         return;
  201.     if( p_sys->i_length == -1 ) /* First time */
  202.     {
  203.         p_sys->i_length = 0;
  204.         /* Check beginning */
  205.         i = 0;
  206.         i_current_pos = stream_Tell( p_demux->s );
  207.         while( vlc_object_alive (p_demux) && i < 40 && Demux2( p_demux, false ) > 0 ) i++;
  208.         /* Check end */
  209.         i_size = stream_Size( p_demux->s );
  210.         i_end = __MAX( 0, __MIN( 200000, i_size ) );
  211.         stream_Seek( p_demux->s, i_size - i_end );
  212.         i = 0;
  213.         while( vlc_object_alive (p_demux) && i < 40 && Demux2( p_demux, true ) > 0 );
  214.         if( i_current_pos >= 0 ) stream_Seek( p_demux->s, i_current_pos );
  215.     }
  216.     for( i = 0; i < PS_TK_COUNT; i++ )
  217.     {
  218.         ps_track_t *tk = &p_sys->tk[i];
  219.         if( tk->i_first_pts >= 0 && tk->i_last_pts > 0 )
  220.             if( tk->i_last_pts > tk->i_first_pts )
  221.             {
  222.                 int64_t i_length = (int64_t)tk->i_last_pts - tk->i_first_pts;
  223.                 if( i_length > p_sys->i_length )
  224.                 {
  225.                     p_sys->i_length = i_length;
  226.                     p_sys->i_time_track = i;
  227.                     msg_Dbg( p_demux, "we found a length of: %"PRId64, p_sys->i_length );
  228.                 }
  229.             }
  230.     }
  231. }
  232. /*****************************************************************************
  233.  * Demux:
  234.  *****************************************************************************/
  235. static int Demux( demux_t *p_demux )
  236. {
  237.     demux_sys_t *p_sys = p_demux->p_sys;
  238.     int i_ret, i_id, i_mux_rate;
  239.     uint32_t i_code;
  240.     block_t *p_pkt;
  241.     i_ret = ps_pkt_resynch( p_demux->s, &i_code );
  242.     if( i_ret < 0 )
  243.     {
  244.         return 0;
  245.     }
  246.     else if( i_ret == 0 )
  247.     {
  248.         if( !p_sys->b_lost_sync )
  249.             msg_Warn( p_demux, "garbage at input, trying to resync..." );
  250.         p_sys->b_lost_sync = true;
  251.         return 1;
  252.     }
  253.     if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
  254.     p_sys->b_lost_sync = false;
  255.     if( p_sys->i_length < 0 && p_sys->b_seekable )
  256.         FindLength( p_demux );
  257.     if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL )
  258.     {
  259.         return 0;
  260.     }
  261.     switch( i_code )
  262.     {
  263.     case 0x1b9:
  264.         block_Release( p_pkt );
  265.         break;
  266.     case 0x1ba:
  267.         if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_scr, &i_mux_rate ) )
  268.         {
  269.             if( !p_sys->b_have_pack ) p_sys->b_have_pack = true;
  270.             /* done later on to work around bad vcd/svcd streams */
  271.             /* es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr ); */
  272.             if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
  273.         }
  274.         block_Release( p_pkt );
  275.         break;
  276.     case 0x1bb:
  277.         if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) )
  278.         {
  279.             int i;
  280.             for( i = 0; i < PS_TK_COUNT; i++ )
  281.             {
  282.                 ps_track_t *tk = &p_sys->tk[i];
  283.                 if( tk->b_seen && !tk->es && tk->fmt.i_cat != UNKNOWN_ES )
  284.                 {
  285.                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
  286.                 }
  287.             }
  288.         }
  289.         block_Release( p_pkt );
  290.         break;
  291.     case 0x1bc:
  292.         if( p_sys->psm.i_version == 0xFFFF )
  293.             msg_Dbg( p_demux, "contains a PSM");
  294.         ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out );
  295.         block_Release( p_pkt );
  296.         break;
  297.     default:
  298.         if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 )
  299.         {
  300.             bool b_new = false;
  301.             ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  302.             if( !tk->b_seen )
  303.             {
  304.                 if( !ps_track_fill( tk, &p_sys->psm, i_id ) )
  305.                 {
  306.                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
  307.                     b_new = true;
  308.                 }
  309.                 else
  310.                 {
  311.                     msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
  312.                 }
  313.                 tk->b_seen = true;
  314.             }
  315.             /* The popular VCD/SVCD subtitling WinSubMux does not
  316.              * renumber the SCRs when merging subtitles into the PES */
  317.             if( tk->b_seen &&
  318.                 ( tk->fmt.i_codec == VLC_FOURCC('o','g','t',' ') ||
  319.                   tk->fmt.i_codec == VLC_FOURCC('c','v','d',' ') ) )
  320.             {
  321.                 p_sys->i_scr = -1;
  322.             }
  323.             if( p_sys->i_scr > 0 )
  324.                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr );
  325.             p_sys->i_scr = -1;
  326.             if( tk->b_seen && tk->es &&
  327.                 (
  328. #ifdef ZVBI_COMPILED /* FIXME!! */
  329.                 tk->fmt.i_codec == VLC_FOURCC('t','e','l','x') ||
  330. #endif
  331.                 !ps_pkt_parse_pes( p_pkt, tk->i_skip ) ) )
  332.             {
  333.                 if( !b_new && !p_sys->b_have_pack &&
  334.                     (tk->fmt.i_cat == AUDIO_ES) &&
  335.                     (p_pkt->i_pts > 0) )
  336.                 {
  337.                     /* A hack to sync the A/V on PES files. */
  338.                     msg_Dbg( p_demux, "force SCR: %"PRId64, p_pkt->i_pts );
  339.                     es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_pkt->i_pts );
  340.                 }
  341.                 if( (int64_t)p_pkt->i_pts > p_sys->i_current_pts )
  342.                 {
  343.                     p_sys->i_current_pts = (int64_t)p_pkt->i_pts;
  344.                 }
  345.                 es_out_Send( p_demux->out, tk->es, p_pkt );
  346.             }
  347.             else
  348.             {
  349.                 block_Release( p_pkt );
  350.             }
  351.         }
  352.         else
  353.         {
  354.             block_Release( p_pkt );
  355.         }
  356.         break;
  357.     }
  358.     return 1;
  359. }
  360. /*****************************************************************************
  361.  * Control:
  362.  *****************************************************************************/
  363. static int Control( demux_t *p_demux, int i_query, va_list args )
  364. {
  365.     demux_sys_t *p_sys = p_demux->p_sys;
  366.     double f, *pf;
  367.     int64_t i64, *pi64;
  368.     switch( i_query )
  369.     {
  370.         case DEMUX_GET_POSITION:
  371.             pf = (double*) va_arg( args, double* );
  372.             i64 = stream_Size( p_demux->s );
  373.             if( i64 > 0 )
  374.             {
  375.                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
  376.             }
  377.             else
  378.             {
  379.                 *pf = 0.0;
  380.             }
  381.             return VLC_SUCCESS;
  382.         case DEMUX_SET_POSITION:
  383.             f = (double) va_arg( args, double );
  384.             i64 = stream_Size( p_demux->s );
  385.             p_sys->i_current_pts = 0;
  386.             return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
  387.         case DEMUX_GET_TIME:
  388.             pi64 = (int64_t*)va_arg( args, int64_t * );
  389.             if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 )
  390.             {
  391.                 *pi64 = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts;
  392.                 return VLC_SUCCESS;
  393.             }
  394.             if( p_sys->i_mux_rate > 0 )
  395.             {
  396.                 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) /
  397.                     p_sys->i_mux_rate;
  398.                 return VLC_SUCCESS;
  399.             }
  400.             *pi64 = 0;
  401.             return VLC_EGENERIC;
  402.         case DEMUX_GET_LENGTH:
  403.             pi64 = (int64_t*)va_arg( args, int64_t * );
  404.             if( p_sys->i_length > 0 )
  405.             {
  406.                 *pi64 = p_sys->i_length;
  407.                 return VLC_SUCCESS;
  408.             }
  409.             else if( p_sys->i_mux_rate > 0 )
  410.             {
  411.                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) /
  412.                     p_sys->i_mux_rate;
  413.                 return VLC_SUCCESS;
  414.             }
  415.             *pi64 = 0;
  416.             return VLC_EGENERIC;
  417.         case DEMUX_SET_TIME:
  418.             i64 = (int64_t)va_arg( args, int64_t );
  419.             if( p_sys->i_time_track >= 0 && p_sys->i_current_pts > 0 )
  420.             {
  421.                 int64_t i_now = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track].i_first_pts;
  422.                 int64_t i_pos = stream_Tell( p_demux->s );
  423.                 if( !i_now )
  424.                     return i64 ? VLC_EGENERIC : VLC_SUCCESS;
  425.                 i_pos *= (float)i64 / (float)i_now;
  426.                 stream_Seek( p_demux->s, i_pos );
  427.                 return VLC_SUCCESS;
  428.             }
  429.             return VLC_EGENERIC;
  430.         case DEMUX_GET_FPS:
  431.         default:
  432.             return VLC_EGENERIC;
  433.     }
  434. }
  435. /*****************************************************************************
  436.  * Divers:
  437.  *****************************************************************************/
  438. /* PSResynch: resynch on a system startcode
  439.  *  It doesn't skip more than 512 bytes
  440.  *  -1 -> error, 0 -> not synch, 1 -> ok
  441.  */
  442. static int ps_pkt_resynch( stream_t *s, uint32_t *pi_code )
  443. {
  444.     const uint8_t *p_peek;
  445.     int     i_peek;
  446.     int     i_skip;
  447.     if( stream_Peek( s, &p_peek, 4 ) < 4 )
  448.     {
  449.         return -1;
  450.     }
  451.     if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
  452.         p_peek[3] >= 0xb9 )
  453.     {
  454.         *pi_code = 0x100 | p_peek[3];
  455.         return 1;
  456.     }
  457.     if( ( i_peek = stream_Peek( s, &p_peek, 512 ) ) < 4 )
  458.     {
  459.         return -1;
  460.     }
  461.     i_skip = 0;
  462.     for( ;; )
  463.     {
  464.         if( i_peek < 4 )
  465.         {
  466.             break;
  467.         }
  468.         if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
  469.             p_peek[3] >= 0xb9 )
  470.         {
  471.             *pi_code = 0x100 | p_peek[3];
  472.             return stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1;
  473.         }
  474.         p_peek++;
  475.         i_peek--;
  476.         i_skip++;
  477.     }
  478.     return stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1;
  479. }
  480. static block_t *ps_pkt_read( stream_t *s, uint32_t i_code )
  481. {
  482.     const uint8_t *p_peek;
  483.     int      i_peek = stream_Peek( s, &p_peek, 14 );
  484.     int      i_size;
  485.     VLC_UNUSED(i_code);
  486.     /* Smallest valid packet */
  487.     if( i_peek < 6 ) return NULL;
  488.     i_size = ps_pkt_size( p_peek, i_peek );
  489.     if( i_size < 0 || ( i_size <= 6 && p_peek[3] > 0xba ) )
  490.     {
  491.         /* Special case, search the next start code */
  492.         i_size = 6;
  493.         for( ;; )
  494.         {
  495.             i_peek = stream_Peek( s, &p_peek, i_size + 1024 );
  496.             if( i_peek <= i_size + 4 )
  497.             {
  498.                 return NULL;
  499.             }
  500.             while( i_size <= i_peek - 4 )
  501.             {
  502.                 if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
  503.                     p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= 0xb9 )
  504.                 {
  505.                     return stream_Block( s, i_size );
  506.                 }
  507.                 i_size++;
  508.             }
  509.         }
  510.     }
  511.     else
  512.     {
  513.         /* Normal case */
  514.         return stream_Block( s, i_size );
  515.     }
  516.     return NULL;
  517. }