]> git.sesse.net Git - vlc/commitdiff
* configure.ac, modules/codec/Modules.am, modules/codec/speex.c: new speex decoder...
authorGildas Bazin <gbazin@videolan.org>
Wed, 22 Oct 2003 17:12:31 +0000 (17:12 +0000)
committerGildas Bazin <gbazin@videolan.org>
Wed, 22 Oct 2003 17:12:31 +0000 (17:12 +0000)
* modules/demux/ogg.c: added support for speex to the Ogg demuxer.
* modules/mux/ogg.c: added support for speex to the Ogg muxer.
* src/misc/variables.c: when creating choices object variables with inheritance enabled, automatically add the inherited value to the list of choices.
* modules/access/udp.c: use an object variable and inheritance for "udp-caching".
* src/input/input.c: disable the hack for filenames with colons on win32 because filenames can't contain colons.

configure.ac
modules/access/udp.c
modules/codec/Modules.am
modules/codec/speex.c [new file with mode: 0755]
modules/demux/ogg.c
modules/mux/ogg.c
src/input/input.c
src/misc/variables.c

index e37bf617feb8e8c668aacf7eb376c7a90010a210..57fb56391601795edebf8f16610a1e488646598b 100644 (file)
@@ -1,5 +1,5 @@
 dnl Autoconf settings for vlc
-dnl $Id: configure.ac,v 1.89 2003/10/21 17:31:36 gbazin Exp $
+dnl $Id: configure.ac,v 1.90 2003/10/22 17:12:30 gbazin Exp $
 
 AC_INIT(vlc,0.6.3-cvs)
 
@@ -2035,6 +2035,18 @@ then
    ],[])
 fi
 
+dnl
+dnl  Speex plugin
+dnl
+AC_ARG_ENABLE(speex,
+  [  --enable-speex         Speex decoder support (default enabled)])
+if test "${enable_speex}" != "no"
+then
+  AC_CHECK_HEADERS(speex.h, [
+    AX_ADD_PLUGINS([speex])
+    AX_ADD_LDFLAGS([speex],[-lspeex]) ],[])
+fi
+
 dnl
 dnl  tarkin decoder plugin
 dnl
index 231c1ff29dd7c880a5a2473d59f9d69fc86ea6ad..692a9cf1dda4f25710a574d0a419ac60b44e4d54 100644 (file)
@@ -2,7 +2,7 @@
  * udp.c: raw UDP & RTP access plug-in
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: udp.c,v 1.22 2003/08/24 16:59:35 hartman Exp $
+ * $Id: udp.c,v 1.23 2003/10/22 17:12:30 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *          Tristan Leteurtre <tooney@via.ecp.fr>
@@ -106,6 +106,7 @@ static int Open( vlc_object_t *p_this )
     char *              psz_bind_port = "";
     int                 i_bind_port = 0, i_server_port = 0;
     network_socket_t    socket_desc;
+    vlc_value_t         val;
 
     if( config_GetInt( p_input, "ipv4" ) )
     {
@@ -272,7 +273,7 @@ static int Open( vlc_object_t *p_this )
         return( -1 );
     }
     module_Unneed( p_input, p_network );
-    
+
     p_access_data = malloc( sizeof(input_socket_t) );
     p_input->p_access_data = (access_sys_t *)p_access_data;
 
@@ -286,7 +287,9 @@ static int Open( vlc_object_t *p_this )
     p_input->i_mtu = socket_desc.i_mtu;
 
     /* Update default_pts to a suitable value for udp access */
-    p_input->i_pts_delay = config_GetInt( p_input, "udp-caching" ) * 1000;
+    var_Create( p_input, "udp-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+    var_Get( p_input, "udp-caching", &val );
+    p_input->i_pts_delay = val.i_int * 1000;
 
     return( 0 );
 }
index db2856e01507e2788a019837901ced96f9d1e063..404b4595c9e0d347f6f9aa05dba60d1d706566fa 100644 (file)
@@ -8,6 +8,7 @@ SOURCES_vorbis = vorbis.c
 SOURCES_tarkin = tarkin.c
 SOURCES_theora = theora.c
 SOURCES_tremor = vorbis.c
