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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * ps.h: Program Stream demuxer helper
  3.  *****************************************************************************
  4.  * Copyright (C) 2004 VideoLAN
  5.  * $Id: ps.h 8799 2004-09-26 12:06:50Z 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. #define PS_TK_COUNT (512 - 0xc0)
  24. #define PS_ID_TO_TK( id ) ((id) <= 0xff ? (id) - 0xc0 : 
  25.                                           ((id)&0xff) + (256 - 0xc0))
  26. typedef struct ps_psm_t ps_psm_t;
  27. static inline int ps_id_to_type( ps_psm_t *, int );
  28. typedef struct
  29. {
  30.     vlc_bool_t  b_seen;
  31.     int         i_skip;
  32.     int         i_id;
  33.     es_out_id_t *es;
  34.     es_format_t fmt;
  35. } ps_track_t;
  36. /* Init a set of track */
  37. static inline void ps_track_init( ps_track_t tk[PS_TK_COUNT] )
  38. {
  39.     int i;
  40.     for( i = 0; i < PS_TK_COUNT; i++ )
  41.     {
  42.         tk[i].b_seen = VLC_FALSE;
  43.         tk[i].i_skip = 0;
  44.         tk[i].i_id   = 0;
  45.         tk[i].es     = NULL;
  46.         es_format_Init( &tk[i].fmt, UNKNOWN_ES, 0 );
  47.     }
  48. }
  49. /* From id fill i_skip and es_format_t */
  50. static inline int ps_track_fill( ps_track_t *tk, ps_psm_t *p_psm, int i_id )
  51. {
  52.     tk->i_skip = 0;
  53.     tk->i_id = i_id;
  54.     if( ( i_id&0xff00 ) == 0xbd00 )
  55.     {
  56.         if( ( i_id&0xf8 ) == 0x88 )
  57.         {
  58.             es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('d','t','s',' ') );
  59.             tk->i_skip = 4;
  60.         }
  61.         else if( ( i_id&0xf0 ) == 0x80 )
  62.         {
  63.             es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('a','5','2',' ') );
  64.             tk->i_skip = 4;
  65.         }
  66.         else if( ( i_id&0xe0 ) == 0x20 )
  67.         {
  68.             es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('s','p','u',' ') );
  69.             tk->i_skip = 1;
  70.         }
  71.         else if( ( i_id&0xf0 ) == 0xa0 )
  72.         {
  73.             es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('l','p','c','m') );
  74.             tk->i_skip = 1;
  75.         }
  76.         else if( ( i_id&0xff ) == 0x70 )
  77.         {
  78.             es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('o','g','t',' ') );
  79.         }
  80.         else if( ( i_id&0xfc ) == 0x00 )
  81.         {
  82.             es_format_Init( &tk->fmt, SPU_ES, VLC_FOURCC('c','v','d',' ') );
  83.         }
  84.         else
  85.         {
  86.             es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
  87.             return VLC_EGENERIC;
  88.         }
  89.     }
  90.     else
  91.     {
  92.         int i_type = ps_id_to_type( p_psm , i_id );
  93.         es_format_Init( &tk->fmt, UNKNOWN_ES, 0 );
  94.         if( (i_id&0xf0) == 0xe0 && i_type == 0x10 )
  95.         {
  96.             es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('m','p','4','v') );
  97.         }
  98.         else if( (i_id&0xf0) == 0xe0 && i_type == 0x02 )
  99.         {
  100.             es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('m','p','g','v') );
  101.         }
  102.         else if( ( i_id&0xe0 ) == 0xc0 && i_type == 0x03 )
  103.         {
  104.             es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('m','p','g','a') );
  105.         }
  106.         if( tk->fmt.i_cat == UNKNOWN_ES && ( i_id&0xf0 ) == 0xe0 )
  107.         {
  108.             es_format_Init( &tk->fmt, VIDEO_ES, VLC_FOURCC('m','p','g','v') );
  109.         }
  110.         else if( tk->fmt.i_cat == UNKNOWN_ES && ( i_id&0xe0 ) == 0xc0 )
  111.         {
  112.             es_format_Init( &tk->fmt, AUDIO_ES, VLC_FOURCC('m','p','g','a') );
  113.         }
  114.         else if( tk->fmt.i_cat == UNKNOWN_ES ) return VLC_EGENERIC;
  115.     }
  116.     /* PES packets usually contain truncated frames */
  117.     tk->fmt.b_packetized = VLC_FALSE;
  118.     return VLC_SUCCESS;
  119. }
  120. /* return the id of a PES (should be valid) */
  121. static inline int ps_pkt_id( block_t *p_pkt )
  122. {
  123.     if( p_pkt->p_buffer[3] == 0xbd &&
  124.         p_pkt->i_buffer >= 9 &&
  125.         p_pkt->i_buffer >= 9 + p_pkt->p_buffer[8] )
  126.     {
  127.         return 0xbd00 | p_pkt->p_buffer[9+p_pkt->p_buffer[8]];
  128.     }
  129.     return p_pkt->p_buffer[3];
  130. }
  131. /* return the size of the next packet
  132.  * XXX you need to give him at least 14 bytes (and it need to start as a
  133.  * valid packet) */
  134. static inline int ps_pkt_size( uint8_t *p, int i_peek )
  135. {
  136.     if( p[3] == 0xb9 && i_peek >= 4 )
  137.     {
  138.         return 4;
  139.     }
  140.     else if( p[3] == 0xba )
  141.     {
  142.         if( (p[4] >> 6) == 0x01 && i_peek >= 14 )
  143.         {
  144.             return 14 + (p[13]&0x07);
  145.         }
  146.         else if( (p[4] >> 4) == 0x02 && i_peek >= 12 )
  147.         {
  148.             return 12;
  149.         }
  150.         return -1;
  151.     }
  152.     else if( i_peek >= 6 )
  153.     {
  154.         return 6 + ((p[4]<<8) | p[5] );
  155.     }
  156.     return -1;
  157. }
  158. /* parse a PACK PES */
  159. static inline int ps_pkt_parse_pack( block_t *p_pkt, int64_t *pi_scr,
  160.                                      int *pi_mux_rate )
  161. {
  162.     uint8_t *p = p_pkt->p_buffer;
  163.     if( p_pkt->i_buffer >= 14 && (p[4] >> 6) == 0x01 )
  164.     {
  165.         *pi_scr =((((int64_t)p[4]&0x38) << 27 )|
  166.                   (((int64_t)p[4]&0x03) << 28 )|
  167.                    ((int64_t)p[5] << 20 )|
  168.                   (((int64_t)p[6]&0xf8) << 12 )|
  169.                   (((int64_t)p[6]&0x03) << 13 )|
  170.                    ((int64_t)p[7] << 5 )|
  171.                    ((int64_t)p[8] >> 3 )) * 100 / 9;
  172.         *pi_mux_rate = ( p[10] << 14 )|( p[11] << 6 )|( p[12] >> 2);
  173.     }
  174.     else if( p_pkt->i_buffer >= 12 && (p[4] >> 4) == 0x02 )
  175.     {
  176.         *pi_scr =((((int64_t)p[4]&0x0e) << 29 )|
  177.                    ((int64_t)p[5] << 22 )|
  178.                   (((int64_t)p[6]&0xfe) << 14 )|
  179.                    ((int64_t)p[7] <<  7 )|
  180.                    ((int64_t)p[8] >> 1 )) * 100 / 9;
  181.         *pi_mux_rate = ( ( p[9]&0x7f )<< 15 )|( p[10] << 7 )|( p[11] >> 1);
  182.     }
  183.     else
  184.     {
  185.         return VLC_EGENERIC;
  186.     }
  187.     return VLC_SUCCESS;
  188. }
  189. /* Parse a SYSTEM PES */
  190. static inline int ps_pkt_parse_system( block_t *p_pkt, ps_psm_t *p_psm,
  191.                                        ps_track_t tk[PS_TK_COUNT] )
  192. {
  193.     uint8_t *p = &p_pkt->p_buffer[6 + 3 + 1 + 1 + 1];
  194.     /* System header is not useable if it references private streams (0xBD)
  195.      * or 'all audio streams' (0xB8) or 'all video streams' (0xB9) */
  196.     while( p < &p_pkt->p_buffer[p_pkt->i_buffer] )
  197.     {
  198.         int i_id = p[0];
  199.         /* fprintf( stderr, "   SYSTEM_START_CODEEE: id=0x%xn", p[0] ); */
  200.         if( p[0] >= 0xBC || p[0] == 0xB8 || p[0] == 0xB9 ) p += 2;
  201.         p++;
  202.         if( i_id >= 0xc0 )
  203.         {
  204.             int i_tk = PS_ID_TO_TK( i_id );
  205.             if( !tk[i_tk].b_seen )
  206.             {
  207.                 if( !ps_track_fill( &tk[i_tk], p_psm, i_id ) )
  208.                 {
  209.                     tk[i_tk].b_seen = VLC_TRUE;
  210.                 }
  211.             }
  212.         }
  213.     }
  214.     return VLC_SUCCESS;
  215. }
  216. /* Parse a PES (and skip i_skip_extra in the payload) */
  217. static inline int ps_pkt_parse_pes( block_t *p_pes, int i_skip_extra )
  218. {
  219.     uint8_t header[30];
  220.     int     i_skip  = 0;
  221.     memcpy( header, p_pes->p_buffer, __MIN( p_pes->i_buffer, 30 ) );
  222.     switch( header[3] )
  223.     {
  224.         case 0xBC:  /* Program stream map */
  225.         case 0xBE:  /* Padding */
  226.         case 0xBF:  /* Private stream 2 */
  227.         case 0xB0:  /* ECM */
  228.         case 0xB1:  /* EMM */
  229.         case 0xFF:  /* Program stream directory */
  230.         case 0xF2:  /* DSMCC stream */
  231.         case 0xF8:  /* ITU-T H.222.1 type E stream */
  232.             i_skip = 6;
  233.             break;
  234.         default:
  235.             if( ( header[6]&0xC0 ) == 0x80 )
  236.             {
  237.                 /* mpeg2 PES */
  238.                 i_skip = header[8] + 9;
  239.                 if( header[7]&0x80 )    /* has pts */
  240.                 {
  241.                     p_pes->i_pts = ((mtime_t)(header[ 9]&0x0e ) << 29)|
  242.                                     (mtime_t)(header[10] << 22)|
  243.                                    ((mtime_t)(header[11]&0xfe) << 14)|
  244.                                     (mtime_t)(header[12] << 7)|
  245.                                     (mtime_t)(header[13] >> 1);
  246.                     if( header[7]&0x40 )    /* has dts */
  247.                     {
  248.                          p_pes->i_dts = ((mtime_t)(header[14]&0x0e ) << 29)|
  249.                                          (mtime_t)(header[15] << 22)|
  250.                                         ((mtime_t)(header[16]&0xfe) << 14)|
  251.                                          (mtime_t)(header[17] << 7)|
  252.                                          (mtime_t)(header[18] >> 1);
  253.                     }
  254.                 }
  255.             }
  256.             else
  257.             {
  258.                 i_skip = 6;
  259.                 while( i_skip < 23 && header[i_skip] == 0xff )
  260.                 {
  261.                     i_skip++;
  262.                 }
  263.                 if( i_skip == 23 )
  264.                 {
  265.                     /* msg_Err( p_demux, "too much MPEG-1 stuffing" ); */
  266.                     return VLC_EGENERIC;
  267.                 }
  268.                 if( ( header[i_skip] & 0xC0 ) == 0x40 )
  269.                 {
  270.                     i_skip += 2;
  271.                 }
  272.                 if(  header[i_skip]&0x20 )
  273.                 {
  274.                      p_pes->i_pts = ((mtime_t)(header[i_skip]&0x0e ) << 29)|
  275.                                      (mtime_t)(header[i_skip+1] << 22)|
  276.                                     ((mtime_t)(header[i_skip+2]&0xfe) << 14)|
  277.                                      (mtime_t)(header[i_skip+3] << 7)|
  278.                                      (mtime_t)(header[i_skip+4] >> 1);
  279.                     if( header[i_skip]&0x10 )    /* has dts */
  280.                     {
  281.                          p_pes->i_dts = ((mtime_t)(header[i_skip+5]&0x0e ) << 29)|
  282.                                          (mtime_t)(header[i_skip+6] << 22)|
  283.                                         ((mtime_t)(header[i_skip+7]&0xfe) << 14)|
  284.                                          (mtime_t)(header[i_skip+8] << 7)|
  285.                                          (mtime_t)(header[i_skip+9] >> 1);
  286.                          i_skip += 10;
  287.                     }
  288.                     else
  289.                     {
  290.                         i_skip += 5;
  291.                     }
  292.                 }
  293.                 else
  294.                 {
  295.                     i_skip += 1;
  296.                 }
  297.             }
  298.     }
  299.     i_skip += i_skip_extra;
  300.     if( p_pes->i_buffer <= i_skip )
  301.     {
  302.         return VLC_EGENERIC;
  303.     }
  304.     p_pes->p_buffer += i_skip;
  305.     p_pes->i_buffer -= i_skip;
  306.     p_pes->i_dts = 100 * p_pes->i_dts / 9;
  307.     p_pes->i_pts = 100 * p_pes->i_pts / 9;
  308.     return VLC_SUCCESS;
  309. }
  310. /* Program stream map handling */
  311. typedef struct p_es_t
  312. {
  313.     int i_type;
  314.     int i_id;
  315.     int i_descriptor;
  316.     uint8_t *p_descriptor;
  317. } ps_es_t;
  318. struct ps_psm_t
  319. {
  320.     int i_version;
  321.     int     i_es;
  322.     ps_es_t **es;
  323. };
  324. static inline int ps_id_to_type( ps_psm_t *p_psm, int i_id )
  325. {
  326.     int i;
  327.     for( i = 0; p_psm && i < p_psm->i_es; i++ )
  328.     {
  329.         if( p_psm->es[i]->i_id == i_id ) return p_psm->es[i]->i_type;     
  330.     }
  331.     return 0;
  332. }
  333. static inline void ps_psm_init( ps_psm_t *p_psm )
  334. {
  335.     p_psm->i_version = 0xFFFF;
  336.     p_psm->i_es = 0;
  337.     p_psm->es = 0;
  338. }
  339. static inline void ps_psm_destroy( ps_psm_t *p_psm )
  340. {
  341.     while( p_psm->i_es-- )
  342.     {
  343.         if( p_psm->es[p_psm->i_es]->i_descriptor )
  344.             free( p_psm->es[p_psm->i_es]->p_descriptor );
  345.         free( p_psm->es[p_psm->i_es] );
  346.     }
  347.     if( p_psm->es ) free( p_psm->es );
  348.     p_psm->es = 0;
  349.     p_psm->i_es = 0;
  350. }
  351. static inline int ps_psm_fill( ps_psm_t *p_psm, block_t *p_pkt,
  352.                                ps_track_t tk[PS_TK_COUNT], es_out_t *out )
  353. {
  354.     int i_buffer = p_pkt->i_buffer;
  355.     uint8_t *p_buffer = p_pkt->p_buffer;
  356.     int i_length, i_version, i_info_length, i_esm_length, i_es_base, i;
  357.     if( !p_psm || p_buffer[3] != 0xbc ) return VLC_EGENERIC;
  358.     i_length = (uint16_t)(p_buffer[4] << 8) + p_buffer[5];
  359.     if( i_length > i_buffer ) return VLC_EGENERIC;
  360.     //i_current_next_indicator = (p_buffer[6] && 0x01);
  361.     i_version = (p_buffer[6] && 0xf8);
  362.     if( p_psm->i_version == i_version ) return VLC_EGENERIC;
  363.     ps_psm_destroy( p_psm );
  364.     i_info_length = (uint16_t)(p_buffer[8] << 8) + p_buffer[9];
  365.     if( i_info_length + 10 > i_length ) return VLC_EGENERIC;
  366.     /* Elementary stream map */
  367.     i_esm_length = (uint16_t)(p_buffer[ 10 + i_info_length ] << 8) +
  368.         p_buffer[ 11 + i_info_length];
  369.     i_es_base = 12 + i_info_length;
  370.     while( i_es_base + 4 < i_length )
  371.     {
  372.         ps_es_t es;
  373.         es.i_type = p_buffer[ i_es_base  ];
  374.         es.i_id = p_buffer[ i_es_base + 1 ];
  375.         i_info_length = (uint16_t)(p_buffer[ i_es_base + 2 ] << 8) +
  376.             p_buffer[ i_es_base + 3 ];
  377.         if( i_es_base + 4 + i_info_length > i_length ) break;
  378.         es.p_descriptor = 0;
  379.         es.i_descriptor = i_info_length;
  380.         if( i_info_length > 0 )
  381.         {
  382.             es.p_descriptor = malloc( i_info_length );
  383.             memcpy( es.p_descriptor, p_buffer + i_es_base + 4, i_info_length);
  384.         }
  385.         p_psm->es = realloc( p_psm->es, sizeof(ps_es_t *) * (p_psm->i_es+1) );
  386.         p_psm->es[p_psm->i_es] = malloc( sizeof(ps_es_t) );
  387.         *p_psm->es[p_psm->i_es++] = es;
  388.         i_es_base += 4 + i_info_length; 
  389.     }
  390.     /* TODO: CRC */
  391.     p_psm->i_version = i_version;
  392.     /* Check/Modify our existing tracks */
  393.     for( i = 0; i < PS_TK_COUNT; i++ )
  394.     {
  395.         ps_track_t tk_tmp;
  396.         if( !tk[i].b_seen || !tk[i].es ) continue;
  397.         if( ps_track_fill( &tk_tmp, p_psm, tk[i].i_id ) != VLC_SUCCESS )
  398.             continue;
  399.         if( tk_tmp.fmt.i_codec == tk[i].fmt.i_codec ) continue;
  400.         es_out_Del( out, tk[i].es );
  401.         tk[i] = tk_tmp;
  402.         tk[i].b_seen = VLC_TRUE;
  403.         tk[i].es = es_out_Add( out, &tk[i].fmt );
  404.     }
  405.     return VLC_SUCCESS;
  406. }