ps.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:11k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ps.c: Program Stream demux module for VLC.
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: ps.c 8972 2004-10-11 12:50:13Z gbazin $
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <vlc/vlc.h>
  28. #include <vlc/input.h>
  29. #include "ps.h"
  30. /* TODO:
  31.  *  - re-add pre-scanning.
  32.  *  - ...
  33.  */
  34. /*****************************************************************************
  35.  * Module descriptor
  36.  *****************************************************************************/
  37. static int  Open   ( vlc_object_t * );
  38. static int  OpenAlt( vlc_object_t * );
  39. static void Close  ( vlc_object_t * );
  40. vlc_module_begin();
  41.     set_description( _("PS demuxer") );
  42.     set_capability( "demux2", 1 );
  43.     set_callbacks( Open, Close );
  44.     add_shortcut( "ps" );
  45.     add_submodule();
  46.     set_description( _("PS demuxer") );
  47.     set_capability( "demux2", 9 );
  48.     set_callbacks( OpenAlt, Close );
  49. vlc_module_end();
  50. /*****************************************************************************
  51.  * Local prototypes
  52.  *****************************************************************************/
  53. struct demux_sys_t
  54. {
  55.     ps_psm_t    psm;
  56.     ps_track_t  tk[PS_TK_COUNT];
  57.     int64_t     i_scr;
  58.     int         i_mux_rate;
  59. };
  60. static int Demux  ( demux_t *p_demux );
  61. static int Control( demux_t *p_demux, int i_query, va_list args );
  62. static int      ps_pkt_resynch( stream_t *, uint32_t *pi_code );
  63. static block_t *ps_pkt_read   ( stream_t *, uint32_t i_code );
  64. /*****************************************************************************
  65.  * Open
  66.  *****************************************************************************/
  67. static int Open( vlc_object_t *p_this )
  68. {
  69.     demux_t     *p_demux = (demux_t*)p_this;
  70.     demux_sys_t *p_sys;
  71.     uint8_t     *p_peek;
  72.     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
  73.     {
  74.         msg_Err( p_demux, "cannot peek" );
  75.         return VLC_EGENERIC;
  76.     }
  77.     if( p_peek[0] != 0 || p_peek[1] != 0 ||
  78.         p_peek[2] != 1 || p_peek[3] < 0xb9 )
  79.     {
  80.         msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
  81.                   "continuing anyway" );
  82.     }
  83.     /* Fill p_demux field */
  84.     p_demux->pf_demux = Demux;
  85.     p_demux->pf_control = Control;
  86.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  87.     /* Init p_sys */
  88.     p_sys->i_mux_rate = 0;
  89.     p_sys->i_scr      = -1;
  90.     ps_psm_init( &p_sys->psm );
  91.     ps_track_init( p_sys->tk );
  92.     /* TODO prescanning of ES */
  93.     return VLC_SUCCESS;
  94. }
  95. static int OpenAlt( vlc_object_t *p_this )
  96. {
  97.     demux_t *p_demux = (demux_t*)p_this;
  98.     uint8_t *p_peek;
  99.     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
  100.     {
  101.         msg_Err( p_demux, "cannot peek" );
  102.         return VLC_EGENERIC;
  103.     }
  104.     if( p_peek[0] != 0 || p_peek[1] != 0 ||
  105.         p_peek[2] != 1 || p_peek[3] < 0xb9 )
  106.     {
  107.         if( !p_demux->b_force ) return VLC_EGENERIC;
  108.     }
  109.     return Open( p_this );
  110. }
  111. /*****************************************************************************
  112.  * Close
  113.  *****************************************************************************/
  114. static void Close( vlc_object_t *p_this )
  115. {
  116.     demux_t     *p_demux = (demux_t*)p_this;
  117.     demux_sys_t *p_sys = p_demux->p_sys;
  118.     int i;
  119.     for( i = 0; i < PS_TK_COUNT; i++ )
  120.     {
  121.         ps_track_t *tk = &p_sys->tk[i];
  122.         if( tk->b_seen )
  123.         {
  124.             es_format_Clean( &tk->fmt );
  125.             if( tk->es ) es_out_Del( p_demux->out, tk->es );
  126.         }
  127.     }
  128.     ps_psm_destroy( &p_sys->psm );
  129.     free( p_sys );
  130. }
  131. /*****************************************************************************
  132.  * Demux:
  133.  *****************************************************************************/
  134. static int Demux( demux_t *p_demux )
  135. {
  136.     demux_sys_t *p_sys = p_demux->p_sys;
  137.     int i_ret, i_id, i_mux_rate;
  138.     uint32_t i_code;
  139.     block_t *p_pkt;
  140.     i_ret = ps_pkt_resynch( p_demux->s, &i_code );
  141.     if( i_ret < 0 )
  142.     {
  143.         return 0;
  144.     }
  145.     else if( i_ret == 0 )
  146.     {
  147.         msg_Warn( p_demux, "garbage at input" );
  148.         return 1;
  149.     }
  150.     if( ( p_pkt = ps_pkt_read( p_demux->s, i_code ) ) == NULL )
  151.     {
  152.         return 0;
  153.     }
  154.     switch( i_code )
  155.     {
  156.     case 0x1b9:
  157.         block_Release( p_pkt );
  158.         break;
  159.     case 0x1ba:
  160.         if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_scr, &i_mux_rate ) )
  161.         {
  162.             /* done later on to work around bad vcd/svcd streams */
  163.             /* es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr ); */
  164.             if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
  165.         }
  166.         block_Release( p_pkt );
  167.         break;
  168.     case 0x1bb:
  169.         if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) )
  170.         {
  171.             int i;
  172.             for( i = 0; i < PS_TK_COUNT; i++ )
  173.             {
  174.                 ps_track_t *tk = &p_sys->tk[i];
  175.                 if( tk->b_seen && !tk->es && tk->fmt.i_cat != UNKNOWN_ES )
  176.                 {
  177.                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
  178.                 }
  179.             }
  180.         }
  181.         block_Release( p_pkt );
  182.         break;
  183.     case 0x1bc:
  184.         /* msg_Dbg( p_demux, "received PSM"); */
  185.         ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out );
  186.         block_Release( p_pkt );
  187.         break;
  188.     default:
  189.         if( (i_id = ps_pkt_id( p_pkt )) >= 0xc0 )
  190.         {
  191.             ps_track_t *tk = &p_sys->tk[PS_ID_TO_TK(i_id)];
  192.             if( !tk->b_seen )
  193.             {
  194.                 if( !ps_track_fill( tk, &p_sys->psm, i_id ) )
  195.                 {
  196.                     tk->es = es_out_Add( p_demux->out, &tk->fmt );
  197.                 }
  198.                 tk->b_seen = VLC_TRUE;
  199.             }
  200.             /* The popular VCD/SVCD subtitling WinSubMux does not
  201.              * renumber the SCRs when merging subtitles into the PES */
  202.             if( tk->b_seen &&
  203.                 ( tk->fmt.i_codec == VLC_FOURCC('o','g','t',' ') ||
  204.                   tk->fmt.i_codec == VLC_FOURCC('c','v','d',' ') ) )
  205.             {
  206.                 p_sys->i_scr = -1;
  207.             }
  208.             if( p_sys->i_scr > 0 )
  209.                 es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_scr );
  210.             p_sys->i_scr = -1;
  211.             if( tk->b_seen && tk->es &&
  212.                 !ps_pkt_parse_pes( p_pkt, tk->i_skip ) )
  213.             {
  214.                 es_out_Send( p_demux->out, tk->es, p_pkt );
  215.             }
  216.             else
  217.             {
  218.                 block_Release( p_pkt );
  219.             }
  220.         }
  221.         else
  222.         {
  223.             block_Release( p_pkt );
  224.         }
  225.         break;
  226.     }
  227.     return 1;
  228. }
  229. /*****************************************************************************
  230.  * Control:
  231.  *****************************************************************************/
  232. static int Control( demux_t *p_demux, int i_query, va_list args )
  233. {
  234.     demux_sys_t *p_sys = p_demux->p_sys;
  235.     double f, *pf;
  236.     int64_t i64, *pi64;
  237.     switch( i_query )
  238.     {
  239.         case DEMUX_GET_POSITION:
  240.             pf = (double*) va_arg( args, double* );
  241.             i64 = stream_Size( p_demux->s );
  242.             if( i64 > 0 )
  243.             {
  244.                 *pf = (double)stream_Tell( p_demux->s ) / (double)i64;
  245.             }
  246.             else
  247.             {
  248.                 *pf = 0.0;
  249.             }
  250.             return VLC_SUCCESS;
  251.         case DEMUX_SET_POSITION:
  252.             f = (double) va_arg( args, double );
  253.             i64 = stream_Size( p_demux->s );
  254.             es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  255.             return stream_Seek( p_demux->s, (int64_t)(i64 * f) );
  256.         case DEMUX_GET_TIME:
  257.             pi64 = (int64_t*)va_arg( args, int64_t * );
  258.             if( p_sys->i_mux_rate > 0 )
  259.             {
  260.                 *pi64 = (int64_t)1000000 * ( stream_Tell( p_demux->s ) / 50 ) /
  261.                     p_sys->i_mux_rate;
  262.                 return VLC_SUCCESS;
  263.             }
  264.             *pi64 = 0;
  265.             return VLC_EGENERIC;
  266.         case DEMUX_GET_LENGTH:
  267.             pi64 = (int64_t*)va_arg( args, int64_t * );
  268.             if( p_sys->i_mux_rate > 0 )
  269.             {
  270.                 *pi64 = (int64_t)1000000 * ( stream_Size( p_demux->s ) / 50 ) /
  271.                     p_sys->i_mux_rate;
  272.                 return VLC_SUCCESS;
  273.             }
  274.             *pi64 = 0;
  275.             return VLC_EGENERIC;
  276.         case DEMUX_SET_TIME:
  277.         case DEMUX_GET_FPS:
  278.         default:
  279.             return VLC_EGENERIC;
  280.     }
  281. }
  282. /*****************************************************************************
  283.  * Divers:
  284.  *****************************************************************************/
  285. /* PSResynch: resynch on a system starcode
  286.  *  It doesn't skip more than 512 bytes
  287.  *  -1 -> error, 0 -> not synch, 1 -> ok
  288.  */
  289. static int ps_pkt_resynch( stream_t *s, uint32_t *pi_code )
  290. {
  291.     uint8_t *p_peek;
  292.     int     i_peek;
  293.     int     i_skip;
  294.     if( stream_Peek( s, &p_peek, 4 ) < 4 )
  295.     {
  296.         return -1;
  297.     }
  298.     if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
  299.         p_peek[3] >= 0xb9 )
  300.     {
  301.         *pi_code = 0x100 | p_peek[3];
  302.         return 1;
  303.     }
  304.     if( ( i_peek = stream_Peek( s, &p_peek, 512 ) ) < 4 )
  305.     {
  306.         return -1;
  307.     }
  308.     i_skip = 0;
  309.     for( ;; )
  310.     {
  311.         if( i_peek < 4 )
  312.         {
  313.             break;
  314.         }
  315.         if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 &&
  316.             p_peek[3] >= 0xb9 )
  317.         {
  318.             *pi_code = 0x100 | p_peek[3];
  319.             return stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1;
  320.         }
  321.         p_peek++;
  322.         i_peek--;
  323.         i_skip++;
  324.     }
  325.     return stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1;
  326. }
  327. static block_t *ps_pkt_read( stream_t *s, uint32_t i_code )
  328. {
  329.     uint8_t *p_peek;
  330.     int      i_peek = stream_Peek( s, &p_peek, 14 );
  331.     int      i_size = ps_pkt_size( p_peek, i_peek );
  332.     if( i_size <= 6 && p_peek[3] > 0xba )
  333.     {
  334.         /* Special case, search the next start code */
  335.         i_size = 6;
  336.         for( ;; )
  337.         {
  338.             i_peek = stream_Peek( s, &p_peek, i_size + 1024 );
  339.             if( i_peek <= i_size + 4 )
  340.             {
  341.                 return NULL;
  342.             }
  343.             while( i_size <= i_peek - 4 )
  344.             {
  345.                 if( p_peek[i_size] == 0x00 && p_peek[i_size+1] == 0x00 &&
  346.                     p_peek[i_size+2] == 0x01 && p_peek[i_size+3] >= 0xb9 )
  347.                 {
  348.                     return stream_Block( s, i_size );
  349.                 }
  350.                 i_size++;
  351.             }
  352.         }
  353.     }
  354.     else
  355.     {
  356.         /* Normal case */
  357.         return  stream_Block( s, i_size );
  358.     }
  359.     return NULL;
  360. }