+SOURCES_speex = speex.c
 SOURCES_dv = dv.c
 SOURCES_xvid = xvid.c
 SOURCES_adpcm = adpcm.c
diff --git a/modules/codec/speex.c b/modules/codec/speex.c
new file mode 100755 (executable)
index 0000000..4c35300
--- /dev/null
@@ -0,0 +1,579 @@
+/*****************************************************************************
+ * speex.c: speex decoder module making use of libspeex.
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: speex.c,v 1.1 2003/10/22 17:12:30 gbazin Exp $
+ *
+ * Authors: Gildas Bazin <gbazin@netcourrier.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h>                                      /* malloc(), free() */
+#include <string.h>                                    /* memcpy(), memset() */
+
+#include <vlc/vlc.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+#include <vlc/input.h>
+#include <vlc/sout.h>
+#include <input_ext-dec.h>
+
+#include <vlc/input.h>
+
+#include <ogg/ogg.h>
+#include <speex.h>
+#include "speex_header.h"
+#include "speex_stereo.h"
+#include "speex_callbacks.h"
+
+/*****************************************************************************
+ * decoder_sys_t : speex decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+    /* Module mode */
+    vlc_bool_t b_packetizer;
+
+    /*
+     * Input properties
+     */
+    int i_headers;
+
+    /*
+     * Speex properties
+     */
+    SpeexBits bits;
+    SpeexHeader *p_header;
+    SpeexStereoState stereo;
+    void *p_state;
+
+    /*
+     * Output properties
+     */
+    aout_instance_t        *p_aout;
+    aout_input_t           *p_aout_input;
+    audio_sample_format_t   aout_format;
+
+    /*
+     * Packetizer output properties
+     */
+    sout_packetizer_input_t *p_sout_input;
+    sout_format_t           sout_format;
+
+    /*
+     * Common properties
+     */
+    audio_date_t          end_date;
+
+};
+
+static int pi_channels_maps[6] =
+{
+    0,
+    AOUT_CHAN_CENTER,   AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
+    AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
+     | AOUT_CHAN_REARRIGHT,
+    AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
+     | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+};
+
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+static int OpenDecoder   ( vlc_object_t * );
+static int OpenPacketizer( vlc_object_t * );
+
+static int InitDecoder   ( decoder_t * );
+static int RunDecoder    ( decoder_t *, block_t * );
+static int EndDecoder    ( decoder_t * );
+
+static int ProcessHeader ( decoder_t *, ogg_packet * );
+static int ProcessPacket ( decoder_t *, ogg_packet *, mtime_t );
+static int DecodePacket  ( decoder_t *, ogg_packet * );
+static int SendPacket    ( decoder_t *, ogg_packet * );
+
+static void ParseSpeexComments( decoder_t *, ogg_packet * );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+    set_description( _("Speex audio decoder") );
+    set_capability( "decoder", 100 );
+    set_callbacks( OpenDecoder, NULL );
+
+    add_submodule();
+    set_description( _("Speex audio packetizer") );
+    set_capability( "packetizer", 100 );
+    set_callbacks( OpenPacketizer, NULL );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+
+    if( p_dec->p_fifo->i_fourcc != VLC_FOURCC('s','p','x',' ') )
+    {
+        return VLC_EGENERIC;
+    }
+
+    p_dec->pf_init = InitDecoder;
+    p_dec->pf_decode = RunDecoder;
+    p_dec->pf_end = EndDecoder;
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+    {
+        msg_Err( p_dec, "out of memory" );
+        return VLC_EGENERIC;
+    }
+    p_dec->p_sys->b_packetizer = VLC_FALSE;
+
+    return VLC_SUCCESS;
+}
+
+static int OpenPacketizer( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+
+    int i_ret = OpenDecoder( p_this );
+
+    if( i_ret == VLC_SUCCESS ) p_dec->p_sys->b_packetizer = VLC_TRUE;
+
+    return i_ret;
+}
+
+/*****************************************************************************
+ * InitDecoder: Initalize the decoder
+ *****************************************************************************/
+static int InitDecoder( decoder_t *p_dec )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    aout_DateSet( &p_sys->end_date, 0 );
+
+    p_sys->p_aout = NULL;
+    p_sys->p_aout_input = NULL;
+    p_sys->aout_format.i_format = VLC_FOURCC('s','p','x',' ');
+
+    p_sys->p_sout_input = NULL;
+    p_sys->sout_format.i_cat = AUDIO_ES;
+    p_sys->sout_format.i_fourcc = VLC_FOURCC( 's', 'p', 'x', ' ' );
+    p_sys->sout_format.i_block_align = 0;
+    p_sys->sout_format.i_bitrate     = 0;
+    p_sys->sout_format.i_extra_data  = 0;
+    p_sys->sout_format.p_extra_data  = NULL;
+
+    p_sys->i_headers = 0;
+    p_sys->p_state = NULL;
+    p_sys->p_header = NULL;
+
+    return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * RunDecoder: the whole thing
+ ****************************************************************************
+ * This function must be fed with ogg packets.
+ ****************************************************************************/
+static int RunDecoder( decoder_t *p_dec, block_t *p_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    ogg_packet oggpacket;
+    int i_ret;
+
+    /* Block to Ogg packet */
+    oggpacket.packet = p_block->p_buffer;
+    oggpacket.bytes = p_block->i_buffer;
+    oggpacket.granulepos = -1;
+    oggpacket.b_o_s = 0;
+    oggpacket.e_o_s = 0;
+    oggpacket.packetno = 0;
+
+    if( p_sys->i_headers == 0 )
+    {
+        /* Take care of the initial Speex header */
+        if( ProcessHeader( p_dec, &oggpacket ) != VLC_SUCCESS )
+        {
+            msg_Err( p_dec, "Initial Speex header is corrupted" );
+            return VLC_EGENERIC;
+        }
+
+        p_sys->i_headers++;
+
+        if( p_sys->b_packetizer )
+        {
+            i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
+            block_Release( p_block );
+            return i_ret;
+        }
+        else
+        {
+            block_Release( p_block );
+            return VLC_SUCCESS;
+        }
+    }
+
+    if( p_sys->i_headers == 1 )
+    {
+        /* The next packet in order is the comments header */
+        ParseSpeexComments( p_dec, &oggpacket );
+        p_sys->i_headers++;
+
+        if( p_sys->b_packetizer )
+        {
+            i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
+            block_Release( p_block );
+            return i_ret;
+        }
+        else
+        {
+            block_Release( p_block );
+            return VLC_SUCCESS;
+        }
+    }
+
+    if( p_sys->i_headers < p_sys->p_header->extra_headers + 2 )
+    {
+        /* Skip them for now */
+        p_sys->i_headers++;
+    
+        if( p_sys->b_packetizer )
+        {
+            i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
+            block_Release( p_block );
+            return i_ret;
+        }
+        else
+        {
+            block_Release( p_block );
+            return VLC_SUCCESS;
+        }
+    }
+
+    i_ret = ProcessPacket( p_dec, &oggpacket, p_block->i_pts );
+    block_Release( p_block );
+    return i_ret;
+}
+
+/*****************************************************************************
+ * ProcessHeader: processes the inital Speex header packet.
+ *****************************************************************************/
+static int ProcessHeader( decoder_t *p_dec, ogg_packet *p_oggpacket )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    void *p_state;
+    SpeexHeader *p_header;
+    SpeexMode *p_mode;
+    SpeexCallback callback;
+
+    p_sys->p_header = p_header =
+        speex_packet_to_header( p_oggpacket->packet, p_oggpacket->bytes );
+    if( !p_header )
+    {
+        msg_Err( p_dec, "Cannot read Speex header" );
+        return VLC_EGENERIC;
+    }
+    if( p_header->mode >= SPEEX_NB_MODES )
+    {
+        msg_Err( p_dec, "Mode number %d does not (yet/any longer) exist in "
+                 "this version of libspeex", p_header->mode );
+        return VLC_EGENERIC;
+    }
+
+    p_mode = speex_mode_list[p_header->mode];
+
+    if( p_header->speex_version_id > 1 )
+    {
+        msg_Err( p_dec, "This file was encoded with Speex bit-stream "
+                 "version %d, which I don't know how to decode",
+                 p_header->speex_version_id );
+        return VLC_EGENERIC;
+    }
+
+    if( p_mode->bitstream_version < p_header->mode_bitstream_version )
+    {
+        msg_Err( p_dec, "File encoded with a newer version of Speex" );
+        return VLC_EGENERIC;
+    }
+    if( p_mode->bitstream_version > p_header->mode_bitstream_version ) 
+    {
+        msg_Err( p_dec, "File encoded with an older version of Speex" );
+        return VLC_EGENERIC;
+    }
+   
+    msg_Dbg( p_dec, "Speex %d Hz audio using %s mode %s%s", 
+             p_header->rate, p_mode->modeName,
+             ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo",
+             p_header->vbr ? ", VBR)" : ")" );
+
+    aout_DateInit( &p_sys->end_date, p_header->rate );
+
+    if( p_sys->b_packetizer )
+    {
+        /* add an input for the stream ouput */
+        p_sys->sout_format.i_sample_rate = p_header->rate;
+        p_sys->sout_format.i_channels    = p_header->nb_channels;
+        p_sys->sout_format.i_block_align = 1;
+        p_sys->sout_format.i_bitrate     = 0;
+
+        p_sys->p_sout_input = sout_InputNew( p_dec, &p_sys->sout_format );
+        if( !p_sys->p_sout_input )
+        {
+            msg_Err( p_dec, "cannot add a new stream" );
+            return VLC_EGENERIC;
+        }
+
+        /* We're done */
+        return VLC_SUCCESS;
+    }
+
+    /* Take care of speex decoder init */
+    speex_bits_init( &p_sys->bits );
+    p_sys->p_state = p_state = speex_decoder_init( p_mode );
+    if( !p_state )
+    {
+        msg_Err( p_dec, "Decoder initialization failed" );
+        return VLC_EGENERIC;
+    }
+
+    if( p_header->nb_channels == 1 )
+    {
+        SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;
+        p_sys->stereo = stereo;
+        callback.callback_id = SPEEX_INBAND_STEREO;
+        callback.func = speex_std_stereo_request_handler;
+        callback.data = &p_sys->stereo;
+        speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback );
+    }
+
+    p_sys->aout_format.i_format = AOUT_FMT_S16_NE;
+    p_sys->aout_format.i_physical_channels =
+        p_sys->aout_format.i_original_channels =
+            pi_channels_maps[p_header->nb_channels];
+    p_sys->aout_format.i_rate = p_header->rate;
+
+    p_sys->p_aout = NULL;
+    p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout,
+                                       &p_sys->aout_format );
+    if( p_sys->p_aout_input == NULL )
+    {
+        msg_Err( p_dec, "failed to create aout fifo" );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * ProcessPacket: processes a Speex packet.
+ *****************************************************************************/
+static int ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
+                          mtime_t i_pts )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    /* Date management */
+    if( i_pts > 0 && i_pts != aout_DateGet( &p_sys->end_date ) )
+    {
+        aout_DateSet( &p_sys->end_date, i_pts );
+    }
+
+    if( !aout_DateGet( &p_sys->end_date ) )
+    {
+        /* We've just started the stream, wait for the first PTS. */
+        return VLC_SUCCESS;
+    }
+
+    if( p_sys->b_packetizer )
+    {
+        return SendPacket( p_dec, p_oggpacket );
+    }
+    else
+    {
+        return DecodePacket( p_dec, p_oggpacket );
+    }
+}
+
+/*****************************************************************************
+ * DecodePacket: decodes a Speex packet.
+ *****************************************************************************/
+static int DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    int j;
+
+    /* Copy Ogg packet to Speex bitstream */
+    speex_bits_read_from( &p_sys->bits, p_oggpacket->packet,
+                          p_oggpacket->bytes );
+
+    /* Decode each frame of the packet */
+    for( j = 0; j != p_sys->p_header->frames_per_packet; j++ )
+    {
+        aout_buffer_t *p_aout_buffer;
+        int i_ret;
+
+        p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout, p_sys->p_aout_input,
+                                           p_sys->p_header->frame_size );
+        if( !p_aout_buffer )
+        {
+            msg_Err( p_dec, "cannot get aout buffer" );
+            return VLC_SUCCESS;
+        }
+
+        i_ret = speex_decode( p_sys->p_state, &p_sys->bits,
+                              (int16_t *)p_aout_buffer->p_buffer );
+        if( i_ret == -1 ) break; /* End of stream */
+        if( i_ret== -2 )
+        {
+            msg_Warn( p_dec, "Decoding error: corrupted stream?" );
+            break;
+        }
+
+        if( speex_bits_remaining( &p_sys->bits ) < 0 )
+        {
+            msg_Warn( p_dec, "Decoding overflow: corrupted stream?" );
+            break;
+        }
+
+        if( p_sys->p_header->nb_channels == 2 )
+            speex_decode_stereo( (int16_t *)p_aout_buffer->p_buffer,
+                                 p_sys->p_header->frame_size, &p_sys->stereo );
+
+        /* Date management */
+        p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
+        p_aout_buffer->end_date =
+            aout_DateIncrement( &p_sys->end_date, p_sys->p_header->frame_size);
+
+        aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer );
+    }
+
+}
+
+/*****************************************************************************
+ * SendPacket: send an ogg packet to the stream output.
+ *****************************************************************************/
+static int SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    sout_buffer_t *p_sout_buffer =
+        sout_BufferNew( p_sys->p_sout_input->p_sout, p_oggpacket->bytes );
+
+    if( !p_sout_buffer ) return VLC_EGENERIC;
+
+    p_dec->p_vlc->pf_memcpy( p_sout_buffer->p_buffer,
+                             p_oggpacket->packet,
+                             p_oggpacket->bytes );
+
+    p_sout_buffer->i_bitrate = 0;
+
+    /* Date management */
+    p_sout_buffer->i_dts = p_sout_buffer->i_pts =
+        aout_DateGet( &p_sys->end_date );
+
+    if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )
+        p_sout_buffer->i_length =
+            aout_DateIncrement( &p_sys->end_date,
+                                p_sys->p_header->frame_size ) -
+            p_sout_buffer->i_pts;
+    else
+        p_sout_buffer->i_length = 0;
+
+    sout_InputSendBuffer( p_sys->p_sout_input, p_sout_buffer );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * ParseSpeexComments: FIXME should be done in demuxer
+ *****************************************************************************/
+#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
+                           ((buf[base+2]<<16)&0xff0000)| \
+                           ((buf[base+1]<<8)&0xff00)| \
+                            (buf[base]&0xff))
+
+static void ParseSpeexComments( decoder_t *p_dec, ogg_packet *p_oggpacket )
+{
+    input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    input_info_category_t *p_cat =
+        input_InfoCategory( p_input, _("Speex Comment") );
+
+    char *p_buf = (char *)p_oggpacket->packet;
+    SpeexMode *p_mode;
+    int i_len;
+
+    p_mode = speex_mode_list[p_sys->p_header->mode];
+    input_AddInfo( p_cat, _("Mode"), "%s%s",
+                   p_mode->modeName, p_sys->p_header->vbr ? " VBR" : "" );
+
+    if( p_oggpacket->bytes < 8 )
+    {
+        msg_Warn( p_dec, "Invalid/corrupted comments" );
+        return;
+    }
+
+    i_len = readint( p_buf, 0 ); p_buf += 4;
+    if( i_len > p_oggpacket->bytes - 4 )
+    {
+        msg_Warn( p_dec, "Invalid/corrupted comments" );
+        return;
+    }
+
+    input_AddInfo( p_cat, p_buf, "" );
+
+    /* TODO: finish comments parsing */
+}
+
+/*****************************************************************************
+ * EndDecoder: speex decoder destruction
+ *****************************************************************************/
+static int EndDecoder( decoder_t * p_dec )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->p_aout_input != NULL )
+    {
+        aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
+    }
+
+    if( p_sys->p_sout_input != NULL )
+    {
+        sout_InputDelete( p_sys->p_sout_input );
+    }
+
+    if( p_sys->p_state )
+    {
+        speex_decoder_destroy( p_sys->p_state );
+        speex_bits_destroy( &p_sys->bits );
+    }
+
+    if( p_sys->p_header ) free( p_sys->p_header );
+    free( p_sys );
+
+    return VLC_SUCCESS;
+}
index 3d24327baeac83e8f11a08228a9719c96e57e5a1..231e2790afe25029392e213a16d47c6326fdcfa4 100644 (file)
@@ -2,7 +2,7 @@
  * ogg.c : ogg stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: ogg.c,v 1.39 2003/10/19 16:53:59 gbazin Exp $
