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

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * flac.c : FLAC demux module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2003 VideoLAN
  5.  * $Id: flac.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. /*****************************************************************************
  30.  * Module descriptor
  31.  *****************************************************************************/
  32. static int  Open  ( vlc_object_t * );
  33. static void Close ( vlc_object_t * );
  34. vlc_module_begin();
  35.     set_description( _("FLAC demuxer") );
  36.     set_capability( "demux2", 155 );
  37.     set_callbacks( Open, Close );
  38.     add_shortcut( "flac" );
  39. vlc_module_end();
  40. /*****************************************************************************
  41.  * Local prototypes
  42.  *****************************************************************************/
  43. static int Demux  ( demux_t * );
  44. static int Control( demux_t *, int, va_list );
  45. struct demux_sys_t
  46. {
  47.     vlc_bool_t  b_start;
  48.     es_out_id_t *p_es;
  49.     /* Packetizer */
  50.     decoder_t *p_packetizer;
  51. };
  52. #define STREAMINFO_SIZE 38
  53. #define FLAC_PACKET_SIZE 16384
  54. /*****************************************************************************
  55.  * Open: initializes ES structures
  56.  *****************************************************************************/
  57. static int Open( vlc_object_t * p_this )
  58. {
  59.     demux_t     *p_demux = (demux_t*)p_this;
  60.     demux_sys_t *p_sys;
  61.     int          i_peek;
  62.     byte_t      *p_peek;
  63.     es_format_t  fmt;
  64.     /* Have a peep at the show. */
  65.     if( stream_Peek( p_demux->s, &p_peek, 4 ) < 4 )
  66.     {
  67.         /* Stream shorter than 4 bytes... */
  68.         msg_Err( p_demux, "cannot peek()" );
  69.         return VLC_EGENERIC;
  70.     }
  71.     if( p_peek[0]!='f' || p_peek[1]!='L' || p_peek[2]!='a' || p_peek[3]!='C' )
  72.     {
  73.         if( strncmp( p_demux->psz_demux, "flac", 4 ) )
  74.         {
  75.             msg_Warn( p_demux, "flac module discarded (no startcode)" );
  76.             return VLC_EGENERIC;
  77.         }
  78.         /* User forced */
  79.         msg_Err( p_demux, "this doesn't look like a flac stream, "
  80.                  "continuing anyway" );
  81.     }
  82.     p_demux->pf_demux   = Demux;
  83.     p_demux->pf_control = Control;
  84.     p_demux->p_sys      = p_sys = malloc( sizeof( demux_sys_t ) );
  85.     es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'f', 'l', 'a', 'c' ) );
  86.     p_sys->b_start = VLC_TRUE;
  87.     /* We need to read and store the STREAMINFO metadata */
  88.     i_peek = stream_Peek( p_demux->s, &p_peek, 8 );
  89.     if( p_peek[4] & 0x7F )
  90.     {
  91.         msg_Err( p_demux, "this isn't a STREAMINFO metadata block" );
  92.         return VLC_EGENERIC;
  93.     }
  94.     if( ((p_peek[5]<<16)+(p_peek[6]<<8)+p_peek[7]) != (STREAMINFO_SIZE - 4) )
  95.     {
  96.         msg_Err( p_demux, "invalid size for a STREAMINFO metadata block" );
  97.         return VLC_EGENERIC;
  98.     }
  99.     /*
  100.      * Load the FLAC packetizer
  101.      */
  102.     p_sys->p_packetizer = vlc_object_create( p_demux, VLC_OBJECT_DECODER );
  103.     p_sys->p_packetizer->pf_decode_audio = 0;
  104.     p_sys->p_packetizer->pf_decode_video = 0;
  105.     p_sys->p_packetizer->pf_decode_sub = 0;
  106.     p_sys->p_packetizer->pf_packetize = 0;
  107.     /* Initialization of decoder structure */
  108.     es_format_Init( &p_sys->p_packetizer->fmt_in, AUDIO_ES,
  109.                     VLC_FOURCC( 'f', 'l', 'a', 'c' ) );
  110.     /* Store STREAMINFO for the decoder and packetizer */
  111.     p_sys->p_packetizer->fmt_in.i_extra = fmt.i_extra = STREAMINFO_SIZE + 4;
  112.     p_sys->p_packetizer->fmt_in.p_extra = malloc( STREAMINFO_SIZE + 4 );
  113.     stream_Read( p_demux->s, p_sys->p_packetizer->fmt_in.p_extra,
  114.                  STREAMINFO_SIZE + 4 );
  115.     /* Fake this as the last metadata block */
  116.     ((uint8_t*)p_sys->p_packetizer->fmt_in.p_extra)[4] |= 0x80;
  117.     fmt.p_extra = malloc( STREAMINFO_SIZE + 4 );
  118.     memcpy( fmt.p_extra, p_sys->p_packetizer->fmt_in.p_extra,
  119.             STREAMINFO_SIZE + 4 );
  120.     p_sys->p_packetizer->p_module =
  121.         module_Need( p_sys->p_packetizer, "packetizer", NULL, 0 );
  122.     if( !p_sys->p_packetizer->p_module )
  123.     {
  124.         if( p_sys->p_packetizer->fmt_in.p_extra )
  125.             free( p_sys->p_packetizer->fmt_in.p_extra );
  126.         vlc_object_destroy( p_sys->p_packetizer );
  127.         msg_Err( p_demux, "cannot find flac packetizer" );
  128.         return VLC_EGENERIC;
  129.     }
  130.     p_sys->p_es = es_out_Add( p_demux->out, &fmt );
  131.     return VLC_SUCCESS;
  132. }
  133. /*****************************************************************************
  134.  * Close: frees unused data
  135.  *****************************************************************************/
  136. static void Close( vlc_object_t * p_this )
  137. {
  138.     demux_t     *p_demux = (demux_t*)p_this;
  139.     demux_sys_t *p_sys = p_demux->p_sys;
  140.     /* Unneed module */
  141.     module_Unneed( p_sys->p_packetizer, p_sys->p_packetizer->p_module );
  142.     if( p_sys->p_packetizer->fmt_in.p_extra )
  143.         free( p_sys->p_packetizer->fmt_in.p_extra );
  144.     /* Delete the decoder */
  145.     vlc_object_destroy( p_sys->p_packetizer );
  146.     free( p_sys );
  147. }
  148. /*****************************************************************************
  149.  * Demux: reads and demuxes data packets
  150.  *****************************************************************************
  151.  * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
  152.  *****************************************************************************/
  153. static int Demux( demux_t *p_demux )
  154. {
  155.     demux_sys_t *p_sys = p_demux->p_sys;
  156.     block_t     *p_block_in, *p_block_out;
  157.     if( !( p_block_in = stream_Block( p_demux->s, FLAC_PACKET_SIZE ) ) )
  158.     {
  159.         return 0;
  160.     }
  161.     if( p_sys->b_start )
  162.     {
  163.         p_block_in->i_pts = p_block_in->i_dts = 1;
  164.         p_sys->b_start = VLC_FALSE;
  165.     }
  166.     else
  167.     {
  168.         p_block_in->i_pts = p_block_in->i_dts = 0;
  169.     }
  170.     while( (p_block_out = p_sys->p_packetizer->pf_packetize(
  171.                 p_sys->p_packetizer, &p_block_in )) )
  172.     {
  173.         while( p_block_out )
  174.         {
  175.             block_t *p_next = p_block_out->p_next;
  176.             /* set PCR */
  177.             es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_block_out->i_dts );
  178.             es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
  179.             p_block_out = p_next;
  180.         }
  181.     }
  182.     return 1;
  183. }
  184. /*****************************************************************************
  185.  * Control:
  186.  *****************************************************************************/
  187. static int Control( demux_t *p_demux, int i_query, va_list args )
  188. {
  189.     /* demux_sys_t *p_sys  = p_demux->p_sys; */
  190.     /* FIXME bitrate */
  191.     if( i_query == DEMUX_SET_TIME )
  192.         return VLC_EGENERIC;
  193.     else
  194.         return demux2_vaControlHelper( p_demux->s,
  195.                                        0, -1,
  196.                                        8*0, 1, i_query, args );
  197. }