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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ps.c: MPEG PS (ISO/IEC 13818-1) / MPEG SYSTEM (ISO/IEC 1172-1)
  3.  *       multiplexer module for vlc
  4.  *****************************************************************************
  5.  * Copyright (C) 2001, 2002 VideoLAN
  6.  * $Id: ps.c 9067 2004-10-27 14:59:24Z gbazin $
  7.  *
  8.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  9.  *          Eric Petit <titer@videolan.org>
  10.  *          Gildas Bazin <gbazin@videolan.org>
  11.  *
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2 of the License, or
  15.  * (at your option) any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; if not, write to the Free Software
  24.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  25.  *****************************************************************************/
  26. /*****************************************************************************
  27.  * Preamble
  28.  *****************************************************************************/
  29. #include <stdlib.h>
  30. #include <vlc/vlc.h>
  31. #include <vlc/input.h>
  32. #include <vlc/sout.h>
  33. #include "codecs.h"
  34. #include "bits.h"
  35. #include "pes.h"
  36. /*****************************************************************************
  37.  * Module descriptor
  38.  *****************************************************************************/
  39. #define DTS_TEXT N_("DTS delay (ms)")
  40. #define DTS_LONGTEXT N_("This option will delay the DTS (decoding time " 
  41.   "stamps) and PTS (presentation timestamps) of the data in the " 
  42.   "stream, compared to the SCRs. This allows for some buffering inside " 
  43.   "the client decoder.")
  44. static int     Open   ( vlc_object_t * );
  45. static void    Close  ( vlc_object_t * );
  46. #define SOUT_CFG_PREFIX "sout-ps-"
  47. vlc_module_begin();
  48.     set_description( _("PS muxer") );
  49.     set_capability( "sout mux", 50 );
  50.     add_shortcut( "ps" );
  51.     add_shortcut( "mpeg1" );
  52.     add_shortcut( "dvd" );
  53.     set_callbacks( Open, Close );
  54.     add_integer( SOUT_CFG_PREFIX "dts-delay", 200, NULL, DTS_TEXT,
  55.                  DTS_LONGTEXT, VLC_TRUE );
  56. vlc_module_end();
  57. /*****************************************************************************
  58.  * Exported prototypes
  59.  *****************************************************************************/
  60. static int Control  ( sout_mux_t *, int, va_list );
  61. static int AddStream( sout_mux_t *, sout_input_t * );
  62. static int DelStream( sout_mux_t *, sout_input_t * );
  63. static int Mux      ( sout_mux_t * );
  64. /*****************************************************************************
  65.  * Local prototypes
  66.  *****************************************************************************/
  67. static int  MuxGetStream        ( sout_mux_t *, int *, mtime_t * );
  68. static void MuxWritePackHeader  ( sout_mux_t *, block_t **, mtime_t );
  69. static void MuxWriteSystemHeader( sout_mux_t *, block_t **, mtime_t );
  70. static void StreamIdInit        ( vlc_bool_t *id, int i_range );
  71. static int  StreamIdGet         ( vlc_bool_t *id, int i_id_min, int i_id_max );
  72. static void StreamIdRelease     ( vlc_bool_t *id, int i_id_min, int i_id );
  73. typedef struct ps_stream_s
  74. {
  75.     int             i_stream_id;
  76. } ps_stream_t;
  77. struct sout_mux_sys_t
  78. {
  79.     /* Which id are unused */
  80.     vlc_bool_t  stream_id_mpga[16]; /* 0xc0 -> 0xcf */
  81.     vlc_bool_t  stream_id_mpgv[16]; /* 0xe0 -> 0xef */
  82.     vlc_bool_t  stream_id_a52[8];   /* 0x80 -> 0x87 <- FIXME I'm not sure */
  83.     vlc_bool_t  stream_id_spu[32];  /* 0x20 -> 0x3f */
  84.     vlc_bool_t  stream_id_dts[8];   /* 0x88 -> 0x8f */
  85.     vlc_bool_t  stream_id_lpcm[16]; /* 0xa0 -> 0xaf */
  86.     int i_audio_bound;
  87.     int i_video_bound;
  88.     int i_pes_count;
  89.     int i_system_header;
  90.     int i_dts_delay;
  91.     vlc_bool_t b_mpeg2;
  92. };
  93. static const char *ppsz_sout_options[] = {
  94.     "dts-delay", NULL
  95. };
  96. /*****************************************************************************
  97.  * Open:
  98.  *****************************************************************************/
  99. static int Open( vlc_object_t *p_this )
  100. {
  101.     sout_mux_t *p_mux = (sout_mux_t*)p_this;
  102.     sout_mux_sys_t *p_sys;
  103.     vlc_value_t val;
  104.     msg_Info( p_mux, "Open" );
  105.     sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
  106.     p_mux->pf_control   = Control;
  107.     p_mux->pf_addstream = AddStream;
  108.     p_mux->pf_delstream = DelStream;
  109.     p_mux->pf_mux       = Mux;
  110.     p_mux->p_sys        = p_sys = malloc( sizeof( sout_mux_sys_t ) );
  111.     /* Init free stream id */
  112.     StreamIdInit( p_sys->stream_id_a52,  8  );
  113.     StreamIdInit( p_sys->stream_id_dts,  8  );
  114.     StreamIdInit( p_sys->stream_id_mpga, 16 );
  115.     StreamIdInit( p_sys->stream_id_mpgv, 16 );
  116.     StreamIdInit( p_sys->stream_id_lpcm, 16 );
  117.     StreamIdInit( p_sys->stream_id_spu,  32 );
  118.     p_sys->i_audio_bound   = 0;
  119.     p_sys->i_video_bound   = 0;
  120.     p_sys->i_system_header = 0;
  121.     p_sys->i_pes_count     = 0;
  122.     p_sys->b_mpeg2 = !(p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mpeg1" ));
  123.     var_Get( p_mux, SOUT_CFG_PREFIX "dts-delay", &val );
  124.     p_sys->i_dts_delay = (int64_t)val.i_int * 1000;
  125.     return VLC_SUCCESS;
  126. }
  127. /*****************************************************************************
  128.  * Close:
  129.  *****************************************************************************/
  130. static void Close( vlc_object_t * p_this )
  131. {
  132.     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
  133.     sout_mux_sys_t  *p_sys = p_mux->p_sys;
  134.     block_t   *p_end;
  135.     msg_Info( p_mux, "Close" );
  136.     p_end = block_New( p_mux, 4 );
  137.     p_end->p_buffer[0] = 0x00;
  138.     p_end->p_buffer[1] = 0x00;
  139.     p_end->p_buffer[2] = 0x01;
  140.     p_end->p_buffer[3] = 0xb9;
  141.     sout_AccessOutWrite( p_mux->p_access, p_end );
  142.     free( p_sys );
  143. }
  144. /*****************************************************************************
  145.  * Control:
  146.  *****************************************************************************/
  147. static int Control( sout_mux_t *p_mux, int i_query, va_list args )
  148. {
  149.     vlc_bool_t *pb_bool;
  150.     char **ppsz;
  151.    switch( i_query )
  152.    {
  153.        case MUX_CAN_ADD_STREAM_WHILE_MUXING:
  154.            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
  155.            *pb_bool = VLC_TRUE;
  156.            return VLC_SUCCESS;
  157.        case MUX_GET_ADD_STREAM_WAIT:
  158.            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
  159.            *pb_bool = VLC_FALSE;
  160.            return VLC_SUCCESS;
  161.        case MUX_GET_MIME:
  162.            ppsz = (char**)va_arg( args, char ** );
  163.            *ppsz = strdup( "video/mpeg" );
  164.            return VLC_SUCCESS;
  165.         default:
  166.             return VLC_EGENERIC;
  167.    }
  168. }
  169. /*****************************************************************************
  170.  * AddStream:
  171.  *****************************************************************************/
  172. static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
  173. {
  174.     sout_mux_sys_t  *p_sys = p_mux->p_sys;
  175.     ps_stream_t *p_stream;
  176.     msg_Dbg( p_mux, "adding input codec=%4.4s",
  177.              (char*)&p_input->p_fmt->i_codec );
  178.     p_input->p_sys = p_stream = malloc( sizeof( ps_stream_t ) );
  179.     /* Init this new stream */
  180.     switch( p_input->p_fmt->i_codec )
  181.     {
  182.         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
  183.             p_stream->i_stream_id =
  184.                 StreamIdGet( p_sys->stream_id_mpgv, 0xe0, 0xef );
  185.             break;
  186.         case VLC_FOURCC( 'l', 'p', 'c', 'm' ):
  187.             p_stream->i_stream_id =
  188.                 0xbd00 | StreamIdGet( p_sys->stream_id_lpcm, 0xa0, 0xaf );
  189.             break;
  190.         case VLC_FOURCC( 'd', 't', 's', ' ' ):
  191.             p_stream->i_stream_id =
  192.                 0xbd00 | StreamIdGet( p_sys->stream_id_dts, 0x88, 0x8f );
  193.             break;
  194.         case VLC_FOURCC( 'a', '5', '2', ' ' ):
  195.             p_stream->i_stream_id =
  196.                 0xbd00 | StreamIdGet( p_sys->stream_id_a52, 0x80, 0x87 );
  197.             break;
  198.         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
  199.             p_stream->i_stream_id =
  200.                 StreamIdGet( p_sys->stream_id_mpga, 0xc0, 0xcf );
  201.             break;
  202.         case VLC_FOURCC( 's', 'p', 'u', ' ' ):
  203.             p_stream->i_stream_id =
  204.                 0xbd00 | StreamIdGet( p_sys->stream_id_spu, 0x20, 0x3f );
  205.             break;
  206.         default:
  207.             goto error;
  208.     }
  209.     if( p_stream->i_stream_id < 0 )
  210.     {
  211.         goto error;
  212.     }
  213.     if( p_input->p_fmt->i_cat == AUDIO_ES )
  214.     {
  215.         p_sys->i_audio_bound++;
  216.     }
  217.     else if( p_input->p_fmt->i_cat == VIDEO_ES )
  218.     {
  219.         p_sys->i_video_bound++;
  220.     }
  221.     return VLC_SUCCESS;
  222. error:
  223.     free( p_stream );
  224.     return VLC_EGENERIC;
  225. }
  226. /*****************************************************************************
  227.  * DelStream:
  228.  *****************************************************************************/
  229. static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
  230. {
  231.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  232.     ps_stream_t *p_stream =(ps_stream_t*)p_input->p_sys;
  233.     msg_Dbg( p_mux, "removing input" );
  234.     switch( p_input->p_fmt->i_codec )
  235.     {
  236.         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
  237.             StreamIdRelease( p_sys->stream_id_mpgv, 0xe0,
  238.                              p_stream->i_stream_id );
  239.             break;
  240.         case VLC_FOURCC( 'l', 'p', 'c', 'm' ):
  241.             StreamIdRelease( p_sys->stream_id_lpcm, 0xa0,
  242.                              p_stream->i_stream_id&0xff );
  243.             break;
  244.         case VLC_FOURCC( 'd', 't', 's', ' ' ):
  245.             StreamIdRelease( p_sys->stream_id_dts, 0x88,
  246.                              p_stream->i_stream_id&0xff );
  247.             break;
  248.         case VLC_FOURCC( 'a', '5', '2', ' ' ):
  249.             StreamIdRelease( p_sys->stream_id_a52, 0x80,
  250.                              p_stream->i_stream_id&0xff );
  251.             break;
  252.         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
  253.             StreamIdRelease( p_sys->stream_id_mpga, 0xc0,
  254.                              p_stream->i_stream_id  );
  255.             break;
  256.         case VLC_FOURCC( 's', 'p', 'u', ' ' ):
  257.             StreamIdRelease( p_sys->stream_id_spu, 0x20,
  258.                              p_stream->i_stream_id&0xff );
  259.             break;
  260.         default:
  261.             /* Never reached */
  262.             break;
  263.     }
  264.     if( p_input->p_fmt->i_cat == AUDIO_ES )
  265.     {
  266.         p_sys->i_audio_bound--;
  267.     }
  268.     else if( p_input->p_fmt->i_cat == VIDEO_ES )
  269.     {
  270.         p_sys->i_video_bound--;
  271.     }
  272.     free( p_stream );
  273.     return VLC_SUCCESS;
  274. }
  275. /*****************************************************************************
  276.  * Mux: Call each time there is new data for at least one stream
  277.  *****************************************************************************/
  278. static int Mux( sout_mux_t *p_mux )
  279. {
  280.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  281.     for( ;; )
  282.     {
  283.         sout_input_t *p_input;
  284.         ps_stream_t *p_stream;
  285.         block_t *p_ps, *p_data;
  286.         mtime_t        i_dts;
  287.         int            i_stream;
  288.         /* Choose which stream to mux */
  289.         if( MuxGetStream( p_mux, &i_stream, &i_dts ) )
  290.         {
  291.             return VLC_SUCCESS;
  292.         }
  293.         p_input  = p_mux->pp_inputs[i_stream];
  294.         p_stream = (ps_stream_t*)p_input->p_sys;
  295.         p_ps     = NULL;
  296.         /* Write regulary PackHeader */
  297.         if( p_sys->i_pes_count % 30 == 0)
  298.         {
  299.             MuxWritePackHeader( p_mux, &p_ps, i_dts );
  300.         }
  301.         /* Write regulary SystemHeader */
  302.         if( p_sys->i_pes_count % 300 == 0 )
  303.         {
  304.             block_t *p_pk;
  305.             MuxWriteSystemHeader( p_mux, &p_ps, i_dts );
  306.             /* For MPEG1 streaming, set HEADER flag */
  307.             for( p_pk = p_ps; p_pk != NULL; p_pk = p_pk->p_next )
  308.             {
  309.                 p_pk->i_flags |= BLOCK_FLAG_HEADER;
  310.             }
  311.         }
  312.         /* Get and mux a packet */
  313.         p_data = block_FifoGet( p_input->p_fifo );
  314.         E_( EStoPES )( p_mux->p_sout, &p_data, p_data,
  315.                        p_input->p_fmt, p_stream->i_stream_id,
  316.                        p_mux->p_sys->b_mpeg2, 0, 0 );
  317.         block_ChainAppend( &p_ps, p_data );
  318.         sout_AccessOutWrite( p_mux->p_access, p_ps );
  319.         /* Increase counter */
  320.         p_sys->i_pes_count++;
  321.     }
  322.     return VLC_SUCCESS;
  323. }
  324. /*****************************************************************************
  325.  *
  326.  *****************************************************************************/
  327. static void StreamIdInit( vlc_bool_t *id, int i_range )
  328. {
  329.     int i;
  330.     for( i = 0; i < i_range; i++ )
  331.     {
  332.         id[i] = VLC_TRUE;
  333.     }
  334. }
  335. static int StreamIdGet( vlc_bool_t *id, int i_id_min, int i_id_max )
  336. {
  337.     int i;
  338.     for( i = 0; i <= i_id_max - i_id_min; i++ )
  339.     {
  340.         if( id[i] )
  341.         {
  342.             id[i] = VLC_FALSE;
  343.             return i_id_min + i;
  344.         }
  345.     }
  346.     return -1;
  347. }
  348. static void StreamIdRelease( vlc_bool_t *id, int i_id_min, int i_id )
  349. {
  350.     id[i_id - i_id_min] = VLC_TRUE;
  351. }
  352. static void MuxWritePackHeader( sout_mux_t *p_mux, block_t **p_buf,
  353.                                 mtime_t i_dts )
  354. {
  355.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  356.     bits_buffer_t bits;
  357.     block_t *p_hdr;
  358.     mtime_t i_scr;
  359.     i_scr = (i_dts - p_sys->i_dts_delay) * 9 / 100;
  360.     p_hdr = block_New( p_mux, 18 );
  361.     p_hdr->i_pts = p_hdr->i_dts = i_dts;
  362.     bits_initwrite( &bits, 14, p_hdr->p_buffer );
  363.     bits_write( &bits, 32, 0x01ba );
  364.     if( p_sys->b_mpeg2 )
  365.     {
  366.         bits_write( &bits, 2, 0x01 );
  367.     }
  368.     else
  369.     {
  370.         bits_write( &bits, 4, 0x02 );
  371.     }
  372.     bits_write( &bits, 3, ( i_scr >> 30 )&0x07 );
  373.     bits_write( &bits, 1,  1 );
  374.     bits_write( &bits, 15, ( i_scr >> 15 )&0x7fff );
  375.     bits_write( &bits, 1,  1 );
  376.     bits_write( &bits, 15, i_scr&0x7fff );
  377.     bits_write( &bits, 1,  1 );
  378.     if( p_sys->b_mpeg2 )
  379.     {
  380.         bits_write( &bits, 9,  0 ); // src extention
  381.     }
  382.     bits_write( &bits, 1,  1 );
  383.     bits_write( &bits, 22,  1000/8/50); // FIXME mux rate
  384.     bits_write( &bits, 1,  1 );
  385.     if( p_sys->b_mpeg2 )
  386.     {
  387.         bits_write( &bits, 1,  1 );
  388.         bits_write( &bits, 5,  0x1f );  // FIXME reserved
  389.         bits_write( &bits, 3,  0 );     // stuffing bytes
  390.     }
  391.     p_hdr->i_buffer = p_sys->b_mpeg2 ? 14: 12;
  392.     block_ChainAppend( p_buf, p_hdr );
  393. }
  394. static void MuxWriteSystemHeader( sout_mux_t *p_mux, block_t **p_buf,
  395.                                   mtime_t i_dts )
  396. {
  397.     sout_mux_sys_t  *p_sys = p_mux->p_sys;
  398.     block_t   *p_hdr;
  399.     bits_buffer_t   bits;
  400.     vlc_bool_t      b_private;
  401.     int             i_nb_private, i_nb_stream;
  402.     int i;
  403.     /* Count the number of private stream */
  404.     for( i = 0, i_nb_private = 0; i < p_mux->i_nb_inputs; i++ )
  405.     {
  406.         ps_stream_t *p_stream;
  407.         p_stream = (ps_stream_t*)p_mux->pp_inputs[i]->p_sys;
  408.         if( ( p_stream->i_stream_id&0xff00 ) == 0xbd00 )
  409.         {
  410.             i_nb_private++;
  411.         }
  412.     }
  413.     /* Private stream are declared only one time */
  414.     i_nb_stream = p_mux->i_nb_inputs -
  415.         ( i_nb_private > 0 ? i_nb_private - 1 : 0 );
  416.     p_hdr = block_New( p_mux, 12 + i_nb_stream * 3 );
  417.     p_hdr->i_dts = p_hdr->i_pts = i_dts;
  418.     bits_initwrite( &bits, 12 + i_nb_stream * 3, p_hdr->p_buffer );
  419.     bits_write( &bits, 32, 0x01bb );
  420.     bits_write( &bits, 16, 12 - 6 + i_nb_stream * 3 );
  421.     bits_write( &bits, 1,  1 );
  422.     bits_write( &bits, 22, 0 ); // FIXME rate bound
  423.     bits_write( &bits, 1,  1 );
  424.     bits_write( &bits, 6,  p_sys->i_audio_bound );
  425.     bits_write( &bits, 1,  0 ); // fixed flag
  426.     bits_write( &bits, 1,  0 ); // CSPS flag
  427.     bits_write( &bits, 1,  0 ); // system audio lock flag
  428.     bits_write( &bits, 1,  0 ); // system video lock flag
  429.     bits_write( &bits, 1,  1 ); // marker bit
  430.     bits_write( &bits, 5,  p_sys->i_video_bound );
  431.     bits_write( &bits, 1,  1 ); // packet rate restriction flag (1 for mpeg1)
  432.     bits_write( &bits, 7,  0xff ); // reserved bits
  433.     /* stream_id table */
  434.     for( i = 0, b_private = VLC_FALSE; i < p_mux->i_nb_inputs; i++ )
  435.     {
  436.         sout_input_t *p_input;
  437.         ps_stream_t *p_stream;
  438.         p_input = p_mux->pp_inputs[i];
  439.         p_stream = (ps_stream_t *)p_input->p_sys;
  440.         if( ( p_stream->i_stream_id&0xff00 ) == 0xbd00 )
  441.         {
  442.             if( b_private )
  443.             {
  444.                 continue;
  445.             }
  446.             b_private = VLC_TRUE;
  447.             /* Write stream id */
  448.             bits_write( &bits, 8, 0xbd );
  449.         }
  450.         else
  451.         {
  452.             /* Write stream id */
  453.             bits_write( &bits, 8, p_stream->i_stream_id&0xff );
  454.         }
  455.         bits_write( &bits, 2, 0x03 );
  456.         if( p_input->p_fmt->i_cat == AUDIO_ES )
  457.         {
  458.             bits_write( &bits, 1, 0 );
  459.             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 / 128 );
  460.         }
  461.         else if( p_input->p_fmt->i_cat == VIDEO_ES )
  462.         {
  463.             bits_write( &bits, 1, 1 );
  464.             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 / 1024);
  465.         }
  466.         else
  467.         {
  468.             /* FIXME */
  469.             bits_write( &bits, 1, 0 );
  470.             bits_write( &bits, 13, /* stream->max_buffer_size */ 0 );
  471.         }
  472.     }
  473.     block_ChainAppend( p_buf, p_hdr );
  474. }
  475. /*
  476.  * Find stream to be muxed.
  477.  */
  478. static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
  479. {
  480.     mtime_t i_dts;
  481.     int     i_stream;
  482.     int     i;
  483.     for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
  484.     {
  485.         sout_input_t *p_input = p_mux->pp_inputs[i];
  486.         block_t *p_data;
  487.         if( p_input->p_fifo->i_depth <= 0 )
  488.         {
  489.             if( p_input->p_fmt->i_cat == AUDIO_ES ||
  490.                 p_input->p_fmt->i_cat == VIDEO_ES )
  491.             {
  492.                 /* We need that audio+video fifo contain at least 1 packet */
  493.                 return VLC_EGENERIC;
  494.             }
  495.             /* SPU */
  496.             continue;
  497.         }
  498.         p_data = block_FifoShow( p_input->p_fifo );
  499.         if( i_stream == -1 || p_data->i_dts < i_dts )
  500.         {
  501.             i_stream = i;
  502.             i_dts    = p_data->i_dts;
  503.         }
  504.     }
  505.     *pi_stream = i_stream;
  506.     *pi_dts = i_dts;
  507.     return VLC_SUCCESS;
  508. }