+ * $Id: ogg.c,v 1.40 2003/10/22 17:12:30 gbazin Exp $
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
  * 
@@ -356,6 +356,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
         switch( p_stream->i_fourcc )
         {
         case VLC_FOURCC( 'v','o','r','b' ):
+        case VLC_FOURCC( 's','p','x',' ' ):
         case VLC_FOURCC( 't','h','e','o' ):
           if( p_stream->i_packets_backup == 3 ) p_stream->b_force_backup = 0;
           break;
@@ -398,7 +399,8 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
     vlc_mutex_unlock( &p_input->stream.control.control_lock );
 
     /* Convert the pcr into a pts */
-    if( p_stream->i_fourcc == VLC_FOURCC( 'v','o','r','b' ) )
+    if( p_stream->i_fourcc == VLC_FOURCC( 'v','o','r','b' ) ||
+        p_stream->i_fourcc == VLC_FOURCC( 's','p','x',' ' ) )
     {
         if( p_stream->i_pcr >= 0 )
         {
@@ -484,6 +486,7 @@ static void Ogg_DecodePacket( input_thread_t *p_input,
     if( p_stream->i_cat == SPU_ES ) p_pes->i_dts = 0;
 
     if( p_stream->i_fourcc != VLC_FOURCC( 'v','o','r','b' ) &&
+        p_stream->i_fourcc != VLC_FOURCC( 's','p','x',' ' ) &&
         p_stream->i_fourcc != VLC_FOURCC( 't','a','r','k' ) &&
         p_stream->i_fourcc != VLC_FOURCC( 't','h','e','o' ) )
     {
@@ -602,6 +605,49 @@ static int Ogg_FindLogicalStreams( input_thread_t *p_input, demux_sys_t *p_ogg)
                                        p_stream->i_bitrate );
                     }
                 }
+                /* Check for Speex header */
+                if( oggpacket.bytes >= 7 &&
+                    ! strncmp( &oggpacket.packet[0], "Speex", 5 ) )
+                {
+                    oggpack_buffer opb;
+
+                    p_stream->i_cat = AUDIO_ES;
+                    p_stream->i_fourcc = VLC_FOURCC( 's','p','x',' ' );
+
+                    /* Signal that we want to keep a backup of the vorbis
+                     * stream headers. They will be used when switching between
+                     * audio streams. */
+                    p_stream->b_force_backup = 1;
+
+                    /* Cheat and get additionnal info ;) */
+                    oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes);
+                    oggpack_adv( &opb, 224 );
+                    oggpack_adv( &opb, 32 ); /* speex_version_id */
+                    oggpack_adv( &opb, 32 ); /* header_size */
+                    p_stream->f_rate = oggpack_read( &opb, 32 );
+                    oggpack_adv( &opb, 32 ); /* mode */
+                    oggpack_adv( &opb, 32 ); /* mode_bitstream_version */
+                    p_stream->i_channels = oggpack_read( &opb, 32 );
+                    p_stream->i_bitrate = oggpack_read( &opb, 32 );
+                    {
+                        char title[sizeof("Stream") + 10];
+                        input_info_category_t *p_cat;
+                        sprintf( title, "Stream %d", p_ogg->i_streams );
+                        p_cat = input_InfoCategory( p_input, title );
+                        input_AddInfo( p_cat, _("Type"), _("Audio") );
+                        input_AddInfo( p_cat, _("Codec"), _("Speex") );
+                        input_AddInfo( p_cat, _("Sample Rate"), "%f",
+                                       p_stream->f_rate );
+                        input_AddInfo( p_cat, _("Channels"), "%d",
+                                       p_stream->i_channels );
+                        input_AddInfo( p_cat, _("Bit Rate"), "%d",
+                                       p_stream->i_bitrate );
+                        msg_Dbg( p_input, "found speex header, channels: %i, "
+                                 "rate: %i,  bitrate: %i",
+                                 p_stream->i_channels,
+                                 (int)p_stream->f_rate, p_stream->i_bitrate );
+                    }
+                }
                 /* Check for Theora header */
                 else if( oggpacket.bytes >= 7 &&
                          ! strncmp( &oggpacket.packet[1], "theora", 6 ) )
@@ -1489,7 +1535,8 @@ static int Demux( input_thread_t * p_input )
                 }
 
                 /* An Ogg/vorbis packet contains an end date granulepos */
