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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * a52.c : raw A/52 stream input module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2001 VideoLAN
  5.  * $Id: a52.c 7231 2004-04-01 23:19:30Z fenrir $
  6.  *
  7.  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  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 <vlc/vlc.h>
  27. #include <vlc/input.h>
  28. #include <vlc_codec.h>
  29. #ifdef HAVE_UNISTD_H
  30. #   include <unistd.h>
  31. #endif
  32. /*****************************************************************************
  33.  * Module descriptor
  34.  *****************************************************************************/
  35. static int  Open  ( vlc_object_t * );
  36. static void Close ( vlc_object_t * );
  37. vlc_module_begin();
  38.     set_description( _("Raw A/52 demuxer") );
  39.     set_capability( "demux2", 145 );
  40.     set_callbacks( Open, Close );
  41.     add_shortcut( "a52" );
  42. vlc_module_end();
  43. /*****************************************************************************
  44.  * Local prototypes
  45.  *****************************************************************************/
  46. static int Demux  ( demux_t * );
  47. static int Control( demux_t *, int, va_list );
  48. struct demux_sys_t
  49. {
  50.     vlc_bool_t  b_start;
  51.     es_out_id_t *p_es;
  52.     /* Packetizer */
  53.     decoder_t *p_packetizer;
  54.     int i_mux_rate;
  55.     vlc_bool_t b_big_endian;
  56. };
  57. static int CheckSync( uint8_t *p_peek, vlc_bool_t *p_big_endian );
  58. #define PCM_FRAME_SIZE (1536 * 4)
  59. #define A52_PACKET_SIZE (4 * PCM_FRAME_SIZE)
  60. #define A52_MAX_HEADER_SIZE 10
  61. /*****************************************************************************
  62.  * Open: initializes ES structures
  63.  *****************************************************************************/
  64. static int Open( vlc_object_t * p_this )
  65. {
  66.     demux_t     *p_demux = (demux_t*)p_this;
  67.     demux_sys_t *p_sys;
  68.     byte_t      *p_peek;
  69.     int         i_peek = 0;
  70.     vlc_bool_t  b_big_endian;
  71.     /* Check if we are dealing with a WAV file */
  72.     if( stream_Peek( p_demux->s, &p_peek, 12 ) == 12 &&
  73.         !strncmp( p_peek, "RIFF", 4 ) && !strncmp( &p_peek[8], "WAVE", 4 ) )
  74.     {
  75.         int i_size;
  76.         /* Skip the wave header */
  77.         i_peek = 12 + 8;
  78.         while( stream_Peek( p_demux->s, &p_peek, i_peek ) == i_peek &&
  79.                strncmp( p_peek + i_peek - 8, "data", 4 ) )
  80.         {
  81.             i_peek += GetDWLE( p_peek + i_peek - 4 ) + 8;
  82.         }
  83.         /* TODO: should check wave format and sample_rate */
  84.         /* Some A52 wav files don't begin with a sync code so we do a more
  85.          * extensive search */
  86.         i_size = stream_Peek( p_demux->s, &p_peek, i_peek + A52_PACKET_SIZE * 2);
  87.         i_size -= (PCM_FRAME_SIZE + A52_MAX_HEADER_SIZE);
  88.         while( i_peek < i_size )
  89.         {
  90.             if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
  91.                 /* The data is stored in 16 bits words */
  92.                 i_peek += 2;
  93.             else
  94.             {
  95.                 /* Check following sync code */
  96.                 if( CheckSync( p_peek + i_peek + PCM_FRAME_SIZE,
  97.                                &b_big_endian ) != VLC_SUCCESS )
  98.                 {
  99.                     i_peek += 2;
  100.                     continue;
  101.                 }
  102.                 break;
  103.             }
  104.         }
  105.     }
  106.     /* Have a peep at the show. */
  107.     if( stream_Peek( p_demux->s, &p_peek, i_peek + A52_MAX_HEADER_SIZE * 2 ) <
  108.         i_peek + A52_MAX_HEADER_SIZE * 2 )
  109.     {
  110.         /* Stream too short */
  111.         msg_Warn( p_demux, "cannot peek()" );
  112.         return VLC_EGENERIC;
  113.     }
  114.     if( CheckSync( p_peek + i_peek, &b_big_endian ) != VLC_SUCCESS )
  115.     {
  116.         if( strncmp( p_demux->psz_demux, "a52", 3 ) )
  117.         {
  118.             return VLC_EGENERIC;
  119.         }
  120.         /* User forced */
  121.         msg_Err( p_demux, "this doesn't look like a A52 audio stream, "
  122.                  "continuing anyway" );
  123.     }
  124.     /* Fill p_demux fields */
  125.     p_demux->pf_demux = Demux;
  126.     p_demux->pf_control = Control;
  127.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  128.     p_sys->b_start = VLC_TRUE;
  129.     p_sys->i_mux_rate = 0;
  130.     p_sys->b_big_endian = b_big_endian;
  131.     /*
  132.      * Load the A52 packetizer
  133.      */
  134.     p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER );
  135.     p_sys->p_packetizer->pf_decode_audio = 0;
  136.     p_sys->p_packetizer->pf_decode_video = 0;
  137.     p_sys->p_packetizer->pf_decode_sub = 0;
  138.     p_sys->p_packetizer->pf_packetize = 0;
  139.     /* Initialization of decoder structure */
  140.     es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES,
  141.                     VLC_FOURCC( 'a', '5', '2', ' ' ) );
  142.     p_sys->p_packetizer->p_module =
  143.         module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
  144.     if( !p_sys->p_packetizer->p_module )
  145.     {
  146.         msg_Err( p_demux, "cannot find A52 packetizer" );
  147.         return VLC_EGENERIC;
  148.     }
  149.     /* Create one program */
  150.     p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_in );
  151.     return VLC_SUCCESS;
  152. }
  153. /*****************************************************************************
  154.  * Close: frees unused data
  155.  *****************************************************************************/
  156. static void Close( vlc_object_t * p_this )
  157. {
  158.     demux_t        *p_demux = (demux_t*)p_this;
  159.     demux_sys_t    *p_sys = p_demux->p_sys;
  160.     /* Unneed module */
  161.     module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
  162.     /* Delete the decoder */
  163.     vlc_object_destroy( p_sys->p_packetizer );
  164.     free( p_sys );
  165. }
  166. /*****************************************************************************
  167.  * Demux: reads and demuxes data packets
  168.  *****************************************************************************
  169.  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  170.  *****************************************************************************/
  171. static int Demux( demux_t *p_demux )
  172. {
  173.     demux_sys_t *p_sys = p_demux->p_sys;
  174.     block_t     *p_block_in, *p_block_out;
  175.      /* Align stream */
  176.     int64_t i_pos = stream_Tell( p_demux->s );
  177.     if( i_pos % 2 ) stream_Read( p_demux->s, NULL, 1 );
  178.     if( !( p_block_in = stream_Block( p_demux->s, A52_PACKET_SIZE ) ) )
  179.     {
  180.         return 0;
  181.     }
  182.     if( !p_sys->b_big_endian && p_block_in->i_buffer )
  183.     {
  184.         /* Convert to big endian */
  185. #ifdef HAVE_SWAB
  186.         swab(p_block_in->p_buffer, p_block_in->p_buffer, p_block_in->i_buffer);
  187. #else
  188.         int i;
  189.         byte_t *p_tmp, tmp;
  190.         p_tmp = p_block_in->p_buffer;
  191.         for( i = p_block_in->i_buffer / 2 ; i-- ; )
  192.         {
  193.             tmp = p_tmp[0];
  194.             p_tmp[0] = p_tmp[1];
  195.             p_tmp[1] = tmp;
  196.             p_tmp += 2;
  197.         }
  198. #endif
  199.     }
  200.     if( p_sys->b_start )
  201.         p_block_in->i_pts = p_block_in->i_dts = 1;
  202.     else
  203.         p_block_in->i_pts = p_block_in->i_dts = 0;
  204.     while( (p_block_out = p_sys->p_packetizer->pf_packetize(
  205.                 p_sys->p_packetizer, &p_block_in )) )
  206.     {
  207.         p_sys->b_start = VLC_FALSE;
  208.         while( p_block_out )
  209.         {
  210.             block_t *p_next = p_block_out->p_next;
  211.             /* We assume a constant bitrate */
  212.             if( p_block_out->i_length )
  213.             {
  214.                 p_sys->i_mux_rate =
  215.                     p_block_out->i_buffer * I64C(1000000)/p_block_out->i_length;
  216.             }
  217.             /* set PCR */
  218.             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
  219.             es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
  220.             p_block_out = p_next;
  221.         }
  222.     }
  223.     return 1;
  224. }
  225. /*****************************************************************************
  226.  * Control:
  227.  *****************************************************************************/
  228. static int Control( demux_t *p_demux, int i_query, va_list args )
  229. {
  230.     demux_sys_t *p_sys  = p_demux->p_sys;
  231.     if( i_query == DEMUX_SET_TIME )
  232.         return VLC_EGENERIC;
  233.     else
  234.         return demux2_vaControlHelper( p_demux->s,
  235.                                        0, -1,
  236.                                        8*p_sys->i_mux_rate, 1, i_query, args );
  237. }
  238. /*****************************************************************************
  239.  * CheckSync: Check if buffer starts with an A52 sync code
  240.  *****************************************************************************/
  241. static int CheckSync( uint8_t *p_peek, vlc_bool_t *p_big_endian )
  242. {
  243.     /* Little endian version of the bitstream */
  244.     if( p_peek[0] == 0x77 && p_peek[1] == 0x0b &&
  245.         p_peek[4] < 0x60 /* bsid < 12 */ )
  246.     {
  247.         *p_big_endian = VLC_FALSE;
  248.         return VLC_SUCCESS;
  249.     }
  250.     /* Big endian version of the bitstream */
  251.     else if( p_peek[0] == 0x0b && p_peek[1] == 0x77 &&
  252.              p_peek[5] < 0x60 /* bsid < 12 */ )
  253.     {
  254.         *p_big_endian = VLC_TRUE;
  255.         return VLC_SUCCESS;
  256.     }
  257.     return VLC_EGENERIC;
  258. }