-                if( p_stream->i_fourcc == VLC_FOURCC( 'v','o','r','b' ) )
+                if( p_stream->i_fourcc == VLC_FOURCC( 'v','o','r','b' ) ||
+                    p_stream->i_fourcc == VLC_FOURCC( 's','p','x',' ' ) )
                 {
                     if( ogg_stream_packetout( &p_stream->os, &oggpacket ) > 0 )
                     {
index 015c5a9c235cd338a5078e921755c1640a38a052..55c80d9b76baa3030dd1dc590f400a8288a19583 100644 (file)
@@ -2,7 +2,7 @@
  * ogg.c: ogg muxer module for vlc
  *****************************************************************************
  * Copyright (C) 2001, 2002 VideoLAN
- * $Id: ogg.c,v 1.18 2003/10/10 17:09:42 gbazin Exp $
+ * $Id: ogg.c,v 1.19 2003/10/22 17:12:30 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *          Gildas Bazin <gbazin@netcourrier.com>
@@ -422,6 +422,10 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
             msg_Dbg( p_mux, "vorbis stream" );
             break;
 
+        case VLC_FOURCC( 's', 'p', 'x', ' ' ):
+            msg_Dbg( p_mux, "speex stream" );
+            break;
+
         default:
             FREE( p_input->p_sys );
             return( VLC_EGENERIC );
@@ -595,12 +599,13 @@ static sout_buffer_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
         p_stream->i_packet_no = 0;
 
         if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) ||
+            p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ||
             p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) )
         {
             /* Special case, headers are already there in the
              * incoming stream or we backed them up earlier */
 
-            /* first packet in order: vorbis/theora info */
+            /* first packet in order: vorbis/speex/theora info */
             if( !p_stream->i_sout_headers )
             {
                 p_og = sout_FifoGet( p_mux->pp_inputs[i]->p_fifo );
@@ -655,6 +660,7 @@ static sout_buffer_t *OggCreateHeader( sout_mux_t *p_mux, mtime_t i_dts )
         ogg_stream_t *p_stream = (ogg_stream_t*)p_mux->pp_inputs[i]->p_sys;
 
         if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) ||
+            p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) ||
             p_stream->i_fourcc == VLC_FOURCC( 't', 'h', 'e', 'o' ) )
         {
             /* Special case, headers are already there in the incoming stream.
@@ -860,6 +866,7 @@ static int Mux( sout_mux_t *p_mux )
         p_data   = sout_FifoGet( p_input->p_fifo );
 
         if( p_stream->i_fourcc != VLC_FOURCC( 'v', 'o', 'r', 'b' ) &&
+            p_stream->i_fourcc != VLC_FOURCC( 's', 'p', 'x', ' ' ) &&
             p_stream->i_fourcc != VLC_FOURCC( 't', 'h', 'e', 'o' ) )
         {
             sout_BufferReallocFromPreHeader( p_mux->p_sout, p_data, 1 );
@@ -874,7 +881,8 @@ static int Mux( sout_mux_t *p_mux )
 
         if( p_stream->i_cat == AUDIO_ES )
         {
-            if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
+            if( p_stream->i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) ||
+                p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) )
             {
                 /* number of sample from begining + current packet */
                 op.granulepos =
@@ -908,9 +916,11 @@ static int Mux( sout_mux_t *p_mux )
 
         ogg_stream_packetin( &p_stream->os, &op );
 
-        if( p_stream->i_cat == SPU_ES )
+        if( p_stream->i_cat == SPU_ES ||
+            p_stream->i_fourcc == VLC_FOURCC( 's', 'p', 'x', ' ' ) )
         {
-            /* Subtitles need to be flushed to be sent on time */
+            /* Subtitles or Speex packets are quite small so they 
+             * need to be flushed to be sent on time */
             sout_BufferChain( &p_og, OggStreamFlush( p_mux, &p_stream->os,
                                                      p_data->i_dts ) );
         }
index 9da9831d9d2e0d030efa68a0f90853a47204993f..a23dfea2dd54ce98e5d1d2d0e6d242541567f8dd 100644 (file)
@@ -4,7 +4,7 @@
  * decoders.
  *****************************************************************************
  * Copyright (C) 1998-2002 VideoLAN
- * $Id: input.c,v 1.248 2003/10/20 00:01:06 hartman Exp $
+ * $Id: input.c,v 1.249 2003/10/22 17:12:31 gbazin Exp $
  *
  * Authors: Christophe Massiot <massiot@via.ecp.fr>
  *
@@ -627,11 +627,13 @@ static int InitThread( input_thread_t * p_input )
     p_input->p_access = module_Need( p_input, "access",
                                      p_input->psz_access );
 
+#ifndef WIN32      /* Remove this gross hack from the win32 build as colons
+                    * are forbidden in filenames on Win32. */
+
+    /* Maybe we got something like: /Volumes/toto:titi/gabu.mpg */
     if ( p_input->p_access == NULL
           && (*p_input->psz_demux || *p_input->psz_access) )
     {
-        /* Maybe we got something like :
-         * /Volumes/toto:titi/gabu.mpg */
         p_input->psz_access = p_input->psz_demux = "";
         p_input->psz_name = p_input->psz_source;
         free( p_input->psz_dupsource);
@@ -640,6 +642,7 @@ static int InitThread( input_thread_t * p_input )
         p_input->p_access = module_Need( p_input, "access",
                                          p_input->psz_access );
     }
+#endif
 
     if( p_input->p_access == NULL )
     {
index 6e1b76f2b5a2719314cc6d095d711dedfdefe7ce..8ba5ed5a7cb447c19991c6e352c143508f208966 100644 (file)
@@ -2,7 +2,7 @@
  * variables.c: routines for object variables handling
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: variables.c,v 1.31 2003/09/29 15:45:19 sigmunau Exp $
+ * $Id: variables.c,v 1.32 2003/10/22 17:12:31 gbazin Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
@@ -271,10 +271,21 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
         {
             /* Free data if needed */
             p_var->pf_free( &p_var->val );
-            /* Check boundaries and list */
-            CheckValue( p_var, &val );
             /* Set the variable */
             p_var->val = val;
+
+            if( i_type & VLC_VAR_HASCHOICE )
+            {
+                /* We must add the inherited value to our choice list */
+                p_var->i_default = 0;
+
+                INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count,
+                             0, val );
+                INSERT_ELEM( p_var->choices_text.p_values,
+                             p_var->choices_text.i_count, 0, val );
+                p_var->pf_dup( &p_var->choices.p_values[0] );
+                p_var->choices_text.p_values[0].psz_string = NULL;
+            }
         }
     }
 
@@ -1173,7 +1184,6 @@ static int InheritValue( vlc_object_t *p_this, const char *psz_name,
     if( i_var >= 0 )
     {
         /* We found it! */
-
         p_var = &p_this->p_parent->p_vars[i_var];
 
         /* Really get the variable */